fix: 修复用户选择器bug

This commit is contained in:
MoChou
2024-11-08 22:04:14 +08:00
parent 5ade6bcecf
commit 233bd62bab
3 changed files with 83 additions and 54 deletions

View File

@@ -9,6 +9,7 @@
:columns="tableColumns" :columns="tableColumns"
:loading="loading" :loading="loading"
:scroll="{ x: '100%', y: '100%', minWidth: 1000 }" :scroll="{ x: '100%', y: '100%', minWidth: 1000 }"
style="max-height: 600px"
:pagination="pagination" :pagination="pagination"
:disabled-tools="['size', 'fullscreen', 'setting', 'refresh']" :disabled-tools="['size', 'fullscreen', 'setting', 'refresh']"
:row-selection="{ type: props.multiple ? 'checkbox' : 'radio', showCheckedAll: true }" :row-selection="{ type: props.multiple ? 'checkbox' : 'radio', showCheckedAll: true }"
@@ -30,7 +31,9 @@
@change="search" @change="search"
/> />
<a-button @click="reset"> <a-button @click="reset">
<template #icon><icon-refresh /></template> <template #icon>
<icon-refresh />
</template>
<template #default>重置</template> <template #default>重置</template>
</a-button> </a-button>
</a-space> </a-space>
@@ -59,7 +62,7 @@
<a-col :span="24" :md="6" class="section"> <a-col :span="24" :md="6" class="section">
<a-card title="已选用户"> <a-card title="已选用户">
<a-table :columns="rightColumn" :data="selectedData"> <a-table :columns="rightColumn" :data="selectedData" :pagination="paginationOptions">
<template #nickname="{ record }"> <template #nickname="{ record }">
{{ record.nickname }}({{ record.username }}) {{ record.nickname }}({{ record.username }})
</template> </template>
@@ -78,9 +81,9 @@
<script setup lang="ts"> <script setup lang="ts">
import type { TreeNodeData } from '@arco-design/web-vue' import type { TreeNodeData } from '@arco-design/web-vue'
import { useDept } from '@/hooks/app' import { useDept } from '@/hooks/app'
import { useTable } from '@/hooks' import { type Options, useTable } from '@/hooks'
import { type UserQuery, listAllUser, listUser } from '@/apis' import { type UserQuery, type UserResp, listAllUser, listUser } from '@/apis'
import type { UserItem, UserSelectPropType } from '@/components/UserSelect/type' import type { UserSelectPropType } from '@/components/UserSelect/type'
import type { TableInstanceColumns } from '@/components/GiTable/type' import type { TableInstanceColumns } from '@/components/GiTable/type'
import { isMobile } from '@/utils' import { isMobile } from '@/utils'
@@ -127,6 +130,11 @@ const rightColumn = [
const queryForm = reactive<UserQuery>({ const queryForm = reactive<UserQuery>({
sort: ['t1.createTime,desc'], sort: ['t1.createTime,desc'],
}) })
// 定义分页器参数
const paginationOptions: Options = {
defaultPageSize: 10,
defaultSizeOptions: [10, 20, 30, 40, 50],
}
// 用户列表 // 用户列表
const { tableData: dataList, loading, pagination, search } = useTable( const { tableData: dataList, loading, pagination, search } = useTable(
@@ -157,65 +165,92 @@ const filterDeptOptions = (searchKey: string, nodeData: TreeNodeData) => {
return false return false
} }
const selectedKeys = ref<string[]>([]) const allUsers = ref<UserResp[]>() // 用于存储所有用户信息
const selectedData = ref<any[]>([]) const selectedKeys = ref<string[]>([]) // 使用 Array 来存储选中的 id
const selectedData = ref<Set<UserResp>>(new Set()) // 使用 Set 来存储选中的用户对象
const emitSelectedUsers = () => { const emitSelectedUsers = () => {
emit('update:selectedUsers', selectedKeys.value) emit('update:selectedUsers', selectedKeys.value)
} }
// 行选择事件 // 行选择事件
const onRowSelect = (rowKeys: string[], rowKey: string, record: UserItem) => { const onRowSelect = (rowKeys: string[], rowKey: string, record: UserResp) => {
selectedData.value = props.multiple if (props.multiple) {
? rowKeys.includes(rowKey) // 多选
? [...selectedData.value, record] if (rowKeys.includes(rowKey)) {
: selectedData.value.filter((item) => item.id !== rowKey) // 包含 选中
: [record] selectedData.value.add(record)
selectedKeys.value = selectedData.value.map((item) => item.id) selectedKeys.value?.push(rowKey)
} else {
// 不包含 去除
selectedData.value.delete(record)
selectedKeys.value?.splice(selectedKeys.value?.indexOf(rowKey), 1)
}
} else {
// 单选
selectedData.value.clear()
selectedKeys.value = []
if (rowKeys.includes(rowKey)) {
// 包含 选中
selectedData.value.add(record)
selectedKeys.value?.push(rowKey)
}
}
emitSelectedUsers() emitSelectedUsers()
} }
// 全选事件 // 全选事件
const onTableSelectAll = (checked: boolean) => { const onTableSelectAll = (checked: boolean) => {
selectedData.value = checked if (checked) {
? [...selectedData.value, ...dataList.value.filter((item) => !selectedKeys.value.includes(item.id))] // 选中
: [] dataList.value.forEach((item) => {
selectedKeys.value = selectedData.value.map((item) => item.id) selectedData.value.add(item)
selectedKeys.value?.push(item.id)
})
} else {
// 取消选中
dataList.value.forEach((item) => {
selectedData.value.delete(item)
selectedKeys.value?.splice(selectedKeys.value?.indexOf(item.id), 1)
})
}
emitSelectedUsers() emitSelectedUsers()
} }
// 从选中列表中移除用户 // 从选中列表中移除用户
const handleDeleteSelectUser = (user: UserItem) => { const handleDeleteSelectUser = (user: UserResp) => {
selectedData.value = selectedData.value.filter((item) => item.id !== user.id) selectedData.value.delete(user)
selectedKeys.value = selectedData.value.map((item) => item.id) selectedKeys.value?.splice(selectedKeys.value?.indexOf(user.id), 1)
emitSelectedUsers() emitSelectedUsers()
} }
// 清空所有选中数据 // 清空所有选中数据
const onClearSelected = () => { const onClearSelected = () => {
selectedData.value = [] selectedData.value.clear()
selectedKeys.value = [] selectedKeys.value = []
emitSelectedUsers() emitSelectedUsers()
} }
// 初始化函数 // 初始化函数
const init = (selectUsers: string[]) => { const init = async (selectUsers: string[]) => {
getDeptList() getDeptList()
search() search()
// 获取所有用户数据
const { data } = await listAllUser({})
allUsers.value = data
// 过滤已选择的用户
if (selectUsers && selectUsers.length > 0) { if (selectUsers && selectUsers.length > 0) {
// admin的id是number 不是string 类型 所以处理一下 if (props.multiple) {
listAllUser({ userIds: selectUsers }).then((dataList) => { selectedData.value = new Set(allUsers.value.filter((item) => selectUsers.includes(item.id)))
selectedData.value = dataList.data.map((data) => { selectedKeys.value = Array.from(selectedData.value).map((user) => user.id)
return { ...data, id: data.id } } else {
}) selectedData.value = new Set(allUsers.value.filter((item) => selectUsers[0] === item.id))
}) selectedKeys.value = Array.from(selectedData.value).map((user) => user.id)
}
} }
} }
watch(() => props.selectedUsers, (newValue) => {
const newSelectedKeys = Array.isArray(newValue) ? newValue : [newValue]
selectedKeys.value = newSelectedKeys.filter(Boolean)
selectedData.value = dataList.value.filter((item) => selectedKeys.value.includes(item.id))
}, { immediate: true })
defineExpose({ init, onClearSelected }) defineExpose({ init, onClearSelected })
</script> </script>

View File

@@ -40,19 +40,19 @@ import { useWindowSize } from '@vueuse/core'
import UserSelectContent from './component/UserSelectContent.vue' import UserSelectContent from './component/UserSelectContent.vue'
import { listUserDict } from '@/apis' import { listUserDict } from '@/apis'
import type { UserSelectPropType } from '@/components/UserSelect/type' import type { UserSelectPropType } from '@/components/UserSelect/type'
import type { LabelValueState } from '@/types/global'
const props = withDefaults(defineProps<UserSelectPropType>(), { const props = withDefaults(defineProps<UserSelectPropType>(), {
multiple: false, // 是否支持多选 multiple: false, // 是否支持多选
value: '', value: [], // 单选时默认值为空数组
}) })
const emit = defineEmits(['update:value']) const emit = defineEmits(['update:value'])
const { width } = useWindowSize() // 获取窗口的宽度,用于设置弹窗宽度 const { width } = useWindowSize() // 获取窗口的宽度,用于设置弹窗宽度
const visible = ref<boolean>(false) // 控制弹窗显示的状态 const visible = ref<boolean>(false) // 控制弹窗显示的状态
const userList = ref([]) // 保存用户选项列表 const userList = ref<LabelValueState[]>([]) // 保存用户选项列表
const userSelectContentRef = ref() // 引用 UserSelectContent 组件实例 const userSelectContentRef = ref() // 引用 UserSelectContent 组件实例
const selectedUsers = ref([]) // 保存已选择的用户 const selectedUsers = ref<string[]>([]) // 保存已选择的用户
// 打开用户选择弹窗 // 打开用户选择弹窗
const onOpen = () => { const onOpen = () => {
visible.value = true visible.value = true
@@ -66,7 +66,13 @@ const emitDataChange = () => {
// 处理用户选择变更事件 // 处理用户选择变更事件
const handleSelectChange = (value: any) => { const handleSelectChange = (value: any) => {
selectedUsers.value = props.multiple ? value : [...value] if (props.multiple) {
// 多选模式下selectedUsers 应该是一个数组
selectedUsers.value = value
} else {
// 单选模式下selectedUsers 只应保存一个值
selectedUsers.value = value ? [value] : []
}
emitDataChange() // 每次选择变化时发出更新事件 emitDataChange() // 每次选择变化时发出更新事件
} }
@@ -90,15 +96,3 @@ onMounted(async () => {
selectedUsers.value = Array.isArray(props.value) ? props.value : props.value?.split(',') selectedUsers.value = Array.isArray(props.value) ? props.value : props.value?.split(',')
}) })
</script> </script>
<style scoped>
:deep(.arco-input-append) {
padding: 0;
.arco-btn {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
border: 1px solid transparent;
}
}
</style>

View File

@@ -1,6 +1,6 @@
export interface UserSelectPropType { export interface UserSelectPropType {
multiple: boolean multiple: boolean
value?: string[] value: string[] | string
} }
export interface UserItem { export interface UserItem {