// Axios客户端实例(仅注入JWT Token,factory_id由后端从Token提取) import axios from 'axios'; import type { AxiosInstance } from 'axios'; import { getSessionStorage, removeSessionStorage, setSessionStorage, STORAGE_KEYS } from '@smartcut/shared-utils'; export interface ApiClientConfig { baseURL: string; tokenKey: string; // sessionStorage中的token键名 } /** * 创建API客户端实例 * factory_id 不再由前端传递,后端通过 JWT Token 自动提取 */ export function createApiClient(config: ApiClientConfig): AxiosInstance { const instance = axios.create({ baseURL: config.baseURL, timeout: 30000, headers: { 'Content-Type': 'application/json' } }); // 请求拦截器:仅注入JWT Token instance.interceptors.request.use( (requestConfig) => { const token = getSessionStorage(config.tokenKey); if (token) { requestConfig.headers.Authorization = `Bearer ${token}`; } return requestConfig; }, (error) => Promise.reject(error) ); // 响应拦截器:Token续期 + 业务错误码处理 + 401处理 instance.interceptors.response.use( (response) => { const newToken = response.headers['x-new-token']; if (newToken) { setSessionStorage(config.tokenKey, newToken); } // 后端对业务错误返回 HTTP 200 + code!=0,此处统一转为 rejected, // 让各视图的 catch 块能正确显示错误信息 const body = response.data; if (body && typeof body === 'object' && typeof body.code === 'number' && body.code !== 0) { const err = new Error(body.msg || '请求失败'); (err as any).code = body.code; (err as any).response = response; return Promise.reject(err); } return response; }, (error) => { if (error.response?.status === 401) { // 401时仅清除Token,保留factory_id便于重新登录同一工厂 removeSessionStorage(config.tokenKey); const factoryId = getSessionStorage(STORAGE_KEYS.CURRENT_FACTORY_ID); // P2: 保存当前路径,登录后返回原页面;redirect 仅允许相对路径,防开放重定向 const currentPath = window.location.pathname + window.location.search; const isSafeRedirect = currentPath.startsWith('/') && !currentPath.startsWith('//') && !currentPath.startsWith('/login'); const base = isSafeRedirect ? '/login?redirect=' + encodeURIComponent(currentPath) : '/login'; const factoryParam = factoryId ? '&factory=' + encodeURIComponent(factoryId) : ''; window.location.href = base + factoryParam; } return Promise.reject(error); } ); return instance; }