# 新增 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` 里只拼装调用，不再手写边结构。

