fix: 清单4 未完成项二轮(视频项目收口/选用角色/场景空镜/场景刷新 + 4:5 尺寸)
ZWQ#15 视频进度卡 3/4(真因补全): - current_stage 没推到 VIDEO 时 settle 守卫直接返回 → 永不收口。 submit/poll/adopt 幂等补推 current_stage→VIDEO;进详情(retrieve)检测全段已出片即自愈收口。 存量卡死项目一打开就自动变「已完成」。+2 测试 ZWQ#7 演员库选用角色未自动「已过审/已采用」: - 真实流程是 attach(选用),非详情弹窗按钮。attach 时显式置 adopt=adopted + 人物立绘自动送审(on_commit)。+1 测试 ZWQ#13 场景出真人致视频被拒(加强): - 场景空镜约束改为显式压过脚本描述里的人物词(「即使上文提到人也只画环境」)。 ZWQ#17 场景生成中刷新跳新窗口: - 正在生成的场景草稿不再落盘 → 生成中刷新页面不会与新实体卡并存成两个窗口。 附:平台套图 4:5 尺寸 1664x2080→1728x2160(≥Seedream 5.0 最小面积 3686400px,否则 ARK 退 400)。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -614,11 +614,14 @@ export function PipelinePage(props: {
|
||||
// 出图成功后从草稿列表移除(生成结果会作为实体卡出现在下方)。不直接生成,避免一点就出一张默认图。
|
||||
// 持久化到 localStorage(按项目隔离):新增场景没点 AI 生成就刷新页面也不会丢(ZWQ#10)。
|
||||
const sceneDraftsKey = `airshelf:scenedrafts:${project.id}`;
|
||||
const [sceneDrafts, setSceneDrafts] = useState<Array<{ id: string; title: string; prompt: string }>>(() => {
|
||||
try { const raw = localStorage.getItem(sceneDraftsKey); return raw ? (JSON.parse(raw) as Array<{ id: string; title: string; prompt: string }>) : []; } catch { return []; }
|
||||
type SceneDraft = { id: string; title: string; prompt: string; generating?: boolean };
|
||||
const [sceneDrafts, setSceneDrafts] = useState<SceneDraft[]>(() => {
|
||||
try { const raw = localStorage.getItem(sceneDraftsKey); return raw ? (JSON.parse(raw) as SceneDraft[]).map((d) => ({ ...d, generating: false })) : []; } catch { return []; }
|
||||
});
|
||||
useEffect(() => {
|
||||
try { localStorage.setItem(sceneDraftsKey, JSON.stringify(sceneDrafts)); } catch { /* localStorage 不可用时静默降级 */ }
|
||||
// 只持久化「还没点 AI 生成」的草稿;正在生成的草稿不落盘——否则生成中刷新页面后,
|
||||
// 这张草稿会和生成完成后新出现的实体卡并存成两个窗口(ZWQ#17)。
|
||||
try { localStorage.setItem(sceneDraftsKey, JSON.stringify(sceneDrafts.filter((d) => !d.generating))); } catch { /* localStorage 不可用时静默降级 */ }
|
||||
}, [sceneDrafts, sceneDraftsKey]);
|
||||
// 行39 · 商品三视图:点「AI 生成三视图」展开卡片右侧预览面板(对齐原版 prod-preview,非弹窗)
|
||||
// 每次生成=一个 product group=一版三视图;预览态(triPreviewId)只切主图,采用态存 metadata.product_tri_group
|
||||
@@ -3029,7 +3032,14 @@ export function PipelinePage(props: {
|
||||
<div className="hstack" style={{ marginTop: 10 }}>
|
||||
<button className="btn btn-ghost btn-sm" type="button" data-stop disabled={busy} onClick={() => setSceneDrafts((list) => list.filter((d) => d.id !== draft.id))}>移除</button>
|
||||
<span className="spacer"></span>
|
||||
<button className="btn btn-primary btn-sm" type="button" data-stop disabled={busy} onClick={async () => { const p = draft.prompt.trim() || genPrompt; const res = await genBaseAsset("scene", p, draft.title.trim() || undefined, dk); if (res && (res.id || res.adopted_asset)) setSceneDrafts((list) => list.filter((d) => d.id !== draft.id)); }}>{busy ? "生成中…" : "AI 生成"}</button>
|
||||
<button className="btn btn-primary btn-sm" type="button" data-stop disabled={busy} onClick={async () => {
|
||||
const p = draft.prompt.trim() || genPrompt;
|
||||
// 一启动就标 generating(此后不再落盘):生成中刷新页面不会留下这张草稿 → 不会和新实体卡并存(ZWQ#17)
|
||||
setSceneDrafts((list) => list.map((d) => d.id === draft.id ? { ...d, generating: true } : d));
|
||||
const res = await genBaseAsset("scene", p, draft.title.trim() || undefined, dk);
|
||||
if (res && (res.id || res.adopted_asset)) setSceneDrafts((list) => list.filter((d) => d.id !== draft.id)); // 成功:结果已成实体卡,移除草稿
|
||||
else setSceneDrafts((list) => list.map((d) => d.id === draft.id ? { ...d, generating: false } : d)); // 失败:恢复草稿可重试
|
||||
}}>{busy ? "生成中…" : "AI 生成"}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user