From 9a37c5e1b2190c3f6ec71483923922189091dd52 Mon Sep 17 00:00:00 2001
From: shuishen <1109946754@qq.com>
Date: Wed, 18 Dec 2024 09:42:01 +0800
Subject: [PATCH] 事件模拟更新

---
 src/utils/http.js |  144 +++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 131 insertions(+), 13 deletions(-)

diff --git a/src/utils/http.js b/src/utils/http.js
index 7c162c2..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,
@@ -19,9 +19,18 @@
 
 import NProgress from 'nprogress' // progress bar
 import 'nprogress/nprogress.css' // progress bar style
+import { Base64 } from 'js-base64'
+import { baseUrl } from '@/config/env'
+import crypto from '@/utils/crypto'
+
+import { useLogin } from '@/store/login'
 
 // 全局未授权错误提示状态,只提示一次
 let isErrorShown = false
+
+// 全局锁机制相关变量
+let isRefreshing = false // 标记当前是否正在刷新token
+let refreshTokenPromise = null // 刷新token的Promise,避免重复请求
 
 // 超时时间设置为10分钟,部分接口上传比较慢,如固件上传
 axios.defaults.timeout = 600000
@@ -38,7 +47,12 @@
 //http request拦截
 axios.interceptors.request.use(
   config => {
-    console.log(config, '906456456465')
+    const store = useLogin()
+    //地址为已经配置状态则不添加前缀
+    if (!isURL(config.url) && !config.url.startsWith(baseUrl)) {
+      config.url = baseUrl + config.url
+    }
+
     // start progress bar
     NProgress.start()
     // 初始化错误提示状态
@@ -46,23 +60,39 @@
 
     //安全请求header
     config.headers['Blade-Requested-With'] = 'BladeHttpRequest'
+    //headers判断是否需要
+    const authorization = config.authorization === false
+    if (!authorization) {
+      config.headers['Authorization'] = `Basic ${Base64.encode(
+        `zhyq:zhyq_secret`
+      )}`
+    }
 
     //headers判断请求是否携带token
     const meta = config.meta || {}
+    const isToken = meta.isToken === false
     //headers传递token是否加密
+    const cryptoToken = config.cryptoToken === true
     //判断传递数据是否加密
+    const cryptoData = config.cryptoData === true
+    const token = store.token
 
+    if (token && !isToken) {
+      config.headers['Blade-Auth'] = cryptoToken
+        ? 'crypto ' + crypto.encryptAES(token, crypto.cryptoKey)
+        : 'bearer ' + token
+    }
     // 开启报文加密
-    // if (cryptoData) {
-    //   if (config.params) {
-    //     const data = crypto.encryptAES(JSON.stringify(config.params), crypto.aesKey);
-    //     config.params = { data };
-    //   }
-    //   if (config.data) {
-    //     config.text = true;
-    //     config.data = crypto.encryptAES(JSON.stringify(config.data), crypto.aesKey);
-    //   }
-    // }
+    if (cryptoData) {
+      if (config.params) {
+        const data = crypto.encryptAES(JSON.stringify(config.params), crypto.aesKey)
+        config.params = { data }
+      }
+      if (config.data) {
+        config.text = true
+        config.data = crypto.encryptAES(JSON.stringify(config.data), crypto.aesKey)
+      }
+    }
     //headers中配置text请求
     if (config.text === true) {
       config.headers['Content-Type'] = 'text/plain'
@@ -77,15 +107,103 @@
 //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 = website.statusWhiteList || []
+    const statusWhiteList = []
     const message = res.data.msg || res.data.error_description || '系统错误'
     const config = res.config
     const cryptoData = config.cryptoData === true
     //如果在白名单里则自行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