import { TreeNodeData } from "@mantine/core" /** * 判断一个节点本身是否命中 * 父节点看 label(group_name),叶子看 label(member_name) */ const nodeMatch = (node: TreeNodeData, search: string): boolean => { if (!search) return true // 空搜索默认全过 const text = String(node.label).toLowerCase() return text.includes(search.toLowerCase()) } /* ------------------------------------------------- * 1. DFS 自上而下,匹配即保留,否则剪掉整枝 * ------------------------------------------------- */ export const filterTreeData_dfs = ( treeData: TreeNodeData[], searchName: string ): TreeNodeData[] => { if (!searchName.trim()) return treeData // 空搜索直接返回原树 const loop = (list: TreeNodeData[]): TreeNodeData[] => { const result: TreeNodeData[] = [] for (const n of list) { // 1. 只要节点本身命中,就整枝保留(children 不用再判断) if (nodeMatch(n, searchName)) { result.push({ ...n }) // 浅拷贝一份,避免污染原树 continue } // 2. 本身没命中,再看 children 有没有命中 if (n.children) { const newChildren = loop(n.children) if (newChildren.length) { result.push({ ...n, children: newChildren }) } } } return result } return loop(treeData) } // 辅助:根据 value 查找 label export interface FindResult { path: string // 完整 label 路径,用 / 分隔 node: TreeNodeData | null } export const findLabel = ( nodes: TreeNodeData[], targetValue: string, pathArr: string[] = [] // 内部用,调用端无需传入 ): FindResult => { for (const node of nodes) { const curPath = [...pathArr, node.label as string] // 复制一份,避免污染上层 if (node.value === targetValue) { return { path: curPath.join(""), node } } if (node.children) { const found = findLabel(node.children, targetValue, curPath) if (found.node) return found } } return { path: "", node: null } } export const getStateFromDataByName = ( data: TreeNodeData[], record: Record = {} ): Record => { let result = data?.reduce((acc, item) => { let child_acc = {} if (item.children && item.children?.length) { acc[item.value] = true child_acc = getStateFromDataByName(item.children, record) } return { ...acc, ...child_acc } }, record) return result }