From ebc88286135d4daa1a2dcc37c97645106abbf78e Mon Sep 17 00:00:00 2001 From: GiveMePast <1248298477@qq.com> Date: Wed, 4 Mar 2026 15:15:39 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=91=98=E5=B7=A5=E7=95=8C?= =?UTF-8?q?=E9=9D=A2=EF=BC=8Ctoken=E8=BF=87=E6=9C=9F=E4=B8=8D=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E8=B7=B3=E8=BD=AC=EF=BC=8C=E4=BB=A5=E5=8F=8A=E5=A4=9A?= =?UTF-8?q?=E4=B8=AA=E5=BC=B9=E7=AA=97=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/request.js | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/src/utils/request.js b/src/utils/request.js index 7f5d6d3..405acfc 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -7,6 +7,9 @@ const service = axios.create({ timeout: 10000 }) +// 标记位,防止重复弹窗 +let isRelogging = false + // 请求拦截器 service.interceptors.request.use( config => { @@ -30,13 +33,39 @@ service.interceptors.response.use( return response.data; }, error => { - if (error.response && error.response.status === 500) { - if (error.response.data.message === 'The token is expired.') { + const resData = error.response?.data; + const status = error.response?.status; + + // 1. 判定是否为 Token 相关的认证错误 + // 包含 500 状态码且消息含有 token 字样(如 decode 失败、过期等) + if (status === 500 && resData?.message && /token/i.test(resData.message)) { + + if (!isRelogging) { + isRelogging = true; // 锁定 + localStorage.removeItem('token'); + // 清除用户信息,防止 UserView.vue 的 computed 报错 + localStorage.removeItem('user_info'); + ElMessage.error('登录已失效,请重新登录'); - router.push('/login'); + + router.push('/login').then(() => { + // 2. 延迟解锁,确保页面跳转期间的所有并发请求都已返回并被此拦截器捕获 + setTimeout(() => { + isRelogging = false; + }, 3000); + }); } + + // 3. 【关键】无论是否是第一个请求,只要是 Token 错误,都返回 Pending Promise + // 这会阻止组件内的 catch 块执行,从而消失“加载列表失败”等弹窗 + return new Promise(() => { }); } + + // 2. 处理非 Token 错误的普通报错(如网络断开、真正的服务器崩溃等) + // 只有不符合上面 Token 错误条件的请求才会走到这里 + const msg = resData?.message || '服务器响应异常'; + ElMessage.error(msg); return Promise.reject(error); } );