request.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import axios from 'axios'
  2. import { useUserStore } from '@/store'
  3. import storage from 'store'
  4. import { Notification, Message } from '@arco-design/web-vue';
  5. import { VueAxios } from './axios'
  6. import { v4 as uuidv4 } from 'uuid'
  7. import { LRUCache } from 'lru-cache'
  8. import { generateAesKey, aesEncrypt, aesDecrypt, rsaEncryptKey } from './encrypt'
  9. import { isElectron } from './electron'
  10. const electron = isElectron()
  11. const request = axios.create({
  12. baseURL: import.meta.env.VITE_APP_API_BASE_URL,
  13. timeout: 10000
  14. })
  15. const aesKeyCache = new LRUCache({
  16. max: 200,
  17. ttl: 1000 * 60 * 5
  18. })
  19. const errorHandler = (error) => {
  20. const userStore = useUserStore()
  21. const user = storage.get('user')
  22. console.log(error.stack)
  23. if (error.response) {
  24. if (error.response.status === 401) {
  25. Message.error('登录失效,请重新登录')
  26. if (user) {
  27. userStore.logout() // 调用 Pinia store 中的 logout 方法
  28. setTimeout(() => {
  29. window.location.reload()
  30. }, 1500)
  31. }
  32. }
  33. } else {
  34. console.error('无法连接到服务器,请检查网络')
  35. Notification.error({
  36. title: '请求失败',
  37. content: '网络不畅或服务器停机维护中,请稍后再试'
  38. })
  39. }
  40. }
  41. request.interceptors.request.use(config => {
  42. const userStore = useUserStore()
  43. const user = userStore.$state
  44. if (config.headers['Content-Type'] !== 'multipart/form-data') {
  45. const data = {
  46. ...(config.method === 'get' ? config.params : config.data),
  47. time: Date.now(),
  48. uuid: user?.uuid,
  49. session: user?.session
  50. }
  51. const aesKey = generateAesKey()
  52. const encryptedData = aesEncrypt(data, aesKey)
  53. const encryptedKey = rsaEncryptKey(aesKey)
  54. const requestId = uuidv4()
  55. config.headers['X-Request-ID'] = requestId
  56. aesKeyCache.set(requestId, aesKey)
  57. if (config.method === 'get')
  58. config.params = {
  59. a: encryptedData,
  60. b: encryptedKey
  61. }
  62. else
  63. config.data = {
  64. a: encryptedData,
  65. b: encryptedKey
  66. }
  67. }
  68. if (electron)
  69. config.headers["Device-Type"] = 'RunForge Desktop Client'
  70. return config
  71. }, errorHandler)
  72. request.interceptors.response.use(async (response) => {
  73. if (response.data.b) {
  74. const requestId = response.config.headers['X-Request-ID']
  75. const aesKey = aesKeyCache.get(requestId)
  76. response.data.data = aesDecrypt(response.data.b, aesKey)
  77. aesKeyCache.delete(requestId)
  78. }
  79. return response.data
  80. }, errorHandler)
  81. const installer = {
  82. vm: {},
  83. install(Vue) {
  84. Vue.use(VueAxios, request)
  85. }
  86. }
  87. export default request
  88. export {
  89. installer as VueAxios,
  90. request as axios
  91. }