Преглед на файлове

用户列表新增抽屉效果详细信息

RuoYi преди 2 месеца
родител
ревизия
18983c9d94
променени са 3 файла, в които са добавени 241 реда и са изтрити 1 реда
  1. 52 0
      src/assets/styles/ruoyi.scss
  2. 13 1
      src/views/system/user/index.vue
  3. 176 0
      src/views/system/user/view.vue

+ 52 - 0
src/assets/styles/ruoyi.scss

@@ -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 {

+ 13 - 1
src/views/system/user/index.vue

@@ -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" />
@@ -173,6 +177,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 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"
 
 const router = useRouter()
@@ -365,6 +372,11 @@ function handleSelectionChange(selection) {
   multiple.value = !selection.length
 }
 
+/** 详情按钮操作 */
+function handleViewData(row) {
+  proxy.$refs["userViewRef"].open(row.userId)
+}
+
 /** 导入按钮操作 */
 function handleImport() {
   proxy.$refs["importUserRef"].open()

+ 176 - 0
src/views/system/user/view.vue

@@ -0,0 +1,176 @@
+<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>
+import { getUser } from '@/api/system/user'
+
+const visible = ref(false)
+const loading = ref(false)
+const info = reactive({})
+const postOptions = ref([])
+const roleOptions = ref([])
+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(() => {
+  if (!postOptions.value.length || !info.postIds) return ''
+  return postOptions.value.filter(p => info.postIds?.includes(p.postId)).map(p => p.postName).join('、') || ''
+})
+
+const roleNames = computed(() => {
+  if (!roleOptions.value.length || !info.roleIds) return ''
+  return roleOptions.value.filter(r => info.roleIds?.includes(r.roleId)).map(r => r.roleName).join('、') || ''
+})
+
+const open = async (userId) => {
+  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
+  }
+}
+
+function handleClose() {
+  visible.value = false
+}
+
+defineExpose({
+  open
+})
+</script>