From d98899a5f8510b0e0882fd6193a57bdbe3b1d169 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 6 Oct 2026 11:59:15 +0800 Subject: [PATCH] =?UTF-8?q?feat(organize):=20=E6=95=B4=E7=90=86=E8=AE=B0?= =?UTF-8?q?=E5=BD=95=E5=88=97=E8=A1=A8=E5=B8=A6=E5=87=BA=E4=BA=8C=E7=BA=A7?= =?UTF-8?q?=E5=88=86=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 列表与详情的 media.category 取自冻结计划里的 classification.category,供整理记录行显示分类(对照 MP 历史记录页);不需要迁移。 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei --- .../acquisition-organize/services/organize-records.ts | 5 +++++ .../test/acquisition-organize/records-filter.test.ts | 10 ++++++++-- packages/contracts/src/organization.ts | 2 ++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/apps/server/src/modules/acquisition-organize/services/organize-records.ts b/apps/server/src/modules/acquisition-organize/services/organize-records.ts index 4f9658f8..3cfb0f77 100644 --- a/apps/server/src/modules/acquisition-organize/services/organize-records.ts +++ b/apps/server/src/modules/acquisition-organize/services/organize-records.ts @@ -70,6 +70,10 @@ export async function loadRecordsPublic(exec: Exec, rows: OrganizationRecordRow[ const v = (metadata as { posterPath?: { value?: unknown } } | null)?.posterPath?.value; return typeof v === "string" && v ? v : null; }; + const categoryOf = (plan: unknown) => { + const v = (plan as { classification?: { category?: unknown } } | null)?.classification?.category; + return typeof v === "string" && v ? v : null; + }; // blocked:* 的说明在 error.conflicts[].detail(中文),有就用它,不把内部串直接给人看 const conflictText = (err: unknown) => ((err as { conflicts?: { detail?: string }[] } | null)?.conflicts ?? []) @@ -119,6 +123,7 @@ export async function loadRecordsPublic(exec: Exec, rows: OrganizationRecordRow[ externalId: i.external_id, })), posterPath: posterOf(e.metadata), + category: categoryOf(r.plan), } : null, trigger: r.trigger, diff --git a/apps/server/test/acquisition-organize/records-filter.test.ts b/apps/server/test/acquisition-organize/records-filter.test.ts index 07172472..f0ee3fa6 100644 --- a/apps/server/test/acquisition-organize/records-filter.test.ts +++ b/apps/server/test/acquisition-organize/records-filter.test.ts @@ -44,6 +44,10 @@ describe.skipIf(skip)("整理记录筛选与统计", () => { media_entity_id: r.entity, download_task_id: "task" in r ? r.task : null, source_path: r.src, + // 冻结计划里的二级分类(列表带出 media.category) + ...(r.k === "film" + ? { plan: JSON.stringify({ classification: { category: "欧美电影", matchedFields: [], fallback: false } }) } + : {}), action: r.action, status: r.status, ...("at" in r ? { created_at: r.at } : {}), @@ -135,13 +139,15 @@ describe.skipIf(skip)("整理记录筛选与统计", () => { } }); - it("列表项带海报、大小、下载器名称与 hash", async () => { + it("列表项带海报、分类、大小、下载器名称与 hash", async () => { const [film] = await list("q=Arrival.2016"); expect(film).toMatchObject({ - media: { title: "Arrival", posterPath: "/arrival.jpg" }, + media: { title: "Arrival", posterPath: "/arrival.jpg", category: "欧美电影" }, sizeBytes: 1000, download: { name: "Arrival.2016", hash: "abcdef0123456789abcdef0123456789abcdef01", downloaderName: "家里的 qB" }, }); + const [show] = await list("q=Severance"); + expect(show).toMatchObject({ media: { title: "Severance", category: null } }); const [unknown] = await list("kind=none"); expect(unknown).toMatchObject({ media: null, download: null, sizeBytes: 1000 }); }); diff --git a/packages/contracts/src/organization.ts b/packages/contracts/src/organization.ts index c90a4989..470cf93d 100644 --- a/packages/contracts/src/organization.ts +++ b/packages/contracts/src/organization.ts @@ -232,6 +232,8 @@ export const PublicOrganizationRecord = z.object({ externalIds: z.array(z.object({ provider: z.string(), entityType: z.string(), externalId: z.string() })), /** HIS-1:作品海报(TMDB poster_path,如 /abc.jpg);没有为 null */ posterPath: z.string().nullable().optional(), + /** 整理时按二级分类策略得到的分类(如「纪录片」「欧美电影」,取自冻结计划);没有为 null */ + category: z.string().nullable().optional(), }) .nullable(), trigger: OrganizationTrigger,