更新
This commit is contained in:
+2
-1
@@ -1,3 +1,4 @@
|
||||
export default {
|
||||
app_title: 'vueadmin'
|
||||
app_title: 'vueadmin',
|
||||
baseURL: ''
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { defineStore } from 'pinia'
|
||||
|
||||
export const useUserStore = defineStore('user', () => {
|
||||
const token = ref(localStorage.getItem('token') || '')
|
||||
const refreshToken = ref(localStorage.getItem('refreshToken') || '')
|
||||
const userInfo = ref(JSON.parse(localStorage.getItem('userInfo') || 'null'))
|
||||
|
||||
// 设置 token
|
||||
@@ -11,6 +12,12 @@ export const useUserStore = defineStore('user', () => {
|
||||
localStorage.setItem('token', newToken)
|
||||
}
|
||||
|
||||
// 设置 refresh token
|
||||
function setRefreshToken(newRefreshToken) {
|
||||
refreshToken.value = newRefreshToken
|
||||
localStorage.setItem('refreshToken', newRefreshToken)
|
||||
}
|
||||
|
||||
// 设置用户信息
|
||||
function setUserInfo(info) {
|
||||
userInfo.value = info
|
||||
@@ -20,8 +27,10 @@ export const useUserStore = defineStore('user', () => {
|
||||
// 登出
|
||||
function logout() {
|
||||
token.value = ''
|
||||
refreshToken.value = ''
|
||||
userInfo.value = null
|
||||
localStorage.removeItem('token')
|
||||
localStorage.removeItem('refreshToken')
|
||||
localStorage.removeItem('userInfo')
|
||||
}
|
||||
|
||||
@@ -32,8 +41,10 @@ export const useUserStore = defineStore('user', () => {
|
||||
|
||||
return {
|
||||
token,
|
||||
refreshToken,
|
||||
userInfo,
|
||||
setToken,
|
||||
setRefreshToken,
|
||||
setUserInfo,
|
||||
logout,
|
||||
isLoggedIn,
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user