diff --git a/app/(chat)/api/chat/route.ts b/app/(chat)/api/chat/route.ts index d8ca94ef2..6865d963c 100644 --- a/app/(chat)/api/chat/route.ts +++ b/app/(chat)/api/chat/route.ts @@ -7688,6 +7688,8 @@ export async function POST(request: Request) { ? presetModeConfig.sku.includeModelSlot : false; const replacementReferences = normalizeAgentModeReferences(agentModePayload); + const detailReplacementStrategy = + normalizeAgentModeDetailReplacementStrategy(agentModePayload); const isMatchingReplacementPayload = (isDetailReplacementPreset && agentModePayload?.modeType === "detail_replacement") || (isSkuReplacementPreset && agentModePayload?.modeType === "sku_replacement"); diff --git a/components/canvas/nodes/ImageNode.tsx b/components/canvas/nodes/ImageNode.tsx index d8a79e892..b637c96b2 100644 --- a/components/canvas/nodes/ImageNode.tsx +++ b/components/canvas/nodes/ImageNode.tsx @@ -1981,6 +1981,9 @@ export function ImageNode({ const cropOverlayRef = useRef(null); const toolbarRef = useRef(null); const boxCutoutToolbarRef = useRef(null); + const localEditPromptInputRefs = useRef< + Record + >({}); const updateNode = useCanvasStore((state) => state.updateNode); const deleteNode = useCanvasStore((state) => state.deleteNode); @@ -2410,6 +2413,20 @@ export function ImageNode({ setEditingLocalEditRegionId(null); }, []); + const focusLocalEditPromptInput = useCallback((regionId: string) => { + if (typeof window === "undefined") return; + window.requestAnimationFrame(() => { + const input = localEditPromptInputRefs.current[regionId]; + if (!input) return; + input.focus({ preventScroll: true }); + }); + }, []); + + useEffect(() => { + if (!localEditMode || !editingLocalEditRegionId) return; + focusLocalEditPromptInput(editingLocalEditRegionId); + }, [editingLocalEditRegionId, focusLocalEditPromptInput, localEditMode]); + const commitLocalEditRegions = useCallback( (regions: LocalEditRegion[]) => { const nextRegions = reindexLocalEditRegions( @@ -7528,8 +7545,11 @@ export function ImageNode({ className="absolute z-[175] flex items-center gap-1.5" data-canvas-no-drag="true" onClick={(event) => event.stopPropagation()} + onClickCapture={(event) => event.stopPropagation()} onMouseDown={(event) => event.stopPropagation()} + onMouseDownCapture={(event) => event.stopPropagation()} onPointerDown={(event) => event.stopPropagation()} + onPointerDownCapture={(event) => event.stopPropagation()} style={{ left, top: Math.max(4, promptTop), @@ -7539,17 +7559,29 @@ export function ImageNode({ {isEditing ? ( { - const nextPrompt = event.currentTarget.value; - persistLocalEditRegionPrompt(region.id, nextPrompt); - if (nextPrompt.trim()) { - setEditingLocalEditRegionId(null); + const relatedTarget = + event.relatedTarget instanceof HTMLElement + ? event.relatedTarget + : null; + const nextPrompt = event.currentTarget.value.trim(); + if ( + !nextPrompt && + editingLocalEditRegionId === region.id && + !relatedTarget?.closest("[data-local-edit-control='true']") + ) { + focusLocalEditPromptInput(region.id); } }} onChange={(event) => updateLocalEditRegionPrompt(region.id, event.target.value) } + onClick={(event) => { + event.stopPropagation(); + focusLocalEditPromptInput(region.id); + }} onFocus={() => setEditingLocalEditRegionId(region.id)} onKeyDown={(event) => { event.stopPropagation(); @@ -7571,7 +7603,17 @@ export function ImageNode({ } }} onKeyUp={(event) => event.stopPropagation()} + onMouseDown={(event) => event.stopPropagation()} + onMouseDownCapture={(event) => event.stopPropagation()} + onPointerDown={(event) => event.stopPropagation()} + onPointerDownCapture={(event) => { + event.stopPropagation(); + focusLocalEditPromptInput(region.id); + }} placeholder={`区域 ${region.index} 提示词`} + ref={(input) => { + localEditPromptInputRefs.current[region.id] = input; + }} value={region.prompt} /> ) : ( @@ -7586,6 +7628,7 @@ export function ImageNode({ )}