import axios from 'axios' import type { AxiosInstance, InternalAxiosRequestConfig, AxiosResponse } from 'axios' import { ElMessage } from 'element-plus' import router from '@/router' import { useAuthStore } from '@/stores/auth' // 创建 axios 实例 const request: AxiosInstance = axios.create({ baseURL: import.meta.env.VITE_API_URL, // 从环境变量读取 timeout: 10000, // 10秒超时 }) // Token 管理器(使用 Pinia) const TokenManager = { setToken(token: string) { const authStore = useAuthStore() authStore.setToken(token) // 同时设置默认请求头 request.defaults.headers.common['Authorization'] = `Bearer ${token}` }, getToken(): string { const authStore = useAuthStore() return authStore.getToken() }, removeToken() { const authStore = useAuthStore() authStore.removeToken() // 删除默认请求头 delete request.defaults.headers.common['Authorization'] }, // 初始化token(应用启动时调用) initToken() { const token = this.getToken() if (token) { request.defaults.headers.common['Authorization'] = `Bearer ${token}` } }, } // 应用启动时初始化token TokenManager.initToken() // 登录过期提示防重复标志 let isLoginExpiredShown = false // 处理登录过期(防重复提示) const handleLoginExpired = () => { if (!isLoginExpiredShown) { isLoginExpiredShown = true // 清除token TokenManager.removeToken() // 显示提示消息 ElMessage.error('登录已过期,请重新登录') // 跳转到登录页 router.replace('/login').finally(() => { // 延迟重置标志位,确保跳转完成后再允许下次提示 setTimeout(() => { isLoginExpiredShown = false }, 1000) }) } } // 请求拦截器 request.interceptors.request.use( (config: InternalAxiosRequestConfig) => { const token = TokenManager.getToken() if (token) { // .NET Core API使用标准的Bearer认证 config.headers['Authorization'] = `Bearer ${token}` } return config }, (error) => { return Promise.reject(error) } ) // 响应拦截器 request.interceptors.response.use( (response: AxiosResponse) => { const { data } = response // 如果返回 code 为 0 且有新 token,更新 token if (data.code === 0 && data.token) { TokenManager.setToken(data.token) } console.log('data*--', data) // 处理业务错误码 if (data.code === 302) { // 处理登录过期(防重复提示) handleLoginExpired() return Promise.reject(data) } // 其他错误码 if (data.code !== 0 && data.code !== undefined) { // 检查是否是状态刷新相关的请求,如果是则静默处理某些错误 const url = response.config?.url || '' const isStatusRefreshRequest = url.includes('/plc/plcStatus') || url.includes('/plc/getModel') const errorMsg = data.message || data.msg || '' // 如果是状态刷新请求,且错误消息包含特定关键词,则静默处理 if (isStatusRefreshRequest && ( errorMsg.includes('停止失败') || errorMsg.includes('未连接') || errorMsg.includes('连接失败') || errorMsg.includes('获取状态失败') || errorMsg.includes('获取模式失败') )) { // 静默处理,不弹出错误提示 console.debug('状态刷新请求错误(已静默处理):', errorMsg) return Promise.reject(data) } ElMessage.error(errorMsg || '请求失败') return Promise.reject(data) } return data }, (error) => { // 处理401未授权错误 if (error.response?.status === 401) { // 处理登录过期(防重复提示) handleLoginExpired() return Promise.reject(error) } // 检查是否是状态刷新相关的请求 const url = error.config?.url || '' const isStatusRefreshRequest = url.includes('/plc/plcStatus') || url.includes('/plc/getModel') const errorMsg = error.response?.data?.message || error.response?.data?.msg || '请求失败' // 如果是状态刷新请求,且错误消息包含特定关键词,则静默处理 if (isStatusRefreshRequest && ( errorMsg.includes('停止失败') || errorMsg.includes('未连接') || errorMsg.includes('连接失败') || errorMsg.includes('获取状态失败') || errorMsg.includes('获取模式失败') )) { // 静默处理,不弹出错误提示 console.debug('状态刷新请求错误(已静默处理):', errorMsg) return Promise.reject(error) } // 网络错误或其他错误 ElMessage.error(errorMsg) return Promise.reject(error) } ) export default request