123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- <template>
- <div class="main-box">
- <TreeFilter title="部门列表" :is-all="false" :data="treeFilterData" :default-value="initParam.deptId" @change="changeTreeFilter" />
- <div class="table-box">
- <ProTable
- ref="proTable"
- row-key="userId"
- :indent="20"
- :columns="columns"
- :request-api="listUserApi"
- :request-auto="false"
- :init-param="initParam"
- :search-col="{ xs: 1, sm: 1, md: 2, lg: 3, xl: 3 }"
- >
- <!-- 表格 header 按钮 -->
- <template #tableHeader="scope">
- <el-button type="primary" v-auth="['system:user:add']" :icon="CirclePlus" @click="openDialog(1, '用户新增')"> 新增 </el-button>
- <el-button type="primary" v-auth="['system:user:import']" :icon="Upload" plain @click="batchAdd">导入</el-button>
- <el-button type="primary" v-auth="['system:user:export']" :icon="Download" plain @click="downloadFile">导出</el-button>
- <el-button
- type="danger"
- v-auth="['system:user:remove']"
- :icon="Delete"
- plain
- :disabled="!scope.isSelected"
- @click="batchDelete(scope.selectedListIds)"
- >
- 批量删除
- </el-button>
- </template>
- <!-- 表格操作 -->
- <template #operation="scope">
- <el-button type="primary" link v-if="scope.row.userId !== 1" :icon="View" @click="openDialog(3, '用户查看', scope.row)">查看</el-button>
- <el-button type="primary" link v-if="scope.row.userId !== 1" :icon="EditPen" @click="openDialog(2, '用户编辑', scope.row)">编辑</el-button>
- <el-button type="primary" link v-if="scope.row.userId !== 1" :icon="Delete" @click="deleteAccount(scope.row)">删除</el-button>
- </template>
- </ProTable>
- <FormDialog ref="formDialogRef" />
- <ImportExcel ref="dialogRef" />
- </div>
- </div>
- </template>
- <script setup lang="tsx" name="UserManage">
- import { onMounted, reactive, ref } from 'vue'
- import { User } from '@/api/interface'
- import { useDownload } from '@/hooks/useDownload'
- import { useHandleData } from '@/hooks/useHandleData'
- import { ElMessageBox } from 'element-plus'
- import ProTable from '@/components/ProTable/index.vue'
- import TreeFilter from '@/components/TreeFilter/index.vue'
- import ImportExcel from '@/components/ImportExcel/index.vue'
- import FormDialog from '@/components/DialogOld/form.vue'
- import { CirclePlus, Download, Upload, View, Delete, EditPen } from '@element-plus/icons-vue'
- import { ColumnProps, ProTableInstance } from '@/components/ProTable/interface'
- import {
- listUserApi,
- delUserApi,
- addUserApi,
- updateUserApi,
- changeUserStatus,
- importTemplateApi,
- importDataApi,
- exportApi,
- getUserApi,
- deptTreeSelectApi
- } from '@/api/modules/system/user'
- import { getDictsApi } from '@/api/modules/system/dictData'
- onMounted(() => {
- getTreeFilter()
- })
- // ProTable 实例
- const proTable = ref<ProTableInstance>()
- // 如果表格需要初始化请求参数,直接定义传给 ProTable(之后每次请求都会自动带上该参数,此参数更改之后也会一直带上,改变此参数会自动刷新表格数据)
- const initParam = reactive({ deptId: '' })
- // 获取 treeFilter 数据
- // 当 proTable 的 requestAuto 属性为 false,不会自动请求表格数据,等待 treeFilter 数据回来之后,更改 initParam.departmentId 的值,才会触发请求 proTable 数据
- const treeFilterData = ref<any>([])
- const getTreeFilter = async () => {
- const { data } = await deptTreeSelectApi()
- treeFilterData.value = data
- initParam.deptId = treeFilterData.value[0].id
- }
- // 树形筛选切换
- const changeTreeFilter = (val: string) => {
- // ElMessage.success('请注意查看请求参数变化 🤔')
- proTable.value!.pageable.pageNum = 1
- initParam.deptId = val
- }
- // 切换用户状态
- const changeStatus = async (row: User.ResUserList) => {
- await useHandleData(changeUserStatus, { userId: row.userId, status: row.status == '1' ? 0 : 1 }, `切换【${row.userName}】用户状态`)
- proTable.value?.getTableList()
- }
- // 删除用户信息
- const deleteAccount = async (params: User.ResUserList) => {
- await useHandleData(delUserApi, params.userId, `删除【${params.userName}】用户`)
- proTable.value?.getTableList()
- }
- // 批量删除用户信息
- const batchDelete = async (ids: string[]) => {
- await useHandleData(delUserApi, ids, '删除所选用户信息')
- proTable.value?.clearSelection()
- proTable.value?.getTableList()
- }
- // 导出用户列表
- const downloadFile = async () => {
- ElMessageBox.confirm('确认导出用户数据?', '温馨提示', { type: 'warning' }).then(() =>
- useDownload(exportApi, '用户列表', proTable.value?.searchParam)
- )
- }
- // 批量添加用户
- const dialogRef = ref<InstanceType<typeof ImportExcel> | null>(null)
- const batchAdd = () => {
- const params = {
- title: '用户',
- tempApi: importTemplateApi,
- importApi: importDataApi,
- getTableList: proTable.value?.getTableList
- }
- dialogRef.value?.acceptParams(params)
- }
- const formDialogRef = ref<InstanceType<typeof FormDialog> | null>(null)
- const postOptions = ref<any[]>([])
- const roleOptions = ref<any[]>([])
- // 打开弹框的功能
- const openDialog = async (type: number, title: string, row?: any) => {
- let res = await getUserApi(row?.userId || null)
- postOptions.value = res.data.posts
- roleOptions.value = res.data.roles
- // 表单项配置
- const fieldList: Form.FieldItem[] = [
- {
- label: '用户昵称',
- placeholder: '请输入用户昵称',
- span: 12,
- field: 'nickName',
- rules: [{ required: true, message: '用户昵称不能为空' }]
- },
- {
- label: '归属部门',
- span: 12,
- field: 'deptId',
- placeholder: '请选择归属部门',
- enum: () => deptTreeSelectApi(),
- type: 'select-tree',
- options: {
- valueKey: 'id',
- labelKey: 'label',
- children: 'children'
- }
- },
- {
- label: '手机号码',
- placeholder: '请输入手机号码',
- span: 12,
- field: 'phonenumber',
- rules: [{ pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: '请输入正确的手机号码', trigger: 'blur' }]
- },
- {
- label: '邮箱',
- placeholder: '请输入邮箱',
- span: 12,
- field: 'email',
- rules: [{ type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] }]
- },
- {
- label: '性别',
- span: 12,
- field: 'sex',
- enum: () => getDictsApi('sys_user_gender'),
- type: 'select',
- options: {
- labelKey: 'dictLabel',
- valueKey: 'dictValue'
- }
- },
- {
- label: '状态',
- span: 12,
- field: 'status',
- type: 'radio',
- enum: () => getDictsApi('sys_normal_disable'),
- options: {
- labelKey: 'dictLabel',
- valueKey: 'dictValue'
- }
- },
- {
- label: '岗位',
- span: 12,
- field: 'postIds',
- enum: postOptions.value,
- type: 'select',
- options: {
- valueKey: 'postId',
- labelKey: 'postName',
- multiple: true
- }
- },
- {
- label: '角色',
- span: 12,
- field: 'roleIds',
- enum: roleOptions.value,
- type: 'select',
- options: {
- valueKey: 'roleId',
- labelKey: 'roleName',
- multiple: true
- }
- },
- {
- label: '备注',
- placeholder: '请输入内容',
- field: 'remark',
- type: 'textarea'
- }
- ]
- if (type == 1) {
- fieldList.splice(
- 4,
- 0,
- {
- label: '用户名称',
- placeholder: '请输入用户名称',
- field: 'userName',
- span: 12,
- rules: [
- { required: true, message: '用户名称不能为空' },
- { min: 2, max: 20, message: '用户名称长度必须介于 2 和 20 之间', trigger: 'blur' }
- ]
- },
- {
- label: '用户密码',
- placeholder: '请输入密码',
- field: 'password',
- type: 'password',
- showPassword: true,
- span: 12,
- rules: [
- { required: true, message: '密码不能为空' },
- { min: 5, max: 20, message: '用户密码长度必须介于 5 和 20 之间', trigger: 'blur' }
- ]
- }
- )
- }
- if (row?.userId) {
- res.data.user.postIds = res.data.postIds
- res.data.user.roleIds = res.data.roleIds
- }
- const params = {
- title,
- width: 680,
- isEdit: type !== 3,
- fieldList: fieldList,
- model: type == 1 ? {} : res.data.user,
- api: type == 1 ? addUserApi : updateUserApi,
- getTableList: proTable.value?.getTableList
- }
- formDialogRef.value?.openDialog(params)
- }
- // 表格配置项
- const columns = reactive<ColumnProps<User.ResUserList>[]>([
- { type: 'selection', fixed: 'left', width: 70 },
- { prop: 'userId', label: '用户编号' },
- { prop: 'userName', label: '用户名称', search: { el: 'input' }, width: 120 },
- { prop: 'nickName', label: '用户昵称', search: { el: 'input' }, width: 120 },
- { prop: 'dept.deptName', label: '部门', width: 120 },
- { prop: 'phonenumber', label: '手机号码', width: 120 },
- {
- prop: 'status',
- label: '用户状态',
- width: 120,
- enum: () => getDictsApi('sys_normal_disable'),
- search: { el: 'tree-select' },
- fieldNames: { label: 'dictLabel', value: 'dictValue' },
- render: scope => {
- return (
- <el-switch
- model-value={scope.row.status}
- active-text={scope.row.status === '1' ? '禁用' : '启用'}
- active-value={'0'}
- inactive-value={'1'}
- onClick={() => changeStatus(scope.row)}
- />
- )
- }
- },
- {
- prop: 'sex',
- label: '性别',
- width: 120,
- enum: () => getDictsApi('sys_user_gender'),
- fieldNames: {
- label: 'dictLabel',
- value: 'dictValue'
- }
- },
- { prop: 'createTime', label: '创建时间', width: 180 },
- { prop: 'operation', label: '操作', width: 230, fixed: 'right' }
- ])
- </script>
|