import type { Department } from '@/api/types' /** * Tree node consumed by ``. Element Plus looks at `label` for * the text and `children` for sub-nodes (both configurable via props). */ export interface DeptTreeNode { dept_id: string label: string raw: Department children: DeptTreeNode[] } /** * Build a department forest from the backend's flat `parent_id` list. * * - Roots = departments with no `parent_id` (or whose parent is missing). * - Children are sorted by `path` then `dept_id` to mirror the backend ordering * (the API already returns ordered by path, but orphans re-ordering is cheap * insurance). * - Falls back gracefully on cycles / dangling parent_ids (orphans become roots * rather than disappearing). */ export function buildDeptTree(departments: Department[]): DeptTreeNode[] { const nodes = new Map() for (const d of departments) { nodes.set(d.dept_id, { dept_id: d.dept_id, label: d.name?.trim() || d.dept_id, raw: d, children: [], }) } const roots: DeptTreeNode[] = [] for (const d of departments) { const node = nodes.get(d.dept_id)! const parent = d.parent_id ? nodes.get(d.parent_id) : undefined if (parent) { parent.children.push(node) } else { roots.push(node) } } const sortRec = (list: DeptTreeNode[]) => { list.sort((a, b) => (a.raw.path ?? a.dept_id).localeCompare(b.raw.path ?? b.dept_id), ) for (const n of list) sortRec(n.children) } sortRec(roots) return roots }