先说一下需求吧。因为所作系统存在多租户的情况,一个用户可能属于不同租户,所有选择任意一个用户时,要求选中所有不同租户下的全部相同用户,并且在选择框内只展示一个用户。如下图效果:
使用组件是 treeSelect,实现思路是:当选择时遍历数据,选中所有相同 userId 的数据,取消选中亦是。 难点在于如何在输入框只展示一条。找了半天文档没找到,最终通过操作节点,隐藏节点实现。具体代码如下:
<template>
<div id="app">
<treeselect :value="value" :multiple="true" style="width: 300px" :default-expand-level="3" :options="options"
:normalizer="normalizer" @select="select" @deselect="deselect">
<div slot="value-label" slot-scope="{ node }">{{ node.raw.userName }}<span class="user-div">{{node.raw.userId}}</span></div>
</treeselect>
</div>
</template>
<script>
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
const OPTIONS = [
{
userId: 'all',
userName: '全选',
children: [
{
id: 'tenant1',
tenantName: '钻石集团',
children: [{
userId: 'admin001',
tenantId: 'tenant1',
userName: '租户1'
}, {
userId: 'admin002',
tenantId: 'tenant1',
userName: '租户2'
}]
}, {
id: 'tenant2',
tenantName: '铂金集团',
children: [{
userId: 'admin001',
tenantId: 'tenant2',
userName: '租户1'
}, {
userId: 'admin003',
tenantId: 'tenant2',
userName: '租户3'
}, {
userId: 'admin004',
tenantId: 'tenant2',
userName: '租户4'
}]
}, {
id: 'tenant3',
tenantName: '黄金集团',
children: [{
userId: 'admin001',
tenantId: 'tenant3',
userName: '租户1'
}, {
userId: 'admin005',
tenantId: 'tenant3',
userName: '租户5'
}]
}
]
}
]
export default {
components: {Treeselect},
data () {
return {
value: [],
options: [],
allList: [],
normalizer (node) {
if (node.id) {
node.userId = node.id
node.userName = node.tenantName
}
return {
id: `${node.userId}${node.tenantId ? (';' + node.tenantId) : ''}`,
label: node.userName,
children: node.children
}
}
}
},
methods: {
/**
* 选中节点
* @param node
*/
select (node) {
if (node.userId === 'all') {
this.value = this.allList.map(el => `${el.userId};${el.tenantId}`)
} else if (node.id && node.children) {
let users = []
node.children.forEach(item => {
let info = this.allList.filter(el => el.userId === item.userId).map(el => `${el.userId};${el.tenantId}`)
users = [...users, ...info]
})
this.value = Array.from(new Set([...this.value, ...users]))
} else {
let users = this.allList.filter(el => el.userId === node.userId).map(el => `${el.userId};${el.tenantId}`)
this.value = [...this.value, ...users]
}
this.$nextTick(() => {
let userIds = []
let nodes = document.getElementsByClassName('vue-treeselect__multi-value-item-container')
for (let item of nodes) {
let info = item.getElementsByClassName('user-div')
let userId = info[0].innerHTML
if (userIds.includes(userId)) {
item.style.display = 'none'
} else {
userIds.push(userId)
}
}
})
},
/**
* 取消选中
* @param node
*/
deselect (node) {
if (node.userId === 'all') {
this.value = []
} else if (node.id && node.children) {
node.children.forEach(item => {
this.value = this.value.filter(el => !el.includes(item.userId))
})
} else {
this.value = this.value.filter(el => !el.includes(node.userId))
}
}
},
created () {
this.options = OPTIONS
this.allList = []
OPTIONS[0].children.forEach(item => {
this.allList = [...this.allList, ...item.children]
})
}
}
</script>
<style scoped>
.user-div{
display: none;
}
</style>