Skip to content

模块:Node System

唯一职责:实现 Vue Flow 自定义节点的渲染、编辑和 AI 生成交互。

边界

属于本模块:

  • 通用节点框架(NodeShell):节点容器、标题栏、连接点、阴影状态
  • 紧凑模式 / 编辑模式切换、悬浮面板、右键上下文菜单
  • 状态机 composable(useNodeShellState):selected/hovered/connecting → 各区域可见性
  • TextNode:TipTap 富文本编辑(Markdown 存储 + 渲染)+ AI 文本生成
  • ImageNode:图片上传/预览 + AI 图片生成(支持参考图)
  • VideoNode:视频播放 + AI 视频生成
  • Toolbar(各节点的内容操作工具,通过 NodeShell toolbar slot 悬浮显示)
  • NodeActionBar + Prompt Input(UDropdownMenu 模型选择、credits、#params slot 透传、生成按钮,通过 NodeToolbar 悬浮显示。按钮样式共享 NODE_TOOLBAR_BTN class from constants/nodeUi.ts
  • UpstreamMediaPreview(上游参考图/视频缩略图预览,NodeShell 自动渲染)
  • 节点状态管理(idle → generating → done/error)

不属于本模块:

  • 节点在画布上的位置管理(由 Vue Flow + flowStore 负责)
  • 节点间的连线和数据流(由 Canvas Editor + State Management 负责)
  • HTTP 请求发送(由 AI Service 模块负责)
  • 全局连线状态(isConnecting)的 provide(由 useCanvasEditor 负责)

对外接口

节点通过 Vue Flow 的 node-types 注册(text / image / video),不对外暴露组件 API。IS_CONNECTING_KEYuseCanvasEditor provide,节点内部 inject 使用。

消费的接口

依赖模块调用的方法/属性用途
flowStoreupdateNodeData(id, data)更新节点数据(乐观 + WS 同步)
flowStoreremoveNode(id)删除节点(通过右键菜单)
useGenerategenerate(nodeId, params)触发 AI 生成(HTTP POST + WS Push 接收结果)
useNodeModelsmodels获取当前节点类型可用模型列表
modelsStoregetAiModels(modality)获取模型列表
modelsStoregetDefaultModelKey(modality)获取默认模型
useModelAbilitiesaspectRatioOptions, resolutionOptions, durationOptions, resolveValues, getConstrainedOptions获取模型动态能力选项、rules 约束修正
useCanvasEditorprovide(IS_CONNECTING_KEY, ref)注入全局连线状态

状态机

节点生成状态(NodeStatus

NodeShell 显示模式

详见 NodeShell spec 状态机

不变量

  1. 每个节点组件接收 Vue Flow 的 NodeProps,从 data 读取/写入状态
  2. 未选中时紧凑模式:仅标题 + 内容预览,内容区有透明蒙版阻止交互
  3. 选中时编辑模式:上方悬浮 Toolbar(通过 v-if + NodeToolbar :is-visible="true"),下方悬浮 Prompt + ActionBar
  4. Handle 在 hover / selected / connecting 三种情况显示,其余隐藏(opacity + pointer-events)
  5. 右键上下文菜单通过 UContextMenu 包裹节点卡片实现
  6. generating 状态下生成按钮被禁用,内容区叠加半透明遮罩 + loading 指示器阻止交互,浮动工具栏隐藏
  7. 生成失败不丢失用户已输入的 prompt 和现有内容
  8. 图片上传限制:类型 JPG/PNG/WebP、大小 ≤ 30MB
  9. 视频上传限制:类型 MP4/WebM、大小 ≤ 300MB
  10. ImageNode/VideoNode 的生成参数(宽高比、分辨率、时长等)由模型 abilities 动态驱动,不硬编码
  11. 模型切换或初次加载时自动修正参数到合法值(watch + { immediate: true }
  12. 生成时校验参考图片数量不超过模型 reference_image 限制
  13. 下游节点(有 incoming edge 的 Image/Video 节点)不渲染上传区域和工具栏上传按钮,只能通过 AI 生成获得内容

错误场景

场景模块行为调用方职责
图片上传文件类型不合法(非 JPG/PNG/WebP)拒绝文件,显示 toast 错误提示无需处理(节点内部兜底)
图片上传文件超过 30MB / 视频超过 300MB拒绝文件,显示 toast 错误提示无需处理
下游节点尝试上传上传区域和工具栏上传按钮不渲染,无法触发上传无需处理
AI 生成请求网络超时或后端返回错误节点状态变为 error,保留用户已输入的 prompt 和现有内容无需处理
AI 生成请求被 abort(组件卸载或用户取消)请求取消,节点状态恢复为之前状态无需处理
Object URL 泄漏(组件卸载时未释放)组件 onUnmounted 中释放所有 Object URL 和 abort 进行中的请求无需处理
模型列表未加载完成时用户点击生成使用当前已选模型(或默认模型),不阻塞生成无需处理

组件结构

实现位置

角色文件路径
通用框架app/components/nodes/NodeShell.vue
状态机 composableapp/composables/useNodeShellState.ts
连接点app/components/nodes/NodeHandle.vue
标题栏app/components/nodes/NodeHeader.vue
生成控制栏app/components/nodes/NodeActionBar.vue
Prompt 输入app/components/nodes/NodePromptInput.vue
上游媒体预览app/components/nodes/UpstreamMediaPreview.vue
上游数据 composableapp/composables/useUpstreamData.ts
模型能力 composableapp/composables/useModelAbilities.ts
文本节点app/components/nodes/TextNode.vue
图片节点app/components/nodes/ImageNode.vue
视频节点app/components/nodes/VideoNode.vue
编辑器 composableapp/composables/useTextEditor.ts
测试test/nuxt/nodeShell.test.ts, useNodeShellState.test.ts, textNode.test.ts, videoNode.test.ts