import type { Decision } from "@umt/contracts"; import { useDecisions } from "~/api/decisions.ts"; import { humanizeReason } from "~/lib/reasons.ts"; import { EpisodeDecision } from "./decision.tsx"; // 集数待确认的原因(2026-10-06 去掉待处理中心后):不再作为逐条要处理的条目, // 同一作品的问题聚合在作品页「集数映射」与订阅详情里显示原因;智能体建议 / 建议规则可在这里采用(写进作品识别词)。 // 数据来自内部事项 episode_mapping(只给关注中的作品开,见 server sources-identity/service/watched.ts)。 const OPEN = ["open", "investigating", "awaiting_user"]; function entityOf(d: Decision): string | null { const m = d.evidence.mediaEntityId; return typeof m === "string" ? m : d.subjectType === "media_entity" ? d.subjectId : null; } /** 某作品(可选按来源季)未关闭的集数待确认事项 */ export function useEpisodeIssues(entityId: string | null | undefined, season?: number | null) { const q = useDecisions({ kind: "episode_mapping" }, !!entityId); const items = (q.data?.pages.flatMap((p) => p.items) ?? []).filter( (d) => OPEN.includes(d.status) && entityOf(d) === entityId && (season == null || (d.evidence as { season?: unknown }).season === season), ); return { ...q, items }; } /** 作品页集数映射分区:逐组写原因,建议规则 / 智能体建议可确认 */ export function EpisodeIssuesList({ entityId, onEdit }: { entityId: string; onEdit?: (line: string) => void }) { const { items } = useEpisodeIssues(entityId); if (!items.length) return null; return (

换算不了的资源({items.length} 组)

); } /** 订阅详情:缺集原因一句一组(只读,处理去作品页) */ export function EpisodeIssueReasons({ entityId, season }: { entityId: string; season: number | null }) { const { items } = useEpisodeIssues(entityId, season); if (!items.length) return null; return ( ); }