diff --git a/static/public/js/login.js b/static/public/js/login.js index 83f2689..ad117d7 100644 --- a/static/public/js/login.js +++ b/static/public/js/login.js @@ -8,15 +8,14 @@ const usernameInput = document.getElementById('loginUsername'); const passwordInput = document.getElementById('loginPassword'); const emailInput = document.getElementById('loginEmail'); const agreeBox = document.getElementById('agreeBox'); -const protocol = document.getElementById('agreement'); -const submit = document.getElementById('loginBtn'); - -const resetUser = document.getElementById('resetUser'); -const registerBtn = document.getElementById('registerBtn'); +const protocol = document.getElementById('agreement'); +const resetUser = document.getElementById('resetUser'); +const registerBtn = document.getElementById('registerBtn'); +const loginButton = document.getElementById('loginBtn'); resetUser.addEventListener('click', function() { clearTipStyle(); -}) +}); function clearTipStyle() { msgTip.innerHTML = ''; @@ -36,68 +35,37 @@ clearTipStyle(); /** * @returns {string|false} */ -function checkUsername() { - const val = usernameInput.value.trim(); - msgTip.innerHTML = ''; - msgTip.classList.remove('tip-red', 'tip-yellow', 'tip-green'); - - if (!val) { - msgTip.innerHTML = '用户名不可为空'; - msgTip.classList.add('tip-red'); - return false; - } - if (val.length > 20) { - msgTip.innerHTML = '用户名不得长于20字符!'; - msgTip.classList.add('tip-yellow'); - return false; - } - - msgTip.innerHTML = '√ 用户名格式正确'; - msgTip.classList.add('tip-green'); - return val; +function checkUsername() { + const result = FormValidators.username(usernameInput.value); + msgTip.innerHTML = ''; + msgTip.classList.remove('tip-red', 'tip-yellow', 'tip-green'); + msgTip.textContent = result.message; + msgTip.classList.add(result.className); + return result.valid ? result.value : false; } /** * @returns {string|false} */ -function checkPwd() { - const val = passwordInput.value.trim(); - pwdTip.innerHTML = ''; - pwdTip.classList.remove('tip-red', 'tip-yellow', 'tip-green'); - - if (!val) { - pwdTip.innerHTML = '密码不可为空!'; - pwdTip.classList.add('tip-red'); - return false; - } - - pwdTip.innerHTML = '河狸'; - pwdTip.classList.add('tip-green'); - return val; +function checkPwd() { + const result = FormValidators.password(passwordInput.value); + pwdTip.innerHTML = ''; + pwdTip.classList.remove('tip-red', 'tip-yellow', 'tip-green'); + pwdTip.textContent = result.message; + pwdTip.classList.add(result.className); + return result.valid ? result.value : false; } /** * @returns {string|false} */ -function checkEml() { - const val = emailInput.value.trim(); - const emlStand = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/; - emlTip.innerHTML = ''; - emlTip.classList.remove('tip-red', 'tip-yellow', 'tip-green'); - - if (!val) { - emlTip.innerHTML = '邮箱不可为空!'; - emlTip.classList.add('tip-red'); - return false; - } else if (!emlStand.test(val)) { - emlTip.innerHTML = '邮箱格式不正确!'; - emlTip.classList.add('tip-yellow'); - return false; - } - - emlTip.innerHTML = '河狸'; - emlTip.classList.add('tip-green'); - return val; +function checkEml() { + const result = FormValidators.email(emailInput.value); + emlTip.innerHTML = ''; + emlTip.classList.remove('tip-red', 'tip-yellow', 'tip-green'); + emlTip.textContent = result.message; + emlTip.classList.add(result.className); + return result.valid ? result.value : false; } /** @@ -134,21 +102,7 @@ agreeBox.addEventListener('change', checkAgree); registerBtn.addEventListener('click', function() { location.href = 'register.html'; -}) - -/** - * @param {string} - * @returns {string} - */ -function htmlEscape(str) { - if (typeof str !== 'string') return str; - return str - .replace(/&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, '''); -} +}); form.addEventListener('submit', async function(e) { e.preventDefault(); @@ -169,6 +123,7 @@ form.addEventListener('submit', async function(e) { }); try { + loginButton.disabled = true; const res = await fetch('/login', { method: 'POST', headers: { @@ -182,8 +137,9 @@ form.addEventListener('submit', async function(e) { try { result = JSON.parse(responseText); - } catch (err) { - throw new Error(`服务器返回了非 JSON 内容(HTTP ${res.status}):${responseText.slice(0, 100)}`); + } catch { + console.error(`登录接口返回非 JSON 内容(HTTP ${res.status}):`, responseText); + throw new Error('服务器响应格式异常,请稍后重试'); } if (!res.ok) { @@ -191,6 +147,9 @@ form.addEventListener('submit', async function(e) { } if (result.code === 0) { + if (!result.data || !result.data.token || !result.data.username) { + throw new Error('登录成功,但服务器返回的数据不完整'); + } alert(`${result.message},账号:${result.data.username}`); sessionStorage.setItem('token', result.data.token); location.href = 'main.html'; @@ -200,5 +159,7 @@ form.addEventListener('submit', async function(e) { } catch (err) { alert(err.message || '接口请求失败,请检查后端服务是否启动'); console.error('登录请求异常:', err); - } + } finally { + loginButton.disabled = false; + } }); diff --git a/static/public/js/register.js b/static/public/js/register.js index 2dd7789..f5f5bd0 100644 --- a/static/public/js/register.js +++ b/static/public/js/register.js @@ -1,73 +1,205 @@ -let sendCode = ""; -let codeTarget = ""; +const form = document.getElementById('form'); +const usernameInput = document.getElementById('regusername'); +const emailInput = document.getElementById('regemail'); +const codeInput = document.getElementById('code'); +const getCodeButton = document.getElementById('getCode'); +const passwordInput = document.getElementById('regpsw'); +const repeatPasswordInput = document.getElementById('repwd'); +const msgTip = document.getElementById('msgTip'); +const emlTip = document.getElementById('emlTip'); +const pwdTip = document.getElementById('pwdTip'); +const codeTip = document.getElementById('codeTip'); +const submitButton = document.getElementById('formsub'); -getCode.onclick = function () { - const phoneMail = email.value.trim(); +let sendCode = ''; +let codeTarget = ''; - if (phoneMail === "") { - alert("请先填写邮箱号!"); +form.addEventListener('reset', function () { + clearTipStyle(); + sendCode = ''; + codeTarget = ''; +}); + +function clearTipStyle() { + msgTip.innerHTML = ''; + emlTip.innerHTML = ''; + pwdTip.innerHTML = ''; + codeTip.innerHTML = ''; + + msgTip.classList.remove('tip-red', 'tip-yellow', 'tip-green'); + emlTip.classList.remove('tip-red', 'tip-yellow', 'tip-green'); + pwdTip.classList.remove('tip-red', 'tip-yellow', 'tip-green'); + codeTip.classList.remove('tip-red', 'tip-yellow', 'tip-green'); +} +clearTipStyle(); + +function checkUsername() { + const result = FormValidators.username(usernameInput.value); + msgTip.innerHTML = ''; + msgTip.classList.remove('tip-red', 'tip-yellow', 'tip-green'); + msgTip.textContent = result.message; + msgTip.classList.add(result.className); + return result.valid ? result.value : false; +} + +function checkEmail() { + const result = FormValidators.email(emailInput.value); + emlTip.innerHTML = ''; + emlTip.classList.remove('tip-red', 'tip-yellow', 'tip-green'); + emlTip.textContent = result.message; + emlTip.classList.add(result.className); + return result.valid ? result.value : false; +} + +function checkPassword() { + const result = FormValidators.password(passwordInput.value, 6); + pwdTip.innerHTML = ''; + pwdTip.classList.remove('tip-red', 'tip-yellow', 'tip-green'); + + if (!result.valid) { + pwdTip.textContent = result.message; + pwdTip.classList.add(result.className); + return false; + } + if (result.value !== repeatPasswordInput.value) { + pwdTip.textContent = '两次输入的密码不一致!'; + pwdTip.classList.add('tip-yellow'); + return false; + } + + pwdTip.textContent = result.message; + pwdTip.classList.add(result.className); + return result.value; +} + +function checkCode() { + const code = codeInput.value.trim(); + codeTip.innerHTML = ''; + codeTip.classList.remove('tip-red', 'tip-yellow', 'tip-green'); + + if (!sendCode) { + codeTip.textContent = '请先获取验证码!'; + codeTip.classList.add('tip-red'); + return false; + } + if (emailInput.value.trim() !== codeTarget) { + codeTip.textContent = '邮箱已修改,请重新获取验证码!'; + codeTip.classList.add('tip-red'); + return false; + } + if (!/^\d{6}$/.test(code)) { + codeTip.textContent = '验证码必须是6位数字!'; + codeTip.classList.add('tip-yellow'); + return false; + } + if (code !== sendCode) { + codeTip.textContent = '验证码错误,请核对!'; + codeTip.classList.add('tip-red'); + return false; + } + + codeTip.textContent = '验证码正确'; + codeTip.classList.add('tip-green'); + return code; +} + +usernameInput.addEventListener('focus', checkUsername); +passwordInput.addEventListener('focus', checkPassword); +repeatPasswordInput.addEventListener('focus', checkPassword); + +usernameInput.addEventListener('input', checkUsername); +passwordInput.addEventListener('input', checkPassword); +repeatPasswordInput.addEventListener('input', checkPassword); + +usernameInput.addEventListener('blur', checkUsername); +passwordInput.addEventListener('blur', checkPassword); +repeatPasswordInput.addEventListener('blur', checkPassword); + +emailInput.addEventListener('focus', checkEmail); +emailInput.addEventListener('input', function () { + checkEmail(); + if (sendCode) { + checkCode(); + } +}); +emailInput.addEventListener('blur', checkEmail); + +codeInput.addEventListener('focus', checkCode); +codeInput.addEventListener('input', checkCode); +codeInput.addEventListener('blur', checkCode); + +getCodeButton.addEventListener('click', function () { + const email = checkEmail(); + if (!email) { return; } sendCode = Math.floor(100000 + Math.random() * 900000).toString(); - codeTarget = phoneMail; + codeTarget = email; + codeInput.value = ''; + codeTip.textContent = '验证码已发送,请填写验证码'; + codeTip.classList.remove('tip-red', 'tip-yellow', 'tip-green'); + codeTip.classList.add('tip-green'); + alert(`验证码已发送至${email},您的验证码:${sendCode}`); +}); - alert(`验证码已发送至 ${phoneMail},您的验证码:${sendCode}`); -}; - -regForm.onsubmit = function (e) { +form.addEventListener('submit', async function (e) { e.preventDefault(); - const uname = username.value.trim(); - const emailVal = email.value.trim(); - const codeVal = code.value.trim(); - const pwdVal = psw.value; - const repwdVal = repwd.value; + const username = checkUsername(); + const email = checkEmail(); + const password = checkPassword(); + const code = checkCode(); - if (uname === "") { - alert("请填写用户名"); + if (!username || !email || !password || !code) { return; } + const jsonBody = JSON.stringify({ + username, + password + }); - if (emailVal === "") { - alert("请填写邮箱号"); - return; + try { + submitButton.disabled = true; + const res = await fetch('/register', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + body: jsonBody + }); + + const responseText = await res.text(); + let result; + + try { + result = JSON.parse(responseText); + } catch { + console.error(`注册接口返回非 JSON 内容(HTTP ${res.status}):`, responseText); + throw new Error('服务器响应格式异常,请稍后重试'); + } + + if (!res.ok) { + throw new Error(result.message || `注册失败(HTTP ${res.status})`); + } + + if (result.code === 0) { + if (!result.data || !result.data.username) { + throw new Error('注册成功,但服务器返回的数据不完整'); + } + alert(`${result.message},账号:${result.data.username}`); + form.reset(); + sendCode = ''; + codeTarget = ''; + location.href = 'login.html'; + return; + } + + alert(result.message || '注册失败'); + } catch (err) { + console.error('注册请求异常:', err); + alert(err.message || '接口请求失败,请检查后端服务是否启动'); + } finally { + submitButton.disabled = false; } - - if (sendCode === "") { - alert("请先点击获取验证码!"); - return; - } - - if (emailVal !== codeTarget) { - alert("邮箱已修改,请重新获取验证码!"); - sendCode = ""; - return; - } - - if (!/^\d{6}$/.test(codeVal)) { - alert("验证码必须是6位数字"); - return; - } - - if (codeVal !== sendCode) { - alert("验证码错误,请核对!"); - code.value = ""; - return; - } - - if (pwdVal.length < 6) { - alert("密码至少6位字符"); - return; - } - - if (pwdVal !== repwdVal) { - alert("两次输入的密码不一致"); - return; - } - - alert("注册成功!"); - regForm.reset(); - sendCode = ""; - codeTarget = ""; -}; \ No newline at end of file +}); diff --git a/static/public/js/validation.js b/static/public/js/validation.js new file mode 100644 index 0000000..0922808 --- /dev/null +++ b/static/public/js/validation.js @@ -0,0 +1,62 @@ +(function () { + function username(value) { + const normalizedValue = value.trim(); + + if (!normalizedValue) { + return { valid: false, message: '用户名不可为空', className: 'tip-red' }; + } + if (normalizedValue.length > 20) { + return { valid: false, message: '用户名不得长于20字符!', className: 'tip-yellow' }; + } + + return { + valid: true, + value: normalizedValue, + message: '用户名格式正确', + className: 'tip-green' + }; + } + + function password(value, minLength) { + const requiredLength = minLength || 1; + + if (!value) { + return { valid: false, message: '密码不可为空!', className: 'tip-red' }; + } + if (value.length < requiredLength) { + return { + valid: false, + message: `密码至少${requiredLength}位字符!`, + className: 'tip-red' + }; + } + + return { + valid: true, + value, + message: '密码格式正确', + className: 'tip-green' + }; + } + + function email(value) { + const normalizedValue = value.trim(); + const emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/; + + if (!normalizedValue) { + return { valid: false, message: '邮箱不可为空!', className: 'tip-red' }; + } + if (!emailPattern.test(normalizedValue)) { + return { valid: false, message: '邮箱格式不正确!', className: 'tip-yellow' }; + } + + return { + valid: true, + value: normalizedValue, + message: '邮箱格式正确', + className: 'tip-green' + }; + } + + window.FormValidators = { username, password, email }; +}()); diff --git a/static/public/register.html b/static/public/register.html index 469b530..9213fce 100644 --- a/static/public/register.html +++ b/static/public/register.html @@ -3,21 +3,43 @@
-