fix: add interceptors to user store api client

- Add request interceptor to inject Authorization Bearer token
- Add response interceptor to handle AjaxResult format uniformly
- Fix getInfo() response parsing to read nested data.user/roles/permissions
- Ensure login token is correctly extracted and stored

Root cause: apiClient had no interceptors, so getInfo() sent requests
without token after login, causing 401 and redirect back to login.
feature/20260628/refactor-frontend-modernization
Lxy 2 weeks ago
parent 90d5f32098
commit e2c3815062

@ -1,13 +1,88 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { ref } from 'vue' import { ref } from 'vue'
import { getToken, setToken, removeToken } from '@/utils/auth'
import axios from 'axios' import axios from 'axios'
import { ElMessage } from 'element-plus'
import { getToken, setToken, removeToken } from '@/utils/auth'
const apiClient = axios.create({ const apiClient = axios.create({
baseURL: import.meta.env.VITE_APP_BASE_API || '/dev-api', baseURL: import.meta.env.VITE_APP_BASE_API || '/dev-api',
timeout: 60000, timeout: 60000,
headers: {
'Content-Type': 'application/json;charset=utf-8',
},
}) })
// 请求拦截器:自动注入 Token
apiClient.interceptors.request.use(
(config) => {
const token = getToken()
if (token) {
config.headers['Authorization'] = `Bearer ${token}`
}
return config
},
(error) => {
return Promise.reject(error)
}
)
// 响应拦截器:统一处理 AjaxResult 格式
apiClient.interceptors.response.use(
(response) => {
const res = response.data
// 二进制数据直接返回
if (res instanceof Blob || response.config.responseType === 'blob') {
return res
}
const { code, msg, data } = res
if (code === 200) {
// 返回完整响应对象,保留顶层字段(如 token
return res
} else if (code === 401) {
ElMessage.error(msg || '登录状态已过期,请重新登录')
removeToken()
window.location.href = '/login'
return Promise.reject(new Error(msg || '登录已过期'))
} else if (code === 500) {
ElMessage.error(msg || '系统内部错误')
return Promise.reject(new Error(msg || '系统内部错误'))
} else {
ElMessage.error(msg || '请求失败')
return Promise.reject(new Error(msg || '请求失败'))
}
},
(error) => {
let message = '网络异常'
if (error.response) {
switch (error.response.status) {
case 401:
message = '未授权,请重新登录'
break
case 403:
message = '拒绝访问'
break
case 404:
message = '请求地址不存在'
break
case 500:
message = '服务器内部错误'
break
default:
message = `连接错误 ${error.response.status}`
}
} else if (error.code === 'ECONNABORTED') {
message = '请求超时'
} else {
message = error.message || '网络异常'
}
ElMessage.error(message)
return Promise.reject(error)
}
)
export interface UserInfo { export interface UserInfo {
userId: number userId: number
userName: string userName: string
@ -24,19 +99,27 @@ export const useUserStore = defineStore('user', () => {
const permissions = ref<string[]>([]) const permissions = ref<string[]>([])
async function login(username: string, password: string, code?: string, uuid?: string) { async function login(username: string, password: string, code?: string, uuid?: string) {
const { data } = await apiClient.post('/login', { username, password, code, uuid }) const res = await apiClient.post('/login', { username, password, code, uuid })
setToken(data.token) const tokenValue = res.token
token.value = data.token if (!tokenValue) {
return data throw new Error('登录失败,未获取到 token')
}
setToken(tokenValue)
token.value = tokenValue
return res
} }
async function getInfo() { async function getInfo() {
const { data } = await apiClient.get('/getInfo') const res = await apiClient.get('/getInfo')
const data = res.data || {}
const user = data.user const user = data.user
if (!user) {
throw new Error('获取用户信息失败')
}
userInfo.value = user userInfo.value = user
roles.value = user.roles || [] roles.value = user.roles || data.roles || []
permissions.value = user.permissions || [] permissions.value = user.permissions || data.permissions || []
return data return res
} }
async function logout() { async function logout() {

Loading…
Cancel
Save