/** * Auth Modes: * 0 - Login * 1 - Register * 2 - Reset Password */ let authMode = 0; const getEl = (id) => document.getElementById(id); const updateUI = () => { const title = getEl('authTitle'); const sub = getEl('authSub'); const submitBtnSpan = getEl('authSubmitBtn')?.querySelector('span'); const switchBtn = getEl('authSwitchBtn'); const forgotBtn = getEl('forgotPwdBtn'); const smsGroup = getEl('smsGroup'); const captchaGroup = getEl('captchaGroup'); const inviteGroup = getEl('inviteGroup'); if (!title || !sub || !submitBtnSpan || !switchBtn || !forgotBtn || !smsGroup || !captchaGroup) return; if (authMode === 1) { // Register title.innerText = "加入视界 AI"; sub.innerText = "注册并开启创作"; submitBtnSpan.innerText = "立即注册"; switchBtn.innerText = "已有账号?返回登录"; forgotBtn.classList.add('hidden'); smsGroup.classList.remove('hidden'); captchaGroup.classList.remove('hidden'); // 注册模式默认显示图形验证码防止刷短信 if (inviteGroup) inviteGroup.classList.remove('hidden'); } else if (authMode === 2) { // Reset Password title.innerText = "重置密码"; sub.innerText = "验证短信以设置新密码"; submitBtnSpan.innerText = "确认重置"; switchBtn.innerText = "我想起来了,返回登录"; forgotBtn.classList.add('hidden'); smsGroup.classList.remove('hidden'); captchaGroup.classList.remove('hidden'); // 重置模式默认显示 if (inviteGroup) inviteGroup.classList.add('hidden'); } else { // Login title.innerText = "欢迎回来"; sub.innerText = "请登录以开启 AI 创作之旅"; submitBtnSpan.innerText = "立即登录"; switchBtn.innerText = "没有账号?立即注册"; forgotBtn.classList.remove('hidden'); smsGroup.classList.add('hidden'); captchaGroup.classList.add('hidden'); // 登录默认隐藏,除非高频失败 if (inviteGroup) inviteGroup.classList.add('hidden'); } }; const refreshCaptcha = () => { const phone = getEl('authPhone')?.value; const captchaImg = getEl('captchaImg'); if (!captchaImg) return; if (!phone) { // 如果没有手机号,不加载,或者显示占位(此处保持空,等待用户输入) return; } // 简单的手机号长度检查,避免无效请求 if (phone.length < 11) return; captchaImg.src = `/api/auth/captcha?phone=${phone}&t=${Date.now()}`; }; const handleAuth = async () => { const phone = getEl('authPhone')?.value; const password = getEl('authPass')?.value; if (!phone || !password) { return showToast('请输入手机号和密码', 'warning'); } let url = ''; let body = { phone, password }; if (authMode === 1) { url = '/api/auth/register'; body.code = getEl('authCode')?.value; body.invite_code = getEl('authInvite')?.value; // 获取邀请码 } else if (authMode === 0) { url = '/api/auth/login'; if (!getEl('captchaGroup')?.classList.contains('hidden')) { body.code = getEl('authCaptcha')?.value; } } else if (authMode === 2) { url = '/api/auth/reset_password'; body.code = getEl('authCode')?.value; if (!body.code) return showToast('请输入短信验证码', 'warning'); } try { const btn = getEl('authSubmitBtn'); if (btn) btn.disabled = true; const r = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) }); const d = await r.json(); if (r.status === 403 && d.require_captcha) { showToast(d.error, 'warning'); getEl('captchaGroup')?.classList.remove('hidden'); refreshCaptcha(); if (btn) btn.disabled = false; return; } if (d.error) { showToast(d.error, 'error'); if (getEl('captchaGroup') && !getEl('captchaGroup').classList.contains('hidden')) { refreshCaptcha(); } if (btn) btn.disabled = false; } else { showToast(d.message, 'success'); if (authMode === 1 || authMode === 2) { authMode = 0; updateUI(); if (btn) btn.disabled = false; } else { const urlParams = new URLSearchParams(window.location.search); const nextUrl = urlParams.get('next') || '/'; window.location.href = nextUrl; } } } catch (e) { showToast('网络连接失败', 'error'); const btn = getEl('authSubmitBtn'); if (btn) btn.disabled = false; } }; // 初始化 document.addEventListener('DOMContentLoaded', () => { updateUI(); getEl('authSwitchBtn').onclick = () => { authMode = (authMode === 0) ? 1 : 0; updateUI(); if (authMode === 1 || authMode === 2) refreshCaptcha(); }; getEl('forgotPwdBtn').onclick = () => { authMode = 2; updateUI(); refreshCaptcha(); }; getEl('captchaImg').onclick = refreshCaptcha; getEl('authSubmitBtn').onclick = handleAuth; // 回车登录支持 ['authPhone', 'authPass', 'authCode', 'authCaptcha'].forEach(id => { getEl(id)?.addEventListener('keydown', (e) => { if (e.key === 'Enter') handleAuth(); }); }); // 监听手机号输入,自动刷新验证码 const phoneInput = getEl('authPhone'); if (phoneInput) { phoneInput.addEventListener('blur', refreshCaptcha); phoneInput.addEventListener('input', (e) => { if (e.target.value.length === 11) refreshCaptcha(); }); } getEl('sendSmsBtn').onclick = async () => { const phone = getEl('authPhone')?.value; const captcha = getEl('authCaptcha')?.value; const btn = getEl('sendSmsBtn'); if (!phone) return showToast('请输入手机号', 'warning'); if (!captcha) { getEl('captchaGroup')?.classList.remove('hidden'); refreshCaptcha(); return showToast('请先输入图形验证码以发送短信', 'warning'); } btn.disabled = true; const originalText = btn.innerText; try { const r = await fetch('/api/auth/send_code', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ phone, captcha }) }); const d = await r.json(); if (d.error) { showToast(d.error, 'error'); btn.disabled = false; if (d.show_captcha || d.refresh_captcha) { getEl('captchaGroup')?.classList.remove('hidden'); refreshCaptcha(); } } else { showToast(d.message, 'success'); // 发送成功后也要刷新图形验证码,防止被再次利用 refreshCaptcha(); let countdown = 60; const timer = setInterval(() => { btn.innerText = `${countdown}秒后重试`; countdown--; if (countdown < 0) { clearInterval(timer); btn.innerText = originalText; btn.disabled = false; } }, 1000); } } catch (e) { showToast('短信发送失败', 'error'); btn.disabled = false; } }; // 处理邀请链接逻辑 const urlParams = new URLSearchParams(window.location.search); const inviteCode = urlParams.get('invite_code'); if (inviteCode) { authMode = 1; // 切换到注册模式 updateUI(); refreshCaptcha(); // 注册需验证码 const inviteInput = getEl('authInvite'); if (inviteInput) { inviteInput.value = inviteCode; inviteInput.disabled = true; // 锁定邀请码 inviteInput.classList.add('bg-indigo-50', 'text-indigo-600', 'font-bold'); showToast('已自动填入邀请码', 'success'); } } });