diff --git a/en/docs/common/checklogin_form.md b/en/docs/common/checklogin_form.md
index db0a25e..7da9305 100644
--- a/en/docs/common/checklogin_form.md
+++ b/en/docs/common/checklogin_form.md
@@ -148,6 +148,22 @@
background-color: #2980b9;
}
+/* Forgot password link styles */
+.forgot-password-link {
+ display: block;
+ text-align: center;
+ margin-top: 15px;
+ color: #3498db;
+ text-decoration: none;
+ font-size: 14px;
+ transition: color 0.3s ease;
+}
+
+.forgot-password-link:hover {
+ color: #2980b9;
+ text-decoration: underline;
+}
+
.close {
float: right;
cursor: pointer;
@@ -298,6 +314,7 @@
+ Forgot Password?
@@ -314,6 +331,21 @@
+
+
+
@@ -329,8 +361,11 @@
const modal = document.getElementById("loginModal");
const loginForm = document.getElementById("loginForm");
const registerForm = document.getElementById("registerForm");
+ const resetForm = document.getElementById("resetForm");
const sendCodeBtn = document.getElementById("sendCodeBtn");
+ const sendResetCodeBtn = document.getElementById("sendResetCodeBtn");
let countdownTimer;
+ let resetCountdownTimer;
// Get message modal elements
const messageModal = document.getElementById("messageModal");
@@ -341,6 +376,9 @@
// Tab switching functionality
window.switchTab = function(tabName) {
+ // Get tab container
+ const tabContainer = document.querySelector('.tab-container');
+
// Hide all tab content
const tabContents = document.querySelectorAll('.tab-content');
tabContents.forEach(tab => tab.classList.remove('active'));
@@ -351,11 +389,19 @@
// Show corresponding tab content and set button active state
if (tabName === 'login') {
+ // Show tab container
+ tabContainer.style.display = 'flex';
document.getElementById('loginTab').classList.add('active');
document.querySelector('.tab-button').classList.add('active');
} else if (tabName === 'register') {
+ // Show tab container
+ tabContainer.style.display = 'flex';
document.getElementById('registerTab').classList.add('active');
document.querySelectorAll('.tab-button')[1].classList.add('active');
+ } else if (tabName === 'reset') {
+ // Hide tab container when in forgot password panel
+ tabContainer.style.display = 'none';
+ document.getElementById('resetTab').classList.add('active');
}
}
@@ -558,6 +604,46 @@
});
}
+ // Send reset password verification code
+ sendResetCodeBtn.onclick = function() {
+ const contactValue = document.getElementById('resetEmail').value;
+
+ if (!validateEmail(contactValue)) {
+ showMessage('Input Error', 'Please enter a valid email address!', 'error');
+ return;
+ }
+
+ // Disable button and start countdown
+ startResetCountdown();
+
+ // Send AJAX request to get verification code
+ fetch(`${baseUrl}/fty/sendCode`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ type: "1", // Fixed as email type
+ username: contactValue
+ })
+ })
+ .then(response => response.json())
+ .then(data => {
+ console.log("Reset password verification code send response", data);
+ if (data.code==2000) {
+ showMessage('Send Success', 'Verification code has been sent to your email!', 'success');
+ } else {
+ showMessage('Send Failed', data.msg || 'Failed to send verification code, please try again later!', 'error');
+ resetResetCountdown();
+ }
+ })
+ .catch(error => {
+ console.error('Error:', error);
+ showMessage('Network Error', 'Failed to send verification code request, please try again later!', 'error');
+ resetResetCountdown();
+ });
+ }
+
// Validate email format
function validateEmail(email) {
const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
@@ -587,6 +673,29 @@
sendCodeBtn.textContent = 'Send Code';
}
+ // Start reset password verification code countdown
+ function startResetCountdown() {
+ let countdown = 60;
+ sendResetCodeBtn.disabled = true;
+ sendResetCodeBtn.textContent = `Retry after ${countdown}s`;
+
+ resetCountdownTimer = setInterval(() => {
+ countdown--;
+ sendResetCodeBtn.textContent = `Retry after ${countdown}s`;
+
+ if (countdown <= 0) {
+ resetResetCountdown();
+ }
+ }, 1000);
+ }
+
+ // Reset reset password verification code countdown
+ function resetResetCountdown() {
+ clearInterval(resetCountdownTimer);
+ sendResetCodeBtn.disabled = false;
+ sendResetCodeBtn.textContent = 'Send Code';
+ }
+
// Handle login form submission
loginForm.onsubmit = function(e) {
console.log("Login form submitted");
@@ -756,6 +865,83 @@
});
}
+ // Handle forgot password form submission
+ resetForm.onsubmit = function(e) {
+ console.log("Reset password form submitted");
+ e.preventDefault();
+ const email = document.getElementById("resetEmail").value;
+ const verificationCode = document.getElementById("resetVerificationCode").value;
+ const password = document.getElementById("resetPassword").value;
+ const confirmPassword = document.getElementById("resetConfirmPassword").value;
+
+ if (!validateEmail(email)) {
+ showMessage('Input Error', 'Please enter a valid email address!', 'error');
+ return;
+ }
+
+ if (!verificationCode) {
+ showMessage('Input Error', 'Please enter verification code!', 'error');
+ return;
+ }
+
+ if (!password) {
+ showMessage('Input Error', 'Please enter new password!', 'error');
+ return;
+ }
+
+ if (password !== confirmPassword) {
+ showMessage('Input Error', 'The two passwords entered are inconsistent!', 'error');
+ return;
+ }
+
+ // Show loading state
+ const submitBtn = resetForm.querySelector('button[type="submit"]');
+ const originalText = submitBtn.textContent;
+ submitBtn.textContent = 'Resetting...';
+ submitBtn.disabled = true;
+
+ // Send AJAX request
+ fetch(`${baseUrl}/fty/resetpwd`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ type: 1, // Fixed as email type
+ username: email,
+ code: verificationCode,
+ password: password,
+ confirm_password: confirmPassword
+ })
+ })
+ .then(response => response.json())
+ .then(data => {
+ console.log("Reset password response", data);
+ if (data.code==2000) {
+ showMessage('Reset Success', 'Password reset successful! Please login with your new password', 'success');
+ resetResetCountdown();
+
+ // Delay switch to login tab
+ setTimeout(() => {
+ switchTab('login');
+ // Clear reset form
+ resetForm.reset();
+ }, 1500);
+ } else {
+ showMessage('Reset Failed', data.msg || 'Password reset failed, please check your input!', 'error');
+ }
+ })
+ .catch(error => {
+ console.error('Error:', error);
+ showMessage('Network Error', 'Password reset request failed, please try again later!', 'error');
+ })
+ .finally(() => {
+ // Restore button state
+ submitBtn.textContent = originalText;
+ submitBtn.disabled = false;
+ });
+ }
+
// ESC key to close login modal
document.addEventListener('keydown', function(event) {
if (event.key === 'Escape' && modal.style.display === 'block') {
diff --git a/en/docs/common/customer_form.md b/en/docs/common/customer_form.md
index 880a501..bb4b020 100644
--- a/en/docs/common/customer_form.md
+++ b/en/docs/common/customer_form.md
@@ -105,6 +105,8 @@
+
+
@@ -122,6 +124,10 @@ const companyInput = document.getElementById("company");
const emailInput = document.getElementById("email");
const topicSelect = document.getElementById("topic");
const contentTextarea = document.getElementById("content");
+const pageUrlInput = document.getElementById("pageUrl");
+
+// Set current page URL to hidden field
+pageUrlInput.value = window.location.href;
// Get message modal elements
const messageModal = document.getElementById("messageModal");
@@ -222,7 +228,8 @@ customerForm.onsubmit = function(event) {
company: companyInput.value.trim(),
email: emailInput.value.trim(),
topic: topicSelect.value,
- content: contentTextarea.value.trim()
+ content: contentTextarea.value.trim(),
+ pageUrl: pageUrlInput.value
};
// Send AJAX request
diff --git a/zh/docs/common/checklogin_form.md b/zh/docs/common/checklogin_form.md
index 8d0db65..2d54f53 100644
--- a/zh/docs/common/checklogin_form.md
+++ b/zh/docs/common/checklogin_form.md
@@ -141,6 +141,22 @@
background-color: #2980b9;
}
+/* 忘记密码链接样式 */
+.forgot-password-link {
+ display: block;
+ text-align: center;
+ margin-top: 15px;
+ color: #3498db;
+ text-decoration: none;
+ font-size: 14px;
+ transition: color 0.3s ease;
+}
+
+.forgot-password-link:hover {
+ color: #2980b9;
+ text-decoration: underline;
+}
+
.close {
float: right;
cursor: pointer;
@@ -291,6 +307,7 @@
+ 忘记密码?
@@ -307,6 +324,21 @@
+
+
+
@@ -323,8 +355,11 @@
const modal = document.getElementById("loginModal");
const loginForm = document.getElementById("loginForm");
const registerForm = document.getElementById("registerForm");
+ const resetForm = document.getElementById("resetForm");
const sendCodeBtn = document.getElementById("sendCodeBtn");
+ const sendResetCodeBtn = document.getElementById("sendResetCodeBtn");
let countdownTimer;
+ let resetCountdownTimer;
// 获取消息弹出框元素
const messageModal = document.getElementById("messageModal");
@@ -335,6 +370,9 @@
// Tab 切换功能
window.switchTab = function(tabName) {
+ // 获取tab容器
+ const tabContainer = document.querySelector('.tab-container');
+
// 隐藏所有tab内容
const tabContents = document.querySelectorAll('.tab-content');
tabContents.forEach(tab => tab.classList.remove('active'));
@@ -345,11 +383,19 @@
// 显示对应的tab内容和设置按钮active状态
if (tabName === 'login') {
+ // 显示tab容器
+ tabContainer.style.display = 'flex';
document.getElementById('loginTab').classList.add('active');
document.querySelector('.tab-button').classList.add('active');
} else if (tabName === 'register') {
+ // 显示tab容器
+ tabContainer.style.display = 'flex';
document.getElementById('registerTab').classList.add('active');
document.querySelectorAll('.tab-button')[1].classList.add('active');
+ } else if (tabName === 'reset') {
+ // 忘记密码面板时隐藏tab容器
+ tabContainer.style.display = 'none';
+ document.getElementById('resetTab').classList.add('active');
}
}
@@ -552,6 +598,46 @@
});
}
+ // 发送重置密码验证码
+ sendResetCodeBtn.onclick = function() {
+ const contactValue = document.getElementById('resetEmail').value;
+
+ if (!validateEmail(contactValue)) {
+ showMessage('输入错误', '请输入有效的邮箱地址!', 'error');
+ return;
+ }
+
+ // 禁用按钮并开始倒计时
+ startResetCountdown();
+
+ // 发送AJAX请求获取验证码
+ fetch(`${baseUrl}/fty/sendCode`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ type: "1", // 固定为邮箱类型
+ username: contactValue
+ })
+ })
+ .then(response => response.json())
+ .then(data => {
+ console.log("重置密码验证码发送返回",data);
+ if (data.code==2000) {
+ showMessage('发送成功', '验证码已发送到您的邮箱!', 'success');
+ } else {
+ showMessage('发送失败', data.msg || '验证码发送失败,请稍后重试!', 'error');
+ resetResetCountdown();
+ }
+ })
+ .catch(error => {
+ console.error('Error:', error);
+ showMessage('网络错误', '验证码发送请求失败,请稍后重试!', 'error');
+ resetResetCountdown();
+ });
+ }
+
// 验证邮箱格式
function validateEmail(email) {
const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
@@ -581,6 +667,29 @@
sendCodeBtn.textContent = '发送验证码';
}
+ // 开始重置密码验证码倒计时
+ function startResetCountdown() {
+ let countdown = 60;
+ sendResetCodeBtn.disabled = true;
+ sendResetCodeBtn.textContent = `${countdown}秒后重试`;
+
+ resetCountdownTimer = setInterval(() => {
+ countdown--;
+ sendResetCodeBtn.textContent = `${countdown}秒后重试`;
+
+ if (countdown <= 0) {
+ resetResetCountdown();
+ }
+ }, 1000);
+ }
+
+ // 重置重置密码验证码倒计时
+ function resetResetCountdown() {
+ clearInterval(resetCountdownTimer);
+ sendResetCodeBtn.disabled = false;
+ sendResetCodeBtn.textContent = '发送验证码';
+ }
+
// 处理登录表单提交
loginForm.onsubmit = function(e) {
console.log("Login form submitted");
@@ -728,6 +837,83 @@
});
}
+ // 处理忘记密码表单提交
+ resetForm.onsubmit = function(e) {
+ console.log("Reset password form submitted");
+ e.preventDefault();
+ const email = document.getElementById("resetEmail").value;
+ const verificationCode = document.getElementById("resetVerificationCode").value;
+ const password = document.getElementById("resetPassword").value;
+ const confirmPassword = document.getElementById("resetConfirmPassword").value;
+
+ if (!validateEmail(email)) {
+ showMessage('输入错误', '请输入有效的邮箱地址!', 'error');
+ return;
+ }
+
+ if (!verificationCode) {
+ showMessage('输入错误', '请输入验证码!', 'error');
+ return;
+ }
+
+ if (!password) {
+ showMessage('输入错误', '请输入新密码!', 'error');
+ return;
+ }
+
+ if (password !== confirmPassword) {
+ showMessage('输入错误', '两次输入的密码不一致!', 'error');
+ return;
+ }
+
+ // 显示加载状态
+ const submitBtn = resetForm.querySelector('button[type="submit"]');
+ const originalText = submitBtn.textContent;
+ submitBtn.textContent = '重置中...';
+ submitBtn.disabled = true;
+
+ // 发送AJAX请求
+ fetch(`${baseUrl}/fty/resetpwd`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ type: 1, // 固定为邮箱类型
+ username: email,
+ code: verificationCode,
+ password: password,
+ confirm_password: confirmPassword
+ })
+ })
+ .then(response => response.json())
+ .then(data => {
+ console.log("重置密码返回",data);
+ if (data.code==2000) {
+ showMessage('重置成功', '密码重置成功!请使用新密码登录', 'success');
+ resetResetCountdown();
+
+ // 延迟切换到登录标签
+ setTimeout(() => {
+ switchTab('login');
+ // 清空重置表单
+ resetForm.reset();
+ }, 1500);
+ } else {
+ showMessage('重置失败', data.msg || '密码重置失败,请检查输入信息!', 'error');
+ }
+ })
+ .catch(error => {
+ console.error('Error:', error);
+ showMessage('网络错误', '密码重置请求失败,请稍后重试!', 'error');
+ })
+ .finally(() => {
+ // 恢复按钮状态
+ submitBtn.textContent = originalText;
+ submitBtn.disabled = false;
+ });
+ }
+
// ESC键关闭登录框
document.addEventListener('keydown', function(event) {
if (event.key === 'Escape' && modal.style.display === 'block') {
diff --git a/zh/docs/common/customer_form.md b/zh/docs/common/customer_form.md
index f9763cd..443899c 100644
--- a/zh/docs/common/customer_form.md
+++ b/zh/docs/common/customer_form.md
@@ -105,6 +105,8 @@
+
+
@@ -122,6 +124,10 @@ const companyInput = document.getElementById("company");
const emailInput = document.getElementById("email");
const topicSelect = document.getElementById("topic");
const contentTextarea = document.getElementById("content");
+const pageUrlInput = document.getElementById("pageUrl");
+
+// 设置当前页面URL到隐藏字段
+pageUrlInput.value = window.location.href;
// 获取消息弹出框元素
const messageModal = document.getElementById("messageModal");
@@ -222,7 +228,8 @@ customerForm.onsubmit = function(event) {
company: companyInput.value.trim(),
email: emailInput.value.trim(),
topic: topicSelect.value,
- content: contentTextarea.value.trim()
+ content: contentTextarea.value.trim(),
+ pageUrl: pageUrlInput.value
};
// 发送AJAX请求