Files
xiaoxia-saas/apps/web/src/api/client.ts
T
Audit Bot 07ee86dc65
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 210h57m58s
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Failing after 210h58m2s
fix: resolve all ESLint warnings for clean lint output
- Fix 48x @typescript-eslint/no-explicit-any: err: any → err: unknown with type narrowing
- Fix 3x @typescript-eslint/no-unused-vars: remove unused imports/variables
- Fix 2x react-refresh/only-export-components: add eslint-disable comments
- Fix 1x react-hooks/exhaustive-deps: wrap in useCallback
- 28 files modified across app/ and src/pages/
- ESLint now passes with 0 errors + 0 warnings (--max-warnings 0)
2026-06-30 17:56:10 +08:00

84 lines
2.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* API 客户端配置
* 封装 Axios 实例,配置拦截器和 Token 管理
*/
import axios, { AxiosError, InternalAxiosRequestConfig } from 'axios';
import { message } from 'antd';
import { useAuthStore } from '@/store/authStore';
// 创建 Axios 实例
const apiClient = axios.create({
baseURL: '/api/v1',
timeout: 10000,
headers: {
'Content-Type': 'application/json',
},
});
// 请求拦截器:添加 Token
apiClient.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
const token = localStorage.getItem('access_token');
if (token && config.headers) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error: AxiosError) => {
return Promise.reject(error);
}
);
// 响应拦截器:统一错误提示 + 处理未授权状态
apiClient.interceptors.response.use(
(response) => response,
async (error: AxiosError<{ detail?: string; message?: string; msg?: string }>) => {
// 401 → 清除登录态
if (error.response?.status === 401) {
useAuthStore.getState().clearAuth();
}
// 提取后端返回的错误信息(detail / message / msg
const data = error.response?.data;
const serverMsg = data?.detail || data?.message || data?.msg;
let handled = false;
if (error.code === 'ECONNABORTED' || error.message?.includes('timeout')) {
message.error('请求超时,请检查网络后重试');
handled = true;
} else if (!error.response) {
message.error('网络连接异常,请检查网络设置');
handled = true;
} else if (serverMsg) {
message.error(serverMsg);
handled = true;
} else {
const status = error.response?.status;
if (status === 413) {
message.error('文件过大,请缩小后重试');
handled = true;
} else if (status === 415) {
message.error('不支持的文件格式');
handled = true;
} else if (status === 503) {
message.error('服务暂不可用,请稍后再试');
handled = true;
} else if (status && status >= 500) {
message.error('服务器繁忙,请稍后再试');
handled = true;
}
// 其他 4xx 且无具体信息时不弹通用提示,由各组件自行处理
}
// 标记已展示过提示,组件 onError 可据此跳过重复 toast
if (handled) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(error as any).__msgShown = true;
}
return Promise.reject(error);
}
);
export default apiClient;