From 3dd39bba44d08987dad269df27bc0b76a9f87863 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E8=87=AA=E8=BE=BE?= <980324341@qq.com> Date: Sun, 6 Sep 2026 02:33:51 +0800 Subject: [PATCH] =?UTF-8?q?task-279(=E9=AA=8C=E6=94=B6=E5=8F=8D=E9=A6=88):?= =?UTF-8?q?=20=E4=BF=AE=E5=A4=8D=E7=B1=BB=E7=9B=AE=E6=A0=91=E5=AD=90?= =?UTF-8?q?=E7=BA=A7=E6=8C=82=E9=94=99=E7=88=B6=E7=BA=A7(=E6=A0=B9?= =?UTF-8?q?=E7=BA=A7loadMore=20id=3D-1=E4=B8=8E=E7=88=B6=E7=BA=A71?= =?UTF-8?q?=E7=9A=84=E5=90=88=E6=88=90=E8=8A=82=E7=82=B9=E6=92=9Enode-key,?= =?UTF-8?q?=E5=90=88=E6=88=90id=E6=94=B9=E7=8B=AC=E7=AB=8B=E8=B4=9F?= =?UTF-8?q?=E6=95=B0=E5=9F=9F)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/pages/asin/product-category-model.ts | 4 +++- .../tests/align-category-tree.test.ts | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/admin-frontend-vue/src/pages/asin/product-category-model.ts b/admin-frontend-vue/src/pages/asin/product-category-model.ts index 5749607a..dba5635d 100644 --- a/admin-frontend-vue/src/pages/asin/product-category-model.ts +++ b/admin-frontend-vue/src/pages/asin/product-category-model.ts @@ -165,7 +165,9 @@ export function makeCategoryLoadMoreNode( loadedCount: number, totalCount: number, ): CategoryLoadMoreNode { - const syntheticId = parentId ? -parentId : -1 + // 合成 id 独立负数域(-2_000_000 以下):父级 id=1 时 -parentId=-1 会与根级(-1)撞 key, + // el-tree node-key 重复会致节点状态错位(子级挂错父级)。placeholder 域(-1_000_000)与此错开。 + const syntheticId = -(parentId ?? 0) - 2_000_000 return { id: syntheticId, parentId, diff --git a/admin-frontend-vue/tests/align-category-tree.test.ts b/admin-frontend-vue/tests/align-category-tree.test.ts index 194b0d31..e971acb9 100644 --- a/admin-frontend-vue/tests/align-category-tree.test.ts +++ b/admin-frontend-vue/tests/align-category-tree.test.ts @@ -1,7 +1,7 @@ import test from 'node:test' import assert from 'node:assert/strict' import { readSource } from './helpers.ts' -import { isCategoryPlaceholderNode, toProductCategoryNode, makeCategoryPlaceholderNode } from '../src/pages/asin/product-category-model.ts' +import { isCategoryPlaceholderNode, toProductCategoryNode, makeCategoryPlaceholderNode, makeCategoryLoadMoreNode } from '../src/pages/asin/product-category-model.ts' // 验收反馈:类目树太紧凑、没有折叠展开、父子级效果对齐旧版(旧版为缩进树形表格带 +/- 展开)。 // 不变式:childCount>0 的未加载节点带占位子级(children 非空),el-tree 因此显示展开箭头; @@ -42,3 +42,19 @@ test('align_category_tree_dependency_failure_returns_actionable_message', () => assert.match(page, /\.node-row\s*\{[^}]*padding/, '节点行有 padding') assert.match(page, /el-tree-node__expand-icon|expand-icon/, '展开图标样式定制') }) + +test('align_category_tree_synthetic_ids_are_unique', () => { + // 修复回归:合成节点 id 唯一——根级 loadMore 与父级1的 loadMore 不得同 key(曾因 -1 撞 key 致子级挂错父级)。 + const ids = new Set() + const samples = [ + makeCategoryLoadMoreNode(null, 1, 2).id, + makeCategoryLoadMoreNode(1, 1, 2).id, + makeCategoryLoadMoreNode(2, 1, 2).id, + makeCategoryPlaceholderNode(null).id, + makeCategoryPlaceholderNode(1).id, + makeCategoryPlaceholderNode(2).id, + ] + for (const id of samples) ids.add(id) + assert.equal(ids.size, samples.length, '合成节点 id 两两唯一') + assert.ok(makeCategoryLoadMoreNode(null, 1, 2).id !== -1, '根级 loadMore 不得使用 -1(与父级1的旧式 -parentId 撞 key)') +})