Browse Source

feat(vben5): Implement phone number change

pull/1159/head
colin 2 years ago
parent
commit
d52947719d
  1. 28
      apps/vben5/packages/@abp/account/src/api/useProfileApi.ts
  2. 14
      apps/vben5/packages/@abp/account/src/components/MySetting.vue
  3. 82
      apps/vben5/packages/@abp/account/src/components/components/ChangePhoneNumberModal.vue
  4. 11
      apps/vben5/packages/@abp/account/src/types/profile.ts
  5. 4
      apps/vben5/packages/@abp/settings/src/components/settings/SettingForm.vue

28
apps/vben5/packages/@abp/account/src/api/useProfileApi.ts

@ -2,9 +2,11 @@ import type {
AuthenticatorDto, AuthenticatorDto,
AuthenticatorRecoveryCodeDto, AuthenticatorRecoveryCodeDto,
ChangePasswordInput, ChangePasswordInput,
ChangePhoneNumberInput,
ChangePictureInput, ChangePictureInput,
ConfirmEmailInput, ConfirmEmailInput,
ProfileDto, ProfileDto,
SendChangePhoneNumberCodeInput,
SendEmailConfirmCodeDto, SendEmailConfirmCodeDto,
TwoFactorEnabledDto, TwoFactorEnabledDto,
UpdateProfileDto, UpdateProfileDto,
@ -49,6 +51,30 @@ export function useProfileApi() {
}); });
} }
/**
* 发送修改手机号验证码
* @param input 参数
*/
function sendChangePhoneNumberCodeApi(
input: SendChangePhoneNumberCodeInput,
): Promise<void> {
return request('/api/account/my-profile/send-phone-number-change-code', {
data: input,
method: 'POST',
});
}
/**
* 修改手机号
* @param input 参数
*/
function changePhoneNumberApi(input: ChangePhoneNumberInput): Promise<void> {
return request('/api/account/my-profile/change-phone-number', {
data: input,
method: 'PUT',
});
}
/** /**
* 修改头像 * 修改头像
* @param input 参数 * @param input 参数
@ -158,6 +184,7 @@ export function useProfileApi() {
return { return {
cancel, cancel,
changePasswordApi, changePasswordApi,
changePhoneNumberApi,
changePictureApi, changePictureApi,
changeTwoFactorEnabledApi, changeTwoFactorEnabledApi,
confirmEmailApi, confirmEmailApi,
@ -166,6 +193,7 @@ export function useProfileApi() {
getPictureApi, getPictureApi,
getTwoFactorEnabledApi, getTwoFactorEnabledApi,
resetAuthenticatorApi, resetAuthenticatorApi,
sendChangePhoneNumberCodeApi,
sendEmailConfirmLinkApi, sendEmailConfirmLinkApi,
updateApi, updateApi,
verifyAuthenticatorCodeApi, verifyAuthenticatorCodeApi,

14
apps/vben5/packages/@abp/account/src/components/MySetting.vue

@ -96,6 +96,11 @@ const [ChangePasswordModal, changePasswordModalApi] = useVbenModal({
() => import('./components/ChangePasswordModal.vue'), () => import('./components/ChangePasswordModal.vue'),
), ),
}); });
const [ChangePhoneNumberModal, changePhoneNumberModalApi] = useVbenModal({
connectedComponent: defineAsyncComponent(
() => import('./components/ChangePhoneNumberModal.vue'),
),
});
function onEmailConfirm() { function onEmailConfirm() {
if (query?.confirmToken) { if (query?.confirmToken) {
emailConfirmModalApi.setData({ emailConfirmModalApi.setData({
@ -109,6 +114,11 @@ async function onGetProfile() {
const profile = await getApi(); const profile = await getApi();
myProfile.value = profile; myProfile.value = profile;
} }
async function onPhoneNumberChange(phoneNumber: string) {
userStore.$patch((state) => {
state.userInfo && (state.userInfo.phoneNumber = phoneNumber);
});
}
async function onUpdateProfile(input: UpdateProfileDto) { async function onUpdateProfile(input: UpdateProfileDto) {
Modal.confirm({ Modal.confirm({
centered: true, centered: true,
@ -128,8 +138,7 @@ function onChangePassword() {
changePasswordModalApi.open(); changePasswordModalApi.open();
} }
function onChangePhoneNumber() { function onChangePhoneNumber() {
// TODO: onChangePhoneNumber 暂时未实现! changePhoneNumberModalApi.open();
console.warn('onChangePhoneNumber 暂时未实现!');
} }
onMounted(async () => { onMounted(async () => {
await onGetProfile(); await onGetProfile();
@ -174,6 +183,7 @@ onMounted(async () => {
</Card> </Card>
<EmailConfirmModal /> <EmailConfirmModal />
<ChangePasswordModal /> <ChangePasswordModal />
<ChangePhoneNumberModal @change="onPhoneNumberChange" />
</div> </div>
</template> </template>

82
apps/vben5/packages/@abp/account/src/components/components/ChangePhoneNumberModal.vue

@ -0,0 +1,82 @@
<script setup lang="ts">
import { useVbenForm, useVbenModal } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { message } from 'ant-design-vue';
import { useProfileApi } from '../../api';
const emits = defineEmits<{
(event: 'change', data: string): void;
}>();
const { changePhoneNumberApi, sendChangePhoneNumberCodeApi } = useProfileApi();
const [Form, formApi] = useVbenForm({
handleSubmit: onSubmit,
schema: [
{
component: 'Input',
fieldName: 'newPhoneNumber',
label: $t('AbpIdentity.DisplayName:NewPhoneNumber'),
rules: 'required',
},
{
component: 'VbenPinInput',
componentProps: {
createText: (countdown: number) => {
const text =
countdown > 0
? $t('authentication.sendText', [countdown])
: $t('authentication.sendCode');
return text;
},
handleSendCode: onSendCode,
},
fieldName: 'code',
label: $t('AbpIdentity.DisplayName:SmsVerifyCode'),
rules: 'required',
},
],
showDefaultActions: false,
});
const [Modal, modalApi] = useVbenModal({
async onConfirm() {
await formApi.validateAndSubmitForm();
},
});
async function onSendCode() {
const result = await formApi.validateField('newPhoneNumber');
if (!result.valid) {
throw new Error(result.errors.join('\n'));
}
const input = await formApi.getValues();
await sendChangePhoneNumberCodeApi({
newPhoneNumber: input.newPhoneNumber,
});
}
async function onSubmit(values: Record<string, any>) {
try {
modalApi.setState({ submitting: true });
await changePhoneNumberApi({
code: values.code,
newPhoneNumber: values.newPhoneNumber,
});
message.success($t('AbpAccount.PhoneNumberChangedMessage'));
emits('change', values.newPhoneNumber);
modalApi.close();
} finally {
modalApi.setState({ submitting: false });
}
}
</script>
<template>
<Modal :title="$t('AbpIdentity.PhoneNumber')">
<Form />
</Modal>
</template>
<style scoped></style>

11
apps/vben5/packages/@abp/account/src/types/profile.ts

@ -36,6 +36,15 @@ interface ChangePasswordInput {
newPassword: string; newPassword: string;
} }
interface ChangePhoneNumberInput {
code: string;
newPhoneNumber: string;
}
interface SendChangePhoneNumberCodeInput {
newPhoneNumber: string;
}
interface ChangePictureInput { interface ChangePictureInput {
file: File; file: File;
} }
@ -73,9 +82,11 @@ export type {
AuthenticatorDto, AuthenticatorDto,
AuthenticatorRecoveryCodeDto, AuthenticatorRecoveryCodeDto,
ChangePasswordInput, ChangePasswordInput,
ChangePhoneNumberInput,
ChangePictureInput, ChangePictureInput,
ConfirmEmailInput, ConfirmEmailInput,
ProfileDto, ProfileDto,
SendChangePhoneNumberCodeInput,
SendEmailConfirmCodeDto, SendEmailConfirmCodeDto,
TwoFactorEnabledDto, TwoFactorEnabledDto,
UpdateProfileDto, UpdateProfileDto,

4
apps/vben5/packages/@abp/settings/src/components/settings/SettingForm.vue

@ -78,7 +78,7 @@ async function onSubmit() {
} }
function onCheckChange(setting: SettingDetail) { function onCheckChange(setting: SettingDetail) {
setting.value = setting.value === 'true' ? 'false' : 'true'; setting.value = setting.value?.toLowerCase() === 'true' ? 'false' : 'true';
onValueChange(setting); onValueChange(setting);
} }
@ -202,7 +202,7 @@ onMounted(onGet);
</Select> </Select>
<Checkbox <Checkbox
v-if="detail.valueType === ValueType.Boolean" v-if="detail.valueType === ValueType.Boolean"
:checked="detail.value === 'true'" :checked="detail.value?.toLowerCase() === 'true'"
@change="onCheckChange(detail)" @change="onCheckChange(detail)"
> >
{{ detail.displayName }} {{ detail.displayName }}

Loading…
Cancel
Save