feat(front): 网关台账前端——台账/路由/目标三页+重载注册表
- 与 notice 同形态:hash 路由 + TablePageAlovaNew 分页 + alova 信封分支 - API 层手写(文档端点仅容器网内可达,api:gen 无通路),键名对齐后端 operationId - 审计修复:outDir 回 dist 根(CI zip 根须含 html)、main.ts 显式引入 @/api 挂载全局 Apis、 保存失败重拉回滚、路由页补只读 timeout/bodyLimit 列、详情弹窗 backendCode 恒空说明
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
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 },
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user