要求一:只可选择末级节点的数据,所以采用了只有末级节点有checkdbox来控制.
要求二:选择末级节点情况下,是控制单选的,采用给每个节点加disabled属性,已选择时其他设置为不可选.
要求三:后台传的数据(共三级节点,有的只有二级影响checkedbox展示)需要拿到数据后进行过滤
要求四:实用性强,还需要满足节点都可选的业务,也就是说需要父组件传个flag值控制是都可选还是只有末节点可以传
封装的组件代码:
<template>
<vab-dialog
ref="dialog"
class="dialog-mini"
:config="dconfig"
@close="resetForm"
>
<el-input v-model="filterText" placeholder="输入关键字进行过滤" />
<el-tree
:key="treeKey"
ref="tree"
:class="checkBoxFlag ? 'checkTreeClass' : 'treeClass'"
node-key="id"
:data="treeData"
:props="treeProps"
:filter-node-method="filterNode"
:default-checked-keys="defaultCheckedKey"
:default-expanded-keys="defaultKey"
show-checkbox
@node-click="nodeClick"
@check="checkChange"
></el-tree>
</vab-dialog>
</template>
<script>
import { services } from '@/config/settings'
import request from '@/utils/request'
export default {
name: 'TreeSelect',
props: {
/* 定义title属性 */
title: {
type: String,
default: () => {
return ''
},
},
/* 定义过滤条件 key-value 不需要的话不传即可 把末节点不对应的key value过滤 */
filteCondation: {
type: Object,
default: () => {
return {}
},
},
/*定义treeProps*/
treeProps: {
type: Object,
default: () => {
return {}
},
},
/*定义请求树数据的url*/
url: {
type: String,
default: () => {
return ''
},
},
/*定义微服务service*/
service: {
type: String,
default: () => {
return ''
},
},
/*定义dialog大小*/
size: {
type: String,
default: () => {
return 'mini'
},
},
/*定义是否显示checkdbox,即是否只能选择末节点*/
checkBoxFlag: {
type: Boolean,
default: () => {
return true
},
},
},
data() {
return {
//记录checkedbox选择的数据
defaultCheckedKey: undefined,
treeKey: 0,
flag: false,
checkData: undefined,
// 默认展开的树节点
defaultKey: [],
filterText: undefined,
dconfig: {
title: '',
size: this.size,
},
treeData: [],
}
},
watch: {
filterText(val) {
this.$refs.tree.filter(val)
},
},
methods: {
//点击节点触发
nodeClick(data) {
if (!this.checkBoxFlag) {
this.checkData = []
this.checkData = data
}
},
//循环遍历树设置disabled值
selectData(data, flag) {
if (data.length > 1) {
data.forEach((item) => {
item.disabled = flag
if (item[this.treeProps.children]) {
return this.selectData(item[this.treeProps.children], flag)
}
})
} else {
data.disabled = flag
if (data[this.treeProps.children]) {
return this.selectData(data[this.treeProps.children], flag)
}
return
}
},
//获取选择的班组
checkChange(data, node) {
this.defaultCheckedKey = []
this.selectData(this.treeData[0][this.treeProps.children], !this.flag)
this.flag = !this.flag
data.disabled = false
this.treeKey = new Date().getTime()
this.$nextTick(() => {
this.$refs.tree.filter('')
})
if (this.flag) {
this.defaultKey.push(
node.halfCheckedKeys[node.halfCheckedKeys.length - 1]
)
this.defaultCheckedKey.push(node.checkedKeys[0])
this.checkData = node.checkedNodes[0]
}
},
//查询
filterNode(value, data) {
let filterFlag = true
for (let key in this.filteCondation) {
filterFlag = data[key] === this.filteCondation[key]
if (!filterFlag) break
}
if (!value) return filterFlag
return data[this.treeProps.label].indexOf(value) !== -1 && filterFlag
},
resetForm() {
this.filterText = undefined
},
async open() {
this.flag = false
this.defaultCheckedKey = []
const { data } = await request({
url: services[this.service] + this.url,
method: 'post',
// data: this.queryForm,
})
this.treeData = data
this.checkData = undefined
//给树的数据添加上disabled属性
this.treeData.forEach((item) => {
item.disabled = false
})
//过滤树的数据
this.$nextTick(() => {
this.filterText = ''
})
this.defaultKey.push(this.treeData[0].id)
this.treeData[0].children &&
this.defaultKey.push(this.treeData[0].children[0].id)
this.dconfig.title = '选择' + this.title
// 为表单赋值
this.$refs.dialog.open((cancel) => {
// 提交按钮回调--触发表单的校验以及提交
if (!this.checkData) {
this.$message.error('请选择' + this.title)
} else {
this.$emit('getselecteddata', this.checkData)
cancel()
}
})
},
},
}
</script>
<style lang="scss" scoped>
.dialog-mini {
::v-deep {
.el-dialog__body {
height: 420px;
}
}
}
::v-deep {
.treeClass {
.el-checkbox .el-checkbox__inner {
display: none;
}
}
}
::v-deep {
.el-tree-node__content > label.el-checkbox {
margin-right: 3px;
}
}
::v-deep {
.checkTreeClass {
padding-top: 15px;
padding-left: 10px;
// 不可全选样式
.el-tree-node {
.is-leaf + .el-checkbox .el-checkbox__inner {
display: inline-block;
}
.el-checkbox .el-checkbox__inner {
display: none;
}
}
}
}
</style>
父组件的调用:
<template>
<vab-dialog-tree
ref="maintenance"
title="维护班组"
:filte-condation="filterCondation"
:tree-props="treeProps1"
:check-box-flag="true"
service="sys"
url="/org/getTree"
@getselecteddata="getSelectTreeData"
></vab-dialog-tree>
</template>
data:
//定义弹窗树的过滤条件
filterCondation: {
deptNature: '班组',
},
//定义维护班组的treeprops
treeProps1: {
children: 'children',
label: 'deptName',
},
效果图:
1.只可选末级节点情况
2.都可选情况:(单选,click事件选择)