98 lines
3.3 KiB
TypeScript
98 lines
3.3 KiB
TypeScript
"use client";
|
|
|
|
import { useParams, useRouter } from "next/navigation";
|
|
import { useCallback } from "react";
|
|
import { toast } from "sonner";
|
|
import { SceneFusionView } from "@/components/scene-fusion-view";
|
|
import { canvasService } from "@/services/canvas";
|
|
import { canvasSelectors, useCanvasStore } from "@/store/canvas";
|
|
|
|
export default function CanvasBatchProcessingPage() {
|
|
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 selectNodes = useCanvasStore((state) => state.selectNodes);
|
|
const getCanvasState = useCanvasStore((state) => state.getCanvasState);
|
|
|
|
const selectedImageNode =
|
|
selectedNodeIds.length === 1
|
|
? nodes.find(
|
|
(node) => node.id === selectedNodeIds[0] && node.type === "image"
|
|
)
|
|
: null;
|
|
|
|
const handleBack = useCallback(() => {
|
|
router.push(`/canvas/${id}`);
|
|
}, [id, router]);
|
|
|
|
const handleBatchAddToCanvas = useCallback(
|
|
async (imageUrls: string[]) => {
|
|
if (!imageUrls || imageUrls.length === 0) {
|
|
toast.error("没有可添加到画布的图片");
|
|
return;
|
|
}
|
|
|
|
const columns = Math.min(4, imageUrls.length);
|
|
const viewportX = viewport.x || 0;
|
|
const viewportY = viewport.y || 0;
|
|
const viewportZoom = viewport.zoom || 1;
|
|
const stageWidth = typeof window !== "undefined" ? window.innerWidth : 1440;
|
|
const stageHeight = typeof window !== "undefined" ? window.innerHeight : 900;
|
|
const startX = (stageWidth * 0.22 - viewportX) / viewportZoom;
|
|
const startY = (stageHeight * 0.18 - viewportY) / viewportZoom;
|
|
const createdNodeIds: string[] = [];
|
|
|
|
for (const [index, imageUrl] of imageUrls.entries()) {
|
|
const x = startX + (index % columns) * 320;
|
|
const y = startY + Math.floor(index / columns) * 320;
|
|
const nodeId = addNode({
|
|
type: "image",
|
|
position: { x, y },
|
|
size: { width: 300, height: 300 },
|
|
data: {
|
|
src: imageUrl,
|
|
status: "completed",
|
|
title: `批量结果-${index + 1}`,
|
|
prompt: "批量处理结果",
|
|
},
|
|
connections: [],
|
|
});
|
|
createdNodeIds.push(nodeId);
|
|
}
|
|
|
|
if (createdNodeIds.length > 0) {
|
|
selectNodes(createdNodeIds);
|
|
}
|
|
|
|
try {
|
|
await canvasService.saveCanvasState(id, getCanvasState());
|
|
} catch (error) {
|
|
console.error("[CanvasBatchProcessingPage] 保存批量处理结果失败:", error);
|
|
}
|
|
},
|
|
[addNode, getCanvasState, id, selectNodes, viewport.x, viewport.y, viewport.zoom]
|
|
);
|
|
|
|
return (
|
|
<div className="h-dvh w-full overflow-hidden bg-background">
|
|
<SceneFusionView
|
|
canvasId={id}
|
|
initialProductImage={
|
|
selectedImageNode ? String((selectedImageNode.data as any)?.src || "") : null
|
|
}
|
|
initialProductName={
|
|
selectedImageNode ? String((selectedImageNode.data as any)?.title || "") : ""
|
|
}
|
|
onBack={handleBack}
|
|
onBatchAddToCanvas={handleBatchAddToCanvas}
|
|
persistenceKey={id ? `canvas-scene-fusion:${id}` : null}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|