fix: 修复登录失败提示错误

This commit is contained in:
2026-05-20 11:30:37 +08:00
parent 90023663fd
commit 3995358095
3 changed files with 36 additions and 5 deletions
+7
View File
@@ -1,4 +1,11 @@
# 项目上下文记录
## 2026-05-20:修复登录失败误提示会话过期
- `frontend/src/api/client.ts` 不再把 `/api/login` 的 401 响应当作全局会话过期处理,登录失败会按后端真实错误显示“账号或密码错误”。
- 已登录业务接口遇到 401 时仍会清理本地 token 并切回登录页,但 `AppShell` 不再额外弹出全局“登录已过期”提示,避免组件自身错误提示和全局提示同时出现。
- 默认登录密码仍由 `app/auth.py` 定义为 `Capacity`,大小写敏感;如本地 `auth.ini` 未修改,输入小写 `capacity` 会按正常登录失败处理。
- 已执行 `npm run build`,构建通过;前端构建仅保留 Vite 大 chunk 提示,生成产物随后清理。
## 2026-05-20:增加按 ZIP 数据日期校验的使用期限限制
- 新增 `app/services/license.py` 和 `/api/license/status`、`/api/license/activate`:本地 `license.dat` 用 XOR+HMAC 方式加密保存到期日期,缺失时自动初始化为 `2026-06-20`,文件已加入 `.gitignore`。
-1
View File
@@ -194,7 +194,6 @@ watch(
setUnauthorizedHandler(() => {
token.value = '';
message.warning('登录已过期');
});
async function handleLogin(payload: { username: string; password: string }) {
+29 -4
View File
@@ -50,16 +50,24 @@ export async function apiPost<T>(url: string, body?: unknown): Promise<T> {
export async function request<T>(url: string, init: RequestInit = {}): Promise<T> {
const headers = new Headers(init.headers);
const token = getToken();
const token = isLoginRequest(url) ? '' : getToken();
if (token) {
headers.set('Authorization', `Bearer ${token}`);
}
const response = await fetch(apiUrl(url), { ...init, headers });
if (response.status === 401) {
if (isLoginRequest(url)) {
const error = await readError(response);
throw new ApiRequestError(error.message, response.status, error.detail);
}
clearToken();
onUnauthorized?.();
throw new Error('登录已过期,请重新登录');
throw new ApiRequestError('登录已过期,请重新登录', response.status, {
code: 'UNAUTHORIZED',
message: '登录已过期,请重新登录'
});
}
if (!response.ok) {
@@ -94,7 +102,12 @@ export function upload<T>(
if (xhr.status === 401) {
clearToken();
onUnauthorized?.();
reject(new Error('登录已过期,请重新登录'));
reject(
new ApiRequestError('登录已过期,请重新登录', xhr.status, {
code: 'UNAUTHORIZED',
message: '登录已过期,请重新登录'
})
);
return;
}
@@ -143,7 +156,10 @@ export async function downloadGet(url: string, fallbackFilename: string): Promis
if (response.status === 401) {
clearToken();
onUnauthorized?.();
throw new Error('登录已过期,请重新登录');
throw new ApiRequestError('登录已过期,请重新登录', response.status, {
code: 'UNAUTHORIZED',
message: '登录已过期,请重新登录'
});
}
if (!response.ok) {
@@ -215,3 +231,12 @@ function apiUrl(url: string): string {
}
return `${API_BASE}${url.startsWith('/') ? url : `/${url}`}`;
}
function isLoginRequest(url: string): boolean {
try {
const parsed = new URL(url, window.location.origin);
return parsed.pathname === '/api/login';
} catch {
return url.replace(/^https?:\/\/[^/]+/i, '').split('?')[0] === '/api/login';
}
}