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
+38 -17
View File
@@ -241,22 +241,23 @@ const PageMarket = {
_showLogin() { _showLogin() {
const overlay = document.createElement('div'); const overlay = document.createElement('div');
overlay.className = 'modal-overlay'; overlay.className = 'modal-overlay';
overlay.innerHTML = `<div class="modal" style="min-width:360px;max-width:400px"> const isLogin = !this._marketToken;
<h3>市场账户</h3> 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-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="form-group"><label>密码</label><input id="ml-pass" type="password"></div>
<div class="modal-actions"> <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-sm" id="ml-logout" style="display:${this._marketToken?'':'none'};margin-right:auto;background:var(--bg2);color:var(--text2)">退出</button>
<button class="btn btn-secondary btn-sm" id="ml-register">注册</button> <span style="flex:1"></span>
<button class="btn btn-primary btn-sm" id="ml-login">登录</button> <button class="btn btn-primary btn-sm" id="ml-submit">${isLogin?'登录':'注册'}</button>
</div></div>`; </div></div>`;
document.body.appendChild(overlay); document.body.appendChild(overlay);
if (this._marketToken) { 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', () => { overlay.querySelector('#ml-logout').addEventListener('click', () => {
this._marketToken = null; this._marketToken = null;
localStorage.removeItem('turbosu-market-token'); localStorage.removeItem('turbosu-market-token');
@@ -266,11 +267,31 @@ 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.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 email = document.getElementById('ml-email').value;
const pass = document.getElementById('ml-pass').value; const pass = document.getElementById('ml-pass').value;
if (!email || !pass) { Toast.show('请输入邮箱和密码', 'error'); return; } if (!email || !pass) { Toast.show('请输入邮箱和密码', 'error'); return; }
if (mode === 'login') {
const res = await fetch('/api/market/auth', { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify({email, password: pass}) }); 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(); const data = await res.json();
if (data.token) { if (data.token) {
@@ -280,17 +301,17 @@ const PageMarket = {
overlay.remove(); overlay.remove();
this._updateUI(); this._updateUI();
} else { Toast.show(data.message || '登录失败', 'error'); } } else { Toast.show(data.message || '登录失败', 'error'); }
}); } else {
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 || ''; 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 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(); const data = await res.json();
Toast.show(data.error ? '注册失败' : '注册成功,请查收验证邮件(点击关闭)', data.error ? 'error' : 'success', data.error ? 3000 : 0); Toast.show(data.error ? '注册失败: ' + data.error : '注册成功,请查收验证邮件(点击关闭)', data.error ? 'error' : 'success', data.error ? 3000 : 0);
if (!data.error) overlay.remove(); 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) { _emptyHtml(msg) {