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(() => {
if (!effectiveAgentEnabled || typeof window === "undefined") return;
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}」`}生成一张图`;
const focusComposerWithPrompt = (prompt: string) => {
handleSelectGenerationMode("agent");
setInput(prompt);
@ -3640,19 +3636,54 @@ export function CanvasChatPanel({
selection.removeAllRanges();
selection.addRange(range);
}, 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("已选中槽位,可补充生成要求后发送");
};
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(
"canvas-agent-slot-fill-request",
handleAgentSlotFillRequest
);
window.addEventListener(
"canvas-agent-annotation-edit-request",
handleAgentAnnotationEditRequest
);
return () => {
window.removeEventListener(
"canvas-agent-slot-fill-request",
handleAgentSlotFillRequest
);
window.removeEventListener(
"canvas-agent-annotation-edit-request",
handleAgentAnnotationEditRequest
);
};
}, [effectiveAgentEnabled, handleSelectGenerationMode]);

View File

@ -1333,6 +1333,7 @@ export function ImageNode({
() => canvasAgentAnnotations.slice(-3),
[canvasAgentAnnotations]
);
const hasCanvasAgentAnnotations = canvasAgentAnnotations.length > 0;
const imageNodeMoreItem = getCanvasToolbarItem(canvasToolbarConfig, "imageNodeMore");
const imageAddToChatItem = getCanvasToolbarItem(canvasToolbarConfig, "imageAddToChat");
const imagePickObjectItem = getCanvasToolbarItem(canvasToolbarConfig, "imagePickObject");
@ -1516,6 +1517,7 @@ export function ImageNode({
imageRemoveWatermarkEnabled ||
imageEnhanceEnabled ||
imageNoteEnabled ||
hasCanvasAgentAnnotations ||
(isLayerSplitEnabled && imageLayerSplitEnabledByToolbar) ||
imageResizeEnabled ||
imageMultiAngleEnabled ||
@ -1535,6 +1537,7 @@ export function ImageNode({
selectedImageMoreActionKeys.size > 0;
const hasSelectedImageMoreMenu =
hasSelectedImageMorePrimaryActions ||
(imageNodeMoreEnabled && hasCanvasAgentAnnotations) ||
(imageNodeMoreEnabled && imageDeleteEnabled);
const hasSelectedImagePrimaryToolbarActions =
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(() => {
if (typeof window === "undefined") return;
@ -9215,29 +9242,35 @@ export function ImageNode({
/>
</DropdownMenuItem>
) : null}
{imageEnhanceEnabled ? (
<DropdownMenuItem onClick={() => handleAction("enhance")}>
<CanvasToolbarIcon
className="mr-2 h-4 w-4"
fallback={Sparkles}
item={imageEnhanceItem}
/>
{imageEnhanceItem.label}
<ImageActionCreditBadge label={enhanceCostShortLabel} />
</DropdownMenuItem>
) : null}
{imageNoteEnabled ? (
<DropdownMenuItem onClick={() => handleAction("note")}>
<CanvasToolbarIcon
className="mr-2 h-4 w-4"
fallback={StickyNote}
item={imageNoteItem}
/>
{imageNoteItem.label}
</DropdownMenuItem>
) : null}
{isLayerSplitEnabled && imageLayerSplitEnabledByToolbar ? (
<DropdownMenuItem onClick={() => handleAction("layer-split")}>
{imageEnhanceEnabled ? (
<DropdownMenuItem onClick={() => handleAction("enhance")}>
<CanvasToolbarIcon
className="mr-2 h-4 w-4"
fallback={Sparkles}
item={imageEnhanceItem}
/>
{imageEnhanceItem.label}
<ImageActionCreditBadge label={enhanceCostShortLabel} />
</DropdownMenuItem>
) : null}
{imageNoteEnabled ? (
<DropdownMenuItem onClick={() => handleAction("note")}>
<CanvasToolbarIcon
className="mr-2 h-4 w-4"
fallback={StickyNote}
item={imageNoteItem}
/>
{imageNoteItem.label}
</DropdownMenuItem>
) : null}
{hasCanvasAgentAnnotations ? (
<DropdownMenuItem onClick={requestCanvasAgentAnnotationEdit}>
<Wand2 className="mr-2 h-4 w-4" />
按批注修改
</DropdownMenuItem>
) : null}
{isLayerSplitEnabled && imageLayerSplitEnabledByToolbar ? (
<DropdownMenuItem onClick={() => handleAction("layer-split")}>
<CanvasToolbarIcon
className="mr-2 h-4 w-4"
fallback={Layers}
@ -10423,19 +10456,26 @@ export function ImageNode({
/>
</DropdownMenuItem>
) : null}
{isSelectedImageActionInMore("note") ? (
<DropdownMenuItem onClick={() => handleAction("note")}>
<CanvasToolbarIcon
className="mr-2 h-4 w-4"
fallback={StickyNote}
item={imageNoteItem}
/>
{imageNoteItem.label}
{isSelectedImageActionInMore("note") ? (
<DropdownMenuItem onClick={() => handleAction("note")}>
<CanvasToolbarIcon
className="mr-2 h-4 w-4"
fallback={StickyNote}
item={imageNoteItem}
/>
{imageNoteItem.label}
</DropdownMenuItem>
) : null}
{hasCanvasAgentAnnotations ? (
<DropdownMenuItem onClick={requestCanvasAgentAnnotationEdit}>
<Wand2 className="mr-2 h-4 w-4" />
按批注修改
</DropdownMenuItem>
) : null}
{hasSelectedImageMorePrimaryActions && imageDeleteEnabled ? (
<DropdownMenuSeparator />
) : null}
{(hasSelectedImageMorePrimaryActions || hasCanvasAgentAnnotations) &&
imageDeleteEnabled ? (
<DropdownMenuSeparator />
) : null}
{imageDeleteEnabled ? (
<DropdownMenuItem
className="text-red-600 focus:text-red-700"