import axios from "axios"; import { useAuthStore } from "@/stores/auth"; const AUTH_ERROR_CODE = 401; const SESSION_REPLACED_CODE = 40101; const http = axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL || "/api", timeout: 15000, headers: { Accept: "application/json", "Content-Type": "application/json", }, }); let redirectingToLogin = false; function redirectToLogin(reason) { const currentPath = window.location.pathname.replace(/\/+$/, "") || "/"; if (currentPath === "/login" || redirectingToLogin) return; redirectingToLogin = true; const redirect = `${window.location.pathname}${window.location.search}${window.location.hash}`; const query = new URLSearchParams({ redirect }); if (reason) query.set("reason", reason); window.location.assign(`/login?${query.toString()}`); } function isAuthenticationError(code) { return code === AUTH_ERROR_CODE || code === SESSION_REPLACED_CODE; } function handleUnauthorized(code) { const authStore = useAuthStore(); authStore.clearSession(); redirectToLogin(code === SESSION_REPLACED_CODE ? "session-replaced" : "expired"); } http.interceptors.request.use((config) => { const authStore = useAuthStore(); if (authStore.token) { config.headers.Authorization = `Bearer ${authStore.token}`; } return config; }); http.interceptors.response.use( (response) => { const payload = response.data; if (payload?.code === undefined) return payload; const result = { ...payload, success: payload.code === 0, }; if (result.success) return result; if (isAuthenticationError(result.code)) handleUnauthorized(result.code); const error = new Error(result.message || "请求失败"); error.code = result.code; error.data = result.data; error.success = result.success; throw error; }, (error) => { const status = error.response?.status; const payload = error.response?.data; const authenticationCode = payload?.code ?? status; if (isAuthenticationError(authenticationCode)) handleUnauthorized(authenticationCode); const requestError = new Error( payload?.message || (error.code === "ECONNABORTED" ? "请求超时,请稍后重试" : "网络异常,请检查服务是否正常"), ); requestError.code = payload?.code ?? status; requestError.data = payload?.data; requestError.success = false; throw requestError; }, ); export function post(path, data, config) { return http.post(path, data, config); } export default http;