83 lines
2.6 KiB
TypeScript
83 lines
2.6 KiB
TypeScript
"use client";
|
|
|
|
import { useCallback } from "react";
|
|
import { useParams, useRouter } from "next/navigation";
|
|
import { toast } from "sonner";
|
|
import { RealtimeCanvasDialog } from "@/components/canvas/RealtimeCanvasDialog";
|
|
import { canvasService } from "@/services/canvas";
|
|
import { useCanvasStore, canvasSelectors } from "@/store/canvas";
|
|
|
|
export default function CanvasRealtimePage() {
|
|
const router = useRouter();
|
|
const routeParams = useParams();
|
|
const id = String(routeParams?.id || "");
|
|
|
|
const viewport = useCanvasStore(canvasSelectors.viewport);
|
|
const selectedNodeIds = useCanvasStore(canvasSelectors.selectedNodeIds);
|
|
const nodes = useCanvasStore(canvasSelectors.nodes);
|
|
const addNode = useCanvasStore((state) => state.addNode);
|
|
const getCanvasState = useCanvasStore((state) => state.getCanvasState);
|
|
|
|
const selectedImageNode =
|
|
selectedNodeIds.length === 1
|
|
? nodes.find((node) => node.id === selectedNodeIds[0] && node.type === "image")
|
|
: null;
|
|
|
|
const handleOpenChange = useCallback(
|
|
(nextOpen: boolean) => {
|
|
if (!nextOpen) {
|
|
router.push(`/canvas/${id}`);
|
|
}
|
|
},
|
|
[id, router]
|
|
);
|
|
|
|
const handleApplyResult = useCallback(
|
|
async ({ imageUrl, prompt }: { imageUrl: string; prompt: string }) => {
|
|
const viewportX = viewport.x || 0;
|
|
const viewportY = viewport.y || 0;
|
|
const viewportZoom = viewport.zoom || 1;
|
|
const stageWidth = typeof window !== "undefined" ? window.innerWidth : 1280;
|
|
const stageHeight = typeof window !== "undefined" ? window.innerHeight : 720;
|
|
const targetWidth = 360;
|
|
const targetHeight = 360;
|
|
|
|
const x = (stageWidth * 0.45 - viewportX) / viewportZoom - targetWidth / 2;
|
|
const y = (stageHeight * 0.45 - viewportY) / viewportZoom - targetHeight / 2;
|
|
|
|
addNode({
|
|
type: "image",
|
|
position: { x, y },
|
|
size: { width: targetWidth, height: targetHeight },
|
|
data: {
|
|
src: imageUrl,
|
|
status: "completed",
|
|
title: "实时画布结果",
|
|
prompt,
|
|
model: "bfl/flux-2",
|
|
},
|
|
connections: [],
|
|
});
|
|
|
|
try {
|
|
await canvasService.saveCanvasState(id, getCanvasState());
|
|
} catch (error) {
|
|
console.error("[RealtimeCanvasPage] 保存结果失败:", error);
|
|
}
|
|
|
|
toast.success("实时画布结果已添加");
|
|
},
|
|
[addNode, getCanvasState, id, viewport.x, viewport.y, viewport.zoom]
|
|
);
|
|
|
|
return (
|
|
<RealtimeCanvasDialog
|
|
standalone
|
|
open
|
|
onOpenChange={handleOpenChange}
|
|
initialImageUrl={selectedImageNode ? ((selectedImageNode.data as any)?.src as string) : null}
|
|
onApplyResult={handleApplyResult}
|
|
/>
|
|
);
|
|
}
|