12 KiB
12 KiB
Vue页面可视化设计器 - 项目设计文档
1. 项目概述
本项目是一个基于 Vue3 + TypeScript + Element Plus 的可视化页面设计器,通过拖拽操作直接编辑真实的Vue源文件,实现低代码页面快速构建。
1.1 核心特性
| 特性 | 描述 |
|---|---|
| 直接解析Vue文件 | 动态渲染真实的.vue页面 |
| 源码级修改 | 拖拽操作直接修改Vue源文件 |
| 智能层级选择 | 键盘方向键切换嵌套元素层级 |
| 元数据编辑 | 可视化编辑组件属性 |
| 多视图联动 | 设计中心、结构树、元数据面板同步选中 |
| 热更新 | 修改后自动刷新预览 |
1.2 技术架构
┌─────────────────────────────────────────────────────────────────┐
│ 前端应用 (Vue3 + Vite) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 页面管理 │ │设计组件列│ │ 设计中心 │ │ 元数据 │ │
│ │ │ │表 │ │ │ │ 编辑器 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Pinia 状态管理 + 插件系统 │ │
│ │ dragStore │ interactionStore │ designStore │ vueFileStore│ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│ HTTP API
▼
┌─────────────────────────────────────────────────────────────────┐
│ 后端服务 (Node.js + Express) │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ templateService - Vue模板AST解析与修改 │ │
│ │ @vue/compiler-sfc + @vue/compiler-dom │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│ 文件操作
▼
┌─────────────────────────────────────────────────────────────────┐
│ Vue源文件 (src/views/*.vue) │
└─────────────────────────────────────────────────────────────────┘
2. 核心模块设计
2.1 前端模块
2.1.1 设计中心 (DesignCenter)
职责:动态渲染选中的Vue页面,注入交互事件
核心组件:
index.vue- 主容器,动态加载Vue页面组件InteractiveWrapper.vue- 交互包装器,注入事件监听DropZone.vue- 拖放区域指示器DragPreview.vue- 拖拽跟随预览
交互事件注入流程:
// 1. 动态渲染页面组件
<component :is="selectedPageComponent" />
// 2. 挂载后扫描DOM,注入事件
const injectInteractionEvents = () => {
document.querySelectorAll('.el-row, .el-col').forEach(el => {
const path = generateElementPath(el) // 生成结构化路径
bindElementEvents(el, type, path) // 绑定交互事件
})
}
// 3. MutationObserver监听DOM变化,动态注入
observer.observe(container, { childList: true, subtree: true })
2.1.2 结构树 (TreeViewer)
职责:展示页面的el-row/el-col结构,支持选中和删除
功能:
- 树形展示页面结构
- 点击节点选中对应元素
- 拖拽节点调整顺序
- 右键菜单/删除图标/Del键删除
2.1.3 元数据编辑器 (DataTable)
职责:展示和编辑选中组件的属性
支持的属性类型:
number- 数字输入(如span宽度)text- 文本输入(如placeholder)select- 下拉选择(如size尺寸)boolean- 开关切换(如stripe斑马纹)color- 颜色选择器
2.1.4 插件系统 (plugins/)
dragStore - 拖拽状态管理
interface DragStore {
// 状态
isDragging: boolean
dragPhase: 'source' | 'target' // 两阶段拖拽
dragSource: DragSource | null
hierarchyNodes: HierarchyNode[] // 层级节点列表
selectedHierarchyIndex: number // 当前选中层级
hoverDirection: Direction | null
// 方法
startDragFromCanvas(path, type, element) // 开始画布内拖拽
startDragFromComponentList(id, name, template) // 开始组件列表拖拽
enterTargetPhase(element) // 进入目标选择阶段
selectParentLevel() // 选择父级(↑键)
selectChildLevel() // 选择子级(↓键)
confirmDrop(pagePath) // 确认拖放
}
interactionStore - 交互事件钩子
interface InteractionStore {
hoverTarget: InteractionTarget | null
selectedTarget: InteractionTarget | null
onHover(target)
onClick(target)
onLeave()
}
2.2 后端模块
2.2.1 templateService
职责:解析Vue文件,执行结构修改
核心函数:
| 函数 | 功能 |
|---|---|
moveElement(vueContent, options) |
移动元素到新位置 |
insertElement(vueContent, options) |
插入新元素 |
deleteElement(vueContent, elementPath) |
删除元素 |
parseElementTree(vueContent) |
解析页面结构树 |
parseComponentProps(vueContent, path) |
获取组件属性 |
updateComponentProps(vueContent, path, updates) |
更新组件属性 |
技术实现:
// 使用 @vue/compiler-sfc 解析Vue文件
import { parse as parseSFC } from '@vue/compiler-sfc'
// 使用 @vue/compiler-dom 解析template获取AST
import { parse as parseTemplate } from '@vue/compiler-dom'
// 通过AST定位元素,使用字符串操作修改(保持原始格式)
3. 数据结构设计
3.1 结构化路径
格式:r{n}c{m}r{x}c{y}...
| 前缀 | 含义 |
|---|---|
| r | el-row |
| c | el-col |
| 数字 | 同级元素中的索引(从1开始) |
示例:r1c2r1 = 第1个row → 第2个col → 第1个row
3.2 设计组件配置
{
"id": "TextInput",
"name": "输入框",
"icon": "✏️",
"description": "用于输入文本内容的表单组件",
"defaultSpan": 12,
"metadata": {
"span": {
"label": "宽度",
"type": "number",
"min": 1,
"max": 24,
"target": "el-col",
"attr": ":span"
},
"placeholder": {
"label": "占位符",
"type": "text",
"target": "el-input",
"attr": "placeholder"
}
}
}
3.3 设计组件模板
<el-col :span="12">
<div class="design-component design-text-input" data-component="输入框">
<el-form-item label="文本输入">
<el-input v-model="inputValue" placeholder="请输入内容"></el-input>
</el-form-item>
</div>
</el-col>
关键点:
- 外层必须是
el-col - 内层
div必须有data-component属性标识组件类型 - 使用
class="design-component"标识设计组件
4. API设计
4.1 元素操作API
移动元素
POST /api/move-element
Body: {
"pagePath": "D:/workspace/.../TestPage1.vue",
"source": {
"type": "canvas-element",
"path": "r1c1",
"elementType": "ec"
},
"targetPath": "r1c2",
"targetType": "ec",
"direction": "right" // top|bottom|left|right|inside
}
插入元素
POST /api/insert-element
Body: {
"pagePath": "...",
"templateContent": "<el-col :span=\"12\">...</el-col>",
"targetPath": "r1c1",
"direction": "right"
}
删除元素
POST /api/delete-element
Body: {
"pagePath": "...",
"elementPath": "r1c2"
}
4.2 属性操作API
获取组件属性
GET /api/component-props?pagePath=...&elementPath=r1c1
Response: {
"success": true,
"componentId": "输入框",
"props": {
"span": 12,
"el-input:placeholder": "请输入"
}
}
更新组件属性
POST /api/update-props
Body: {
"pagePath": "...",
"elementPath": "r1c1",
"updates": {
"span": 8,
"el-input:placeholder": "新占位符"
}
}
4.3 结构查询API
获取页面结构树
GET /api/element-tree?pagePath=...
Response: {
"success": true,
"tree": [
{
"type": "row",
"path": "r1",
"label": "el-row",
"children": [
{
"type": "col",
"path": "r1c1",
"componentName": "输入框",
"children": []
}
]
}
]
}
5. 交互设计
5.1 拖拽流程
1. 用户开始拖拽(组件列表/画布元素)
↓
2. 进入源选择阶段,收集层级节点
↓
3. 移动到目标位置,进入目标选择阶段
↓
4. 显示DropZone(上/下/左/右/放入)
↓
5. 用户点击方向确认拖放
↓
6. 调用后端API修改源文件
↓
7. 触发vue-template-updated事件
↓
8. 前端刷新页面和结构树
5.2 层级选择
当鼠标悬停在嵌套元素上时(如r1c1r1c1):
- 默认选中:最深层级(r1c1r1c1)
- ↑键:切换到父级(r1c1r1 → r1c1 → r1)
- ↓键:切换到子级
- Esc:取消拖拽
5.3 多视图联动
- 点击设计中心元素 → 结构树高亮 + 元数据面板更新
- 点击结构树节点 → 设计中心高亮 + 元数据面板更新
- 元数据面板修改 → 源文件更新 → 设计中心刷新
6. 扩展指南
6.1 添加设计组件
- 在
src/fauto/designComponents/创建目录 - 添加
index.json(配置+元数据schema) - 添加
template.html(组件模板) - 自动在组件列表显示
6.2 添加物料组件
- 在
src/fauto/materials/创建目录 - 添加
index.vue(组件实现) - 添加
index.json(配置信息) - 在
materials/index.ts注册
6.3 扩展元数据类型
在 designStore.ts 的 MetadataField 接口添加新类型,并在 DataTable/index.vue 添加对应的编辑控件。
7. 技术规范
7.1 Vue页面规范
<template>
<!-- 第一层级必须且只能有一个el-row -->
<el-row :gutter="20">
<el-col :span="24">
<!-- 设计组件必须有data-component属性 -->
<div class="design-component" data-component="组件名">
<!-- 组件内容 -->
</div>
</el-col>
</el-row>
</template>
7.2 代码规范
- TypeScript 严格模式
- Composition API 组织代码
- Props 必须定义类型
- 样式使用 scoped
- 插件代码放
fauto/plugins/
8. 版本信息
- 前端框架: Vue 3.5.24
- 构建工具: Vite 7.3.0
- 状态管理: Pinia 3.0.4
- UI框架: Element Plus
- 后端运行时: Node.js
- 模板解析: @vue/compiler-sfc, @vue/compiler-dom
文档更新时间:2026-01-20