若子元素全选取子元素与父元素值集合
若子元素未全选,则只取子元素值集合
/**
* 处理级联选择结果
* @param {Array[]} selectedPaths 选中的路径数组,如 [["66","603","1399","1791"], ["66","603","1399","1792"]]
* @param {Object[]} fullTreeData 完整的树形结构数据
* @param {string} field 节点ID字段,默认为 'id'
* @returns {string[]} 处理后的集合数组
*/
export const processCascaderSelection = (selectedPaths, fullTreeData, field = 'id') => {
// 1. 将选中的路径转换为扁平化的ID集合
const selectedIds = new Set(selectedPaths.flat());
// 2. 构建节点映射表和父子关系
const nodeMap = new Map();
const allChildrenMap = new Map(); // 存储每个节点的所有子节点ID
const buildMaps = (nodes) => {
nodes.forEach((node) => {
nodeMap.set(node[field], node);
if (node.children && node.children.length > 0) {
const childrenIds = node.children.map((child) => child[field]);
allChildrenMap.set(node[field], new Set(childrenIds));
buildMaps(node.children);
}
});
};
buildMaps(fullTreeData);
// 3. 处理结果集
const result = new Set();
// 4. 递归检查节点
const checkNode = (nodeId) => {
const node = nodeMap.get(nodeId);
if (!node) return false;
// 如果是叶子节点
if (!node.children || node.children.length === 0) {
if (selectedIds.has(nodeId)) {
result.add(nodeId);
return true;
}
return false;
}
// 获取所有子节点ID
const allChildren = allChildrenMap.get(nodeId) || new Set();
let allChildrenSelected = true;
// 检查每个子节点是否被选中
for (const childId of allChildren) {
const childSelected = checkNode(childId);
allChildrenSelected = allChildrenSelected && childSelected;
}
// 只有当所有子节点都被选中时,才添加当前节点
if (allChildrenSelected && allChildren.size > 0) {
result.add(nodeId);
return true;
}
return false;
};
// 5. 从所有选中的顶级节点开始检查
const topLevelSelected = new Set();
selectedPaths.forEach((path) => {
if (path.length > 0) {
topLevelSelected.add(path[0]);
}
});
topLevelSelected.forEach((nodeId) => {
checkNode(nodeId);
});
return Array.from(result);
};
// 测试1: 全选一个分支
const test1 = processCascaderSelection([
["66","603","1399","1791"],
["66","603","1399","1792"],
["66","603","1399","4373"] // 选中1399的所有子节点
], fullTreeData);
console.log(test1); // 输出: ["1399"]
// 测试2: 部分选择
const test2 = processCascaderSelection([
["66","603","1399","1791"], // 只选中1399的一个子节点
["66","603","1793"]
], fullTreeData);
console.log(test2); // 输出: ["1791", "1793"]