1
0

request.ts 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. /**
  2. * 该文件可自行根据业务逻辑进行调整
  3. */
  4. import type { HttpResponse } from '@vben/request';
  5. import { useAppConfig } from '@vben/hooks';
  6. import { preferences } from '@vben/preferences';
  7. import {
  8. authenticateResponseInterceptor,
  9. errorMessageResponseInterceptor,
  10. RequestClient,
  11. } from '@vben/request';
  12. import { useAccessStore } from '@vben/stores';
  13. import { message } from 'ant-design-vue';
  14. import { useAuthStore } from '#/store';
  15. import { refreshTokenApi } from './core';
  16. const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD);
  17. function createRequestClient(baseURL: string) {
  18. const client = new RequestClient({
  19. baseURL,
  20. });
  21. /**
  22. * 重新认证逻辑
  23. */
  24. async function doReAuthenticate() {
  25. console.warn('Access token or refresh token is invalid or expired. ');
  26. const accessStore = useAccessStore();
  27. const authStore = useAuthStore();
  28. accessStore.setAccessToken(null);
  29. if (
  30. preferences.app.loginExpiredMode === 'modal' &&
  31. accessStore.isAccessChecked
  32. ) {
  33. accessStore.setLoginExpired(true);
  34. } else {
  35. await authStore.logout();
  36. }
  37. }
  38. /**
  39. * 刷新token逻辑
  40. */
  41. async function doRefreshToken() {
  42. const accessStore = useAccessStore();
  43. const resp = await refreshTokenApi();
  44. const newToken = resp.data;
  45. accessStore.setAccessToken(newToken);
  46. return newToken;
  47. }
  48. function formatToken(token: null | string) {
  49. return token ? `Bearer ${token}` : null;
  50. }
  51. // 请求头处理
  52. client.addRequestInterceptor({
  53. fulfilled: async (config) => {
  54. const accessStore = useAccessStore();
  55. config.headers.Authorization = formatToken(accessStore.accessToken);
  56. config.headers['Accept-Language'] = preferences.app.locale;
  57. return config;
  58. },
  59. });
  60. // response数据解构
  61. client.addResponseInterceptor<HttpResponse>({
  62. fulfilled: (response) => {
  63. const { data: responseData, status } = response;
  64. const { code, data, message: msg } = responseData;
  65. if (status >= 200 && status < 400 && code === 0) {
  66. return data;
  67. }
  68. throw new Error(`Error ${status}: ${msg}`);
  69. },
  70. });
  71. // token过期的处理
  72. client.addResponseInterceptor(
  73. authenticateResponseInterceptor({
  74. client,
  75. doReAuthenticate,
  76. doRefreshToken,
  77. enableRefreshToken: preferences.app.enableRefreshToken,
  78. formatToken,
  79. }),
  80. );
  81. // 通用的错误处理,如果没有进入上面的错误处理逻辑,就会进入这里
  82. client.addResponseInterceptor(
  83. errorMessageResponseInterceptor((msg: string, _error) => {
  84. // 这里可以根据业务进行定制,你可以拿到 error 内的信息进行定制化处理,根据不同的 code 做不同的提示,而不是直接使用 message.error 提示 msg
  85. message.error(msg);
  86. }),
  87. );
  88. return client;
  89. }
  90. export const requestClient = createRequestClient(apiURL);
  91. export const baseRequestClient = new RequestClient({ baseURL: apiURL });