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 <cursoragent@cursor.com>
This commit is contained in:
wuzilongandCursor committed 2026-10-18 16:24:12 +08:00
1 parent 4529a18a8d
commit ffd25d93e9
2 files changed
+94

No files matched your search

@@ -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]), '末级')
})
})
@@ -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<string, boolean> = {}
): Record<string, boolean> {
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<string, boolean>
): boolean {
const required = collectExpandIds(nodes, {})
const ids = Object.keys(required)
if (!ids.length) return true
return ids.every((id) => !!expandedIds[id])
}