feat(personal-center): 实现个人信息功能
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, nextTick, ref, watch } from 'vue';
|
||||
import { fetchUpdateMyPassword } from '@/service/api';
|
||||
import { useAuthStore } from '@/store/modules/auth';
|
||||
import { useForm, useFormRules } from '@/hooks/common/form';
|
||||
import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';
|
||||
|
||||
defineOptions({ name: 'ProfilePasswordDialog' });
|
||||
|
||||
interface Props {
|
||||
username?: string | null;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
interface Emits {
|
||||
(e: 'submitted'): void;
|
||||
}
|
||||
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
const visible = defineModel<boolean>('visible', {
|
||||
default: false
|
||||
});
|
||||
|
||||
const authStore = useAuthStore();
|
||||
const { formRef, validate } = useForm();
|
||||
const { createRequiredRule, createConfirmPwdRule, patternRules } = useFormRules();
|
||||
|
||||
const submitting = ref(false);
|
||||
|
||||
const model = ref({
|
||||
oldPassword: '',
|
||||
newPassword: '',
|
||||
confirmPassword: ''
|
||||
});
|
||||
|
||||
const confirmDisabled = computed(() => {
|
||||
return (
|
||||
submitting.value ||
|
||||
!model.value.oldPassword.trim() ||
|
||||
!model.value.newPassword.trim() ||
|
||||
!model.value.confirmPassword.trim()
|
||||
);
|
||||
});
|
||||
|
||||
const rules = computed<Record<string, App.Global.FormRule[]>>(() => ({
|
||||
oldPassword: [createRequiredRule('请输入旧密码')],
|
||||
newPassword: [
|
||||
createRequiredRule('请输入新密码'),
|
||||
patternRules.pwd,
|
||||
{
|
||||
asyncValidator: (_rule, value: string) => {
|
||||
if (value.trim() !== '' && value === model.value.oldPassword) {
|
||||
return Promise.reject(new Error('新密码不能与旧密码相同'));
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
},
|
||||
trigger: 'change'
|
||||
}
|
||||
],
|
||||
confirmPassword: createConfirmPwdRule(model.value.newPassword)
|
||||
}));
|
||||
|
||||
const displayUsername = computed(() => props.username?.trim() || '--');
|
||||
|
||||
function initModel() {
|
||||
model.value.oldPassword = '';
|
||||
model.value.newPassword = '';
|
||||
model.value.confirmPassword = '';
|
||||
}
|
||||
|
||||
function closeDialog() {
|
||||
visible.value = false;
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
if (confirmDisabled.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
await validate();
|
||||
|
||||
submitting.value = true;
|
||||
|
||||
const { error } = await fetchUpdateMyPassword({
|
||||
oldPassword: model.value.oldPassword.trim(),
|
||||
newPassword: model.value.newPassword.trim()
|
||||
});
|
||||
|
||||
submitting.value = false;
|
||||
|
||||
if (error) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.$message?.success('密码修改成功,请重新登录');
|
||||
closeDialog();
|
||||
emit('submitted');
|
||||
await authStore.resetStore();
|
||||
}
|
||||
|
||||
watch(visible, async value => {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
initModel();
|
||||
await nextTick();
|
||||
formRef.value?.clearValidate();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BusinessFormDialog
|
||||
v-model="visible"
|
||||
title="修改密码"
|
||||
preset="sm"
|
||||
:confirm-loading="submitting"
|
||||
:confirm-disabled="confirmDisabled"
|
||||
@confirm="handleSubmit"
|
||||
>
|
||||
<ElForm ref="formRef" :model="model" :rules="rules" label-position="top" autocomplete="off">
|
||||
<input class="business-form-autofill-guard" type="text" name="fake-username" autocomplete="username" />
|
||||
<input class="business-form-autofill-guard" type="password" name="fake-password" autocomplete="new-password" />
|
||||
|
||||
<ElRow :gutter="16">
|
||||
<ElCol :span="24">
|
||||
<ElFormItem label="用户名">
|
||||
<ElInput :model-value="displayUsername" disabled />
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="24">
|
||||
<ElAlert title="密码修改后会退出当前登录态,请使用新密码重新登录。" type="info" :closable="false" show-icon />
|
||||
</ElCol>
|
||||
<ElCol :span="24">
|
||||
<ElFormItem label="旧密码" prop="oldPassword">
|
||||
<ElInput
|
||||
v-model="model.oldPassword"
|
||||
show-password
|
||||
autocomplete="current-password"
|
||||
placeholder="请输入旧密码"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="24">
|
||||
<ElFormItem label="新密码" prop="newPassword">
|
||||
<ElInput v-model="model.newPassword" show-password autocomplete="new-password" placeholder="请输入新密码" />
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="24">
|
||||
<ElFormItem label="确认新密码" prop="confirmPassword">
|
||||
<ElInput
|
||||
v-model="model.confirmPassword"
|
||||
show-password
|
||||
autocomplete="new-password"
|
||||
placeholder="请再次输入新密码"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
</ElRow>
|
||||
</ElForm>
|
||||
</BusinessFormDialog>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.business-form-autofill-guard {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border: 0;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user