+```
+
+---
+
+**文档更新时间**:2026-01-20
diff --git a/README.md b/README.md
index ede3dc0..44b859a 100644
--- a/README.md
+++ b/README.md
@@ -1,166 +1,192 @@
# Fauto Design - Vue页面可视化设计器
-
-
-
-
-
+
+
+
+
-
- 🤖 本项目完全由 Qoder AI 开发,所有代码均为 AI 生成
-
+## 📖 简介
----
+**Fauto Design** 是一个基于 Vue3 的可视化页面设计器,通过拖拽操作直接编辑真实的Vue源文件,实现**所见即所得**的低代码开发体验。
-## 📖 项目简介
+### ✨ 特性
-**Fauto Design** 是一个基于 Vue3 的**可视化页面设计器**,通过拖拽操作直接编辑真实的 Vue 源文件。与传统低代码平台不同,本项目直接操作 `.vue` 文件,生成的代码即是最终代码。
-
-### ✨ 核心特性
-
-- 🎯 **直接编辑源码** - 拖拽操作实时修改 Vue 文件,所见即所得
-- 🖱️ **智能拖拽交互** - 两阶段拖拽:先选源元素层级,再选目标位置
-- ⌨️ **键盘层级选择** - ↑↓ 键切换嵌套元素层级,精准定位
-- 🔄 **跨类型拖放** - 支持 el-row/el-col 之间的灵活布局调整
-- 📝 **保持代码格式** - AST 解析 + 智能缩进,保持源码整洁
-
----
-
-## 🏗️ 技术架构
-
-```
-┌─────────────────────────────────────────────────┐
-│ 前端 (Vue3 + Vite) │
-│ ┌─────────────┐ ┌─────────────┐ ┌─────────┐ │
-│ │ PageManager │ │DesignCenter│ │DropZone │ │
-│ └─────────────┘ └─────────────┘ └─────────┘ │
-│ ↓ ↓ ↓ │
-│ ┌──────────────────────────────────────────┐ │
-│ │ dragStore (Pinia) │ │
-│ │ 两阶段拖拽 | 层级选择 | 跨类型判断 │ │
-│ └──────────────────────────────────────────┘ │
-└─────────────────────────────────────────────────┘
- │ HTTP
- ▼
-┌─────────────────────────────────────────────────┐
-│ 后端 (Node.js + Express) │
-│ ┌──────────────────────────────────────────┐ │
-│ │ templateService.js │ │
-│ │ @vue/compiler-sfc | AST解析 | 元素移动 │ │
-│ └──────────────────────────────────────────┘ │
-└─────────────────────────────────────────────────┘
- │
- ▼
- Vue 源文件 (*.vue)
-```
-
----
+- 🎯 **源码级编辑** - 拖拽操作直接修改Vue文件,支持热更新
+- 🔧 **非侵入式设计** - 无需修改业务页面代码即可实现可视化编辑
+- 🎨 **智能层级选择** - 键盘方向键精准切换嵌套元素层级
+- 📝 **元数据编辑** - 可视化修改组件属性(宽度、颜色、尺寸等)
+- 🌳 **结构树视图** - 清晰展示页面el-row/el-col结构
+- 🔄 **多视图联动** - 设计中心、结构树、属性面板实时同步
## 🚀 快速开始
### 环境要求
-- Node.js >= 18.x
-- npm >= 9.x
+- Node.js >= 18
+- npm >= 9
-### 安装依赖
+### 安装与运行
```bash
-# 前端
+# 克隆项目
+git clone
+cd fauto-design
+
+# 启动前端
cd draggable-panels
npm install
-
-# 后端
-cd vue-template-service
-npm install
-```
-
-### 启动服务
-
-```bash
-# 终端1 - 启动前端 (端口 5173)
-cd draggable-panels
npm run dev
-# 终端2 - 启动后端 (端口 3001)
+# 新开终端,启动后端
cd vue-template-service
+npm install
node src/index.js
```
-### 访问
+### 访问设计器
-打开浏览器访问:**http://localhost:5173/draggable**
+```
+http://localhost:5173/draggable
+```
----
+## 📸 功能演示
+
+### 基本操作流程
+
+1. **选择页面** - 在左侧"页面管理"中选择要编辑的Vue文件
+2. **拖拽组件** - 从"设计组件列表"拖拽组件到设计区域
+3. **调整位置** - 使用↑↓键切换层级,选择放置方向
+4. **编辑属性** - 点击组件,在"元数据"面板编辑属性
+5. **删除元素** - 右键菜单、Del键或点击删除图标
+
+### 键盘快捷键
+
+| 快捷键 | 功能 |
+|--------|------|
+| ↑ | 选择父级元素 |
+| ↓ | 选择子级元素 |
+| Delete | 删除选中元素 |
+| Esc | 取消拖拽操作 |
## 📁 项目结构
```
fauto-design/
-├── 项目上下文.md # AI 协作上下文文档
-├── 项目设计文档.md # 详细技术设计文档
-├── README.md # 本文件
-│
├── draggable-panels/ # 前端项目
-│ └── src/
-│ ├── fauto/ # 设计器核心
-│ │ ├── components/ # UI组件
-│ │ ├── materials/ # 物料组件
-│ │ ├── plugins/ # 核心插件 (dragStore等)
-│ │ └── stores/ # 状态管理
-│ └── views/ # 示例页面
+│ ├── src/
+│ │ ├── fauto/ # 设计器核心
+│ │ │ ├── components/ # UI组件
+│ │ │ ├── materials/ # 物料组件
+│ │ │ ├── designComponents/ # 设计组件库
+│ │ │ ├── plugins/ # 插件系统
+│ │ │ └── stores/ # 状态管理
+│ │ └── views/ # 示例页面
+│ └── vite.config.ts
│
└── vue-template-service/ # 后端服务
└── src/
+ ├── index.js # API入口
└── services/
- └── templateService.js # Vue模板解析修改
+ └── templateService.js # 模板解析
```
----
+## 🔌 设计组件
-## 🎮 使用方法
+内置设计组件:
-1. **选择页面** - 在左侧面板选择要编辑的 Vue 页面
-2. **开始拖拽** - 点击页面中的 el-row 或 el-col 元素
-3. **选择源层级** - 按 ↑↓ 键切换要移动的层级
-4. **移动到目标** - 拖动到目标元素上
-5. **选择目标层级** - 按 ↑↓ 键切换目标层级
-6. **确认位置** - 松开鼠标,选择放置方向(上/下/左/右/内部)
-7. **自动保存** - 源文件自动更新,页面热刷新
+| 组件 | 描述 |
+|------|------|
+| 输入框 (TextInput) | 文本输入表单组件 |
+| 单选器 (RadioSelect) | 单选按钮组组件 |
+| 表格 (GridTable) | 数据表格组件 |
----
+### 添加自定义设计组件
-## 🤖 关于 AI 开发
+1. 在 `draggable-panels/src/fauto/designComponents/` 创建目录
+2. 添加配置文件 `index.json`:
+```json
+{
+ "id": "MyComponent",
+ "name": "我的组件",
+ "icon": "🎯",
+ "description": "组件描述",
+ "defaultSpan": 12,
+ "metadata": {
+ "span": {
+ "label": "宽度",
+ "type": "number",
+ "min": 1,
+ "max": 24,
+ "target": "el-col",
+ "attr": ":span"
+ }
+ }
+}
+```
-本项目是一个 **AI 驱动开发**的实验性项目:
+3. 添加模板文件 `template.html`:
+```html
+
+
+
+
+
+```
-- **开发工具**:Qoder AI(AI 编程助手)
-- **代码生成**:100% 由 AI 生成
-- **人工参与**:需求描述、测试反馈、方向指导
+## 📋 Vue页面规范
-这证明了 AI 辅助开发在复杂前端项目中的可行性,包括:
-- 状态管理设计
-- 拖拽交互实现
-- AST 解析与修改
-- 多阶段工作流
+设计器要求Vue页面遵循以下结构:
----
+```vue
+
+
+
+
+
+
+
+
+
+
+
+```
-## 📄 相关文档
+## 🔗 API文档
-- [项目上下文.md](./项目上下文.md) - AI 协作快速恢复上下文
-- [项目设计文档.md](./项目设计文档.md) - 详细技术设计
+后端服务运行在 `http://localhost:3001`
----
+| 端点 | 方法 | 功能 |
+|------|------|------|
+| `/api/move-element` | POST | 移动元素 |
+| `/api/insert-element` | POST | 插入新元素 |
+| `/api/delete-element` | POST | 删除元素 |
+| `/api/element-tree` | GET | 获取页面结构 |
+| `/api/component-props` | GET | 获取组件属性 |
+| `/api/update-props` | POST | 更新组件属性 |
-## 📜 License
+## 📚 文档
+
+- [项目上下文](./项目上下文.md) - AI协作上下文
+- [项目设计文档](./项目设计文档.md) - 详细技术设计
+- [开发指南](./DEVELOPMENT.md) - 开发规范与扩展指南
+
+## 🛠️ 技术栈
+
+**前端**
+- Vue 3.5 (Composition API)
+- TypeScript
+- Vite 7.3
+- Pinia 3.0
+- Element Plus
+
+**后端**
+- Node.js
+- Express
+- @vue/compiler-sfc
+- @vue/compiler-dom
+
+## 📄 License
MIT License
-
----
-
-
- 🚀 Powered by Qoder AI
-
diff --git a/draggable-panels/README.md b/draggable-panels/README.md
new file mode 100644
index 0000000..c36a77a
--- /dev/null
+++ b/draggable-panels/README.md
@@ -0,0 +1,21 @@
+# Draggable Panels - 前端项目
+
+这是 Fauto Design 的前端项目,基于 Vue 3 + TypeScript + Vite 构建。
+
+## 快速开始
+
+```bash
+npm install
+npm run dev
+```
+
+访问:`http://localhost:5173/draggable`
+
+## 详细文档
+
+请参阅项目根目录的文档:
+
+- [README.md](../README.md) - 项目介绍
+- [项目上下文.md](../项目上下文.md) - AI协作上下文
+- [项目设计文档.md](../项目设计文档.md) - 技术设计
+- [DEVELOPMENT.md](../DEVELOPMENT.md) - 开发指南
diff --git a/项目上下文.md b/项目上下文.md
index 11e6b3c..d5dca58 100644
--- a/项目上下文.md
+++ b/项目上下文.md
@@ -1,6 +1,6 @@
# Vue页面可视化设计器 - 项目上下文
-> **用途**:AI 协作快速恢复上下文
+> **用途**:用于在新环境快速恢复 AI 协作上下文
> **更新时间**:2026-01-20
> **项目路径**:`d:/workspace/fauto-design`
@@ -8,15 +8,17 @@
## 📋 项目概述
-基于 **Vue3 + TypeScript + Vite + Element Plus** 的**可视化页面设计器**,通过拖拽操作直接编辑真实的Vue源文件。
+这是一个基于 **Vue3 + TypeScript + Vite + Element Plus** 的**可视化页面设计器**,通过拖拽操作直接编辑真实的Vue页面源文件。
### 核心特性
-1. **直接解析Vue文件** - 动态扫描并渲染 `src/views` 下的页面
-2. **拖拽式设计** - 将组件拖拽到页面的 el-row/el-col 上
-3. **两阶段拖拽** - 源选择阶段 → 目标选择阶段
-4. **智能层级选择** - 键盘 ↑↓ 切换嵌套元素层级
-5. **源码实时修改** - 后端服务解析AST并修改Vue文件
+1. **直接解析Vue文件** - 动态扫描并渲染`src/views`下的页面
+2. **拖拽式设计** - 将设计组件拖拽到页面,支持四个方向放置
+3. **源码级修改** - 拖拽操作直接修改Vue源文件,支持热更新
+4. **智能层级选择** - 键盘方向键切换嵌套元素层级
+5. **实时视觉反馈** - 拖拽预览 + 拖放区域显示
+6. **元数据编辑** - 点击组件可编辑属性(宽度、尺寸、颜色等)
+7. **多种删除方式** - 右键菜单、Del键、删除图标
---
@@ -25,152 +27,215 @@
```
fauto-design/
├── draggable-panels/ # 前端项目
-│ └── src/
-│ ├── fauto/ # 🔥 设计器核心
-│ │ ├── Designer.vue # 设计器主入口
-│ │ ├── components/ # 基础UI组件
-│ │ ├── materials/ # 物料组件系统
-│ │ │ ├── DesignCenter/ # 设计中心
-│ │ │ │ ├── InteractiveWrapper.vue # 交互注入器
-│ │ │ │ └── DropZone.vue # 拖放指示器
-│ │ │ ├── DesignComponentList/ # 设计组件列表
-│ │ │ └── PageManager/ # 页面管理
-│ │ ├── designComponents/ # 设计组件库
-│ │ ├── plugins/ # 🔌 核心插件
-│ │ │ ├── dragStore.ts # 拖拽状态管理
-│ │ │ ├── interactionStore.ts
-│ │ │ └── pathUtils.ts # 路径工具
-│ │ └── stores/ # Pinia状态
-│ └── views/ # 示例页面
+│ ├── src/
+│ │ ├── fauto/ # 🔥 设计器核心代码
+│ │ │ ├── Designer.vue # 设计器主入口
+│ │ │ │
+│ │ │ ├── components/ # 基础UI组件
+│ │ │ │ ├── Header.vue # 顶部菜单栏
+│ │ │ │ ├── Footer.vue # 底部状态栏
+│ │ │ │ ├── MainLayout.vue # 三栏布局容器
+│ │ │ │ ├── Panel.vue # 面板容器
+│ │ │ │ └── Resizer.vue # 面板分隔器
+│ │ │ │
+│ │ │ ├── materials/ # 🎁 物料组件系统
+│ │ │ │ ├── PageManager/ # 页面管理(树形文件选择)
+│ │ │ │ ├── DesignComponentList/ # 设计组件列表
+│ │ │ │ ├── DesignCenter/ # 设计中心(动态渲染页面)
+│ │ │ │ │ ├── index.vue
+│ │ │ │ │ ├── InteractiveWrapper.vue # 交互包装器
+│ │ │ │ │ ├── DropZone.vue # 拖放区域指示器
+│ │ │ │ │ └── DragPreview.vue # 拖拽预览
+│ │ │ │ ├── TreeViewer/ # 结构树(页面结构展示)
+│ │ │ │ └── DataTable/ # 元数据编辑器
+│ │ │ │
+│ │ │ ├── designComponents/ # 🎨 设计组件库
+│ │ │ │ ├── TextInput/ # 输入框
+│ │ │ │ │ ├── index.json # 组件配置+元数据schema
+│ │ │ │ │ └── template.html # 组件模板
+│ │ │ │ ├── RadioSelect/ # 单选器
+│ │ │ │ └── GridTable/ # 表格
+│ │ │ │
+│ │ │ ├── plugins/ # 🔌 插件系统
+│ │ │ │ ├── index.ts # 统一导出
+│ │ │ │ ├── interactionStore.ts # 交互事件钩子
+│ │ │ │ ├── dragStore.ts # 拖拽状态管理
+│ │ │ │ └── pathUtils.ts # 结构化路径工具
+│ │ │ │
+│ │ │ ├── stores/ # 🗄️ Pinia状态管理
+│ │ │ │ ├── panelStore.ts # 面板布局状态
+│ │ │ │ ├── designStore.ts # 设计组件元数据
+│ │ │ │ └── vueFileStore.ts# Vue文件选择状态
+│ │ │ │
+│ │ │ └── types/ # 📝 类型定义
+│ │ │
+│ │ └── views/ # 📄 示例页面
+│ │
+│ └── vite.config.ts
│
-└── vue-template-service/ # 后端服务(Node.js)
+└── vue-template-service/ # 🖥️ 后端服务
└── src/
- ├── index.js # Express API
+ ├── index.js # Express服务入口
└── services/
- └── templateService.js # Vue模板解析修改
+ └── templateService.js # Vue模板解析与修改服务
```
---
## 🔑 核心技术要点
-### 1. Vue页面规范 ⭐
+### 1. **两阶段拖拽机制** ⭐
-**强制规则**:template 第一层级**有且仅有一个 el-row**
-
-```vue
-
-
- 内容
-
-
- 嵌套内容
-
-
-
-
-```
-
-### 2. 结构化路径ID ⭐
-
-**格式**:`r{n}c{m}...`(r=row, c=col, 数字=索引从1开始)
-
-**示例**:`r1c2r1c3` = 第1个row → 第2个col → 第1个row → 第3个col
-
-### 3. 两阶段拖拽 ⭐⭐
-
-| 阶段 | 触发 | ↑↓键功能 | 拖放方向 |
-|------|------|----------|---------|
-| **源选择** | 点击元素 | 切换源层级 | 不显示 |
-| **目标选择** | 移到其他元素 | 切换目标层级 | 显示 |
+**第一阶段(源选择)**:鼠标按下开始,收集当前位置的层级节点
+**第二阶段(目标选择)**:移动到新位置,选择目标和方向
```typescript
-// dragStore.ts 核心状态
-dragPhase: 'source' | 'target'
-confirmedSource: { path, type, element }
+// dragStore.ts
+startDragFromCanvas(path, type, element) → 进入源选择阶段
+enterTargetPhase(element) → 进入目标选择阶段
+confirmDrop(pagePath) → 调用后端API执行移动
```
-### 4. 跨类型拖放 ⭐
+### 2. **结构化路径ID** ⭐
-- **同类型**:el-row→el-row 显示上/下,el-col→el-col 显示左/右
-- **跨类型**:el-row→el-col 或 el-col→el-row 显示"放入内部"(inside)
+**格式**:`r{n}c{m}r{x}c{y}...`
+- `r`: el-row
+- `c`: el-col
+- 数字:同级索引(从1开始)
-### 5. 后端模板服务 ⭐⭐
+**示例**:`r1c2r1c3` 表示:
+- 第1个el-row → 第2个el-col → 第1个el-row → 第3个el-col
-**API**:`POST http://localhost:3001/api/move-element`
+### 3. **设计组件标识** ⭐
+
+设计组件使用 `data-component` 属性标识类型:
+
+```html
+
+
+
+
+
+
+
+```
+
+### 4. **元数据Schema定义** ⭐
+
+设计组件的 index.json 定义可编辑属性:
```json
{
- "pagePath": "views/TestPage1.vue",
- "source": "r1c1",
- "target": "r1c2",
- "direction": "right" // top|bottom|left|right|inside
+ "id": "TextInput",
+ "name": "输入框",
+ "metadata": {
+ "span": { "label": "宽度", "type": "number", "min": 1, "max": 24, "target": "el-col", "attr": ":span" },
+ "label": { "label": "标签", "type": "text", "target": "el-form-item", "attr": "label" },
+ "placeholder": { "label": "占位符", "type": "text", "target": "el-input", "attr": "placeholder" }
+ }
}
```
-**技术栈**:
-- `@vue/compiler-sfc` - 解析Vue SFC
-- `@vue/compiler-dom` - 解析template AST
-- 字符串操作移动元素(保持原始格式)
+---
+
+## 🔗 后端API
+
+| 端点 | 方法 | 功能 |
+|------|------|------|
+| `/api/move-element` | POST | 移动元素(画布内拖拽) |
+| `/api/insert-element` | POST | 插入新元素(设计组件拖入) |
+| `/api/delete-element` | POST | 删除元素 |
+| `/api/element-tree` | GET | 获取页面结构树 |
+| `/api/component-props` | GET | 获取组件属性值 |
+| `/api/update-props` | POST | 更新组件属性值 |
---
-## 🎯 数据流
+## 🎯 数据流图
```
-用户点击元素开始拖拽
-↓
-dragStore.startDragFromCanvas() → 源选择阶段
-↓
-按↑↓键切换源层级
-↓
-移动到其他元素 → dragStore.enterTargetPhase() → 目标选择阶段
-↓
-按↑↓键切换目标层级,显示DropZone
-↓
-松开鼠标 → dragStore.confirmDrop()
-↓
-调用后端API → templateService.moveElement()
-↓
-修改Vue源文件 → 页面热更新
+┌─────────────────────────────────────────────────────────────────┐
+│ 用户操作 │
+└───────────────────────────┬─────────────────────────────────────┘
+ │
+ ┌───────────────────┼───────────────────┐
+ ▼ ▼ ▼
+┌───────────────┐ ┌───────────────┐ ┌───────────────┐
+│ 页面管理器 │ │ 设计组件列表 │ │ 设计中心 │
+│ (选择Vue文件) │ │ (拖拽组件) │ │ (编辑区域) │
+└───────┬───────┘ └───────┬───────┘ └───────┬───────┘
+ │ │ │
+ ▼ ▼ ▼
+┌───────────────────────────────────────────────────────────────┐
+│ Pinia 状态管理 │
+│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
+│ │ vueFileStore │ │ dragStore │ │ designStore │ │
+│ └──────────────┘ └──────────────┘ └──────────────┘ │
+└───────────────────────────┬───────────────────────────────────┘
+ │
+ ▼
+┌───────────────────────────────────────────────────────────────┐
+│ vue-template-service │
+│ (Node.js后端服务) │
+│ ┌─────────────────────────────────────────────────────────┐ │
+│ │ templateService.js - Vue模板AST解析与修改 │ │
+│ └─────────────────────────────────────────────────────────┘ │
+└───────────────────────────┬───────────────────────────────────┘
+ │
+ ▼
+┌───────────────────────────────────────────────────────────────┐
+│ Vue源文件 │
+│ (src/views/*.vue) │
+└───────────────────────────────────────────────────────────────┘
```
---
## 🛠️ 快速开始
+### 启动前端
```bash
-# 启动前端(端口5173)
cd draggable-panels
+npm install
npm run dev
-
-# 启动后端(端口3001)
-cd vue-template-service
-node src/index.js
+# 访问 http://localhost:5173/draggable
```
-**访问**:http://localhost:5173/draggable
+### 启动后端
+```bash
+cd vue-template-service
+npm install
+node src/index.js
+# 服务运行在 http://localhost:3001
+```
---
-## 📝 关键文件
+## 📝 Vue页面规范
-| 文件 | 用途 |
-|------|------|
-| `plugins/dragStore.ts` | 拖拽状态、两阶段逻辑、层级选择 |
-| `materials/DesignCenter/InteractiveWrapper.vue` | 交互注入、键盘监听、拖放确认 |
-| `materials/DesignCenter/DropZone.vue` | 拖放方向指示器 |
-| `vue-template-service/src/services/templateService.js` | AST解析、元素移动 |
+**强制规则**:template的第一层级**有且仅有一个el-row**
+
+```vue
+
+
+
+
+
+
+
+
+
+```
---
-## 💡 注意事项
+## 📚 相关文档
-1. 拖拽时会禁用文本选择(`user-select: none`)
-2. 使用全局鼠标事件获取悬停位置(避免 pointer-events 问题)
-3. 移动元素时保持相对缩进关系
-4. 前后端都需要运行才能完成拖放后的源码修改
+- **详细设计文档**:`项目设计文档.md`
+- **开发者指南**:`DEVELOPMENT.md`
+- **README**:`README.md`
---
-**最后更新**:2026-01-20
+**最后更新**:2026-01-20
+**AI协作建议**:优先阅读"核心技术要点"和"后端API"部分,理解系统的数据流和交互方式
diff --git a/项目设计文档.md b/项目设计文档.md
index 0c6f3cb..e17de41 100644
--- a/项目设计文档.md
+++ b/项目设计文档.md
@@ -1,366 +1,423 @@
# Vue页面可视化设计器 - 项目设计文档
-## 项目概述
+## 1. 项目概述
-本项目是一个基于 **Vite + Vue3 + TypeScript + Element Plus** 的可视化页面设计器,通过拖拽操作直接编辑真实的Vue源文件,实现低代码页面快速构建。
+本项目是一个基于 **Vue3 + TypeScript + Element Plus** 的可视化页面设计器,通过拖拽操作直接编辑真实的Vue源文件,实现低代码页面快速构建。
-## 技术架构
+### 1.1 核心特性
-### 技术栈
+| 特性 | 描述 |
+|------|------|
+| 直接解析Vue文件 | 动态渲染真实的.vue页面 |
+| 源码级修改 | 拖拽操作直接修改Vue源文件 |
+| 智能层级选择 | 键盘方向键切换嵌套元素层级 |
+| 元数据编辑 | 可视化编辑组件属性 |
+| 多视图联动 | 设计中心、结构树、元数据面板同步选中 |
+| 热更新 | 修改后自动刷新预览 |
-| 类别 | 技术 | 版本 |
-|------|------|------|
-| 构建工具 | Vite | 7.3.0 |
-| 前端框架 | Vue 3 (Composition API) | 3.5.24 |
-| UI组件库 | Element Plus | - |
-| 状态管理 | Pinia | 3.0.4 |
-| 类型系统 | TypeScript | - |
-| 后端运行时 | Node.js | 22.x |
-| 后端框架 | Express | - |
-| 模板解析 | @vue/compiler-sfc, @vue/compiler-dom | - |
-
-### 系统架构
+### 1.2 技术架构
```
-┌─────────────────────────────────────────────────────────────┐
-│ 前端 (Vue3 + Vite) │
-├─────────────────────────────────────────────────────────────┤
-│ Designer.vue │
-│ ├── Header (顶部菜单) │
-│ ├── MainLayout (三栏布局) │
-│ │ ├── 左侧面板 (PageManager, DesignComponentList) │
-│ │ ├── 中间面板 (DesignCenter + InteractiveWrapper) │
-│ │ └── 右侧面板 (属性编辑器 - 待实现) │
-│ └── Footer (状态栏 - 显示拖放记录) │
-├─────────────────────────────────────────────────────────────┤
-│ 状态管理层 │
-│ ├── dragStore.ts (拖拽状态、两阶段逻辑、层级选择) │
-│ ├── panelStore.ts (面板布局状态) │
-│ ├── designStore.ts (设计组件元数据) │
-│ └── vueFileStore.ts (Vue文件选择状态) │
-└─────────────────────────────────────────────────────────────┘
- │
+┌─────────────────────────────────────────────────────────────────┐
+│ 前端应用 (Vue3 + Vite) │
+│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
+│ │ 页面管理 │ │设计组件列│ │ 设计中心 │ │ 元数据 │ │
+│ │ │ │表 │ │ │ │ 编辑器 │ │
+│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
+│ │
+│ ┌──────────────────────────────────────────────────────────┐ │
+│ │ Pinia 状态管理 + 插件系统 │ │
+│ │ dragStore │ interactionStore │ designStore │ vueFileStore│ │
+│ └──────────────────────────────────────────────────────────┘ │
+└─────────────────────────────────────────────────────────────────┘
│ HTTP API
▼
-┌─────────────────────────────────────────────────────────────┐
-│ 后端 (Node.js + Express) │
-├─────────────────────────────────────────────────────────────┤
-│ API: POST /api/move-element │
-│ ├── 接收: { pagePath, source, target, direction } │
-│ └── 处理: templateService.moveElement() │
-├─────────────────────────────────────────────────────────────┤
-│ templateService.js │
-│ ├── parseSFC() - 解析Vue单文件组件 │
-│ ├── parseTemplate() - 解析template获取AST │
-│ ├── findElementByPath() - 根据路径定位元素 │
-│ ├── moveElement() - 移动元素(同级前后) │
-│ └── moveElementInside() - 移动元素(放入内部) │
-└─────────────────────────────────────────────────────────────┘
- │
+┌─────────────────────────────────────────────────────────────────┐
+│ 后端服务 (Node.js + Express) │
+│ ┌──────────────────────────────────────────────────────────┐ │
+│ │ templateService - Vue模板AST解析与修改 │ │
+│ │ @vue/compiler-sfc + @vue/compiler-dom │ │
+│ └──────────────────────────────────────────────────────────┘ │
+└─────────────────────────────────────────────────────────────────┘
+ │ 文件操作
▼
-┌─────────────────────────────────────────────────────────────┐
-│ Vue源文件 (src/views/) │
-└─────────────────────────────────────────────────────────────┘
+┌─────────────────────────────────────────────────────────────────┐
+│ Vue源文件 (src/views/*.vue) │
+└─────────────────────────────────────────────────────────────────┘
```
---
-## 核心功能模块
+## 2. 核心模块设计
-### 1. 拖拽状态管理 (dragStore.ts)
+### 2.1 前端模块
-#### 核心状态
+#### 2.1.1 设计中心 (DesignCenter)
+**职责**:动态渲染选中的Vue页面,注入交互事件
+
+**核心组件**:
+- `index.vue` - 主容器,动态加载Vue页面组件
+- `InteractiveWrapper.vue` - 交互包装器,注入事件监听
+- `DropZone.vue` - 拖放区域指示器
+- `DragPreview.vue` - 拖拽跟随预览
+
+**交互事件注入流程**:
```typescript
-// 拖拽阶段
-dragPhase: 'source' | 'target'
+// 1. 动态渲染页面组件
+
-// 拖拽源信息
-dragSource: {
- type: 'design-component' | 'canvas-element'
- componentId?: string
- componentName?: string
- path?: string
- elementType?: 'er' | 'ec'
-}
-
-// 已确定的源元素(进入目标阶段时保存)
-confirmedSource: {
- path: string
- type: 'er' | 'ec'
- element: HTMLElement
-}
-
-// 层级节点列表(从深到浅排序)
-hierarchyNodes: HierarchyNode[]
-
-// 当前选中的层级索引
-selectedHierarchyIndex: number
-
-// 拖放方向
-hoverDirection: 'top' | 'bottom' | 'left' | 'right' | 'inside' | null
-```
-
-#### 两阶段拖拽流程
-
-```
-源选择阶段 (source)
-├── 触发: startDragFromCanvas(path, type, element)
-├── 功能:
-│ ├── 构建当前元素的层级列表
-│ └── ↑↓键切换要拖拽的源层级
-├── 特点:
-│ ├── 不显示DropZone
-│ └── 松开鼠标取消拖拽
-└── 退出: 移动到其他元素 → enterTargetPhase()
-
-目标选择阶段 (target)
-├── 触发: enterTargetPhase(targetElement)
-├── 功能:
-│ ├── 保存确定的源元素到 confirmedSource
-│ ├── 构建目标元素的层级列表
-│ └── ↑↓键切换目标层级
-├── 特点:
-│ ├── 显示DropZone
-│ └── 根据源/目标类型显示方向
-└── 退出: 松开鼠标 → confirmDrop()
-```
-
-#### 跨类型拖放逻辑
-
-```typescript
-const isCrossTypeDrop = computed(() => {
- if (dragPhase.value !== 'target') return false
- if (!confirmedSource.value || !selectedNode.value) return false
-
- // 源类型与目标类型不同
- return confirmedSource.value.type !== selectedNode.value.type
-})
-
-// 跨类型时显示 'inside' 方向
-if (isCrossTypeDrop.value) {
- hoverDirection.value = 'inside'
-}
-```
-
-### 2. 交互注入器 (InteractiveWrapper.vue)
-
-#### 核心职责
-
-1. **动态渲染Vue页面** - 使用 `defineAsyncComponent` 加载选中的页面
-2. **注入交互事件** - 为所有 el-row/el-col 绑定事件
-3. **监听DOM变化** - 使用 MutationObserver 检测新元素
-4. **键盘事件处理** - ↑↓切换层级,Esc取消
-
-#### 事件绑定
-
-```typescript
-const bindElementEvents = (element, type, path) => {
- // 标记已绑定
- element.setAttribute('data-fauto-bindend', 'true')
- element.setAttribute('data-path', path)
- element.classList.add('fauto-interactive')
-
- // 悬停事件 - 进入目标阶段
- element.addEventListener('mouseenter', (e) => {
- if (dragStore.isDragging) {
- const sourcePath = dragStore.confirmedSource?.path || dragStore.dragSource?.path
- if (sourcePath && path !== sourcePath && !path.startsWith(sourcePath)) {
- dragStore.enterTargetPhase(element)
- }
- }
- })
-
- // 按下事件 - 开始拖拽
- element.addEventListener('mousedown', (e) => {
- if (!dragStore.isDragging) {
- dragStore.startDragFromCanvas(path, type, element)
- }
+// 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** - 拖拽状态管理
```typescript
-// 全局鼠标移动 - 更新拖放方向
-const handleGlobalMouseMove = (e) => {
- if (dragStore.isDragging && dragStore.dragPhase === 'target') {
- dragStore.updateDirectionFromMouse(e.clientX, e.clientY)
- }
-}
-
-// 全局鼠标松开 - 确认拖放
-const handleGlobalMouseUp = async () => {
- if (dragStore.isDragging && dragStore.dragPhase === 'target') {
- await dragStore.confirmDrop(vueFileStore.selectedFilePath)
- }
- dragStore.endDrag()
-}
-```
-
-### 3. 后端模板服务 (templateService.js)
-
-#### 路径解析
-
-```javascript
-// 解析路径: "r1c2r1" → [{type:'r',index:1}, {type:'c',index:2}, {type:'r',index:1}]
-function parsePath(pathStr) {
- const nodes = []
- const regex = /([rc])(\d+)/g
- let match
- while ((match = regex.exec(pathStr)) !== null) {
- nodes.push({ type: match[1], index: parseInt(match[2], 10) })
- }
- return nodes
-}
-```
-
-#### 元素定位
-
-```javascript
-function findElementByPath(ast, pathStr) {
- const pathNodes = parsePath(pathStr)
- let currentChildren = ast.children
- let currentNode = null
+interface DragStore {
+ // 状态
+ isDragging: boolean
+ dragPhase: 'source' | 'target' // 两阶段拖拽
+ dragSource: DragSource | null
+ hierarchyNodes: HierarchyNode[] // 层级节点列表
+ selectedHierarchyIndex: number // 当前选中层级
+ hoverDirection: Direction | null
- for (const pathNode of pathNodes) {
- const targetType = pathNode.type === 'r' ? 'el-row' : 'el-col'
- let count = 0
-
- for (const child of currentChildren) {
- if (child.type === 1 && child.tag === targetType) {
- count++
- if (count === pathNode.index) {
- currentNode = child
- currentChildren = child.children || []
- break
+ // 方法
+ startDragFromCanvas(path, type, element) // 开始画布内拖拽
+ startDragFromComponentList(id, name, template) // 开始组件列表拖拽
+ enterTargetPhase(element) // 进入目标选择阶段
+ selectParentLevel() // 选择父级(↑键)
+ selectChildLevel() // 选择子级(↓键)
+ confirmDrop(pagePath) // 确认拖放
+}
+```
+
+**interactionStore** - 交互事件钩子
+```typescript
+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)` | 更新组件属性 |
+
+**技术实现**:
+```javascript
+// 使用 @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 设计组件配置
+
+```json
+{
+ "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 设计组件模板
+
+```html
+
+
+
+
+
+
+
+```
+
+**关键点**:
+- 外层必须是 `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": "...",
+ "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": []
}
- }
+ ]
}
- }
- return currentNode
-}
-```
-
-#### 缩进调整算法
-
-```javascript
-function adjustIndentation(sourceText, targetIndent) {
- const lines = sourceText.split('\n')
-
- // 获取第一行的原始缩进
- const firstLineIndent = getIndentLevel(lines[0])
-
- // 计算缩进差值
- const indentDiff = targetIndent.length - firstLineIndent
-
- // 对每一行应用缩进差值(保持相对缩进)
- return lines.map(line => {
- if (!line.trim()) return ''
- const currentIndent = getIndentLevel(line)
- const newIndent = Math.max(0, currentIndent + indentDiff)
- return ' '.repeat(newIndent) + line.trimStart()
- }).join('\n')
-}
-```
-
-#### 元素移动(从后向前处理)
-
-```javascript
-// 关键:从后向前处理,避免偏移量错误
-if (deleteStart > insertPosition) {
- // 删除位置在后:先删除,再插入
- result = content.substring(0, deleteStart) + content.substring(deleteEnd)
- result = result.substring(0, insertPosition) + insertText + result.substring(insertPosition)
-} else {
- // 删除位置在前:先删除,调整插入位置
- const deletedLength = deleteEnd - deleteStart
- const adjustedInsertPos = insertPosition - deletedLength
- result = content.substring(0, deleteStart) + content.substring(deleteEnd)
- result = result.substring(0, adjustedInsertPos) + insertText + result.substring(adjustedInsertPos)
+ ]
}
```
---
-## 开发规范
+## 5. 交互设计
-### Vue页面结构规范
+### 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 添加设计组件
+
+1. 在 `src/fauto/designComponents/` 创建目录
+2. 添加 `index.json`(配置+元数据schema)
+3. 添加 `template.html`(组件模板)
+4. 自动在组件列表显示
+
+### 6.2 添加物料组件
+
+1. 在 `src/fauto/materials/` 创建目录
+2. 添加 `index.vue`(组件实现)
+3. 添加 `index.json`(配置信息)
+4. 在 `materials/index.ts` 注册
+
+### 6.3 扩展元数据类型
+
+在 `designStore.ts` 的 `MetadataField` 接口添加新类型,并在 `DataTable/index.vue` 添加对应的编辑控件。
+
+---
+
+## 7. 技术规范
+
+### 7.1 Vue页面规范
```vue
-
-
-
-
-
- 内容
-
-
-
- 嵌套内容
-
+
+
+
+
+
+
+
```
-### 代码规范
+### 7.2 代码规范
-1. 使用 TypeScript 严格模式
-2. 组件使用 Composition API
-3. Props 必须明确定义类型
-4. 样式使用 scoped 避免污染
-
-### 插件开发规范
-
-所有与页面交互相关的代码放在 `src/fauto/plugins/` 目录:
-- 状态管理类使用 Pinia defineStore
-- 工具函数单独文件导出
-- 统一通过 `index.ts` 导出
+- TypeScript 严格模式
+- Composition API 组织代码
+- Props 必须定义类型
+- 样式使用 scoped
+- 插件代码放 `fauto/plugins/`
---
-## API 接口
+## 8. 版本信息
-### 移动元素
-
-```
-POST /api/move-element
-
-Request:
-{
- "pagePath": "views/TestPage1.vue", // 相对于 src 的路径
- "source": "r1c1", // 源元素路径
- "target": "r1c2", // 目标元素路径
- "direction": "right" // top|bottom|left|right|inside
-}
-
-Response:
-{
- "success": true,
- "message": "元素移动成功"
-}
-```
+- **前端框架**: Vue 3.5.24
+- **构建工具**: Vite 7.3.0
+- **状态管理**: Pinia 3.0.4
+- **UI框架**: Element Plus
+- **后端运行时**: Node.js
+- **模板解析**: @vue/compiler-sfc, @vue/compiler-dom
---
-## 待实现功能
-
-1. **属性编辑器** - 展示和编辑选中组件的属性
-2. **撤销/重做** - 操作历史记录
-3. **设计组件拖入** - 从组件列表拖入新组件
-4. **预览模式** - 隐藏交互层预览最终效果
-5. **导出功能** - 导出设计结果
-
----
-
-## 已知问题
-
-1. 拖放操作有概率生成错误HTML结构(已基本修复)
-2. 复杂嵌套结构下缩进可能不完美
-
----
-
-**最后更新**:2026-01-20
+**文档更新时间**:2026-01-20