mirror of
https://gitee.com/ccnetcore/Yi
synced 2026-03-03 00:00:58 +08:00
feat(api): 兼容多种后端API响应风格
- 在环境变量中新增VITE_GLOB_API_STYLE配置项以支持auto、furion和abp三种响应风格 - 在全局类型定义中添加apiStyle字段,支持对应响应风格类型约束 - request.ts中实现Furion风格响应判断和自动切换ABP风格处理逻辑 - 增加ABP风格错误处理,包含401/403自动登出及验证错误提示 - ABP风格下支持HTTP 200直接成功返回数据和不同成功提示模式 - use-app-config.ts中添加apiStyle配置读取及默认值逻辑 - 注释掉YiAbpWebModule中Furion统一响应API的启用代码,改为默认使用ABP风格
This commit is contained in:
@@ -6,3 +6,6 @@ VITE_APP_NAMESPACE=vben-web-antd
|
|||||||
|
|
||||||
# 对store进行加密的密钥,在将store持久化到localStorage时会使用该密钥进行加密
|
# 对store进行加密的密钥,在将store持久化到localStorage时会使用该密钥进行加密
|
||||||
VITE_APP_STORE_SECURE_KEY=please-replace-me-with-your-own-key
|
VITE_APP_STORE_SECURE_KEY=please-replace-me-with-your-own-key
|
||||||
|
|
||||||
|
# API响应风格: auto(自动检测) | furion | abp
|
||||||
|
VITE_GLOB_API_STYLE=auto
|
||||||
|
|||||||
@@ -27,11 +27,29 @@ import {
|
|||||||
} from '#/utils/encryption/crypto';
|
} from '#/utils/encryption/crypto';
|
||||||
import * as encryptUtil from '#/utils/encryption/jsencrypt';
|
import * as encryptUtil from '#/utils/encryption/jsencrypt';
|
||||||
|
|
||||||
const { apiURL, clientId, enableEncrypt, demoMode } = useAppConfig(
|
const { apiURL, clientId, enableEncrypt, demoMode, apiStyle } = useAppConfig(
|
||||||
import.meta.env,
|
import.meta.env,
|
||||||
import.meta.env.PROD,
|
import.meta.env.PROD,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/** 判断是否为 Furion 风格响应 */
|
||||||
|
function isFurionResponse(data: any): boolean {
|
||||||
|
return (
|
||||||
|
data != null &&
|
||||||
|
typeof data === 'object' &&
|
||||||
|
'statusCode' in data &&
|
||||||
|
'succeeded' in data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 判断当前响应是否应按 ABP 风格处理 */
|
||||||
|
function shouldUseAbpStyle(data: any): boolean {
|
||||||
|
if (apiStyle === 'abp') return true;
|
||||||
|
if (apiStyle === 'furion') return false;
|
||||||
|
// auto: 不是 Furion 结构就按 ABP 处理
|
||||||
|
return !isFurionResponse(data);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否已经处在登出过程中了 一个标志位
|
* 是否已经处在登出过程中了 一个标志位
|
||||||
* 主要是防止一个页面会请求多个api 都401 会导致登出执行多次
|
* 主要是防止一个页面会请求多个api 都401 会导致登出执行多次
|
||||||
@@ -180,6 +198,47 @@ function createRequestClient(baseURL: string) {
|
|||||||
if (error?.__isDemoModeError || error?.name === 'DemoModeException') {
|
if (error?.__isDemoModeError || error?.name === 'DemoModeException') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const status = error?.response?.status;
|
||||||
|
const responseData = error?.response?.data;
|
||||||
|
const abpError = responseData?.error;
|
||||||
|
|
||||||
|
// 判断是否为 ABP 风格错误
|
||||||
|
const isAbp =
|
||||||
|
apiStyle === 'abp' ||
|
||||||
|
(apiStyle === 'auto' &&
|
||||||
|
abpError &&
|
||||||
|
typeof abpError.message === 'string');
|
||||||
|
|
||||||
|
if (isAbp) {
|
||||||
|
// ABP 401/403 需要触发登出
|
||||||
|
if ((status === 401 || status === 403) && !isLogoutProcessing) {
|
||||||
|
isLogoutProcessing = true;
|
||||||
|
const _msg = abpError?.message || msg;
|
||||||
|
const userStore = useAuthStore();
|
||||||
|
userStore.logout().finally(() => {
|
||||||
|
message.error(_msg);
|
||||||
|
isLogoutProcessing = false;
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ABP 其他错误:提取 error.message,拼接 validationErrors
|
||||||
|
let errorMsg = abpError?.message || msg;
|
||||||
|
if (abpError?.validationErrors?.length) {
|
||||||
|
const details = abpError.validationErrors
|
||||||
|
.map((e: any) => e.message)
|
||||||
|
.filter(Boolean)
|
||||||
|
.join('; ');
|
||||||
|
if (details) {
|
||||||
|
errorMsg = `${errorMsg}: ${details}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
message.error(errorMsg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Furion 风格 / 非 ABP:保持原有行为
|
||||||
message.error(msg);
|
message.error(msg);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -234,6 +293,20 @@ function createRequestClient(baseURL: string) {
|
|||||||
throw new Error($t('http.apiRequestFailed'));
|
throw new Error($t('http.apiRequestFailed'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ABP 风格:HTTP 200 即成功,直接返回数据
|
||||||
|
if (shouldUseAbpStyle(axiosResponseData)) {
|
||||||
|
if (response.config.successMessageMode === 'modal') {
|
||||||
|
Modal.success({
|
||||||
|
content: $t('http.operationSuccess'),
|
||||||
|
title: $t('http.successTip'),
|
||||||
|
});
|
||||||
|
} else if (response.config.successMessageMode === 'message') {
|
||||||
|
message.success($t('http.operationSuccess'));
|
||||||
|
}
|
||||||
|
return axiosResponseData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Furion 风格响应处理
|
||||||
console.log('axiosResponseData', axiosResponseData);
|
console.log('axiosResponseData', axiosResponseData);
|
||||||
// 适配后端数据结构: { statusCode, data, succeeded, errors, extras, timestamp }
|
// 适配后端数据结构: { statusCode, data, succeeded, errors, extras, timestamp }
|
||||||
const { statusCode, data, succeeded, errors, extras, timestamp } =
|
const { statusCode, data, succeeded, errors, extras, timestamp } =
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ export function useAppConfig(
|
|||||||
VITE_GLOB_RSA_PUBLIC_KEY,
|
VITE_GLOB_RSA_PUBLIC_KEY,
|
||||||
VITE_GLOB_SSE_ENABLE,
|
VITE_GLOB_SSE_ENABLE,
|
||||||
VITE_GLOB_DEMO_MODE,
|
VITE_GLOB_DEMO_MODE,
|
||||||
|
VITE_GLOB_API_STYLE,
|
||||||
} = config;
|
} = config;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -39,5 +40,9 @@ export function useAppConfig(
|
|||||||
sseEnable: VITE_GLOB_SSE_ENABLE === 'false',
|
sseEnable: VITE_GLOB_SSE_ENABLE === 'false',
|
||||||
// 是否开启演示模式
|
// 是否开启演示模式
|
||||||
demoMode: VITE_GLOB_DEMO_MODE === 'true',
|
demoMode: VITE_GLOB_DEMO_MODE === 'true',
|
||||||
|
// API响应风格
|
||||||
|
apiStyle: (['abp', 'furion'].includes(VITE_GLOB_API_STYLE)
|
||||||
|
? VITE_GLOB_API_STYLE
|
||||||
|
: 'auto') as 'abp' | 'auto' | 'furion',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
4
Yi.Vben5.Vue3/packages/types/global.d.ts
vendored
4
Yi.Vben5.Vue3/packages/types/global.d.ts
vendored
@@ -22,6 +22,8 @@ export interface VbenAdminProAppConfigRaw {
|
|||||||
VITE_GLOB_SSE_ENABLE: string;
|
VITE_GLOB_SSE_ENABLE: string;
|
||||||
// 是否开启演示模式(只读模式,禁止修改操作) 注意从配置文件获取的类型为string
|
// 是否开启演示模式(只读模式,禁止修改操作) 注意从配置文件获取的类型为string
|
||||||
VITE_GLOB_DEMO_MODE: string;
|
VITE_GLOB_DEMO_MODE: string;
|
||||||
|
// API响应风格: auto(自动检测) | furion | abp
|
||||||
|
VITE_GLOB_API_STYLE: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ApplicationConfig {
|
export interface ApplicationConfig {
|
||||||
@@ -39,6 +41,8 @@ export interface ApplicationConfig {
|
|||||||
sseEnable: boolean;
|
sseEnable: boolean;
|
||||||
// 是否开启演示模式(只读模式,禁止修改操作)
|
// 是否开启演示模式(只读模式,禁止修改操作)
|
||||||
demoMode: boolean;
|
demoMode: boolean;
|
||||||
|
// API响应风格
|
||||||
|
apiStyle: 'abp' | 'auto' | 'furion';
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
|||||||
Reference in New Issue
Block a user