306 lines
8.8 KiB
Markdown
306 lines
8.8 KiB
Markdown
# Vue页面可视化设计器 - 项目上下文
|
||
|
||
> **用途**:用于在新环境快速恢复 AI 协作上下文
|
||
> **更新时间**:2025-12-22
|
||
> **项目路径**:`d:/workspace/fauto-design/draggable-panels`
|
||
|
||
---
|
||
|
||
## 📋 项目概述
|
||
|
||
这是一个基于 **Vue3 + TypeScript + Vite + Element Plus** 的**可视化页面设计器**,通过拖拽操作直接编辑真实的Vue页面文件。
|
||
|
||
### 核心特性
|
||
|
||
1. **直接解析Vue文件** - 动态扫描并渲染`src/views`下的页面
|
||
2. **拖拽式设计** - 将设计组件拖拽到页面的el-row/el-col上
|
||
3. **非侵入式交互** - 通过注入方式绑定事件,不修改页面代码
|
||
4. **智能层级选择** - 键盘方向键切换嵌套元素层级
|
||
5. **实时视觉反馈** - 拖拽预览 + 拖放区域显示(上/下/左/右)
|
||
|
||
---
|
||
|
||
## 🏗️ 项目结构
|
||
|
||
```
|
||
draggable-panels/
|
||
├── src/
|
||
│ ├── fauto/ # 🔥 设计器核心代码
|
||
│ │ ├── Designer.vue # 设计器主入口
|
||
│ │ │
|
||
│ │ ├── components/ # 基础UI组件
|
||
│ │ │ ├── Header.vue # 顶部菜单栏
|
||
│ │ │ ├── Footer.vue # 底部状态栏(显示拖拽状态)
|
||
│ │ │ ├── MainLayout.vue # 三栏布局容器
|
||
│ │ │ ├── Panel.vue # 面板容器
|
||
│ │ │ └── Resizer.vue # 面板分隔器
|
||
│ │ │
|
||
│ │ ├── materials/ # 🎁 物料组件系统
|
||
│ │ │ ├── PageManagement/ # 页面管理(树形选择Vue文件)
|
||
│ │ │ ├── DesignComponentList/ # 设计组件列表
|
||
│ │ │ └── DesignCenter/ # 设计中心(动态渲染页面)
|
||
│ │ │ ├── index.vue # 主组件
|
||
│ │ │ ├── InteractiveWrapper.vue # 交互包装器(注入事件)
|
||
│ │ │ ├── DropZone.vue # 拖放区域指示器
|
||
│ │ │ └── DragPreview.vue # 拖拽预览
|
||
│ │ │
|
||
│ │ ├── designComponents/ # 🎨 设计组件库
|
||
│ │ │ ├── TextInput/ # 文本输入框
|
||
│ │ │ ├── RadioSelect/ # 单选器
|
||
│ │ │ └── GridTable/ # 表格
|
||
│ │ │
|
||
│ │ ├── plugins/ # 🔌 插件系统(核心功能)
|
||
│ │ │ ├── index.ts # 统一导出
|
||
│ │ │ ├── interactionStore.ts # 全局交互事件钩子
|
||
│ │ │ ├── dragStore.ts # 拖拽状态管理(层级选择)
|
||
│ │ │ └── pathUtils.ts # 结构化路径工具
|
||
│ │ │
|
||
│ │ ├── stores/ # 🗄️ Pinia状态管理
|
||
│ │ │ ├── panelStore.ts # 面板布局状态
|
||
│ │ │ ├── designStore.ts # 设计组件元数据
|
||
│ │ │ └── vueFileStore.ts # Vue文件选择状态
|
||
│ │ │
|
||
│ │ └── types/ # 📝 类型定义
|
||
│ │
|
||
│ ├── views/ # 📄 示例页面
|
||
│ │ ├── TestPage1.vue # 测试页面1
|
||
│ │ ├── TestPage2.vue # 测试页面2
|
||
│ │ ├── user/Profile.vue # 用户资料页
|
||
│ │ └── dashboard/Overview.vue # 仪表板
|
||
│ │
|
||
│ ├── router.ts # 路由配置
|
||
│ ├── main.ts # 应用入口
|
||
│ ├── App.vue # 根组件
|
||
│ └── style.css # 全局样式
|
||
│
|
||
└── vite.config.ts # Vite配置
|
||
```
|
||
|
||
---
|
||
|
||
## 🔑 核心技术要点
|
||
|
||
### 1. **Vue页面规范** ⭐
|
||
|
||
**强制规则**:template的第一层级**有且仅有一个el-row**
|
||
|
||
**示例**:
|
||
```vue
|
||
<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>
|
||
```
|
||
|
||
**目的**:保证布局可解析性,方便自动生成结构化路径ID
|
||
|
||
### 2. **结构化路径ID** ⭐
|
||
|
||
**格式**:`r{n}c{m}r{x}c{y}...`
|
||
- `r`: el-row
|
||
- `c`: el-col
|
||
- 数字:同级索引(从1开始)
|
||
|
||
**示例**:`r1c2r1c3` 表示:
|
||
- 第1个el-row → 第2个el-col → 第1个el-row → 第3个el-col
|
||
|
||
**实现**:`fauto/plugins/pathUtils.ts`
|
||
|
||
### 3. **交互事件注入** ⭐
|
||
|
||
**InteractiveWrapper.vue** 核心流程:
|
||
|
||
```typescript
|
||
// 1. 动态渲染组件
|
||
<component :is="selectedPageComponent" />
|
||
|
||
// 2. 挂载后扫描DOM
|
||
const injectInteractionEvents = () => {
|
||
const rows = containerRef.value.querySelectorAll('.el-row')
|
||
const cols = containerRef.value.querySelectorAll('.el-col')
|
||
|
||
// 3. 为每个元素注入事件
|
||
rows.forEach((row) => {
|
||
const path = generateElementPath(row) // 生成路径ID
|
||
bindElementEvents(row, 'er', path) // 绑定事件
|
||
})
|
||
}
|
||
|
||
// 4. 使用MutationObserver监听DOM变化
|
||
observer.observe(containerRef.value, { childList: true, subtree: true })
|
||
```
|
||
|
||
### 4. **层级选择机制** ⭐
|
||
|
||
**核心思想**:当鼠标悬停在嵌套元素上时(如`r1c1r1`),会同时触发`r1c1r1`、`r1c1`、`r1`三个层级。
|
||
|
||
**解决方案**(`dragStore.ts`):
|
||
|
||
```typescript
|
||
// 1. 收集所有层级节点
|
||
const updateHierarchy = (element: HTMLElement) => {
|
||
const nodes = []
|
||
let current = 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)
|
||
}
|
||
|
||
// 2. 键盘切换层级
|
||
↑ 键 → selectParentLevel() // 切换到父级
|
||
↓ 键 → selectChildLevel() // 切换到子级
|
||
Esc → cancelDrag() // 取消拖拽
|
||
```
|
||
|
||
### 5. **拖拽交互优化** ⭐
|
||
|
||
#### 禁用文本选择
|
||
```typescript
|
||
// DragPreview.vue
|
||
watch(() => dragStore.isDragging, (isDragging) => {
|
||
if (isDragging) {
|
||
document.body.classList.add('is-dragging')
|
||
} else {
|
||
document.body.classList.remove('is-dragging')
|
||
}
|
||
})
|
||
```
|
||
|
||
```css
|
||
/* style.css */
|
||
body.is-dragging {
|
||
user-select: none !important;
|
||
cursor: grabbing !important;
|
||
}
|
||
```
|
||
|
||
#### 拖拽预览效果
|
||
- 跟随鼠标的半透明卡片
|
||
- 显示组件图标 + 名称
|
||
- Teleport到body避免z-index问题
|
||
|
||
---
|
||
|
||
## 🎯 数据流图
|
||
|
||
```
|
||
1. 页面管理
|
||
用户点击Vue文件
|
||
↓
|
||
vueFileStore.selectFile(path)
|
||
↓
|
||
DesignCenter动态渲染该页面
|
||
↓
|
||
InteractiveWrapper注入交互事件
|
||
|
||
2. 拖拽交互
|
||
用户拖拽设计组件
|
||
↓
|
||
dragStore.startDragFromComponentList(id, name)
|
||
↓
|
||
鼠标移动到页面元素上
|
||
↓
|
||
dragStore.updateHierarchy(element) // 识别层级
|
||
↓
|
||
用户按↑↓键切换层级
|
||
↓
|
||
DropZone显示可放置区域(上/下/左/右)
|
||
↓
|
||
用户点击区域确认
|
||
↓
|
||
dragStore.confirmDrop()
|
||
↓
|
||
Footer显示拖放记录:TextInput → r1c1 左侧
|
||
```
|
||
|
||
---
|
||
|
||
## 🛠️ 快速开始
|
||
|
||
### 访问设计器
|
||
```
|
||
http://localhost:5173/draggable
|
||
```
|
||
|
||
### 使用流程
|
||
1. 点击左侧"页面管理"物料
|
||
2. 在树形列表中选择一个Vue页面
|
||
3. 页面在"设计中心"中渲染
|
||
4. 从"设计组件列表"拖拽组件
|
||
5. 移动到页面的el-row或el-col上
|
||
6. 使用↑↓键切换层级
|
||
7. 点击放置方向(上/下/左/右)
|
||
8. 查看Footer中的拖放记录
|
||
|
||
---
|
||
|
||
## 📝 开发规范
|
||
|
||
### 创建符合规范的Vue页面
|
||
```vue
|
||
<template>
|
||
<!-- 第一层级必须且只能有一个el-row -->
|
||
<el-row :gutter="20">
|
||
<el-col :span="24">
|
||
<!-- 内容 -->
|
||
</el-col>
|
||
</el-row>
|
||
</template>
|
||
```
|
||
|
||
### 添加设计组件
|
||
1. 在`src/fauto/designComponents/`下创建目录
|
||
2. 添加`index.vue`和`index.json`
|
||
3. 自动在列表中显示
|
||
|
||
### 插件开发
|
||
所有与页面解析、交互相关的代码放在`src/fauto/plugins/`
|
||
|
||
---
|
||
|
||
## 🚀 下一步计划
|
||
|
||
1. **拖放后修改源文件** - 通过API将操作写入.vue文件
|
||
2. **属性编辑器** - 展示和编辑组件属性
|
||
3. **热更新同步** - 修改后自动刷新页面
|
||
4. **撤销/重做** - 操作历史记录
|
||
|
||
---
|
||
|
||
## 📚 相关文档
|
||
|
||
- **详细设计文档**:`项目设计文档.md`
|
||
- **技术选型**:Vue3 + TypeScript + Element Plus + Pinia
|
||
- **构建工具**:Vite 7.3.0
|
||
|
||
---
|
||
|
||
## 💡 核心创新点
|
||
|
||
1. **非侵入式设计** - 无需修改Vue页面代码即可实现拖拽设计
|
||
2. **智能层级选择** - 自动识别嵌套结构,精准定位目标位置
|
||
3. **实时视觉反馈** - 完善的拖拽交互体验
|
||
4. **结构化路径** - 人类可读的元素定位方式
|
||
|
||
---
|
||
|
||
**最后更新**:2025-12-22
|
||
**AI协作建议**:优先阅读本文档的"核心技术要点"部分,理解项目的设计理念和实现方式
|