diff --git a/apps/frontend/src/components/admin/ConsignmentTemplateCopyModal.tsx b/apps/frontend/src/components/admin/ConsignmentTemplateCopyModal.tsx index 7ee49418..aff74e81 100644 --- a/apps/frontend/src/components/admin/ConsignmentTemplateCopyModal.tsx +++ b/apps/frontend/src/components/admin/ConsignmentTemplateCopyModal.tsx @@ -31,7 +31,9 @@ type TemplateOption = { } type TemplateTreeNode = { - key: string + // rc-tree 以节点的 value 作为内部 key(fieldNames.key 默认指向 value), + // 自定义 key 必须与 value 完全一致,否则 treeExpandedKeys 无法命中。 + key: number value: number title: string selectable: boolean @@ -188,7 +190,7 @@ export default function ConsignmentTemplateCopyModal({ const root = group.root const rootLabel = root?.label || group.groupName || '未命名分类' const childNodes: TemplateTreeNode[] = group.children.map((option) => ({ - key: `child-${option.value}`, + key: option.value, value: option.value, title: option.label, selectable: true, @@ -199,7 +201,7 @@ export default function ConsignmentTemplateCopyModal({ if (root && childNodes.length === 0) { return [ { - key: `root-${root.value}`, + key: root.value, value: root.value, title: root.label, selectable: true, @@ -212,7 +214,7 @@ export default function ConsignmentTemplateCopyModal({ if (!root) { if (childNodes.length === 0) return [] const groupNode: TemplateTreeNode = { - key: `group-${group.groupCategoryId}`, + key: -group.groupCategoryId, value: -group.groupCategoryId, title: rootLabel, selectable: false, @@ -224,7 +226,7 @@ export default function ConsignmentTemplateCopyModal({ } return [ { - key: `group-${group.groupCategoryId}`, + key: root.value, value: root.value, title: root.label, selectable: !root.disabled, @@ -237,7 +239,7 @@ export default function ConsignmentTemplateCopyModal({ }) }, [options, categoryNames]) const treeGroupKeys = useMemo( - () => treeData.filter((node) => node.children?.length).map((node) => node.key), + () => treeData.filter((node) => node.children?.length).map((node) => node.value), [treeData], ) diff --git a/apps/frontend/src/pages/admin/panels/ConsignmentInventoryPanel.tsx b/apps/frontend/src/pages/admin/panels/ConsignmentInventoryPanel.tsx index 02d94d5c..fdf73f37 100644 --- a/apps/frontend/src/pages/admin/panels/ConsignmentInventoryPanel.tsx +++ b/apps/frontend/src/pages/admin/panels/ConsignmentInventoryPanel.tsx @@ -127,7 +127,9 @@ function resolveGiftEvidenceEmptyText(record: { } type InventoryFilterTreeNode = { - key: string + // rc-tree 以节点的 value 作为内部 key(fieldNames.key 默认指向 value), + // 自定义 key 必须与 value 完全一致,否则 treeExpandedKeys 无法命中。 + key: number value: number title: string selectable: boolean @@ -217,7 +219,7 @@ export default function ConsignmentInventoryPanel() { const root = group.root const rootLabel = root?.name || group.groupName || '未命名分类' const childNodes: InventoryFilterTreeNode[] = group.children.map((item) => ({ - key: `child-${item.categoryId}`, + key: item.categoryId, value: item.categoryId, title: item.name, selectable: true, @@ -227,7 +229,7 @@ export default function ConsignmentInventoryPanel() { if (root && childNodes.length === 0) { return [ { - key: `root-${root.categoryId}`, + key: root.categoryId, value: root.categoryId, title: rootLabel, selectable: true, @@ -239,7 +241,7 @@ export default function ConsignmentInventoryPanel() { if (!root) { if (childNodes.length === 0) return [] const groupNode: InventoryFilterTreeNode = { - key: `group-${group.groupCategoryId}`, + key: -group.groupCategoryId, value: -group.groupCategoryId, title: rootLabel, selectable: false, @@ -251,7 +253,7 @@ export default function ConsignmentInventoryPanel() { } return [ { - key: `group-${group.groupCategoryId}`, + key: root.categoryId, value: root.categoryId, title: rootLabel, selectable: true, @@ -264,7 +266,7 @@ export default function ConsignmentInventoryPanel() { }) }, [filterCategories]) const categoryGroupKeys = useMemo( - () => categoryTreeData.filter((node) => node.children?.length).map((node) => node.key), + () => categoryTreeData.filter((node) => node.children?.length).map((node) => node.value), [categoryTreeData], ) useEffect(() => { diff --git a/apps/frontend/src/pages/worker/WorkerConsignmentPage.tsx b/apps/frontend/src/pages/worker/WorkerConsignmentPage.tsx index 4abd37a6..1334a2c9 100644 --- a/apps/frontend/src/pages/worker/WorkerConsignmentPage.tsx +++ b/apps/frontend/src/pages/worker/WorkerConsignmentPage.tsx @@ -154,7 +154,7 @@ function orderWorkerProfiles(profiles: WorkerConsignmentProfile[]): WorkerConsig } type WorkerProfileTreeNode = { - key: string + key: number value: number title: string selectable: boolean @@ -271,7 +271,7 @@ export default function WorkerConsignmentPage() { ? root.tabTitle || root.categoryName || root.name : group.groupName || '未命名分类' const childNodes: WorkerProfileTreeNode[] = group.children.map((child) => ({ - key: `child-${child.profileId}`, + key: child.profileId, value: child.profileId, title: child.tabTitle || child.categoryName || child.name, selectable: true, @@ -281,7 +281,7 @@ export default function WorkerConsignmentPage() { if (root && childNodes.length === 0) { return [ { - key: `root-${root.profileId}`, + key: root.profileId, value: root.profileId, title: rootLabel, selectable: true, @@ -293,7 +293,7 @@ export default function WorkerConsignmentPage() { if (!root) { if (childNodes.length === 0) return [] const groupNode: WorkerProfileTreeNode = { - key: `group-${group.groupCategoryId}`, + key: -group.groupCategoryId, value: -group.groupCategoryId, title: rootLabel, selectable: false, @@ -305,7 +305,7 @@ export default function WorkerConsignmentPage() { } return [ { - key: `group-${group.groupCategoryId}`, + key: root.profileId, value: root.profileId, title: rootLabel, selectable: true, @@ -318,7 +318,7 @@ export default function WorkerConsignmentPage() { }) }, [orderedConsignmentProfiles]) const profileGroupKeys = useMemo( - () => profileTreeData.filter((node) => node.children?.length).map((node) => node.key), + () => profileTreeData.filter((node) => node.children?.length).map((node) => node.value), [profileTreeData], ) useEffect(() => { diff --git a/apps/frontend/tests/consignment-matching-config.test.ts b/apps/frontend/tests/consignment-matching-config.test.ts index 1cb7a614..c454a4b5 100644 --- a/apps/frontend/tests/consignment-matching-config.test.ts +++ b/apps/frontend/tests/consignment-matching-config.test.ts @@ -155,6 +155,10 @@ test('寄卖配置:规格字段与联系方式区块提供复制模板配置 '来源树默认必须展开二级', ) assert.ok(modal.includes('treeTitleRender'), '来源树必须自定义层级标题') + assert.ok( + !modal.includes('key: `') && modal.includes('.map((node) => node.value)'), + '展开键必须来自节点 value(rc-tree 内部 key 即 value),否则默认展开失效', + ) }) test('打手端:寄卖分类按一二级层级展示', () => { @@ -168,6 +172,10 @@ test('打手端:寄卖分类按一二级层级展示', () => { '默认必须展开二级', ) assert.ok(page.includes('treeTitleRender'), '必须自定义层级标题') + assert.ok( + !page.includes('key: `') && page.includes('.map((node) => node.value)'), + '展开键必须来自节点 value(rc-tree 内部 key 即 value),否则默认展开失效', + ) assert.ok(page.includes('二级'), '二级分类必须有层级标签') }) @@ -180,5 +188,9 @@ test('寄售仓库:寄卖分类筛选按一二级层级展示', () => { '默认必须展开二级', ) assert.ok(panel.includes('treeTitleRender'), '必须自定义层级标题') + assert.ok( + !panel.includes('key: `') && panel.includes('.map((node) => node.value)'), + '展开键必须来自节点 value(rc-tree 内部 key 即 value),否则默认展开失效', + ) assert.ok(panel.includes('继承'), '继承型二级分类必须有继承标记') })