alova.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import type { uniappRequestAdapter } from '@alova/adapter-uniapp'
  2. import type { IResponse } from './types'
  3. import AdapterUniapp from '@alova/adapter-uniapp'
  4. import { createAlova } from 'alova'
  5. import { createServerTokenAuthentication } from 'alova/client'
  6. import VueHook from 'alova/vue'
  7. import { LOGIN_PAGE } from '@/router/config'
  8. import { ContentTypeEnum, ResultEnum, ShowMessage } from './tools/enum'
  9. // 配置动态Tag
  10. export const API_DOMAINS = {
  11. DEFAULT: import.meta.env.VITE_SERVER_BASEURL,
  12. SECONDARY: import.meta.env.VITE_SERVER_BASEURL_SECONDARY,
  13. }
  14. /**
  15. * 创建请求实例
  16. */
  17. const { onAuthRequired, onResponseRefreshToken } = createServerTokenAuthentication<
  18. typeof VueHook,
  19. typeof uniappRequestAdapter
  20. >({
  21. refreshTokenOnError: {
  22. isExpired: (error) => {
  23. return error.response?.status === ResultEnum.Unauthorized
  24. },
  25. handler: async () => {
  26. try {
  27. // await authLogin();
  28. }
  29. catch (error) {
  30. // 切换到登录页
  31. await uni.reLaunch({ url: LOGIN_PAGE })
  32. throw error
  33. }
  34. },
  35. },
  36. })
  37. /**
  38. * alova 请求实例
  39. */
  40. const alovaInstance = createAlova({
  41. baseURL: API_DOMAINS.DEFAULT,
  42. ...AdapterUniapp(),
  43. timeout: 5000,
  44. statesHook: VueHook,
  45. beforeRequest: onAuthRequired((method) => {
  46. // 设置默认 Content-Type
  47. method.config.headers = {
  48. ContentType: ContentTypeEnum.JSON,
  49. Accept: 'application/json, text/plain, */*',
  50. ...method.config.headers,
  51. }
  52. const { config } = method
  53. const ignoreAuth = !config.meta?.ignoreAuth
  54. console.log('ignoreAuth===>', ignoreAuth)
  55. // 处理认证信息 自行处理认证问题
  56. if (ignoreAuth) {
  57. const token = 'getToken()'
  58. if (!token) {
  59. throw new Error('[请求错误]:未登录')
  60. }
  61. // method.config.headers.token = token;
  62. }
  63. // 处理动态域名
  64. if (config.meta?.domain) {
  65. method.baseURL = config.meta.domain
  66. console.log('当前域名', method.baseURL)
  67. }
  68. }),
  69. responded: onResponseRefreshToken((response, method) => {
  70. const { config } = method
  71. const { requestType } = config
  72. const {
  73. statusCode,
  74. data: rawData,
  75. errMsg,
  76. } = response as UniNamespace.RequestSuccessCallbackResult
  77. // 处理特殊请求类型(上传/下载)
  78. if (requestType === 'upload' || requestType === 'download') {
  79. return response
  80. }
  81. // 处理 HTTP 状态码错误
  82. if (statusCode !== 200) {
  83. const errorMessage = ShowMessage(statusCode) || `HTTP请求错误[${statusCode}]`
  84. console.error('errorMessage===>', errorMessage)
  85. uni.showToast({
  86. title: errorMessage,
  87. icon: 'error',
  88. })
  89. throw new Error(`${errorMessage}:${errMsg}`)
  90. }
  91. // 处理业务逻辑错误
  92. const { code, message, data } = rawData as IResponse
  93. // 0和200当做成功都很普遍,这里直接兼容两者,见 ResultEnum
  94. if (code !== ResultEnum.Success0 && code !== ResultEnum.Success200) {
  95. if (config.meta?.toast !== false) {
  96. uni.showToast({
  97. title: message,
  98. icon: 'none',
  99. })
  100. }
  101. throw new Error(`请求错误[${code}]:${message}`)
  102. }
  103. // 处理成功响应,返回业务数据
  104. return data
  105. }),
  106. })
  107. export const http = alovaInstance