203 lines
6.8 KiB
JavaScript
203 lines
6.8 KiB
JavaScript
/**
|
|
* 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');
|
|
|
|
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'); // 注册模式默认显示图形验证码防止刷短信
|
|
} 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'); // 重置模式默认显示
|
|
} else { // Login
|
|
title.innerText = "欢迎回来";
|
|
sub.innerText = "请登录以开启 AI 创作之旅";
|
|
submitBtnSpan.innerText = "立即登录";
|
|
switchBtn.innerText = "没有账号?立即注册";
|
|
forgotBtn.classList.remove('hidden');
|
|
smsGroup.classList.add('hidden');
|
|
captchaGroup.classList.add('hidden'); // 登录默认隐藏,除非高频失败
|
|
}
|
|
};
|
|
|
|
const refreshCaptcha = () => {
|
|
const phone = getEl('authPhone')?.value;
|
|
const captchaImg = getEl('captchaImg');
|
|
if (!phone || !captchaImg) 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;
|
|
} 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();
|
|
});
|
|
});
|
|
|
|
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;
|
|
}
|
|
};
|
|
});
|