83 lines
2.4 KiB
TypeScript
83 lines
2.4 KiB
TypeScript
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<string, any> = {}
|
||
): Record<string, any> => {
|
||
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
|
||
}
|