wip: 🚧 个人中心添加修改密码、邮箱和手机号

This commit is contained in:
ray
2024-08-16 18:22:13 +08:00
parent f1cdb47766
commit 3399e5ecfa
2 changed files with 253 additions and 75 deletions

View File

@@ -276,6 +276,15 @@ export interface UserProfileVO {
/** 邮箱 */ /** 邮箱 */
email?: string; email?: string;
/** 部门名称 */
deptName?: string;
/** 角色名称,多个使用英文逗号(,)分割 */
roleNames?: string;
/** 创建时间 */
createTime?: Date;
} }
/** 个人中心用户信息表单 */ /** 个人中心用户信息表单 */
@@ -309,3 +318,19 @@ export interface PasswordChangeForm {
/** 新密码 */ /** 新密码 */
newPassword?: string; newPassword?: string;
} }
/** 手机绑定表单 */
export interface MobileBindingForm {
/** 新手机号 */
mobile?: string;
/** 验证码 */
code?: string;
}
/** 邮箱绑定表单 */
export interface EmailBindingForm {
/** 新邮箱 */
email?: string;
/** 验证码 */
code?: string;
}

View File

@@ -1,10 +1,12 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-tabs tab-position="left"> <el-tabs tab-position="left">
<!-- 基本设置 Tab Pane -->
<el-tab-pane label="基本设置"> <el-tab-pane label="基本设置">
<div class="w-full"> <div class="w-full">
<el-card class="flex-1"> <el-card class="flex-1">
<div class=""> <div class="">
<!-- 头像和昵称部分 -->
<div class="relative w-100px h-100px flex-center"> <div class="relative w-100px h-100px flex-center">
<el-avatar :src="userProfile.avatar" :size="100" /> <el-avatar :src="userProfile.avatar" :size="100" />
<el-button <el-button
@@ -29,14 +31,15 @@
</el-icon> </el-icon>
</div> </div>
</div> </div>
<!-- 用户信息描述 -->
<el-descriptions :column="1" class="mt-10"> <el-descriptions :column="1" class="mt-10">
<!-- 用户名 -->
<el-descriptions-item> <el-descriptions-item>
<template #label> <template #label>
<el-icon class="align-middle"><User /></el-icon> <el-icon class="align-middle"><User /></el-icon>
用户名 用户名
</template> </template>
{{ userProfile.username }} {{ userProfile.username }}
<el-icon <el-icon
v-if="userProfile.gender === 1" v-if="userProfile.gender === 1"
class="align-middle color-blue" class="align-middle color-blue"
@@ -66,21 +69,32 @@
<el-icon class="align-middle"><User /></el-icon> <el-icon class="align-middle"><User /></el-icon>
部门 部门
</template> </template>
{{ userProfile.email }} {{ userProfile.deptName }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item> <el-descriptions-item>
<template #label> <template #label>
<el-icon class="align-middle"><User /></el-icon> <el-icon class="align-middle"><User /></el-icon>
角色 角色
</template> </template>
{{ userProfile.email }} {{ userProfile.roleNames }}
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<el-icon class="align-middle"><User /></el-icon>
创建日期
</template>
{{ userProfile.createTime }}
</el-descriptions-item> </el-descriptions-item>
</el-descriptions> </el-descriptions>
</el-card> </el-card>
</div> </div>
</el-tab-pane> </el-tab-pane>
<!-- 安全设置 -->
<el-tab-pane label="安全设置"> <el-tab-pane label="安全设置">
<el-card> <el-card>
<!-- 账户密码 -->
<el-row> <el-row>
<el-col :span="16"> <el-col :span="16">
<div class="font-bold">账户密码</div> <div class="font-bold">账户密码</div>
@@ -90,7 +104,7 @@
type="primary" type="primary"
plain plain
size="small" size="small"
@click="handleOpenDialog" @click="() => handleOpenDialog(DialogType.PASSWORD)"
class="ml-5" class="ml-5"
> >
修改 修改
@@ -98,9 +112,8 @@
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
<!-- 绑定手机 -->
<el-row class="mt-5"> <div class="mt-5">
<el-col :span="16">
<div class="font-bold">绑定手机</div> <div class="font-bold">绑定手机</div>
<div class="text-14px mt-2"> <div class="text-14px mt-2">
<span v-if="userProfile.mobile"> <span v-if="userProfile.mobile">
@@ -111,72 +124,136 @@
type="primary" type="primary"
plain plain
size="small" size="small"
@click="handleOpenDialog" @click="() => handleOpenDialog(DialogType.MOBILE)"
class="ml-5" class="ml-5"
v-if="userProfile.mobile" v-if="userProfile.mobile"
> >
修改 更换
</el-button> </el-button>
<el-button <el-button
type="primary" type="primary"
plain plain
size="small" size="small"
@click="handleOpenDialog" @click="() => handleOpenDialog(DialogType.MOBILE)"
class="ml-5" class="ml-5"
v-else v-else
> >
绑定 绑定
</el-button> </el-button>
</div> </div>
</el-col> </div>
</el-row> <!-- 绑定邮箱 -->
<div class="mt-5">
<el-row class="mt-5">
<el-col :span="16">
<div class="font-bold">绑定邮箱</div> <div class="font-bold">绑定邮箱</div>
<div class="text-14px mt-2"> <div class="text-14px mt-2">
可用邮箱加密码登录可通过邮箱找回密码 <span v-if="userProfile.email">
</div> 已绑定邮箱{{ userProfile.email }}
</el-col> </span>
<el-col :span="8"> <span v-else>未绑定邮箱</span>
<div class="flex-y-center h-full">
<el-button <el-button
type="primary" type="primary"
plain plain
size="small" size="small"
@click="handleOpenDialog" @click="() => handleOpenDialog(DialogType.EMAIL)"
class="ml-5"
v-if="userProfile.email"
>
更换
</el-button>
<el-button
type="primary"
plain
size="small"
@click="() => handleOpenDialog(DialogType.EMAIL)"
class="ml-5"
v-else
> >
绑定 绑定
</el-button> </el-button>
</div> </div>
</el-col> </div>
</el-row>
</el-card> </el-card>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
<el-dialog title="修改密码" v-model:visible="dialogVisible"> <!-- 弹窗 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" :width="400">
<el-form <el-form
v-if="dialog.type === DialogType.PASSWORD"
:model="passwordChangeForm" :model="passwordChangeForm"
:rules="passwordChangeRules" :rules="passwordChangeRules"
ref="passwordChangeForm" ref="passwordChangeFormRef"
> >
<el-form-item label="原密码" prop="oldPassword"> <el-form-item label="原密码" prop="oldPassword">
<el-input v-model="passwordChangeForm.oldPassword" show-password /> <el-input
type="password"
v-model="passwordChangeForm.oldPassword"
show-password
/>
</el-form-item> </el-form-item>
<el-form-item label="新密码" prop="newPassword"> <el-form-item label="新密码" prop="newPassword">
<el-input v-model="passwordChangeForm.newPassword" show-password /> <el-input
type="password"
v-model="passwordChangeForm.newPassword"
show-password
/>
</el-form-item> </el-form-item>
<el-form-item label="确认密码" prop="confirmPassword"> <el-form-item label="确认密码" prop="confirmPassword">
<el-input v-model="confirmPassword" show-password /> <el-input type="password" v-model="confirmPassword" show-password />
</el-form-item>
</el-form>
<el-form
v-else-if="dialog.type === DialogType.MOBILE"
:model="mobileBindingForm"
:rules="mobileBindingRules"
ref="mobileBindingFormRef"
>
<el-form-item label="手机号码" prop="mobile">
<el-input v-model="mobileBindingForm.mobile" />
</el-form-item>
<el-form-item>
<el-button
:disabled="mobileCountdown > 0"
@click="handleSendMobileCode"
>
{{
mobileCountdown > 0
? `${mobileCountdown}s后重新发送`
: "发送验证码"
}}
</el-button>
</el-form-item>
<el-form-item label="验证码" prop="code">
<el-input v-model="mobileBindingForm.code" />
</el-form-item>
</el-form>
<el-form
v-else-if="dialog.type === DialogType.EMAIL"
:model="emailBindingForm"
:rules="emailBindingRules"
ref="emailBindingFormRef"
>
<el-form-item label="邮箱" prop="email">
<el-input v-model="emailBindingForm.email" />
</el-form-item>
<el-form-item>
<el-button
:disabled="emailCountdown > 0"
@click="handleSendEmailCode"
>
{{
emailCountdown > 0 ? `${emailCountdown}s后重新发送` : "发送验证码"
}}
</el-button>
</el-form-item>
<el-form-item label="验证码" prop="code">
<el-input v-model="emailBindingForm.code" />
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button> <el-button @click="dialog.visible = false">取消</el-button>
<el-button type="primary" @click="handleChangePassword"> <el-button type="primary" @click="handleSubmit">确定</el-button>
</el-button>
</span> </span>
</template> </template>
</el-dialog> </el-dialog>
@@ -188,6 +265,8 @@ import UserAPI, {
UserProfileVO, UserProfileVO,
UserProfileForm, UserProfileForm,
PasswordChangeForm, PasswordChangeForm,
MobileBindingForm,
EmailBindingForm,
} from "@/api/user"; } from "@/api/user";
import { useUserStore } from "@/store/modules/user"; import { useUserStore } from "@/store/modules/user";
import { Camera } from "@element-plus/icons-vue"; import { Camera } from "@element-plus/icons-vue";
@@ -195,11 +274,30 @@ const userStore = useUserStore();
const userProfile = ref<UserProfileVO>({}); const userProfile = ref<UserProfileVO>({});
const passwordChangeForm = ref<PasswordChangeForm>({}); enum DialogType {
PASSWORD = "password",
MOBILE = "mobile",
EMAIL = "email",
}
const dialog = reactive({
visible: false,
title: "",
type: "" as DialogType, // 修改密码、绑定手机、绑定邮箱
});
const dialogVisible = ref(false);
const confirmPassword = ref(""); const confirmPassword = ref("");
const passwordChangeForm = reactive<PasswordChangeForm>({});
const mobileBindingForm = reactive<MobileBindingForm>({});
const emailBindingForm = reactive<EmailBindingForm>({});
const mobileCountdown = ref(0);
const mobileTimer = ref<NodeJS.Timeout | null>(null);
const emailCountdown = ref(0);
const emailTimer = ref<NodeJS.Timeout | null>(null);
const passwordChangeRules = { const passwordChangeRules = {
oldPassword: [{ required: true, message: "请输入原密码", trigger: "blur" }], oldPassword: [{ required: true, message: "请输入原密码", trigger: "blur" }],
newPassword: [{ required: true, message: "请输入新密码", trigger: "blur" }], newPassword: [{ required: true, message: "请输入新密码", trigger: "blur" }],
@@ -208,18 +306,66 @@ const passwordChangeRules = {
], ],
}; };
const handleOpenDialog = () => { const mobileBindingRules = {
dialogVisible.value = true; mobile: [{ required: true, message: "请输入手机号", trigger: "blur" }],
mobileCode: [{ required: true, message: "请输入验证码", trigger: "blur" }],
}; };
const handleChangePassword = async () => { const emailBindingRules = {
const form = passwordChangeForm.value; email: [{ required: true, message: "请输入邮箱", trigger: "blur" }],
if (form.newPassword !== confirmPassword.value) { emailCode: [{ required: true, message: "请输入验证码", trigger: "blur" }],
};
const handleOpenDialog = (type: DialogType) => {
dialog.type = type;
dialog.visible = true;
};
const handleSendMobileCode = async () => {
if (!mobileBindingForm.value.mobile) {
return; return;
} }
// await UserAPI.sendMobileCode(mobileBindingForm.value.mobile);
await UserAPI.changePassword(form); mobileCountdown.value = 60;
dialogVisible.value = false; mobileTimer.value = setInterval(() => {
if (mobileCountdown.value > 0) {
mobileCountdown.value -= 1;
} else {
clearInterval(mobileTimer.value!);
}
}, 1000);
};
const handleSendEmailCode = async () => {
if (!emailBindingForm.email) {
return;
}
// await UserAPI.sendEmailCode(emailBindingForm.value.email);
emailCountdown.value = 60;
emailTimer.value = setInterval(() => {
if (emailCountdown.value > 0) {
emailCountdown.value -= 1;
} else {
clearInterval(emailTimer.value!);
}
}, 1000);
};
const handleSubmit = async () => {
if (dialog.type === DialogType.PASSWORD) {
if (passwordChangeForm.newPassword !== confirmPassword.value) {
ElMessage.error("两次输入的密码不一致");
return;
}
await UserAPI.changePassword(passwordChangeForm);
} else if (dialog.type === "mobile") {
//await UserAPI.bindMobile(mobileBindingForm.value);
} else if (dialog.type === "email") {
//await UserAPI.bindEmail(emailBindingForm.value);
}
dialog.visible = false;
}; };
const fileInput = ref<HTMLInputElement | null>(null); const fileInput = ref<HTMLInputElement | null>(null);
@@ -238,6 +384,13 @@ const handleFileChange = (event: Event) => {
}; };
onMounted(async () => { onMounted(async () => {
if (mobileTimer.value) {
clearInterval(mobileTimer.value);
}
if (emailTimer.value) {
clearInterval(emailTimer.value);
}
const data = await UserAPI.getProfile(userStore.user.userId); const data = await UserAPI.getProfile(userStore.user.userId);
userProfile.value = data; userProfile.value = data;
}); });