feat: 注册、重置密码、重发验证邮件添加验证码功能

后端修改:
- 添加通用验证码验证函数 verifyCaptcha()
- /api/register 接口添加验证码验证
- /api/password/forgot 接口添加验证码验证
- /api/resend-verification 接口添加验证码验证

前端修改:
- 注册表单添加验证码输入框和图片
- 忘记密码模态框添加验证码
- 重发验证邮件区域添加验证码输入
- 添加各表单的验证码刷新方法
- 提交失败后自动刷新验证码

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-28 13:11:03 +08:00
parent f8c9f8f739
commit 1d65e97b04
3 changed files with 148 additions and 14 deletions

View File

@@ -29,8 +29,10 @@ createApp({
registerForm: {
username: '',
email: '',
password: ''
password: '',
captcha: ''
},
registerCaptchaUrl: '',
// 验证码相关
showCaptcha: false,
@@ -125,8 +127,10 @@ createApp({
// 忘记密码
showForgotPasswordModal: false,
forgotPasswordForm: {
email: ''
email: '',
captcha: ''
},
forgotPasswordCaptchaUrl: '',
showResetPasswordModal: false,
resetPasswordForm: {
token: '',
@@ -134,6 +138,8 @@ createApp({
},
showResendVerify: false,
resendVerifyEmail: '',
resendVerifyCaptcha: '',
resendVerifyCaptchaUrl: '',
// 系统设置
systemSettings: {
@@ -604,18 +610,37 @@ handleDragLeave(e) {
}
},
// 刷新验证码
// 刷新验证码(登录)
refreshCaptcha() {
this.captchaUrl = `${this.apiBase}/api/captcha?t=${Date.now()}`;
},
// 刷新注册验证码
refreshRegisterCaptcha() {
this.registerCaptchaUrl = `${this.apiBase}/api/captcha?t=${Date.now()}`;
},
// 刷新忘记密码验证码
refreshForgotPasswordCaptcha() {
this.forgotPasswordCaptchaUrl = `${this.apiBase}/api/captcha?t=${Date.now()}`;
},
// 刷新重发验证邮件验证码
refreshResendVerifyCaptcha() {
this.resendVerifyCaptchaUrl = `${this.apiBase}/api/captcha?t=${Date.now()}`;
},
async resendVerification() {
if (!this.resendVerifyEmail) {
this.showToast('error', '错误', '请输入邮箱或用户名后再重试');
return;
}
if (!this.resendVerifyCaptcha) {
this.showToast('error', '错误', '请输入验证码');
return;
}
try {
const payload = {};
const payload = { captcha: this.resendVerifyCaptcha };
if (this.resendVerifyEmail.includes('@')) {
payload.email = this.resendVerifyEmail;
} else {
@@ -624,10 +649,17 @@ handleDragLeave(e) {
const response = await axios.post(`${this.apiBase}/api/resend-verification`, payload);
if (response.data.success) {
this.showToast('success', '成功', '验证邮件已发送,请查收');
this.showResendVerify = false;
this.resendVerifyEmail = '';
this.resendVerifyCaptcha = '';
this.resendVerifyCaptchaUrl = '';
}
} catch (error) {
console.error('重发验证邮件失败:', error);
this.showToast('error', '错误', error.response?.data?.message || '发送失败');
// 刷新验证码
this.resendVerifyCaptcha = '';
this.refreshResendVerifyCaptcha();
}
},
@@ -661,8 +693,10 @@ handleDragLeave(e) {
this.registerForm = {
username: '',
email: '',
password: ''
password: '',
captcha: ''
};
this.registerCaptchaUrl = '';
}
} catch (error) {
const errorData = error.response?.data;
@@ -671,6 +705,9 @@ handleDragLeave(e) {
} else {
this.errorMessage = errorData?.message || '注册失败';
}
// 刷新验证码
this.registerForm.captcha = '';
this.refreshRegisterCaptcha();
}
},
@@ -1881,6 +1918,10 @@ handleDragLeave(e) {
this.showToast('error', '错误', '请输入注册邮箱');
return;
}
if (!this.forgotPasswordForm.captcha) {
this.showToast('error', '错误', '请输入验证码');
return;
}
try {
const response = await axios.post(
@@ -1891,11 +1932,15 @@ handleDragLeave(e) {
if (response.data.success) {
this.showToast('success', '成功', '如果邮箱存在,将收到重置邮件');
this.showForgotPasswordModal = false;
this.forgotPasswordForm = { email: '' };
this.forgotPasswordForm = { email: '', captcha: '' };
this.forgotPasswordCaptchaUrl = '';
}
} catch (error) {
console.error('提交密码重置请求失败:', error);
this.showToast('error', '错误', error.response?.data?.message || '提交失败');
// 刷新验证码
this.forgotPasswordForm.captcha = '';
this.refreshForgotPasswordCaptcha();
}
},