fix(storyboard): 还原故事板 — 时间区间/缩略图/白底/字号对齐HTML

- E1 每场卡字号对齐 HTML:.nm 12→11.5、.sub 12→10.5、.asset-tag 12→11.5
- E2 故事板主图留白底色 --background-lighter(灰)→ --surface(白),
  contain 完整显示竖长拼图时不再透出「灰底大框」
- E3 每场 sub 由「#1」改为时间区间「0~15s」(累加脚本镜时长,无脚本回退序号)
- E4 绑定资产前的占位圆点 → 已引用资产缩略图(groupMainUrl,无图回退圆点)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
seaislee1209
2026-06-20 18:51:42 +08:00
co-authored by Claude Opus 4.8
parent d7f7ed2bae
commit 8550d532ac
2 changed files with 28 additions and 19 deletions
+20 -14
View File
@@ -2825,16 +2825,21 @@ export function PipelinePage(props: {
<div className="stage-storyboard">
<div className="sb-canvas">
<div className="sb-scenes-col" id="sb-scenes-row">
{sbFrames.length ? sbFrames.map((frame, idx) => {
const url = frameUrl(frame);
return (
<div className={`sb-scene-thumb${idx === sbSelected ? " selected" : ""}`} key={frame.id} data-sid={frame.id} onClick={() => setSbSelected(idx)}>
<div className={`placeholder${url ? " has-mock-media" : ""}`} style={url ? mediaStyle(url) : undefined}><span className="ph-frame"> {idx + 1}</span></div>
<div className="nm"> {idx + 1}</div>
<div className="sub">#{frame.sort_order + 1}</div>
</div>
);
}) : sbExpectedShots ? (
{sbFrames.length ? (() => {
// 每场显示时间区间(累加脚本镜时长 → 「0~5s」),对齐 HTML;无脚本时回退序号
let cum = 0;
const times = shots.map((s) => { const st = cum; cum += s.duration_seconds || 15; return `${st}~${cum}s`; });
return sbFrames.map((frame, idx) => {
const url = frameUrl(frame);
return (
<div className={`sb-scene-thumb${idx === sbSelected ? " selected" : ""}`} key={frame.id} data-sid={frame.id} onClick={() => setSbSelected(idx)}>
<div className={`placeholder${url ? " has-mock-media" : ""}`} style={url ? mediaStyle(url) : undefined}><span className="ph-frame"> {idx + 1}</span></div>
<div className="nm"> {idx + 1}</div>
<div className="sub">{times[idx] || `#${frame.sort_order + 1}`}</div>
</div>
);
});
})() : sbExpectedShots ? (
/* 还没出图:按采用版脚本镜头数铺等量空占位,标「待生成」,让用户看出本该有几张 */
Array.from({ length: sbExpectedShots }, (_, idx) => (
<div className={`sb-scene-thumb${idx === sbSelected ? " selected" : ""}`} key={`ph-${idx}`} onClick={() => setSbSelected(idx)}>
@@ -2912,12 +2917,13 @@ export function PipelinePage(props: {
// 与 Stage 2 同源:用 metadata.label 取名(不依赖全局 assets 列表),排除三视图组并按名字去重,
// 否则同一角色的立绘组+三视图组+多版本会各算一个,且名字会退化成「人物(人物)」。
const bound = [
...groupsByKind("product").filter((g) => g.adopted_asset).map((g) => ({ id: g.id, name: (g.metadata?.label || "").trim() || KIND_LABEL.product, kind: "product" as const })),
...buildEntities("person").filter((e) => e.group.adopted_asset).map((e) => ({ id: e.key, name: e.name, kind: "person" as const })),
...buildEntities("scene").filter((e) => e.group.adopted_asset).map((e) => ({ id: e.key, name: e.name, kind: "scene" as const })),
...groupsByKind("product").filter((g) => g.adopted_asset).map((g) => ({ id: g.id, name: (g.metadata?.label || "").trim() || KIND_LABEL.product, kind: "product" as const, url: groupMainUrl(g) })),
...buildEntities("person").filter((e) => e.group.adopted_asset).map((e) => ({ id: e.key, name: e.name, kind: "person" as const, url: groupMainUrl(e.group) })),
...buildEntities("scene").filter((e) => e.group.adopted_asset).map((e) => ({ id: e.key, name: e.name, kind: "scene" as const, url: groupMainUrl(e.group) })),
];
// 圆点占位 → 已引用资产缩略图(一眼看出绑了哪张),无图时回退圆点
return bound.length ? bound.map((b) => (
<span className="asset-tag" key={b.id}><span className="dotc"></span>{b.name}({KIND_LABEL[b.kind]})</span>
<span className="asset-tag" key={b.id}>{b.url ? <span className="asset-thumb" style={{ backgroundImage: `url(${b.url})` }} /> : <span className="dotc"></span>}{b.name}({KIND_LABEL[b.kind]})</span>
)) : <span className="muted-2 mono" style={{ fontSize: "12px" }}>// 暂无绑定资产</span>;
})()}
</div>