feat(workflow): add node duplication

This commit is contained in:
Xin Wang
2026-08-03 07:32:43 +08:00
parent 9daa46ed4d
commit c241e815cc
3 changed files with 83 additions and 16 deletions

View File

@@ -328,6 +328,50 @@ export function WorkflowCanvas({
[editingNodeId, nodes, onEditingNodeIdChange, setNodes, setEdges],
);
const duplicateNode = useCallback(
(id: string) => {
const source = nodes.find((node) => node.id === id);
if (!source || source.type === "start") return;
const spec = specsByType[source.type as string];
if (!spec) return;
const limit = spec.constraints.maxInstances;
if (
limit !== undefined &&
nodes.filter((node) => node.type === source.type).length >= limit
) {
return;
}
nodeSeq += 1;
const duplicateId = `${source.type}-${Date.now()}-${nodeSeq}`;
const sourceData = source.data as WorkflowNodeData;
const duplicateData = structuredClone(sourceData);
duplicateData.name = `${sourceData.name || spec.displayName}(副本)`;
setNodes((currentNodes) => [
...currentNodes.map((node) => ({ ...node, selected: false })),
{
id: duplicateId,
type: source.type,
position: {
x: source.position.x + 40,
y: source.position.y + 40,
},
data: duplicateData,
selected: true,
},
]);
onEditingNodeIdChange(null);
},
[
nodes,
onEditingNodeIdChange,
setNodes,
specsByType,
],
);
const handleNodesChange = useCallback(
(changes: NodeChange[]) => {
const startIds = new Set(
@@ -431,10 +475,12 @@ export function WorkflowCanvas({
onEditingEdgeIdChange(null);
onEditingNodeIdChange(id);
},
duplicate: duplicateNode,
remove: deleteNode,
}),
[
deleteNode,
duplicateNode,
onDebugOpenChange,
onEditingEdgeIdChange,
onEditingNodeIdChange,