index.ts 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. import axios, { AxiosRequestConfig } from 'axios'
  2. import { v4 } from 'uuid'
  3. //import qs from 'qs'
  4. import cryptojs from 'crypto-js'
  5. //import { addPending, removePending } from './pending'
  6. import { encryptBody, decryptBody } from '@/services/websocket/package/crypto'
  7. import { IMessageHead } from '@/types/proto/proto'
  8. import { useLoginStore, useAccountStore, useErrorInfoStore } from '@/stores'
  9. import { CommonResult, ResultCode, SendMsgToMQ } from './types'
  10. import { FunCode } from '@/constants/funcode'
  11. import service from '@/services'
  12. export default new (class {
  13. private readonly axiosInstance = axios.create({
  14. timeout: 30000,
  15. })
  16. constructor() {
  17. // 请求拦截器
  18. this.axiosInstance.interceptors.request.use(
  19. (config) => {
  20. const loginStore = useLoginStore()
  21. //addPending(config) //将当前请求添加到列表中
  22. //请求头签名
  23. const sign = {
  24. token: loginStore.token,
  25. signsecret: 'qz7qWOMXKTMT5JlDs5w4NTPwWeR3xhF1v6wqbZ9cExmP6cc3spvNAp1wJJ1SqRI5',
  26. timestamp: new Date().getTime(),
  27. }
  28. //设置请求头
  29. config.headers = {
  30. Authorization: sign.token,
  31. LoginID: loginStore.loginId,
  32. Group: loginStore.clientType,
  33. 'x-token': sign.token,
  34. //Signid: 'eecd3f37625f4501b88e9f0fa14b4b51',
  35. //Sign: cryptojs.SHA256(qs.stringify(sign)).toString(),
  36. //Timestamp: sign.timestamp.toString(),
  37. }
  38. return config
  39. },
  40. (err) => {
  41. console.error(err)
  42. return Promise.reject('发生错误,请稍后再试')
  43. }
  44. )
  45. // 响应拦截器
  46. this.axiosInstance.interceptors.response.use(
  47. (res) => {
  48. //removePending(res) //在请求结束后,移除本次请求
  49. return res
  50. },
  51. (err) => {
  52. if (err.message === 'Network Error') {
  53. return Promise.reject('无效的网络连接')
  54. }
  55. if (err.response) {
  56. const { msg, message } = err.response.data ?? {}
  57. switch (err.response.status) {
  58. case 408: {
  59. return Promise.reject('请求超时,请稍后再试')
  60. }
  61. default: {
  62. return Promise.reject(msg || message)
  63. }
  64. }
  65. }
  66. return Promise.reject('发生错误,请稍后再试')
  67. }
  68. )
  69. }
  70. /** 请求响应集合 */
  71. private resultMap = new Set<() => void>()
  72. /**
  73. * 建议在过渡动画中启用,动画结束时禁用
  74. * 可防止在动画过程中同时请求数据,数据请求先于动画完成,双绑数据的页面会实时渲染,导致动画卡顿的问题
  75. */
  76. private _pending = false
  77. /** 全局 pending 状态 */
  78. get pending() {
  79. return this._pending
  80. }
  81. /** 在动画开始时设置一个 pending 状态,在动画结束后取消 pending 状态 */
  82. set pending(status: boolean) {
  83. this._pending = status
  84. if (!status) {
  85. // 当 pending 状态为 false 时返回所有请求的回调
  86. this.resultMap.forEach((fn) => {
  87. fn()
  88. this.resultMap.delete(fn)
  89. })
  90. }
  91. }
  92. /**
  93. * Http 请求
  94. * @param config
  95. * @param errMsg
  96. * @returns
  97. */
  98. request<T>(config: AxiosRequestConfig, errMsg?: string) {
  99. return new Promise<T>((resolve, reject) => {
  100. this.axiosInstance(config).then((res) => {
  101. if (this.pending) {
  102. this.resultMap.add(() => resolve(res.data))
  103. } else {
  104. resolve(res.data)
  105. }
  106. }).catch((err) => {
  107. const msg = err ?? (errMsg ? '请求失败: ' + errMsg : '请求失败,请稍后重试')
  108. reject(msg)
  109. })
  110. })
  111. }
  112. /**
  113. * Http 通用请求
  114. * @param config
  115. * @param errMsg
  116. * @returns
  117. */
  118. async commonRequest<T>(config: AxiosRequestConfig, errMsg?: string) {
  119. const baseUrl = service.getConfig('goCommonSearchUrl')
  120. config.url = baseUrl + config.url
  121. const res = await this.request<CommonResult<T>>(config, errMsg)
  122. switch (res.code) {
  123. case ResultCode.InvalidToken:
  124. return Promise.reject('令牌无效')
  125. case ResultCode.Success:
  126. return res
  127. default:
  128. return Promise.reject(res.msg)
  129. }
  130. }
  131. /**
  132. * Http 通用请求
  133. * @param config
  134. * @param errMsg
  135. * @returns
  136. */
  137. async goRequest<T>(config: AxiosRequestConfig, errMsg?: string) {
  138. const baseUrl = service.getConfig('goAccess')
  139. config.url = baseUrl + config.url
  140. const res = await this.request<CommonResult<T>>(config, errMsg)
  141. switch (res.code) {
  142. case ResultCode.InvalidToken:
  143. return Promise.reject('令牌无效')
  144. case 0:
  145. return res
  146. default:
  147. return Promise.reject(res.msg)
  148. }
  149. }
  150. /**
  151. * Http 通用请求
  152. * @param config
  153. * @param errMsg
  154. * @returns
  155. */
  156. async mqRequest<T>({ data, requestCode, responseCode, marketId = 0 }: SendMsgToMQ<{ Header?: IMessageHead }>, errMsg?: string) {
  157. const loginStore = useLoginStore()
  158. const accountStore = useAccountStore()
  159. const requestId = FunCode[requestCode]
  160. const responseId = FunCode[responseCode]
  161. if (data) {
  162. data.Header = {
  163. AccountID: accountStore.accountId,
  164. FunCode: requestId,
  165. UUID: v4(),
  166. UserID: loginStore.userId,
  167. MarketID: marketId,
  168. ...data.Header,
  169. }
  170. }
  171. console.log(requestCode, data)
  172. const config: AxiosRequestConfig = {
  173. method: 'post',
  174. url: '/MQ/SendMsgToMQ',
  175. data: {
  176. data: encryptBody(JSON.stringify(data ?? '{}')),
  177. funCodeReq: requestId,
  178. funCodeRsp: responseId,
  179. isEncrypted: true,
  180. }
  181. }
  182. try {
  183. const res = await this.goRequest<{ data: string }>(config, errMsg)
  184. return await this.package50Parse<T>(responseCode, res.data.data)
  185. } catch (err) {
  186. return await Promise.reject(err)
  187. }
  188. }
  189. /**
  190. * 解析 package50 数据
  191. * @param responseCode
  192. * @param data
  193. * @returns
  194. */
  195. private package50Parse<T>(responseCode: keyof typeof FunCode, data: string) {
  196. const decryptedData = decryptBody(data)
  197. const res = JSON.parse(decryptedData)
  198. console.log(responseCode, res)
  199. switch (res.RetCode) {
  200. case 0: {
  201. return Promise.resolve(res as T)
  202. }
  203. case 12018: {
  204. if (res.RetDesc) {
  205. const word = cryptojs.enc.Base64.parse(res.RetDesc) // 解析base64
  206. res.RetDesc = cryptojs.enc.Utf8.stringify(word)
  207. }
  208. return Promise.reject(res.RetDesc)
  209. }
  210. default: {
  211. // 银行 业务 以 Status 作为判断依据
  212. if (res.Status === 0 || res.Status == 6007) {
  213. return Promise.resolve(res as T)
  214. }
  215. const { getErrorInfoByCode } = useErrorInfoStore()
  216. const msg = getErrorInfoByCode(res.RetCode)
  217. const error = String(res.RetDesc || res.RetCode || res.Status)
  218. return Promise.reject(msg ?? error)
  219. }
  220. }
  221. }
  222. })