feat: add canvas annotation edit prompt entry

This commit is contained in:
134 2026-06-22 21:52:33 +08:00
parent 9bc887eee1
commit e1685b517a
2 changed files with 110 additions and 39 deletions

View File

@ -3617,11 +3617,7 @@ export function CanvasChatPanel({
useEffect(() => { useEffect(() => {
if (!effectiveAgentEnabled || typeof window === "undefined") return; if (!effectiveAgentEnabled || typeof window === "undefined") return;
const handleAgentSlotFillRequest = (event: Event) => { const focusComposerWithPrompt = (prompt: string) => {
const detail = (event as CustomEvent<{ nodeId?: string; label?: string }>).detail;
const label = String(detail?.label || "这个槽位").trim();
const prompt = `在${label === "这个槽位" ? label : `「${label}」`}生成一张图`;
handleSelectGenerationMode("agent"); handleSelectGenerationMode("agent");
setInput(prompt); setInput(prompt);
@ -3640,19 +3636,54 @@ export function CanvasChatPanel({
selection.removeAllRanges(); selection.removeAllRanges();
selection.addRange(range); selection.addRange(range);
}, 0); }, 0);
};
const handleAgentSlotFillRequest = (event: Event) => {
const detail = (event as CustomEvent<{ nodeId?: string; label?: string }>).detail;
const label = String(detail?.label || "这个槽位").trim();
const prompt = `在${label === "这个槽位" ? label : `「${label}」`}生成一张图`;
focusComposerWithPrompt(prompt);
toast.message("已选中槽位,可补充生成要求后发送"); toast.message("已选中槽位,可补充生成要求后发送");
}; };
const handleAgentAnnotationEditRequest = (event: Event) => {
const detail = (
event as CustomEvent<{
nodeId?: string;
title?: string;
annotationCount?: number;
}>
).detail;
const title = String(detail?.title || "").trim();
const prompt = title
? `按「${title}」这张图上的批注修改`
: "按这张图上的批注修改";
focusComposerWithPrompt(prompt);
toast.message(
`已带入${Math.max(1, Number(detail?.annotationCount || 0))}条批注,可补充修改要求后发送`
);
};
window.addEventListener( window.addEventListener(
"canvas-agent-slot-fill-request", "canvas-agent-slot-fill-request",
handleAgentSlotFillRequest handleAgentSlotFillRequest
); );
window.addEventListener(
"canvas-agent-annotation-edit-request",
handleAgentAnnotationEditRequest
);
return () => { return () => {
window.removeEventListener( window.removeEventListener(
"canvas-agent-slot-fill-request", "canvas-agent-slot-fill-request",
handleAgentSlotFillRequest handleAgentSlotFillRequest
); );
window.removeEventListener(
"canvas-agent-annotation-edit-request",
handleAgentAnnotationEditRequest
);
}; };
}, [effectiveAgentEnabled, handleSelectGenerationMode]); }, [effectiveAgentEnabled, handleSelectGenerationMode]);

View File

@ -1333,6 +1333,7 @@ export function ImageNode({
() => canvasAgentAnnotations.slice(-3), () => canvasAgentAnnotations.slice(-3),
[canvasAgentAnnotations] [canvasAgentAnnotations]
); );
const hasCanvasAgentAnnotations = canvasAgentAnnotations.length > 0;
const imageNodeMoreItem = getCanvasToolbarItem(canvasToolbarConfig, "imageNodeMore"); const imageNodeMoreItem = getCanvasToolbarItem(canvasToolbarConfig, "imageNodeMore");
const imageAddToChatItem = getCanvasToolbarItem(canvasToolbarConfig, "imageAddToChat"); const imageAddToChatItem = getCanvasToolbarItem(canvasToolbarConfig, "imageAddToChat");
const imagePickObjectItem = getCanvasToolbarItem(canvasToolbarConfig, "imagePickObject"); const imagePickObjectItem = getCanvasToolbarItem(canvasToolbarConfig, "imagePickObject");
@ -1516,6 +1517,7 @@ export function ImageNode({
imageRemoveWatermarkEnabled || imageRemoveWatermarkEnabled ||
imageEnhanceEnabled || imageEnhanceEnabled ||
imageNoteEnabled || imageNoteEnabled ||
hasCanvasAgentAnnotations ||
(isLayerSplitEnabled && imageLayerSplitEnabledByToolbar) || (isLayerSplitEnabled && imageLayerSplitEnabledByToolbar) ||
imageResizeEnabled || imageResizeEnabled ||
imageMultiAngleEnabled || imageMultiAngleEnabled ||
@ -1535,6 +1537,7 @@ export function ImageNode({
selectedImageMoreActionKeys.size > 0; selectedImageMoreActionKeys.size > 0;
const hasSelectedImageMoreMenu = const hasSelectedImageMoreMenu =
hasSelectedImageMorePrimaryActions || hasSelectedImageMorePrimaryActions ||
(imageNodeMoreEnabled && hasCanvasAgentAnnotations) ||
(imageNodeMoreEnabled && imageDeleteEnabled); (imageNodeMoreEnabled && imageDeleteEnabled);
const hasSelectedImagePrimaryToolbarActions = const hasSelectedImagePrimaryToolbarActions =
selectedImageInlineActionKeys.size > 0; selectedImageInlineActionKeys.size > 0;
@ -6694,6 +6697,30 @@ export function ImageNode({
} }
}; };
const requestCanvasAgentAnnotationEdit = useCallback(() => {
if (!hasCanvasAgentAnnotations || typeof window === "undefined") {
toast.info("当前图片还没有可用于 Agent 的批注");
return;
}
selectNode(node.id, false);
window.dispatchEvent(
new CustomEvent("canvas-agent-annotation-edit-request", {
detail: {
nodeId: node.id,
title: displayTitle,
annotationCount: canvasAgentAnnotations.length,
},
})
);
}, [
canvasAgentAnnotations.length,
displayTitle,
hasCanvasAgentAnnotations,
node.id,
selectNode,
]);
useEffect(() => { useEffect(() => {
if (typeof window === "undefined") return; if (typeof window === "undefined") return;
@ -9215,29 +9242,35 @@ export function ImageNode({
/> />
</DropdownMenuItem> </DropdownMenuItem>
) : null} ) : null}
{imageEnhanceEnabled ? ( {imageEnhanceEnabled ? (
<DropdownMenuItem onClick={() => handleAction("enhance")}> <DropdownMenuItem onClick={() => handleAction("enhance")}>
<CanvasToolbarIcon <CanvasToolbarIcon
className="mr-2 h-4 w-4" className="mr-2 h-4 w-4"
fallback={Sparkles} fallback={Sparkles}
item={imageEnhanceItem} item={imageEnhanceItem}
/> />
{imageEnhanceItem.label} {imageEnhanceItem.label}
<ImageActionCreditBadge label={enhanceCostShortLabel} /> <ImageActionCreditBadge label={enhanceCostShortLabel} />
</DropdownMenuItem> </DropdownMenuItem>
) : null} ) : null}
{imageNoteEnabled ? ( {imageNoteEnabled ? (
<DropdownMenuItem onClick={() => handleAction("note")}> <DropdownMenuItem onClick={() => handleAction("note")}>
<CanvasToolbarIcon <CanvasToolbarIcon
className="mr-2 h-4 w-4" className="mr-2 h-4 w-4"
fallback={StickyNote} fallback={StickyNote}
item={imageNoteItem} item={imageNoteItem}
/> />
{imageNoteItem.label} {imageNoteItem.label}
</DropdownMenuItem> </DropdownMenuItem>
) : null} ) : null}
{isLayerSplitEnabled && imageLayerSplitEnabledByToolbar ? ( {hasCanvasAgentAnnotations ? (
<DropdownMenuItem onClick={() => handleAction("layer-split")}> <DropdownMenuItem onClick={requestCanvasAgentAnnotationEdit}>
<Wand2 className="mr-2 h-4 w-4" />
按批注修改
</DropdownMenuItem>
) : null}
{isLayerSplitEnabled && imageLayerSplitEnabledByToolbar ? (
<DropdownMenuItem onClick={() => handleAction("layer-split")}>
<CanvasToolbarIcon <CanvasToolbarIcon
className="mr-2 h-4 w-4" className="mr-2 h-4 w-4"
fallback={Layers} fallback={Layers}
@ -10423,19 +10456,26 @@ export function ImageNode({
/> />
</DropdownMenuItem> </DropdownMenuItem>
) : null} ) : null}
{isSelectedImageActionInMore("note") ? ( {isSelectedImageActionInMore("note") ? (
<DropdownMenuItem onClick={() => handleAction("note")}> <DropdownMenuItem onClick={() => handleAction("note")}>
<CanvasToolbarIcon <CanvasToolbarIcon
className="mr-2 h-4 w-4" className="mr-2 h-4 w-4"
fallback={StickyNote} fallback={StickyNote}
item={imageNoteItem} item={imageNoteItem}
/> />
{imageNoteItem.label} {imageNoteItem.label}
</DropdownMenuItem>
) : null}
{hasCanvasAgentAnnotations ? (
<DropdownMenuItem onClick={requestCanvasAgentAnnotationEdit}>
<Wand2 className="mr-2 h-4 w-4" />
按批注修改
</DropdownMenuItem> </DropdownMenuItem>
) : null} ) : null}
{hasSelectedImageMorePrimaryActions && imageDeleteEnabled ? ( {(hasSelectedImageMorePrimaryActions || hasCanvasAgentAnnotations) &&
<DropdownMenuSeparator /> imageDeleteEnabled ? (
) : null} <DropdownMenuSeparator />
) : null}
{imageDeleteEnabled ? ( {imageDeleteEnabled ? (
<DropdownMenuItem <DropdownMenuItem
className="text-red-600 focus:text-red-700" className="text-red-600 focus:text-red-700"