wujingjing
2024-10-17 2c9729f0cecffe6dbb7f8f99ebad72f3e85a7ded
src/utils/request.ts
@@ -1,23 +1,43 @@
import type { AxiosInstance, AxiosRequestConfig } from 'axios';
import axios from 'axios';
import { ElMessage } from 'element-plus';
import { NO_AUTH_API_LIST } from '../api/ai/chat';
import { LOGIN_URL, TEL_LOGIN_URL } from '../api/ai/user';
import emitter from './mitt';
import { debounce } from './util';
import { debounce, decodeFormData } from './util';
import { AUTH_URL, MAIN_URL, SECONDARY_URL } from '/@/constants';
import { Local, Session } from '/@/utils/storage';
import { Local, LoginInfo, Session } from '/@/utils/storage';
import { Logger } from '../model/logger/Logger';
// import JSONbig from 'json-bigint';
//#region ====================== 后端 res.err_code ======================
export const enum ErrorCode {
   /** @description 权限验证失败 */
   Message = 'MESSAGE',
   /** @description 内部错误 */
   Exception = 'EXCEPTION',
   /** @description 无权使用 */
   Auth = 'AUTH',
}
//#endregion
const openLoginDlg = debounce(() => {
const emitNoAuth = () => {
   emitter.emit('logout');
   emitter.emit('openLoginDlg');
});
};
export const handleNormalAuth = () => {
   const accessSession = Local.get(accessSessionKey);
   if (!accessSession) {
      emitter.emit('logout');
      emitter.emit('openLoginDlg');
   }
   return !!accessSession;
};
export const handleNoAuth = debounce(() => {
   emitNoAuth();
});
const initRequestInterceptor = (request: AxiosInstance) => {
   // 添加请求拦截器
   request.interceptors.request.use(
@@ -27,9 +47,14 @@
         if (accessSession) {
            // 将 token 添加到请求报文头中
            config.headers['hswatersession'] = accessSession;
         } else {
            openLoginDlg();
         }
         if (!NO_AUTH_API_LIST.includes(config.url)) {
            if (!accessSession && config.url !== LOGIN_URL && config.url !== TEL_LOGIN_URL) {
               handleNoAuth(config.url);
               throw '权限验证失败';
            }
         }
         return config;
      },
      (error) => {
@@ -63,27 +88,31 @@
         if (!serveData.json_ok) {
            switch (serveData?.err_code) {
               case ErrorCode.Auth:
                  openLoginDlg();
                  throw '权限验证失败';
                  if (res.config.url !== LOGIN_URL && res.config.url !== TEL_LOGIN_URL) {
                     handleNoAuth();
                     throw '权限验证失败';
                  }
                  break;
               case ErrorCode.Exception:
                  const param = res.config.data ? `\n    请求参数:${JSON.stringify(decodeFormData(res.config.data))}\n` : '';
                  ElMessage.error('内部错误!');
                  Logger.error(`${res.config.url} 响应失败${param}`, serveData?.json_msg && new Error(serveData?.json_msg));
                  return res.data;
            }
            const msg = serveData.json_msg ?? '';
            const error = serveData?.err_code ? `${msg ? `【${serveData.err_code}】` : serveData.err_code}` : '';
            const tip = error + msg || '请求失败';
            ElMessage.error(tip);
            const url = res.request.responseURL;
            throw new Error(url + '\n' + tip);
         }
         return res.data;
      },
      (error) => {
         if (typeof error === 'string') {
            // ElMessage.error(error);
            return Promise.reject(error);
         }
         // 处理响应错误
         if (error.response) {
            if (error.response.status === 401) {
               clearAccessTokens();
            }
         }
         // 对响应错误做点什么
         if (error.message.indexOf('timeout') != -1) {
            ElMessage.error('网络超时');
@@ -132,19 +161,33 @@
 * @description 域名前缀
 * 防止类似于 http://sqi.beng35.com/airp 和 http://sqi.beng35.com/test 公用同一个 token 或 userInfo
 */
const subDomainName = window.location.pathname
   .split('/')
   .filter((item) => !!item)
   .join('-');
const domainPrefix = subDomainName ? `${subDomainName}-` : '';
export const getDomainPrefix = (win: Window) => {
   const subDomainName = win.location.pathname
      .split('/')
      .filter((item) => !!item)
      .join('-');
   const domainPrefix = subDomainName ? `${subDomainName}-` : '';
   return domainPrefix;
};
// token 键定义
export const accessSessionKey = domainPrefix + 'access-session';
export const userNameKey = domainPrefix + 'userName';
export const sessionName = 'access-session';
export const userName = 'userName';
export const getSessionKey = (win: Window) => {
   return getDomainPrefix(win) + sessionName;
};
export const getUserNameKey = (win: Window) => {
   return getDomainPrefix(win) + userName;
};
export const accessSessionKey = getSessionKey(window);
export const userNameKey = getUserNameKey(window);
export const refreshAccessTokenKey = `x-${accessSessionKey}`;
// userInfo键定义
export const userInfoKey = domainPrefix + 'userInfo';
export const userInfoKey = getDomainPrefix(window) + 'userInfo';
// 获取 token
export const getSession = () => {
@@ -153,7 +196,8 @@
// 清除 token
export const clearAccessTokens = async () => {
   Local.remove(accessSessionKey);
   // Local.remove(accessSessionKey);
   LoginInfo.remove();
   // 清除用户信息(每次刷新都需要利用用户信息去请求对应权限菜单)
   Local.remove(userInfoKey);
   // 清除其他