2025-08-06 17:09:15 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<el-tree-select
|
|
|
|
|
|
:model-value="modelVal"
|
|
|
|
|
|
:data="treeData"
|
|
|
|
|
|
style="width: 300px;"
|
|
|
|
|
|
:props="defaultProps"
|
|
|
|
|
|
searchable
|
|
|
|
|
|
clearable
|
|
|
|
|
|
v-bind="$attrs"
|
|
|
|
|
|
@update:model-value="updateValue"
|
|
|
|
|
|
@change="handleChange"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
|
import { ref, onMounted, computed } from 'vue'
|
|
|
|
|
|
import { listDept } from '@/api/system/dept'
|
|
|
|
|
|
import { listUser } from '@/api/system/user'
|
|
|
|
|
|
|
|
|
|
|
|
defineOptions({
|
|
|
|
|
|
name: 'UserSelect'
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
const emit = defineEmits(['update:modelValue', 'change'])
|
|
|
|
|
|
const props = defineProps({
|
|
|
|
|
|
modelValue: {
|
|
|
|
|
|
type: [String, Number, Array],
|
|
|
|
|
|
default: undefined
|
|
|
|
|
|
},
|
|
|
|
|
|
// 是否只选择用户,false 表示部门也可以选择
|
|
|
|
|
|
userOnly: {
|
|
|
|
|
|
type: Boolean,
|
|
|
|
|
|
default: false
|
|
|
|
|
|
},
|
|
|
|
|
|
// 是否多选
|
|
|
|
|
|
multiple: {
|
|
|
|
|
|
type: Boolean,
|
|
|
|
|
|
default: false
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
const treeData = ref([])
|
|
|
|
|
|
const defaultProps = {
|
|
|
|
|
|
value: 'id',
|
|
|
|
|
|
label: 'label',
|
|
|
|
|
|
children: 'children'
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 加载部门和用户数据
|
|
|
|
|
|
const loadData = async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 获取部门列表
|
|
|
|
|
|
const { data: deptList } = await listDept()
|
|
|
|
|
|
// 获取用户列表
|
|
|
|
|
|
const { rows: userList } = await listUser()
|
|
|
|
|
|
|
|
|
|
|
|
// 转换部门数据
|
|
|
|
|
|
const transformedDeptList = deptList.map(dept => ({
|
|
|
|
|
|
id: `dept_${dept.deptId}`,
|
|
|
|
|
|
label: dept.deptName,
|
|
|
|
|
|
parentId: dept.parentId === 0 ? null : `dept_${dept.parentId}`,
|
|
|
|
|
|
type: 'dept'
|
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
|
|
// 转换用户数据
|
|
|
|
|
|
const transformedUserList = userList.map(user => ({
|
2025-08-07 13:03:28 +08:00
|
|
|
|
id: `${user.userId}`,
|
2025-08-06 17:09:15 +08:00
|
|
|
|
label: user.nickName || user.userName,
|
|
|
|
|
|
parentId: `dept_${user.deptId}`,
|
|
|
|
|
|
type: 'user'
|
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
|
|
// 如果只选择用户,过滤掉部门节点
|
|
|
|
|
|
let allNodes = props.userOnly
|
|
|
|
|
|
? transformedUserList
|
|
|
|
|
|
: [...transformedDeptList, ...transformedUserList]
|
|
|
|
|
|
|
|
|
|
|
|
// 构建树形结构
|
|
|
|
|
|
treeData.value = buildTree(allNodes)
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('加载数据失败:', error)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 构建树形结构
|
|
|
|
|
|
const buildTree = (nodes) => {
|
|
|
|
|
|
const map = {}
|
|
|
|
|
|
const result = []
|
|
|
|
|
|
|
|
|
|
|
|
// 创建节点映射
|
|
|
|
|
|
nodes.forEach(node => {
|
|
|
|
|
|
map[node.id] = { ...node, children: [] }
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
// 构建树形关系
|
|
|
|
|
|
nodes.forEach(node => {
|
|
|
|
|
|
const current = map[node.id]
|
|
|
|
|
|
if (node.parentId) {
|
|
|
|
|
|
const parent = map[node.parentId]
|
|
|
|
|
|
if (parent) {
|
|
|
|
|
|
parent.children.push(current)
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
result.push(current)
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 使用计算属性处理双向绑定
|
|
|
|
|
|
const modelVal = computed({
|
|
|
|
|
|
get: () => props.modelValue,
|
|
|
|
|
|
set: (value) => {
|
|
|
|
|
|
emit('update:modelValue', value)
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
// 处理值更新
|
|
|
|
|
|
const updateValue = (value) => {
|
|
|
|
|
|
modelVal.value = value
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 处理选择变化
|
|
|
|
|
|
const handleChange = (value) => {
|
|
|
|
|
|
emit('change', value)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 组件挂载时加载数据
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
loadData()
|
|
|
|
|
|
})
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
|
.el-tree-select {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|