mirror of
https://gitee.com/orangeform/orange-admin.git
synced 2026-01-17 18:46:36 +08:00
commit
This commit is contained in:
300
orange-demo-web/src/components/TreeSelect/index.vue
Normal file
300
orange-demo-web/src/components/TreeSelect/index.vue
Normal 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>
|
||||
Reference in New Issue
Block a user