task-282(验收反馈): 类目改回旧版树形表格(缩进+[+-]折叠标记+名称/层级路径/排序/来源/说明/操作列,懒加载与加载更多保留)

This commit is contained in:
2026-09-06 02:45:46 +08:00
parent b7029835d8
commit 6bd935dc6b
3 changed files with 167 additions and 135 deletions
@@ -1,60 +1,53 @@
import test from 'node:test'
import assert from 'node:assert/strict'
import { readSource } from './helpers.ts'
import { isCategoryPlaceholderNode, toProductCategoryNode, makeCategoryPlaceholderNode, makeCategoryLoadMoreNode } from '../src/pages/asin/product-category-model.ts'
import { makeCategoryLoadMoreNode, toProductCategoryNode } from '../src/pages/asin/product-category-model.ts'
// 验收反馈:类目树太紧凑、没有折叠展开、父子级效果对齐旧版(旧版为缩进树形表格带 +/- 展开)。
// 不变式:childCount>0 的未加载节点带占位子级(children 非空),el-tree 因此显示展开箭头;
// 节点间距加大(:indent 28 + node-row padding),父子级视觉与旧版缩进树一致。
// 验收反馈(两轮):类目树显示不对,参考旧版页面 —— 改为树形表格:
// 缩进层级 + [+/-] 展开折叠标记 + 名称/层级路径/排序/来源/说明/操作列,懒加载与加载更多保留。
test('align_category_tree_normal_primary_path', () => {
// 有子级但未返回 children 数据时,解析为带占位子级的节点(el-tree 显示展开箭头)。
const node = toProductCategoryNode({ id: 5, name: '父类目', child_count: 3, path: '父类目' })
assert.ok(node && node.children.length > 0, 'childCount>0 节点需带占位子级以显示展开箭头')
assert.ok(node && node.children.every((child) => isCategoryPlaceholderNode(child)), '占位子级可识别')
test('align_category_tree_table_normal_primary_path', () => {
const page = readSource('src/pages/asin/ProductCategoryPage.vue')
assert.ok(!page.includes('<el-tree'), '不再使用 el-tree,改为树形表格')
assert.match(page, /tree-node-mark/, '树形展开折叠标记(+/)')
assert.match(page, /tree-indent/, '层级缩进')
})
test('align_category_tree_normal_variant_input', () => {
// 占位节点 id 与真实节点不冲突(负数域),且不可被误认为真实类目。
const placeholder = makeCategoryPlaceholderNode(5)
assert.ok(placeholder.id < 0, '占位节点 id 用负数域避免与真实 id 冲突')
assert.ok(isCategoryPlaceholderNode(placeholder))
assert.equal(isCategoryPlaceholderNode({ id: 1, parentId: null, name: '真实', categoryKey: '', sortOrder: 0, description: '', isBuiltin: false, childCount: 0, level: 0, path: '', children: [] }), false)
test('align_category_tree_table_normal_variant_input', () => {
const page = readSource('src/pages/asin/ProductCategoryPage.vue')
assert.match(page, /expandedIds/, '客户端展开状态集合')
assert.match(page, /flatRows|treeRows/, '按展开状态扁平化行集')
for (const col of ['层级路径', '排序', '来源', '说明']) {
assert.match(page, new RegExp(col), `树形表格含「${col}」列`)
}
})
test('align_category_tree_boundary_empty_input', () => {
// 无子级节点保持叶子形态(children 空)。
test('align_category_tree_table_boundary_empty_input', () => {
// 展开折叠标记:childCount>0 显示 +/−;叶子无标记(对齐旧版 tree-node-mark is-leaf)。
const page = readSource('src/pages/asin/ProductCategoryPage.vue')
assert.match(page, /childCount/, '标记按 childCount 判断')
assert.match(page, /is-leaf/, '叶子标记态样式')
})
test('align_category_tree_table_boundary_single_item', () => {
// 懒加载保留:展开时未加载子级先拉取第一页;加载更多合成行保留。
const page = readSource('src/pages/asin/ProductCategoryPage.vue')
assert.match(page, /loadChildrenPage/, '展开懒加载保留')
assert.match(page, /isCategoryLoadMoreNode/, '加载更多行保留')
})
test('align_category_tree_table_repeated_operation_is_idempotent', () => {
// 合成节点 id 仍唯一(loadMore 独立负数域,避免 node key 冲突致行错位)。
const ids = new Set([makeCategoryLoadMoreNode(null, 1, 2).id, makeCategoryLoadMoreNode(1, 1, 2).id, makeCategoryLoadMoreNode(2, 1, 2).id])
assert.equal(ids.size, 3)
// 叶子节点 children 为空数组(无占位注入)。
const leaf = toProductCategoryNode({ id: 9, name: '叶子', child_count: 0, path: '叶子' })
assert.ok(leaf && leaf.children.length === 0, '叶子节点无占位子级')
assert.ok(leaf && leaf.children.length === 0)
})
test('align_category_tree_boundary_single_item', () => {
test('align_category_tree_table_dependency_failure_returns_actionable_message', () => {
// 视觉复刻旧版:20px 圆角方块标记、缩进宽度变量、名称加粗。
const page = readSource('src/pages/asin/ProductCategoryPage.vue')
assert.match(page, /:indent="28"/, '树缩进加大(28px/级)')
assert.match(page, /isCategoryPlaceholderNode/, '模板渲染占位节点分支')
// 展开加载需识别"只有占位子级"的节点(children 全占位也触发懒加载)。
assert.match(page, /some\(.*isCategoryPlaceholderNode/, '展开判断兼容占位子级')
})
test('align_category_tree_dependency_failure_returns_actionable_message', () => {
// 视觉:节点行加 padding 不再紧凑;箭头样式放大加色。
const page = readSource('src/pages/asin/ProductCategoryPage.vue')
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<number>()
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')
assert.match(page, /tree-node-mark/, '展开标记样式存在')
assert.match(page, /var\(--indent|--indent/, '缩进变量')
})