fix: 修复旧版前端登录跳转
This commit is contained in:
@@ -1,5 +1,12 @@
|
|||||||
# 项目上下文记录
|
# 项目上下文记录
|
||||||
|
|
||||||
|
## 2026-05-15:修复旧版前端未登录闪烁
|
||||||
|
|
||||||
|
- `frontend_old/js/app.js` 现在会在首页初始化前检查登录 token;未登录时直接跳到旧版登录页,避免首页继续初始化并反复请求 API 造成未授权提示闪烁。
|
||||||
|
- 旧版前端鉴权统一兼容 `capacity_report_token` 和旧 key `token`:请求优先读取新版 key,登录页会同时写入两个 key,并继续写入 `token` cookie。
|
||||||
|
- 旧版 API 401、XHR 上传 401 和退出登录都会清理两个本地 token key 及 cookie,并跳转到 `/login.html`;通过 `/old/...` 路径访问旧版时会跳转到 `/old/login.html`。
|
||||||
|
- 已用 headless Chrome 验证:清空本地存储后访问 `http://127.0.0.1:9082/` 会进入 `http://127.0.0.1:9082/login.html`;按本机 `auth.ini` 登录后回到旧版首页,`/api/cache/size` 携带 token 调用返回 200。
|
||||||
|
|
||||||
## 2026-05-15:新版上传页对齐旧版布局并恢复拖拽上传
|
## 2026-05-15:新版上传页对齐旧版布局并恢复拖拽上传
|
||||||
|
|
||||||
- `frontend/src/components/FileWorkflow.vue` 的上传页内容区已按旧版 `frontend_old/index.html` 的上传结构重排,保留新版侧边导航和顶部标题栏,只对齐页面主体中的上传区、文件列表、上传进度和处理日志布局。
|
- `frontend/src/components/FileWorkflow.vue` 的上传页内容区已按旧版 `frontend_old/index.html` 的上传结构重排,保留新版侧边导航和顶部标题栏,只对齐页面主体中的上传区、文件列表、上传进度和处理日志布局。
|
||||||
|
|||||||
+43
-10
@@ -5,6 +5,38 @@
|
|||||||
|
|
||||||
// ==================== 工具函数 ====================
|
// ==================== 工具函数 ====================
|
||||||
|
|
||||||
|
const LEGACY_TOKEN_KEY = 'token';
|
||||||
|
const APP_TOKEN_KEY = 'capacity_report_token';
|
||||||
|
|
||||||
|
function getLegacyLoginPath() {
|
||||||
|
const path = window.location.pathname;
|
||||||
|
return path === '/old' || path.startsWith('/old/') ? '/old/login.html' : '/login.html';
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAuthToken() {
|
||||||
|
return localStorage.getItem(APP_TOKEN_KEY) || localStorage.getItem(LEGACY_TOKEN_KEY) || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearAuthToken() {
|
||||||
|
localStorage.removeItem(APP_TOKEN_KEY);
|
||||||
|
localStorage.removeItem(LEGACY_TOKEN_KEY);
|
||||||
|
document.cookie = 'token=; path=/; max-age=0';
|
||||||
|
}
|
||||||
|
|
||||||
|
function redirectToLogin() {
|
||||||
|
const loginPath = getLegacyLoginPath();
|
||||||
|
if (window.location.pathname !== loginPath) {
|
||||||
|
window.location.replace(loginPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function requireAuthToken() {
|
||||||
|
if (getAuthToken()) return true;
|
||||||
|
clearAuthToken();
|
||||||
|
redirectToLogin();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
function $(selector) {
|
function $(selector) {
|
||||||
return document.querySelector(selector);
|
return document.querySelector(selector);
|
||||||
}
|
}
|
||||||
@@ -114,7 +146,7 @@ async function api(endpoint, options = {}) {
|
|||||||
// 如果没有指定 method 且没有 body,默认使用 GET
|
// 如果没有指定 method 且没有 body,默认使用 GET
|
||||||
const method = options.method || (options.body ? 'POST' : 'GET');
|
const method = options.method || (options.body ? 'POST' : 'GET');
|
||||||
|
|
||||||
const token = localStorage.getItem('token');
|
const token = getAuthToken();
|
||||||
|
|
||||||
const fetchOptions = {
|
const fetchOptions = {
|
||||||
method: method,
|
method: method,
|
||||||
@@ -134,7 +166,7 @@ async function api(endpoint, options = {}) {
|
|||||||
const response = await fetch(`/api${endpoint}`, fetchOptions);
|
const response = await fetch(`/api${endpoint}`, fetchOptions);
|
||||||
|
|
||||||
if (response.status === 401 && endpoint !== '/login') {
|
if (response.status === 401 && endpoint !== '/login') {
|
||||||
localStorage.removeItem('token');
|
clearAuthToken();
|
||||||
showLoginModal();
|
showLoginModal();
|
||||||
throw new Error('未授权或登录已过期,请重新登录');
|
throw new Error('未授权或登录已过期,请重新登录');
|
||||||
}
|
}
|
||||||
@@ -148,15 +180,13 @@ async function api(endpoint, options = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function showLoginModal() {
|
function showLoginModal() {
|
||||||
localStorage.removeItem('token');
|
clearAuthToken();
|
||||||
document.cookie = 'token=; path=/; max-age=0';
|
redirectToLogin();
|
||||||
window.location.href = '/';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function logout() {
|
function logout() {
|
||||||
localStorage.removeItem('token');
|
clearAuthToken();
|
||||||
document.cookie = 'token=; path=/; max-age=0';
|
window.location.href = getLegacyLoginPath();
|
||||||
window.location.href = '/';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -651,7 +681,7 @@ class FileUploader {
|
|||||||
resolve({ success: true });
|
resolve({ success: true });
|
||||||
}
|
}
|
||||||
} else if (xhr.status === 401) {
|
} else if (xhr.status === 401) {
|
||||||
localStorage.removeItem('token');
|
clearAuthToken();
|
||||||
showLoginModal();
|
showLoginModal();
|
||||||
reject(new Error('未授权或登录已过期,请重新登录'));
|
reject(new Error('未授权或登录已过期,请重新登录'));
|
||||||
} else {
|
} else {
|
||||||
@@ -666,7 +696,7 @@ class FileUploader {
|
|||||||
|
|
||||||
// 开始上传
|
// 开始上传
|
||||||
xhr.open('POST', '/api/upload');
|
xhr.open('POST', '/api/upload');
|
||||||
const token = localStorage.getItem('token');
|
const token = getAuthToken();
|
||||||
if (token) {
|
if (token) {
|
||||||
xhr.setRequestHeader('Authorization', `Bearer ${token}`);
|
xhr.setRequestHeader('Authorization', `Bearer ${token}`);
|
||||||
}
|
}
|
||||||
@@ -2208,6 +2238,9 @@ async function updateCacheSize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
if (!requireAuthToken()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
initApp();
|
initApp();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+17
-4
@@ -161,6 +161,21 @@
|
|||||||
<div class="toast" id="toast"></div>
|
<div class="toast" id="toast"></div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
const LEGACY_TOKEN_KEY = 'token';
|
||||||
|
const APP_TOKEN_KEY = 'capacity_report_token';
|
||||||
|
|
||||||
|
function getLegacyHomePath() {
|
||||||
|
const path = window.location.pathname;
|
||||||
|
return path === '/old/login.html' || path.startsWith('/old/') ? '/old' : '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
function setAuthToken(token) {
|
||||||
|
if (!token) return;
|
||||||
|
localStorage.setItem(APP_TOKEN_KEY, token);
|
||||||
|
localStorage.setItem(LEGACY_TOKEN_KEY, token);
|
||||||
|
document.cookie = `token=${encodeURIComponent(token)}; path=/; max-age=${86400 * 30}; SameSite=Lax`;
|
||||||
|
}
|
||||||
|
|
||||||
function showToast(msg, type) {
|
function showToast(msg, type) {
|
||||||
const t = document.getElementById('toast');
|
const t = document.getElementById('toast');
|
||||||
t.textContent = msg;
|
t.textContent = msg;
|
||||||
@@ -197,11 +212,9 @@
|
|||||||
|
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
if (data.success && data.token) {
|
if (data.success && data.token) {
|
||||||
localStorage.setItem('token', data.token);
|
setAuthToken(data.token);
|
||||||
// 设置 cookie 供后端 / 路由判断
|
|
||||||
document.cookie = `token=${data.token}; path=/; max-age=${86400 * 30}; SameSite=Lax`;
|
|
||||||
showToast('登录成功', 'success');
|
showToast('登录成功', 'success');
|
||||||
setTimeout(() => { window.location.href = '/'; }, 300);
|
setTimeout(() => { window.location.href = getLegacyHomePath(); }, 300);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showToast(err.message, 'error');
|
showToast(err.message, 'error');
|
||||||
|
|||||||
Reference in New Issue
Block a user