v-show="isShowSelect">
title="" trigger="manual" v-model="isShowSelect" @hide="popoverHide"> v-model="filterText" size="small">
width="width" style="height:300px" ref="tree" :data="data" :props="obj" :show-checkbox="multiple" :node-key="obj.id" :check-strictly="checkStrictly" :default-expanded-keys="defaultKey" :default-checked-keys="checkKeys" :expand-on-click-node="multiple&&expandClickNode" :check-on-click-node="checkClickNode" :highlight-current="true" @check-change="nodeClick" :filter-node-method="filterNode" @node-click="nodeClick">
ref="select" :size="size" popper-class="operateDropOption" :popper-append-to-body="true" style="width: 300px" v-model="returnDataKeys" :multiple="multiple" :clearable="clearable" :collapse-tags="collapseTags" @click.native="selectClick" @remove-tag="removeTag" @clear="clean" class="tree-select"> :key="item.value" :label="item.label" :value="item.value">
export default {
name: "tree-select",
props: {
// 树结构数据
data: {
type: Array,
default() {
return [];
}
},
obj: {
type: Object,
required: false,
default: () => {
return {
id: 'value',// ID
label: 'label',// 显示名称
children: 'children', //子级字段名
path: 'path',//路径
content: 'content',//描述
pid: 'pid',//父id
}
}
},
// 配置是否可多选
multiple: {
type: Boolean,
default() {
return true;
}
},
// 配置是否可清空选择
clearable: {
type: Boolean,
default() {
return false;
}
},
// 配置多选时是否将选中值按文字的形式展示
collapseTags: {
type: Boolean,
default() {
return false;
}
},
// 显示复选框情况下,是否严格遵循父子不互相关联
checkStrictly: {
type: Boolean,
default() {
return false;
}
},
//多选是设置点击节点是否可以选中
checkClickNode: {
type: Boolean,
default() {
return false;
}
},
//多选时:点击节点展开还是点三角标
expandClickNode: {
type: Boolean,
default() {
return false;
}
},
// 默认选中的节点key
defaultKey: {
type: [Number, String, Array, Object],
default() {
return [''];
}
},
checkKeys: {
type: [Number, String, Array, Object],
default() {
return [''];
}
},
size: {
type: String,
default() {
return 'small';
}
},
width: {
type: String,
default() {
return '100%';
}
},
height: {
type: String,
default() {
return '100%';
}
},
},
data() {
return {
filterText: '',
popoverWidth: "300px",//下拉框大小
isShowSelect: false, // 是否显示树状选择器
options: [],//select option选项
returnDatas: [],//返回给父组件数组对象
returnDataKeys: [],//返回父组件数组主键值
};
},
computed: {
// treeData() { // 若非树状结构,则转化为树状结构数据
// return JSON.stringify(this.data).indexOf(this.obj.children) !== -1 ? this.data : this.switchTree();
// },
},
mounted() {
this.nodeClick()
addEventListener('click', (val) => {
this.isShowSelect = false
})
},
deactivated() {
this.clean()
},
methods: {
init() {
// eslint-disable-next-line no-undef,no-debugger
// debugger
if (this.defaultKey != undefined && this.defaultKey.length > 0) {
if (this.multiple) {
// 多选
if (Object.prototype.toString.call(this.defaultKey).indexOf("Array") != -1) {
if (Object.prototype.toString.call(this.defaultKey[0]).indexOf("Object") != -1) {//对象
this.setDatas(this.defaultKey);
} else if (Object.prototype.toString.call(this.defaultKey[0]).indexOf("Number") != -1
|| Object.prototype.toString.call(this.defaultKey[0]).indexOf("String") != -1) {
this.setKeys(this.defaultKey);
} else {
// console.log("多选:传入参数类型不匹配");
return;
}
} else {
// console.log("多选:传入参数类型不匹配");
return;
}
} else {
// 单选
if (Object.prototype.toString.call(this.defaultKey).indexOf("Number") != -1
|| Object.prototype.toString.call(this.defaultKey).indexOf("String") != -1
|| Object.prototype.toString.call(this.defaultKey).indexOf("Object") != -1) {
this.setKey(this.defaultKey);
} else {
// console.log("单选:传入参数类型不匹配");
return;
}
}
}
},
//下拉框select点击[入口]
selectClick() {
this.$nextTick(function () {//设置下拉框自适应宽度
this.popoverWidth = this.$refs.select.$el.clientWidth - 26;
})
//显示下拉框
return this.isShowSelect = !this.isShowSelect
},
//单选: 树点击方法
nodeClick(data, node) {
if (!this.multiple) {//单选
this.isShowSelect = false;
this.setKey(node.key);
} else {//多选
var checkedNodes = this.$refs.tree.getCheckedNodes(true, false); // 所有被选中的节点
var t = [];
// 数组去重
const map = new Map()
checkedNodes.forEach((item) => {
if (!map.has(item['id'])) {
map.set(item['id'], item)
}
})
const newCheckedNodes = [...map.values()]
var checkedKeys = newCheckedNodes.map(item => item.id) // 所有被选中的节点的 key 所组成的数组数据
this.options = checkedKeys.map((item) => {//设置option选项
var node = this.$refs.tree.getNode(item); // 所有被选中的节点对应的node
t.push(node.data);
return { label: node.label, value: node.key };
});
this.returnDataKeys = this.options.map((item) => {
return item.value;
});
this.$emit('change', this.returnDataKeys)
this.returnDatas = t;
}
},
filterNode(value, data) {
if (!value) return true;
return data.label.indexOf(value) !== -1;
},
//单选:清空选中
clean() {
this.$refs.tree.setCurrentKey(null);//清除树选中key
this.returnDatas = null; this.returnDataKeys = '';
this.popoverHide();
this.isShowSelect = false;
this.$refs.tree.setCheckedKeys([]);
this.$refs.tree.setChecked([]);
//折叠全部节点
for (let i = 0; i < this.$refs.tree.store._getAllNodes().length; i++) {
this.$refs.tree.store._getAllNodes()[i].expanded = false;
}
},
//单选:设置、初始化值 key
setKey(thisKey) {
this.$refs.tree.setCurrentKey(thisKey);
var node = this.$refs.tree.getNode(thisKey);
this.setData(node.data);
},
//单选:设置、初始化对象
setData(data) {
this.options = [];
this.options.push({ label: data[this.obj.label], value: data[this.obj.id] });
this.returnDatas = data;
this.returnDataKeys = data[this.obj.id]
},
//多选:设置、初始化值 keys
setKeys(thisKeys) {
this.$refs.tree.setCheckedKeys(thisKeys);
this.returnDataKeys = thisKeys;
var t = [];
thisKeys.map((item) => {//设置option选项
var node = this.$refs.tree.getNode(item); // 所有被选中的节点对应的node
t.push(node.data);
return { label: node.label, value: node.key };
});
this.returnDatas = t;
this.popoverHide()
},
//多选:设置、初始化对象
setDatas(data) {
this.$refs.tree.setCheckedNodes(data);
this.returnDatas = data;
var t = [];
data.map((item) => {//设置option选项
t.push(item[this.obj.id]);
});
this.returnDataKeys = t;
this.popoverHide()
},
// 多选,删除任一select选项的回调
removeTag(val) {
this.$refs.tree.setChecked(val, false);//设置为未选中
var node = this.$refs.tree.getNode(val);//获取节点
if (!this.checkStrictly && node.childNodes.length > 0) {
this.treeToList(node).map(item => {
if (item.childNodes.length <= 0) {
this.$refs.tree.setChecked(item, false);
}
});
}
this.nodeClick();
this.popoverHide();
},
//下拉框关闭执行
popoverHide() {
this.$emit('getValue', this.returnDataKeys, this.returnDatas);
},
// 多选,清空所有勾选
clearSelectedNodes() {
var checkedKeys = this.$refs.tree.getCheckedKeys(); // 所有被选中的节点的 key 所组成的数组数据
for (let i = 0; i < checkedKeys.length; i++) {
this.$refs.tree.setChecked(checkedKeys[i], false);
}
},
//树形转为集合
treeToList(tree) {
var queen = [];
var out = [];
queen = queen.concat(tree);
while (queen.length) {
var first = queen.shift();
if (first.childNodes) {
queen = queen.concat(first.childNodes);
}
out.push(first);
}
return out;
},
// switchTree() {
// return this.buildTree(this.data, this.defaultValue);
// },
// 将一维的扁平数组转换为多层级对象
// buildTree(data, id) {
// const fa = (id) => {
// const temp = [];
// for (let i = 0; i < data.length; i++) {
// const n = data[i];
// if (n[this.obj.pid] === id) {
// n[this.obj.children] = fa(n[this.obj.id]);
// temp.push(n);
// }
// }
// return temp;
// };
// return fa(id);
// },
},
watch: {
// eslint-disable-next-line no-unused-vars
isShowSelect(val) {
// 隐藏select自带的下拉框
if (!val) {
this.$refs.select.blur();
}
},
checkKeys: {
handler(newValue, oldValue) {
this.returnDataKeys = newValue;
},
deep: true,
immediate: true
},
// treeData() {//监听tree数据
// this.$nextTick(() => {
// this.init();
// })
// },
filterText(val) {
this.$nextTick(() => {
this.$refs.tree.filter(val);
})
}
}
};
.mask {
height: 300px;
position: fixed;
top: 300px;
left: 0;
opacity: 0;
z-index: 11;
}
.common-tree {
overflow: auto;
}
.tree-select {
z-index: 111;
}
.ok {
float: right;
}
.el-row {
padding-top: 0px !important;
}
.checkall-box {
width: 100%;
height: 40px;
line-height: 40px;
border-bottom: 1px solid #fff;
}
.el-popover {
min-width: 300px !important;
}
.el-popover {
min-width: 274px;
}
/* 隐藏默认下拉 */
.operateDropOption.el-select-dropdown__empty {
display: none;
}
.operateDropOption.el-select-dropdown__list {
display: none;
}
.operateDropOption.el-select-dropdown {
display: none;
}
// 滚动条
::-webkit-scrollbar {
max-width: 12px;
height: 8px;
background-color: #fff !important;
}
::-webkit-scrollbar-thumb {
border-radius: 8px;
background-color: #d8dce0 !important;
border-style: solid;
border-color: transparent;
border-width: 2px;
background-clip: padding-box;
}
::-webkit-scrollbar-track {
border-radius: 12px;
border-radius: 0 !important;
background-color: #fff !important;
}
调用:
width="width" size="small" :data="dataList" :obj="obj" multiple :default-key="defaultKey" :checkKeys="checkKeys" clearable collapseTags expand-click-node check-click-node @change="change">
import TreeSelect from '../tree-select/tree-select.vue';
import { DeviceService } from "@/service";
export default {
components: {
TreeSelect
},
data() {
return {
defaultKey: [],
dataList: [],
};
},
props: {
value: [String, Array], // 选择的值
width: {
type: String,
default() {
return '300px';
}
},
height: {
type: String,
default() {
return '200px';
}
},
obj: {
type: Object,
required: false,
default: () => {
return {
id: 'id',// ID
label: 'label',// 显示名称
children: 'children', //子级字段名
path: 'path',//路径
content: 'content',//描述
pid: 'pid',//父id
}
}
},
},
watch: {
value: {
handler(newValue, oldValue) {
this.checkKeys = newValue;
this.defaultKey = newValue;
this.$emit("input", newValue);
},
deep: true,
immediate: true
},
},
created() {
this.getDeviceGroupTree();
},
methods: {
change(val) {
this.$emit("input", val);
this.$emit("onChange", val);
},
// 获取机型组树形数据
getDeviceGroupTree() {
DeviceService.getDeviceGroupTree().then(res => {
if (res && res.data) {
this.dataList = res.data.data
}
})
}
}
};