This commit is contained in:
2026-01-14 10:10:29 +08:00
parent 8deaa1a7e2
commit e01690803d
5 changed files with 359 additions and 3 deletions

145
src/utils/request.js Normal file
View File

@@ -0,0 +1,145 @@
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 refreshTokenValue = localStorage.getItem('refreshToken')
const response = await axios.post(refreshUrl, {
refreshToken: refreshTokenValue
})
// 假设返回格式为 { code, data: { token, refreshToken } }
return response.data.data.token
}
export default http