| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- import axios from 'axios'
- import { ElMessage } from 'element-plus'
- import router from '../router'
- const apiBaseURL =
- import.meta.env.VITE_API_BASE_URL || 'http://127.0.0.1:5000'
- const request = axios.create({
- baseURL: apiBaseURL,
- timeout: 600000,
- headers: {
- 'ngrok-skip-browser-warning': 'true',
- },
- })
- // 是否正在刷新 token
- let isRefreshing = false
- // 请求队列
- let requestQueue = []
- // 请求拦截器
- request.interceptors.request.use(
- config => {
- // 从 localStorage 获取 token
- const token = localStorage.getItem('access_token')
- if (token) {
- config.headers.Authorization = `Bearer ${token}`
- }
- return config
- },
- error => {
- return Promise.reject(error)
- }
- )
- // 响应拦截器
- request.interceptors.response.use(
- response => {
- return response.data
- },
- async error => {
- // 如果响应中包含数据,则返回数据
- if (error.response?.data) {
- // 处理 token 过期情况 (401 错误)
- if (error.response.status === 401) {
- const originalRequest = error.config
- const refreshToken = localStorage.getItem('refresh_token')
- // 如果没有 refresh_token,直接跳转到登录页
- if (!refreshToken) {
- ElMessage.error({
- message: '登录已过期,请重新登录',
- duration: 5000
- })
- localStorage.clear()
- router.push('/login')
- return Promise.reject(error)
- }
- // 如果已经在刷新 token,将请求加入队列
- if (isRefreshing) {
- return new Promise(resolve => {
- requestQueue.push(() => {
- originalRequest.headers.Authorization = `Bearer ${localStorage.getItem('access_token')}`
- resolve(request(originalRequest))
- })
- })
- }
- isRefreshing = true
- try {
- // 创建一个新的 axios 实例来刷新 token,避免进入拦截器循环
- const refreshResponse = await axios.post(`${apiBaseURL}/user/refresh`, {}, {
- headers: {
- 'Authorization': `Bearer ${refreshToken}`
- }
- })
- // 更新 token
- const newToken = refreshResponse.data.access_token
- localStorage.setItem('access_token', newToken)
- // 重新发送队列中的请求
- requestQueue.forEach(callback => callback())
- requestQueue = []
- // 重新发送原始请求
- originalRequest.headers.Authorization = `Bearer ${newToken}`
- return request(originalRequest)
- } catch (refreshError) {
- // 刷新 token 失败,说明 refresh_token 过期,清除 token 并跳转到登录页
- console.error('刷新 token 失败', refreshError)
- ElMessage.error('登录已过期,请重新登录')
- ElMessage.error({
- message: '登录已过期,请重新登录',
- duration: 5000
- })
- localStorage.clear()
- router.push('/login')
- return Promise.reject(refreshError)
- } finally {
- isRefreshing = false
- }
- }
- // 显示失败信息
- ElMessage.warning({
- message: error.response.data.operation?.failure_message || error.response.data.failure_message || '请求失败',
- duration: 4000
- })
- // 返回响应数据,让业务代码可以继续处理
- return error.response.data
- }
- // 如果没有响应数据,则拒绝 Promise
- ElMessage.error({
- message: '网络错误,请稍后重试',
- duration: 5000
- })
- return Promise.reject(error)
- }
- )
- export default request
|