199 lines
4.9 KiB
Vue
199 lines
4.9 KiB
Vue
<template>
|
||
<div class="form-item-box zk-frameWork-wrap" :style="{ width: width }">
|
||
<el-select
|
||
:model-value="frameWork"
|
||
:placeholder="placeholder"
|
||
@clear="handleClear"
|
||
@change="selectChange"
|
||
:clearable="clearable"
|
||
v-bind="$attrs"
|
||
:multiple="multiple"
|
||
popper-class="frameWork-select"
|
||
>
|
||
<el-option value="1" style="display: none"></el-option>
|
||
<el-input
|
||
v-if="filterable"
|
||
v-model="filterText"
|
||
style="width: 96% !important; margin: 0 2%; font-size: 12px"
|
||
:prefix-icon="Search"
|
||
/>
|
||
<div class="alllist">
|
||
<el-tree
|
||
ref="tree"
|
||
:data="treeData"
|
||
:props="defaultConf"
|
||
default-expand-all
|
||
:filter-node-method="filterNode"
|
||
:show-checkbox="multiple"
|
||
:node-key="nodeKey"
|
||
@check-change="handleCheckChange"
|
||
@node-click="clickNode"
|
||
/>
|
||
</div>
|
||
</el-select>
|
||
<!-- <el-icon class="errorIcon"><circle-close-filled /></el-icon>
|
||
<el-icon class="checkIcon"><circle-check-filled /></el-icon> -->
|
||
</div>
|
||
</template>
|
||
<script setup>
|
||
import { COMPONENT_WIDTH } from '@/constant';
|
||
import { nextTick, ref, watch } from "vue";
|
||
import { Search } from "@element-plus/icons-vue";
|
||
const emits = defineEmits(["handleChange"]); //子组件向父组件事件传递
|
||
const props = defineProps({
|
||
clearable: {
|
||
default: false,
|
||
type: Boolean
|
||
},
|
||
multiple: {
|
||
default: false,
|
||
type: Boolean
|
||
},
|
||
filterable: {
|
||
default: false,
|
||
type: Boolean
|
||
},
|
||
treeData: {
|
||
default: () => [],
|
||
type: Array
|
||
},
|
||
placeholder: {
|
||
default: "选择组织机构",
|
||
type: String
|
||
},
|
||
defaultConf: {
|
||
type: Object,
|
||
default: () => ({
|
||
children: "children",
|
||
label: "label"
|
||
})
|
||
},
|
||
frameWork: {
|
||
type: [String, Array],
|
||
default: ""
|
||
},
|
||
width: {
|
||
default: COMPONENT_WIDTH,
|
||
type: String
|
||
}
|
||
});
|
||
const nodeKey = "id";
|
||
const filterText = ref("");
|
||
const mineStatusValue = ref([]); //选中状态存贮
|
||
nextTick(() => {
|
||
if (props.frameWork) {
|
||
if (typeof props.frameWork === "string") {
|
||
//传过来的默认值类型
|
||
if (props.frameWork) {
|
||
tree.value.setCheckedKeys([props.frameWork], false);
|
||
}
|
||
} else {
|
||
if (props.frameWork.length > 0) {
|
||
tree.value.setCheckedKeys(props.frameWork, false);
|
||
}
|
||
}
|
||
mineStatusValue.value = treeValueFind(props.treeData, props.frameWork);
|
||
}
|
||
});
|
||
const tree = ref(null);
|
||
let deferTimer;
|
||
watch(filterText, (val) => {
|
||
tree.value.filter(val);
|
||
});
|
||
const filterNode = (value, data) => {
|
||
if (!value) return true;
|
||
return data[props.defaultConf.label].indexOf(value) !== -1;
|
||
};
|
||
|
||
//多选选中
|
||
const handleCheckChange = () => {
|
||
const res = tree.value.getCheckedNodes(true, true); // 这里两个true,1. 是否只是叶子节点 2. 是否包含半选节点
|
||
mineStatusValue.value = res;
|
||
clearTimeout(deferTimer);
|
||
deferTimer = setTimeout(() => {
|
||
emits("handleChange", res);
|
||
}, 200);
|
||
};
|
||
//节点选择
|
||
const clickNode = (data, node, obj) => {
|
||
if (props.multiple) {
|
||
// 多选不执行
|
||
const index = mineStatusValue.value.findIndex((d) => d.id === data.id);
|
||
if (index > -1) {
|
||
tree.value.setChecked(data, false);
|
||
} else {
|
||
tree.value.setChecked(data, true);
|
||
}
|
||
return;
|
||
}
|
||
if (!data.children) {
|
||
mineStatusValue.value.push(data.id);
|
||
tree.value.setCheckedKeys([data.id], false);
|
||
}
|
||
};
|
||
//select值变化
|
||
const selectChange = (e) => {
|
||
if (!props.multiple || !props.treeData.length) {
|
||
return false;
|
||
}
|
||
const arrNew = [];
|
||
const dataLength = mineStatusValue.value.length;
|
||
const eleng = e.length;
|
||
for (let i = 0; i < dataLength; i++) {
|
||
for (let j = 0; j < eleng; j++) {
|
||
if (e[j] === mineStatusValue.value[i][props.defaultConf.label]) {
|
||
arrNew.push(mineStatusValue.value[i][nodeKey]);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
setTimeout(() => {
|
||
tree.value.setCheckedKeys(arrNew, false);
|
||
}, 200);
|
||
};
|
||
//select clear
|
||
const handleClear = (e) => {
|
||
mineStatusValue.value = [];
|
||
tree.value.setCheckedKeys([], false);
|
||
};
|
||
const treeValueFind = (tree, arr, newArr = []) => {
|
||
if (typeof arr === "string") {
|
||
tree.forEach((el) => {
|
||
if (el[nodeKey] === arr) {
|
||
newArr.push(el);
|
||
}
|
||
if (el[props.defaultConf.children]) {
|
||
treeValueFind(el[props.defaultConf.children], arr, newArr);
|
||
}
|
||
});
|
||
} else {
|
||
for (let i = arr.length; i >= 0; i--) {
|
||
tree.forEach((el) => {
|
||
if (el[nodeKey] === arr[i]) {
|
||
newArr.push(el);
|
||
arr.splice(i, 1);
|
||
}
|
||
if (el[props.defaultConf.children] && arr.length > 0) {
|
||
treeValueFind(el[props.defaultConf.children], arr, newArr);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
return newArr;
|
||
};
|
||
</script>
|
||
<style lang="scss" scoped>
|
||
.optionclass {
|
||
height: auto;
|
||
padding: 0;
|
||
position: relative;
|
||
width: 100%;
|
||
overflow-y: overflow;
|
||
}
|
||
.zk-frameWork-wrap {
|
||
.el-select {
|
||
width: 100%;
|
||
}
|
||
}
|
||
</style>
|