wip: 🚧 个人中心添加修改密码、邮箱和手机号
This commit is contained in:
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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,85 +112,148 @@
|
|||||||
</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">
|
已绑定手机号:{{ userProfile.mobile }}
|
||||||
已绑定手机号:{{ userProfile.mobile }}
|
</span>
|
||||||
</span>
|
<span v-else>未绑定手机</span>
|
||||||
<span v-else>未绑定手机</span>
|
<el-button
|
||||||
<el-button
|
type="primary"
|
||||||
type="primary"
|
plain
|
||||||
plain
|
size="small"
|
||||||
size="small"
|
@click="() => handleOpenDialog(DialogType.MOBILE)"
|
||||||
@click="handleOpenDialog"
|
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(DialogType.MOBILE)"
|
||||||
@click="handleOpenDialog"
|
class="ml-5"
|
||||||
class="ml-5"
|
v-else
|
||||||
v-else
|
>
|
||||||
>
|
绑定
|
||||||
绑定
|
</el-button>
|
||||||
</el-button>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
<!-- 绑定邮箱 -->
|
||||||
</el-row>
|
<div class="mt-5">
|
||||||
|
<div class="font-bold">绑定邮箱</div>
|
||||||
<el-row class="mt-5">
|
<div class="text-14px mt-2">
|
||||||
<el-col :span="16">
|
<span v-if="userProfile.email">
|
||||||
<div class="font-bold">绑定邮箱</div>
|
已绑定邮箱:{{ userProfile.email }}
|
||||||
<div class="text-14px mt-2">
|
</span>
|
||||||
可用邮箱加密码登录,可通过邮箱找回密码
|
<span v-else>未绑定邮箱</span>
|
||||||
</div>
|
<el-button
|
||||||
</el-col>
|
type="primary"
|
||||||
<el-col :span="8">
|
plain
|
||||||
<div class="flex-y-center h-full">
|
size="small"
|
||||||
<el-button
|
@click="() => handleOpenDialog(DialogType.EMAIL)"
|
||||||
type="primary"
|
class="ml-5"
|
||||||
plain
|
v-if="userProfile.email"
|
||||||
size="small"
|
>
|
||||||
@click="handleOpenDialog"
|
更换
|
||||||
>
|
</el-button>
|
||||||
绑定
|
<el-button
|
||||||
</el-button>
|
type="primary"
|
||||||
</div>
|
plain
|
||||||
</el-col>
|
size="small"
|
||||||
</el-row>
|
@click="() => handleOpenDialog(DialogType.EMAIL)"
|
||||||
|
class="ml-5"
|
||||||
|
v-else
|
||||||
|
>
|
||||||
|
绑定
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</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;
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user