+
-
+
-
+
{spec.displayName}
+
{nodeData.name || spec.displayName}
-
{spec.displayName}
+
{preview ? (
-
+
{preview}
) : (
-
- 点击编辑节点内容…
+
+ {spec.description}
)}
@@ -124,7 +133,7 @@ export function GenericNode({ id, type, data, selected }: NodeProps) {
)}
diff --git a/frontend/src/components/workflow/WorkflowEditor.tsx b/frontend/src/components/workflow/WorkflowEditor.tsx
index cf183ab..78cf0c5 100644
--- a/frontend/src/components/workflow/WorkflowEditor.tsx
+++ b/frontend/src/components/workflow/WorkflowEditor.tsx
@@ -17,6 +17,7 @@ import {
type Edge,
MiniMap,
type Node,
+ type NodeChange,
Panel,
ReactFlow,
ReactFlowProvider,
@@ -214,11 +215,26 @@ function Canvas({
const deleteNode = useCallback(
(id: string) => {
+ if (nodes.find((node) => node.id === id)?.type === "startCall") return;
setNodes((ns) => ns.filter((n) => n.id !== id));
setEdges((es) => es.filter((e) => e.source !== id && e.target !== id));
setEditingId((cur) => (cur === id ? null : cur));
},
- [setNodes, setEdges],
+ [nodes, setNodes, setEdges],
+ );
+
+ const handleNodesChange = useCallback(
+ (changes: NodeChange[]) => {
+ const startIds = new Set(
+ nodes.filter((node) => node.type === "startCall").map((node) => node.id),
+ );
+ onNodesChange(
+ changes.filter(
+ (change) => change.type !== "remove" || !startIds.has(change.id),
+ ),
+ );
+ },
+ [nodes, onNodesChange],
);
const updateEdgeData = useCallback(
@@ -259,96 +275,151 @@ function Canvas({
-
-
{
- setEditingId(null);
- setEditingEdgeId(null);
- }}
- fitView
- proOptions={{ hideAttribution: true }}
- defaultEdgeOptions={{ type: "condition", animated: true }}
- className="bg-canvas-soft"
- >
-
+
+
-
-
-
-
-
-
-
+
+
{
+ setEditingId(null);
+ setEditingEdgeId(null);
+ }}
+ fitView
+ proOptions={{ hideAttribution: true }}
+ defaultEdgeOptions={{ type: "condition", animated: true }}
+ >
+
+
+
+
+
+
+
+
+
{/* 添加节点弹窗 */}