diff --git a/core/frontend/src/pipeline-page.css b/core/frontend/src/pipeline-page.css index a4b4210..5191e8a 100644 --- a/core/frontend/src/pipeline-page.css +++ b/core/frontend/src/pipeline-page.css @@ -375,7 +375,8 @@ .prompt-box[contenteditable="true"] { cursor: text; outline: none; } .prompt-box[contenteditable="true"]:hover { border-color: var(--heat-20); } .prompt-box[contenteditable="true"]:focus { border-color: var(--heat); background: var(--surface); color: var(--accent-black); box-shadow: 0 0 0 3px var(--heat-12); } - .fail-icon { width: 28px; height: 28px; background: var(--accent-crimson); color: var(--accent-white); display: grid; place-items: center; font-weight: 600; font-size: 16px; border-radius: 50%; } + /* 外层人物/场景卡提示词框:固定 5 行高(行高 1.55 + 内边距/边框),超长不撑高、框内上下滚动 */ + .prompt-box { height: calc(5 * 1.55em + 22px); overflow-y: auto; box-sizing: border-box; } /* ============= STAGE 3 · 故事板 ============= */ .content--fh .stage[data-stage-pane="3"].active > .stage-storyboard { flex: 1 1 0; min-height: 0; overflow-y: auto; } diff --git a/core/frontend/src/routes/pipeline.tsx b/core/frontend/src/routes/pipeline.tsx index 060c2cb..386f967 100644 --- a/core/frontend/src/routes/pipeline.tsx +++ b/core/frontend/src/routes/pipeline.tsx @@ -799,6 +799,14 @@ export function PipelinePage(props: { setAdTriId(null); // 跟随当前立绘的最新三视图 setAdPrompt(entity.group.prompt ?? ""); } + // seed(未生成)卡也能点进详情:还没组,用脚本名(=key)+ 当前提示词开一个「空壳」详情。 + // 进去先生成立绘;三视图按既有逻辑(无立绘则禁用)天然挡住。生成完刷新 → 同 key(=名字)自动切到真实体。 + function openSeedDetail(kind: "person" | "scene", tag: string, promptValue: string) { + setAdDetail({ kind, key: tag }); + setAdPortraitId(null); + setAdTriId(null); + setAdPrompt(promptValue); + } // 流程步骤4 · 演员库覆盖层:replace 带要替换的目标(已生成卡=groupId;seed 占位卡还没组=kind+label); // browse 带 studio 直接进「添加人物工作台」 const [actorLib, setActorLib] = useState<{ mode: "browse" | "replace"; studio?: boolean; groupId?: string; seedKind?: "person" | "scene"; seedLabel?: string; addNew?: boolean } | null>(null); @@ -2819,13 +2827,14 @@ export function PipelinePage(props: { const busy = isBusy(seedKey) || isBusy(`${seedKey}:tri`) || pendingHas(kind, tag); return (
-
+
openSeedDetail(kind, tag, promptValue)} onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); openSeedDetail(kind, tag, promptValue); } }}> {busy ?
生成中 · 约 8s
: {tag} · 待生成}
-
{tag}来自脚本
+
openSeedDetail(kind, tag, promptValue)}>{tag}来自脚本
setAssetPromptDraft((m) => ({ ...m, [seedKey]: v }))} />
@@ -3612,8 +3621,15 @@ export function PipelinePage(props: { {/* ── 流程步骤4 · 人物/场景详情弹窗:立绘 + 三视图(人物)+ 提示词重获 + 版本历史 + 应用到当前项目 ── */} {adDetail && (() => { const entities = buildEntities(adDetail.kind); - const entity = entities.find((e) => e.key === adDetail.key); - if (!entity) return null; + const realEntity = entities.find((e) => e.key === adDetail.key); + // seed(还没生成组)也能开详情:用脚本名(=key)+ 当前提示词兜个「空壳」实体,进去先生成立绘。 + // 生成完刷新 → buildEntities 按同 key(label=名字)收到真实组,自动切回真实体。 + const entity: AssetEntity = realEntity ?? { + key: adDetail.key, label: adDetail.key, name: adDetail.key, kind: adDetail.kind, + group: { id: "", kind: adDetail.kind, prompt: adPrompt, adopted_asset: null, candidate_assets: [] }, + versions: [], + }; + const isSeed = !realEntity; // 空壳态:还没立绘 const isPerson = adDetail.kind === "person"; const grp = entity.group; const portraitVersions = grp.candidate_assets ?? []; @@ -3626,7 +3642,8 @@ export function PipelinePage(props: { const viewTriAsset = (adTriId && triVersions.includes(adTriId)) ? adTriId : (triGroup?.adopted_asset || triVersions.at(-1) || ""); const triUrl = candUrl(triGroup, viewTriAsset); const pBK = `addet-portrait:${entity.key}`; - const busyPortrait = isBusy(pBK); + // 没立绘时(尤其 seed 首次生成),立绘在 worker 跑 ~30s,本地 isBusy 早已落回 → 用 pendingHas 兜底转圈 + const busyPortrait = isBusy(pBK) || (!portraitUrl && pendingHas(adDetail.kind, entity.name)); const busyTri = isBusy(`addet-tri:${entity.key}`) || isBusy(`${pBK}:tri`); async function regenPortrait() { const prompt = adPrompt.trim() || grp.prompt || `${entity!.name},9:16 竖屏`; @@ -3701,7 +3718,7 @@ export function PipelinePage(props: { {!triUrl && !busyTri && (
- 三视图据这版立绘生成,保证正/侧/背多角度一致。点下方按钮生成。 + {viewPortraitAsset ? "三视图据这版立绘生成,保证正/侧/背多角度一致。点下方按钮生成。" : "请先生成左侧「立绘」,有了立绘才能据它生成三视图。"}
)} @@ -3725,9 +3742,9 @@ export function PipelinePage(props: {
- +