feat(canvas): 图片编辑 - 合并打光预设与镜头参数控制

This commit is contained in:
ddCat
2026-09-09 22:55:19 +08:00
24 changed files with 1634 additions and 19 deletions

View File

@@ -26,7 +26,8 @@ import { flushCanvasStorePersistence } from "@/stores/canvas/use-canvas-store";
import { ensureCanvasNodeAsset } from "@/services/project-asset-sync";
import { useThemeStore } from "@/stores/use-theme-store";
import { useUserStore } from "@/stores/use-user-store";
import { App, Button, Modal } from "antd";
import { App, Button } from "antd";
import { AppModal } from "@/components/ui/product/app-modal";
import { getNodeSpec } from "@/constant/canvas";
import { CanvasConfigComposer } from "@/components/canvas/canvas-config-composer";
import { CanvasConfigNodePanel } from "@/components/canvas/canvas-config-node-panel";
@@ -48,6 +49,7 @@ import { CanvasVideoSegmentDialog } from "@/components/canvas/canvas-video-segme
import { CanvasTimelineDialog } from "@/components/canvas/canvas-timeline-dialog";
import { syncNodeSubtitlesToTimeline } from "@/lib/timeline/timeline-build";
import { CanvasNodeAnglePanel } from "@/components/canvas/canvas-node-angle-dialog";
import { CanvasNodeLightingPanel } from "@/components/canvas/canvas-node-lighting-dialog";
import { CanvasTextEditorModal } from "@/components/canvas/canvas-text-editor-modal";
import { CanvasNodeSearchModal } from "@/components/canvas/canvas-node-search-modal";
import { CanvasStylePickerModal } from "@/components/canvas/canvas-style-picker-modal";
@@ -783,6 +785,7 @@ function InfiniteCanvasPage() {
const {
angleNodeId,
lightingNodeId,
emotionNodeId,
annotationNodeId,
createImageReversePromptNodes,
@@ -796,6 +799,7 @@ function InfiniteCanvasPage() {
extractingVideoFramesNodeId,
frameDialogNodeId,
generateAngleNode,
generateLightingNode,
generateEmotionNode,
handleSegmentConfirm,
maskEditImageNode,
@@ -810,6 +814,7 @@ function InfiniteCanvasPage() {
setFrameDialogNodeId,
setSegmentDialogNodeId,
setAngleNodeId,
setLightingNodeId,
setEmotionNodeId,
setAnnotationNodeId,
setCropNodeId,
@@ -862,6 +867,7 @@ function InfiniteCanvasPage() {
setSplitNodeId(clearDeletedId);
setUpscaleNodeId(clearDeletedId);
setAngleNodeId(clearDeletedId);
setLightingNodeId(clearDeletedId);
setEmotionNodeId(clearDeletedId);
setSuperResolveNodeId(clearDeletedId);
setPreviewNodeId(clearDeletedId);
@@ -879,7 +885,7 @@ function InfiniteCanvasPage() {
}
cleanupCanvasFiles({ projectId, nodes: nextNodes, chatSessions });
},
[chatSessions, cleanupCanvasFiles, message, projectId, setAngleNodeId, setAnnotationNodeId, setArtCritiqueNodeId, setCropNodeId, setEmotionNodeId, setFrameDialogNodeId, setMaskEditNodeId, setSegmentDialogNodeId, setSplitNodeId, setUpscaleNodeId, setRunningNodeId],
[chatSessions, cleanupCanvasFiles, message, projectId, setAngleNodeId, setAnnotationNodeId, setArtCritiqueNodeId, setCropNodeId, setEmotionNodeId, setFrameDialogNodeId, setLightingNodeId, setMaskEditNodeId, setSegmentDialogNodeId, setSplitNodeId, setUpscaleNodeId, setRunningNodeId],
);
const {
@@ -1218,6 +1224,7 @@ function InfiniteCanvasPage() {
activeScriptNode,
activeStylePresetId,
angleNode,
lightingNode,
emotionNode,
annotationNode,
batchChildCountById,
@@ -1268,6 +1275,7 @@ function InfiniteCanvasPage() {
upscaleNodeId,
superResolveNodeId,
angleNodeId,
lightingNodeId,
emotionNodeId,
previewNodeId,
contextMenu,
@@ -1521,6 +1529,7 @@ function InfiniteCanvasPage() {
setMaskEditNodeId(null);
setAnnotationNodeId(null);
setAngleNodeId(null);
setLightingNodeId(null);
setEmotionNodeId(null);
setPreviewNodeId(null);
setRunningNodeId(null);
@@ -2436,13 +2445,13 @@ function InfiniteCanvasPage() {
</div>
{angleNode?.metadata?.content ? (
<Modal
<AppModal
flush
open
centered
title="多角度编辑器"
footer={null}
width={620}
destroyOnHidden
onCancel={() => setAngleNodeId(null)}
>
<CanvasNodeAnglePanel
@@ -2452,7 +2461,27 @@ function InfiniteCanvasPage() {
void generateAngleNode(angleNode, params);
}}
/>
</Modal>
</AppModal>
) : null}
{lightingNode?.metadata?.content ? (
<AppModal
flush
open
centered
title="打光效果"
footer={null}
width={900}
onCancel={() => setLightingNodeId(null)}
>
<CanvasNodeLightingPanel
dataUrl={lightingNode.metadata.content}
onClose={() => setLightingNodeId(null)}
onConfirm={(options, prompt) => {
void generateLightingNode(lightingNode, options, prompt);
}}
/>
</AppModal>
) : null}
{emotionNode?.metadata?.content && !isCanvasNodeMoving ? (
@@ -2556,6 +2585,10 @@ function InfiniteCanvasPage() {
setDialogNodeId(null);
setAngleNodeId((current) => (current === node.id ? null : node.id));
}}
onLighting={(node) => {
setDialogNodeId(null);
setLightingNodeId((current) => (current === node.id ? null : node.id));
}}
onViewImage={(node) => setPreviewNodeId(node.id)}
onExtractVideoFrames={openVideoFrameExtractor}
onExtractAudioFromVideo={(node) => void extractAudioFromVideo(node)}