优化后台界面与无操作退出体验
This commit is contained in:
@@ -5,8 +5,7 @@ import { getToken } from "../utils/auth";
|
||||
import type { ApiError } from "../types/api";
|
||||
import { useStudyStore } from "../store/study";
|
||||
import { TEXT } from "../locales";
|
||||
import { extendAccessToken, forceLogout, lockSession, markNetworkActive } from "../session/sessionManager";
|
||||
import { useSessionStore } from "../store/session";
|
||||
import { extendAccessToken, forceLogout, LOGOUT_REASON_AUTH_EXPIRED } from "../session/sessionManager";
|
||||
|
||||
const instance: AxiosInstance = axios.create({
|
||||
baseURL: "/",
|
||||
@@ -14,59 +13,29 @@ const instance: AxiosInstance = axios.create({
|
||||
});
|
||||
|
||||
export type ApiRequestConfig = AxiosRequestConfig & {
|
||||
ignoreIdle?: boolean;
|
||||
allowWhileLocked?: boolean;
|
||||
suppressErrorMessage?: boolean;
|
||||
_retry?: boolean;
|
||||
};
|
||||
|
||||
class LockedError extends Error {
|
||||
constructor() {
|
||||
super("LOCKED");
|
||||
this.name = "LockedError";
|
||||
}
|
||||
}
|
||||
|
||||
instance.interceptors.request.use((config: InternalAxiosRequestConfig & ApiRequestConfig) => {
|
||||
const session = useSessionStore();
|
||||
const reqUrl = config.url || "";
|
||||
const allowWhileLocked =
|
||||
config.allowWhileLocked ||
|
||||
reqUrl.includes("/api/v1/auth/login") ||
|
||||
reqUrl.includes("/api/v1/auth/register") ||
|
||||
reqUrl.includes("/api/v1/auth/unlock");
|
||||
if (session.locked && !allowWhileLocked) {
|
||||
return Promise.reject(new LockedError());
|
||||
}
|
||||
const token = getToken();
|
||||
if (token) {
|
||||
config.headers = config.headers || {};
|
||||
(config.headers as Record<string, string>).Authorization = `Bearer ${token}`;
|
||||
}
|
||||
if (!config.ignoreIdle) {
|
||||
markNetworkActive();
|
||||
}
|
||||
return config;
|
||||
});
|
||||
|
||||
instance.interceptors.response.use(
|
||||
(response: AxiosResponse) => response,
|
||||
async (error: AxiosError<ApiError>) => {
|
||||
if (error instanceof LockedError) {
|
||||
const lockedConfig = error.config as ApiRequestConfig | undefined;
|
||||
if (!lockedConfig?.suppressErrorMessage) {
|
||||
ElMessage.warning(TEXT.common.messages.sessionLocked || "请解锁后继续操作");
|
||||
}
|
||||
return Promise.reject(error);
|
||||
}
|
||||
const status = error.response?.status;
|
||||
const data = error.response?.data;
|
||||
const reqUrl = error.config?.url || "";
|
||||
const isAuthEndpoint =
|
||||
reqUrl.includes("/api/v1/auth/login") ||
|
||||
reqUrl.includes("/api/v1/auth/register") ||
|
||||
reqUrl.includes("/api/v1/auth/extend") ||
|
||||
reqUrl.includes("/api/v1/auth/unlock");
|
||||
reqUrl.includes("/api/v1/auth/extend");
|
||||
if (isAuthEndpoint) {
|
||||
// 认证相关的错误由具体页面自行处理,避免重复提示
|
||||
return Promise.reject(error);
|
||||
@@ -92,11 +61,11 @@ instance.interceptors.response.use(
|
||||
return instance(config);
|
||||
}
|
||||
if (result.authFailed) {
|
||||
lockSession("token_invalid");
|
||||
forceLogout(LOGOUT_REASON_AUTH_EXPIRED);
|
||||
}
|
||||
}
|
||||
} else if (status === 403 && (data as any)?.detail === "账号已停用") {
|
||||
forceLogout();
|
||||
forceLogout(LOGOUT_REASON_AUTH_EXPIRED);
|
||||
} else {
|
||||
const suppressErrorMessage = (error.config as ApiRequestConfig | undefined)?.suppressErrorMessage;
|
||||
if (!suppressErrorMessage) {
|
||||
|
||||
Reference in New Issue
Block a user