布局编辑器

概述

QuickUIDesign 的布局编辑器(Editor)是一个可视化拖拽布局工具,用于设计在 UE5 中运行的 UI 界面布局。它采用"所见即所得"的工作方式,通过拖拽组件、调整位置和尺寸、编辑属性,自动保存到项目的本地配置存储中。

编辑器与 Preview(预览)、Runtime(运行)共同构成三模式体系:

  • Editor — 可视化编辑布局,支持自动保存和发布流程
  • Preview — 在浏览器中预览效果(交互式配置选择或 ?layout= URL 参数)
  • Runtime — 生产构建,单 HTML 嵌入 UE5(--layout=<名称>

快速开始

启动编辑器

pnpm dev:editor

启动后浏览器打开 http://localhost:3000,显示启动对话框。

启动对话框

首次启动时,对话框提供三个选项:

选项说明
新建配置创建空白布局,从零开始设计
打开配置configs/ 目录选择已发布配置或草稿
最近编辑快速继续编辑最近使用的布局

如果有最近文件,对话框会自动跳转到"最近编辑"页面。

基础流程

启动对话框 ──→ 编辑器 ──自动保存──→ .drafts/ ──发布──→ configs/ ──→ 预览 / 构建

界面布局

编辑器采用经典的三栏布局:

┌──────────────────────────────────────────────────────────────────┐
│  工具栏 (文件名 + 保存状态 | 导入 / 复制JSON / 保存 / 发布)      │
├────────┬──────────────────────────────┬──────────────────────────┤
│ 组件   │                              │  属性编辑                │
│ 面板   │      画布 (Grid Canvas)      │  - 组件信息              │
│        │                              │  - 位置信息              │
│ Button │   ┌──────┐  ┌───────┐       │  - 组件属性              │
│ Card   │   │Button│  │ Input │       │                          │
│ Input  │   └──────┘  └───────┘       │  选择组件后              │
│ Label  │                              │  编辑属性                │
│ Alert  │                              │                          │
├────────┴──────────────────────────────┴──────────────────────────┤
│  提示:选择一个组件以编辑属性                                      │
└──────────────────────────────────────────────────────────────────┘

左侧:组件面板

组件面板按分类列出所有可注册的组件。当前内置组件:

分类组件
表单Button, Input, Label
布局Card
反馈Alert

每个组件都可直接拖拽到画布上。拖拽时鼠标指针变为 grab 样式。

中间:画布

画布基于 react-grid-layout 实现,提供:

  • 拖拽移动 — 拖拽组件标题栏(⋮⋮ 手柄)移动位置
  • 尺寸调整 — 拖拽组件右下角调整宽高
  • 选中 — 单击组件,边框高亮显示
  • 右键菜单 — 右键组件弹出操作菜单

右侧:属性面板

选中画布上的组件后,属性面板显示:

  • 组件信息 — 组件类型名称和 ID
  • 位置信息 — X/Y 坐标和宽高(只读,由拖拽实时更新)
  • 组件属性 — 根据组件注册表动态生成的编辑表单

属性编辑示例

Button 组件属性:

属性类型说明
文字string按钮显示的文本
样式selectdefault / secondary / ghost / link / outline / destructive
尺寸selectsm / default / lg

Input 组件属性:

属性类型说明
占位文字string输入框占位符
类型selecttext / password / number
禁用boolean是否禁用输入框

Card 组件属性:

属性类型说明
标题string卡片标题文字
描述string卡片描述文字

右键菜单

在画布上右键单击组件,弹出上下文菜单:

操作说明
编辑属性关闭菜单,激活右侧属性面板
替换组件悬停展开子菜单,选择要替换成的组件类型(保留位置,重置属性为默认值)
复制组件在画布底部创建一个同类型的新组件
删除组件从画布和组件列表中移除

保存与导出

编辑器采用混合保存策略:每次编辑操作自动保存草稿,手动发布后供预览和构建使用。

自动保存(草稿)

每次编辑操作(拖拽、调整大小、修改属性)触发 500ms 防抖自动保存。草稿存储在 configs/.drafts/{名称}.layout.json参与预览和构建。

工具栏显示当前的保存状态:

指示器状态
🟡 保存中...正在保存
🟢 已保存上次保存成功
🔴 保存失败保存出错

发布

点击"发布"按钮,将当前草稿发布到 configs/{名称}.layout.json。发布的配置可供预览和构建使用。

手动保存

点击"保存"按钮,立即触发一次手动保存到草稿(与自动保存效果相同)。

复制 JSON

将当前布局的 JSON 字符串复制到剪贴板,方便快速粘贴到 URL 参数中用于预览。

导入 JSON

点击"导入",选择之前保存的 .json 文件,恢复编辑状态。

注意: 导入会覆盖当前编辑的所有内容,请先保存当前布局。


完整工作流程示例

步骤 1:启动编辑器

pnpm dev:editor

启动对话框出现,选择新建配置,输入名称(例如 dashboard),点击创建。

步骤 2:编辑布局

  1. 从左侧拖入一个 Button 到画布
  2. 再拖入一个 Card,放在 Button 下方
  3. 单击 Button 选中,在右侧将"文字"改为"确认提交","样式"改为"danger"
  4. 拖拽 Card 右下角调整宽度到 6 列
  5. 右键 Button → 复制组件

每次修改后自动保存,工具栏显示 🟢 已保存。

步骤 3:发布

点击工具栏"发布"按钮,将草稿发布为正式配置:configs/dashboard.layout.json

步骤 4:预览

pnpm dev:preview

配置选择器出现 — 点击你的布局即可预览。也可通过 URL 直接指定:

http://localhost:3000?layout=dashboard

步骤 5:生产构建

pnpm build --layout=dashboard

构建产物位于 dist/merged/index.html,为单文件 HTML,可直接在 UE5 Web 浏览器控件中加载。


扩展组件

编辑器的组件面板通过 src/layout/registry.ts 中的注册表管理。添加新组件只需三步:

1. 导入组件

import { YourComponent } from '@/components/ui/your-component'

2. 注册组件元信息

const registry: ComponentMeta[] = [
  // ... 已有组件
  {
    type: 'YourComponent',       // 显示名称
    component: YourComponent,     // React 组件
    defaultProps: { foo: 'bar' }, // 默认属性
    propsSchema: [                // 属性编辑表单定义
      { name: 'foo', type: 'string', label: '属性名', defaultValue: 'bar' },
    ],
    category: '自定义分类',       // 在组件面板中的分组
  },
]

3. PropDef 类型说明

interface PropDef {
  name: string                    // 属性名(对应组件 props 的 key)
  type: 'string' | 'number' | 'boolean' | 'select'
  label: string                   // 属性面板中显示的标签文字
  options?: { label: string; value: any }[]  // select 类型的选项
  defaultValue?: any              // 默认值
}

内置 shadcn 组件

当前 5 个内置组件均来自 shadcn/ui:ButtonCardInputLabelAlert。可通过相同方式扩展任意 React 组件。


常见问题

拖拽无效?

确保点击的是组件标题栏(⋮⋮ 手柄区域),dragConfig.handle: '.drag-handle' 限制了只有 .drag-handle 元素才能触发拖拽。

布局不响应?

画布当前固定在 lg 断点(≥1200px)下编辑。在浏览器中缩小窗口会自动切换断点,但编辑器目前只编辑 lg 布局。

生产构建报错?

使用 pnpm build --layout=<名称> 指定要构建的已发布配置。布局名称必须匹配 configs/ 中的文件名(例如 configs/dashboard.layout.json--layout=dashboard)。如果未指定布局且未找到最近文件,构建会报错并提示帮助信息。

自动保存不工作?

自动保存需要通过启动对话框打开或创建布局后才能使用。必须设置 currentFileName 才能保存草稿。检查工具栏的保存状态指示器。