Skip to content

Feature: 节点多选批量连线

Goal

用户多选节点后,选区框出现 group handle,拖拽可一次性将所有选中节点批量连接到目标节点(或从外部节点批量连接到所有选中节点),避免逐条手动拖线。

Behavior Constraints

约束 1:选区 Group Handle 显示

Pre: 画布中有 2+ 个节点被选中 Behavior: 选区框左侧出现 group target handle,右侧出现 group source handle Post: Group handle 仅在多选状态下可见,取消选择后消失

约束 2:批量连出(多→一)

Pre: 多个节点被选中,选区框显示 group source handle Behavior: 用户从 group source handle 拖拽到目标节点的 target handle(或节点体),系统为每个选中节点逐一创建到目标节点的连线 Post: 通过验证的连线全部创建,未通过的跳过

约束 3:批量连入(一→多)

Pre: 多个节点被选中,选区框显示 group target handle Behavior: 用户从外部节点的 source handle 拖拽到 group target handle,系统为每个选中节点逐一创建从源节点到该选中节点的连线 Post: 通过验证的连线全部创建,未通过的跳过

约束 4:逐条验证,部分成功

Pre: 批量连线触发(约束 2 或 3) Behavior: 对每条待创建的连线独立执行现有验证规则(自连接、循环、重复、handle 方向、uploaded target 限制)。验证通过的创建,不通过的静默跳过。 Post: 仅创建合法连线,无失败反馈

约束 5:拖拽到空白区域

Pre: 用户从 group source handle 拖拽到画布空白区域 Behavior: 弹出浮动菜单,用户选择类型后创建新节点,并为每个选中节点创建到新节点的连线(逐条验证) Post: 新节点创建,通过验证的连线全部建立

约束 6:选中节点包含目标节点

Pre: 批量连线的目标节点本身也在选中集合中 Behavior: 不做特殊处理,该边由现有自连接校验自然拦截 Post: 无自连接边产生,无额外提示

Acceptance Criteria

显示

  • [x] AC-01:选中 2+ 个节点时,选区框右侧出现 group source handle,左侧出现 group target handle
  • [x] AC-02:取消多选后(点击空白区域 / 只剩 1 个选中),group handle 消失

批量连出(多→一)

  • [x] AC-03:从 group source handle 拖拽到目标节点 target handle,为每个选中节点创建到目标节点的连线
  • [x] AC-04:从 group source handle 拖拽到目标节点体(非 handle),同样批量创建连线
  • [x] AC-05:从 group source handle 拖拽到空白区域,弹出浮动菜单,选择类型后创建新节点并批量连线

批量连入(一→多)

  • [x] AC-06:从外部节点 source handle 拖拽到 group target handle,为每个选中节点创建从源节点到该选中节点的连线

验证

  • [x] AC-07:批量创建时,不通过验证的连线(自连接、循环、重复、handle 方向、uploaded target)被静默跳过,通过的正常创建
  • [x] AC-08:目标节点在选中集合中时,自连接边被现有规则拦截,其余连线正常创建

BDD Scenarios

gherkin
Feature: 节点多选批量连线

  # AC-01, AC-02
  Scenario: 多选时显示 group handle
    Given 画布中有节点 A、B、C
    When 用户框选 A 和 B
    Then 选区框右侧出现 group source handle
    And 选区框左侧出现 group target handle
    When 用户点击画布空白区域取消选择
    Then group handle 消失

  # AC-03
  Scenario: 批量连出到目标节点 handle
    Given 画布中有节点 A、B、C
    And 用户已选中 A 和 B
    When 用户从 group source handle 拖拽到 C 的 target handle
    Then 创建 A → C 连线
    And 创建 B → C 连线

  # AC-04
  Scenario: 批量连出到目标节点体
    Given 画布中有节点 A、B、C
    And 用户已选中 A 和 B
    When 用户从 group source handle 拖拽到 C 的节点体
    Then 创建 A → C 连线
    And 创建 B → C 连线

  # AC-05
  Scenario: 批量连出到空白区域创建新节点
    Given 画布中有节点 A 和 B
    And 用户已选中 A 和 B
    When 用户从 group source handle 拖拽到画布空白区域
    Then 弹出浮动菜单
    When 选择 "图片" 节点类型
    Then 创建图片节点 C
    And 创建 A → C 连线
    And 创建 B → C 连线

  # AC-06
  Scenario: 批量连入从外部节点
    Given 画布中有节点 A、B、C
    And 用户已选中 B 和 C
    When 用户从 A 的 source handle 拖拽到 group target handle
    Then 创建 A → B 连线
    And 创建 A → C 连线

  # AC-07
  Scenario: 验证失败的连线被静默跳过
    Given 画布中有节点 A、B、C
    And 已存在 A → C 连线
    And 用户已选中 A 和 B
    When 用户从 group source handle 拖拽到 C 的 target handle
    Then A → C 重复边被跳过
    And 仅创建 B → C 连线

  # AC-07 uploaded 限制
  Scenario: uploaded 节点作为 target 被跳过
    Given 画布中有文本节点 A 和图片节点 B(origin 为 uploaded)和图片节点 C(origin 为 empty)
    And 用户已选中 B 和 C
    And 外部有文本节点 D
    When 用户从 D 的 source handle 拖拽到 group target handle
    Then D → B 被跳过(uploaded 不可作 target)
    And 仅创建 D → C 连线

  # AC-08
  Scenario: 目标节点在选中集合中
    Given 画布中有节点 A、B、C
    And 用户已选中 A、B、C
    When 用户从 group source handle 拖拽到 C 的 target handle
    Then A → C 连线创建成功
    And B → C 连线创建成功
    And C → C 自连接被跳过

TDD Pointers

批量连线创建逻辑(flowStore.addBatchEdges):

  • [x] Test: 传入 N 个 source 节点 + 1 个 target 节点,返回 N 条边(AC-03) → flowStore.test.ts
  • [x] Test: 传入 1 个 source 节点 + N 个 target 节点,返回 N 条边(AC-06) → flowStore.test.ts
  • [x] Test: 其中一条边已存在(重复),结果中排除该边(AC-07) → flowStore.test.ts
  • [x] Test: 其中一个 target 为 uploaded 图片节点,结果中排除该边(AC-07) → flowStore.test.ts
  • [x] Test: target 节点在 source 集合中,自连接边被排除(AC-08) → flowStore.test.ts
  • [x] Test: 所有边都不通过验证时,返回空数组(AC-07 边界) → flowStore.test.ts
  • [x] Test: 传入空选中集合,返回空数组(边界) → flowStore.test.ts

flowValidation 扩展:

未新增 validateBatchEdges 函数 — addBatchEdges 直接在循环中逐条调用 validateEdge,无需独立批量验证函数。

Out of Scope

  • Group handle 的视觉样式(颜色、大小、动画)— 属于 design-system 职责
  • 多选框选的交互本身(框选、Shift+点击)— Vue Flow 内置能力,不需要自定义
  • 批量删除、批量移动等其他多选操作 — 不在本功能范围
  • 连线兼容性警告态(edge-system AC-11/12)— 依赖 model-capabilities
  • 批量连线的撤销/重做 — 属于 canvas-system 撤销重做功能
  • 连线动画或拖拽过程中的视觉预览(如同时显示多条虚线) — ✅ 已实现(connection-line slot 多线预览)