import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig, } from 'axios' import {ElMessage, ElMessageBox} from 'element-plus' import {useUserStore} from '@/stores/user' import router from '@/router' // 创建axios实例 const service: AxiosInstance = axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL || '', withCredentials: true, timeout: Number(import.meta.env.VITE_TIMEOUT) || 10000, headers: { 'Content-Type': 'application/json', }, }) // 请求拦截器 service.interceptors.request.use( (config: InternalAxiosRequestConfig) => { const userStore = useUserStore() // 添加token if (userStore.token) { config.headers = config.headers || {} config.headers['Authorization'] = `Bearer ${userStore.token}` } return config }, (error) => { console.error('请求错误:', error) return Promise.reject(error) } ) // 响应拦截器 service.interceptors.response.use( (response: AxiosResponse) => { const res = response.data if (typeof res?.success === 'boolean') { if (!res.success) { if (response.status === 401) { ElMessage.error(res.message || '登录状态已失效') } else { ElMessage.error(res.message || '请求失败') } return Promise.reject(new Error(res.message || '请求失败')) } return res } // 自定义状态码处理 if (res.code !== 200 && res.code !== 0) { // 业务错误 if (res.code === 401) { // 未登录或token失效 ElMessageBox.confirm('登录已过期,请重新登录', '提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning', }).then(() => { const userStore = useUserStore() userStore.logout() router.push('/login') }) } else if (res.code === 403) { // 无权限 ElMessage.error('无权限访问') } else { // 其他业务错误 ElMessage.error(res.message || '请求失败') } return Promise.reject(new Error(res.message || '请求失败')) } return res }, (error) => { console.error('响应错误:', error) // 提取后端返回的业务错误消息 const bizMessage = error.response?.data?.message let displayMessage = '' if (error.response) { switch (error.response.status) { case 400: // 业务错误(如"该团组已满员"),只显示后端返回的消息 displayMessage = bizMessage || '请求参数错误' break case 401: displayMessage = '未授权,请登录' break case 403: displayMessage = '拒绝访问' break case 404: displayMessage = '请求地址不存在' break case 429: displayMessage = '请求过于频繁,请稍后再试' break case 500: displayMessage = '服务器内部错误' break default: displayMessage = bizMessage || '请求失败' } } else if (error.request) { displayMessage = '网络错误,请检查网络连接' } else { displayMessage = '请求配置错误' } ElMessage.error(displayMessage) // 用业务消息替换原始 axios error message,避免组件 catch 显示 "Request failed with status code 400" const rejectError = new Error(displayMessage) ;(rejectError as any)._handled = true return Promise.reject(rejectError) } ) // 通用请求方法 export const request = { get(url: string, params?: any): Promise { return service.get(url, {params}) }, post(url: string, data?: any): Promise { return service.post(url, data) }, put(url: string, data?: any): Promise { return service.put(url, data) }, delete(url: string, data?: any, config?: AxiosRequestConfig): Promise { return service.delete(url, { ...config, data, }) }, } export default service