<template>
|
<div>
|
<el-tree
|
ref="tree"
|
class="comb-tree"
|
:disabled="disabled"
|
highlight-current
|
:check-strictly="checkStrictly"
|
:default-expand-all="!lazy"
|
:expand-on-click-node="true"
|
:props="defaultProps"
|
:show-checkbox="multiple"
|
:check-on-click-node="leafOnly"
|
:node-key="idField"
|
:data="treeDatas"
|
:filter-node-method="filterNode"
|
:lazy="lazy"
|
:load="loadNode"
|
:default-expanded-keys="expandedIds"
|
@node-click="onNodeClick"
|
@check-change="onCheckChange">
|
</el-tree>
|
<div style="margin-top: 10px;">{{filterTip}}</div>
|
</div>
|
</template>
|
<script>
|
|
import cloneDeep from 'lodash/cloneDeep'
|
|
export default {
|
name: 'ZtTreeSelector',
|
components: {},
|
props: {
|
value: [String, Array],
|
idField: {
|
type: String,
|
default: 'id'
|
},
|
textField: {
|
type: String,
|
default: 'name'
|
},
|
disabled:{
|
type: Boolean,
|
default: false,
|
},
|
parentIdField: {
|
type: String,
|
default: 'pid'
|
},
|
url: String,
|
datas: [String, Array],
|
simple: Boolean, // 简单模式
|
multiple: { // 默认多选
|
type: Boolean,
|
default: true
|
},
|
leafOnly: { // 是否只能选择叶子节点
|
type: Boolean,
|
default: false
|
},
|
hasHalfChecked: { // 是否包含半选的节点
|
type: Boolean,
|
default: false
|
},
|
checkStrictly: { // 在显示复选框的情况下,是否严格的遵循父子不互相关联的做法
|
type: Boolean,
|
default: false
|
},
|
lazy: { // 懒加载子节点
|
type: Boolean,
|
default: false
|
},
|
expandLevel: { // 懒加载展开层级
|
type: Number,
|
default: 0
|
},
|
disabledFilter: Function, // 可选的节点
|
placeholder: String
|
},
|
data() {
|
return {
|
editing: false,
|
dataList: [],
|
treeDatas: [], // 带children的
|
dataMap: {},
|
expandedIds: [],
|
filterTip: '',
|
defaultProps: {
|
children: 'children',
|
label: this.textField,
|
isLeaf: 'leaf',
|
disabled: this.disabledFilter
|
}
|
}
|
},
|
computed: {},
|
watch: {
|
value(val, oldval) {
|
if (!this.editing) {
|
this.setText(val)
|
}
|
this.editing = false
|
},
|
url(val, oldval) {
|
this.queryDataList(val)
|
},
|
datas(val, oldval) {
|
this.setDataList(val)
|
}
|
},
|
mounted() {
|
if (this.datas !== undefined && this.datas.length > 0) {
|
this.setDataList(cloneDeep(this.datas))
|
} else if (this.url !== undefined) { // 指定了url
|
this.queryDataList(this.url)
|
}
|
},
|
methods: {
|
async queryDataList(url) {
|
let res = await this.$http.get(url, null)
|
this.setDataList(res.data)
|
},
|
setDataList(data) { // 设置树的值
|
let dataList
|
if (Array.isArray(data)) {
|
dataList = data
|
} else {
|
dataList = data.rows
|
}
|
if (this.simple === true) { // 简单数组
|
this.dataList = dataList
|
|
let dataMap = {}
|
let treeDatas = []
|
dataList.forEach(item => {
|
dataMap[item[this.idField]] = item
|
})
|
dataList.forEach(item => {
|
let parent = this.dataMap[item[this.parentIdField]]
|
if (parent) { // 存在父节点
|
let children = parent.children || []
|
children.push(item)
|
parent.children = children
|
} else {
|
treeDatas.push(item)
|
}
|
})
|
this.treeDatas = treeDatas
|
this.flattenTrees(treeDatas) // 设置level
|
} else { // 带children的
|
this.treeDatas = dataList
|
this.dataList = this.flattenTrees(dataList)
|
}
|
if (this.lazy) { // 懒加载时
|
let expandedIds = []
|
this.dataList.forEach(item => {
|
// console.log(item,'itemitemitemitem')
|
if (item.children ===undefined || item.children.length === 0) {
|
item.leaf = true
|
}
|
if (item._level < this.expandLevel) {
|
expandedIds.push(item[this.idField])
|
}
|
})
|
this.expandedIds = expandedIds
|
}
|
if (this.value && this.value.length > 0) {
|
this.setText(this.value)
|
}
|
},
|
|
filter(val) { // 输入过滤
|
this.filterTip = ''
|
if (this.lazy && val.length > 0) {
|
let expandedIds = [] // 需要展开的节点
|
for (var i = 0; i < this.dataList.length; i++) {
|
let item = this.dataList[i]
|
if (item[this.textField].indexOf(val) !== -1) {
|
expandedIds.push(item[this.idField])
|
}
|
}
|
if (expandedIds.length > 0) {
|
let maxLength = 50
|
if (expandedIds.length >= maxLength) { // 最多展示maxLength条
|
this.filterTip = `*找到${expandedIds.length}条结果,只展示前${maxLength}条`
|
expandedIds = expandedIds.slice(0, maxLength)
|
}
|
this.expandNodes(expandedIds)
|
this.$nextTick(() => {
|
this.$refs.tree.filter(val)
|
})
|
return
|
}
|
}
|
this.$refs.tree.filter(val)
|
},
|
onNodeClick(data, node) { // 单选:修改了父节点也可以被选中。
|
if (!this.multiple && (!this.disabledFilter || !this.disabledFilter(data))) { // 单选
|
if (this.leafOnly && (data.children || []).length > 0) { // 只能选择叶子节点,但当前不是叶子节点
|
return
|
}
|
this.editing = true // 编辑中
|
|
this.$emit('input', data[this.idField])
|
this.$emit('selected', data, true)
|
}
|
},
|
onCheckChange(data, checked, indeterminate) { // 多选选中
|
if (this.multiple) {
|
this.editing = true // 编辑中
|
let checkedNodes = this.$refs.tree.getCheckedNodes(this.leafOnly)
|
if (this.hasHalfChecked) { // 半选的
|
checkedNodes = checkedNodes.concat(this.$refs.tree.getHalfCheckedNodes())
|
}
|
checkedNodes = checkedNodes.filter(node => (!this.disabledFilter || !this.disabledFilter(node))) // 所有允许选中的
|
let values = []
|
checkedNodes.forEach(node => {
|
values.push(node[this.idField])
|
})
|
this.$emit('input', values)
|
this.$emit('selected', checkedNodes, true)
|
}
|
},
|
cancelSelected(node) { // 取消节点选中
|
this.$refs.tree.setChecked(node, false)
|
},
|
setText(value) { // 设置值
|
value = value || ''
|
if (!this.multiple) { // 单选
|
if (!value) {
|
this.$emit('selected', null, false)
|
} else {
|
let that = this
|
let nodes = this.dataList.filter(item => item[that.idField] === value)
|
if (nodes && nodes.length === 1) {
|
this.$refs.tree.setCurrentKey(nodes[0][that.idField])// 选中
|
this.$emit('selected', nodes[0], false)
|
} else {
|
this.$emit('selected', null, false)
|
}
|
}
|
} else { // 多选
|
let selectValues = Array.isArray(value) ? value : value.split(',')
|
let selectNodes = this.dataList.filter(d => selectValues.indexOf(d[this.idField]) >= 0)
|
let values = []
|
selectNodes.filter(d => (d.children || []).length === 0).forEach(node => {
|
if (!this.disabledFilter || !this.disabledFilter(node)) {
|
values.push(node[this.idField])
|
}
|
})
|
this.$refs.tree.setCheckedKeys(values)// 会级联选中上级
|
this.$emit('selected', selectNodes, false)
|
}
|
if (this.lazy) { // 懒加载时
|
if (value.length > 0) {
|
this.expandNodes(Array.isArray(value) ? value : value.split(','))
|
}
|
}
|
},
|
filterNode(value, data) { // 筛选
|
if (!value) {
|
return true
|
}
|
return data[this.textField].indexOf(value) !== -1 && (!this.disabledFilter || !this.disabledFilter(data))
|
},
|
flattenTrees(trees, level = 0) { // tree转array
|
let result = []
|
trees.forEach(item => {
|
result.push(item)
|
item._level = level
|
item.children && result.push(...this.flattenTrees(item.children, level + 1))
|
})
|
return result
|
},
|
loadNode(node, resolve) {
|
let that = this
|
if (node.level === 0) {
|
return resolve(that.treeDatas)
|
} else if (node.data) {
|
return resolve((node.data.children || []))
|
} else {
|
return resolve([])
|
}
|
},
|
expandNodes(ids) { // 展开节点及其父节点
|
let expandedIds = []
|
let getParentIds = (id) => {
|
if (expandedIds.indexOf(id) !== -1) {
|
return []
|
}
|
for (var i = 0; i < this.dataList.length; i++) {
|
let item = this.dataList[i]
|
if (expandedIds.indexOf(item[this.idField]) === -1) {
|
if (item.children != undefined)
|
{
|
for (var j = 0; j < item.children.length; j++) {
|
let children = item.children[j]
|
if (children[this.idField] === id) {
|
return [item.id, ...getParentIds(item.id)]
|
}
|
}
|
}
|
}
|
}
|
return []
|
}
|
ids.forEach((id) => {
|
expandedIds.push(...getParentIds(id), id)
|
})
|
this.expandedIds = expandedIds
|
}
|
}
|
}
|
</script>
|
<style lang="scss">
|
.is-reverse {
|
transform: rotate(-180deg);
|
}
|
|
.comb-tree {
|
display: flex;
|
width: auto;
|
height: 250px;
|
overflow-y: auto;
|
|
label.el-checkbox {
|
margin-right: 8px;
|
}
|
}
|
</style>
|