ny
昨天 282fbc6488f4e8ceb5fda759f963ee88fbf7b999
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/**
 * 该文件可自行根据业务逻辑进行调整
 */
import type { AxiosResponse, CreateAxiosOptions, CreateInternalAxiosRequestConfig, RequestInterceptorConfig, RequestOptions } from '@vben/request';
 
import { AesEncryption, isObject } from '@jnpf/utils';
 
import { useAppConfig } from '@vben/hooks';
import { $t } from '@vben/locales';
import { preferences } from '@vben/preferences';
import { errorMessageResponseInterceptor, RequestClient, ResultEnum } from '@vben/request';
import { useAccessStore } from '@vben/stores';
 
import { message } from 'ant-design-vue';
 
import { useAuthStore } from '#/store';
import { getRealJnpfAppEnCode } from '#/utils/jnpf';
 
const aesEncryption = new AesEncryption();
const { apiURL, reportApiURL } = useAppConfig(import.meta.env, import.meta.env.PROD);
 
// 请求之前处理config
function beforeRequestHook(): RequestInterceptorConfig {
  return {
    fulfilled(config) {
      // 数据加密
      if (config?.requestOptions?.useCipher && config.data) {
        const resultStr = aesEncryption.encryptByAES(JSON.stringify(config.data));
        if (resultStr) config.data = { encryptData: resultStr };
      }
      return config;
    },
  };
}
// 数据处理,方便区分多种处理方式
function transformResponseHook() {
  return {
    fulfilled(res: AxiosResponse<any>) {
      const options = (res.config as CreateInternalAxiosRequestConfig)?.requestOptions;
      // 数据解密
      if ((options as RequestOptions).useCipher) {
        const resultStr = aesEncryption.decryptByAES(res.data);
        if (resultStr) res.data = JSON.parse(resultStr);
      }
      const { isTransformResponse, isReturnNativeResponse } = options as RequestOptions;
      // 是否返回原生响应头 比如:需要获取响应头时使用该属性
      if (isReturnNativeResponse) {
        return res;
      }
      // 不进行任何处理,直接返回
      // 用于页面代码可能需要直接获取code,data,msg这些信息时开启
      if (!isTransformResponse) {
        return res.data;
      }
      if (!res.data) {
        throw new Error($t('fallback.http.internalServerError'));
      }
      //  这里 code,data,msg为 后台统一的字段,需要在 types.ts内修改为项目自己的接口返回格式
      const { code, msg } = res.data;
 
      // 这里逻辑可以根据项目进行修改
      const hasSuccess = res.data && isObject(res.data) && Reflect.has(res.data, 'code') && code === ResultEnum.SUCCESS;
      if (hasSuccess) {
        return res.data;
      }
      // 在此处根据自己项目的实际情况对不同的code执行不同的操作
      // 如果不希望中断当前请求,请return数据,否则直接抛出异常即可
      let errorMsg = '';
      switch (code) {
        case ResultEnum.FORBIDDEN: {
          errorMsg = msg || $t('fallback.http.forbidden');
          if (getRealJnpfAppEnCode() && res.config.url?.includes('oauth/CurrentUser')) {
            const authStore = useAuthStore();
            authStore.goForbidden();
          }
          break;
        }
        case ResultEnum.TOKEN_ERROR:
        case ResultEnum.TOKEN_LOGGED:
        case ResultEnum.TOKEN_TIMEOUT: {
          errorMsg = msg || $t('fallback.http.internalServerError');
          const accessStore = useAccessStore();
          const authStore = useAuthStore();
          accessStore.setAccessToken(null);
          authStore.logout();
          break;
        }
        default: {
          errorMsg = msg || $t('fallback.http.internalServerError');
        }
      }
      if ((options as RequestOptions).errorMessageMode === 'message') {
        message.error(errorMsg);
      }
      throw new Error(errorMsg);
    },
  };
}
 
function createRequestClient(opt?: Partial<CreateAxiosOptions>) {
  const client = new RequestClient(opt || {});
 
  // 请求头处理
  client.addRequestInterceptor({
    fulfilled: async (config) => {
      const accessStore = useAccessStore();
 
      config.headers.Authorization = accessStore.accessToken;
      config.headers['App-Code'] = getRealJnpfAppEnCode();
      config.headers['Accept-Language'] = preferences.app.locale;
      config.headers['Jnpf-Origin'] = 'pc';
      config.headers['Vue-Version'] = '3';
      return config;
    },
  });
 
  client.addRequestInterceptor(beforeRequestHook());
 
  // response数据解构
  client.addResponseInterceptor({
    fulfilled: (response) => {
      const { status } = response;
 
      if (status >= 200 && status < 400) {
        return response;
      }
      throw Object.assign({}, response, { response });
    },
  });
 
  // 通用的错误处理,如果没有进入上面的错误处理逻辑,就会进入这里
  client.addResponseInterceptor(
    errorMessageResponseInterceptor((msg: string, error) => {
      // 这里可以根据业务进行定制,你可以拿到 error 内的信息进行定制化处理,根据不同的 code 做不同的提示,而不是直接使用 message.error 提示 msg
      // 当前mock接口返回的错误字段是 error 或者 message
      const responseData = error?.response?.data ?? {};
      const errorMessage = responseData?.error ?? responseData?.msg ?? '';
      // 如果没有错误信息,则会根据状态码进行提示
      message.error(errorMessage || msg);
    }),
  );
 
  client.addResponseInterceptor(transformResponseHook());
 
  return client;
}
 
export const defHttp = createRequestClient({ requestOptions: { apiUrl: apiURL } });
 
// 报表接口
export const reportHttp = createRequestClient({ requestOptions: { apiUrl: reportApiURL } });