feat(profile): implement independent email update dialog to prevent accidental password resets during partial updates

This commit is contained in:
DXC
2026-04-17 12:48:30 +08:00
parent d651d19e86
commit 772f3f45f4
3 changed files with 140 additions and 2 deletions

View File

@ -4,7 +4,7 @@ import { useRouter, useRoute } from 'vue-router'
import { ElMessageBox, ElMessage } from 'element-plus'
import { InfoFilled, SwitchButton, UserFilled, Lock, User, ArrowDown } from '@element-plus/icons-vue'
import { useUserStore } from '@/stores/user'
import { getMyProfile, changeMyPassword } from '@/api/auth'
import { getMyProfile, changeMyPassword, updateMyEmail } from '@/api/auth'
const router = useRouter()
const route = useRoute()
@ -34,13 +34,15 @@ interface ProfileData {
username: string
display_name: string
department: string
email: string
}
const profileForm = ref<ProfileData>({
id: 0,
username: '',
display_name: '',
department: ''
department: '',
email: ''
})
const passwordForm = ref({
@ -50,6 +52,62 @@ const passwordForm = ref({
const passwordFormRef = ref()
// ================================================================
// 绑定/修改邮箱
// ================================================================
const emailDialogVisible = ref(false)
const emailLoading = ref(false)
const emailFormRef = ref()
interface EmailForm {
email: string
}
const emailForm = ref<EmailForm>({
email: ''
})
const emailRules = {
email: [
{ required: true, message: '请输入邮箱地址', trigger: 'blur' },
{ type: 'email', message: '请输入正确的邮箱格式', trigger: ['blur', 'change'] }
]
}
// 打开邮箱弹窗
const openEmailDialog = () => {
emailForm.value.email = profileForm.value.email || ''
emailDialogVisible.value = true
}
// 提交邮箱修改
const submitEmailUpdate = async () => {
const formRef = emailFormRef.value
if (!formRef) return
await formRef.validate(async (valid: boolean) => {
if (valid) {
emailLoading.value = true
try {
await updateMyEmail({ email: emailForm.value.email })
ElMessage.success('邮箱绑定成功')
emailDialogVisible.value = false
// 刷新个人资料
openProfileDialog()
} catch (e: any) {
ElMessage.error(e?.response?.data?.msg || e?.message || '绑定失败')
} finally {
emailLoading.value = false
}
}
})
}
// 重置表单
const resetEmailForm = () => {
emailFormRef.value?.resetFields()
}
// 打开个人中心弹窗
const openProfileDialog = async () => {
profileDialogVisible.value = true
@ -210,6 +268,12 @@ const handleLogout = () => {
<!-- 严格脱敏系统角色字段已移除不在此展示 -->
</div>
<div style="margin: 16px 0; text-align: center;">
<el-button type="primary" plain @click="openEmailDialog">
绑定/修改邮箱
</el-button>
</div>
<el-divider>
<el-icon><Lock /></el-icon> 修改密码
</el-divider>
@ -260,6 +324,19 @@ const handleLogout = () => {
</div>
</template>
</el-dialog>
<!-- 绑定/修改邮箱弹窗 -->
<el-dialog v-model="emailDialogVisible" title="绑定/修改邮箱" width="400px" @close="resetEmailForm">
<el-form :model="emailForm" :rules="emailRules" ref="emailFormRef" label-width="80px">
<el-form-item label="新邮箱" prop="email">
<el-input v-model="emailForm.email" placeholder="请输入有效邮箱地址" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="emailDialogVisible = false">取消</el-button>
<el-button type="primary" :loading="emailLoading" @click="submitEmailUpdate">确认</el-button>
</template>
</el-dialog>
</div>
</template>

View File

@ -68,6 +68,15 @@ export function changeMyPassword(data: { new_password: string; confirm_password:
})
}
// 【新增】自我更新邮箱(与密码修改完全隔离)
export function updateMyEmail(data: { email: string }) {
return request({
url: '/v1/auth/me/email',
method: 'put',
data
})
}
// 【新增】批量创建用户
export function batchCreateUser(data: any[]) {
return request({