88c6ce8ccc
- 迁移为 frontend-web、frontend-electron、backend-web 与 docker 部署结构 - 网页端:订阅门禁二次弹窗、套餐/支付组件化、顶栏分组对齐 - 首页:最近文件与模板库布局优化,缩略图对齐,下载与删除操作 - 新增管理后台、支付与云端文件 API,更新 README 与项目规范 Co-authored-by: Cursor <cursoragent@cursor.com>
117 lines
3.2 KiB
JavaScript
117 lines
3.2 KiB
JavaScript
(function () {
|
|
'use strict';
|
|
|
|
var TOKEN_KEY = 'soon_access';
|
|
|
|
function getV1Base() {
|
|
var cfg = window.SOON_DEPLOY_CONFIG || {};
|
|
return (cfg.api_v1_base || '/api/v1').replace(/\/+$/, '');
|
|
}
|
|
|
|
function redirectTarget() {
|
|
var p = new URLSearchParams(location.search);
|
|
var r = p.get('redirect');
|
|
if (r && typeof soonSafeRedirect === 'function') {
|
|
return soonSafeRedirect(r, 'index.html');
|
|
}
|
|
return r || 'index.html';
|
|
}
|
|
|
|
function clearTokens() {
|
|
try {
|
|
localStorage.removeItem(TOKEN_KEY);
|
|
localStorage.removeItem('soon_refresh');
|
|
} catch (e) { /* ignore */ }
|
|
}
|
|
|
|
function showError(msg) {
|
|
var err = document.getElementById('loginError');
|
|
if (err) {
|
|
err.textContent = msg;
|
|
err.style.display = 'block';
|
|
}
|
|
}
|
|
|
|
async function verifyAdmin(token) {
|
|
var r = await fetch(getV1Base() + '/auth/me', {
|
|
headers: { Authorization: 'Bearer ' + token },
|
|
});
|
|
var j = await r.json();
|
|
if (!j.ok || !j.data || j.data.role !== 'admin') return null;
|
|
return j.data;
|
|
}
|
|
|
|
function init() {
|
|
if (localStorage.getItem(TOKEN_KEY)) {
|
|
verifyAdmin(localStorage.getItem(TOKEN_KEY)).then(function (me) {
|
|
if (me) location.href = redirectTarget();
|
|
});
|
|
}
|
|
|
|
var pwdToggle = document.getElementById('pwdToggle');
|
|
if (pwdToggle) {
|
|
pwdToggle.onclick = function () {
|
|
var p = document.getElementById('password');
|
|
var show = p.type === 'password';
|
|
p.type = show ? 'text' : 'password';
|
|
this.textContent = show ? '隐藏' : '显示';
|
|
};
|
|
}
|
|
|
|
var form = document.getElementById('loginForm');
|
|
if (!form) return;
|
|
|
|
form.onsubmit = function (e) {
|
|
e.preventDefault();
|
|
var err = document.getElementById('loginError');
|
|
if (err) { err.style.display = 'none'; err.textContent = ''; }
|
|
|
|
var email = document.getElementById('email').value.trim();
|
|
var password = document.getElementById('password').value;
|
|
|
|
fetch(getV1Base() + '/auth/login', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ email: email, password: password }),
|
|
}).then(function (r) { return r.json(); }).then(function (j) {
|
|
if (!j.ok) {
|
|
showError(j.message || '登录失败');
|
|
return;
|
|
}
|
|
localStorage.setItem(TOKEN_KEY, j.data.access_token);
|
|
localStorage.setItem('soon_refresh', j.data.refresh_token);
|
|
return verifyAdmin(j.data.access_token);
|
|
}).then(function (me) {
|
|
if (me === undefined) return;
|
|
if (!me) {
|
|
clearTokens();
|
|
showError('无管理员权限,请使用管理员账号登录');
|
|
soonToast('无管理员权限', 'warn');
|
|
return;
|
|
}
|
|
location.href = redirectTarget();
|
|
}).catch(function () {
|
|
showError('网络错误,请稍后重试');
|
|
});
|
|
};
|
|
}
|
|
|
|
function boot() {
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', init);
|
|
} else {
|
|
init();
|
|
}
|
|
}
|
|
|
|
if (typeof layui !== 'undefined') {
|
|
layui.use(['layer'], function () {
|
|
window.layer = layui.layer;
|
|
layer.config({ skin: 'soon-layer' });
|
|
boot();
|
|
});
|
|
} else {
|
|
boot();
|
|
}
|
|
})();
|