其實搬移到一半發現工程量有點大,而且再五天就要結束數鐵人賽了,所以決定繼續以:JavaScripts + HTML + CSS 去完成。前兩天的 React
就當作初步了解,之後有機會再自己透過專案去練習。
今天打算來「忘記密碼」的功能,由於是個小專案,所以沒有打算要寫 Email 作為驗證身分的媒介,目前的想法是參考學校系統的方式:
加上選擇問題的部分,還有給使用者輸入答案的欄位
<form id="signupForm">
<label for="username">帳號名:</label>
<input type="text" id="username" required><br><br>
<label for="password">密碼:</label>
<!-- 密碼建議用 type="password" 而不是 number -->
<input type="password" id="password" required><br><br>
<label for="securityQuestion">安全問題:</label>
<select id="securityQuestion" required>
<option value="" disabled selected>請選擇問題</option>
<option value="pet">你的小學名字是?</option>
<option value="food">你最喜歡的食物是?</option>
<option value="movie">你最喜歡的電影是?</option>
</select>
<br><br>
<label for="securityAnswer">答案:</label>
<input type="text" id="securityAnswer" required>
<br><br>
// ================== 註冊表單邏輯 ==================
const signupForm = document.getElementById("signupForm");
if (signupForm) {
signupForm.addEventListener("submit", function (e) {
e.preventDefault();
const username = document.getElementById("username").value.trim();
const password = document.getElementById("password").value.trim();
const securityQuestion = document.getElementById("securityQuestion").value;
const securityAnswer = document.getElementById("securityAnswer").value.trim();
const message = document.getElementById("message");
let users = JSON.parse(localStorage.getItem("users")) || {};
if (!username || !password) {
message.textContent = "請輸入帳號與密碼!";
message.style.color = "red";
return;
}
if (users[username]) {
message.textContent = "此帳號已被註冊,請換一個!";
message.style.color = "red";
} else {
//這裡要存完整結構,不只是 password
users[username] = {
password,
securityQuestion,
securityAnswer,
};
localStorage.setItem("users", JSON.stringify(users));
message.textContent = "註冊成功!將自動前往登入頁...";
message.style.color = "green";
setTimeout(() => {
window.location.href = "login.html";
}, 1000);
}
});
}
新增了:
const securityQuestion = document.getElementById("securityQuestion").value;
const securityAnswer = document.getElementById("securityAnswer").value.trim();
這是點擊忘記密碼後,轉跳至的重設頁面
流程:確認帳號 → 回答問題 → 確認是本人 → 修改密碼 → 轉跳至登入頁面 ( 重新登入 )
<head>
<link rel="stylesheet" href="style.css" />
<title>忘記密碼</title>
<script src="script.js" defer></script>
</head>
<body>
<!-- 加上 id 讓 script.js 能找到 navbar -->
<nav id="navbar">
<a href="index.html">首頁</a>
<a href="signup.html">註冊</a>
<a href="login.html">登入</a>
</nav>
<h1>重設密碼</h1>
<div id="resetContainer">
<!-- 第一步:輸入帳號 -->
<form id="resetForm">
<label for="resetUsername">帳號名:</label>
<input type="text" id="resetUsername" required>
<button type="submit">確認帳號</button>
</form>
<!-- 第二步:顯示安全問題,輸入答案 -->
<!-- 原本 style="display:none;" 改成 class="hidden" -->
<div id="securitySection" class="hidden">
<p id="securityQuestionText"></p>
<label for="securityAnswerInput">答案:</label>
<input type="text" id="securityAnswerInput" required>
<button type="button" id="checkAnswerBtn">送出答案</button>
</div>
<!-- 第三步:輸入新密碼 -->
<!-- 原本 style="display:none;" 改成 class="hidden" -->
<div id="newPasswordSection" class="hidden">
<label for="newPassword">新密碼:</label>
<input type="password" id="newPassword" required>
<button type="button" id="resetPasswordBtn">重設密碼</button>
</div>
</div>
<p id="resetMessage"></p>
</body>
// ================== 忘記密碼邏輯 ==================
const resetForm = document.getElementById("resetForm");
if (resetForm) {
const securitySection = document.getElementById("securitySection");
const securityQuestionText = document.getElementById("securityQuestionText");
const securityAnswerInput = document.getElementById("securityAnswerInput");
const checkAnswerBtn = document.getElementById("checkAnswerBtn");
const newPasswordSection = document.getElementById("newPasswordSection");
const newPasswordInput = document.getElementById("newPassword");
const resetPasswordBtn = document.getElementById("resetPasswordBtn");
const resetMessage = document.getElementById("resetMessage");
let currentUser = null; // 記錄正在重設密碼的帳號
const QUESTION_TEXT = {
pet: "你的小學名字是?",
food: "你最喜歡的食物是?",
movie: "你最喜歡的電影是?",
};
// 第一步:輸入帳號,顯示安全問題
resetForm.addEventListener("submit", function (e) {
e.preventDefault();
resetMessage.textContent = "";
const username = document.getElementById("resetUsername").value.trim();
const users = JSON.parse(localStorage.getItem("users") || "{}");
const user = users[username];
if (!user) {
resetMessage.textContent = "查無此帳號!";
resetMessage.style.color = "red";
securitySection.classList.add("hidden");
newPasswordSection.classList.add("hidden");
return;
}
currentUser = username;
securityQuestionText.textContent =
QUESTION_TEXT[user.securityQuestion] || "請回答你的安全問題";
// 顯示安全問題、隱藏新密碼區
securitySection.classList.remove("hidden");
newPasswordSection.classList.add("hidden");
securityAnswerInput.value = "";
securityAnswerInput.focus();
});
// 第二步:檢查答案是否正確
checkAnswerBtn.addEventListener("click", function () {
const users = JSON.parse(localStorage.getItem("users") || "{}");
if (!currentUser || !users[currentUser]) return;
const expected = (users[currentUser].securityAnswer || "")
.trim()
.toLowerCase();
const got = (securityAnswerInput.value || "").trim().toLowerCase();
if (got && got === expected) {
resetMessage.textContent = "驗證成功,請輸入新密碼";
resetMessage.style.color = "green";
newPasswordSection.classList.remove("hidden");
newPasswordInput.value = "";
newPasswordInput.focus();
} else {
resetMessage.textContent = "答案錯誤!";
resetMessage.style.color = "red";
newPasswordSection.classList.add("hidden");
}
});
// 第三步:設定新密碼
resetPasswordBtn.addEventListener("click", function () {
const users = JSON.parse(localStorage.getItem("users") || "{}");
if (!currentUser || !users[currentUser]) return;
const newPassword = (newPasswordInput.value || "").trim();
if (!newPassword) {
resetMessage.textContent = "新密碼不可為空!";
resetMessage.style.color = "red";
return;
}
users[currentUser].password = newPassword;
localStorage.setItem("users", JSON.stringify(users));
resetMessage.textContent = "密碼已成功重設!請回到登入頁";
resetMessage.style.color = "green";
// 收尾
newPasswordSection.classList.add("hidden");
securitySection.classList.add("hidden");
resetForm.reset();
});
}
輸入帳號 → 顯示問題
resetForm.addEventListener("submit", ...)
currentUser
輸入答案 → 驗證
checkAnswerBtn.addEventListener("click", ...)
localStorage
裡的答案比對輸入新密碼 → 更新
resetPasswordBtn.addEventListener("click", ...)
localStorage
裡的密碼