fix: move generation confirm into composer

This commit is contained in:
2026-05-20 22:42:08 +08:00
parent 39b9d211aa
commit ab31a98383
3 changed files with 43 additions and 81 deletions

View File

@@ -3404,7 +3404,6 @@ function SourceSubjectPipeline({
const [agentSelectedTraits, setAgentSelectedTraits] = useState<string[]>(() => job.subject_agent?.selected_traits ?? [])
const [agentInput, setAgentInput] = useState("")
const [subjectAgentBusy, setSubjectAgentBusy] = useState<"analyze" | "message" | null>(null)
const [promptConfirmOpen, setPromptConfirmOpen] = useState(false)
const [promptMemoryByMode, setPromptMemoryByMode] = useState<Record<SubjectReconstructionMode, string[]>>(() => loadSubjectPromptMemory(job.id))
const [cartoonStyle] = useState<CartoonReconstructionStyle>("3d_animation")
const [subjectBusyFor, setSubjectBusyFor] = useState<{ jobId: string; jobLabel: string; mode: SubjectReconstructionMode; viewCount: number; sourceCount: number; profileLabel: string; modelLabel: string } | null>(null)
@@ -3508,7 +3507,6 @@ function SourceSubjectPipeline({
setAgentSelectedTraits(job.subject_agent?.selected_traits ?? [])
setAgentInput("")
setSubjectAgentBusy(null)
setPromptConfirmOpen(false)
setPromptMemoryByMode(loadSubjectPromptMemory(job.id))
setLastSubjectProfile(null)
setSubjectBusyFor(null)
@@ -3911,7 +3909,7 @@ function SourceSubjectPipeline({
setAgentSelectedTraits(nextAgent.selected_traits ?? [])
}
setAgentInput("")
setPromptConfirmOpen(true)
toast.success("出图提示词已生成,可以直接确认生成。")
} catch (e) {
toast.error("生图要求更新失败:" + (e instanceof Error ? e.message : String(e)))
} finally {
@@ -3935,12 +3933,17 @@ function SourceSubjectPipeline({
const effectiveAgentViews = subjectViewsForQuantity(effectiveAgentQuantity)
const effectivePrompt = (agentPrompt || subjectAgent?.generation_prompt_en || "").trim()
const effectiveRequirement = (subjectAgent?.requirements_zh || agentRequirement).trim()
const agentInputText = agentInput.trim()
const agentInputConfirmsGeneration = /^(确认)?(生成|出图|开始生成|确认出图)(\s*\d+\s*张?)?$/.test(agentInputText)
const canGenerateAgentPack = effectiveAgentMode === "custom"
? Boolean(effectiveRequirement || agentReferenceFrames.length)
: agentReferenceFrames.length > 0
const agentModeRunning = runningActorModes.has(effectiveAgentMode)
const showInlineGenerateAction = Boolean(effectivePrompt) && (!agentInputText || agentInputConfirmsGeneration) && !agentSelectedTraitsDirty
const sendDisabled = !!subjectAgentBusy || (!agentInputText && !agentRequirement.trim() && !selectedAgentTraits.length && !agentSelectedTraitsDirty)
const generateDisabled = !canGenerateAgentPack || subjectBusy || agentModeRunning
const confirmSubjectGeneration = () => {
setPromptConfirmOpen(false)
setAgentInput("")
void generateSubjectPack(effectiveAgentMode, agentReferenceFrameIndices, effectiveAgentViews)
}
@@ -4206,15 +4209,10 @@ function SourceSubjectPipeline({
</span>
{effectivePrompt ? (
<button
type="button"
onClick={() => setPromptConfirmOpen(true)}
disabled={!canGenerateAgentPack || subjectBusy || agentModeRunning}
className="inline-flex h-6 items-center gap-1 rounded-md border border-[#d6b36a]/28 bg-[#d6b36a]/[0.075] px-2 text-[9px] font-semibold text-[#f4dc88] transition hover:border-[#d6b36a]/48 hover:bg-[#d6b36a]/12 disabled:cursor-not-allowed disabled:opacity-40"
>
<span className="inline-flex h-6 items-center gap-1 rounded-md border border-[#d6b36a]/24 bg-[#d6b36a]/[0.07] px-2 text-[9px] font-semibold text-[#f4dc88]">
<Check className="h-3 w-3" />
· {effectiveAgentViews.length}
</button>
· {effectiveAgentViews.length}
</span>
) : (
<span className="text-[9px] text-white/34">
{reconstructionModeConfig(effectiveAgentMode).label} · {effectiveAgentQuantity}
@@ -4226,7 +4224,7 @@ function SourceSubjectPipeline({
value={agentInput}
onChange={(event) => setAgentInput(event.target.value)}
placeholder="直接写要怎么生成,或补充要改什么。"
className="h-28 w-full resize-none rounded border border-transparent bg-transparent px-2 py-2 text-[11px] leading-relaxed text-white outline-none transition placeholder:text-white/24 focus:border-cyan-200/45"
className="h-40 w-full resize-none rounded border border-transparent bg-transparent px-2 py-2 text-[11px] leading-relaxed text-white outline-none transition placeholder:text-white/24 focus:border-cyan-200/45"
/>
<div className="mt-2 flex items-center gap-2">
<div className="flex h-10 shrink-0 items-center overflow-hidden rounded-md border border-white/10 bg-black/35">
@@ -4269,12 +4267,18 @@ function SourceSubjectPipeline({
</div>
<button
type="button"
onClick={() => void sendSubjectAgentRequirement()}
disabled={!!subjectAgentBusy || (!agentInput.trim() && !agentRequirement.trim() && !selectedAgentTraits.length && !agentSelectedTraitsDirty)}
onClick={showInlineGenerateAction ? confirmSubjectGeneration : () => void sendSubjectAgentRequirement()}
disabled={showInlineGenerateAction ? generateDisabled : sendDisabled}
className="skg-primary-action inline-flex h-10 flex-1 items-center justify-center gap-2 px-3 text-[11.5px] font-semibold transition disabled:cursor-not-allowed disabled:opacity-40"
>
{subjectAgentBusy === "message" ? <Loader2 className="h-4 w-4 animate-spin" /> : <Send className="h-4 w-4" />}
{subjectAgentBusy === "message" ? (
<Loader2 className="h-4 w-4 animate-spin" />
) : showInlineGenerateAction ? (
<Sparkles className="h-4 w-4" />
) : (
<Send className="h-4 w-4" />
)}
{showInlineGenerateAction ? `确认生成 ${effectiveAgentViews.length}` : "发送消息"}
</button>
</div>
</div>
@@ -4395,60 +4399,6 @@ function SourceSubjectPipeline({
</div>
</div>
</div>
{promptConfirmOpen && effectivePrompt && typeof document !== "undefined" ? createPortal(
<div className="fixed inset-0 z-[10020] flex items-center justify-center bg-black/72 p-4 backdrop-blur-sm">
<div className="w-full max-w-2xl rounded-xl border border-white/14 bg-[#11140f] p-4 shadow-[0_28px_90px_rgba(0,0,0,0.72)]">
<div className="flex items-start justify-between gap-3">
<div>
<div className="text-sm font-semibold text-white"></div>
<div className="mt-1 text-[11px] text-white/46">
{subjectModelLabel(subjectModelBundle)} · {reconstructionModeConfig(effectiveAgentMode).label} · {effectiveAgentViews.length}
</div>
</div>
<button
type="button"
onClick={() => setPromptConfirmOpen(false)}
className="rounded-md border border-white/10 bg-black/30 px-2 py-1 text-[11px] text-white/56 transition hover:border-white/24 hover:text-white"
>
</button>
</div>
{effectiveRequirement ? (
<div className="mt-3 rounded-md border border-white/10 bg-black/24 px-3 py-2">
<div className="text-[10px] font-semibold text-white/54"></div>
<p className="mt-1 text-[11px] leading-relaxed text-white/72">{effectiveRequirement}</p>
</div>
) : null}
<div className="mt-3 rounded-md border border-[#d6b36a]/24 bg-[#d6b36a]/[0.07] px-3 py-2">
<div className="mb-1 text-[10px] font-semibold text-[#f4dc88]"></div>
<textarea
readOnly
value={effectivePrompt}
className="h-44 w-full resize-none rounded-md border border-white/10 bg-black/30 px-2 py-2 font-mono text-[11px] leading-relaxed text-white/76 outline-none"
/>
</div>
<div className="mt-4 flex items-center justify-end gap-2">
<button
type="button"
onClick={() => setPromptConfirmOpen(false)}
className="skg-secondary-action inline-flex h-9 items-center justify-center px-4 text-[12px] font-semibold"
>
</button>
<button
type="button"
onClick={confirmSubjectGeneration}
disabled={!canGenerateAgentPack || subjectBusy || agentModeRunning}
className="skg-primary-action inline-flex h-9 items-center justify-center gap-1.5 px-4 text-[12px] font-semibold transition disabled:cursor-not-allowed disabled:opacity-40"
>
<Sparkles className="h-4 w-4" />
{effectiveAgentViews.length}
</button>
</div>
</div>
</div>,
document.body,
) : null}
</>
)
}