Browse Source

feat(vben5): Realize password recovery

- 完善登录页忘记密码
pull/1219/head
colin 8 months ago
parent
commit
a9282a2245
  1. 143
      apps/vben5/apps/app-antd/src/views/_core/authentication/forget-password.vue

143
apps/vben5/apps/app-antd/src/views/_core/authentication/forget-password.vue

@ -1,41 +1,162 @@
<script lang="ts" setup>
import type { VbenFormSchema } from '@vben/common-ui';
import type { ExtendedFormApi, VbenFormSchema } from '@vben/common-ui';
import type { Recordable } from '@vben/types';
import { computed, ref } from 'vue';
import { computed, ref, useTemplateRef } from 'vue';
import { useRouter } from 'vue-router';
import { AuthenticationForgetPassword, z } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { useAccountApi } from '@abp/account';
import { isPhone } from '@abp/core';
import { usePasswordValidator } from '@abp/identity';
import { message } from 'ant-design-vue';
interface FormModel {
currentPassword: string;
newPassword: string;
newPasswordConfirm: string;
}
interface ForgetPasswordExpose {
getFormApi(): ExtendedFormApi;
}
defineOptions({ name: 'ForgetPassword' });
const router = useRouter();
const { validate } = usePasswordValidator();
const { resetPasswordApi, sendPhoneResetPasswordCodeApi } = useAccountApi();
const loading = ref(false);
const forgetPassword = useTemplateRef<ForgetPasswordExpose>('forgetPassword');
const formSchema = computed((): VbenFormSchema[] => {
return [
{
component: 'VbenInput',
component: 'Input',
componentProps: {
placeholder: $t('AbpAccount.DisplayName:PhoneNumber'),
},
fieldName: 'phoneNumber',
label: $t('AbpAccount.DisplayName:PhoneNumber'),
rules: z
.string()
.min(1, { message: $t('authentication.mobileTip') })
.refine((v) => isPhone(v), {
message: $t('authentication.mobileErrortip'),
}),
},
{
component: 'VbenPinInput',
componentProps: {
createText: (countdown: number) => {
const text =
countdown > 0
? $t('authentication.sendText', [countdown])
: $t('authentication.sendCode');
return text;
},
handleSendCode: onSendCode,
placeholder: $t('authentication.code'),
},
fieldName: 'code',
label: $t('authentication.code'),
rules: z.string().min(1, { message: $t('authentication.codeTip') }),
},
{
component: 'InputPassword',
componentProps: {
placeholder: 'example@example.com',
placeholder: $t('AbpAccount.DisplayName:NewPassword'),
},
fieldName: 'email',
label: $t('authentication.email'),
fieldName: 'newPassword',
label: $t('AbpAccount.DisplayName:NewPassword'),
rules: z
.string()
.min(1, { message: $t('authentication.emailTip') })
.email($t('authentication.emailValidErrorTip')),
.superRefine(async (newPassword, ctx) => {
try {
await validate(newPassword);
} catch (error) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: String(error),
});
}
})
.refine(
async (newPassword) => {
const formApi = forgetPassword.value?.getFormApi();
const input = (await formApi?.getValues()) as FormModel;
return input.currentPassword !== newPassword;
},
{
message: $t('AbpAccount.NewPasswordSameAsOld'),
},
)
.refine(
async (newPassword) => {
const formApi = forgetPassword.value?.getFormApi();
const input = (await formApi?.getValues()) as FormModel;
return input.newPasswordConfirm === newPassword;
},
{
message: $t(
'AbpIdentity.Volo_Abp_Identity:PasswordConfirmationFailed',
),
},
),
},
{
component: 'InputPassword',
componentProps: {
placeholder: $t('AbpAccount.DisplayName:NewPasswordConfirm'),
},
fieldName: 'newPasswordConfirm',
label: $t('AbpAccount.DisplayName:NewPasswordConfirm'),
rules: z.string().refine(
async (newPasswordConfirm) => {
const formApi = forgetPassword.value?.getFormApi();
const input = (await formApi?.getValues()) as FormModel;
return input.newPassword === newPasswordConfirm;
},
{
message: $t(
'AbpIdentity.Volo_Abp_Identity:PasswordConfirmationFailed',
),
},
),
},
];
});
function handleSubmit(value: Recordable<any>) {
// eslint-disable-next-line no-console
console.log('reset email:', value);
async function onSendCode() {
const formApi = forgetPassword.value?.getFormApi();
const input = await formApi?.getValues();
await sendPhoneResetPasswordCodeApi({
phoneNumber: input!.phoneNumber,
});
}
async function handleSubmit(values: Recordable<any>) {
loading.value = true;
try {
await resetPasswordApi({
code: values.code,
phoneNumber: values.phoneNumber,
newPassword: values.newPassword,
});
message.success($t('AbpAccount.YourPasswordIsSuccessfullyReset'));
router.push('/auth/login');
} finally {
loading.value = false;
}
}
</script>
<template>
<AuthenticationForgetPassword
ref="forgetPassword"
:form-schema="formSchema"
:loading="loading"
@submit="handleSubmit"

Loading…
Cancel
Save