diff --git a/docker-compose.yml b/docker-compose.yml index 64c31c3..8f3bd42 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -85,7 +85,6 @@ services: # 挂载前端与服务端源码为只读,确保容器运行当前工作区代码(避免旧镜像残留) - ./server/src:/app/server/src:ro - ./index.html:/app/index.html:ro - - ./login.html:/app/login.html:ro - ./admin:/app/admin:ro - ./views:/app/views:ro - ./js:/app/js:ro diff --git a/index.html b/index.html index c9868c2..2fe5837 100644 --- a/index.html +++ b/index.html @@ -1440,42 +1440,6 @@ - - - diff --git a/js/boot/backend-gate.js b/js/boot/backend-gate.js deleted file mode 100644 index ed62990..0000000 --- a/js/boot/backend-gate.js +++ /dev/null @@ -1,133 +0,0 @@ -// backend-gate.js — 在“后端模式”未登录时,拦截并跳转到登录页 -// 适用范围:主站/落地页/其他静态页面(不影响 /admin 管理台) - -(function () { - try { - var loc = window.location; - var path = loc.pathname || ''; - - // 纯本地文件访问(file://)时,强制视为前端模式:不做任何后端探测或跳转 - if (loc.protocol === 'file:') return; - - // 排除管理台与登录页自身 - if (path.startsWith('/admin') || path.endsWith('/login.html')) return; - - function q(key) { - try { return new URLSearchParams(loc.search).get(key); } catch { return null; } - } - - function normalizeRedirectParam(urlObj) { - try { - var red = urlObj.searchParams.get('redirect'); - if (!red) return; - function deepDecode(s, limit) { - var i = 0, prev = s; - while (i++ < (limit || 8)) { - try { - var next = decodeURIComponent(prev); - if (next === prev) break; - prev = next; - } catch { break; } - } - return prev; - } - var decoded = deepDecode(red, 8); - // 连续嵌套或超长,直接归一为首页 - if (red.length > 512 || decoded.length > 512 || decoded.indexOf('/login.html?redirect=') !== -1) { - urlObj.searchParams.set('redirect', '/'); - return; - } - var target = null; - try { target = new URL(decoded, urlObj.origin); } catch {} - if (!target || target.origin !== urlObj.origin || target.pathname.endsWith('/login.html')) { - urlObj.searchParams.set('redirect', '/'); - } - } catch {} - } - - function modeForced() { - var m = (q('mode') || '').toLowerCase(); - if (m === 'backend') return true; - var env = (window.ENV_DEPLOYMENT_MODE || '').toLowerCase(); - return env === 'backend'; - } - - function modeFrontendForced() { - var m = (q('mode') || '').toLowerCase(); - return m === 'frontend'; - } - - function hasToken() { - try { return !!localStorage.getItem('auth_token'); } catch { return false; } - } - - function buildSafeRedirectTarget() { - try { - var u = new URL(window.location.href); - // 避免递归嵌套:去除已有的 redirect 参数 - u.searchParams.delete('redirect'); - // 若当前已是登录页,则回首页 - if (u.pathname.endsWith('/login.html')) { - u.pathname = '/'; - u.search = ''; - } - // 限制同源 - if (u.origin !== window.location.origin) return '/'; - return u.toString(); - } catch { return '/'; } - } - - function redirectToLogin() { - // 如果当前 URL 已包含 redirect 指向 login.html(异常嵌套),则强制回首页 - try { - var current = new URL(window.location.href); - normalizeRedirectParam(current); - // 将标准化后的当前 URL 写回,避免下次读取到异常 redirect - history.replaceState(null, '', current.toString()); - } catch {} - var safe = encodeURIComponent(buildSafeRedirectTarget()); - window.location.replace('/login.html?redirect=' + safe); - } - - function gateIfBackendKnown() { - // 若明确为后端模式,且未登录且未显式前端绕过 → 跳转登录 - if (modeFrontendForced()) return; // 允许 ?mode=frontend 绕过 - if (hasToken()) return; - redirectToLogin(); - } - - async function healthCheck(timeoutMs) { - try { - var ctrl = new AbortController(); - var id = setTimeout(function(){ try{ctrl.abort();}catch{} }, timeoutMs); - var base = window.ENV_API_BASE_URL || '/api'; - var res = await fetch(base + '/health', { signal: ctrl.signal, cache: 'no-store' }); - clearTimeout(id); - return !!(res && res.ok); - } catch { return false; } - } - - // 情况 1:已强制后端 → 立即门禁 - if (modeForced()) { - gateIfBackendKnown(); - return; - } - - // 情况 2:依赖 storage-adapter 的自动切换事件(若其已加载) - if (typeof window !== 'undefined') { - window.addEventListener('pb:storage-mode-changed', function (evt) { - if (evt && evt.detail && evt.detail.mode === 'backend') gateIfBackendKnown(); - }); - } - - // 情况 3:页面未加载 storage-adapter(例如落地页)→ 自行做一次短健康检查 - // 仅当未显式前端绕过时执行 - if (!modeFrontendForced()) { - healthCheck(700).then(function (hasBackend) { - if (hasBackend) gateIfBackendKnown(); - }); - } - } catch (e) { - // 忽略所有门禁过程中的异常,避免影响前端模式体验 - } -})(); diff --git a/js/storage/storage-adapter.js b/js/storage/storage-adapter.js index df59fae..2a9b0a0 100644 --- a/js/storage/storage-adapter.js +++ b/js/storage/storage-adapter.js @@ -82,9 +82,8 @@ class BackendStorage { if (!response.ok) { if (response.status === 401) { - // Token 过期,需要重新登录 + // Token 过期,清除token AuthManager.removeToken(); - window.location.href = '/login.html'; } throw new Error(`API Error: ${response.status}`); } diff --git a/login.html b/login.html deleted file mode 100644 index 94fae9f..0000000 --- a/login.html +++ /dev/null @@ -1,132 +0,0 @@ - - -
- - -默认管理员:admin@paperburner.local / admin123456
管理员入口:/admin
-