Files
vueadmin/src/utils/request.js
2026-01-26 09:44:48 +08:00

147 lines
3.5 KiB
JavaScript
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.
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.API_URL,
})
// 是否正在刷新 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 === 1) {
return { code, data, message }
}
// 其他错误码处理
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