Appearance
ADR-003: 连线校验设计
Status
Accepted
Date
2026-03-23
Context
画布编辑器允许用户通过拖拽创建节点间连线。需要防止无效连线(自连接、循环依赖、重复连线),否则数据流引擎会出现死循环或不可预测行为。
校验逻辑需要在两个时机执行:
- 拖拽中实时反馈 — Vue Flow 的
isValidConnection回调,决定是否允许用户将连线放下 - 创建时最终校验 —
flowStore.addEdge()调用前,双重保险
Options Considered
Option A: 在 flowStore 内部直接写校验逻辑
- Pros: 简单,所有逻辑集中在一个文件
- Cons: 依赖 Vue Flow 和 Pinia,难以独立测试;校验逻辑与状态管理耦合
Option B: 抽取为纯函数模块
- Pros: 零依赖,可在任何环境独立测试;输入输出明确(edges 数组 + 新 edge → 校验结果)
- Cons: 多一个文件
Decision
选择 Option B:校验逻辑抽取为 stores/flowValidation.ts 纯函数模块。
三级校验策略(按检测成本从低到高排列):
- 自连接检测:
source === target,O(1) - 循环检测:BFS 从 target 出发沿现有边正向遍历,检测能否到达 source,O(V+E)
- 重复检测:遍历现有边检测相同 source/target/handle 组合,O(E)
导出类型 EdgeValidationResult: { valid: boolean, reason?: 'self-connection' | 'cycle' | 'duplicate' }。
Consequences
- 校验函数无任何框架依赖,可用纯 Vitest 测试覆盖
- flowStore 通过
validateEdge(edges.value, newEdge)调用,保持 store 简洁 isValidConnection回调同样委托给 flowStore.validateEdge,避免重复实现- 未来若需支持"输入端口单连线"规则(后连接替换先前连线),只需在
validateEdge中新增一级检测