refactor: login modal with tabs, username only on register

This commit is contained in:
2026-07-27 10:03:13 +08:00
parent 08e5729de3
commit c59c7a172c
+51 -30
View File
@@ -241,22 +241,23 @@ const PageMarket = {
_showLogin() {
const overlay = document.createElement('div');
overlay.className = 'modal-overlay';
overlay.innerHTML = `<div class="modal" style="min-width:360px;max-width:400px">
<h3>市场账户</h3>
const isLogin = !this._marketToken;
overlay.innerHTML = `<div class="modal" style="min-width:380px;max-width:420px;padding:24px">
<div style="display:flex;gap:0;margin-bottom:18px;border-bottom:1px solid var(--border-subtle)">
<button id="ml-tab-login" class="btn btn-sm ${isLogin?'':'btn-secondary'}" style="border-radius:0;border-bottom:2px solid ${isLogin?'var(--accent)':'transparent'};color:${isLogin?'var(--accent)':'var(--text-secondary)'};background:transparent;padding:8px 16px">登录</button>
<button id="ml-tab-register" class="btn btn-sm ${!isLogin?'':'btn-secondary'}" style="border-radius:0;border-bottom:2px solid ${!isLogin?'var(--accent)':'transparent'};color:${!isLogin?'var(--accent)':'var(--text-secondary)'};background:transparent;padding:8px 16px">注册</button>
</div>
<div class="form-group"><label>邮箱</label><input id="ml-email" type="email" placeholder="your@email.com"></div>
<div class="form-group"><label>用户名</label><input id="ml-name" type="text" placeholder="可选"></div>
<div class="form-group" id="ml-name-group" style="display:${!isLogin?'':'none'}"><label>用户名</label><input id="ml-name" type="text" placeholder="可选"></div>
<div class="form-group"><label>密码</label><input id="ml-pass" type="password"></div>
<div class="modal-actions">
<button class="btn btn-secondary btn-sm" id="ml-logout" style="display:none;margin-right:auto">退出</button>
<button class="btn btn-secondary btn-sm" id="ml-register">注册</button>
<button class="btn btn-primary btn-sm" id="ml-login">登录</button>
<button class="btn btn-sm" id="ml-logout" style="display:${this._marketToken?'':'none'};margin-right:auto;background:var(--bg2);color:var(--text2)">退出</button>
<span style="flex:1"></span>
<button class="btn btn-primary btn-sm" id="ml-submit">${isLogin?'登录':'注册'}</button>
</div></div>`;
document.body.appendChild(overlay);
if (this._marketToken) {
overlay.querySelector('#ml-login').style.display = 'none';
overlay.querySelector('#ml-register').style.display = 'none';
overlay.querySelector('#ml-logout').style.display = '';
overlay.querySelector('#ml-logout').addEventListener('click', () => {
this._marketToken = null;
localStorage.removeItem('turbosu-market-token');
@@ -266,31 +267,51 @@ const PageMarket = {
});
}
let mode = isLogin ? 'login' : 'register';
const tabLogin = overlay.querySelector('#ml-tab-login');
const tabRegister = overlay.querySelector('#ml-tab-register');
const nameGroup = overlay.querySelector('#ml-name-group');
const submitBtn = overlay.querySelector('#ml-submit');
function setTab(t) {
mode = t;
const isL = t === 'login';
tabLogin.style.cssText = `border-radius:0;border-bottom:2px solid ${isL?'var(--accent)':'transparent'};color:${isL?'var(--accent)':'var(--text-secondary)'};background:transparent;padding:8px 16px`;
tabRegister.style.cssText = `border-radius:0;border-bottom:2px solid ${!isL?'var(--accent)':'transparent'};color:${!isL?'var(--accent)':'var(--text-secondary)'};background:transparent;padding:8px 16px`;
nameGroup.style.display = isL ? 'none' : '';
submitBtn.textContent = isL ? '登录' : '注册';
}
tabLogin.addEventListener('click', () => setTab('login'));
tabRegister.addEventListener('click', () => setTab('register'));
overlay.addEventListener('click', (e) => { if (e.target === overlay) overlay.remove(); });
overlay.querySelector('#ml-login')?.addEventListener('click', async () => {
const doAuth = async () => {
const email = document.getElementById('ml-email').value;
const pass = document.getElementById('ml-pass').value;
if (!email || !pass) { Toast.show('请输入邮箱和密码', 'error'); return; }
const res = await fetch('/api/market/auth', { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify({email, password: pass}) });
const data = await res.json();
if (data.token) {
this._marketToken = data.token;
localStorage.setItem('turbosu-market-token', data.token);
Toast.show('登录成功', 'success');
overlay.remove();
this._updateUI();
} else { Toast.show(data.message || '登录失败', 'error'); }
});
overlay.querySelector('#ml-register')?.addEventListener('click', async () => {
const email = document.getElementById('ml-email').value;
const pass = document.getElementById('ml-pass').value;
const name = document.getElementById('ml-name')?.value || '';
if (!email || !pass) { Toast.show('请输入邮箱和密码', 'error'); return; }
const res = await fetch('/api/market/register', { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify({email, password: pass, passwordConfirm: pass, name}) });
const data = await res.json();
Toast.show(data.error ? '注册失败' : '注册成功,请查收验证邮件(点击关闭)', data.error ? 'error' : 'success', data.error ? 3000 : 0);
if (!data.error) overlay.remove();
});
if (mode === 'login') {
const res = await fetch('/api/market/auth', { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify({email, password: pass}) });
const data = await res.json();
if (data.token) {
this._marketToken = data.token;
localStorage.setItem('turbosu-market-token', data.token);
Toast.show('登录成功', 'success');
overlay.remove();
this._updateUI();
} else { Toast.show(data.message || '登录失败', 'error'); }
} else {
const name = document.getElementById('ml-name')?.value || '';
const res = await fetch('/api/market/register', { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify({email, password: pass, passwordConfirm: pass, name}) });
const data = await res.json();
Toast.show(data.error ? '注册失败: ' + data.error : '注册成功,请查收验证邮件(点击关闭)', data.error ? 'error' : 'success', data.error ? 3000 : 0);
if (!data.error) overlay.remove();
}
};
overlay.querySelector('#ml-submit').addEventListener('click', doAuth);
overlay.querySelector('#ml-pass').addEventListener('keydown', (e) => { if (e.key === 'Enter') doAuth(); });
},
_emptyHtml(msg) {