feat(user): 集成 NovaDialog 组件到用户管理页面
- 替换所有原生 n-modal 为自定义 NovaDialog 组件 - 统一用户表单、角色分配、重置密码、头像查看和导入功能的弹框交互 - 使用 novaOpen/novaClose 方法控制所有弹框显示状态 - 保持原有功能和用户体验不变 - 与角色管理页面保持一致的弹框风格 - 提升整体页面的一致性和可维护性
This commit is contained in:
parent
7577077c26
commit
ebffbd78bc
@ -2,6 +2,7 @@
|
||||
import { h, nextTick, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||
import type { DataTableColumns, FormInst } from 'naive-ui'
|
||||
import { NButton, NCheckbox, NDropdown, NIcon, NPopconfirm, NProgress, NSpace, NSwitch, NTag, NUpload, NUploadDragger } from 'naive-ui'
|
||||
import NovaDialog from '@/components/common/NovaDialog.vue'
|
||||
import {
|
||||
addUser,
|
||||
batchDeleteUsers,
|
||||
@ -29,7 +30,6 @@ import { coiMsgBox, coiMsgError, coiMsgInfo, coiMsgSuccess, coiMsgWarning } from
|
||||
// 响应式数据
|
||||
const loading = ref(false)
|
||||
const tableData = ref<UserVo[]>([])
|
||||
const showModal = ref(false)
|
||||
const modalTitle = ref('新增用户')
|
||||
const formRef = ref<FormInst | null>(null)
|
||||
const searchFormRef = ref<FormInst | null>(null)
|
||||
@ -38,8 +38,14 @@ const currentUser = ref<UserVo | null>(null)
|
||||
const selectedRows = ref<UserVo[]>([])
|
||||
const roleOptions = ref<RoleVo[]>([])
|
||||
|
||||
// 弹框引用
|
||||
const userDialogRef = ref()
|
||||
const roleDialogRef = ref()
|
||||
const resetPwdDialogRef = ref()
|
||||
const avatarDialogRef = ref()
|
||||
const importDialogRef = ref()
|
||||
|
||||
// 角色分配相关
|
||||
const showRoleModal = ref(false)
|
||||
const roleModalTitle = ref('分配角色')
|
||||
const currentAssignUser = ref<UserVo | null>(null)
|
||||
const availableRoles = ref<{ label: string, value: number }[]>([])
|
||||
@ -47,7 +53,6 @@ const selectedRoleIds = ref<number[]>([])
|
||||
const roleLoading = ref(false)
|
||||
|
||||
// 重置密码相关
|
||||
const showResetPwdModal = ref(false)
|
||||
const resetPwdFormRef = ref<FormInst | null>(null)
|
||||
const currentResetUser = ref<UserVo | null>(null)
|
||||
const resetPwdForm = ref({
|
||||
@ -56,12 +61,10 @@ const resetPwdForm = ref({
|
||||
})
|
||||
|
||||
// 头像查看相关
|
||||
const showAvatarModal = ref(false)
|
||||
const currentAvatar = ref('')
|
||||
const currentAvatarUser = ref<UserVo | null>(null)
|
||||
|
||||
// 导入相关
|
||||
const showImportModal = ref(false)
|
||||
const importLoading = ref(false)
|
||||
const selectedFile = ref<File | null>(null)
|
||||
const updateSupport = ref(false)
|
||||
@ -488,7 +491,7 @@ function handleAdd() {
|
||||
remark: '',
|
||||
roleIds: [],
|
||||
}
|
||||
showModal.value = true
|
||||
userDialogRef.value?.novaOpen()
|
||||
}
|
||||
|
||||
// 编辑用户
|
||||
@ -509,7 +512,7 @@ function handleEdit(user: UserVo) {
|
||||
remark: user.remark || '',
|
||||
roleIds: user.roleIds || [],
|
||||
}
|
||||
showModal.value = true
|
||||
userDialogRef.value?.novaOpen()
|
||||
}
|
||||
|
||||
// 删除用户
|
||||
@ -595,7 +598,7 @@ function handleResetPassword(user: UserVo) {
|
||||
newPassword: '',
|
||||
confirmPassword: '',
|
||||
}
|
||||
showResetPwdModal.value = true
|
||||
resetPwdDialogRef.value?.novaOpen()
|
||||
}
|
||||
|
||||
// 执行重置密码
|
||||
@ -619,7 +622,7 @@ async function handleConfirmResetPassword() {
|
||||
const { isSuccess } = await resetUserPassword(currentResetUser.value.userId, resetPwdForm.value.newPassword)
|
||||
if (isSuccess) {
|
||||
coiMsgSuccess(`用户「${currentResetUser.value.userName}」密码重置成功`)
|
||||
showResetPwdModal.value = false
|
||||
resetPwdDialogRef.value?.novaClose()
|
||||
}
|
||||
else {
|
||||
coiMsgError('重置密码失败,请稍后重试')
|
||||
@ -633,7 +636,7 @@ async function handleConfirmResetPassword() {
|
||||
|
||||
// 取消重置密码
|
||||
function handleCancelResetPassword() {
|
||||
showResetPwdModal.value = false
|
||||
resetPwdDialogRef.value?.novaClose()
|
||||
resetPwdForm.value = {
|
||||
newPassword: '',
|
||||
confirmPassword: '',
|
||||
@ -679,12 +682,12 @@ function handleViewAvatar(user: UserVo) {
|
||||
currentAvatar.value = blobUrl
|
||||
createdBlobUrls.value.push(blobUrl)
|
||||
}
|
||||
showAvatarModal.value = true
|
||||
avatarDialogRef.value?.novaOpen()
|
||||
}
|
||||
|
||||
// 关闭头像查看
|
||||
function handleCloseAvatar() {
|
||||
showAvatarModal.value = false
|
||||
avatarDialogRef.value?.novaClose()
|
||||
// 如果是生成的默认头像,释放URL
|
||||
if (currentAvatar.value.startsWith('blob:')) {
|
||||
URL.revokeObjectURL(currentAvatar.value)
|
||||
@ -826,7 +829,7 @@ function handleImport() {
|
||||
selectedFile.value = null
|
||||
updateSupport.value = false
|
||||
uploadProgress.value = 0
|
||||
showImportModal.value = true
|
||||
importDialogRef.value?.novaOpen()
|
||||
}
|
||||
|
||||
// 文件选择处理
|
||||
@ -891,7 +894,7 @@ async function handleConfirmImport() {
|
||||
)
|
||||
|
||||
// 关闭模态框并刷新列表
|
||||
showImportModal.value = false
|
||||
importDialogRef.value?.novaClose()
|
||||
await getUserList()
|
||||
}
|
||||
else {
|
||||
@ -916,7 +919,7 @@ async function handleConfirmImport() {
|
||||
|
||||
// 取消导入
|
||||
function handleCancelImport() {
|
||||
showImportModal.value = false
|
||||
importDialogRef.value?.novaClose()
|
||||
selectedFile.value = null
|
||||
updateSupport.value = false
|
||||
uploadProgress.value = 0
|
||||
@ -954,7 +957,7 @@ async function handleAssignRole(user: UserVo) {
|
||||
|
||||
// 预选用户当前角色(使用后端返回的用户角色ID)
|
||||
selectedRoleIds.value = userRoleIds
|
||||
showRoleModal.value = true
|
||||
roleDialogRef.value?.novaOpen()
|
||||
}
|
||||
else {
|
||||
coiMsgInfo('当前系统没有可分配的角色')
|
||||
@ -992,7 +995,7 @@ async function handleConfirmAssignRole() {
|
||||
|
||||
if (response.isSuccess) {
|
||||
coiMsgSuccess('角色分配成功')
|
||||
showRoleModal.value = false
|
||||
roleDialogRef.value?.novaClose()
|
||||
|
||||
// 更新当前用户的角色信息
|
||||
if (currentAssignUser.value) {
|
||||
@ -1016,7 +1019,7 @@ async function handleConfirmAssignRole() {
|
||||
|
||||
// 取消分配角色
|
||||
function handleCancelAssignRole() {
|
||||
showRoleModal.value = false
|
||||
roleDialogRef.value?.novaClose()
|
||||
currentAssignUser.value = null
|
||||
selectedRoleIds.value = []
|
||||
availableRoles.value = []
|
||||
@ -1059,7 +1062,7 @@ async function handleSubmit() {
|
||||
|
||||
if (isSuccess) {
|
||||
coiMsgSuccess(isEdit.value ? '用户信息更新成功' : '用户创建成功')
|
||||
showModal.value = false
|
||||
userDialogRef.value?.novaClose()
|
||||
await getUserList()
|
||||
}
|
||||
else {
|
||||
@ -1074,7 +1077,7 @@ async function handleSubmit() {
|
||||
|
||||
// 取消操作
|
||||
function handleCancel() {
|
||||
showModal.value = false
|
||||
userDialogRef.value?.novaClose()
|
||||
}
|
||||
|
||||
// 组件挂载时获取数据
|
||||
@ -1339,15 +1342,19 @@ onBeforeUnmount(() => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 用户表单模态框 -->
|
||||
<n-modal
|
||||
v-model:show="showModal"
|
||||
<!-- 用户表单弹框 -->
|
||||
<NovaDialog
|
||||
ref="userDialogRef"
|
||||
:title="modalTitle"
|
||||
preset="card"
|
||||
:style="{ width: '800px' }"
|
||||
:mask-closable="false"
|
||||
class="user-modal"
|
||||
:width="800"
|
||||
height="auto"
|
||||
confirm-text="确定"
|
||||
cancel-text="取消"
|
||||
@nova-confirm="handleSubmit"
|
||||
@nova-cancel="handleCancel"
|
||||
>
|
||||
<template #content>
|
||||
<div class="px-3 py-2">
|
||||
<n-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
@ -1470,29 +1477,23 @@ onBeforeUnmount(() => {
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
|
||||
<template #footer>
|
||||
<div class="flex justify-end gap-3">
|
||||
<NButton @click="handleCancel">
|
||||
取消
|
||||
</NButton>
|
||||
<NButton type="primary" @click="handleSubmit">
|
||||
确定
|
||||
</NButton>
|
||||
</div>
|
||||
</template>
|
||||
</n-modal>
|
||||
</NovaDialog>
|
||||
|
||||
<!-- 角色分配模态框 -->
|
||||
<n-modal
|
||||
v-model:show="showRoleModal"
|
||||
<!-- 角色分配弹框 -->
|
||||
<NovaDialog
|
||||
ref="roleDialogRef"
|
||||
:title="roleModalTitle"
|
||||
preset="card"
|
||||
:style="{ width: '600px' }"
|
||||
:mask-closable="false"
|
||||
class="role-assign-modal"
|
||||
:width="600"
|
||||
height="auto"
|
||||
confirm-text="确定"
|
||||
cancel-text="取消"
|
||||
@nova-confirm="handleConfirmAssignRole"
|
||||
@nova-cancel="handleCancelAssignRole"
|
||||
>
|
||||
<div class="space-y-4">
|
||||
<template #content>
|
||||
<div class="p-3 space-y-4">
|
||||
<div class="bg-gray-50 p-4 rounded-lg">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-10 h-10 rounded-full bg-gradient-to-r from-blue-400 to-purple-500 flex items-center justify-center text-white text-sm font-bold">
|
||||
@ -1537,37 +1538,22 @@ onBeforeUnmount(() => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<div class="flex justify-end gap-3">
|
||||
<NButton
|
||||
:disabled="roleLoading"
|
||||
@click="handleCancelAssignRole"
|
||||
>
|
||||
取消
|
||||
</NButton>
|
||||
<NButton
|
||||
type="primary"
|
||||
:loading="roleLoading"
|
||||
:disabled="availableRoles.length === 0"
|
||||
@click="handleConfirmAssignRole"
|
||||
>
|
||||
确定
|
||||
</NButton>
|
||||
</div>
|
||||
</template>
|
||||
</n-modal>
|
||||
</NovaDialog>
|
||||
|
||||
<!-- 重置密码模态框 -->
|
||||
<n-modal
|
||||
v-model:show="showResetPwdModal"
|
||||
<!-- 重置密码弹框 -->
|
||||
<NovaDialog
|
||||
ref="resetPwdDialogRef"
|
||||
title="重置用户密码"
|
||||
preset="card"
|
||||
:style="{ width: '500px' }"
|
||||
:mask-closable="false"
|
||||
class="reset-pwd-modal"
|
||||
:width="500"
|
||||
height="auto"
|
||||
confirm-text="确认重置"
|
||||
cancel-text="取消"
|
||||
@nova-confirm="handleConfirmResetPassword"
|
||||
@nova-cancel="handleCancelResetPassword"
|
||||
>
|
||||
<div class="space-y-4">
|
||||
<template #content>
|
||||
<div class="p-3 space-y-4">
|
||||
<div class="bg-gray-50 p-4 rounded-lg">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-10 h-10 rounded-full bg-gradient-to-r from-orange-400 to-red-500 flex items-center justify-center text-white text-sm font-bold">
|
||||
@ -1629,27 +1615,17 @@ onBeforeUnmount(() => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<div class="flex justify-end gap-3">
|
||||
<NButton @click="handleCancelResetPassword">
|
||||
取消
|
||||
</NButton>
|
||||
<NButton type="primary" @click="handleConfirmResetPassword">
|
||||
确认重置
|
||||
</NButton>
|
||||
</div>
|
||||
</template>
|
||||
</n-modal>
|
||||
</NovaDialog>
|
||||
|
||||
<!-- 头像查看模态框 -->
|
||||
<n-modal
|
||||
v-model:show="showAvatarModal"
|
||||
preset="card"
|
||||
:style="{ width: '600px' }"
|
||||
:mask-closable="true"
|
||||
class="avatar-modal"
|
||||
@close="handleCloseAvatar"
|
||||
<!-- 头像查看弹框 -->
|
||||
<NovaDialog
|
||||
ref="avatarDialogRef"
|
||||
:width="600"
|
||||
height="auto"
|
||||
cancel-text="关闭"
|
||||
:show-confirm="false"
|
||||
@nova-cancel="handleCloseAvatar"
|
||||
>
|
||||
<template #header>
|
||||
<div class="flex items-center gap-3">
|
||||
@ -1663,7 +1639,8 @@ onBeforeUnmount(() => {
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="flex flex-col items-center space-y-4">
|
||||
<template #content>
|
||||
<div class="flex flex-col items-center space-y-4 p-3">
|
||||
<div class="relative">
|
||||
<img
|
||||
:src="currentAvatar"
|
||||
@ -1689,26 +1666,22 @@ onBeforeUnmount(() => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<div class="flex justify-end">
|
||||
<NButton @click="handleCloseAvatar">
|
||||
关闭
|
||||
</NButton>
|
||||
</div>
|
||||
</template>
|
||||
</n-modal>
|
||||
</NovaDialog>
|
||||
|
||||
<!-- 导入用户模态框 -->
|
||||
<n-modal
|
||||
v-model:show="showImportModal"
|
||||
<!-- 导入用户弹框 -->
|
||||
<NovaDialog
|
||||
ref="importDialogRef"
|
||||
title="导入用户数据"
|
||||
preset="card"
|
||||
:style="{ width: '600px' }"
|
||||
:mask-closable="false"
|
||||
class="import-modal"
|
||||
:width="600"
|
||||
height="auto"
|
||||
confirm-text="开始导入"
|
||||
cancel-text="取消"
|
||||
@nova-confirm="handleConfirmImport"
|
||||
@nova-cancel="handleCancelImport"
|
||||
>
|
||||
<div class="space-y-6">
|
||||
<template #content>
|
||||
<div class="p-3 space-y-6">
|
||||
<!-- 文件上传区域 -->
|
||||
<div>
|
||||
<h4 class="text-sm font-medium text-gray-700 mb-3">
|
||||
@ -1782,10 +1755,9 @@ onBeforeUnmount(() => {
|
||||
<li>• 用户状态默认为"启用"</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<div class="flex justify-between">
|
||||
<!-- 下载模板按钮 -->
|
||||
<div class="flex justify-start">
|
||||
<NButton
|
||||
:disabled="importLoading"
|
||||
@click="handleDownloadTemplate"
|
||||
@ -1795,23 +1767,10 @@ onBeforeUnmount(() => {
|
||||
</template>
|
||||
下载模板
|
||||
</NButton>
|
||||
|
||||
<div class="flex gap-3">
|
||||
<NButton :disabled="importLoading" @click="handleCancelImport">
|
||||
取消
|
||||
</NButton>
|
||||
<NButton
|
||||
type="primary"
|
||||
:loading="importLoading"
|
||||
:disabled="!selectedFile"
|
||||
@click="handleConfirmImport"
|
||||
>
|
||||
开始导入
|
||||
</NButton>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</n-modal>
|
||||
</NovaDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user