Files
open-gateway-front/src/utils/alova/alova-core.ts
T
chenxing bed87ced52 feat(front): 网关台账前端——台账/路由/目标三页+重载注册表
- 与 notice 同形态:hash 路由 + TablePageAlovaNew 分页 + alova 信封分支
- API 层手写(文档端点仅容器网内可达,api:gen 无通路),键名对齐后端 operationId
- 审计修复:outDir 回 dist 根(CI zip 根须含 html)、main.ts 显式引入 @/api 挂载全局 Apis、
  保存失败重拉回滚、路由页补只读 timeout/bodyLimit 列、详情弹窗 backendCode 恒空说明
2026-09-23 14:28:10 +08:00

146 lines
4.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { createAlova, Method, StatesHook } from "alova";
import fetchAdapter from "alova/fetch";
import VueHook from "alova/vue";
/* ============= 类型定义 ============= */
export interface RequestHooks {
/** 前置票据/通用头注入 */
injectHeaders?: (method: Method) => void;
/** 加载开始 */
onLoadingStart?: () => void;
/** 加载结束 */
onLoadingEnd?: () => void;
/** 业务错误提示(code !== 0)*/
onBizError?: (msg: string) => void;
/** http 错误提示(status !== 200)*/
onHttpError?: (msg: string) => void;
}
/** 平台统一响应信封(yh-api-std 的 ApiResponse 形态) */
export interface BschResponse<T = any> {
code: number;
msg?: string;
data: T;
urlToRedirectTo?: string;
}
/* ============= 默认空实现 ============= */
const defHooks: Required<RequestHooks> = {
injectHeaders: () => {},
onLoadingStart: () => {},
onLoadingEnd: () => {},
onBizError: () => {},
onHttpError: () => {},
};
/* ============= 错误处理(与 UserBase 同形,适配平台信封) ============= */
function errorHandle<T>(res: BschResponse<T>, status: number): T {
// http 层错误
if (status !== 200) {
let msg = "网络错误";
switch (status) {
case 401:
case 403:
break;
case 404:
msg = "请求的资源不存在!";
break;
default:
msg = res?.msg || "内部服务错误!";
}
throw new Error(msg);
}
// 业务层错误
switch (res.code) {
case 0:
return res.data ?? (null as T);
case 302:
console.log(res);
window.location.href = res.urlToRedirectTo!;
throw new Error("redirect");
case 4:
throw new Error(res.msg || "参数错误!");
default:
throw new Error(res.msg || "业务错误");
}
}
/* ============= 工厂函数 ============= */
export function createBschAlova(baseURL: string, hooks: RequestHooks = {}, statesHook: StatesHook<any> = VueHook) {
const { injectHeaders, onLoadingStart, onLoadingEnd, onBizError, onHttpError } = {
...defHooks,
...hooks,
};
let reqCount = 0;
let timer: ReturnType<typeof setTimeout>;
/* ---- 请求拦截 ---- */
function beforeRequest(method: Method) {
reqCount++;
if (reqCount === 1) timer = setTimeout(() => onLoadingStart(), 800);
Promise.resolve().then(() => {
if (reqCount === 0) {
clearTimeout(timer);
onLoadingEnd();
}
});
// 用户注入票据/角色等头
injectHeaders(method);
method.config.credentials = "include";
// 通用头(网关管理面不识别 yschapirequest/yschreferer/currentRole,故不注入)
method.config.headers = Object.assign(method.config.headers || {}, {
timeout: 20000,
});
}
/* ---- 响应拦截 ---- */
async function onSuccess(response: Response) {
reqCount--;
if (reqCount === 0) {
clearTimeout(timer);
onLoadingEnd();
}
const res: BschResponse = await response.json();
try {
return errorHandle(res, response.status);
} catch (e: any) {
console.log(e);
onBizError(e.message);
return Promise.reject(e);
}
}
async function onError(err: any) {
reqCount = 0;
clearTimeout(timer);
onLoadingEnd();
const msg = err?.message || "网络请求出错";
onHttpError(msg);
return Promise.reject(err);
}
async function onComplete(method: Method) {
if (method.fromCache) {
reqCount--;
if (reqCount === 0) {
clearTimeout(timer);
onLoadingEnd();
}
}
}
return createAlova({
statesHook,
requestAdapter: fetchAdapter(),
baseURL,
cacheFor: null,
beforeRequest,
responded: { onSuccess, onError, onComplete },
});
}