From dc2dd8d3b0c2b7d93fbad88927c8d221b9b84938 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Sun, 6 Sep 2026 10:47:57 +0800 Subject: [PATCH] fix(classification): avoid duplicate uncategorized label --- .../__tests__/ClassificationCategoryEditor.spec.ts | 12 ++++++++++++ src/utils/__tests__/mediaClassification.spec.ts | 10 ++++++++++ src/utils/mediaClassification.ts | 5 ++--- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/components/classification/__tests__/ClassificationCategoryEditor.spec.ts b/src/components/classification/__tests__/ClassificationCategoryEditor.spec.ts index 4dc5aa92..ee86583f 100644 --- a/src/components/classification/__tests__/ClassificationCategoryEditor.spec.ts +++ b/src/components/classification/__tests__/ClassificationCategoryEditor.spec.ts @@ -189,6 +189,18 @@ describe('ClassificationCategoryEditor', () => { await waitFor(() => expect(events.updateFallbacks).toHaveBeenCalledWith({ 音乐: 'music.lossless' })) }) + it('默认分类选项不会重复显示路径中的分类名称', async () => { + const user = userEvent.setup() + await renderEditor({ + categories: [createCategory('tv.uncategorized', '电视剧', '未分类', ['未分类', '通用'])], + }) + + await user.click(screen.getByRole('combobox', { name: '电视剧默认分类' })) + + expect(await screen.findByRole('option', { name: '未分类 · 通用' })).toBeInTheDocument() + expect(screen.queryByRole('option', { name: '未分类 · 未分类 / 通用' })).not.toBeInTheDocument() + }) + it('路径超过最大深度时保留草稿并拒绝发出分类更新', async () => { const user = userEvent.setup() const { events } = await renderEditor({ maxDepth: 2 }) diff --git a/src/utils/__tests__/mediaClassification.spec.ts b/src/utils/__tests__/mediaClassification.spec.ts index c2dba0da..b0b1067d 100644 --- a/src/utils/__tests__/mediaClassification.spec.ts +++ b/src/utils/__tests__/mediaClassification.spec.ts @@ -27,6 +27,16 @@ describe('formatClassificationCategoryOptionTitle', () => { ).toBe('华语电影 · 电影') }) + it('removes a repeated category name from any path segment', () => { + expect( + formatClassificationCategoryOptionTitle({ + id: 'tv.uncategorized', + name: '未分类', + path: ['未分类', '通用'], + }), + ).toBe('未分类 · 通用') + }) + it('can preserve a caller-specific path separator and stable ID', () => { expect( formatClassificationCategoryOptionTitle( diff --git a/src/utils/mediaClassification.ts b/src/utils/mediaClassification.ts index 9196971e..5ad04e72 100644 --- a/src/utils/mediaClassification.ts +++ b/src/utils/mediaClassification.ts @@ -14,13 +14,12 @@ interface ClassificationCategoryOptionTitleOptions { pathSeparator?: string } -/** 生成分类选择器标题,避免分类名与路径末级名称重复显示。 */ +/** 生成分类选择器标题,避免分类名与路径中的同名段重复显示。 */ export function formatClassificationCategoryOptionTitle( category: Pick, options: ClassificationCategoryOptionTitleOptions = {}, ): string { - const pathSegments = [...category.path] - while (pathSegments[pathSegments.length - 1] === category.name) pathSegments.pop() + const pathSegments = category.path.filter(segment => segment !== category.name) const path = pathSegments.join(options.pathSeparator ?? ' / ') const displayPath = path || (category.path.length ? '' : (options.emptyPathLabel ?? '')) const parts = [category.name, displayPath]