feat(storyboard): 整张生成时每张分镜转圈(不全屏遮挡)+ 未生成占位回 2:3 竖屏
- 每张分镜占位(缩略图 + 大图)叠半透明遮罩 + spinner,样式同基础资产趴;不再全屏遮挡 - 中间大图空占位由 16:9 横框改 2:3 竖屏,与成品(1024×1536)同形;fh-flat 下加兜底高度居中 - 生成结束(成功/失败)spinner 自动停 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
9c2a3bc365
commit
dbd1382fb1
@@ -481,7 +481,7 @@ export function PipelinePage(props: {
|
||||
onGenerateTriview: (portraitGroupId: string) => Promise<{ id: string } | null>;
|
||||
// 流程步骤4 · 添加人物工作台命名:把名字写回该人物资产
|
||||
onRenameActor?: (assetId: string, name: string) => Promise<unknown>;
|
||||
onGenerateStoryboard: (prompt: string) => void;
|
||||
onGenerateStoryboard: (prompt: string) => void | Promise<unknown>;
|
||||
onSkipStoryboard: () => Promise<unknown>;
|
||||
onSubmitVideo: (segmentId: string, prompt: string) => void;
|
||||
onSubmitAllVideos: (prompt: string) => void;
|
||||
@@ -846,6 +846,8 @@ export function PipelinePage(props: {
|
||||
// 让用户一眼看出「这里本该有几张」,出图后逐个填真图。无采用版脚本则为 0(显示「暂无」)。
|
||||
const sbAdoptedScript = scripts.find((s) => s.is_adopted) || null;
|
||||
const sbExpectedShots = sbAdoptedScript ? (sbAdoptedScript.segments?.length ?? 0) : 0;
|
||||
// 整张故事板生成中:不全屏遮挡,只在每张分镜占位上转个 spinner(样式同基础资产趴)
|
||||
const [sbGenerating, setSbGenerating] = useState(false);
|
||||
// 没生成故事板时点「确认故事板」→ 弹气泡提示先去生成(3.5s 自动收起)
|
||||
const [sbConfirmHint, setSbConfirmHint] = useState(false);
|
||||
useEffect(() => {
|
||||
@@ -2943,7 +2945,7 @@ export function PipelinePage(props: {
|
||||
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={`placeholder${url ? " has-mock-media" : ""}`} style={url ? mediaStyle(url) : undefined}><span className="ph-frame">场 {idx + 1}</span>{sbGenerating && <span className="sb-gen-veil" aria-hidden="true"><span className="spinner" /></span>}</div>
|
||||
<div className="nm">场 {idx + 1}</div>
|
||||
<div className="sub">{times[idx] || `#${frame.sort_order + 1}`}</div>
|
||||
</div>
|
||||
@@ -2953,7 +2955,7 @@ export function PipelinePage(props: {
|
||||
/* 还没出图:按采用版脚本镜头数铺等量空占位,标「待生成」,让用户看出本该有几张 */
|
||||
Array.from({ length: sbExpectedShots }, (_, idx) => (
|
||||
<div className={`sb-scene-thumb${idx === sbSelected ? " selected" : ""}`} key={`ph-${idx}`} onClick={() => setSbSelected(idx)}>
|
||||
<div className="placeholder"><span className="ph-frame">场 {idx + 1}</span></div>
|
||||
<div className="placeholder"><span className="ph-frame">场 {idx + 1}</span>{sbGenerating && <span className="sb-gen-veil" aria-hidden="true"><span className="spinner" /></span>}</div>
|
||||
<div className="nm">场 {idx + 1}</div>
|
||||
<div className="sub">// 待生成</div>
|
||||
</div>
|
||||
@@ -2965,6 +2967,7 @@ export function PipelinePage(props: {
|
||||
return (
|
||||
<div className={`placeholder sb-main-img${url ? " has-mock-media" : ""}`} id="sb-main-img" style={url ? { ...mediaStyle(url), cursor: "zoom-in" } : undefined} role={url ? "button" : undefined} tabIndex={url ? 0 : undefined} title={url ? "点击放大" : undefined} onClick={url ? () => setPreview({ src: url, kind: "image", name: `场 ${sbSelected + 1}` }) : undefined} onKeyDown={url ? (event) => { if (event.key === "Enter" || event.key === " ") { event.preventDefault(); setPreview({ src: url, kind: "image", name: `场 ${sbSelected + 1}` }); } } : undefined}>
|
||||
<span className="ph-frame">{sbActiveFrame ? `场 ${sbSelected + 1}` : sbExpectedShots ? `场 ${sbSelected + 1} · 待生成` : "// 故事板未生成"}</span>
|
||||
{sbGenerating && <span className="sb-gen-veil" aria-hidden="true"><span className="spinner" /></span>}
|
||||
</div>
|
||||
);
|
||||
})()}
|
||||
@@ -2999,7 +3002,7 @@ export function PipelinePage(props: {
|
||||
onChange={(v) => setStoryboardPrompt(v.trim())}
|
||||
/>
|
||||
<div className="sb-stage-actions">
|
||||
<button className="pill-cta heat" type="button" id="sb-rerun-btn" disabled={loading} onClick={() => guardGen(shots, () => onGenerateStoryboard(storyboardPrompt || SB_PROMPT_DEFAULT))}>
|
||||
<button className="pill-cta heat" type="button" id="sb-rerun-btn" disabled={loading} onClick={() => guardGen(shots, () => { setSbGenerating(true); void Promise.resolve(onGenerateStoryboard(storyboardPrompt || SB_PROMPT_DEFAULT)).finally(() => setSbGenerating(false)); })}>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="M4 12a8 8 0 0 1 14-5.5L21 9" /><path d="M21 4v5h-5" /><path d="M20 12a8 8 0 0 1-14 5.5L3 15" /><path d="M3 20v-5h5" /></svg>
|
||||
{adoptedStoryboard ? "整张重跑" : "生成故事板"}
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user