/** * 导航树聚合工具 * * 场景:父级栏目(如「核心业务」)下挂多个子栏目,父栏目自身通常不放内容。 * 访问父级栏目时,需要聚合其下所有子栏目的数据。 * * 做法:从完整导航树(allNavigations)中找到目标节点,递归收集 * 该节点自身 + 所有后代的 navigationId,交给后端按 category_id IN (...) 查询。 */ interface NavNode { navigationId?: number | null children?: NavNode[] | null } /** * 递归收集某导航节点自身 + 所有后代的 navigationId * * @param navId 目标栏目 navigationId(来自路由参数或导航查找) * @param navigations 完整导航树(allNavigations) * @returns 包含自身及所有后代 navigationId 的数组;未命中时返回空数组 */ export function collectDescendantNavIds( navId: number | string | undefined, navigations: NavNode[] = [] ): number[] { if (navId == null) return [] const target = Number(navId) const result: number[] = [] const collectSelfAndChildren = (node: NavNode) => { if (node?.navigationId != null) { result.push(Number(node.navigationId)) } node?.children?.forEach((child: NavNode) => collectSelfAndChildren(child)) } const findNode = (items: NavNode[]): boolean => { for (const it of items || []) { if (Number(it?.navigationId) === target) { collectSelfAndChildren(it) return true } if (it?.children?.length && findNode(it.children)) return true } return false } findNode(navigations) return result } /** * 判断某 navigationId 是否为父栏目(拥有子栏目) */ export function isParentNavigation( navId: number | string | undefined, navigations: NavNode[] = [] ): boolean { if (navId == null) return false const target = Number(navId) const find = (items: NavNode[]): boolean => { for (const it of items || []) { if (Number(it?.navigationId) === target) return (it?.children?.length ?? 0) > 0 if (it?.children?.length && find(it.children)) return true } return false } return find(navigations) }