修复
This commit is contained in:
@@ -11,7 +11,9 @@ export type HandledRedirectError = {
|
||||
|
||||
export class ApiService {
|
||||
private static initialized = false;
|
||||
|
||||
private static isRefreshing = false;
|
||||
private static refreshWaiters: Array<(success: boolean) => void> = [];
|
||||
|
||||
private static get userStore() {
|
||||
return useUserStore()
|
||||
}
|
||||
@@ -29,13 +31,57 @@ export class ApiService {
|
||||
}
|
||||
|
||||
private static redirectToLogin() {
|
||||
if (typeof localStorage !== "undefined") {
|
||||
localStorage.removeItem("token");
|
||||
localStorage.removeItem("userInfo");
|
||||
this.userStore.offOnline();
|
||||
window.location.href = "/";
|
||||
}
|
||||
|
||||
private static waitForRefresh(): Promise<boolean> {
|
||||
return new Promise(resolve => {
|
||||
this.refreshWaiters.push(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
private static notifyWaiters(success: boolean): void {
|
||||
this.refreshWaiters.forEach(resolve => resolve(success));
|
||||
this.refreshWaiters = [];
|
||||
}
|
||||
|
||||
// 刷新 token,支持并发排队:多个请求同时 401 时只发一次刷新请求
|
||||
private static async doRefreshToken(): Promise<boolean> {
|
||||
if (this.isRefreshing) {
|
||||
return this.waitForRefresh();
|
||||
}
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
PageExtend.Redirect("/home");
|
||||
this.isRefreshing = true;
|
||||
try {
|
||||
const refToken = this.userStore.getRefToken;
|
||||
const token = this.userStore.getToken
|
||||
if (!refToken) {
|
||||
this.notifyWaiters(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
const result = await this.request.post<IResultData<{ token: string; refToken: string; userId: string }>>(
|
||||
"/Login/RefreshToken",
|
||||
{ refToken, token }
|
||||
);
|
||||
if (result.code === 0 && result.data) {
|
||||
this.userStore.setToken(
|
||||
result.data.userId,
|
||||
result.data.token,
|
||||
result.data.refToken ?? this.userStore.refToken
|
||||
);
|
||||
this.notifyWaiters(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
this.notifyWaiters(false);
|
||||
return false;
|
||||
} catch {
|
||||
this.notifyWaiters(false);
|
||||
return false;
|
||||
} finally {
|
||||
this.isRefreshing = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,30 +112,17 @@ export class ApiService {
|
||||
return response;
|
||||
}
|
||||
const result = response.data;
|
||||
if (result.code === 401) {
|
||||
//401刷新token
|
||||
|
||||
console.log(result.data);
|
||||
} else if (result.code === 40101) {
|
||||
this.redirectToLogin();
|
||||
if (result.code === 500) {
|
||||
throw {
|
||||
handled: true,
|
||||
redirectTo: "/",//跳转回首页
|
||||
message: result.msg || "登录已失效"
|
||||
} satisfies HandledRedirectError;
|
||||
} else if (result.code === 500) {
|
||||
// 跳转错误页面
|
||||
throw {
|
||||
handled: true,
|
||||
redirectTo: "/",//跳转回首页
|
||||
message: result.msg || "登录已失效"
|
||||
redirectTo: "/",
|
||||
message: result.msg || "服务器内部错误"
|
||||
} satisfies HandledRedirectError;
|
||||
} else if (result.code === 404) {
|
||||
// 跳转不存在页面
|
||||
throw {
|
||||
handled: true,
|
||||
redirectTo: "/",//跳转回首页
|
||||
message: result.msg || "登录已失效"
|
||||
redirectTo: "/",
|
||||
message: result.msg || "资源不存在"
|
||||
} satisfies HandledRedirectError;
|
||||
}
|
||||
|
||||
@@ -107,26 +140,57 @@ export class ApiService {
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
private static executeRequest<T>(
|
||||
method: HttpMethod,
|
||||
url: string,
|
||||
params: RequestParams
|
||||
): Promise<IResultData<T>> {
|
||||
switch (method) {
|
||||
case "get":
|
||||
return this.request.get<IResultData<T>>(url, { params });
|
||||
case "post":
|
||||
return this.request.post<IResultData<T>>(url, params);
|
||||
case "put":
|
||||
return this.request.put<IResultData<T>>(url, params);
|
||||
case "delete":
|
||||
return this.request.delete<IResultData<T>>(url, { params });
|
||||
case "patch":
|
||||
return this.request.patch<IResultData<T>>(url, params);
|
||||
default:
|
||||
throw new Error(`不支持的请求方法: ${method}`);
|
||||
}
|
||||
}
|
||||
|
||||
private static async requestWithRetry<T>(
|
||||
method: HttpMethod,
|
||||
url: string,
|
||||
params: RequestParams,
|
||||
isRetry: boolean
|
||||
): Promise<IResultData<T>> {
|
||||
const result = await this.executeRequest<T>(method, url, params);
|
||||
|
||||
if (result.code === 401 && !isRetry) {
|
||||
const refreshed = await this.doRefreshToken();
|
||||
if (refreshed) {
|
||||
return this.requestWithRetry<T>(method, url, params, true);
|
||||
}
|
||||
this.redirectToLogin();
|
||||
throw {
|
||||
handled: true,
|
||||
redirectTo: "/",
|
||||
message: "登录已失效,请重新登录"
|
||||
} satisfies HandledRedirectError;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async Request<T = any>(
|
||||
method: HttpMethod,
|
||||
url: string,
|
||||
params: RequestParams = {}
|
||||
): Promise<IResultData<T>> {
|
||||
this.ensureInitialized();
|
||||
|
||||
switch (method) {
|
||||
case "get":
|
||||
return await this.request.get<IResultData<T>>(url, { params });
|
||||
case "post":
|
||||
return await this.request.post<IResultData<T>>(url, params);
|
||||
case "put":
|
||||
return await this.request.put<IResultData<T>>(url, params);
|
||||
case "delete":
|
||||
return await this.request.delete<IResultData<T>>(url, { params });
|
||||
case "patch":
|
||||
return await this.request.patch<IResultData<T>>(url, params);
|
||||
default:
|
||||
throw new Error(`不支持的请求方法: ${method}`);
|
||||
}
|
||||
return this.requestWithRetry<T>(method, url, params, false);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user