index.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. import { isDev, ignoreTokens, config } from "@/config";
  2. import { locale, t } from "../locale";
  3. import { isNull, isObject, parse, storage } from "../utils";
  4. import { useStore } from "../store";
  5. // 请求参数类型定义
  6. export type RequestOptions = {
  7. url: string; // 请求地址
  8. method?: RequestMethod; // 请求方法
  9. data?: any; // 请求体数据
  10. params?: any; // URL参数
  11. header?: any; // 请求头
  12. timeout?: number; // 超时时间
  13. withCredentials?: boolean; // 是否携带凭证
  14. firstIpv4?: boolean; // 是否优先使用IPv4
  15. enableChunked?: boolean; // 是否启用分块传输
  16. };
  17. // 响应数据类型定义
  18. export type Response = {
  19. code?: number;
  20. message?: string;
  21. data?: any;
  22. };
  23. // 请求队列(用于等待token刷新后继续请求)
  24. let requests: ((token: string) => void)[] = [];
  25. // 标记token是否正在刷新
  26. let isRefreshing = false;
  27. // 判断当前url是否忽略token校验
  28. const isIgnoreToken = (url: string) => {
  29. return ignoreTokens.some((e) => {
  30. const pattern = e.replace(/\*/g, ".*");
  31. return new RegExp(pattern).test(url);
  32. });
  33. };
  34. /**
  35. * 通用请求方法
  36. * @param options 请求参数
  37. * @returns Promise<T>
  38. */
  39. export function request(options: RequestOptions): Promise<any | null> {
  40. let { url, method = "GET", data = {}, header = {}, timeout = 60000 } = options;
  41. const { user } = useStore();
  42. // 拼接基础url
  43. if (!url.startsWith("http")) {
  44. url = config.baseUrl + url;
  45. }
  46. // 开发环境下打印请求信息
  47. if (isDev) {
  48. console.log(`[${method}] ${url}`);
  49. }
  50. // 获取当前token
  51. let Authorization: string | null = user.token;
  52. // 如果是忽略token的接口,则不携带token
  53. if (isIgnoreToken(url)) {
  54. Authorization = null;
  55. }
  56. return new Promise((resolve, reject) => {
  57. // 发起请求的实际函数
  58. const next = () => {
  59. uni.request({
  60. url,
  61. method,
  62. data,
  63. header: {
  64. Authorization,
  65. language: locale.value,
  66. ...(header as UTSJSONObject)
  67. },
  68. timeout,
  69. success(res) {
  70. // 401 无权限
  71. if (res.statusCode == 401) {
  72. user.logout();
  73. reject({ message: t("无权限") } as Response);
  74. }
  75. // 502 服务异常
  76. else if (res.statusCode == 502) {
  77. reject({
  78. message: t("服务异常")
  79. } as Response);
  80. }
  81. // 404 未找到
  82. else if (res.statusCode == 404) {
  83. return reject({
  84. message: `[404] ${url}`
  85. } as Response);
  86. }
  87. // 200 正常响应
  88. else if (res.statusCode == 200) {
  89. if (res.data == null) {
  90. resolve(null);
  91. } else if (!isObject(res.data as any)) {
  92. resolve(res.data);
  93. } else {
  94. // 解析响应数据
  95. const { code, message, data } = parse<Response>(
  96. res.data ?? { code: 0 }
  97. )!;
  98. switch (code) {
  99. case 1000:
  100. resolve(data);
  101. break;
  102. default:
  103. reject({ message, code } as Response);
  104. break;
  105. }
  106. }
  107. } else {
  108. reject({ message: t("服务异常") } as Response);
  109. }
  110. },
  111. // 网络请求失败
  112. fail(err) {
  113. reject({ message: err.errMsg } as Response);
  114. }
  115. });
  116. };
  117. next();
  118. });
  119. }
  120. export function useGet(url: string, params?: any, config?: RequestOptions): Promise<Response> {
  121. const options: RequestOptions = {
  122. url,
  123. params,
  124. method: 'GET',
  125. ...config,
  126. }
  127. return request(options)
  128. }
  129. export function usePost(url: string, data?: any, config?: RequestOptions): Promise<Response> {
  130. const options: RequestOptions = {
  131. url,
  132. data,
  133. method: 'POST',
  134. ...config,
  135. }
  136. return request(options)
  137. }
  138. export function usePut(url: string, data?: any, config?: RequestOptions): Promise<Response> {
  139. const options: RequestOptions = {
  140. url,
  141. data,
  142. method: 'PUT',
  143. ...config,
  144. }
  145. return request(options)
  146. }
  147. export function useDelete(url: string, data?: any, config?: RequestOptions): Promise<Response> {
  148. const options: RequestOptions = {
  149. url,
  150. data,
  151. method: 'DELETE',
  152. ...config,
  153. }
  154. return request(options)
  155. }