import axios from 'axios'; import type { AxiosRequestConfig, AxiosResponse } from 'axios'; import { Message, Modal, Notification } from '@arco-design/web-vue'; import { initSyncTime, fetchTime } from '../utils/syncServerTime'; import { getAuthorization } from '../utils/crypto'; import { DEVICE_ID, PLATFORM } from '../constants/app'; import { objTypeOf } from '../utils/utils'; import ls from '../utils/storage'; import { useUserStore } from '../store'; export interface HttpResponse { message: string; code: number; data: T; } axios.defaults.timeout = 10 * 1000; let load = null; // 同一时间有多个请求时,会形成队列。在第一个请求创建loading,在最后一个响应关闭loading const queue = []; // 防止鉴权失效之后多次弹窗。 let unauthMsgBoxIsShow = false; const modifyConfig = (config: AxiosRequestConfig): void => { const userStore = useUserStore(); if (userStore.accessToken) { const ids = { privilegeId: ls.get('privilegeId', ''), orgId: userStore.orgInfo?.id, schoolId: userStore.curSchoolInfo?.id, userId: userStore.id, }; Object.entries(ids).forEach(([key, val]) => { if (val === null || val === 'null' || val === '') return; config.headers[key] = val; }); // 新版鉴权 const timestamp = fetchTime(); const Authorization = getAuthorization( { token: userStore.accessToken, timestamp, account: userStore.sessionId, uri: config.url.split('?')[0], method: config.method, }, 'token' ); config.headers.Authorization = Authorization; config.headers.time = timestamp; } config.headers.deviceId = DEVICE_ID; config.headers.platform = PLATFORM; config.headers.domain = window.location.origin; }; axios.interceptors.request.use( (config: AxiosRequestConfig) => { // 显示loading提示 if (!queue.length) { load = Message.loading({ content: '加载中...', duration: 0, }); } queue.push(1); modifyConfig(config); return config; }, (error) => { // 关闭loading提示 setTimeout(() => { queue.shift(); if (!queue.length) load.close(); }, 100); Message.error({ content: error.message || '请求错误', duration: 5 * 1000, }); return Promise.reject(error); } ); // add response interceptors axios.interceptors.response.use( (response: AxiosResponse) => { initSyncTime(new Date(response.headers.date).getTime()); // 关闭loading提示 setTimeout(() => { queue.shift(); if (!queue.length) load.close(); }, 100); if (response.config.responseType === 'blob') return response; const res = response.data; if (res.code !== 200) { Message.error({ content: res.message || '响应数据错误', duration: 5 * 1000, }); return Promise.reject(res.data); } if ( objTypeOf(res.data) === 'object' && Object.prototype.hasOwnProperty.call(res.data, 'success') ) { if (res.data.success) return res.data; Message.error({ content: res.message || '响应数据错误', duration: 5 * 1000, }); return Promise.reject(res.data); } return res.data; }, (error) => { // 关闭loading提示 setTimeout(() => { queue.shift(); if (!queue.length) load.close(); }, 100); console.dir(error); if (!error.response) { let message = error.message || '无响应错误'; if (message.indexOf('timeout') > -1) { message = '响应超时'; } Message.error({ content: message, duration: 5 * 1000, }); return Promise.reject(error); } const { response } = error; initSyncTime(new Date(response.headers.date).getTime()); if (objTypeOf(response.data) === 'blob') return Promise.reject(error.response.data); const errorData = response.data; let message = errorData.message || '响应未知错误'; const unauthStatus = [401, 403]; if (!unauthStatus.includes(response.status)) { Notification.error({ title: '错误提示', content: message }); return Promise.reject(error); } if (errorData.code === 401001 && message === '没有权限') { Notification.error({ title: '错误提示', content: message }); return Promise.reject(error); } if (unauthMsgBoxIsShow) return Promise.reject(error); const exposeMsgs = ['系统授权信息已过期,请联系系统管理员激活!']; unauthMsgBoxIsShow = true; message = exposeMsgs.includes(message) ? message : '身份验证失效,请重新登录!'; Modal.confirm({ title: '重新登陆?', content: message, escToClose: false, maskClosable: false, closable: false, hideCancel: true, titleAlign: 'start', onOk() { unauthMsgBoxIsShow = false; const userStore = useUserStore(); userStore.logout(); }, }); return Promise.reject(error); } );