mirror of
https://gitcode.com/yangzongzhuan/RuoYi-Vue3.git
synced 2026-05-22 19:08:37 +00:00
用户列表新增抽屉效果详细信息
This commit is contained in:
@@ -241,6 +241,58 @@
|
||||
}
|
||||
|
||||
/** 详细卡片样式 */
|
||||
.detail-drawer {
|
||||
.el-drawer__body {
|
||||
padding: 0;
|
||||
}
|
||||
.el-drawer__header {
|
||||
margin-bottom: 6px;
|
||||
padding: 8px 12px 6px;
|
||||
font-size: 15px;
|
||||
color: #303133;
|
||||
background: #f8f8f8;
|
||||
}
|
||||
.section-header {
|
||||
font-size: 15px;
|
||||
color: #6379bb;
|
||||
border-bottom: 1px solid #ddd;
|
||||
margin: 12px 0 16px 0;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
.drawer-content {
|
||||
padding: 0 20px 20px 20px;
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
padding: 8px 0;
|
||||
min-height: 40px;
|
||||
}
|
||||
.info-label {
|
||||
flex-shrink: 0;
|
||||
width: 200px;
|
||||
color: #606266;
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
padding-top: 4px;
|
||||
text-align: right;
|
||||
margin-right: 14px;
|
||||
}
|
||||
.info-value {
|
||||
flex: 1;
|
||||
color: #303133;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
line-height: 1.6;
|
||||
word-break: break-all;
|
||||
padding-top: 4px;
|
||||
min-height: 1.6em;
|
||||
&.plaintext {
|
||||
border-bottom: 1px dashed #dde1e6;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.detail-wrap { padding: 0 4px; }
|
||||
|
||||
.detail-card {
|
||||
|
||||
@@ -251,14 +251,13 @@ function toggleFullscreen() {
|
||||
const mainContainer = document.querySelector('.main-container') as HTMLElement | null
|
||||
const navbar = document.querySelector('.navbar') as HTMLElement | null
|
||||
const sidebar = document.querySelector('.sidebar-container') as HTMLElement | null
|
||||
const tagsActionBtn = document.querySelector<HTMLElement>('.tags-action-btn')
|
||||
if (!mainContainer) return
|
||||
|
||||
if (!isFullscreen.value) {
|
||||
mainContainer.classList.add('fullscreen-mode')
|
||||
document.body.style.overflow = 'hidden'
|
||||
const elementsToHide = [{ el: navbar, originalDisplay: navbar?.style.display || '' }, { el: sidebar, originalDisplay: sidebar?.style.display || '' }]
|
||||
elementsToHide.forEach((item :any) => {
|
||||
elementsToHide.forEach(item => {
|
||||
if (item.el && item.el.style.display !== 'none') {
|
||||
item.originalDisplay = item.el.style.display
|
||||
item.el.style.display = 'none'
|
||||
@@ -269,13 +268,14 @@ function toggleFullscreen() {
|
||||
} else {
|
||||
mainContainer.classList.remove('fullscreen-mode')
|
||||
document.body.style.overflow = ''
|
||||
hiddenElements.value.forEach((item :any) => {
|
||||
hiddenElements.value.forEach((item: any) => {
|
||||
if (item.el) {
|
||||
item.el.style.display = item.originalDisplay
|
||||
}
|
||||
})
|
||||
hiddenElements.value = ref<any[]>([])
|
||||
tagsActionBtn?.blur()
|
||||
hiddenElements.value = []
|
||||
const tagsBtn = document.querySelector('.tags-action-btn') as HTMLElement | null
|
||||
tagsBtn?.blur()
|
||||
isFullscreen.value = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,11 @@
|
||||
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="50" align="center" />
|
||||
<el-table-column label="用户编号" align="center" key="userId" prop="userId" v-if="columns.userId.visible" />
|
||||
<el-table-column label="用户名称" align="center" key="userName" prop="userName" v-if="columns.userName.visible" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="用户名称" align="center" key="userName" v-if="columns.userName.visible" :show-overflow-tooltip="true">
|
||||
<template #default="scope">
|
||||
<a class="link-type" style="cursor:pointer" @click="handleViewData(scope.row)">{{ scope.row.userName }}</a>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="用户昵称" align="center" key="nickName" prop="nickName" v-if="columns.nickName.visible" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="部门" align="center" key="deptName" prop="dept.deptName" v-if="columns.deptName.visible" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="手机号码" align="center" key="phonenumber" prop="phonenumber" v-if="columns.phonenumber.visible" width="120" />
|
||||
@@ -172,6 +176,8 @@
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 用户详情抽屉 -->
|
||||
<user-view-drawer ref="userViewRef" />
|
||||
<!-- 用户导入对话框 -->
|
||||
<excel-import-dialog ref="importUserRef" title="用户导入" action="/system/user/importData" template-action="/system/user/importTemplate" template-file-name="user_template" update-support-label="是否更新已经存在的用户数据" @success="getList" />
|
||||
</div>
|
||||
@@ -182,6 +188,7 @@ import { getToken } from "@/utils/auth"
|
||||
import useAppStore from '@/store/modules/app'
|
||||
import TreePanel from "@/components/TreePanel"
|
||||
import ExcelImportDialog from "@/components/ExcelImportDialog"
|
||||
import UserViewDrawer from "./view"
|
||||
import { changeUserStatus, listUser, resetUserPwd, delUser, getUser, updateUser, addUser, deptTreeSelect } from "@/api/system/user"
|
||||
import type { SysUser, UserQueryParams, UserFormDataResult } from '@/types/api/system/user'
|
||||
import type { SysRole } from '@/types/api/system/role'
|
||||
@@ -370,6 +377,11 @@ function handleSelectionChange(selection: SysUser[]) {
|
||||
multiple.value = !selection.length
|
||||
}
|
||||
|
||||
/** 详情按钮操作 */
|
||||
function handleViewData(row: SysUser) {
|
||||
proxy.$refs["userViewRef"].open(row.userId)
|
||||
}
|
||||
|
||||
/** 导入按钮操作 */
|
||||
function handleImport() {
|
||||
proxy.$refs["importUserRef"].open()
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
<template>
|
||||
<el-drawer title="用户信息详情" v-model="visible" direction="rtl" size="68%" append-to-body :before-close="handleClose" class="detail-drawer">
|
||||
<div v-loading="loading" class="drawer-content">
|
||||
<!-- 基本信息 -->
|
||||
<h4 class="section-header">基本信息</h4>
|
||||
<el-row :gutter="20" class="mb8">
|
||||
<el-col :span="12">
|
||||
<div class="info-item">
|
||||
<label class="info-label">用户名称:</label>
|
||||
<span class="info-value plaintext">{{ info.nickName }}</span>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="info-item">
|
||||
<label class="info-label">归属部门:</label>
|
||||
<span class="info-value plaintext">{{ (info.dept && info.dept.deptName) }}</span>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20" class="mb8">
|
||||
<el-col :span="12">
|
||||
<div class="info-item">
|
||||
<label class="info-label">手机号码:</label>
|
||||
<span class="info-value plaintext">{{ info.phonenumber }}</span>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="info-item">
|
||||
<label class="info-label">邮箱:</label>
|
||||
<span class="info-value plaintext">{{ info.email }}</span>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20" class="mb8">
|
||||
<el-col :span="12">
|
||||
<div class="info-item">
|
||||
<label class="info-label">登录账号:</label>
|
||||
<span class="info-value plaintext">{{ info.userName }}</span>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="info-item">
|
||||
<label class="info-label">用户状态:</label>
|
||||
<span class="info-value plaintext">
|
||||
<el-tag size="small" :type="info.status === '0' ? 'success' : 'danger'">{{ info.status === '0' ? '正常' : '停用' }}</el-tag>
|
||||
</span>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20" class="mb8">
|
||||
<el-col :span="12">
|
||||
<div class="info-item">
|
||||
<label class="info-label">岗位:</label>
|
||||
<span class="info-value plaintext">{{ postNames || '无岗位' }}</span>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="info-item">
|
||||
<label class="info-label">用户性别:</label>
|
||||
<span class="info-value plaintext">{{ sexLabel }}</span>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20" class="mb8">
|
||||
<el-col :span="24">
|
||||
<div class="info-item full-width">
|
||||
<label class="info-label">角色:</label>
|
||||
<span class="info-value plaintext">{{ roleNames || '无角色' }}</span>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- 其他信息 -->
|
||||
<h4 class="section-header">其他信息</h4>
|
||||
<el-row :gutter="20" class="mb8">
|
||||
<el-col :span="12">
|
||||
<div class="info-item">
|
||||
<label class="info-label">创建者:</label>
|
||||
<span class="info-value plaintext">{{ info.createBy }}</span>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="info-item">
|
||||
<label class="info-label">创建时间:</label>
|
||||
<span class="info-value plaintext">{{ info.createTime }}</span>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20" class="mb8">
|
||||
<el-col :span="12">
|
||||
<div class="info-item">
|
||||
<label class="info-label">更新者:</label>
|
||||
<span class="info-value plaintext">{{ info.updateBy }}</span>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="info-item">
|
||||
<label class="info-label">更新时间:</label>
|
||||
<span class="info-value plaintext">{{ info.updateTime }}</span>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20" class="mb8">
|
||||
<el-col :span="12">
|
||||
<div class="info-item">
|
||||
<label class="info-label">最后登录IP:</label>
|
||||
<span class="info-value plaintext">{{ info.loginIp }}</span>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="info-item">
|
||||
<label class="info-label">最后登录时间:</label>
|
||||
<span class="info-value plaintext">{{ info.loginDate }}</span>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20" class="mb8">
|
||||
<el-col :span="24">
|
||||
<div class="info-item full-width">
|
||||
<label class="info-label">备注:</label>
|
||||
<span class="info-value plaintext">{{ info.remark }}</span>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getUser } from '@/api/system/user'
|
||||
import type { SysUser } from '@/types/api/system/user'
|
||||
import type { SysRole } from '@/types/api/system/role'
|
||||
import type { SysPost } from '@/types/api/system/post'
|
||||
|
||||
const visible = ref<boolean>(false)
|
||||
const loading = ref<boolean>(false)
|
||||
const info = reactive<SysUser>({})
|
||||
const postOptions = ref<SysPost[]>([])
|
||||
const roleOptions = ref<SysRole[]>([])
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const { sys_user_sex } = proxy.useDict("sys_user_sex")
|
||||
|
||||
const sexLabel = computed(() => proxy.selectDictLabel(sys_user_sex.value, info.sex) || '-')
|
||||
|
||||
const postNames = computed<string>(() => {
|
||||
if (!postOptions.value.length || !info.postIds) return ''
|
||||
return postOptions.value.filter((p: SysPost) => info.postIds?.includes(p.postId)).map((p: SysPost) => p.postName).join('、') || ''
|
||||
})
|
||||
|
||||
const roleNames = computed<string>(() => {
|
||||
if (!roleOptions.value.length || !info.roleIds) return ''
|
||||
return roleOptions.value.filter((r: SysRole) => info.roleIds?.includes(r.roleId)).map((r: SysRole) => r.roleName).join('、') || ''
|
||||
})
|
||||
|
||||
const open = async (userId: number): Promise<void> => {
|
||||
visible.value = true
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await getUser(userId)
|
||||
Object.assign(info, res.data || {})
|
||||
postOptions.value = res.posts || []
|
||||
roleOptions.value = res.roles || []
|
||||
info.postIds = res.postIds || []
|
||||
info.roleIds = res.roleIds || []
|
||||
} catch (error) {
|
||||
console.error('获取用户信息失败:', error)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleClose = (): void => {
|
||||
visible.value = false
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open
|
||||
})
|
||||
</script>
|
||||
Reference in New Issue
Block a user