request.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /**
  2. * 该文件可自行根据业务逻辑进行调整
  3. */
  4. import type { RequestClientOptions } from '@vben/request';
  5. import { useAppConfig } from '@vben/hooks';
  6. import { overridesPreferences as preferences } from '#/preferences';
  7. import {
  8. authenticateResponseInterceptor,
  9. defaultResponseInterceptor,
  10. errorMessageResponseInterceptor,
  11. RequestClient,
  12. } from '@vben/request';
  13. import { useAccessStore } from '@vben/stores';
  14. import { message } from 'ant-design-vue';
  15. import { useAuthStore } from '#/store';
  16. import { refreshTokenApi } from './core';
  17. const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD);
  18. function createRequestClient(baseURL: string, options?: RequestClientOptions) {
  19. const client = new RequestClient({
  20. ...options,
  21. baseURL,
  22. });
  23. /**
  24. * 重新认证逻辑
  25. */
  26. async function doReAuthenticate() {
  27. console.warn('Access token or refresh token is invalid or expired. ');
  28. const accessStore = useAccessStore();
  29. const authStore = useAuthStore();
  30. accessStore.setAccessToken(null);
  31. if (
  32. preferences?.app?.loginExpiredMode === 'modal' &&
  33. accessStore.isAccessChecked
  34. ) {
  35. accessStore.setLoginExpired(true);
  36. } else {
  37. await authStore.logout();
  38. }
  39. }
  40. /**
  41. * 刷新token逻辑
  42. */
  43. async function doRefreshToken() {
  44. const accessStore = useAccessStore();
  45. const resp = await refreshTokenApi();
  46. const newToken = resp.data;
  47. accessStore.setAccessToken(newToken);
  48. return newToken;
  49. }
  50. function formatToken(token: null | string) {
  51. return token ? `Bearer ${token}` : null;
  52. }
  53. // 请求头处理
  54. client.addRequestInterceptor({
  55. fulfilled: async (config) => {
  56. const accessStore = useAccessStore();
  57. config.headers.Authorization = formatToken(accessStore.accessToken);
  58. config.headers['Accept-Language'] = preferences?.app?.locale;
  59. config.headers['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
  60. return config;
  61. },
  62. });
  63. // 处理返回的响应数据格式
  64. client.addResponseInterceptor(
  65. defaultResponseInterceptor({
  66. codeField: 'code',
  67. dataField: 'data',
  68. successCode: 0,
  69. }),
  70. );
  71. // token过期的处理
  72. client.addResponseInterceptor(
  73. authenticateResponseInterceptor({
  74. client,
  75. doReAuthenticate,
  76. doRefreshToken,
  77. enableRefreshToken: preferences?.app?.enableRefreshToken || false,
  78. formatToken,
  79. }),
  80. );
  81. // 通用的错误处理,如果没有进入上面的错误处理逻辑,就会进入这里
  82. client.addResponseInterceptor(
  83. errorMessageResponseInterceptor((msg: string, error) => {
  84. // 这里可以根据业务进行定制,你可以拿到 error 内的信息进行定制化处理,根据不同的 code 做不同的提示,而不是直接使用 message.error 提示 msg
  85. // 当前mock接口返回的错误字段是 error 或者 message
  86. const responseData = error?.response?.data ?? {};
  87. const errorMessage = responseData?.error ?? responseData?.message ?? '';
  88. // 服务器提示登录
  89. if(responseData?.code && responseData?.code == 401) {
  90. message.error(errorMessage || msg);
  91. doReAuthenticate();
  92. return;
  93. }
  94. // 如果没有错误信息,则会根据状态码进行提示
  95. message.error(errorMessage || msg);
  96. }),
  97. );
  98. return client;
  99. }
  100. // 直接获取data字段内容,导致message,code, state 拿不到 {"state":1,"code":0,"data":[],"message":"更新游戏成功"}
  101. export const requestClient = createRequestClient(apiURL, {
  102. responseReturn: 'data',
  103. withCredentials: true,
  104. timeout:30 * 1000,
  105. });
  106. // 获取body内容,拿全的内容如data,message, code, state {"state":1,"code":0,"data":[],"message":"更新游戏成功"}
  107. export const requestBodyClient = createRequestClient(apiURL, {
  108. responseReturn: 'body',
  109. withCredentials: true,
  110. timeout:30 * 1000,
  111. });
  112. export const baseRequestClient = new RequestClient({ baseURL: apiURL });