Files
dqb-dev 65755bf520 会员服务器:上传肥牛应用源码 v1.5.1(fnnas.huiyuan 完整 fpk 工程结构)
含 app/server/server.cjs 服务端、app/www 网页(admin/auth/项目云/库备份/settings)、
app/ui 图标、cmd 安装脚本、config、wizard、manifest、图标与对接文档。
按仓库规则排除构建产物 *.fpk 与 .mimosa 缓存。
2026-10-02 00:03:20 +08:00

93 lines
4.8 KiB
JavaScript
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 会员服务器 · 管理登录门(四页共用)
// · 页面引入本文件后:无有效登录态时全屏遮罩要求输入管理密码,登录成功写入 localStorage 并刷新
// · 同时包装 window.fetch:对同源 /api/ 请求自动附加 X-Admin-Token 头(页面业务代码无需改动)
// · 管理密码未设置时提示先到安装向导/应用设置中设置
(function () {
var TOKEN_KEY = 'hy_admin_token';
function 取token() { try { return localStorage.getItem(TOKEN_KEY) || ''; } catch (e) { return ''; } }
function 存token(t) { try { localStorage.setItem(TOKEN_KEY, t); } catch (e) { } }
// 原生 fetch 引用(遮罩内登录请求用原生,避免递归)
var 原fetch = window.fetch.bind(window);
// 包装 fetch:同源 /api/ 请求自动带 X-Admin-Token
window.fetch = function (input, init) {
try {
var url = typeof input === 'string' ? input : (input && input.url) || '';
if (url.indexOf('/api/') === 0) {
init = init || {};
var h = {};
if (init.headers && typeof init.headers === 'object' && !(init.headers instanceof Headers)) h = init.headers;
h['X-Admin-Token'] = 取token();
init.headers = h;
}
} catch (e) { }
return 原fetch(input, init);
};
window.HY = {
token: 取token,
logout: function () { try { localStorage.removeItem(TOKEN_KEY); } catch (e) { } location.reload(); }
};
// ---- 登录遮罩 ----
var 样式 = document.createElement('style');
样式.textContent =
'#hy-login{position:fixed;inset:0;z-index:9999;display:flex;align-items:center;justify-content:center;background:#f5f6f8}' +
'#hy-login .box{background:#fff;border:1px solid #e3e6eb;border-radius:12px;box-shadow:0 12px 40px rgba(0,0,0,.12);padding:32px 34px;width:340px;max-width:92vw}' +
'#hy-login h3{margin:0 0 6px;font-size:18px;font-family:"Microsoft YaHei UI","Microsoft YaHei",sans-serif}' +
'#hy-login .sub{color:#7c8590;font-size:12px;margin:0 0 16px;font-family:"Microsoft YaHei UI","Microsoft YaHei",sans-serif}' +
'#hy-login input{width:100%;padding:9px 11px;border:1px solid #cfd5dd;border-radius:7px;font-size:14px;box-sizing:border-box}' +
'#hy-login input:focus{outline:none;border-color:#2563eb}' +
'#hy-login button{width:100%;margin-top:12px;padding:9px;border:none;border-radius:7px;background:#2563eb;color:#fff;font-size:14px;cursor:pointer}' +
'#hy-login button:hover{background:#1d54d7}' +
'#hy-login .err{color:#c53030;font-size:12px;min-height:16px;margin-top:10px;font-family:"Microsoft YaHei UI","Microsoft YaHei",sans-serif}';
document.head.appendChild(样式);
function 显示登录(提示语) {
var 旧 = document.getElementById('hy-login');
if (旧) 旧.remove();
var ov = document.createElement('div');
ov.id = 'hy-login';
ov.innerHTML = '<div class="box"><h3>会员服务器</h3><p class="sub">请输入管理密码登录'
+ (提示语 ? '(' + 提示语 + ')' : '') + '</p>'
+ '<input type="password" id="hy-pwd" placeholder="管理密码" autocomplete="current-password">'
+ '<button id="hy-btn">登 录</button><div class="err" id="hy-err"></div></div>';
document.body.appendChild(ov);
var pwd = ov.querySelector('#hy-pwd'), btn = ov.querySelector('#hy-btn'), err = ov.querySelector('#hy-err');
function 登录() {
var v = pwd.value;
if (!v) { err.textContent = '请输入管理密码'; return; }
btn.disabled = true; btn.textContent = '登录中…'; err.textContent = '';
原fetch('/api/admin/login', {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ 密码: v })
}).then(function (r) { return r.json(); }).then(function (j) {
if (j.ok) { 存token(j.token); location.reload(); return; }
err.textContent = j.msg || '登录失败';
btn.disabled = false; btn.textContent = '登 录'; pwd.value = ''; pwd.focus();
}).catch(function (e) {
err.textContent = '请求失败: ' + e;
btn.disabled = false; btn.textContent = '登 录';
});
}
btn.onclick = 登录;
pwd.addEventListener('keydown', function (e) { if (e.key === 'Enter') 登录(); });
setTimeout(function () { pwd.focus(); }, 50);
}
function 校验登录态() {
原fetch('/api/admin/check', { headers: { 'X-Admin-Token': 取token() } })
.then(function (r) { return r.json(); })
.then(function (j) {
if (j.ok) return; // 已登录,页面正常
显示登录(j.adminConfigured ? '' : '首次使用请先在安装向导/应用设置中设置管理密码');
})
.catch(function () { 显示登录('无法连接服务器'); });
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', 校验登录态);
else 校验登录态();
})();