2
0

fix:重置密码界面修改重置条件

This commit is contained in:
zhongzm
2025-01-15 18:15:17 +08:00
parent fc177c6b88
commit dc520a14c4
3 changed files with 134 additions and 15 deletions

View File

@@ -271,7 +271,15 @@ const local: any = {
validationError: 'Validation failed, please try again' validationError: 'Validation failed, please try again'
}, },
resetPwd: { resetPwd: {
title: 'Reset Password' title: 'Reset Password',
oldPassword: 'Current Password',
oldPasswordPlaceholder: 'Please enter current password',
oldPasswordRequired: 'Please enter current password',
newPassword: 'New Password',
passwordSameAsOld: 'New password cannot be the same as current password',
passwordLength: 'Password must be at least 6 characters',
byPassword: 'Reset by Password',
byEmail: 'Reset by Email Code'
}, },
bindWeChat: { bindWeChat: {
title: 'Bind WeChat' title: 'Bind WeChat'

View File

@@ -271,7 +271,15 @@ const local:any = {
validationError: '验证失败,请重试' validationError: '验证失败,请重试'
}, },
resetPwd: { resetPwd: {
title: '重置密码' title: '重置密码',
oldPassword: '原密码',
oldPasswordPlaceholder: '请输入原密码',
oldPasswordRequired: '请输入原密码',
newPassword: '新密码',
passwordSameAsOld: '新密码不能与原密码相同',
passwordLength: '密码长度不能小于6位',
byPassword: '通过原密码重置',
byEmail: '通过邮箱验证码重置'
}, },
bindWeChat: { bindWeChat: {
title: '绑定微信' title: '绑定微信'

View File

@@ -2,48 +2,103 @@
import { reactive, computed, ref } from 'vue'; import { reactive, computed, ref } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useFormRules } from '@/hooks/common/form'; import { useFormRules } from '@/hooks/common/form';
import { useCaptcha } from '@/hooks/business/captcha';
import type { Rule } from 'ant-design-vue/es/form'; import type { Rule } from 'ant-design-vue/es/form';
import { import {
Form as AForm, Form as AForm,
FormItem as AFormItem, FormItem as AFormItem,
Input, Input,
Button as AButton, Button as AButton,
Card as ACard Card as ACard,
Radio,
} from 'ant-design-vue'; } from 'ant-design-vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
const AInputPassword = Input.Password; const AInputPassword = Input.Password;
const ARadioGroup = Radio.Group;
const { t } = useI18n(); const { t } = useI18n();
const formRef = ref(); const formRef = ref();
const { label, isCounting, loading, getCaptcha } = useCaptcha();
// 重置方式password-原密码方式email-邮箱验证码方式
const resetType = ref<'password' | 'email'>('password');
interface FormModel { interface FormModel {
oldPassword: string;
password: string; password: string;
confirmPassword: string; confirmPassword: string;
email: string;
code: string;
uuid: string;
} }
const formModel = reactive<FormModel>({ const formModel = reactive<FormModel>({
oldPassword: '',
password: '', password: '',
confirmPassword: '' confirmPassword: '',
email: '',
code: '',
uuid: ''
}); });
// 复用注册界面的密码验证规则 // 表单验证规则
const formRules = computed<Record<string, Rule | Rule[]>>(() => { const formRules = computed<Record<string, Rule | Rule[]>>(() => {
const { createConfirmPwdRule } = useFormRules(); const { createConfirmPwdRule } = useFormRules();
return { const baseRules = {
password: [ password: [
{ required: true, message: t('page.login.register.passwordRequired') }, { required: true, message: t('page.login.register.passwordRequired') },
{ min: 6, message: t('page.login.register.passwordLength') } { min: 6, message: t('page.login.resetPwd.passwordLength') }
], ],
confirmPassword: createConfirmPwdRule(formModel.password) confirmPassword: createConfirmPwdRule(formModel.password)
}; };
if (resetType.value === 'password') {
return {
...baseRules,
oldPassword: [
{ required: true, message: t('page.login.resetPwd.oldPasswordRequired') },
{ min: 6, message: t('page.login.resetPwd.passwordLength') },
],
password: [
...baseRules.password,
{
validator: (_rule: Rule, value: string) => {
if (value && value === formModel.oldPassword) {
return Promise.reject(t('page.login.resetPwd.passwordSameAsOld'));
}
return Promise.resolve();
}
}
]
};
} else {
return {
...baseRules,
email: [
{ required: true, message: t('page.login.register.emailRequired') },
{ type: 'email', message: t('page.login.register.emailInvalid') }
],
code: [{ required: true, message: t('page.login.register.codeRequired') }]
};
}
}); });
async function handleCaptcha() {
const res = await getCaptcha(formModel.email);
if (res) {
formModel.uuid = res.data.uuid;
if (res.data?.text) {
formModel.code = res.data.text;
}
}
}
async function handleSubmit() { async function handleSubmit() {
try { try {
await formRef.value?.validate(); await formRef.value?.validate();
// //
window.$message?.success(t('common.success')); window.$message?.success(t('common.success'));
} catch (error) { } catch (error) {
console.error('Form validation failed:', error); console.error('Form validation failed:', error);
@@ -65,33 +120,77 @@ const handleBack = () => {
{{ t('page.login.common.back') }} {{ t('page.login.common.back') }}
</a-button> </a-button>
</template> </template>
<a-radio-group v-model:value="resetType" class="mb-24px">
<a-radio value="password">{{ t('page.login.resetPwd.byPassword') }}</a-radio>
<a-radio value="email">{{ t('page.login.resetPwd.byEmail') }}</a-radio>
</a-radio-group>
<a-form <a-form
ref="formRef" ref="formRef"
:model="formModel" :model="formModel"
:rules="formRules" :rules="formRules"
:label-col="{ :label-col="{
xs: { span: 24 }, // 移动端占满宽度 xs: { span: 24 },
sm: { span: 8 }, // 小屏幕占8格 sm: { span: 8 },
md: { span: 6 } // 中等及以上屏幕占6格 md: { span: 6 }
}" }"
:wrapper-col="{ :wrapper-col="{
xs: { span: 24 }, // 移动端占满宽度 xs: { span: 24 },
sm: { span: 16 }, // 小屏幕占16格 sm: { span: 16 },
md: { span: 18 } // 中等及以上屏幕占18格 md: { span: 18 }
}" }"
> >
<a-form-item name="password" :label="t('page.login.register.password')"> <template v-if="resetType === 'password'">
<a-form-item name="oldPassword" :label="t('page.login.resetPwd.oldPassword')">
<a-input-password
v-model:value="formModel.oldPassword"
:placeholder="t('page.login.resetPwd.oldPasswordPlaceholder')"
/>
</a-form-item>
</template>
<template v-else>
<a-form-item name="email" :label="t('page.login.register.email')">
<a-input
v-model:value="formModel.email"
:placeholder="t('page.login.common.emailPlaceholder')"
/>
</a-form-item>
<a-form-item name="code" :label="t('page.login.register.code')">
<a-space>
<a-input
v-model:value="formModel.code"
:placeholder="t('page.login.common.codePlaceholder')"
style="width: 200px"
/>
<a-button
type="primary"
:loading="loading"
:disabled="isCounting"
@click="handleCaptcha"
>
{{ label }}
</a-button>
</a-space>
</a-form-item>
</template>
<a-form-item name="password" :label="t('page.login.resetPwd.newPassword')">
<a-input-password <a-input-password
v-model:value="formModel.password" v-model:value="formModel.password"
:placeholder="t('page.login.common.passwordPlaceholder')" :placeholder="t('page.login.common.passwordPlaceholder')"
/> />
</a-form-item> </a-form-item>
<a-form-item name="confirmPassword" :label="t('page.login.register.confirmPassword')"> <a-form-item name="confirmPassword" :label="t('page.login.register.confirmPassword')">
<a-input-password <a-input-password
v-model:value="formModel.confirmPassword" v-model:value="formModel.confirmPassword"
:placeholder="t('page.login.common.confirmPasswordPlaceholder')" :placeholder="t('page.login.common.confirmPasswordPlaceholder')"
/> />
</a-form-item> </a-form-item>
<a-form-item <a-form-item
:wrapper-col="{ :wrapper-col="{
xs: { span: 24, offset: 0 }, xs: { span: 24, offset: 0 },
@@ -186,4 +285,8 @@ const handleBack = () => {
padding: 12px; padding: 12px;
} }
} }
.mb-24px {
margin-bottom: 24px;
}
</style> </style>