feat(episode-mapping): 映射规则接口与模拟预览、待处理确认 / 忽略、作品页集数映射分区与订阅摘要

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-10-03 19:28:09 +08:00
1 parent fe597187dd
commit 45a114263b
26 files changed
+2770 -9

No files matched your search

+11 -3
View File
@@ -15,6 +15,7 @@ import { PageHeader } from "~/components/console/page-header.tsx";
import { StatusBadge } from "~/components/console/status-badge.tsx";
import { TechInfo } from "~/components/console/tech-info.tsx";
import { useListPagination } from "~/components/console/use-list-pagination.ts";
import { EpisodeDecision } from "~/components/episode-mapping/decision.tsx";
import { EntityPicker, type PickedEntity } from "~/components/library/identity-entity-picker.tsx";
import { DECISION_KIND, DECISION_STATUS, opts, SEVERITY } from "~/components/library/labels.ts";
import { Chip, relTime, Tone } from "~/components/library/parts.tsx";
@@ -363,6 +364,8 @@ function DismissButton({ d }: { d: Decision }) {
function DecisionCard({ d }: { d: Decision }) {
const open = OPEN.includes(d.status);
const identity = IDENTITY_KINDS.includes(d.kind);
// 集数待确认:证据与「确认 / 修改 / 忽略」由 EpisodeDecision 渲染
const episode = d.kind === "episode_mapping";
// 身份类:手动 TMDB / 选本地作品两个选项并进「指定作品」
const options = d.options.filter(
(o) =>
@@ -383,11 +386,16 @@ function DecisionCard({ d }: { d: Decision }) {
{d.summary ? (
<p className="mt-1 text-caption break-words text-muted-foreground">{humanizeReason(d.summary)}</p>
) : null}
<GroupReleases d={d} />
{episode ? null : <GroupReleases d={d} />}
{episode ? (
<div className="mt-3">
<EpisodeDecision d={d} open={open} />
</div>
) : null}
<div className="mt-3">
<Evidence d={d} />
</div>
{open ? (
{open && !episode ? (
<div className="mt-3 flex flex-wrap items-center gap-2">
{identity ? <AssignWorkButton d={d} /> : null}
{options.map((o) => (
@@ -404,7 +412,7 @@ function DecisionCard({ d }: { d: Decision }) {
</Link>
) : null}
</div>
) : (
) : open ? null : (
<p className="mt-3 text-meta text-muted-foreground">
{d.resolvedBy ? `${actorText(d.resolvedBy)} ` : ""}于 {formatDateTime(d.resolvedAt)}
{resolution?.optionKey