Skip to content

Feature: Quick Look 节点预览

Goal

用户可以在画布中通过空格键快速预览任意节点的内容(图片、视频、富文本),无需进入节点编辑模式,类似 macOS Quick Look 体验。

Behavior Constraints

约束 1:触发预览

Pre: 画布中存在至少一个节点处于 hover 或 selected 状态,焦点不在任何文本输入元素内 Behavior: 用户按下空格键,系统打开全屏预览浮层,展示该节点的媒体内容 Post: 预览浮层可见,画布交互被阻断(不可拖拽/缩放)

约束 2:关闭预览

Pre: 预览浮层已打开 Behavior: 用户按下空格键 或 Esc 键 或 点击遮罩区域 Post: 预览浮层关闭,画布恢复正常交互

约束 3:按节点类型展示内容

Pre: 预览浮层已打开 Behavior: 根据节点类型展示对应内容 — Image 节点展示图片(支持缩放拖拽)、Video 节点播放视频(支持进度条和倍速)、Text 节点渲染富文本 Post: 内容正确展示在预览浮层中

约束 4:空内容节点

Pre: 目标节点没有可预览内容(ImageNode 无 images、VideoNode 无 videos、TextNode 无 text) Behavior: 按空格键不触发预览 Post: 无变化

约束 5:焦点冲突避免

Pre: 焦点在 Prompt 输入框、富文本编辑器或其他文本输入元素内 Behavior: 空格键正常输入空格字符,不触发预览 Post: 无变化

约束 6:多节点切换

Pre: 预览浮层已打开,画布中有多个包含内容的节点 Behavior: 用户按左/右方向键可在有内容的节点间切换预览 Post: 预览内容切换到前/后一个有内容的节点

约束 7:hover 优先级

Pre: 存在一个 selected 节点和一个不同的 hovered 节点 Behavior: 按空格键时预览 hovered 节点(与 macOS Quick Look 行为一致:指针所在优先) Post: 预览浮层展示 hover 节点的内容

State Machine

Acceptance Criteria

  • [~] AC-01:hover 节点有内容时按空格键,打开全屏预览浮层
  • [~] AC-02:selected 节点有内容时按空格键,打开全屏预览浮层
  • [~] AC-03:同时存在 hover 和 selected 节点时,预览 hover 节点
  • [x] AC-04:Image 节点预览展示图片(images[0]
  • [x] AC-05:Video 节点预览播放视频(videos[0]
  • [x] AC-06:Text 节点预览渲染富文本(text
  • [x] AC-07:节点无可预览内容时,按空格键不触发预览
  • [~] AC-08:焦点在文本输入元素内时,空格键不触发预览
  • [x] AC-09:预览状态下按空格键关闭预览
  • [~] AC-10:预览状态下按 Esc 关闭预览
  • [~] AC-11:预览状态下点击遮罩关闭预览
  • [x] AC-12:预览状态下按左右方向键切换到前/后一个有内容的节点
  • [x] AC-13:切换到边界时(第一个/最后一个),不循环,方向键无效
  • [~] AC-14:图片预览支持缩放和拖拽查看
  • [~] AC-15:视频预览支持进度条拖动和倍速控制

BDD Scenarios

gherkin
Feature: Quick Look 节点预览

  # Maps to AC-01, AC-04
  Scenario: hover 图片节点时按空格预览
    Given 画布中有一个 Image 节点,images 包含一张图片
    When 用户将鼠标悬浮在该节点上
    And 用户按下空格键
    Then 全屏预览浮层出现,展示该图片

  # Maps to AC-02, AC-05
  Scenario: selected 视频节点时按空格预览
    Given 画布中有一个 Video 节点已被选中,videos 包含一个视频
    When 用户按下空格键
    Then 全屏预览浮层出现,播放该视频

  # Maps to AC-06
  Scenario: 预览文本节点
    Given 画布中有一个 Text 节点已被选中,text 包含富文本内容
    When 用户按下空格键
    Then 全屏预览浮层出现,渲染该富文本

  # Maps to AC-03
  Scenario: hover 和 selected 同时存在时优先 hover
    Given 画布中有一个已选中的 Image 节点 A 和一个正在 hover 的 Video 节点 B
    When 用户按下空格键
    Then 预览浮层展示节点 B 的视频

  # Maps to AC-07
  Scenario: 空内容节点不触发预览
    Given 画布中有一个 Image 节点未上传图片(images 为空)
    When 用户悬浮该节点并按空格键
    Then 预览浮层不出现

  # Maps to AC-08
  Scenario: 输入框内按空格不触发预览
    Given 用户焦点在某节点的 Prompt 输入框内
    When 用户按下空格键
    Then 空格字符正常输入,预览不触发

  # Maps to AC-09, AC-10, AC-11
  Scenario: 关闭预览的三种方式
    Given 预览浮层已打开
    When 用户按下空格键
    Then 预览浮层关闭
    When 用户重新打开预览后按 Esc
    Then 预览浮层关闭
    When 用户重新打开预览后点击遮罩区域
    Then 预览浮层关闭

  # Maps to AC-12, AC-13
  Scenario: 方向键切换预览节点
    Given 画布中有 3 个有内容的节点 A B C,当前预览节点 B
    When 用户按右方向键
    Then 预览切换到节点 C
    When 用户再次按右方向键
    Then 预览不变(已到末尾)
    When 用户按左方向键
    Then 预览切换到节点 B

  # Maps to AC-14
  Scenario: 图片预览支持缩放和拖拽
    Given 预览浮层已打开,展示一张图片
    When 用户滚轮缩放或双指捏合
    Then 图片放大或缩小
    When 用户拖拽图片
    Then 图片视口随拖拽移动

  # Maps to AC-15
  Scenario: 视频预览支持进度条和倍速
    Given 预览浮层已打开,播放一个视频
    When 用户拖动进度条
    Then 视频跳转到对应时间点
    When 用户切换倍速
    Then 视频以新速率播放

TDD Pointers

节点内容检测(纯函数):

  • Test: hasPreviewableContent(nodeData) — Image 有 images 返回 true,空数组返回 false (maps to AC-07)
  • Test: Video 有 videos 返回 true,Text 有 text 返回 true

预览目标解析(纯函数):

  • Test: hover 节点优先于 selected 节点 (maps to AC-03)
  • Test: 无 hover 时 fallback 到 selected 节点 (maps to AC-02)
  • Test: 两者都无时返回 null

节点排序/切换(纯函数):

  • Test: 可预览节点列表按画布位置排序,方向键正确切换索引 (maps to AC-12)
  • Test: 边界不循环 (maps to AC-13)

Out of Scope

  • Image 节点多 variations 的网格预览(仅预览 images[0]
  • 触摸屏/移动端手势触发预览
  • 预览浮层的过渡动画细节(由实现决定)
  • 节点生成中(status=generating)的特殊预览行为