interceptor.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. /* eslint-disable brace-style */ // 原因:unibest 官方维护的代码,尽量不要大概,避免难以合并
  2. import type { CustomRequestOptions } from '@/http/types'
  3. import { useTokenStore, useUserStore } from '@/store'
  4. import { getEnvBaseUrl } from '@/utils'
  5. import { ApiEncrypt } from '@/utils/encrypt'
  6. import { stringifyQuery } from './tools/queryString'
  7. // 请求基准地址
  8. const baseUrl = getEnvBaseUrl()
  9. const tenantEnable = import.meta.env.VITE_APP_TENANT_ENABLE
  10. const whiteList: string[] = [
  11. '/login',
  12. '/refresh-token',
  13. '/system/tenant/get-id-by-name',
  14. ] // 白名单列表,不需要传递 token 字段
  15. // 拦截器配置
  16. const httpInterceptor = {
  17. // 拦截前触发
  18. invoke(options: CustomRequestOptions) {
  19. // 接口请求支持通过 query 参数配置 queryString
  20. if (options.query) {
  21. const queryStr = stringifyQuery(options.query)
  22. if (options.url.includes('?')) {
  23. options.url += `&${queryStr}`
  24. }
  25. else {
  26. options.url += `?${queryStr}`
  27. }
  28. }
  29. // 非 http 开头需拼接地址
  30. if (!options.url.startsWith('http')) {
  31. // #ifdef H5
  32. if (JSON.parse(import.meta.env.VITE_APP_PROXY_ENABLE)) {
  33. // 自动拼接代理前缀
  34. options.url = import.meta.env.VITE_APP_PROXY_PREFIX + options.url
  35. }
  36. else {
  37. options.url = baseUrl + options.url
  38. }
  39. // #endif
  40. // 非H5正常拼接
  41. // #ifndef H5
  42. options.url = baseUrl + options.url
  43. // #endif
  44. // TIPS: 如果需要对接多个后端服务,也可以在这里处理,拼接成所需要的地址
  45. }
  46. // 1. 请求超时
  47. options.timeout = 60000 // 60s
  48. // 2. (可选)添加小程序端请求头标识
  49. options.header = {
  50. ...options.header,
  51. }
  52. // 3. 添加 token 请求头标识
  53. const tokenStore = useTokenStore()
  54. const token = tokenStore.validToken
  55. let isToken = (options!.header || {}).isToken === false
  56. for (const v of whiteList) {
  57. if (options.url && options.url.includes(v)) {
  58. isToken = false
  59. break
  60. }
  61. }
  62. if (!isToken && token) {
  63. options.header.Authorization = `Bearer ${token}`
  64. }
  65. // 4. 添加租户标识
  66. if (tenantEnable && tenantEnable === 'true') {
  67. const tenantId = useUserStore().tenantId
  68. if (tenantId) {
  69. options.header['tenant-id'] = tenantId
  70. }
  71. }
  72. // 5. 是否 API 加密
  73. if (options.isEncrypt) {
  74. try {
  75. // 加密请求数据
  76. if (options.data) {
  77. options.data = ApiEncrypt.encryptRequest(options.data)
  78. // 设置加密标识头
  79. options.header[ApiEncrypt.getEncryptHeader()] = 'true'
  80. }
  81. } catch (error) {
  82. console.error('请求数据加密失败:', error)
  83. throw error
  84. }
  85. }
  86. return options
  87. },
  88. }
  89. export const requestInterceptor = {
  90. install() {
  91. // 拦截 request 请求
  92. uni.addInterceptor('request', httpInterceptor)
  93. // 拦截 uploadFile 文件上传
  94. uni.addInterceptor('uploadFile', httpInterceptor)
  95. },
  96. }