feat(canvas): 批量创作表 - 支持全局提示词、参考图编排与连线同步
This commit is contained in:
1 parent
a8770c89b0
commit
c994566ffe
13 files changed
+714
-116
No files matched your search
@@ -68,6 +68,7 @@ import { CanvasZoomControls } from "@/components/canvas/canvas-zoom-controls";
|
||||
import { CanvasShareModal } from "@/components/canvas/canvas-share-modal";
|
||||
import { CanvasScriptEditor, CanvasScriptNodeContent } from "@/components/canvas/canvas-script-node";
|
||||
import { CanvasBatchTableNodeContent } from "@/components/canvas/canvas-batch-table-node";
|
||||
import { promoteLegacyBatchTableSize } from "@/lib/canvas/canvas-batch-table";
|
||||
import { STORYBOARD_HEADER_HEIGHT, STORYBOARD_ROW_HEIGHT, storyboardMinNodeHeight, storyboardTableHeight } from "@/lib/canvas/canvas-storyboard-layout";
|
||||
import { CanvasDirectorNodePanel } from "@/components/canvas/director/canvas-director-node-panel";
|
||||
import { CanvasVersionCompareModal } from "@/components/canvas/canvas-version-compare-modal";
|
||||
@@ -742,6 +743,7 @@ function InfiniteCanvasPage() {
|
||||
pasteAssistantImage,
|
||||
pasteSystemClipboard,
|
||||
replaceNodeMedia,
|
||||
createFileNode,
|
||||
startUploadStatus,
|
||||
uploadModalOpen,
|
||||
uploadTimelineMedia,
|
||||
@@ -1886,7 +1888,7 @@ function InfiniteCanvasPage() {
|
||||
handleGenerateNode,
|
||||
});
|
||||
|
||||
const { addReferenceColumn: addBatchReferenceColumn, addRow: addBatchRow, fillRowsFromConnections, generateRows: generateBatchRows, patchTable: patchBatchTable, removeRow: removeBatchRow, updateRow: updateBatchRow } = useCanvasBatchTable({
|
||||
const { addReferenceColumn: addBatchReferenceColumn, addRow: addBatchRow, fillRowsFromConnections, generateRows: generateBatchRows, moveReferenceCell: moveBatchReferenceCell, patchTable: patchBatchTable, removeReferenceColumn: removeBatchReferenceColumn, removeRow: removeBatchRow, reorderReferenceColumns: reorderBatchReferenceColumns, syncRowsFromConnections, updateRow: updateBatchRow } = useCanvasBatchTable({
|
||||
nodesRef,
|
||||
connectionsRef,
|
||||
setNodes,
|
||||
@@ -1895,6 +1897,22 @@ function InfiniteCanvasPage() {
|
||||
enqueueGenerationBatch,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!projectLoaded) return;
|
||||
setNodes((current) => {
|
||||
let changed = false;
|
||||
const next = current.map((node) => {
|
||||
const promoted = promoteLegacyBatchTableSize(node);
|
||||
if (promoted !== node) changed = true;
|
||||
return promoted;
|
||||
});
|
||||
return changed ? next : current;
|
||||
});
|
||||
nodesRef.current.filter((node) => node.type === CanvasNodeType.BatchTable).forEach((node) => {
|
||||
syncRowsFromConnections(node.id, true);
|
||||
});
|
||||
}, [connections, projectLoaded, setNodes, syncRowsFromConnections]);
|
||||
|
||||
const { addScriptRow, createAndGenerateScriptVideos, createScriptActionBoards, createScriptImageNodes, createScriptVideoNodes, generateScriptImages, generateScriptRows, generateScriptVideos, removeScriptRow, replaceScriptRows, updateScriptRow } =
|
||||
useCanvasStoryboard({
|
||||
projectId,
|
||||
@@ -2105,6 +2123,26 @@ function InfiniteCanvasPage() {
|
||||
onGenerate={(rowIds) => void generateBatchRows(contentNode.id, rowIds)}
|
||||
onRetryItem={(batchId, itemId) => retryFailedBatchItems(contentNode.id, batchId, itemId)}
|
||||
onAddReferenceColumn={() => addBatchReferenceColumn(contentNode.id)}
|
||||
onRemoveReferenceColumn={() => removeBatchReferenceColumn(contentNode.id)}
|
||||
onFocusOutput={(nodeId) => focusCanvasImageNode(nodeId)}
|
||||
onReorderReferenceColumns={(fromColumnId, toColumnId) => reorderBatchReferenceColumns(contentNode.id, fromColumnId, toColumnId)}
|
||||
onMoveReferenceCell={(sourceRowId, sourceColumnIndex, targetRowId, targetColumnIndex) => moveBatchReferenceCell(contentNode.id, sourceRowId, sourceColumnIndex, targetRowId, targetColumnIndex)}
|
||||
onUploadReference={(rowId, columnIndex, file) => {
|
||||
const row = contentNode.metadata?.batchTable?.rows.find((item) => item.id === rowId);
|
||||
const existingId = row?.inputNodeIds[columnIndex];
|
||||
if (existingId) {
|
||||
void replaceNodeMedia(existingId, file);
|
||||
return;
|
||||
}
|
||||
void createFileNode(file, { x: contentNode.position.x - 180, y: contentNode.position.y + columnIndex * 90 }).then((insertedId) => {
|
||||
if (!insertedId) return;
|
||||
const currentRow = nodesRef.current.find((item) => item.id === contentNode.id)?.metadata?.batchTable?.rows.find((item) => item.id === rowId);
|
||||
const ids = [...(currentRow?.inputNodeIds || [])];
|
||||
while (ids.length <= columnIndex) ids.push("");
|
||||
ids[columnIndex] = insertedId;
|
||||
updateBatchRow(contentNode.id, rowId, { inputNodeIds: ids });
|
||||
});
|
||||
}}
|
||||
onConnectStart={(event, handleId) => handleConnectStart(event, contentNode.id, "target", handleId)}
|
||||
onConnectDrop={(event, handleId) => handleConnectDrop(event, contentNode.id, handleId)}
|
||||
/>
|
||||
@@ -2189,6 +2227,7 @@ function InfiniteCanvasPage() {
|
||||
createScriptVideoNodes,
|
||||
currentProject?.directorScenes,
|
||||
fillRowsFromConnections,
|
||||
focusCanvasImageNode,
|
||||
generateBatchRows,
|
||||
generateScriptImages,
|
||||
generateScriptRows,
|
||||
@@ -2203,6 +2242,7 @@ function InfiniteCanvasPage() {
|
||||
openDirectorWorkbench,
|
||||
openStoryInput,
|
||||
patchBatchTable,
|
||||
removeBatchReferenceColumn,
|
||||
removeBatchRow,
|
||||
removeScriptRow,
|
||||
retryFailedBatchItems,
|
||||
|
||||
Reference in new issue
Block a user