组件系统
引言
本文件面向设计器组件系统,系统化阐述组件设计理念、实现原理与使用方法,重点覆盖以下主题:
- 选择器组件的选择逻辑与高亮反馈
- 拖拽组件的拖放机制与落点判定
- 器件(Widget)与设置器(Setter)的注册与管理
- 组件间通信机制、事件传递流程与状态同步策略
- 生命周期管理、渲染优化与性能监控
- 自定义组件开发指南、组件注册机制与样式定制
- 与物料系统的集成、动态加载与版本兼容策略
- 丰富的使用场景与最佳实践路径
- 新增 AI代理自动执行逻辑的bug修复与增强功能
项目结构
设计器组件系统位于 packages/designer,采用"框架层 + 管理层 + 组件层"的分层设计:
- 框架层:提供设计器核心能力(Designer 类、工具注册、状态与事件桥接)
- 管理层:提供器件与设置器的注册、查询、修改、删除等管理接口
- 组件层:提供可视化区域、设置面板、绑定器、骨架屏等 UI 组件
- 物料层:通过 apps/material 提供组件库与物料描述,统一注册与安装
- 新增 AI代理层:提供智能对话、自动执行与工具调用能力
graph TB
subgraph "设计器框架"
D["Designer 类<br/>拖拽/选择/落点判定"]
T["类型定义<br/>Widget/Setter/Region"]
TR["工具注册表"]
AI["AI代理<br/>自动执行逻辑"]
end
subgraph "管理层"
WM["Widget 管理器"]
SM["Setter 管理器"]
TM["工具管理器"]
end
subgraph "组件层"
CIdx["组件导出入口"]
Hooks["设计态钩子<br/>useDesigner/useSelected/useCurrent"]
AIHooks["AI钩子<br/>useAgent/useAI"]
end
subgraph "物料层"
Lib["物料库安装器"]
Mat["物料描述与分类"]
end
D --> WM
D --> SM
D --> TM
D --> AI
WM --> CIdx
SM --> CIdx
TM --> AI
Hooks --> D
AIHooks --> AI
Lib --> CIdx
Mat --> WM
核心组件
- 设计器核心(Designer):负责事件绑定、拖拽状态、落点计算、允许落点判定、高亮与轮廓线绘制、DOM 元素与模型映射
- 设计态钩子(useDesigner/useSelected/useCurrent):封装设计器状态、计算高亮/选中/落点矩形样式、联动引擎变更
- 器件管理器(WidgetManager):内置器件注册、按区域/分组检索、远程器件清理
- 设置器管理器(SetterManager):内置设置器注册、按类型检索、默认设置器
- 工具管理器(ToolRegistry):新增 提供工具注册、查询、执行与描述生成功能
- 组件导出入口:统一导出设计器、骨架屏、设置视图、区域、设置器、小部件等
架构总览
设计器以 Designer 为核心,通过事件监听与引擎上下文完成对渲染器内组件的交互;通过 WidgetManager 与 SetterManager 提供可扩展的可视化区域与属性设置能力;通过物料层实现组件库的统一安装与描述;新增 AI代理层通过工具注册表实现智能自动执行与工具调用。
sequenceDiagram
participant U as "用户"
participant IF as "设计器(iframe)"
participant D as "Designer"
participant AI as "AI代理"
participant E as "引擎/模拟器"
participant R as "渲染器"
participant M as "物料/组件库"
U->>IF : 鼠标移动/点击/拖拽
IF->>D : 触发事件回调
D->>E : 查询当前项目/节点
D->>R : 计算高亮/落点/轮廓线
D->>D : 判定允许落点/落点类型
D->>E : 执行添加/移动节点
E->>R : 刷新渲染
R-->>D : 上下文/refs
D-->>U : 更新高亮/轮廓样式
U->>M : 拖拽组件到画布
M-->>D : 组件描述/块物料
D->>E : 创建节点DSL并落位
U->>AI : 发送AI指令/图片/JSON
AI->>AI : 解析输出/判断下一步
AI->>E : 执行工具调用/代码生成
E->>R : 应用DSL变更
R-->>AI : 返回执行结果
AI-->>U : 展示结果/继续执行
详细组件分析
选择器组件与高亮反馈
- 选择逻辑
- 鼠标悬停触发 hover 更新,点击触发 selected 更新
- 通过事件捕获路径定位 VTJ 元素,解析模型 ID 并映射到 NodeModel/BlockModel
- 计算 DOMRect 并生成 DesignHelper,包含模型、元素、矩形、落点类型、路径索引
- 高亮与轮廓线
- hover/selected/dropping 三态分别维护浅响应式对象,用于驱动视觉反馈
- outlineEnabled 开启时,收集渲染器上下文中的所有节点矩形,形成轮廓线数组
- 计算样式时根据矩形尺寸与位置优先级决定显示与方位
flowchart TD
Start(["事件触发"]) --> Path["获取事件路径<br/>定位 VTJ 元素"]
Path --> Model["解析模型ID<br/>映射到 NodeModel/BlockModel"]
Model --> Rect["计算 DOMRect"]
Rect --> Type["判定落点类型<br/>inner/left/right/top/bottom"]
Type --> Helper["构造 DesignHelper"]
Helper --> HoverSel{"hover/selected?<br/>或 dropping?"}
HoverSel --> |hover| SetHover["更新 hover 状态"]
HoverSel --> |selected| SetSelected["更新 selected 状态"]
HoverSel --> |dropping| SetDropping["更新 dropping 状态"]
SetHover --> Lines["outlineEnabled 时更新轮廓线"]
SetSelected --> Lines
SetDropping --> Lines
Lines --> End(["渲染反馈"])
拖拽组件与拖放机制
- 拖拽开始
- onDragStart 从目标元素解析模型,尝试从物料库或组件映射获取描述,设置拖拽状态
- 同时记录正在拖拽的节点(来自画布内部拖拽)
- 拖拽移动
- onDragOver 计算允许落点,更新 dropping 状态;否则清空
- 拖拽结束
- onDragEnd 清理拖拽状态
- 放置落点
- onDrop 预检允许落点,区分 Block 与普通节点
- 对于 Block:支持直接移动或新增到内部
- 对于普通节点:计算插槽(默认或用户选择),执行 move 或 addNode
- 落位后刷新模拟器与物料缓存
sequenceDiagram
participant U as "用户"
participant D as "Designer"
participant E as "引擎"
participant A as "物料/组件映射"
U->>D : dragstart
D->>A : 解析组件描述/块物料
D->>D : setDragging / setDraggingNode
U->>D : dragover
D->>D : allowDrop(目标, 类型)
alt 允许
D->>D : dropping = 目标
else 不允许
D->>D : dropping = null
end
U->>D : drop
D->>D : 允许落点校验
alt 目标为 Block
D->>E : move/addNode(inner)
else 普通节点
D->>D : 计算/选择插槽
D->>E : move/addNode(带 slot)
end
D->>E : 刷新模拟器/清理缓存
器件(Widget)与设置器(Setter)管理
- 器件(Widget)
- 内置注册:启动时合并内置器件
- 注册/查询/修改/删除:按名称操作,支持按区域与分组检索
- 远程器件:支持标记 remote,便于动态移除
- 设置器(Setter)
- 内置注册:启动时合并内置设置器
- 注册/查询/修改:按名称操作
- 按类型检索:根据 BlockPropDataType 返回匹配的设置器名称列表
- 默认设置器:未命中时回退
classDiagram
class WidgetManager {
-widgets : Record
+register(widget)
+get(name)
+set(name, partial)
+unregister(name)
+getWidgets(region?, group?)
+getRemoteWidgets()
+removeRemoteWidgets()
}
class SetterManager {
-setters : Record
+defaultSetter
+register(setter)
+get(name)
+set(name, partial)
+getByType(type)
}
WidgetManager --> Widget : "管理"
SetterManager --> Setter : "管理"
组件间通信与事件传递
- 事件桥接
- 设计器在 document/window 上绑定鼠标/键盘/滚动/窗口事件
- 通过全局事件总线监听项目激活与节点变更,驱动视图更新
- 状态同步
- hover/selected/dropping/dragging/draggingNode/lines 等状态通过浅响应式与 ref 协调
- 设计态钩子将 Designer 状态转换为可渲染的样式与位置信息
- 生命周期
- 初始化:useDesigner 调用模拟器初始化
- 销毁:dispose 解绑事件并清理状态
sequenceDiagram
participant Doc as "文档/窗口"
participant D as "Designer"
participant Bus as "事件总线"
participant Hook as "设计态钩子"
participant Eng as "引擎"
Doc->>D : mouseover/scroll/resize/click/drag*
D->>Hook : 更新 hover/selected/dropping
Doc->>D : drop/dragend
D->>Eng : 执行节点操作
Eng-->>D : changed
D->>Hook : 触发更新矩形/轮廓线
Bus-->>D : 项目激活/节点变更
D->>Hook : 重置状态
自定义组件开发指南
- 组件注册
- 将组件注册到应用实例:参考物料库安装器的组件注册模式
- 在物料描述中声明组件名称与块物料信息,确保设计器能解析并落位
- 器件与设置器扩展
- 使用 WidgetManager.register 注册自定义器件
- 使用 SetterManager.register 注册设置器,并通过类型映射或默认设置器生效
- 样式定制
- 通过设计器提供的样式入口与区域样式进行覆盖
- 注意与 outlineEnabled 下的轮廓线样式保持一致的 z-index 与边框策略
与物料系统的集成与动态加载
- 物料安装
- 通过 library.install 将组件批量注册到应用
- 物料描述
- 定义组件分组、标签、库映射与描述,统一由 Material 导出
- 动态加载
- 设计器在拖拽时按需从物料映射或块物料获取描述,必要时弹出插槽选择对话框
- 版本兼容
- 通过 package.json 的版本号与 exports 字段控制发布产物与入口
AI代理与自动执行逻辑
AI代理核心功能
AI代理系统通过 useAgent 钩子提供智能自动执行能力,包括:
- 多格式解析:支持 Vue SFC、增量更新diff、JSON工具调用三种格式
- 错误码检测:识别HTTP 4xx/5xx错误码,终止自动执行流程
- 最终结果识别:检测F:和R:标记作为最终结果信号
- 工具调用检测:识别P:标记但未执行A:的动作,继续执行
- 智能决策:根据输出内容决定是否继续下一轮对话
flowchart TD
Start(["AI输出处理"]) --> Parse["解析输出内容"]
Parse --> HasFlag{"包含特定标记?"}
HasFlag --> |"4/5开头错误码"| Stop["停止执行"]
HasFlag --> |"F:/R:最终结果"| Stop
HasFlag --> |"P:但无A:"| Continue["继续执行"]
HasFlag --> |"json工具调用"| Tool["执行工具调用"]
HasFlag --> |"vue/diff代码"| Code["应用代码变更"]
Tool --> Success{"执行成功?"}
Success --> |是| Next["生成下一步提示"]
Success --> |否| Error["记录错误并提示修复"]
Code --> Convert["转换为DSL"]
Convert --> Apply["应用到设计器"]
Apply --> Done["完成"]
Continue --> Next
Stop --> End(["结束"])
Next --> End
Done --> End
Error --> Fix["提示修复"]
Fix --> End
工具系统集成
AI代理通过 TOOL_CONFIGS 注册内置工具,支持以下功能:
- 项目管理:页面、区块的创建、更新、移动、删除
- 全局配置:权限控制、请求配置、拦截器设置
- 国际化:消息词条的增删改查
- 环境变量:开发环境配置管理
- UniApp配置:应用生命周期、页面配置等
classDiagram
class ToolConfig {
+name : string
+description : string
+parameters : ToolParameter[]
+createHandler(context) : Function
}
class ToolRegistry {
+register(tool)
+get(name) : Tool
+set(name, tool)
+unregister(name)
+getAll() : Tool[]
+has(name) : boolean
+generateToolDescriptions() : string[]
}
class Tool {
+name : string
+description : string
+parameters : ToolParameter[]
+handler(...args) : Promise<any>
}
ToolRegistry --> ToolConfig : "注册"
ToolRegistry --> Tool : "执行"
AI对话流程
useAI钩子提供完整的AI对话体验:
- 话题管理:创建、加载、删除AI话题
- 聊天记录:实时流式输出,支持暂停和继续
- 自动应用:根据配置自动应用DSL变更
- 错误处理:网络异常、解析错误的统一处理
- 代码展示:支持Vue代码高亮显示与隐藏
sequenceDiagram
participant User as "用户"
participant AI as "AI系统"
participant Agent as "AI代理"
participant Engine as "设计器引擎"
User->>AI : 发送指令/图片/JSON
AI->>Agent : 处理AI输出
Agent->>Agent : 解析格式/检测状态
alt 工具调用
Agent->>Engine : 执行工具
Engine-->>Agent : 返回结果
else 代码变更
Agent->>Engine : 转换DSL并应用
Engine-->>Agent : 应用成功
end
Agent->>AI : 生成下一步提示
AI->>User : 流式输出结果
依赖关系分析
- 外部依赖
- @vtj/core:提供 NodeModel/BlockModel、事件总线、物料描述等核心模型
- @vtj/renderer:提供渲染上下文与 HTML 标签集合
- @vtj/utils:提供通用工具(如延迟、数组工具、日志)
- @vtj/ui/@vtj/icons/@vtj/uni:提供 UI 组件与图标、跨端能力
- 新增 @vtj/parser:提供代码解析与增量更新能力
- 内部依赖
- 设计器依赖引擎与模拟器,通过 useDesigner 初始化模拟器
- 器件与设置器管理器依赖内置注册项与默认配置
- 新增 AI代理依赖工具注册表与内置工具配置
- 组件层通过统一入口导出,便于按需引入
graph LR
Pkg["@vtj/designer<br/>package.json"] --> Core["@vtj/core"]
Pkg --> Renderer["@vtj/renderer"]
Pkg --> Utils["@vtj/utils"]
Pkg --> UI["@vtj/ui"]
Pkg --> Icons["@vtj/icons"]
Pkg --> Uni["@vtj/uni"]
Pkg --> Parser["@vtj/parser"]
Dsr["designer.ts"] --> Core
Dsr --> Renderer
Dsr --> Utils
WMgr["widget.ts"] --> BuiltInW["built-in widgets"]
SMgr["setter.ts"] --> BuiltInS["built-in setters"]
Agent["useAgent.ts"] --> Tools["TOOL_CONFIGS"]
Agent --> Parser
AI["useAI.ts"] --> Agent
性能考量
- DOM 查询与矩形计算
- updateRect/updateLines 中使用延迟与 nextTick,避免过早读取布局导致误差
- 轮廓线收集遍历渲染器上下文中的 refs,注意节点数量增长带来的成本
- 事件绑定与解绑
- 设计器在销毁时统一解绑事件,防止内存泄漏
- 插槽选择与物料缓存
- 拖拽落位后主动清理物料缓存,保证后续物料解析一致性
- 新增 AI代理性能优化
- 输出解析采用快速路径检测,跳过不必要的正则匹配
- 工具调用执行使用异步处理,避免阻塞UI线程
- 增量更新应用采用增量解析,减少代码处理开销
故障排查指南
- 无法选择/高亮
- 检查 VTJ 元素标记与 data-vtj 属性是否正确
- 确认事件路径中存在 vtj/context 标记
- 拖拽无效
- 确认 allowDrop 返回 true,检查 parentIncludes/childIncludes 与 HTML 标签白名单
- 若目标为 Block,确认 isBlock 判断与 inner 落点分支
- 插槽选择异常
- 确认物料描述的 slots 或组件动态插槽是否正确提供
- 用户取消选择时返回 null,需在调用方处理
- 轮廓线不显示
- 检查 outlineEnabled 状态与渲染器上下文 __refs 是否可用
- 器件/设置器未生效
- 确认已通过 register 注册并按区域/分组正确检索
- 设置器按类型检索时注意大小写不敏感匹配
- 新增 AI代理问题排查
- 检查AI输出格式是否符合预期,包含正确的标记
- 确认工具配置正确注册,工具名称与参数匹配
- 验证DSL转换过程,检查错误信息中的具体问题
- 网络异常时检查代理配置与API密钥
结论
设计器组件系统以 Designer 为核心,结合事件桥接、状态计算与渲染器上下文,实现了高效的选择、拖拽与落点判定;通过 WidgetManager 与 SetterManager 提供了可扩展的可视化区域与属性设置能力;配合物料系统实现组件库的统一安装与描述,满足自定义组件开发与动态加载需求。新增的AI代理系统通过智能决策逻辑、工具调用与自动执行能力,进一步提升了设计器的智能化水平,为开发者提供了更强大的自动化开发体验。遵循本文的架构理解、使用方法与最佳实践,可快速构建稳定、可维护且智能化的设计器组件体系。
附录
- 快速上手
- 在应用中安装物料库组件:参考 library.install
- 在设计器中初始化模拟器:参考 useDesigner 的 engine.simulator.init
- 注册自定义器件/设置器:参考 widgetManager/register 与 setterManager/register
- 新增 配置AI代理:参考 useAgent 的工具注册与配置
- 最佳实践
- 事件处理中尽量使用浅响应式状态,减少不必要的重渲染
- 拖拽落点判定应结合物料描述与动态插槽,提升用户体验
- 轮廓线开启时注意性能影响,必要时限制节点数量或降低刷新频率
- 新增 AI代理输出格式规范化,确保标记符的正确使用
- 工具调用应提供清晰的错误信息,便于用户理解和修复
- 增量更新应用前先验证代码格式,提高成功率