智慧园区前端大屏
shuishen
2024-12-18 9a37c5e1b2190c3f6ec71483923922189091dd52
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)) {
      // 首次报错时提示