8.8 KiB
8.8 KiB
Vue页面可视化设计器项目文档
项目概述
本项目是一个基于 Vite + Vue3 + TypeScript 的可视化页面设计器,通过拖拽操作直接编辑真实的Vue页面文件,实现低代码页面快速构建。
核心特性
- 直接解析Vue文件 - 动态渲染真实的.vue页面
- 拖拽式设计 - 将设计组件拖拽到页面的el-row/el-col上
- 层级选择 - 通过键盘方向键切换嵌套元素的选中层级
- 实时预览 - 拖拽时显示放置方向(上/下/左/右)
- 结构化ID - 自动生成路径ID(如r1c2r1c1)
技术架构
核心技术栈
- 构建工具: Vite 7.3.0
- 前端框架: Vue 3.5.24 (Composition API)
- 状态管理: Pinia 3.0.4
- 类型系统: TypeScript
- 拖拽库: vuedraggable 4.1.0
- 样式: CSS Modules + Scoped Styles
项目结构
src/
├── fauto/ # 核心功能模块
│ ├── components/ # UI组件
│ │ ├── Header.vue # 顶部菜单栏
│ │ ├── Footer.vue # 底部状态栏(显示拖拽状态)
│ │ ├── MainLayout.vue # 主布局容器
│ │ ├── Panel.vue # 面板容器
│ │ └── Resizer.vue # 面板分隔器
│ ├── materials/ # 物料组件系统
│ │ ├── PageManagement/ # 页面管理(树形选择Vue文件)
│ │ ├── DesignComponentList/ # 设计组件列表
│ │ └── DesignCenter/ # 设计中心(动态渲染页面)
│ ├── designComponents/ # 设计组件库
│ │ ├── TextInput/ # 文本输入框
│ │ ├── RadioSelect/ # 单选器
│ │ └── GridTable/ # 表格组件
│ ├── plugins/ # 插件系统(交互事件、拖拽管理)
│ │ ├── interactionStore.ts # 全局交互钩子
│ │ ├── dragStore.ts # 拖拽状态管理
│ │ └── pathUtils.ts # 结构化路径工具
│ ├── stores/ # 状态管理
│ │ ├── panelStore.ts # 面板布局状态
│ │ ├── designStore.ts # 设计组件元数据
│ │ └── vueFileStore.ts # Vue文件选择状态
│ └── Designer.vue # 设计器主入口
├── views/ # 示例页面(测试用)
└── App.vue # 应用入口
核心功能模块
1. 页面管理系统
功能说明
- 动态扫描
src/views目录下的所有Vue文件 - 以树形结构展示文件夹和页面
- 点击选中后在设计中心动态渲染
技术实现
// 使用import.meta.glob动态扫描
const viewModules = import.meta.glob('../../../views/**/*.vue')
// 异步加载选中的组件
const loader = viewModules[selectedFilePath]
const component = defineAsyncComponent(loader)
2. 设计中心系统
InteractiveWrapper(交互包装器)
作用:为动态渲染的Vue页面注入交互事件
核心功能:
- 自动扫描页面中的el-row和el-col
- 为每个元素注入结构化路径ID(如
r1c2) - 绑定交互事件(悬停、点击、拖拽)
- 使用MutationObserver监听DOM变化
DropZone(拖放区域指示器)
作用:拖拽时显示可放置区域
显示规则:
- el-row:显示 上方 和 下方 两个区域
- el-col:显示 左侧 和 右侧 两个区域
DragPreview(拖拽预览)
跟随鼠标显示正在拖拽的内容,提供视觉反馈。
3. 插件系统 (fauto/plugins)
interactionStore(交互状态管理)
管理所有交互事件的全局状态:
hoverTarget: 当前悬停的元素selectedTarget: 当前选中的元素- 提供全局事件钩子(hover, click, longpress, drag, release)
dragStore(拖拽状态管理)
管理拖拽操作的复杂状态:
核心状态:
dragSource: 拖拽源(设计组件/画布元素)hierarchyNodes: 当前悬停位置的所有层级节点selectedHierarchyIndex: 当前选中的层级索引hoverDirection: 当前悬停的拖放方向lastDropRecord: 最后一次拖放记录
层级选择机制:
- 鼠标悬停在嵌套元素上时,自动识别所有父级节点
- 默认选中最深层级
- ↑键:切换到父级
- ↓键:切换到子级
- Esc键:取消拖拽
pathUtils(路径工具)
生成和解析结构化路径ID:
路径格式:r{n}c{m}r{x}c{y}...
r: el-rowc: el-col- 数字:在同级元素中的索引(从1开始)
示例:r1c2r1c3 表示:
- 第1个el-row
- 的第2个el-col
- 内的第1个el-row
- 内的第3个el-col
状态管理设计
PanelStore(面板状态)
管理整个应用的布局和物料组件状态:
layout: 三区域面板配置materialStates: 物料组件状态独立存储- 提供 Tab 操作 API(添加、关闭、移动、激活)
DesignStore(设计组件元数据)
管理设计组件的元数据:
componentMetas: 设计组件元数据列表loadComponentMetas(): 动态扫描设计组件目录getComponentMeta(): 获取指定组件的元数据
VueFileStore(Vue文件状态)
管理页面管理的选中状态:
selectedFilePath: 当前选中的文件路径selectedFileName: 当前选中的文件名selectFile(): 选中指定文件
InteractionStore / DragStore
见插件系统部分
实现细节
1. Vue页面规范
强制规则:template的第一层级有且仅有一个el-row
目的:保证布局可解析性,方便自动生成结构化路径
示例:
<template>
<el-row :gutter="20">
<el-col :span="12">
<div class="design-component">左侧内容</div>
</el-col>
<el-col :span="12">
<el-row :gutter="10">
<el-col :span="24">
<div class="design-component">标题</div>
</el-col>
</el-row>
</el-col>
</el-row>
</template>
2. 拖拽交互优化
禁用文本选择
拖拽时给body添加is-dragging类,设置user-select: none
拖拽预览效果
DragPreview组件跟随鼠标显示:
- 组件图标 + 名称
- 动画效果(缩放 + 淡入)
- Teleport到body,避免z-index问题
3. 层级选择实现
// 递归遍历DOM生成层级节点
const updateHierarchy = (element: HTMLElement) => {
const nodes: HierarchyNode[] = []
let current: HTMLElement | null = element
while (current) {
if (current.classList.contains('el-row') ||
current.classList.contains('el-col')) {
nodes.push({ path, type, element, depth })
}
current = current.parentElement
}
// 按深度排序,最深的在前
nodes.sort((a, b) => b.depth - a.depth)
}
4. 性能优化
- 使用
defineAsyncComponent异步加载页面 - 使用
MutationObserver监听DOM变化 - 防止重复绑定(
data-fauto-bindend属性) - 使用
computed缓存派生数据
API 设计
配置管理 API
GET /api/config # 获取布局配置
POST /api/config # 保存布局配置
GET /api/material-states # 获取物料组件状态
POST /api/material-states # 保存物料组件状态
设计系统 API
GET /api/design-components # 获取设计组件元数据
GET /api/design-state # 获取设计中心状态
POST /api/design-state # 保存设计中心状态
开发规范
Vue页面结构规范
- template第一层级有且仅有一个el-row
- el-row内只能包含el-col或div(设计组件)
- div使用class="design-component"标识
代码规范
- 使用 TypeScript 严格模式
- 组件 Props 必须明确定义类型
- 使用 Composition API 组织代码逻辑
- 样式使用 scoped 避免全局污染
组件开发规范
- 遵循物料组件标准化规范
- 每个组件包含
index.vue和index.json - 插件相关代码放在
fauto/plugins目录
状态管理规范
- 使用 Pinia 进行全局状态管理
- 状态变更必须通过 Store 的方法
- 复杂状态逻辑封装在 Store 内部
扩展性设计
新增设计组件
- 在
designComponents/目录下创建组件文件夹 - 实现
index.vue和index.json - 自动在 DesignComponentList 中显示
功能扩展
- 拖放后修改源文件 - 通过API将拖放操作写入.vue文件
- 属性编辑器 - 展示和编辑设计组件属性
- 热更新同步 - 修改后自动刷新页面
总结
本项目实现了一个完整的Vue页面可视化设计器,通过直接解析和编辑真实的Vue文件,实现了低代码的页面构建方式。
核心亮点:
- 非侵入式设计 - 通过注入式交互,无需修改Vue页面代码
- 智能层级选择 - 自动识别嵌套结构,键盘切换层级
- 实时视觉反馈 - 拖拽预览 + 拖放区域指示
- 结构化路径 - 自动生成可读的元素ID