Browse Source

外部自动同步数据

feature/627
tianYun 2 weeks ago
parent
commit
c8d08c4025
  1. 1
      src/components/composer/GenerationComposer.tsx
  2. 73
      src/store/workflowStore.ts

1
src/components/composer/GenerationComposer.tsx

@ -949,6 +949,7 @@ function ComposerEditor({
useEffect(() => {
if (isHidden) {
persistCurrentComposerConfig();
stopReferenceAudioPreview();
onHiddenPersisted?.();
return;

73
src/store/workflowStore.ts

@ -641,14 +641,22 @@ function buildReferenceSubjectNodePatch(
node: WorkflowNode,
beforeMaterials: ComposerReferenceMaterial[],
afterMaterials: ComposerReferenceMaterial[],
options: { syncPrompt?: boolean } = {}
options: {
syncPrompt?: boolean;
promptBeforeMaterials?: ComposerReferenceMaterial[];
promptAfterMaterials?: ComposerReferenceMaterial[];
} = {}
): Partial<WorkflowNodeData> | null {
const data = node.data as { parameters?: Record<string, unknown>; inputPrompt?: unknown; prompt?: unknown };
const previousSubjects = readNodeReferenceSubjects(node);
const nextSubjects = buildReferenceSubjectListParameter(afterMaterials);
const previousPrompt = readNodeInputPrompt(node);
const nextPrompt = options.syncPrompt
? syncPromptReferenceMaterials(previousPrompt, beforeMaterials, afterMaterials)
? syncPromptReferenceMaterials(
previousPrompt,
options.promptBeforeMaterials ?? beforeMaterials,
options.promptAfterMaterials ?? afterMaterials
)
: previousPrompt;
const nextSubType = isVideoGenerationNode(node)
? normalizeVideoGenerationSubType(
@ -803,11 +811,48 @@ function applyReferenceSubjectListPatch(
const orderedAfterMaterials = options.preserveMaterialOrder
? afterMaterials
: orderReferenceMaterials(afterMaterials, previousOrder);
const patch = buildReferenceSubjectNodePatch(node, orderedBeforeMaterials, orderedAfterMaterials, options);
const patch = buildReferenceSubjectNodePatch(node, orderedBeforeMaterials, orderedAfterMaterials, {
...options,
promptBeforeMaterials: beforeMaterials,
promptAfterMaterials: afterMaterials,
});
if (!patch) return;
get().updateNodeData(nodeId, patch);
}
function collectReferenceMaterialsBeforeRemovingSourceNodes(
removedNodeIds: Set<string>,
get: () => WorkflowStore
): { beforeMaterialsByTarget: Map<string, ComposerReferenceMaterial[]>; removedEdges: WorkflowEdge[] } {
const removedEdges = get().edges.filter(
(edge) => removedNodeIds.has(edge.source) || removedNodeIds.has(edge.target)
);
const beforeMaterialsByTarget = new Map<string, ComposerReferenceMaterial[]>();
removedEdges.forEach((edge) => {
if (!removedNodeIds.has(edge.source) || removedNodeIds.has(edge.target)) return;
if (beforeMaterialsByTarget.has(edge.target)) return;
beforeMaterialsByTarget.set(edge.target, buildNodeReferenceMaterials(edge.target, get));
});
return { beforeMaterialsByTarget, removedEdges };
}
function applyReferenceMaterialChangesAfterRemovingSourceNodes(
beforeMaterialsByTarget: Map<string, ComposerReferenceMaterial[]>,
get: () => WorkflowStore
): void {
beforeMaterialsByTarget.forEach((beforeMaterials, targetNodeId) => {
if (!get().nodes.some((node) => node.id === targetNodeId)) return;
get().applyNodeReferenceMaterialsChange(
targetNodeId,
beforeMaterials,
buildNodeReferenceMaterials(targetNodeId, get),
{ syncPrompt: true }
);
});
}
/** Capture current undoable state as a deep-cloned snapshot */
function captureUndoSnapshot(state: WorkflowStore): UndoSnapshot {
const cloned = clonePreservingStrings({
@ -1490,6 +1535,10 @@ const workflowStoreImpl: StateCreator<WorkflowStore> = (set, get) => ({
removeNode: (nodeId: string) => {
pushUndoCheckpoint(get, set);
const { beforeMaterialsByTarget, removedEdges } = collectReferenceMaterialsBeforeRemovingSourceNodes(
new Set([nodeId]),
get
);
set((state) => ({
nodes: state.nodes.filter((node) => node.id !== nodeId),
edges: state.edges.filter(
@ -1497,6 +1546,15 @@ const workflowStoreImpl: StateCreator<WorkflowStore> = (set, get) => ({
),
hasUnsavedChanges: true,
}));
if (removedEdges.length > 0) {
deleteCheckpointActive = true;
try {
clearStaleInputImages(removedEdges, get);
applyReferenceMaterialChangesAfterRemovingSourceNodes(beforeMaterialsByTarget, get);
} finally {
deleteCheckpointActive = false;
}
}
get().incrementManualChangeCount();
},
@ -1562,6 +1620,13 @@ const workflowStoreImpl: StateCreator<WorkflowStore> = (set, get) => ({
setTimeout(() => { deleteCheckpointActive = false; }, 0);
}
const removedNodeIds = new Set(
effectiveChanges.filter((change) => change.type === "remove").map((change) => change.id)
);
const { beforeMaterialsByTarget, removedEdges } = hasRemoveChange
? collectReferenceMaterialsBeforeRemovingSourceNodes(removedNodeIds, get)
: { beforeMaterialsByTarget: new Map<string, ComposerReferenceMaterial[]>(), removedEdges: [] };
set((state) => {
const removedGroupIds = new Set<string>();
for (const change of effectiveChanges) {
@ -1647,6 +1712,8 @@ const workflowStoreImpl: StateCreator<WorkflowStore> = (set, get) => ({
});
if (hasRemoveChange) {
clearStaleInputImages(removedEdges, get);
applyReferenceMaterialChangesAfterRemovingSourceNodes(beforeMaterialsByTarget, get);
get().incrementManualChangeCount();
}
},

Loading…
Cancel
Save