From 8f9d48be28aae04422edb407b18107e379cbda23 Mon Sep 17 00:00:00 2001
From: linwe <872216996@qq.com>
Date: Thu, 21 Nov 2024 13:48:24 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/main'

---
 src/utils/http.js |   94 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 93 insertions(+), 1 deletions(-)

diff --git a/src/utils/http.js b/src/utils/http.js
index 3fd00b4..2cf82e0 100644
--- a/src/utils/http.js
+++ b/src/utils/http.js
@@ -6,7 +6,7 @@
  * isToken是否需要token
  */
 import axios from 'axios'
-// import router from '@/router/'
+import router from '@/router/index'
 
 import {
   isURL,
@@ -27,6 +27,10 @@
 
 // 全局未授权错误提示状态,只提示一次
 let isErrorShown = false
+
+// 全局锁机制相关变量
+let isRefreshing = false // 标记当前是否正在刷新token
+let refreshTokenPromise = null // 刷新token的Promise,避免重复请求
 
 // 超时时间设置为10分钟,部分接口上传比较慢,如固件上传
 axios.defaults.timeout = 600000
@@ -103,6 +107,8 @@
 //http response拦截
 axios.interceptors.response.use(
   res => {
+    const store = useLogin()
+
     NProgress.done()
     const status = res.data.error_code || res.data.code || res.status
     const statusWhiteList = []
@@ -112,6 +118,92 @@
     //如果在白名单里则自行catch逻辑处理
     if (statusWhiteList.includes(status)) return Promise.reject(res)
 
+    // 如果是401并且没有重试过,尝试刷新token
+    if (status === 401 && !config._retry) {
+      config._retry = true
+
+      // 如果当前已经在刷新token,等待刷新完成
+      if (isRefreshing) {
+        return refreshTokenPromise.then(() => {
+          const meta = config.meta || {}
+          const isToken = meta.isToken === false
+          const cryptoToken = config.cryptoToken === true
+
+          const token = store.token
+
+          if (token && !isToken) {
+            config.headers['Blade-Auth'] = cryptoToken
+              ? 'crypto ' + crypto.encryptAES(token, crypto.cryptoKey)
+              : 'bearer ' + token
+          }
+          return axios(config)
+        })
+      }
+
+      // 开始刷新token
+      isRefreshing = true
+
+      // 调用RefreshToken action来刷新token
+      refreshTokenPromise = store.RefreshToken().then(() => {
+        const meta = config.meta || {}
+        const isToken = meta.isToken === false
+        const cryptoToken = config.cryptoToken === true
+        // 获取刷新后的token
+        const token = store.token
+
+        if (token && !isToken) {
+          config.headers['Blade-Auth'] = cryptoToken
+            ? 'crypto ' + crypto.encryptAES(token, crypto.cryptoKey)
+            : 'bearer ' + token
+        }
+        return axios(config)
+      }).catch(() => {
+        isRefreshing = false // 重置刷新标志
+        // 首次报错时提示
+        if (!isErrorShown) {
+          isErrorShown = true
+          ElMessage({
+            message: '用户令牌过期,请重新登录',
+            type: 'error',
+          })
+        }
+        // 清除token信息
+        store.removeToken()
+        store.removeRefreshToken()
+        // 重定向到登录页
+        store.LogOut().then(res => {
+          router.push({
+            path: '/login'
+          })
+        })
+        return Promise.reject(new Error(message))
+      })
+
+      return refreshTokenPromise
+    }
+
+    // 如果是401并且已经重试过,直接跳转到登录页面
+    if (status === 401 && config._retry) {
+      if (!isErrorShown) {
+        isErrorShown = true
+        ElMessage({
+          message: '用户令牌过期,请重新登录',
+          type: 'error',
+        })
+      }
+      // 清除token信息
+      store.removeToken()
+      store.removeRefreshToken()
+
+      // 重定向到登录页
+      store.LogOut().then(res => {
+        router.push({
+          path: '/login'
+        })
+      })
+      return Promise.reject(new Error(message))
+    }
+
     // 如果请求为oauth2错误码则首次报错时提示
     if (status > 2000 && !validatenull(res.data.error_description)) {
       // 首次报错时提示

--
Gitblit v1.9.3