auto-save 2026-05-14 05:54 (~3)
This commit is contained in:
@@ -1,19 +1,5 @@
|
||||
{
|
||||
"entries": [
|
||||
{
|
||||
"files_changed": 4,
|
||||
"hash": "35b3278",
|
||||
"message": "auto-save 2026-05-12 16:16 (~4)",
|
||||
"ts": "2026-05-12T16:16:52+08:00",
|
||||
"type": "commit"
|
||||
},
|
||||
{
|
||||
"files_changed": 1,
|
||||
"hash": "7283928",
|
||||
"message": "auto-save 2026-05-12 16:22 (~1)",
|
||||
"ts": "2026-05-12T16:22:23+08:00",
|
||||
"type": "commit"
|
||||
},
|
||||
{
|
||||
"files_changed": 1,
|
||||
"hash": "03cd5b4",
|
||||
@@ -3357,6 +3343,19 @@
|
||||
"type": "session-heartbeat",
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 2 项未提交变更 · 最近提交:auto-save 2026-05-14 05:43 (~3)",
|
||||
"files_changed": 2
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-14T05:49:26+08:00",
|
||||
"type": "commit",
|
||||
"message": "auto-save 2026-05-14 05:49 (~2)",
|
||||
"hash": "a98639a",
|
||||
"files_changed": 2
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-13T21:53:13Z",
|
||||
"type": "session-heartbeat",
|
||||
"message": "Claude 会话活跃 · 最近命令:claude · 3 项未提交变更 · 最近提交:auto-save 2026-05-14 05:49 (~2)",
|
||||
"files_changed": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -623,7 +623,7 @@ api/main.py
|
||||
</div>
|
||||
<div class="flow-row">
|
||||
<div><strong>你看到的区域</strong><span>关键帧素材审核面板</span></div>
|
||||
<div><strong>主要源码</strong><span><code>FrameLightbox</code>;按“原图/清洗、场景图、主体资产、审核”四个页签组织;清洗页支持一键批量生成待审核清洗版,相关接口包括 <code>cleanupFrame</code>、<code>addElement</code>、<code>generateSceneAsset</code>、<code>generateSubjectAssets</code>。</span></div>
|
||||
<div><strong>主要源码</strong><span><code>FrameLightbox</code>;按“原图/清洗、场景图、主体资产、审核”四个页签组织;非主体页采用左侧大图 + 右侧窄状态栏,主体资产页保留较宽右栏;清洗页支持一键批量生成待审核清洗版,相关接口包括 <code>cleanupFrame</code>、<code>addElement</code>、<code>generateSceneAsset</code>、<code>generateSubjectAssets</code>。</span></div>
|
||||
<div><strong>适合怎么描述</strong><span>“某张关键帧的水印、场景图、主体多视角/动作/表情图和质量风险应该如何审核”。</span></div>
|
||||
</div>
|
||||
<div class="flow-row">
|
||||
@@ -724,7 +724,7 @@ SubjectAsset {
|
||||
<tr><td>解析视频</td><td><code>POST /jobs/{id}/analyze?frames=&target=&mode=&quality=</code></td><td><code>analyzeJob</code></td><td>拆轨 + 目标化抽关键帧。<code>target</code> 支持综合、清晰主体、转场变化、表情瞬间、动作峰值;<code>mode=append</code> 追加新关键帧;<code>quality=auto</code> 根据本机算力和视频时长自动选择快速、精细或极准。多个抽帧请求进入后端队列顺序处理。</td></tr>
|
||||
<tr><td>手动加帧</td><td><code>POST /jobs/{id}/frames?t=</code></td><td><code>addManualFrame</code></td><td>按视频时间戳抽一帧,index 递增但 frames 按 timestamp 排序。</td></tr>
|
||||
<tr><td>Vision 识别</td><td><code>POST /frames/{idx}/describe</code></td><td><code>describeFrame</code></td><td>写入 frame.description,后续可从 objects 加候选元素。</td></tr>
|
||||
<tr><td>清洗水印</td><td><code>POST /frames/{idx}/cleanup</code></td><td><code>cleanupFrame</code></td><td>支持全图和区域清洗,生成 cleaned 待应用版本;前端批量清洗会顺序调用该接口,不自动覆盖原图。</td></tr>
|
||||
<tr><td>清洗水印</td><td><code>POST /frames/{idx}/cleanup</code></td><td><code>cleanupFrame</code></td><td>支持全图和区域清洗,生成 cleaned 待应用版本;前端批量清洗会顺序调用该接口,不自动覆盖原图。单帧清洗状态按 frame.index 隔离,清洗某一张不会禁用其他关键帧的清洗按钮。</td></tr>
|
||||
<tr><td>应用清洗</td><td><code>POST /cleanup/apply</code></td><td><code>applyCleanedFrame</code></td><td>物理覆盖 frames/{idx}.jpg,并备份原图。</td></tr>
|
||||
<tr><td>元素增改删</td><td><code>POST/PATCH/DELETE /elements</code></td><td><code>addElement/updateElement/deleteElement</code></td><td>让用户修正 Vision 错误,避免候选结果锁死。</td></tr>
|
||||
<tr><td>元素提取</td><td><code>POST /elements/{element_id}/cutout</code></td><td><code>cutoutElement</code></td><td>调用图像模型生成独立白底素材图,每次累积一张 cutout。</td></tr>
|
||||
@@ -839,6 +839,30 @@ SubjectAsset {
|
||||
<h2>变更记录</h2>
|
||||
<p>这个记录不是 git log 的替代品。它记录“产品理解发生了什么变化、影响了哪些源码、你以后描述需求时该怎么说”。后续每次改功能都要补一条。</p>
|
||||
<div class="changelog">
|
||||
<article class="change">
|
||||
<header>
|
||||
<h3>2026-05-14 · 关键帧素材面板右侧改为紧凑状态栏</h3>
|
||||
<span class="tag violet">FrameLightbox</span>
|
||||
<span class="tag blue">Layout</span>
|
||||
</header>
|
||||
<div class="body">
|
||||
<p><strong>问题:</strong>移除旧元素提取和手工加主体入口后,关键帧详情右侧内容变少,继续占用大列会压缩左侧主图和清洗操作区。</p>
|
||||
<p><strong>改动:</strong><code>FrameLightbox</code> 在“原图/清洗、场景图、审核”页把右侧改成固定窄状态栏,左侧主图和操作区获得更大宽度;“主体资产”页仍保留较宽右栏,用于主体识别、主体清单和资产包。</p>
|
||||
<p><strong>影响:</strong><code>web/components/lightbox.tsx</code>、<code>docs/source-analysis.html</code>。</p>
|
||||
</div>
|
||||
</article>
|
||||
<article class="change">
|
||||
<header>
|
||||
<h3>2026-05-14 · 单帧清洗不再全局锁住其他帧</h3>
|
||||
<span class="tag violet">FrameLightbox</span>
|
||||
<span class="tag blue">Bugfix</span>
|
||||
</header>
|
||||
<div class="body">
|
||||
<p><strong>问题:</strong>单独清洗某一张关键帧时,前端使用全局 <code>cleaning</code> 布尔状态,导致切到其他关键帧后清洗按钮仍被禁用。</p>
|
||||
<p><strong>改动:</strong><code>FrameLightbox</code> 改用 <code>cleaningFrameIds</code> 按 <code>frame.index</code> 记录正在清洗的帧,只禁用当前正在清洗的那一张;其他帧可以继续单独清洗。区域清洗完成时也只在用户仍停留于同一帧时清空当前框选,避免异步完成误清别的帧操作状态。</p>
|
||||
<p><strong>影响:</strong><code>web/components/lightbox.tsx</code>、<code>docs/source-analysis.html</code>。</p>
|
||||
</div>
|
||||
</article>
|
||||
<article class="change">
|
||||
<header>
|
||||
<h3>2026-05-14 · 清洗页支持一键批量清洗</h3>
|
||||
|
||||
@@ -128,6 +128,8 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
|
||||
...(f.quality_report?.warnings ?? []),
|
||||
...(latestSceneAsset?.quality_report?.warnings ?? []),
|
||||
]
|
||||
const isSubjectTab = activeTab === "subject"
|
||||
const isCleanTab = activeTab === "clean"
|
||||
|
||||
const handleDescribe = async () => {
|
||||
setDescribing(true)
|
||||
@@ -421,12 +423,16 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 主体 — 左:大图 + 清洗状态;右:主体识别 + 主体资产 */}
|
||||
{/* 主体 — 左:大图 + 主操作;右:当前页上下文 / 主体资产 */}
|
||||
<div className="flex gap-3 p-3 overflow-hidden flex-1 min-h-0">
|
||||
{/* 左侧大图区 */}
|
||||
<div
|
||||
className="flex flex-col items-stretch gap-2 overflow-y-auto pr-1"
|
||||
style={{ flex: "1 1 320px", minWidth: 200, maxWidth: 420, minHeight: 0 }}
|
||||
style={isSubjectTab
|
||||
? { flex: "1 1 360px", minWidth: 220, maxWidth: 460, minHeight: 0 }
|
||||
: isCleanTab
|
||||
? { flex: "1 1 500px", minWidth: 300, maxWidth: 600, minHeight: 0 }
|
||||
: { flex: "1 1 560px", minWidth: 300, maxWidth: 680, minHeight: 0 }}
|
||||
>
|
||||
{/* 上方:主图 + 画框 overlay */}
|
||||
<div
|
||||
@@ -441,7 +447,13 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
|
||||
src={mainSrc}
|
||||
alt={`frame ${f.index}`}
|
||||
className="rounded-lg object-contain w-full pointer-events-none"
|
||||
style={{ maxHeight: hasCleaned ? "38vh" : "62vh" }}
|
||||
style={{
|
||||
maxHeight: isSubjectTab
|
||||
? (hasCleaned ? "38vh" : "62vh")
|
||||
: isCleanTab
|
||||
? "68vh"
|
||||
: (hasCleaned ? "44vh" : "68vh"),
|
||||
}}
|
||||
draggable={false}
|
||||
/>
|
||||
<div className="absolute top-2 left-2 text-[9.5px] px-1.5 py-0.5 rounded backdrop-blur bg-black/50 text-white/80 pointer-events-none">
|
||||
@@ -482,144 +494,6 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
|
||||
)}
|
||||
</div>
|
||||
|
||||
{activeTab === "clean" && (
|
||||
<>
|
||||
<div className="rounded-lg border border-cyan-300/20 bg-cyan-500/[0.08] p-2">
|
||||
<div className="mb-2 flex items-center justify-between gap-2">
|
||||
<div>
|
||||
<div className="text-[11.5px] font-semibold text-white">批量清洗</div>
|
||||
<div className="mt-0.5 text-[9.5px] text-white/42">
|
||||
先批量生成待审核清洗版,不直接覆盖原图
|
||||
</div>
|
||||
</div>
|
||||
<span className="shrink-0 rounded bg-black/35 px-1.5 py-0.5 text-[9.5px] font-mono text-white/55">
|
||||
{cleanedFrameCount}/{frames.length}
|
||||
</span>
|
||||
</div>
|
||||
{batchCleanupProgress && (
|
||||
<div className="mb-2">
|
||||
<div className="mb-1 flex items-center justify-between text-[9.5px] text-white/45">
|
||||
<span>{batchCleaning ? "清洗中" : "最近批量清洗"}</span>
|
||||
<span>{batchCleanupProgress.done}/{batchCleanupProgress.total}{batchCleanupProgress.failed ? ` · 失败 ${batchCleanupProgress.failed}` : ""}</span>
|
||||
</div>
|
||||
<div className="h-1.5 overflow-hidden rounded-full bg-white/10">
|
||||
<div
|
||||
className="h-full rounded-full bg-cyan-300 transition-all"
|
||||
style={{ width: `${Math.round((batchCleanupProgress.done / Math.max(1, batchCleanupProgress.total)) * 100)}%` }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleCleanupAllFrames}
|
||||
disabled={batchCleaning || cropMode || frames.length === 0}
|
||||
className="w-full rounded-md bg-cyan-500/75 px-2 py-1.5 text-[11px] font-medium text-white transition hover:bg-cyan-400 disabled:cursor-wait disabled:opacity-45 inline-flex items-center justify-center gap-1.5"
|
||||
title="自动清洗所有未处理关键帧;不满意的帧再手工框选清洗"
|
||||
>
|
||||
{batchCleaning ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : <Sparkles className="h-3.5 w-3.5" />}
|
||||
{batchCleaning
|
||||
? "批量清洗中…"
|
||||
: pendingCleanFrames.length > 0
|
||||
? `一键清洗未处理 ${pendingCleanFrames.length} 张`
|
||||
: `重新清洗全部 ${frames.length} 张`}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* 画框工具栏 */}
|
||||
{cropMode ? (
|
||||
<div className="space-y-1.5">
|
||||
<div className="text-[10px] text-white/55 leading-snug">
|
||||
{regions.length === 0
|
||||
? "在图上拖动鼠标 → 框选要清洗的水印、字幕、平台 UI 或杂物"
|
||||
: `已框 ${regions.length} 个 · 继续加框或点击「去掉」批量清洗`}
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<button
|
||||
onClick={() => handleCleanup(true)}
|
||||
disabled={isCleaningCurrentFrame || batchCleaning || regions.length === 0}
|
||||
className="flex-1 px-1.5 py-1.5 rounded-md text-[10.5px] font-medium inline-flex items-center justify-center gap-1 transition bg-cyan-500 hover:bg-cyan-400 text-white disabled:opacity-40 disabled:cursor-not-allowed"
|
||||
title="批量清洗所有框内"
|
||||
>
|
||||
{isCleaningCurrentFrame ? <Loader2 className="h-3 w-3 animate-spin" /> : <Sparkle className="h-3 w-3" />}
|
||||
{isCleaningCurrentFrame ? "去掉中" : `去掉${regions.length > 1 ? ` ${regions.length}` : ""}`}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setRegions((prev) => prev.slice(0, -1))}
|
||||
disabled={regions.length === 0}
|
||||
className="px-1.5 py-1.5 rounded-md text-[10.5px] bg-white/10 hover:bg-white/20 text-white disabled:opacity-30 disabled:cursor-not-allowed"
|
||||
title="撤销上一个框"
|
||||
>
|
||||
↶
|
||||
</button>
|
||||
<button
|
||||
onClick={() => { setCropMode(false); setRegions([]); setDraftRegion(null); setDragStart(null) }}
|
||||
className="px-1.5 py-1.5 rounded-md text-[10.5px] bg-white/10 hover:bg-white/20 text-white"
|
||||
title="退出画框"
|
||||
>
|
||||
<X className="h-3 w-3" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<button
|
||||
onClick={() => { setCropMode(true); setRegions([]) }}
|
||||
className="w-full px-3 py-1.5 rounded-md text-[10.5px] font-medium inline-flex items-center justify-center gap-1.5 transition bg-white/[0.06] hover:bg-cyan-500/30 border border-white/15 hover:border-cyan-300/50 text-white/80 hover:text-white"
|
||||
title="可连续画多个框 · 批量清洗局部水印或杂物"
|
||||
>
|
||||
<Crop className="h-3 w-3" />
|
||||
框选清洗区域(可多框)
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* 下方:清洗版(有待应用版本时显示) */}
|
||||
{hasCleaned && cleanedSrc && (
|
||||
<div className="relative rounded-lg border border-emerald-400/40 bg-emerald-500/5 p-2 space-y-1.5">
|
||||
<div className="flex items-center justify-between pr-5">
|
||||
<div className="text-[10px] text-emerald-300 inline-flex items-center gap-1 font-medium">
|
||||
<Sparkle className="h-2.5 w-2.5" />
|
||||
清洗结果
|
||||
</div>
|
||||
<span className="text-[9px] text-white/40">待应用</span>
|
||||
</div>
|
||||
<button
|
||||
onClick={handleDiscardCleaned}
|
||||
title="丢弃这次清洗结果"
|
||||
className="absolute top-1.5 right-1.5 h-5 w-5 rounded-full bg-black/40 hover:bg-rose-500/80 text-white/70 hover:text-white inline-flex items-center justify-center transition"
|
||||
>
|
||||
<X className="h-2.5 w-2.5" />
|
||||
</button>
|
||||
<img
|
||||
src={cleanedSrc}
|
||||
alt={`cleaned ${f.index}`}
|
||||
className="rounded-md object-contain w-full"
|
||||
style={{ maxHeight: "32vh" }}
|
||||
/>
|
||||
<button
|
||||
onClick={handleApplyCleaned}
|
||||
disabled={applying}
|
||||
className="w-full px-2 py-1.5 rounded-md text-[11px] font-medium inline-flex items-center justify-center gap-1 transition bg-emerald-500 hover:bg-emerald-400 text-white disabled:opacity-40 disabled:cursor-not-allowed"
|
||||
title="替换原图为这张干净版 · 后续场景图、主体资产和分镜编排都基于干净版"
|
||||
>
|
||||
{applying ? <Loader2 className="h-3 w-3 animate-spin" /> : <Check className="h-3 w-3" />}
|
||||
{applying ? "替换中…" : "替换原图"}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 清洗按钮(全图) */}
|
||||
<button
|
||||
onClick={() => handleCleanup(false)}
|
||||
disabled={isCleaningCurrentFrame || batchCleaning || cropMode}
|
||||
className="w-full px-3 py-1.5 rounded-md text-[11.5px] font-medium inline-flex items-center justify-center gap-1.5 transition bg-gradient-to-r from-cyan-500/80 to-emerald-500/80 hover:from-cyan-500 hover:to-emerald-500 text-white disabled:opacity-40 disabled:cursor-not-allowed"
|
||||
title="清掉水印 / @用户名 / 字幕 / 平台 logo"
|
||||
>
|
||||
{isCleaningCurrentFrame ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : <Sparkle className="h-3.5 w-3.5" />}
|
||||
{isCleaningCurrentFrame ? "清洗中…(5-15 秒)" : hasCleaned ? "重新清洗" : f.cleaned_applied ? "再次清洗" : "清洗水印"}
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
|
||||
{activeTab === "scene" && (
|
||||
<div className="rounded-lg border border-white/10 bg-white/[0.035] p-2">
|
||||
<div className="mb-2 flex items-center justify-between gap-2">
|
||||
@@ -702,6 +576,7 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
|
||||
</div>
|
||||
)}
|
||||
|
||||
{activeTab !== "clean" && (
|
||||
<div className="rounded-md border border-emerald-300/20 bg-emerald-500/10 px-3 py-2 text-[11px] leading-relaxed text-emerald-50/80">
|
||||
<div className="mb-0.5 inline-flex items-center gap-1 font-medium text-emerald-100">
|
||||
<Check className="h-3 w-3" />
|
||||
@@ -711,25 +586,47 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
|
||||
抽帧留下的关键帧默认都会参与清洗、场景图和主体资产准备,不需要在这里单独选用。
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 右侧主体识别 + 主体资产 */}
|
||||
<div className="flex flex-col gap-2.5 overflow-y-auto flex-1 min-h-0" style={{ minWidth: 240 }}>
|
||||
<div
|
||||
className="flex flex-col gap-2.5 overflow-y-auto min-h-0"
|
||||
style={isSubjectTab
|
||||
? { flex: "1 1 300px", minWidth: 260 }
|
||||
: { flex: "0 0 224px", width: 224, minWidth: 208, maxWidth: 240 }}
|
||||
>
|
||||
{activeTab === "clean" && (
|
||||
<section className="rounded-lg border border-cyan-300/15 bg-cyan-500/[0.08] p-3 text-[11px] leading-relaxed text-white/58">
|
||||
<div className="mb-1.5 text-[12.5px] font-semibold text-white">清洗审核</div>
|
||||
可以先一键清洗全部素材帧,系统只生成待审核清洗版,不直接覆盖原图。看到没处理好的帧,再回到这张图用框选区域做局部清洗。
|
||||
<section className="rounded-lg border border-cyan-300/15 bg-cyan-500/[0.08] p-2.5 text-[10.5px] leading-relaxed text-white/58">
|
||||
<div className="mb-2 text-[12px] font-semibold text-white">清洗状态</div>
|
||||
<div className="mb-2 grid grid-cols-2 gap-1.5">
|
||||
<div className="rounded border border-white/10 bg-black/25 px-2 py-1">
|
||||
<div className="text-[9px] text-white/35">当前</div>
|
||||
<div className="text-[10.5px] text-white/80">{f.cleaned_applied ? "已应用" : hasCleaned ? "待审核" : "未清洗"}</div>
|
||||
</div>
|
||||
<div className="rounded border border-white/10 bg-black/25 px-2 py-1">
|
||||
<div className="text-[9px] text-white/35">全部</div>
|
||||
<div className="text-[10.5px] text-white/80">{cleanedFrameCount}/{frames.length}</div>
|
||||
</div>
|
||||
</div>
|
||||
先批量生成清洗版,再对问题帧局部框选补洗。
|
||||
</section>
|
||||
)}
|
||||
{activeTab === "scene" && (
|
||||
<section className="rounded-lg border border-emerald-300/15 bg-emerald-500/[0.08] p-3 text-[11px] leading-relaxed text-white/58">
|
||||
<div className="mb-1.5 text-[12.5px] font-semibold text-white">场景资产规则</div>
|
||||
每张已选关键帧只需要一张主场景图。它用于后续生视频的空间、构图和光线参考;生成后仍需人工确认水印和细节是否被误改。
|
||||
<section className="rounded-lg border border-emerald-300/15 bg-emerald-500/[0.08] p-2.5 text-[10.5px] leading-relaxed text-white/58">
|
||||
<div className="mb-2 text-[12px] font-semibold text-white">场景状态</div>
|
||||
<div className="mb-2 rounded border border-white/10 bg-black/25 px-2 py-1">
|
||||
<div className="text-[9px] text-white/35">当前场景图</div>
|
||||
<div className="text-[10.5px] text-white/80">
|
||||
{latestSceneAsset ? `${latestSceneAsset.width}×${latestSceneAsset.height}` : "未生成"}
|
||||
</div>
|
||||
</div>
|
||||
每张关键帧保留一张主场景图,用于空间、构图和光线参考。
|
||||
{f.scene_assets?.length ? (
|
||||
<div className="mt-2 grid grid-cols-2 gap-2">
|
||||
<div className="mt-2 grid grid-cols-2 gap-1.5">
|
||||
{f.scene_assets.slice(-4).map((asset) => (
|
||||
<div key={asset.id} className="overflow-hidden rounded-md border border-white/10 bg-black/35">
|
||||
<img src={apiAssetUrl(asset.url)} alt={asset.label} className="h-24 w-full object-contain" />
|
||||
<img src={apiAssetUrl(asset.url)} alt={asset.label} className="h-20 w-full object-contain" />
|
||||
<div className="px-1.5 py-1 text-[9.5px] font-mono text-white/45">{asset.width}×{asset.height}</div>
|
||||
</div>
|
||||
))}
|
||||
@@ -738,13 +635,25 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
|
||||
</section>
|
||||
)}
|
||||
{activeTab === "review" && (
|
||||
<section className="rounded-lg border border-white/10 bg-white/[0.035] p-3 text-[11px] leading-relaxed text-white/58">
|
||||
<div className="mb-2 text-[12.5px] font-semibold text-white">当前帧状态</div>
|
||||
<div className="space-y-1.5">
|
||||
<div>清洗:{f.cleaned_applied ? "已应用" : hasCleaned ? "待确认" : "未处理"}</div>
|
||||
<div>场景图:{latestSceneAsset ? `${latestSceneAsset.width}×${latestSceneAsset.height}` : "未生成"}</div>
|
||||
<div>主体候选:{elements.length} 个</div>
|
||||
<div>主体资产:{subjectAssetCount} 张</div>
|
||||
<section className="rounded-lg border border-white/10 bg-white/[0.035] p-2.5 text-[10.5px] leading-relaxed text-white/58">
|
||||
<div className="mb-2 text-[12px] font-semibold text-white">当前帧状态</div>
|
||||
<div className="grid grid-cols-2 gap-1.5">
|
||||
<div className="rounded border border-white/10 bg-black/25 px-2 py-1">
|
||||
<div className="text-[9px] text-white/35">清洗</div>
|
||||
<div className="text-white/80">{f.cleaned_applied ? "已应用" : hasCleaned ? "待确认" : "未处理"}</div>
|
||||
</div>
|
||||
<div className="rounded border border-white/10 bg-black/25 px-2 py-1">
|
||||
<div className="text-[9px] text-white/35">场景</div>
|
||||
<div className="text-white/80">{latestSceneAsset ? "已生成" : "未生成"}</div>
|
||||
</div>
|
||||
<div className="rounded border border-white/10 bg-black/25 px-2 py-1">
|
||||
<div className="text-[9px] text-white/35">主体</div>
|
||||
<div className="text-white/80">{elements.length} 个</div>
|
||||
</div>
|
||||
<div className="rounded border border-white/10 bg-black/25 px-2 py-1">
|
||||
<div className="text-[9px] text-white/35">资产</div>
|
||||
<div className="text-white/80">{subjectAssetCount} 张</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user