You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
flow-playform-react/docs/add-loop-node-template.md

150 lines
3.9 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 新增 LOOP 类节点模板(基于当前重构版本)
这份模板用于你现在这套 Flow Core`loopFactory + nodeRegistry + useFlowCallbacks`)下,新增“成对节点/分支类”能力。
> 适用场景:像 `LOOP_START/LOOP_END` 这种需要一次创建多个节点和连边的节点族。
---
## 1. 推荐做法(先看)
不要在 `useFlowCallbacks` 里直接手写大段节点/边构造。按现在的模式:
1.`src/utils/flow/` 新增工厂(如 `xxxFactory.ts`
2. 暴露:
- 节点对(或节点组)构造函数
- 组内连接边构造函数
- 外部插入连接边构造函数(可选)
3.`useFlowCallbacks` 只负责调用工厂 + setNodes/setEdges + snapshot
---
## 2. 工厂模板
**路径示例**`src/utils/flow/retryFactory.ts`
```ts
import { Edge } from '@xyflow/react';
export const createRetryNodePair = (position: { x: number; y: number }) => {
const retryStartNode: any = {
id: `RETRY_START-${Date.now()}`,
type: 'RETRY',
position: { x: position.x, y: position.y },
data: {
title: '重试开始',
type: 'RETRY_START',
parameters: {
apiIns: [{ name: 'start', desc: '', dataType: '', defaultValue: '' }],
apiOuts: [{ name: 'done', desc: '', dataType: '', defaultValue: '' }],
dataIns: [],
dataOuts: [],
},
component: {},
},
};
const retryEndNode: any = {
id: `RETRY_END-${Date.now()}`,
type: 'RETRY',
position: { x: position.x + 400, y: position.y },
data: {
title: '重试结束',
type: 'RETRY_END',
parameters: {
apiIns: [
{ name: 'continue', desc: '', dataType: '', defaultValue: '' },
],
apiOuts: [{ name: 'break', desc: '', dataType: '', defaultValue: '' }],
dataIns: [],
dataOuts: [],
},
component: {
type: 'RETRY_END',
customDef: JSON.stringify({ retryStartNodeId: retryStartNode.id }),
retryStartNodeId: retryStartNode.id,
},
},
};
retryStartNode.data.component = {
type: 'RETRY_START',
customDef: JSON.stringify({ retryEndNodeId: retryEndNode.id }),
};
return { retryStartNode, retryEndNode };
};
export const createRetryGroupEdge = (
retryStartId: string,
retryEndId: string
): Edge => ({
id: `${retryStartId}-${retryEndId}-group`,
source: retryStartId,
target: retryEndId,
sourceHandle: `${retryStartId}-group`,
targetHandle: `${retryEndId}-group`,
type: 'custom',
});
```
---
## 3. useFlowCallbacks 接入模板
```ts
import {
createRetryNodePair,
createRetryGroupEdge,
} from '@/utils/flow/retryFactory';
import { ensureNodeTypeRegistered } from '@/utils/flow/nodeRegistry';
import { dispatchFlowSnapshotAsync } from '@/utils/flow/snapshot';
const addRetryNodeWithStartEnd = useCallback(
(position: { x: number; y: number }) => {
const { retryStartNode, retryEndNode } = createRetryNodePair(position);
const groupEdge = createRetryGroupEdge(retryStartNode.id, retryEndNode.id);
ensureNodeTypeRegistered('RETRY', '重试');
setNodes((nds) => {
const newNodes = [...nds, retryStartNode, retryEndNode];
dispatchFlowSnapshotAsync({
nodes: [...newNodes],
edges: [...edges, groupEdge],
});
return newNodes;
});
setEdges((eds) => [...eds, groupEdge]);
},
[edges]
);
```
---
## 4. 类型映射模板
**文件**`src/utils/flow/nodeRegistry.ts`
```ts
case 'RETRY':
return LoopNode; // 或你自己的专用节点组件
```
> 早期可复用 `LoopNode/LocalNode`,后续再拆专用展示组件。
---
## 5. 新增“边上插入该类节点”的模板(可选)
如需在边上插入节点组,建议像 `LOOP` 一样提供工厂函数:
- `createXxxNodePair(position)`
- `createXxxGroupEdge(startId, endId)`
- `createXxxInsertConnectionEdges({ sourceId, sourceHandle, targetId, targetHandle, ... })`
这样 `addNodeOnEdge` 里只拼装调用,不再手写边结构。