Files
RCZN-bs-program/rc_autoplc_front/src/utils/request.ts
2026-02-02 13:48:55 +08:00

161 lines
4.7 KiB
TypeScript
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 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