feat(library): show stored versions per episode and movie (LIBV-1)
- domain versionSpecOf: file name + ffprobe + ingest quality -> version spec;
summarizeVersions; matchVersions (satisfied / missing / upgradeable, single target)
- GET /library/{id}/versions: per-season/episode versions, summaries, matches[]
- organize writes full spec into media_asset.delivery (specVersion 1)
- scripts/asset-spec-backfill.ts: dry-run by default, --probe local only, --apply
- web: season summary line, one-line spec per episode, N versions expand,
tech info details (TODO: DEAI-2 TechInfo), movie versions panel
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
3763c86481
commit
bf9e73e86e
19 files changed
+2060
-9
No files matched your search
@@ -276,6 +276,8 @@ export interface EpisodeRowData {
|
||||
/** 有锁定的字段 */
|
||||
locked?: boolean;
|
||||
onEdit?: () => void;
|
||||
/** 简介下方的附加内容(入库版本) */
|
||||
extra?: ReactNode;
|
||||
}
|
||||
|
||||
function Still({ path }: { path: string | null }) {
|
||||
@@ -304,7 +306,7 @@ export function EpisodeRow({ e }: { e: EpisodeRowData }) {
|
||||
].filter(Boolean);
|
||||
const status = e.status === undefined ? (unaired ? { label: "未播出", tone: "neutral" as const } : null) : e.status;
|
||||
return (
|
||||
<li className="flex gap-3 py-3 first:pt-0 last:pb-0">
|
||||
<li className="flex items-start gap-3 py-3 first:pt-0 last:pb-0">
|
||||
<Still path={e.stillPath} />
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex flex-wrap items-start justify-between gap-x-2 gap-y-1">
|
||||
@@ -331,6 +333,7 @@ export function EpisodeRow({ e }: { e: EpisodeRowData }) {
|
||||
</div>
|
||||
<p className="mt-0.5 text-meta text-muted-foreground tabular-nums">{meta.join(" · ")}</p>
|
||||
{e.overview ? <ClampText text={e.overview} lines={2} className="mt-1 text-caption text-foreground/85" /> : null}
|
||||
{e.extra}
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
@@ -345,6 +348,8 @@ export interface SeasonHeaderData {
|
||||
overview: string | null;
|
||||
/** 季头右侧的摘要,如「已入库 5/9」 */
|
||||
summary?: ReactNode;
|
||||
/** 季头第二行下方的一行说明(入库版本汇总) */
|
||||
detail?: ReactNode;
|
||||
}
|
||||
|
||||
/** 季折叠:季头(海报缩略、季名、首播年、集数、摘要)+ 展开后的内容(集列表由页面传入) */
|
||||
@@ -379,6 +384,9 @@ export function SeasonSection({
|
||||
.filter(Boolean)
|
||||
.join(" · ") || "—"}
|
||||
</p>
|
||||
{s.detail ? (
|
||||
<p className="mt-0.5 text-meta break-words text-muted-foreground tabular-nums">{s.detail}</p>
|
||||
) : null}
|
||||
</div>
|
||||
{s.summary ? <div className="hidden shrink-0 sm:block">{s.summary}</div> : null}
|
||||
<ChevronDown
|
||||
|
||||
Reference in new issue
Block a user