:filter-node-method="filterNodeMethod"此方法对应的是模糊搜索,
// 获取树形数据
const loadTreeData = async () => {
try {
const res = await deviceTree()
if (res.data) {
treeData.value = res.data
// 构建 ID 到标签的映射
idMap.value = new Map()
const buildMap = (nodes) => {
nodes.forEach((node) => {
idMap.value.set(node.id, node.label)
if (node.children) buildMap(node.children)
})
}
buildMap(res.data)
isDataLoaded.value = true
}
} catch (error) {
console.error('获取树形数据失败:', error)
}
}
剩余都是正常的通信,根据自己需要增加参数,下面是整体代码
<template>
<div class="custom-tree-select">
<el-tree-select
v-model="selectedValue"
ref="treeSelectRef"
:data="treeData"
multiple
:max-collapse="2"
collapse-tags
collapse-tags-tooltip
show-checkbox
:filter-node-method="filterNodeMethod"
filterable
node-key="id"
:props="defaultProps"
:style="{ width: width }"
@check="handleCheck"
clearable
@clear="handleClear"
:placeholder="placeholder"
:default-expanded-keys="['1']"
:max-tag-count="maxTagCount"
:max-collapse-tags="maxCollapseTags"
@remove-tag="handleRemoveTag"
:max-tag-placeholder="() => `已选${selectedValue.length}个`">
<!-- 自定义折叠标签显示 -->
<template #collapse-tag>
<div class="custom-collapse-tag">
已选择 {{ selectedValue.length }} 个设备
</div>
</template>
</el-tree-select>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { deviceTree } from '@/api/positioning/apiPositioning'
const props = defineProps({
width: {
type: String,
default: '100%',
},
placeholder: {
type: String,
default: '请选择设备',
},
maxTagCount: {
type: Number,
default: 2
},
maxCollapseTags: {
type: Number,
default: 1 // 设置显示的标签数量
}
})
const emit = defineEmits(['update:deviceIds', 'update:selectedIds'])
const treeSelectRef = ref(null)
const treeData = ref([])
const selectedValue = ref([])
const idMap = ref(new Map())
const isDataLoaded = ref(false)
const handleClear = () => {
emit('update:selectedIds', [])
emit('update:deviceIds', [])
}
// 树形配置
const defaultProps = {
children: 'children',
label: 'label',
}
// 处理节点选中状态变化
const handleCheck = (data, { checkedNodes }) => {
// 过滤出最后一层且有 deviceId 的节点
const leafNodes = checkedNodes.filter((node) => {
return (!node.children || node.children.length == 0) && node.deviceId
})
// 更新选中的节点ID和设备ID
// selectedValue.value = leafNodes.map((node) => node.id)
const deviceIds = leafNodes.map((node) => node.deviceId)
// 向父组件发送更新事件
emit('update:selectedIds', selectedValue.value)
emit('update:deviceIds', deviceIds)
}
// 获取树形数据
const loadTreeData = async () => {
try {
const res = await deviceTree()
if (res.data) {
treeData.value = res.data
// 构建 ID 到标签的映射
idMap.value = new Map()
const buildMap = (nodes) => {
nodes.forEach((node) => {
idMap.value.set(node.id, node.label)
if (node.children) buildMap(node.children)
})
}
buildMap(res.data)
isDataLoaded.value = true
}
} catch (error) {
console.error('获取树形数据失败:', error)
}
}
// 提供重置方法
const reset = () => {
selectedValue.value = []
if (treeSelectRef.value) {
treeSelectRef.value.setCheckedKeys([])
}
emit('update:selectedIds', [])
emit('update:deviceIds', [])
}
// 添加删除标签的处理函数
const handleRemoveTag = (removedTag) => {
// 从选中值中移除被删除的标签
selectedValue.value = selectedValue.value.filter(id => id !== removedTag)
// 更新树形控件的选中状态
if (treeSelectRef.value) {
treeSelectRef.value.setCheckedKeys(selectedValue.value)
}
// 获取当前选中的叶子节点
const checkedNodes = treeSelectRef.value.getCheckedNodes()
const leafNodes = checkedNodes.filter(node => !node.children || node.children.length === 0)
const deviceIds = leafNodes.map(node => node.deviceId)
// 发送更新事件
emit('update:selectedIds', selectedValue.value)
emit('update:deviceIds', deviceIds)
}
const filterNodeMethod = (value, data) => {
if (!isDataLoaded.value) return false
if (!value) return true
const searchValue = value.toLowerCase()
const traverse = (node) => {
if (node.label && node.label.toLowerCase().includes(searchValue)) {
return true
}
if (node.children) {
for (const child of node.children) {
if (traverse(child)) {
return true
}
}
}
return false
}
return traverse(data)
}
// 暴露方法给父组件
defineExpose({
reset,
treeSelectRef,
})
// 初始化加载数据
loadTreeData()
</script>
<style lang="scss" scoped>
.custom-tree-select {
:deep(.el-tree-select) {
.el-select__tags {
max-width: calc(100% - 30px);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
// 自定义折叠标签样式
.custom-collapse-tag {
display: inline-flex;
align-items: center;
height: 24px;
padding: 0 8px;
font-size: 12px;
color: var(--el-text-color-regular);
background: var(--el-fill-color-light);
border-radius: 4px;
}
// 调整标签间距
.el-select__tags-text {
margin-right: 4px;
}
}
}
</style>