From ffd25d93e9834ef9046e38458da0a430febed2a5 Mon Sep 17 00:00:00 2001 From: wuzilong <704541015@qq.com> Date: Sun, 18 Oct 2026 16:24:12 +0800 Subject: [PATCH] feat(web-admin): add product category tree expand helpers. Centralize expand-id collection and child meta labels for the mp category list. Co-authored-by: Cursor --- .../mp-crm-product-category-tree.test.ts | 57 +++++++++++++++++++ .../src/utils/mp-crm-product-category-tree.ts | 37 ++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 web-admin/src/utils/mp-crm-product-category-tree.test.ts create mode 100644 web-admin/src/utils/mp-crm-product-category-tree.ts diff --git a/web-admin/src/utils/mp-crm-product-category-tree.test.ts b/web-admin/src/utils/mp-crm-product-category-tree.test.ts new file mode 100644 index 000000000..8e490b75f --- /dev/null +++ b/web-admin/src/utils/mp-crm-product-category-tree.test.ts @@ -0,0 +1,57 @@ +import assert from 'node:assert/strict' +import { describe, it } from 'node:test' +import { + collectExpandIds, + areAllExpandableExpanded, + categoryChildCount, + categoryChildMetaLabel +} from './mp-crm-product-category-tree' + +type Node = { + id: string + children?: Node[] +} + +const sample: Node[] = [ + { + id: '1', + children: [ + { id: '11', children: [{ id: '111' }] }, + { id: '12' } + ] + }, + { id: '2' } +] + +describe('collectExpandIds', () => { + it('marks every node that has children', () => { + assert.deepEqual(collectExpandIds(sample), { '1': true, '11': true }) + }) +}) + +describe('areAllExpandableExpanded', () => { + it('returns true when all expandable ids are true', () => { + assert.equal(areAllExpandableExpanded(sample, { '1': true, '11': true }), true) + }) + + it('returns false when any expandable id is missing or false', () => { + assert.equal(areAllExpandableExpanded(sample, { '1': true }), false) + assert.equal(areAllExpandableExpanded(sample, { '1': true, '11': false }), false) + }) + + it('returns true for empty tree', () => { + assert.equal(areAllExpandableExpanded([], {}), true) + }) +}) + +describe('categoryChildCount / categoryChildMetaLabel', () => { + it('counts direct children only', () => { + assert.equal(categoryChildCount(sample[0]), 2) + assert.equal(categoryChildCount(sample[1]), 0) + }) + + it('labels leaf vs parent', () => { + assert.equal(categoryChildMetaLabel(sample[0]), '2 个子类') + assert.equal(categoryChildMetaLabel(sample[1]), '末级') + }) +}) diff --git a/web-admin/src/utils/mp-crm-product-category-tree.ts b/web-admin/src/utils/mp-crm-product-category-tree.ts new file mode 100644 index 000000000..634957781 --- /dev/null +++ b/web-admin/src/utils/mp-crm-product-category-tree.ts @@ -0,0 +1,37 @@ +export type CategoryTreeNodeLike = { + id: string + children?: CategoryTreeNodeLike[] +} + +export function categoryChildCount(node: CategoryTreeNodeLike | null | undefined): number { + const children = Array.isArray(node?.children) ? node!.children! : [] + return children.length +} + +export function categoryChildMetaLabel(node: CategoryTreeNodeLike | null | undefined): string { + const n = categoryChildCount(node) + return n > 0 ? `${n} 个子类` : '末级' +} + +export function collectExpandIds( + nodes: CategoryTreeNodeLike[], + acc: Record = {} +): Record { + for (const node of nodes) { + if (categoryChildCount(node) > 0) { + acc[node.id] = true + collectExpandIds(node.children || [], acc) + } + } + return acc +} + +export function areAllExpandableExpanded( + nodes: CategoryTreeNodeLike[], + expandedIds: Record +): boolean { + const required = collectExpandIds(nodes, {}) + const ids = Object.keys(required) + if (!ids.length) return true + return ids.every((id) => !!expandedIds[id]) +}