import axios from 'axios' import config from '@/config' import { useUserStore } from '@/stores/modules/user' import { ElMessage } from 'element-plus' import router from '@/router' const http = axios.create({ timeout: 30000, baseURL: config.baseURL }) // 是否正在刷新 token let isRefreshing = false // 存储待重试的请求 let requests = [] // 请求拦截器 http.interceptors.request.use( (config) => { const userStore = useUserStore() const token = userStore.token // 如果有 token,添加到请求头 if (token) { config.headers['Authorization'] = `Bearer ${token}` } return config }, (error) => { return Promise.reject(error) } ) // 响应拦截器 http.interceptors.response.use( (response) => { // 根据后端返回的数据结构进行处理 // 假设后端返回格式为 { code, data, message } const { code, data, message } = response.data // 请求成功 if (code === 200 || code === 0) { return data } // 其他错误码处理 ElMessage.error(message || '请求失败') return Promise.reject(new Error(message || '请求失败')) }, async (error) => { const userStore = useUserStore() const { response } = error // 无响应(网络错误、超时等) if (!response) { ElMessage.error('网络错误,请检查网络连接') return Promise.reject(error) } const { status, data } = response // 401 未授权 - token 过期或无效 if (status === 401) { // 如果正在刷新 token,将请求加入队列 if (isRefreshing) { return new Promise((resolve) => { requests.push((token) => { // 重新设置请求头 error.config.headers['Authorization'] = `Bearer ${token}` resolve(http(error.config)) }) }) } // 标记正在刷新 isRefreshing = true try { // 尝试刷新 token const newToken = await refreshToken() // 刷新成功,更新 token userStore.setToken(newToken) // 执行队列中的所有请求 requests.forEach((callback) => callback(newToken)) requests = [] // 重新执行当前请求 error.config.headers['Authorization'] = `Bearer ${newToken}` return http(error.config) } catch (refreshError) { // 刷新失败,清空队列并跳转登录页 requests = [] userStore.logout() router.push('/login') ElMessage.error('登录已过期,请重新登录') return Promise.reject(refreshError) } finally { isRefreshing = false } } // 403 禁止访问 if (status === 403) { ElMessage.error('没有权限访问该资源') return Promise.reject(error) } // 404 资源不存在 if (status === 404) { ElMessage.error('请求的资源不存在') return Promise.reject(error) } // 500 服务器错误 if (status >= 500) { ElMessage.error('服务器错误,请稍后重试') return Promise.reject(error) } // 其他错误 const errorMessage = data?.message || error.message || '请求失败' ElMessage.error(errorMessage) return Promise.reject(error) } ) // 刷新 token 的方法 async function refreshToken() { // 这里需要根据实际的刷新 token 接口进行修改 // 假设刷新接口是 /auth/refresh const refreshUrl = config.baseURL + '/auth/refresh' const userStore = useUserStore() const refreshTokenValue = userStore.refreshToken const response = await axios.post(refreshUrl, { refreshToken: refreshTokenValue }) // 假设返回格式为 { code, data: { token, refreshToken } } return response.data.data.token } export default http