feat: 忘记密码增设局部焦点提示及发信成功30秒防刷置灰倒计时锁
This commit is contained in:
@@ -12,6 +12,19 @@ function getCsrfToken() {
|
||||
return document.querySelector('meta[name="csrf-token"]')?.getAttribute("content") ?? "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前应当使用的局部消息框元素。
|
||||
*
|
||||
* @returns {HTMLDivElement|null}
|
||||
*/
|
||||
function getActiveAlertBox() {
|
||||
const stepDetect = document.getElementById("step-detect");
|
||||
if (stepDetect && stepDetect.style.display !== "none") {
|
||||
return document.getElementById("alert-detect");
|
||||
}
|
||||
return document.getElementById("alert-email");
|
||||
}
|
||||
|
||||
/**
|
||||
* 展示找回密码页面提示。
|
||||
*
|
||||
@@ -20,7 +33,7 @@ function getCsrfToken() {
|
||||
* @returns {void}
|
||||
*/
|
||||
function showAlert(message, type) {
|
||||
const alertBox = document.getElementById("alert-box");
|
||||
const alertBox = getActiveAlertBox();
|
||||
if (!alertBox) {
|
||||
return;
|
||||
}
|
||||
@@ -28,6 +41,9 @@ function showAlert(message, type) {
|
||||
alertBox.textContent = message;
|
||||
alertBox.className = type === "success" ? "alert alert-success" : "alert alert-error";
|
||||
alertBox.style.display = "block";
|
||||
|
||||
// 平滑滚动提示框到可视区域
|
||||
alertBox.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,9 +52,13 @@ function showAlert(message, type) {
|
||||
* @returns {void}
|
||||
*/
|
||||
function hideAlert() {
|
||||
const alertBox = document.getElementById("alert-box");
|
||||
if (alertBox) {
|
||||
alertBox.style.display = "none";
|
||||
const alertDetect = document.getElementById("alert-detect");
|
||||
const alertEmail = document.getElementById("alert-email");
|
||||
if (alertDetect) {
|
||||
alertDetect.style.display = "none";
|
||||
}
|
||||
if (alertEmail) {
|
||||
alertEmail.style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,6 +226,8 @@ async function submitPasswordRecovery(event) {
|
||||
}
|
||||
hideAlert();
|
||||
|
||||
let isSentSuccess = false;
|
||||
|
||||
try {
|
||||
const emailInput = document.getElementById("email");
|
||||
const emailVal = emailInput instanceof HTMLInputElement ? emailInput.value.trim() : "";
|
||||
@@ -231,6 +253,7 @@ async function submitPasswordRecovery(event) {
|
||||
|
||||
if (body.status === "success") {
|
||||
showAlert(body.message, "success");
|
||||
isSentSuccess = true;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -240,8 +263,27 @@ async function submitPasswordRecovery(event) {
|
||||
showAlert("网络发送异常,请稍后再试。", "error");
|
||||
} finally {
|
||||
if (submitButton instanceof HTMLButtonElement) {
|
||||
submitButton.disabled = false;
|
||||
submitButton.innerText = "发送重置邮件";
|
||||
if (isSentSuccess) {
|
||||
// 成功时启动 30 秒置灰倒计时锁定
|
||||
let seconds = 30;
|
||||
submitButton.disabled = true;
|
||||
submitButton.innerText = `${seconds}秒内不能重复发送`;
|
||||
|
||||
const timer = setInterval(() => {
|
||||
seconds--;
|
||||
if (seconds <= 0) {
|
||||
clearInterval(timer);
|
||||
submitButton.disabled = false;
|
||||
submitButton.innerText = "二次验证并发送重置邮件";
|
||||
} else {
|
||||
submitButton.innerText = `${seconds}秒内不能重复发送`;
|
||||
}
|
||||
}, 1000);
|
||||
} else {
|
||||
// 校验失败,立刻解除禁用供重新编辑
|
||||
submitButton.disabled = false;
|
||||
submitButton.innerText = "二次验证并发送重置邮件";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,12 +295,11 @@
|
||||
<div class="eyebrow">PASSWORD RECOVERY</div>
|
||||
<h1 id="recovery-title">忘记密码</h1>
|
||||
|
||||
<div id="alert-box" class="alert" aria-live="polite"></div>
|
||||
|
||||
<!-- ================== 步骤一:检测账号昵称 ================== -->
|
||||
<div id="step-detect" class="step-panel">
|
||||
<p class="lead">请输入您的聊天室用户昵称,小助手将智能查询并为您提供最安全的重置方案。</p>
|
||||
<form id="account-detect-form" action="{{ route('password.check_account') }}">
|
||||
<div id="alert-detect" class="alert" aria-live="polite"></div>
|
||||
<label for="username">账号昵称</label>
|
||||
<input
|
||||
id="username"
|
||||
@@ -355,6 +354,7 @@
|
||||
<div id="masked-email-hint" style="margin-bottom: 14px; font-size: 13.5px; color: var(--gold); font-weight: bold; line-height: 1.6; padding: 10px; border: 1px dashed rgba(198,163,91,0.3); background: rgba(198,163,91,0.02);"></div>
|
||||
|
||||
<form id="password-recovery-form" data-password-email-url="{{ route('password.email') }}">
|
||||
<div id="alert-email" class="alert" aria-live="polite"></div>
|
||||
<label for="email">二次安全确认:请输入绑定的完整邮箱</label>
|
||||
<input
|
||||
id="email"
|
||||
|
||||
Reference in New Issue
Block a user