Просмотр исходного кода

fix(auth): 修「重新登录」点完不跳登录页的递归弹窗 bug

bug: 在 401 拦截器里点「重新登录」时,useUserStore().logout()
内部 await logoutApi() 因为 token 已过期会再次返回 401,触发同一
拦截器递归弹窗,体感「点了没反应」。

修法:
- user store logout() 新增 silent 模式: 传 true 时不调后端 /auth/logout
  接口,直接清本地状态(避免 401 递归)
- request.ts 401 拦截器: 「重新登录」回调里用 logout(true),并把
  isRelogin.show = false 移到 logout 完成之后
- permission.ts 路由守卫: token 失效 getInfo 401 时也用 logout(true),
  并把 isRelogin.show 复位
yangjingjing 1 день назад
Родитель
Сommit
ab0d7734d7
3 измененных файлов с 20 добавлено и 6 удалено
  1. 4 2
      src/permission.ts
  2. 10 1
      src/store/modules/user.ts
  3. 6 3
      src/utils/request.ts

+ 4 - 2
src/permission.ts

@@ -33,9 +33,11 @@ router.beforeEach(async (to, from, next) => {
         // 判断当前用户是否已拉取完user_info信息
         const [err] = await tos(useUserStore().getInfo());
         if (err) {
-          await useUserStore().logout();
+          // 静默退出:token 失效时 /auth/logout 必然 401,会触发 axios 拦截器递归弹窗
+          await useUserStore().logout(true);
+          isRelogin.show = false;
           ElMessage.error(err);
-          next({ path: '/' });
+          next({ path: '/login' });
         } else {
           isRelogin.show = false;
           const accessRoutes = await usePermissionStore().generateRoutes();

+ 10 - 1
src/store/modules/user.ts

@@ -58,7 +58,16 @@ export const useUserStore = defineStore('user', () => {
   };
 
   // 注销
-  const logout = async (): Promise<void> => {
+  // silent = true 时不调后端 /auth/logout 接口(避免 token 过期时 401 递归触发"重新登录"弹窗),
+  // 由调用方决定是清本地状态走人,还是发请求让后端踢下线。
+  const logout = async (silent = false): Promise<void> => {
+    if (silent) {
+      token.value = '';
+      roles.value = [];
+      permissions.value = [];
+      removeToken();
+      return;
+    }
     try {
       await logoutApi();
     } catch (err) {

+ 6 - 3
src/utils/request.ts

@@ -137,16 +137,19 @@ service.interceptors.response.use(
           cancelButtonText: '取消',
           type: 'warning'
         }).then(() => {
-          isRelogin.show = false;
-          useUserStore().logout().then(() => {
+          // 静默退出:不调 /auth/logout 后端接口,直接清本地状态
+          // (避免 token 过期时 logoutApi 返回 401 再次触发本拦截器递归弹窗)
+          useUserStore().logout(true).then(() => {
+            isRelogin.show = false;
             router.replace({
               path: '/login',
               query: {
                 redirect: encodeURIComponent(router.currentRoute.value.fullPath || '/')
               }
-            })
+            });
           });
         }).catch(() => {
+          // 用户点"取消" — 重置标记,允许下次 401 再次弹窗
           isRelogin.show = false;
         });
       }