Some checks failed
CI Check / check (push) Has been cancelled
- 创建统一UI三层架构系统(基础层、颜色层、组合层) - 拆分Admin页面为独立Tab组件(MonitorTab、UsersTab、DepartmentsTab等) - 提取公共逻辑到Hooks(useToast、useDataFetch、useUserOperations等) - 提取工具函数(validators、formatters、api等) - 创建统一弹窗组件(Modal)和useModal Hook - 添加错误边界和统一状态组件 - 完善类型定义和可访问性支持 - 更新文档(优化记录、优化计划、更新日志)
80 lines
2.0 KiB
TypeScript
80 lines
2.0 KiB
TypeScript
import { getDepartmentCollator } from '@/lib/departments'
|
|
import type { Department, DepartmentNode } from '../_components/types'
|
|
|
|
const cloneNode = (node: DepartmentNode, children: DepartmentNode[] = []) => ({
|
|
...node,
|
|
children,
|
|
})
|
|
|
|
export const buildDepartmentTree = (
|
|
departments: Department[] = [],
|
|
collator: Intl.Collator = getDepartmentCollator(),
|
|
): DepartmentNode[] => {
|
|
if (!departments.length) return []
|
|
|
|
const nodeMap = new Map<string, DepartmentNode>()
|
|
|
|
departments.forEach((dept) => {
|
|
nodeMap.set(dept.name, {
|
|
id: dept.id,
|
|
name: dept.name,
|
|
fullName: dept.name,
|
|
children: [],
|
|
})
|
|
})
|
|
|
|
const roots: DepartmentNode[] = []
|
|
|
|
departments.forEach((dept) => {
|
|
const node = nodeMap.get(dept.name)
|
|
if (!node) {
|
|
return
|
|
}
|
|
const lastDashIndex = dept.name.lastIndexOf('-')
|
|
if (lastDashIndex === -1) {
|
|
roots.push(node)
|
|
} else {
|
|
const parentName = dept.name.substring(0, lastDashIndex)
|
|
const parentNode = nodeMap.get(parentName)
|
|
if (parentNode) {
|
|
parentNode.children.push(node)
|
|
} else {
|
|
roots.push(node)
|
|
}
|
|
}
|
|
})
|
|
|
|
const sortNodes = (nodes: DepartmentNode[]) => {
|
|
nodes.sort((a, b) => collator.compare(a.fullName, b.fullName))
|
|
nodes.forEach((child) => sortNodes(child.children))
|
|
}
|
|
|
|
sortNodes(roots)
|
|
return roots
|
|
}
|
|
|
|
export const filterDepartmentTree = (
|
|
tree: DepartmentNode[],
|
|
term: string,
|
|
): DepartmentNode[] => {
|
|
const normalized = term.trim().toLowerCase()
|
|
if (!normalized) return tree
|
|
|
|
const filterNodes = (nodes: DepartmentNode[]): DepartmentNode[] =>
|
|
nodes
|
|
.map((node) => {
|
|
const matchesSelf =
|
|
node.name.toLowerCase().includes(normalized) ||
|
|
node.fullName.toLowerCase().includes(normalized)
|
|
const filteredChildren = filterNodes(node.children)
|
|
return matchesSelf || filteredChildren.length
|
|
? cloneNode(node, filteredChildren)
|
|
: null
|
|
})
|
|
.filter((node): node is DepartmentNode => Boolean(node))
|
|
|
|
return filterNodes(tree)
|
|
}
|
|
|
|
|