auto-save 2026-05-12 18:52 (~2)

This commit is contained in:
2026-05-12 18:52:21 +08:00
parent 5a914b96df
commit f6f821262b
2 changed files with 86 additions and 85 deletions

View File

@@ -195,6 +195,13 @@
"message": "auto-save 2026-05-12 18:40 (~2)",
"hash": "864781d",
"files_changed": 2
},
{
"ts": "2026-05-12T18:46:46+08:00",
"type": "commit",
"message": "auto-save 2026-05-12 18:46 (~3)",
"hash": "5a914b9",
"files_changed": 3
}
]
}

View File

@@ -187,43 +187,35 @@ export function Dashboard({ data }: Props) {
<Tile tkey="compose" />
</div>
{/* 展开面板 — 多卡同时展开,按 step 顺序排列 */}
{/* 展开面板 — 单列宽度,居中,卡片竖向堆叠 */}
{expanded.size > 0 && (
<div className="relative mx-4 mb-3 rounded-xl border border-white/10 bg-black/30 backdrop-blur-xl overflow-hidden" style={{ maxHeight: "52vh" }}>
<div className="flex items-center justify-between px-4 py-2 border-b border-white/8">
<span className="text-[10px] uppercase tracking-widest text-[var(--text-faint)]"></span>
<button
onClick={() => setExpanded(new Set())}
className="text-[var(--text-faint)] hover:text-[var(--text-strong)]"
title="收起"
<div className="flex justify-center px-4 pb-3" style={{ maxHeight: "52vh" }}>
{TILES.filter((t) => expanded.has(t.key)).map((t) => (
<section
key={t.key}
className="rounded-xl border border-white/10 bg-black/30 backdrop-blur-xl overflow-hidden flex flex-col"
style={{ width: 360, maxHeight: "52vh" }}
>
<X className="h-4 w-4" />
</button>
</div>
<div className="overflow-y-auto p-3 space-y-3" style={{ maxHeight: "calc(52vh - 40px)" }}>
{TILES.filter((t) => expanded.has(t.key)).map((t) => (
<section key={t.key} className="rounded-lg border border-white/8 overflow-hidden">
<div className="flex items-center justify-between px-3 py-1.5" style={{ background: TYPE_GRAD[t.type] }}>
<div className="flex items-center gap-1.5">
<span className="text-white/70 text-[9px] font-mono">{String(t.step).padStart(2, "0")}</span>
<span className="text-white">{t.icon}</span>
<span className="text-[12.5px] font-semibold text-white">{t.title}</span>
<span className="text-[10px] text-white/60 ml-2">{colSummary[t.key]}</span>
</div>
<button
onClick={() => closeTile(t.key)}
className="text-white/70 hover:text-white"
title="收起此卡"
>
<X className="h-3.5 w-3.5" />
</button>
<div className="flex items-center justify-between px-3 py-2" style={{ background: TYPE_GRAD[t.type] }}>
<div className="flex items-center gap-1.5">
<span className="text-white/70 text-[9px] font-mono">{String(t.step).padStart(2, "0")}</span>
<span className="text-white">{t.icon}</span>
<span className="text-[12.5px] font-semibold text-white">{t.title}</span>
<span className="text-[10px] text-white/70 ml-2">{colSummary[t.key]}</span>
</div>
<div className="p-3 bg-black/20">
{renderSection(t.key)}
</div>
</section>
))}
</div>
<button
onClick={() => closeTile(t.key)}
className="text-white/70 hover:text-white"
title="收起"
>
<X className="h-3.5 w-3.5" />
</button>
</div>
<div className="overflow-y-auto p-3 bg-black/20">
{renderSection(t.key)}
</div>
</section>
))}
</div>
)}
</div>
@@ -231,7 +223,7 @@ export function Dashboard({ data }: Props) {
function renderSection(key: string): ReactNode {
return (
<>
<div className="space-y-3">
{/* ---- Input ---- */}
{key === "input" && (
@@ -367,41 +359,45 @@ export function Dashboard({ data }: Props) {
<div className="text-[11.5px] text-[var(--text-soft)]"> 30 pHash + 5 </div>
</KanbanCard>
) : (
<div className="grid grid-cols-5 gap-3">
{job!.frames.map((f) => {
const isSel = data.selectedFrames.has(f.index)
return (
<KanbanCard
key={f.index}
tone={isSel ? "green" : "pink"}
tags={[`分镜 ${f.index + 1}`, `${f.timestamp.toFixed(1)}s`]}
className={isSel ? "ring-2 ring-emerald-400/60" : ""}
meta={
<button
type="button"
onClick={(e) => { e.stopPropagation(); data.onToggleFrame(f.index) }}
className={`ml-auto text-[10.5px] px-2 py-0.5 rounded-full inline-flex items-center gap-1 ${
isSel
? "bg-emerald-500 text-white"
: "bg-white/10 text-[var(--text-soft)] border border-white/15 hover:bg-white/20"
}`}
>
<Check className="h-2.5 w-2.5" />
{isSel ? "已选用" : "选用此帧"}
</button>
}
>
job!.frames.map((f) => {
const isSel = data.selectedFrames.has(f.index)
return (
<KanbanCard
key={f.index}
tone={isSel ? "green" : "pink"}
tags={[`分镜 ${f.index + 1}`, `${f.timestamp.toFixed(1)}s`]}
className={isSel ? "ring-2 ring-emerald-400/60" : ""}
meta={
<button
type="button"
onClick={(e) => { e.stopPropagation(); data.onExpandFrame(f.index) }}
className="block w-full aspect-video rounded-md overflow-hidden bg-black relative"
onClick={(e) => { e.stopPropagation(); data.onToggleFrame(f.index) }}
className={`ml-auto text-[10.5px] px-2 py-0.5 rounded-full inline-flex items-center gap-1 ${
isSel
? "bg-emerald-500 text-white"
: "bg-white/10 text-[var(--text-soft)] border border-white/15 hover:bg-white/20"
}`}
>
<img src={frameUrl(job!.id, f.index)} alt={`frame ${f.index}`} className="absolute inset-0 w-full h-full object-cover" />
<Check className="h-2.5 w-2.5" />
{isSel ? "已选用" : "选用此帧"}
</button>
</KanbanCard>
)
})}
</div>
}
>
<button
type="button"
onClick={(e) => { e.stopPropagation(); data.onExpandFrame(f.index) }}
className="block w-full rounded-md overflow-hidden bg-black"
title="点击放大"
>
<img
src={frameUrl(job!.id, f.index)}
alt={`frame ${f.index}`}
className="block w-full h-auto"
style={{ objectFit: "contain" }}
/>
</button>
</KanbanCard>
)
})
)}
</div>
)}
@@ -415,24 +411,22 @@ export function Dashboard({ data }: Props) {
</div>
</KanbanCard>
) : (
<div className="grid grid-cols-2 gap-3">
{job!.transcript.map((s) => (
<KanbanCard
key={s.index}
tone={key === "asr" ? "blue" : "cyan"}
tags={[`段落 ${s.index + 1}`, `${s.start.toFixed(1)}s → ${s.end.toFixed(1)}s`]}
>
<div className="text-[12.5px] text-[var(--text-strong)] leading-snug mb-1.5">
<span className="kanban-tag mr-1.5" style={{ padding: "1px 6px", fontSize: 9.5 }}>EN</span>
{s.en}
</div>
<div className="text-[12.5px] text-[var(--text-strong)] leading-snug">
<span className="kanban-tag mr-1.5" style={{ padding: "1px 6px", fontSize: 9.5 }}>ZH</span>
{s.zh || <span className="text-[var(--text-faint)] italic"></span>}
</div>
</KanbanCard>
))}
</div>
job!.transcript.map((s) => (
<KanbanCard
key={s.index}
tone={key === "asr" ? "blue" : "cyan"}
tags={[`段落 ${s.index + 1}`, `${s.start.toFixed(1)}s → ${s.end.toFixed(1)}s`]}
>
<div className="text-[12.5px] text-[var(--text-strong)] leading-snug mb-1.5">
<span className="kanban-tag mr-1.5" style={{ padding: "1px 6px", fontSize: 9.5 }}>EN</span>
{s.en}
</div>
<div className="text-[12.5px] text-[var(--text-strong)] leading-snug">
<span className="kanban-tag mr-1.5" style={{ padding: "1px 6px", fontSize: 9.5 }}>ZH</span>
{s.zh || <span className="text-[var(--text-faint)] italic"></span>}
</div>
</KanbanCard>
))
)
)}
@@ -512,7 +506,7 @@ export function Dashboard({ data }: Props) {
</MiniCard>
</div>
)}
</>
</div>
)
}
}