会员服务器:上传肥牛应用源码 v1.5.1(fnnas.huiyuan 完整 fpk 工程结构)
含 app/server/server.cjs 服务端、app/www 网页(admin/auth/项目云/库备份/settings)、 app/ui 图标、cmd 安装脚本、config、wizard、manifest、图标与对接文档。 按仓库规则排除构建产物 *.fpk 与 .mimosa 缓存。
This commit is contained in:
Executable
+92
@@ -0,0 +1,92 @@
|
||||
// 会员服务器 · 管理登录门(四页共用)
|
||||
// · 页面引入本文件后:无有效登录态时全屏遮罩要求输入管理密码,登录成功写入 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 校验登录态();
|
||||
})();
|
||||
Reference in New Issue
Block a user