Browse Source

REVIEW 用户管理(列表)

YunaiV 2 năm trước cách đây
mục cha
commit
643b387367

+ 3 - 18
src/api/system/user/index.ts

@@ -17,23 +17,8 @@ export interface UserVO {
   createTime: Date
 }
 
-export interface UserPageReqVO extends PageParam {
-  deptId?: number
-  username?: string
-  mobile?: string
-  status?: number
-  createTime?: Date[]
-}
-
-export interface UserExportReqVO {
-  code?: string
-  name?: string
-  status?: number
-  createTime?: Date[]
-}
-
 // 查询用户管理列表
-export const getUserPageApi = (params: UserPageReqVO) => {
+export const getUserPage = (params: PageParam) => {
   return request.get({ url: '/system/user/page', params })
 }
 
@@ -53,12 +38,12 @@ export const updateUserApi = (data: UserVO | Recordable) => {
 }
 
 // 删除用户
-export const deleteUserApi = (id: number) => {
+export const deleteUser = (id: number) => {
   return request.delete({ url: '/system/user/delete?id=' + id })
 }
 
 // 导出用户
-export const exportUserApi = (params: UserExportReqVO) => {
+export const exportUser = (params) => {
   return request.download({ url: '/system/user/export', params })
 }
 

+ 1 - 1
src/views/system/tenantPackage/index.vue

@@ -112,7 +112,7 @@ const { t } = useI18n() // 国际化
 const loading = ref(true) // 列表的加载中
 const total = ref(0) // 列表的总页数
 const list = ref([]) // 列表的数据
-const queryParams: Record<string, any> = ref<Record<string, any>>({
+const queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
   name: null,

+ 17 - 12
src/views/system/user/components/UserDeptTree.vue → src/views/system/user/DeptTree.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="head-container">
-    <el-input v-model="deptName" placeholder="请输入部门名称" clearable style="margin-bottom: 20px">
+    <el-input v-model="deptName" placeholder="请输入部门名称" clearable class="mb-20px">
       <template #prefix>
         <Icon icon="ep:search" />
       </template>
@@ -8,15 +8,15 @@
   </div>
   <div class="head-container">
     <el-tree
-      :data="deptOptions"
+      :data="deptList"
       :props="defaultProps"
+      node-key="id"
       :expand-on-click-node="false"
       :filter-node-method="filterNode"
       ref="treeRef"
-      node-key="id"
       default-expand-all
       highlight-current
-      @node-click="handleDeptNodeClick"
+      @node-click="handleNodeClick"
     />
   </div>
 </template>
@@ -26,25 +26,30 @@ import { ElTree } from 'element-plus'
 import * as DeptApi from '@/api/system/dept'
 import { defaultProps, handleTree } from '@/utils/tree'
 
-const emits = defineEmits(['node-click'])
 const deptName = ref('')
-const deptOptions = ref<Tree[]>([]) // 树形结构
+const deptList = ref<Tree[]>([]) // 树形结构
 const treeRef = ref<InstanceType<typeof ElTree>>()
+
+/** 获得部门树 */
 const getTree = async () => {
   const res = await DeptApi.getSimpleDeptList()
-  deptOptions.value = []
-  deptOptions.value.push(...handleTree(res))
+  deptList.value = []
+  deptList.value.push(...handleTree(res))
 }
 
-const filterNode = (value: string, data: Tree) => {
-  if (!value) return true
-  return data.name.includes(value)
+/** 基于名字过滤 */
+const filterNode = (name: string, data: Tree) => {
+  if (!name) return true
+  return data.name.includes(name)
 }
 
-const handleDeptNodeClick = async (row: { [key: string]: any }) => {
+/** 处理部门被点击 */
+const handleNodeClick = async (row: { [key: string]: any }) => {
   emits('node-click', row)
 }
+const emits = defineEmits(['node-click'])
 
+/** 初始化 */
 onMounted(async () => {
   await getTree()
 })

+ 5 - 5
src/views/system/user/components/UserForm.vue

@@ -56,7 +56,7 @@
             <el-select v-model="formData.sex" placeholder="请选择">
               <el-option
                 v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
-                :key="dict.value as number"
+                :key="dict.value"
                 :label="dict.label"
                 :value="dict.value"
               />
@@ -70,7 +70,7 @@
                 v-for="item in postOptions"
                 :key="item.id"
                 :label="item.name"
-                :value="item.id as number"
+                :value="item.id"
               />
             </el-select>
           </el-form-item>
@@ -102,7 +102,6 @@ import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
 import { defaultProps, handleTree } from '@/utils/tree'
 import { ElForm, FormItemRule } from 'element-plus'
 import { Arrayable } from 'element-plus/es/utils'
-import { UserVO } from '@/api/login/types'
 
 type Form = InstanceType<typeof ElForm>
 
@@ -210,7 +209,8 @@ const cancel = () => {
 }
 
 /* 打开弹框 */
-const openForm = (row: undefined | UserVO) => {
+const open = (type: string, id?: number) => {
+  console.log(type, id)
   resetForm()
   getTree() // 部门树
   if (row && row.id) {
@@ -232,6 +232,6 @@ onMounted(async () => {
 
 defineExpose({
   resetForm,
-  openForm
+  open
 })
 </script>

+ 104 - 165
src/views/system/user/index.vue

@@ -1,20 +1,19 @@
 <template>
-  <!-- 搜索工作栏 -->
   <el-row :gutter="20">
-    <!--部门数据-->
+    <!-- 左侧部门树 -->
     <el-col :span="4" :xs="24">
       <content-wrap class="h-1/1">
-        <UserDeptTree @node-click="handleDeptNodeClick" />
+        <DeptTree @node-click="handleDeptNodeClick" />
       </content-wrap>
     </el-col>
-    <!--用户数据-->
     <el-col :span="20" :xs="24">
+      <!-- 搜索 -->
       <content-wrap>
         <el-form
+          class="-mb-15px"
           :model="queryParams"
           ref="queryFormRef"
           :inline="true"
-          v-show="showSearch"
           label-width="68px"
         >
           <el-form-item label="用户名称" prop="username">
@@ -22,8 +21,8 @@
               v-model="queryParams.username"
               placeholder="请输入用户名称"
               clearable
-              style="width: 240px"
               @keyup.enter="handleQuery"
+              class="!w-240px"
             />
           </el-form-item>
           <el-form-item label="手机号码" prop="mobile">
@@ -31,8 +30,8 @@
               v-model="queryParams.mobile"
               placeholder="请输入手机号码"
               clearable
-              style="width: 240px"
               @keyup.enter="handleQuery"
+              class="!w-240px"
             />
           </el-form-item>
           <el-form-item label="状态" prop="status">
@@ -40,7 +39,7 @@
               v-model="queryParams.status"
               placeholder="用户状态"
               clearable
-              style="width: 240px"
+              class="!w-240px"
             >
               <el-option
                 v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
@@ -53,31 +52,30 @@
           <el-form-item label="创建时间" prop="createTime">
             <el-date-picker
               v-model="queryParams.createTime"
-              style="width: 240px"
               value-format="YYYY-MM-DD HH:mm:ss"
               type="datetimerange"
-              range-separator="-"
               start-placeholder="开始日期"
               end-placeholder="结束日期"
+              class="!w-240px"
             />
           </el-form-item>
           <el-form-item>
-            <el-button type="primary" @click="handleQuery"><Icon icon="ep:search" />搜索</el-button>
+            <el-button @click="handleQuery"><Icon icon="ep:search" />搜索</el-button>
             <el-button @click="resetQuery"><Icon icon="ep:refresh" />重置</el-button>
-            <el-button type="primary" plain @click="handleAdd" v-hasPermi="['system:user:create']">
-              <Icon icon="ep:plus" /> 新增
-            </el-button>
             <el-button
-              type="info"
-              size="small"
-              @click="handleImport"
-              v-hasPermi="['system:user:import']"
+              type="primary"
+              plain
+              @click="openForm('create')"
+              v-hasPermi="['system:user:create']"
             >
+              <Icon icon="ep:plus" /> 新增
+            </el-button>
+            <el-button type="info" plain @click="handleImport" v-hasPermi="['system:user:import']">
               <Icon icon="ep:upload" /> 导入
             </el-button>
             <el-button
               type="warning"
-              size="small"
+              plain
               @click="handleExport"
               :loading="exportLoading"
               v-hasPermi="['system:user:export']"
@@ -88,28 +86,18 @@
         </el-form>
       </content-wrap>
       <content-wrap>
-        <el-table v-loading="loading" :data="userList">
-          <el-table-column
-            label="用户编号"
-            align="center"
-            key="id"
-            prop="id"
-            v-if="columns[0].visible"
-          />
+        <el-table v-loading="loading" :data="list">
+          <el-table-column label="用户编号" align="center" key="id" prop="id" />
           <el-table-column
             label="用户名称"
             align="center"
-            key="username"
             prop="username"
-            v-if="columns[1].visible"
             :show-overflow-tooltip="true"
           />
           <el-table-column
             label="用户昵称"
             align="center"
-            key="nickname"
             prop="nickname"
-            v-if="columns[2].visible"
             :show-overflow-tooltip="true"
           />
           <el-table-column
@@ -117,18 +105,10 @@
             align="center"
             key="deptName"
             prop="dept.name"
-            v-if="columns[3].visible"
             :show-overflow-tooltip="true"
           />
-          <el-table-column
-            label="手机号码"
-            align="center"
-            key="mobile"
-            prop="mobile"
-            v-if="columns[4].visible"
-            width="120"
-          />
-          <el-table-column label="状态" key="status" v-if="columns[5].visible" align="center">
+          <el-table-column label="手机号码" align="center" prop="mobile" width="120" />
+          <el-table-column label="状态" key="status">
             <template #default="scope">
               <el-switch
                 v-model="scope.row.status"
@@ -142,28 +122,20 @@
             label="创建时间"
             align="center"
             prop="createTime"
-            v-if="columns[6].visible"
-            width="160"
-          >
-            <template #default="scope">
-              <span>{{ parseTime(scope.row.createTime) }}</span>
-            </template>
-          </el-table-column>
-          <el-table-column
-            label="操作"
-            align="center"
-            width="160"
-            class-name="small-padding fixed-width"
-          >
+            :formatter="dateFormatter"
+            width="180"
+          />
+          <el-table-column label="操作" align="center" width="160">
             <template #default="scope">
               <div class="flex justify-center items-center">
                 <el-button
                   type="primary"
                   link
-                  @click="handleUpdate(scope.row)"
+                  @click="openForm('update', scope.row.id)"
                   v-hasPermi="['system:user:update']"
-                  ><Icon icon="ep:edit" />修改</el-button
                 >
+                  <Icon icon="ep:edit" />修改
+                </el-button>
                 <el-dropdown
                   @command="(command) => handleCommand(command, scope.$index, scope.row)"
                   v-hasPermi="[
@@ -172,25 +144,25 @@
                     'system:permission:assign-user-role'
                   ]"
                 >
-                  <el-button type="primary" link><Icon icon="ep:d-arrow-right" />更多</el-button>
+                  <el-button type="primary" link><Icon icon="ep:d-arrow-right" /> 更多</el-button>
                   <template #dropdown>
                     <el-dropdown-menu>
                       <!-- div包住避免控制台报错:Runtime directive used on component with non-element root node -->
-                      <div v-if="scope.row.id !== 1" v-hasPermi="['system:user:delete']">
-                        <el-dropdown-item command="handleDelete" type="text"
-                          ><Icon icon="ep:delete" />删除</el-dropdown-item
-                        >
+                      <div v-hasPermi="['system:user:delete']">
+                        <el-dropdown-item command="handleDelete">
+                          <Icon icon="ep:delete" />删除
+                        </el-dropdown-item>
                       </div>
                       <div v-hasPermi="['system:user:update-password']">
-                        <el-dropdown-item command="handleResetPwd" type="text"
-                          ><Icon icon="ep:key" />重置密码</el-dropdown-item
-                        ></div
-                      >
+                        <el-dropdown-item command="handleResetPwd">
+                          <Icon icon="ep:key" />重置密码
+                        </el-dropdown-item>
+                      </div>
                       <div v-hasPermi="['system:permission:assign-user-role']">
-                        <el-dropdown-item command="handleRole" type="text"
-                          ><Icon icon="ep:circle-check" />分配角色</el-dropdown-item
-                        ></div
-                      >
+                        <el-dropdown-item command="handleRole">
+                          <Icon icon="ep:circle-check" />分配角色
+                        </el-dropdown-item>
+                      </div>
                     </el-dropdown-menu>
                   </template>
                 </el-dropdown>
@@ -198,8 +170,7 @@
             </template>
           </el-table-column>
         </el-table>
-        <pagination
-          v-show="total > 0"
+        <Pagination
           :total="total"
           v-model:page="queryParams.pageNo"
           v-model:limit="queryParams.pageSize"
@@ -210,36 +181,32 @@
   </el-row>
 
   <!-- 添加或修改用户对话框 -->
-  <UserForm ref="userFormRef" @success="getList" />
+  <UserForm ref="formRef" @success="getList" />
   <!-- 用户导入对话框 -->
-  <UserImportForm ref="userImportFormRef" @success="getList" />
+  <UserImportForm ref="importFormRef" @success="getList" />
   <!-- 分配角色 -->
-  <UserAssignRoleForm ref="userAssignRoleFormRef" @success="getList" />
+  <UserAssignRoleForm ref="assignRoleFormRef" @success="getList" />
 </template>
 
 <script setup lang="ts" name="User">
-import download from '@/utils/download'
-import { parseTime } from '@/utils/formatTime'
 import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
+import { dateFormatter } from '@/utils/formatTime'
+import download from '@/utils/download'
 import { CommonStatusEnum } from '@/utils/constants'
 
-import {
-  deleteUserApi,
-  exportUserApi,
-  resetUserPwdApi,
-  updateUserStatusApi,
-  getUserPageApi,
-  UserVO
-} from '@/api/system/user'
+import { resetUserPwdApi, updateUserStatusApi, UserVO } from '@/api/system/user'
+import * as UserApi from '@/api/system/user'
 
 import UserForm from './components/UserForm.vue'
 import UserImportForm from './components/UserImportForm.vue'
 import UserAssignRoleForm from './components/UserAssignRoleForm.vue'
-import UserDeptTree from './components/UserDeptTree.vue'
-
+import DeptTree from './DeptTree.vue'
 const message = useMessage() // 消息弹窗
 const { t } = useI18n() // 国际化
 
+const loading = ref(true) // 列表的加载中
+const total = ref(0) // 列表的总页数
+const list = ref([]) // 列表的数
 const queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
@@ -249,35 +216,18 @@ const queryParams = reactive({
   deptId: undefined,
   createTime: []
 })
-const showSearch = ref(true)
-
-const handleDeptNodeClick = async (row: { [key: string]: any }) => {
-  queryParams.deptId = row.id
-  getList()
-}
-
-// 用户列表
-const userList = ref<UserVO[]>([])
-const loading = ref(false)
-const total = ref(0)
-const columns = ref([
-  { key: 0, label: `用户编号`, visible: true },
-  { key: 1, label: `用户名称`, visible: true },
-  { key: 2, label: `用户昵称`, visible: true },
-  { key: 3, label: `部门`, visible: true },
-  { key: 4, label: `手机号码`, visible: true },
-  { key: 5, label: `状态`, visible: true },
-  { key: 6, label: `创建时间`, visible: true }
-])
+const queryFormRef = ref() // 搜索的表单
 
 /** 查询列表 */
-const getList = () => {
+const getList = async () => {
   loading.value = true
-  getUserPageApi(queryParams).then((response) => {
-    userList.value = response.list
-    total.value = response.total
+  try {
+    const data = await UserApi.getUserPage(queryParams.value)
+    list.value = data.list
+    total.value = data.total
+  } finally {
     loading.value = false
-  })
+  }
 }
 
 /** 搜索按钮操作 */
@@ -287,54 +237,35 @@ const handleQuery = () => {
 }
 
 /** 重置按钮操作 */
-const queryFormRef = ref()
 const resetQuery = () => {
   queryFormRef.value?.resetFields()
   handleQuery()
 }
 
-// 添加或编辑
-const userFormRef = ref()
-// 添加用户
-const handleAdd = () => {
-  userFormRef.value?.openForm()
+/** 处理部门被点击 */
+const handleDeptNodeClick = async (row) => {
+  queryParams.deptId = row.id
+  await getList()
 }
 
-// 用户导入
-const userImportFormRef = ref()
-const handleImport = () => {
-  userImportFormRef.value?.openForm()
+/** 添加/修改操作 */
+const formRef = ref()
+const openForm = (type: string, id?: number) => {
+  formRef.value.open(type, id)
 }
 
-// 用户导出
-const exportLoading = ref(false)
-const handleExport = () => {
-  message
-    .confirm('是否确认导出所有用户数据项?')
-    .then(async () => {
-      // 处理查询参数
-      let params = { ...queryParams }
-      params.pageNo = 1
-      params.pageSize = 99999
-      exportLoading.value = true
-      const response = await exportUserApi(params)
-      download.excel(response, '用户数据.xls')
-    })
-    .catch(() => {})
-    .finally(() => {
-      exportLoading.value = false
-    })
+// 用户导入
+const importFormRef = ref()
+const handleImport = () => {
+  importFormRef.value?.openForm()
 }
 
 // 操作分发
-const handleCommand = (command: string, index: number, row: UserVO) => {
+const handleCommand = (command: string, index: number, row: UserApi.UserVO) => {
   console.log(index)
   switch (command) {
-    case 'handleUpdate':
-      handleUpdate(row) //修改客户信息
-      break
     case 'handleDelete':
-      handleDelete(row) //红号变更
+      handleDelete(row.id)
       break
     case 'handleResetPwd':
       handleResetPwd(row)
@@ -366,25 +297,33 @@ const handleStatusChange = (row: UserVO) => {
     })
 }
 
-// 具体数据单行操作
-/** 修改按钮操作 */
-const handleUpdate = (row: UserVO) => {
-  userFormRef.value?.openForm(row)
+/** 删除按钮操作 */
+const handleDelete = async (id: number) => {
+  try {
+    // 删除的二次确认
+    await message.delConfirm()
+    // 发起删除
+    await UserApi.deleteUser(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
 }
 
-// 删除用户
-const handleDelete = (row: UserVO) => {
-  const ids = row.id
-  message
-    .confirm('是否确认删除用户编号为"' + ids + '"的数据项?')
-    .then(async () => {
-      await deleteUserApi(ids)
-      message.success('删除成功')
-      getList()
-    })
-    .catch((e) => {
-      console.error(e)
-    })
+/** 导出按钮操作 */
+const exportLoading = ref(false)
+const handleExport = async () => {
+  try {
+    // 导出的二次确认
+    await message.exportConfirm()
+    // 发起导出
+    exportLoading.value = true
+    const data = await UserApi.exportUser(queryParams)
+    download.excel(data, '用户数据.xls')
+  } catch {
+  } finally {
+    exportLoading.value = false
+  }
 }
 
 // 重置密码
@@ -401,13 +340,13 @@ const handleResetPwd = (row: UserVO) => {
 }
 
 // 分配角色
-const userAssignRoleFormRef = ref()
+const assignRoleFormRef = ref()
 const handleRole = (row: UserVO) => {
-  userAssignRoleFormRef.value?.openForm(row)
+  assignRoleFormRef.value?.openForm(row)
 }
 
-// ========== 初始化 ==========
-onMounted(async () => {
+/** 初始化 */
+onMounted(() => {
   getList()
 })
 </script>