Files
RCZN-bs-program/rc_autoplc_front/src/utils/request.ts

161 lines
4.7 KiB
TypeScript
Raw Normal View History

2025-12-15 16:16:07 +08:00
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']
},
2026-01-19 16:15:02 +08:00
// 初始化token应用启动时调用
initToken() {
const token = this.getToken()
if (token) {
request.defaults.headers.common['Authorization'] = `Bearer ${token}`
}
},
2025-12-15 16:16:07 +08:00
}
2026-01-19 16:15:02 +08:00
// 应用启动时初始化token
TokenManager.initToken()
2026-01-23 11:26:14 +08:00
// 登录过期提示防重复标志
let isLoginExpiredShown = false
// 处理登录过期(防重复提示)
const handleLoginExpired = () => {
if (!isLoginExpiredShown) {
isLoginExpiredShown = true
// 清除token
TokenManager.removeToken()
// 显示提示消息
ElMessage.error('登录已过期,请重新登录')
// 跳转到登录页
router.replace('/login').finally(() => {
// 延迟重置标志位,确保跳转完成后再允许下次提示
setTimeout(() => {
isLoginExpiredShown = false
}, 1000)
})
}
}
2025-12-15 16:16:07 +08:00
// 请求拦截器
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) {
2026-01-23 11:26:14 +08:00
// 处理登录过期(防重复提示)
handleLoginExpired()
2025-12-15 16:16:07 +08:00
return Promise.reject(data)
}
// 其他错误码
if (data.code !== 0 && data.code !== undefined) {
2026-02-02 13:48:55 +08:00
// 检查是否是状态刷新相关的请求,如果是则静默处理某些错误
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 || '请求失败')
2025-12-15 16:16:07 +08:00
return Promise.reject(data)
}
return data
},
(error) => {
2026-01-19 16:15:02 +08:00
// 处理401未授权错误
if (error.response?.status === 401) {
2026-01-23 11:26:14 +08:00
// 处理登录过期(防重复提示)
handleLoginExpired()
2026-01-19 16:15:02 +08:00
return Promise.reject(error)
}
2026-02-02 13:48:55 +08:00
// 检查是否是状态刷新相关的请求
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)
}
2025-12-15 16:16:07 +08:00
// 网络错误或其他错误
2026-02-02 13:48:55 +08:00
ElMessage.error(errorMsg)
2025-12-15 16:16:07 +08:00
return Promise.reject(error)
}
)
export default request