import axios, { AxiosRequestConfig } from 'axios' import { v4 } from 'uuid' //import qs from 'qs' import cryptojs from 'crypto-js' //import { addPending, removePending } from './pending' import { encryptBody, decryptBody } from '@/services/websocket/package/crypto' import { IMessageHead } from '@/types/proto/proto' import { useLoginStore, useAccountStore, useErrorInfoStore } from '@/stores' import { CommonResult, ResultCode, SendMsgToMQ } from './types' import { FunCode } from '@/constants/funcode' import service from '@/services' export default new (class { private readonly axiosInstance = axios.create({ timeout: 30000, }) constructor() { // 请求拦截器 this.axiosInstance.interceptors.request.use( (config) => { const loginStore = useLoginStore() //addPending(config) //将当前请求添加到列表中 //请求头签名 const sign = { token: loginStore.token, signsecret: 'qz7qWOMXKTMT5JlDs5w4NTPwWeR3xhF1v6wqbZ9cExmP6cc3spvNAp1wJJ1SqRI5', timestamp: new Date().getTime(), } //设置请求头 config.headers = { Authorization: sign.token, LoginID: loginStore.loginId, Group: loginStore.clientType, 'x-token': sign.token, //Signid: 'eecd3f37625f4501b88e9f0fa14b4b51', //Sign: cryptojs.SHA256(qs.stringify(sign)).toString(), //Timestamp: sign.timestamp.toString(), } return config }, (err) => { console.error(err) return Promise.reject('发生错误,请稍后再试') } ) // 响应拦截器 this.axiosInstance.interceptors.response.use( (res) => { //removePending(res) //在请求结束后,移除本次请求 return res }, (err) => { if (err.message === 'Network Error') { return Promise.reject('无效的网络连接') } if (err.response) { const { msg, message } = err.response.data ?? {} switch (err.response.status) { case 408: { return Promise.reject('请求超时,请稍后再试') } default: { return Promise.reject(msg || message) } } } return Promise.reject('发生错误,请稍后再试') } ) } /** 请求响应集合 */ private resultMap = new Set<() => void>() /** * 建议在过渡动画中启用,动画结束时禁用 * 可防止在动画过程中同时请求数据,数据请求先于动画完成,双绑数据的页面会实时渲染,导致动画卡顿的问题 */ private _pending = false /** 全局 pending 状态 */ get pending() { return this._pending } /** 在动画开始时设置一个 pending 状态,在动画结束后取消 pending 状态 */ set pending(status: boolean) { this._pending = status if (!status) { // 当 pending 状态为 false 时返回所有请求的回调 this.resultMap.forEach((fn) => { fn() this.resultMap.delete(fn) }) } } /** * Http 请求 * @param config * @param errMsg * @returns */ request(config: AxiosRequestConfig, errMsg?: string) { return new Promise((resolve, reject) => { this.axiosInstance(config).then((res) => { if (this.pending) { this.resultMap.add(() => resolve(res.data)) } else { resolve(res.data) } }).catch((err) => { const msg = err ?? (errMsg ? '请求失败: ' + errMsg : '请求失败,请稍后重试') reject(msg) }) }) } /** * Http 通用请求 * @param config * @param errMsg * @returns */ async commonRequest(config: AxiosRequestConfig, errMsg?: string) { const baseUrl = service.getConfig('goCommonSearchUrl') config.url = baseUrl + config.url const res = await this.request>(config, errMsg) switch (res.code) { case ResultCode.InvalidToken: return Promise.reject('令牌无效') case ResultCode.Success: return res default: return Promise.reject(res.msg) } } /** * Http 通用请求 * @param config * @param errMsg * @returns */ async goRequest(config: AxiosRequestConfig, errMsg?: string) { const baseUrl = service.getConfig('goAccess') config.url = baseUrl + config.url const res = await this.request>(config, errMsg) switch (res.code) { case ResultCode.InvalidToken: return Promise.reject('令牌无效') case 0: return res default: return Promise.reject(res.msg) } } /** * Http 通用请求 * @param config * @param errMsg * @returns */ async mqRequest({ data, requestCode, responseCode, marketId = 0 }: SendMsgToMQ<{ Header?: IMessageHead }>, errMsg?: string) { const loginStore = useLoginStore() const accountStore = useAccountStore() const requestId = FunCode[requestCode] const responseId = FunCode[responseCode] if (data) { data.Header = { AccountID: accountStore.accountId, FunCode: requestId, UUID: v4(), UserID: loginStore.userId, MarketID: marketId, ...data.Header, } } console.log(requestCode, data) const config: AxiosRequestConfig = { method: 'post', url: '/MQ/SendMsgToMQ', data: { data: encryptBody(JSON.stringify(data ?? '{}')), funCodeReq: requestId, funCodeRsp: responseId, isEncrypted: true, } } try { const res = await this.goRequest<{ data: string }>(config, errMsg) return await this.package50Parse(responseCode, res.data.data) } catch (err) { return await Promise.reject(err) } } /** * 解析 package50 数据 * @param responseCode * @param data * @returns */ private package50Parse(responseCode: keyof typeof FunCode, data: string) { const decryptedData = decryptBody(data) const res = JSON.parse(decryptedData) console.log(responseCode, res) switch (res.RetCode) { case 0: { return Promise.resolve(res as T) } case 12018: { if (res.RetDesc) { const word = cryptojs.enc.Base64.parse(res.RetDesc) // 解析base64 res.RetDesc = cryptojs.enc.Utf8.stringify(word) } return Promise.reject(res.RetDesc) } default: { // 银行 业务 以 Status 作为判断依据 if (res.Status === 0 || res.Status == 6007) { return Promise.resolve(res as T) } const { getErrorInfoByCode } = useErrorInfoStore() const msg = getErrorInfoByCode(res.RetCode) const error = String(res.RetDesc || res.RetCode || res.Status) return Promise.reject(msg ?? error) } } } })