
<template>
<div>
<el-cascader
v-model="selected"
clearable
filterable
:options="userOption"
:props="{
multiple: true,
value: 'value',
label: 'label',
}"
:collapse-tags="true"
placeholder="请选择"
@change="selectHandle"
>
<template #default="{ node, data }">
<span>{{ data.label }}</span>
<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
</template>
</el-cascader>
</div>
</template>
<script setup>
import { ref } from "vue";
const preSelected = ref([]); // 上次选中的数据
const originData = ref([]); // 源数据平铺成一级节点
const defaultExpandedKeys = ref([]);
const selected = ref([]);
const userOption = ref([
{ label: "全选", value: "全选" },
{ label: "层级0", value: "0" },
{
label: "层级1",
value: "1",
children: [
{
label: "层级11",
value: "11",
children: [
{ label: "层级111", value: "111" },
{ label: "层级112", value: "112" },
],
},
{
label: "层级12",
value: "12",
children: [{ label: "层级121", value: "121" }],
},
],
},
{
label: "层级2",
value: "2",
children: [
{ label: "层级21", value: "21" },
{ label: "层级22", value: "22" },
],
},
{
label: "层级3",
value: "3",
children: [{ label: "层级31", value: "31" }],
},
]);
const judgetAllSelected = (node) => {
let isAllSelected = false;
for (let i = 0; i < node.length; i++) {
if (node[i][0] === "全选") {
isAllSelected = true;
break;
}
}
return isAllSelected;
};
const loopFlatData = (list, parentNode = []) => {
list.length > 0 &&
list.forEach((e) => {
let pNode = [...parentNode];
if (e.children && e.children.length > 0) {
pNode.push(e.value);
loopFlatData(e.children, pNode);
} else {
if (e.label !== "全选") {
if (parentNode.length > 0) {
pNode.push(e.value);
originData.value.push({ ...e, parentNode: pNode });
} else {
originData.value.push(e);
}
}
}
});
};
const loopSelectData = (list, parentNode = []) => {
list.length > 0 &&
list.forEach((e) => {
let pNode = [...parentNode];
if (e.children && e.children.length > 0) {
pNode.push(e.value);
loopSelectData(e.children, pNode);
} else {
if (parentNode.length > 0) {
selected.value.push([...parentNode, e.value]);
} else {
selected.value.push([e.value]);
}
}
});
};
const checkIsAddAllSelected = () => {
let list = userOption.value;
if (originData.value.length === 0) {
loopFlatData(list);
}
let origin = originData.value;
let now = [...selected.value].filter((item) => item[0] !== "全选");
if (origin.length > now.length) {
selected.value = selected.value.filter((item) => item[0] !== "全选");
} else {
if (selected.value[0] && selected.value[0][0] !== "全选") {
selected.value = [["全选"], ...selected.value];
}
}
};
const selectHandle = async (node) => {
defaultExpandedKeys.value = [];
selected.value = [];
let list = userOption.value;
let current = [];
if (node.length >= preSelected.value.length) {
let keys = preSelected.value.map((item) => JSON.stringify(item));
current = node.filter((item) => !keys.includes(JSON.stringify(item)));
console.log("选中某项", current);
} else {
let keys = node.map((item) => JSON.stringify(item));
current = preSelected.value.filter(
(item) => !keys.includes(JSON.stringify(item))
);
console.log("取消选中", current);
defaultExpandedKeys.value = current[0];
}
const currentValue = current.length > 0 ? current[0][0] || "" : "";
if (currentValue === "全选") {
if (judgetAllSelected(node)) {
loopSelectData(list);
} else {
selected.value = [];
}
} else {
selected.value = node;
}
checkIsAddAllSelected();
preSelected.value = selected.value;
changeHandle();
};
const changeHandle = () => {
console.log("changeHandle: ", selected.value);
};
</script>