/**
|
* 该文件可自行根据业务逻辑进行调整
|
*/
|
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 } });
|