154 lines
5.9 KiB
HTML
154 lines
5.9 KiB
HTML
<!doctype html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>找回密码</title>
|
||
<link rel="stylesheet" href="/app.css" />
|
||
</head>
|
||
<body>
|
||
<div class="center">
|
||
<div class="card wide">
|
||
<div class="cardTitle">找回密码</div>
|
||
|
||
<!-- 步骤1: 请求发送重置邮件 -->
|
||
<div id="requestStep" class="stack">
|
||
<div class="hint">请输入你的用户名,我们将向你注册时填写的邮箱发送 6 位数字验证码。</div>
|
||
<input id="requestUsername" class="input" placeholder="用户名" autocomplete="username" />
|
||
<button id="requestBtn" class="btn btnPrimary">发送验证码</button>
|
||
<div id="requestMsg" class="hint"></div>
|
||
<a class="link" href="/">返回聊天室</a>
|
||
</div>
|
||
|
||
<!-- 步骤2: 输入 token 重置密码 -->
|
||
<div id="resetStep" class="stack" style="display: none;">
|
||
<div class="hint">请输入邮件中收到的 6 位数字验证码和新密码。验证码有效期 30 分钟。</div>
|
||
<input id="token" class="input" placeholder="6 位数字验证码" maxlength="6" pattern="[0-9]*" inputmode="numeric" />
|
||
<input id="newPassword" class="input" placeholder="新密码(至少6位)" type="password" autocomplete="new-password" />
|
||
<button id="resetBtn" class="btn btnPrimary">重置密码</button>
|
||
<div id="resetMsg" class="hint"></div>
|
||
<button id="backToRequestBtn" class="btn" style="margin-top: 10px;">返回重新发送</button>
|
||
<a class="link" href="/">返回聊天室</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<script type="module">
|
||
const $ = (id) => document.getElementById(id);
|
||
const params = new URLSearchParams(location.search);
|
||
|
||
// 如果 URL 中有 token,直接显示重置步骤
|
||
const urlToken = params.get("token");
|
||
if (urlToken) {
|
||
$("token").value = urlToken;
|
||
$("requestStep").style.display = "none";
|
||
$("resetStep").style.display = "block";
|
||
}
|
||
|
||
// 请求发送重置邮件
|
||
$("requestBtn").addEventListener("click", async (e) => {
|
||
e.preventDefault();
|
||
const username = $("requestUsername").value.trim();
|
||
if (!username) {
|
||
$("requestMsg").textContent = "请输入用户名";
|
||
$("requestMsg").style.color = "red";
|
||
return;
|
||
}
|
||
|
||
$("requestBtn").disabled = true;
|
||
$("requestMsg").textContent = "发送中...";
|
||
$("requestMsg").style.color = "";
|
||
|
||
try {
|
||
const resp = await fetch("/api/auth/request-password-reset", {
|
||
method: "POST",
|
||
headers: { "content-type": "application/json" },
|
||
body: JSON.stringify({ username }),
|
||
});
|
||
const data = await resp.json().catch(() => ({}));
|
||
|
||
if (resp.ok) {
|
||
// 开发模式可能返回 devResetLink
|
||
if (data.devResetLink) {
|
||
$("requestMsg").innerHTML = `开发模式:<a href="${data.devResetLink}" class="link">点击这里重置密码</a>`;
|
||
$("requestMsg").style.color = "green";
|
||
} else {
|
||
$("requestMsg").textContent = data.message || "✅ 重置链接已发送到邮箱,请查收";
|
||
$("requestMsg").style.color = "green";
|
||
// 切换到重置步骤
|
||
setTimeout(() => {
|
||
$("requestStep").style.display = "none";
|
||
$("resetStep").style.display = "block";
|
||
}, 2000);
|
||
}
|
||
} else {
|
||
$("requestMsg").textContent = data.error || "请求失败,请稍后重试";
|
||
$("requestMsg").style.color = "red";
|
||
}
|
||
} catch (err) {
|
||
$("requestMsg").textContent = "网络错误,请稍后重试";
|
||
$("requestMsg").style.color = "red";
|
||
} finally {
|
||
$("requestBtn").disabled = false;
|
||
}
|
||
});
|
||
|
||
// 重置密码
|
||
$("resetBtn").addEventListener("click", async (e) => {
|
||
e.preventDefault();
|
||
const token = $("token").value.trim();
|
||
const newPassword = $("newPassword").value;
|
||
|
||
if (!token) {
|
||
$("resetMsg").textContent = "请输入验证码";
|
||
$("resetMsg").style.color = "red";
|
||
return;
|
||
}
|
||
if (!/^\d{6}$/.test(token)) {
|
||
$("resetMsg").textContent = "验证码必须是 6 位数字";
|
||
$("resetMsg").style.color = "red";
|
||
return;
|
||
}
|
||
if (newPassword.length < 6) {
|
||
$("resetMsg").textContent = "密码至少需要 6 位";
|
||
$("resetMsg").style.color = "red";
|
||
return;
|
||
}
|
||
|
||
$("resetBtn").disabled = true;
|
||
$("resetMsg").textContent = "重置中...";
|
||
$("resetMsg").style.color = "";
|
||
|
||
try {
|
||
const resp = await fetch("/api/auth/reset-password", {
|
||
method: "POST",
|
||
headers: { "content-type": "application/json" },
|
||
body: JSON.stringify({ token, newPassword }),
|
||
});
|
||
const data = await resp.json().catch(() => ({}));
|
||
|
||
if (resp.ok) {
|
||
$("resetMsg").textContent = "✅ 密码已重置成功!请返回登录";
|
||
$("resetMsg").style.color = "green";
|
||
} else {
|
||
$("resetMsg").textContent = data.error || "重置失败,验证码可能已过期";
|
||
$("resetMsg").style.color = "red";
|
||
}
|
||
} catch (err) {
|
||
$("resetMsg").textContent = "网络错误,请稍后重试";
|
||
$("resetMsg").style.color = "red";
|
||
} finally {
|
||
$("resetBtn").disabled = false;
|
||
}
|
||
});
|
||
|
||
// 返回重新发送
|
||
$("backToRequestBtn").addEventListener("click", () => {
|
||
$("resetStep").style.display = "none";
|
||
$("requestStep").style.display = "block";
|
||
$("requestMsg").textContent = "";
|
||
$("resetMsg").textContent = "";
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|