diff --git a/admin-frontend-vue/src/pages/asin/ProductCategoryPage.vue b/admin-frontend-vue/src/pages/asin/ProductCategoryPage.vue index 50771846..36d8b0f3 100644 --- a/admin-frontend-vue/src/pages/asin/ProductCategoryPage.vue +++ b/admin-frontend-vue/src/pages/asin/ProductCategoryPage.vue @@ -8,10 +8,8 @@ import { createProductCategory, deleteProductCategory, updateProductCategory } f import { appendCategoryChildren, isCategoryLoadMoreNode, - isCategoryPlaceholderNode, makeCategoryLoadMoreNode, PRODUCT_CATEGORY_DEFAULT_PAGE_SIZE, - productCategoryNodeMeta, productCategorySourceLabel, type ProductCategoryNode, } from './product-category-model.ts' @@ -45,7 +43,7 @@ function stateKeyOf(parentId: number | null): string { function flatten(nodes: ProductCategoryNode[]): ProductCategoryNode[] { const out: ProductCategoryNode[] = [] for (const node of nodes || []) { - if (!isCategoryLoadMoreNode(node) && !isCategoryPlaceholderNode(node)) { + if (!isCategoryLoadMoreNode(node)) { out.push(node) out.push(...flatten(node.children)) } @@ -74,12 +72,49 @@ async function loadTree(): Promise { } } -/** 节点展开时按需加载子级第一页(childCount>0 且未加载过真实子级才拉取;占位子级不算已加载)。 */ -async function onNodeExpand(node: ProductCategoryNode): Promise { - if (isCategoryLoadMoreNode(node) || isCategoryPlaceholderNode(node) || node.childCount <= 0) return - const hasRealChildren = node.children.some((child) => !isCategoryPlaceholderNode(child) && !isCategoryLoadMoreNode(child)) - if (hasRealChildren) return - await loadChildrenPage(node, 1, false) +/** 树形表格(对齐旧版 panel-product-categories):客户端展开状态 + 按展开扁平化行集。 */ +interface TreeRow { + node: ProductCategoryNode + depth: number +} + +const expandedIds = ref>(new Set()) + +function collectRows(nodes: ProductCategoryNode[], depth: number, out: TreeRow[]): void { + for (const node of nodes || []) { + out.push({ node, depth }) + if (!isCategoryLoadMoreNode(node) && expandedIds.value.has(node.id)) { + collectRows(node.children, depth + 1, out) + } + } +} + +const treeRows = computed(() => { + const out: TreeRow[] = [] + collectRows(tree.value, 0, out) + return out +}) + +/** 展开/折叠:未加载过子级的先拉取第一页(懒加载),加载更多行点击翻页。 */ +async function toggleExpand(node: ProductCategoryNode): Promise { + if (isCategoryLoadMoreNode(node)) { + void loadMoreChildren(node) + return + } + if (node.childCount <= 0) return + if (expandedIds.value.has(node.id)) { + const next = new Set(expandedIds.value) + next.delete(node.id) + expandedIds.value = next + return + } + const hasRealChildren = node.children.some((child) => !isCategoryLoadMoreNode(child)) + if (!hasRealChildren) { + await loadChildrenPage(node, 1, false) + } + const next = new Set(expandedIds.value) + next.add(node.id) + expandedIds.value = next } /** 加载某父级一页子级(append=false 重置;append=true 追加并重建「加载更多」节点)。 */ @@ -279,45 +314,71 @@ onMounted(loadTree) - -