init: UserBaseFront (frontend)
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
import { createAlova, Method, StatesHook } from "alova";
|
||||
import fetchAdapter from "alova/fetch";
|
||||
import VueHook from "alova/vue";
|
||||
import { replaceOriginUrl } from "../bschSsoRedirect";
|
||||
import config from "@/assets/config/host.config";
|
||||
import Utils from "..";
|
||||
/* ============= 类型定义 ============= */
|
||||
export interface RequestHooks {
|
||||
/** 前置票据/通用头注入 */
|
||||
injectHeaders?: (method: Method) => void;
|
||||
/** 加载开始 */
|
||||
onLoadingStart?: () => void;
|
||||
/** 加载结束 */
|
||||
onLoadingEnd?: () => void;
|
||||
/** 业务错误提示(code !== 0)*/
|
||||
onBizError?: (msg: string) => void;
|
||||
/** http 错误提示(status !== 200)*/
|
||||
onHttpError?: (msg: string) => void;
|
||||
}
|
||||
|
||||
/** 和后端约定的通用响应格式 */
|
||||
export interface BschResponse<T = any> {
|
||||
code: number;
|
||||
msg?: string;
|
||||
data: T;
|
||||
urlToRedirectTo?: string;
|
||||
}
|
||||
|
||||
/* ============= 默认空实现 ============= */
|
||||
const defHooks: Required<RequestHooks> = {
|
||||
injectHeaders: () => {},
|
||||
onLoadingStart: () => {},
|
||||
onLoadingEnd: () => {},
|
||||
onBizError: () => {},
|
||||
onHttpError: () => {},
|
||||
};
|
||||
|
||||
/* ============= 错误处理(原 axios 逻辑平移) ============= */
|
||||
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!;
|
||||
// window.location.href = replaceOriginUrl(res.urlToRedirectTo!, config.serviceHost);
|
||||
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();
|
||||
}
|
||||
});
|
||||
// 1. 用户注入票据/角色等头
|
||||
injectHeaders(method);
|
||||
|
||||
method.config.credentials = "include";
|
||||
// 2. 通用头
|
||||
method.config.headers = Object.assign(method.config.headers || {}, {
|
||||
yschapirequest: "1",
|
||||
timeout: 20000,
|
||||
yschreferer: Utils.strToHexCharCode(window.location.href),
|
||||
});
|
||||
}
|
||||
|
||||
/* ---- 响应拦截 ---- */
|
||||
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