| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475 |
- // 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<string>(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<string>(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;
- }
|