| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';
- import { toast } from 'sonner';
- import { env } from '../config/env';
- // 创建 axios 实例
- const axiosInstance: AxiosInstance = axios.create({
- baseURL: env.baseUrl ? `${env.baseUrl}/api` : '/api',
- timeout: 30000, // 30秒超时
- headers: {
- 'Content-Type': 'application/json',
- },
- });
- // 请求拦截器
- axiosInstance.interceptors.request.use(
- (config) => {
- // 从 localStorage 获取 token
- const token = localStorage.getItem('token');
- if (token && config.headers) {
- config.headers.Authorization = `Bearer ${token}`;
- }
- // 添加租户信息(如果有)
- const tenant = localStorage.getItem('tenant');
- if (tenant && config.headers) {
- config.headers['X-Tenant-Id'] = tenant;
- }
- return config;
- },
- (error: AxiosError) => {
- return Promise.reject(error);
- }
- );
- // 响应拦截器
- axiosInstance.interceptors.response.use(
- (response: AxiosResponse) => {
- const { data } = response;
- // 如果后端返回的数据格式是 { code, data, message }
- if (data.code !== undefined) {
- if (data.code === 200 || data.code === 0) {
- return data.data !== undefined ? data.data : data;
- } else {
- // 业务错误
- const errorMessage = data.message || '请求失败';
- toast.error(errorMessage);
- return Promise.reject(new Error(errorMessage));
- }
- }
- // 直接返回数据
- return data;
- },
- (error: AxiosError) => {
- // 处理 HTTP 错误
- if (error.response) {
- const { status, data } = error.response;
- let errorMessage = '请求失败';
- switch (status) {
- case 401:
- errorMessage = '未授权,请重新登录';
- // 清除 token 并跳转到登录页
- localStorage.removeItem('token');
- localStorage.removeItem('tenant');
- window.location.href = '/login';
- break;
- case 403:
- errorMessage = '拒绝访问';
- break;
- case 404:
- errorMessage = '请求的资源不存在';
- break;
- case 500:
- errorMessage = '服务器内部错误';
- break;
- case 502:
- errorMessage = '网关错误';
- break;
- case 503:
- errorMessage = '服务不可用';
- break;
- default:
- errorMessage = (data as any)?.message || `请求失败 (${status})`;
- }
- toast.error(errorMessage);
- return Promise.reject(new Error(errorMessage));
- } else if (error.request) {
- // 请求已发出但没有收到响应
- toast.error('网络错误,请检查网络连接');
- return Promise.reject(new Error('网络错误'));
- } else {
- // 其他错误
- toast.error(error.message || '请求失败');
- return Promise.reject(error);
- }
- }
- );
- export default axiosInstance;
|