fix: complete local edit and detail replacement wiring
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-05-19 15:24:13 +08:00
parent 5239250465
commit 1dd1251880
2 changed files with 51 additions and 5 deletions

View File

@ -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");

View File

@ -1981,6 +1981,9 @@ export function ImageNode({
const cropOverlayRef = useRef<HTMLDivElement>(null);
const toolbarRef = useRef<HTMLDivElement>(null);
const boxCutoutToolbarRef = useRef<HTMLDivElement>(null);
const localEditPromptInputRefs = useRef<
Record<string, HTMLInputElement | null>
>({});
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 ? (
<input
autoFocus={editingLocalEditRegionId === region.id}
className="h-9 min-w-0 flex-1 rounded-full border border-slate-300 bg-white/95 px-3 text-[12px] font-medium text-slate-950 shadow-[0_10px_24px_rgba(15,23,42,0.14)] outline-none ring-2 ring-transparent transition placeholder:text-slate-400 focus:border-slate-950 focus:ring-slate-950/15 dark:border-white/20 dark:bg-slate-950/88 dark:text-white dark:placeholder:text-white/42 dark:focus:border-white/40 dark:focus:ring-white/18"
className="nodrag nopan nowheel h-9 min-w-0 flex-1 rounded-full border border-slate-300 bg-white/95 px-3 text-[12px] font-medium text-slate-950 caret-slate-950 shadow-[0_10px_24px_rgba(15,23,42,0.14)] outline-none ring-2 ring-transparent transition placeholder:text-slate-400 focus:border-slate-950 focus:ring-slate-950/15 dark:border-white/20 dark:bg-slate-950/88 dark:text-white dark:caret-white dark:placeholder:text-white/42 dark:focus:border-white/40 dark:focus:ring-white/18"
data-canvas-no-drag="true"
onBlur={(event) => {
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({
)}
<button
className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full border border-slate-200 bg-white/95 text-slate-500 shadow-[0_10px_24px_rgba(15,23,42,0.12)] hover:bg-red-500 hover:text-white dark:border-white/18 dark:bg-slate-950/82 dark:text-white/72 dark:shadow-[0_10px_24px_rgba(0,0,0,0.24)]"
data-local-edit-control="true"
onClick={() => deleteLocalEditRegion(region.id)}
title="删除区域"
type="button"
@ -8167,6 +8210,7 @@ export function ImageNode({
createPortal(
<div
className="fixed z-[9999] flex items-center gap-2 rounded-[24px] border border-slate-200 bg-white px-2 py-2 text-gray-800 shadow-[0_14px_38px_rgba(15,23,42,0.16)] dark:border-slate-700 dark:bg-slate-900 dark:text-gray-100"
data-local-edit-control="true"
onClick={(event) => event.stopPropagation()}
onMouseDown={(event) => event.stopPropagation()}
onPointerDown={(event) => event.stopPropagation()}