Files
aiot-uniapp/src/utils/tree.ts

102 lines
2.4 KiB
TypeScript
Raw Normal View History

/**
*
*/
interface TreeNode {
id?: number
parentId?: number
children?: TreeNode[]
[key: string]: any
}
/**
*
* @param data
* @param id id 'id'
* @param parentId 'parentId'
* @param children 'children'
*/
export function handleTree<T extends TreeNode>(
data: T[],
id = 'id',
parentId = 'parentId',
children = 'children',
): T[] {
if (!Array.isArray(data)) {
console.warn('data must be an array')
return []
}
const nodeMap: Record<number, T> = {}
const childrenListMap: Record<number, T[]> = {}
const tree: T[] = []
// 构建节点映射和子节点列表
for (const node of data) {
const nodeId = node[id] as number
const nodeParentId = node[parentId] as number
nodeMap[nodeId] = { ...node, [children]: [] } as T
if (!childrenListMap[nodeParentId]) {
childrenListMap[nodeParentId] = []
}
childrenListMap[nodeParentId].push(nodeMap[nodeId])
}
// 构建树形结构
for (const node of data) {
const nodeParentId = node[parentId] as number
// 父节点不存在于 nodeMap 中,说明是根节点
if (!nodeMap[nodeParentId]) {
tree.push(nodeMap[node[id] as number])
}
}
// 递归设置子节点
function setChildren(node: T) {
const nodeId = node[id] as number
const nodeChildren = childrenListMap[nodeId]
if (nodeChildren && nodeChildren.length > 0) {
;(node as any)[children] = nodeChildren
for (const child of nodeChildren) {
setChildren(child)
}
}
}
for (const node of tree) {
setChildren(node)
}
return tree
}
/**
*
* @param tree
* @param parentId ID
* @param id id 'id'
* @param children 'children'
*/
export function findChildren<T extends TreeNode>(
tree: T[],
parentId: number,
id = 'id',
children = 'children',
): T[] {
for (const node of tree) {
if (node[id] === parentId) {
return (node[children] as T[]) || []
}
const nodeChildren = node[children] as T[] | undefined
if (nodeChildren && nodeChildren.length > 0) {
const found = findChildren(nodeChildren, parentId, id, children)
if (found.length > 0) {
return found
}
}
}
return []
}