This commit is contained in:
Jerry
2020-08-13 20:48:34 +08:00
parent cba38ca880
commit cf54acfc38
865 changed files with 38797 additions and 11325 deletions

View File

@@ -0,0 +1,300 @@
<template>
<el-popover ref="popover" placement="bottom-start" trigger="click" popper-class="tree-select-popover"
:width="width" @show="onShowPopover">
<el-scrollbar :style="{'height': this.height, 'min-width': this.width}" ref="scrollbar">
<el-tree ref="dropdownTree" :props="getTreeProps" :highlightCurrent="highlightCurrent" :nodeKey="getDataProps.value"
:defaultExpandAll="defaultExpandAll" :expandOnClickNode="expandOnClickNode" :checkOnClickNode="checkOnClickNode"
:autoExpandParent="autoExpandParent" :defaultExpandedKeys="defaultExpandedKeys" :showCheckbox="showCheckbox"
:checkStrictly="checkStrictly" :defaultCheckedKeys="defaultCheckedKeys" :currentNodeKey="getCurrentNodeKey"
:accordion="accordion" :indent="indent" :iconClass="iconClass" :load="loadChildrenNodes" lazy :show-checkbox="multiple"
@node-click="onTreeNodeClick" @check="onTreeNodeCheck">
<span :style="getNodeStyle(data)" slot-scope="{ node, data }">{{data[getDataProps.label]}}</span>
</el-tree>
</el-scrollbar>
<el-select slot="reference" v-model="selectKeys" :multiple="multiple" :disabled="false" :size="size"
:clearable="clearable" :collapseTags="collapseTags" :placeholder="placeholder" popper-class="select-tree-popper"
@clear="onClear" @remove-tag="onClear">
<el-option v-for="item in selectNodes" :key="item[getDataProps.value]"
:value="item[getDataProps.value]" :label="item[getDataProps.label]" />
</el-select>
</el-popover>
</template>
<script>
import { findTreeNode } from '@/utils';
export default {
name: 'TreeSelect',
props: {
value: {
type: [String, Number]
},
multiple: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
},
size: {
type: String
},
height: {
type: String,
default: '200px'
},
width: {
type: String,
default: '300px'
},
activeColor: {
type: String,
default: '#EF5E1C'
},
clearable: {
type: Boolean,
default: false
},
collapseTags: {
type: Boolean,
default: true
},
placeholder: {
type: String
},
loading: {
type: Boolean,
default: false
},
loadingText: {
type: String,
default: '加载中'
},
// 树属性
data: {
type: Array
},
props: {
type: Object,
default: () => {
return {
label: 'label',
value: 'value',
parentKey: 'parentId',
children: 'children',
disabled: 'disabled'
}
}
},
defaultExpandAll: {
type: Boolean,
default: false
},
expandOnClickNode: {
type: Boolean,
default: true
},
checkOnClickNode: {
type: Boolean,
default: false
},
autoExpandParent: {
type: Boolean,
default: true
},
defaultExpandedKeys: {
type: Array
},
checkStrictly: {
type: Boolean,
default: true
},
currentNodeKey: {
type: [String, Number]
},
accordion: {
type: Boolean,
default: false
},
indent: {
type: Number,
default: 16
},
iconClass: {
type: String
}
},
data () {
return {
rootNode: undefined,
rootResolve: undefined,
allTreeNode: [],
selectNodes: [],
scrollTop: 0,
selectKeys: undefined
}
},
methods: {
onShowPopover () {
setTimeout(() => {
this.$refs.scrollbar.wrap.scrollTop = this.scrollTop;
// this.$refs.scrollbar.update();
}, 20);
if (!this.multiple) {
this.$refs.dropdownTree.setCurrentKey(this.value);
}
},
onClear () {
this.$nextTick(() => {
this.$emit('input', this.selectKeys);
});
},
onTreeNodeClick (data, node) {
this.$refs.popover.showPopper = false;
if (!this.multiple) {
this.scrollTop = this.$refs.scrollbar.wrap.scrollTop;
this.$emit('input', data[this.getDataProps.value]);
this.$emit('change', data[this.getDataProps.value]);
}
},
onTreeNodeCheck (data, {checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys}) {
this.scrollTop = this.$refs.scrollbar.wrap.scrollTop
this.$emit('input', checkedKeys);
this.$emit('change', checkedKeys);
},
parseNode (node) {
if (Array.isArray(node) && node.length > 0) {
node.forEach((item) => {
item['__node_is_leaf__'] = !(Array.isArray(item[this.getDataProps.children]) && item[this.getDataProps.children].length > 0);
});
return node;
} else {
return [];
}
},
loadChildrenNodes (node, resolve) {
if (node.level === 0) {
this.rootNode = node;
this.rootResolve = resolve;
return resolve(this.parseNode(this.allTreeNode));
} else {
return resolve(this.parseNode(node.data[this.getDataProps.children]));
}
},
getNodeStyle (data) {
if (!this.multiple && (this.selectNodes[0] || {})[this.getDataProps.value] === data[this.getDataProps.value]) {
return {
color: this.activeColor,
'font-weight': 700
}
}
}
},
computed: {
showCheckbox () {
return this.multiple;
},
getCurrentNodeKey () {
if (!this.multiple && Array.isArray(this.selectNodes) && this.selectNodes.length > 0) {
return this.selectNodes[0][this.getDataProps.value];
} else {
return null;
}
},
highlightCurrent () {
return this.multiple;
},
defaultCheckedKeys () {
return this.multiple ? this.selectNodes : undefined
},
getDataProps () {
return {
label: this.props.label || 'label',
value: this.props.value || 'value',
parentKey: this.props.parentKey || 'parentId',
children: this.props.children || 'children',
disabled: this.props.disabled || 'disabled'
}
},
getTreeProps () {
return {
label: this.getDataProps.label,
children: '__children_list__',
disabled: this.getDataProps.disabled,
isLeaf: '__node_is_leaf__'
};
}
},
watch: {
data: {
handler (newValue, oldValue) {
this.allTreeNode = newValue;
if (this.rootNode != null && this.rootResolve != null) {
this.rootNode.childNodes = [];
this.loadChildrenNodes(this.rootNode, this.rootResolve);
}
this.selectNodes = [];
if (this.multiple) {
if (Array.isArray(this.value)) {
this.value.forEach((item) => {
let data = findTreeNode(this.allTreeNode, item, this.getDataProps.value, this.getDataProps.children);
if (data) this.selectNodes.push(data);
});
}
} else {
let data = findTreeNode(this.allTreeNode, this.value, this.getDataProps.value, this.getDataProps.children);
if (data) this.selectNodes.push(data);
}
},
immediate: true
},
value: {
handler (newValue) {
this.selectNodes = [];
if (Array.isArray(newValue)) {
newValue.forEach((item) => {
let data = findTreeNode(this.allTreeNode, item, this.getDataProps.value, this.getDataProps.children);
if (data) this.selectNodes.push(data);
});
this.selectKeys = newValue;
} else {
let data = findTreeNode(this.allTreeNode, newValue, this.getDataProps.value, this.getDataProps.children);
if (data) this.selectNodes.push(data);
this.selectKeys = newValue;
}
if (this.$refs.dropdownTree) {
this.multiple ? this.$refs.dropdownTree.setCheckedKeys(newValue) : this.$refs.dropdownTree.setCurrentKey(newValue);
}
},
immediate: true
}
}
}
</script>
<style>
.select-tree-popper {
display: none;
}
.tree-select-popover {
padding: 6px 0px;
}
.tree-select-popover .popper__arrow {
left: 35px!important;
}
.tree-select-popover .el-tree .el-tree-node__content {
height: 34px;
line-height: 34px;
}
/*
.tree-select-popover .el-tree .el-tree-node.is-current .el-tree-node__content {
color: #fdb95c;
font-weight: 700;
}
*/
.current-node {
color: #EF5E1C;
font-weight: 700;
}
</style>