|
|
|
@@ -1,29 +1,14 @@
|
|
|
|
|
<template>
|
|
|
|
|
<div class="container">
|
|
|
|
|
<a-row :gutter="16">
|
|
|
|
|
<a-col :span="24" :md="5" class="section">
|
|
|
|
|
<a-input v-model="searchKey" placeholder="请输入部门名称" allow-clear>
|
|
|
|
|
<template #prefix>
|
|
|
|
|
<icon-search />
|
|
|
|
|
</template>
|
|
|
|
|
</a-input>
|
|
|
|
|
<a-tree
|
|
|
|
|
ref="treeRef"
|
|
|
|
|
:data="treeData"
|
|
|
|
|
block-node
|
|
|
|
|
@select="handleDeptSelect"
|
|
|
|
|
/>
|
|
|
|
|
</a-col>
|
|
|
|
|
|
|
|
|
|
<a-col :span="24" :md="14" class="section">
|
|
|
|
|
<a-col :span="24" :md="18" class="section">
|
|
|
|
|
<GiTable
|
|
|
|
|
v-model:selectedKeys="selectedKeys"
|
|
|
|
|
style="min-height: 600px;"
|
|
|
|
|
row-key="id"
|
|
|
|
|
:data="dataList"
|
|
|
|
|
:columns="tableColumns"
|
|
|
|
|
:loading="loading"
|
|
|
|
|
:scroll="{ x: '100%', y: '100%' }"
|
|
|
|
|
:scroll="{ x: '100%', y: '100%', minWidth: 1000 }"
|
|
|
|
|
:pagination="pagination"
|
|
|
|
|
:disabled-tools="['size', 'fullscreen', 'setting', 'refresh']"
|
|
|
|
|
:row-selection="{ type: props.multiple ? 'checkbox' : 'radio', showCheckedAll: true }"
|
|
|
|
@@ -34,16 +19,19 @@
|
|
|
|
|
<template #top>
|
|
|
|
|
<div>
|
|
|
|
|
<a-space class="mt-5">
|
|
|
|
|
<a-input v-model="queryForm.description" placeholder="用户名/昵称/描述" />
|
|
|
|
|
<a-button @click="search">
|
|
|
|
|
<template #icon>
|
|
|
|
|
<icon-search />
|
|
|
|
|
</template>
|
|
|
|
|
</a-button>
|
|
|
|
|
<a-button @click="onRefresh">
|
|
|
|
|
<template #icon>
|
|
|
|
|
<icon-refresh />
|
|
|
|
|
</template>
|
|
|
|
|
<a-input v-model="queryForm.description" placeholder="用户名/昵称/描述" allow-clear @change="search" />
|
|
|
|
|
<a-tree-select
|
|
|
|
|
v-model="queryForm.deptId"
|
|
|
|
|
:data="deptList"
|
|
|
|
|
placeholder="请选择所属部门"
|
|
|
|
|
allow-clear
|
|
|
|
|
allow-search
|
|
|
|
|
:filter-tree-node="filterDeptOptions"
|
|
|
|
|
@change="search"
|
|
|
|
|
/>
|
|
|
|
|
<a-button @click="reset">
|
|
|
|
|
<template #icon><icon-refresh /></template>
|
|
|
|
|
<template #default>重置</template>
|
|
|
|
|
</a-button>
|
|
|
|
|
</a-space>
|
|
|
|
|
</div>
|
|
|
|
@@ -52,7 +40,7 @@
|
|
|
|
|
已选中{{ selectedKeys.length }}条记录(可跨页)
|
|
|
|
|
</template>
|
|
|
|
|
<template v-else>
|
|
|
|
|
未选中任何项目
|
|
|
|
|
未选中任何用户
|
|
|
|
|
</template>
|
|
|
|
|
<template v-if="selectedKeys.length > 0" #action>
|
|
|
|
|
<a-link @click="onClearSelected">清空</a-link>
|
|
|
|
@@ -63,12 +51,18 @@
|
|
|
|
|
<template #status="{ record }">
|
|
|
|
|
<GiCellStatus :status="record.status" />
|
|
|
|
|
</template>
|
|
|
|
|
<template #gender="{ record }">
|
|
|
|
|
<GiCellGender :gender="record.gender" />
|
|
|
|
|
</template>
|
|
|
|
|
</GiTable>
|
|
|
|
|
</a-col>
|
|
|
|
|
|
|
|
|
|
<a-col :span="24" :md="5" class="section">
|
|
|
|
|
<a-col :span="24" :md="6" class="section">
|
|
|
|
|
<a-card title="已选用户">
|
|
|
|
|
<a-table :columns="rightColumn" :data="selectedData">
|
|
|
|
|
<template #nickname="{ record }">
|
|
|
|
|
{{ record.nickname }}({{ record.username }})
|
|
|
|
|
</template>
|
|
|
|
|
<template #action="{ record }">
|
|
|
|
|
<a-button @click="handleDeleteSelectUser(record)">
|
|
|
|
|
<icon-delete />
|
|
|
|
@@ -85,8 +79,10 @@
|
|
|
|
|
import type { TreeNodeData } from '@arco-design/web-vue'
|
|
|
|
|
import { useDept } from '@/hooks/app'
|
|
|
|
|
import { useTable } from '@/hooks'
|
|
|
|
|
import { listAllUser, listUser } from '@/apis'
|
|
|
|
|
import { type UserQuery, listAllUser, listUser } from '@/apis'
|
|
|
|
|
import type { UserItem, UserSelectPropType } from '@/components/UserSelect/type'
|
|
|
|
|
import type { TableInstanceColumns } from '@/components/GiTable/type'
|
|
|
|
|
import { isMobile } from '@/utils'
|
|
|
|
|
|
|
|
|
|
const props = withDefaults(defineProps<UserSelectPropType & { selectedUsers: string | string[] }>(), {
|
|
|
|
|
multiple: false,
|
|
|
|
@@ -95,84 +91,77 @@ const props = withDefaults(defineProps<UserSelectPropType & { selectedUsers: str
|
|
|
|
|
|
|
|
|
|
const emit = defineEmits(['update:selectedUsers'])
|
|
|
|
|
|
|
|
|
|
// 查询表单引用
|
|
|
|
|
const queryForm = ref({ description: '' })
|
|
|
|
|
// 表格列定义
|
|
|
|
|
const tableColumns: TableInstanceColumns[] = [
|
|
|
|
|
{
|
|
|
|
|
title: '昵称',
|
|
|
|
|
dataIndex: 'nickname',
|
|
|
|
|
slotName: 'nickname',
|
|
|
|
|
minWidth: 140,
|
|
|
|
|
ellipsis: true,
|
|
|
|
|
tooltip: true,
|
|
|
|
|
fixed: !isMobile() ? 'left' : undefined,
|
|
|
|
|
},
|
|
|
|
|
{ title: '用户名', dataIndex: 'username', slotName: 'username', minWidth: 140, ellipsis: true, tooltip: true },
|
|
|
|
|
{ title: '状态', slotName: 'status', align: 'center' },
|
|
|
|
|
{ title: '性别', dataIndex: 'gender', slotName: 'gender', align: 'center' },
|
|
|
|
|
{ title: '所属部门', dataIndex: 'deptName', ellipsis: true, tooltip: true, minWidth: 180 },
|
|
|
|
|
{ title: '角色', dataIndex: 'roleNames', minWidth: 160, slotName: 'roleNames' },
|
|
|
|
|
{ title: '手机号', dataIndex: 'phone', minWidth: 170, ellipsis: true, tooltip: true },
|
|
|
|
|
{ title: '邮箱', dataIndex: 'email', minWidth: 170, ellipsis: true, tooltip: true },
|
|
|
|
|
{ title: '系统内置', slotName: 'isSystem', width: 100, align: 'center', show: false },
|
|
|
|
|
{ title: '描述', dataIndex: 'description', minWidth: 130, ellipsis: true, tooltip: true },
|
|
|
|
|
{ title: '创建人', dataIndex: 'createUserString', width: 140, ellipsis: true, tooltip: true, show: false },
|
|
|
|
|
{ title: '创建时间', dataIndex: 'createTime', width: 180 },
|
|
|
|
|
{ title: '修改人', dataIndex: 'updateUserString', width: 140, ellipsis: true, tooltip: true, show: false },
|
|
|
|
|
{ title: '修改时间', dataIndex: 'updateTime', width: 180, show: false },
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
// 部门树引用
|
|
|
|
|
const treeRef = ref()
|
|
|
|
|
const selectedKeys = ref<string[]>([])
|
|
|
|
|
const selectedDeptId = ref<string>('')
|
|
|
|
|
const selectedData = ref<any[]>([])
|
|
|
|
|
// 右侧已选用户列定义
|
|
|
|
|
const rightColumn = [
|
|
|
|
|
{ title: '用户', dataIndex: 'nickname', slotName: 'nickname', minWidth: 140, ellipsis: true, tooltip: true },
|
|
|
|
|
{ title: '操作', dataIndex: 'action', slotName: 'action' },
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
// 查询表单
|
|
|
|
|
const queryForm = reactive<UserQuery>({
|
|
|
|
|
sort: ['t1.createTime,desc'],
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 用户列表
|
|
|
|
|
const { tableData: dataList, loading, pagination, search } = useTable(
|
|
|
|
|
(page) => listUser({ ...queryForm.value, deptId: selectedDeptId.value, sort: [], ...page }),
|
|
|
|
|
(page) => listUser({ ...queryForm, ...page }),
|
|
|
|
|
{ immediate: false, formatResult: (data) => data.map((i) => ({ ...i, disabled: false })) },
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// 刷新表单
|
|
|
|
|
const onRefresh = () => {
|
|
|
|
|
queryForm.value.description = ''
|
|
|
|
|
// 重置
|
|
|
|
|
const reset = () => {
|
|
|
|
|
queryForm.description = undefined
|
|
|
|
|
queryForm.deptId = undefined
|
|
|
|
|
search()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 使用 useDept 钩子获取部门列表数据
|
|
|
|
|
const treeRef = ref()
|
|
|
|
|
// 部门列表
|
|
|
|
|
const { deptList, getDeptList } = useDept({
|
|
|
|
|
onSuccess: () => {
|
|
|
|
|
nextTick(() => treeRef.value?.expandAll(true))
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 部门树过滤函数
|
|
|
|
|
const deptTreeSearch = (keyword: string, data: TreeNodeData[]): TreeNodeData[] => {
|
|
|
|
|
return data
|
|
|
|
|
.map((item) => ({
|
|
|
|
|
...item,
|
|
|
|
|
children: item.children ? deptTreeSearch(keyword, item.children) : [],
|
|
|
|
|
}))
|
|
|
|
|
.filter(
|
|
|
|
|
(item) =>
|
|
|
|
|
item.title?.toLowerCase().includes(keyword.toLowerCase()) || item.children?.length,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 过滤树数据
|
|
|
|
|
const searchKey = ref('')
|
|
|
|
|
const treeData = computed(() => {
|
|
|
|
|
return searchKey.value ? deptTreeSearch(searchKey.value, deptList.value) : deptList.value
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 表格列定义
|
|
|
|
|
const tableColumns = [
|
|
|
|
|
{ title: '昵称', dataIndex: 'nickname' },
|
|
|
|
|
{ title: '部门', dataIndex: 'deptName' },
|
|
|
|
|
{ title: '角色', dataIndex: 'roleNames' },
|
|
|
|
|
{ title: '手机号', dataIndex: 'phone' },
|
|
|
|
|
{ title: '邮箱', dataIndex: 'email' },
|
|
|
|
|
{ title: '状态', dataIndex: 'status', slotName: 'status' },
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
// 右侧已选用户列定义
|
|
|
|
|
const rightColumn = [
|
|
|
|
|
{ title: '昵称', dataIndex: 'nickname' },
|
|
|
|
|
{ title: '操作', dataIndex: 'action', slotName: 'action' },
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
// 处理部门选择
|
|
|
|
|
const handleDeptSelect = (keys: Array<any>) => {
|
|
|
|
|
selectedDeptId.value = keys[0] || ''
|
|
|
|
|
search()
|
|
|
|
|
// 过滤部门
|
|
|
|
|
const filterDeptOptions = (searchKey: string, nodeData: TreeNodeData) => {
|
|
|
|
|
if (nodeData.title) {
|
|
|
|
|
return nodeData.title.toLowerCase().includes(searchKey.toLowerCase())
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const selectedKeys = ref<string[]>([])
|
|
|
|
|
const selectedData = ref<any[]>([])
|
|
|
|
|
const emitSelectedUsers = () => {
|
|
|
|
|
emit('update:selectedUsers', selectedKeys.value)
|
|
|
|
|
}
|
|
|
|
|
// 从选中列表中移除用户
|
|
|
|
|
const handleDeleteSelectUser = (user: UserItem) => {
|
|
|
|
|
selectedData.value = selectedData.value.filter((item) => item.id !== user.id)
|
|
|
|
|
selectedKeys.value = selectedData.value.map((item) => item.id)
|
|
|
|
|
emitSelectedUsers()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 行选择事件
|
|
|
|
|
const onRowSelect = (rowKeys: string[], rowKey: string, record: UserItem) => {
|
|
|
|
|
selectedData.value = props.multiple
|
|
|
|
@@ -180,10 +169,10 @@ const onRowSelect = (rowKeys: string[], rowKey: string, record: UserItem) => {
|
|
|
|
|
? [...selectedData.value, record]
|
|
|
|
|
: selectedData.value.filter((item) => item.id !== rowKey)
|
|
|
|
|
: [record]
|
|
|
|
|
|
|
|
|
|
selectedKeys.value = selectedData.value.map((item) => item.id)
|
|
|
|
|
emitSelectedUsers()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 全选事件
|
|
|
|
|
const onTableSelectAll = (checked: boolean) => {
|
|
|
|
|
selectedData.value = checked
|
|
|
|
@@ -193,6 +182,13 @@ const onTableSelectAll = (checked: boolean) => {
|
|
|
|
|
emitSelectedUsers()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 从选中列表中移除用户
|
|
|
|
|
const handleDeleteSelectUser = (user: UserItem) => {
|
|
|
|
|
selectedData.value = selectedData.value.filter((item) => item.id !== user.id)
|
|
|
|
|
selectedKeys.value = selectedData.value.map((item) => item.id)
|
|
|
|
|
emitSelectedUsers()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 清空所有选中数据
|
|
|
|
|
const onClearSelected = () => {
|
|
|
|
|
selectedData.value = []
|
|
|
|
@@ -208,7 +204,7 @@ const init = (selectUsers: string[]) => {
|
|
|
|
|
// admin的id是number 不是string 类型 所以处理一下
|
|
|
|
|
listAllUser({ userIds: selectUsers }).then((dataList) => {
|
|
|
|
|
selectedData.value = dataList.data.map((data) => {
|
|
|
|
|
return { ...data, id: `${data.id}` }
|
|
|
|
|
return { ...data, id: data.id }
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|