Files
fauto-design/draggable-panels/PROJECT_CONTEXT.md
2025-12-22 23:20:40 +08:00

8.8 KiB
Raw Blame History

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

示例

<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 核心流程:

// 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),会同时触发r1c1r1r1c1r1三个层级。

解决方案dragStore.ts

// 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. 拖拽交互优化

禁用文本选择

// DragPreview.vue
watch(() => dragStore.isDragging, (isDragging) => {
  if (isDragging) {
    document.body.classList.add('is-dragging')
  } else {
    document.body.classList.remove('is-dragging')
  }
})
/* 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页面

<template>
  <!-- 第一层级必须且只能有一个el-row -->
  <el-row :gutter="20">
    <el-col :span="24">
      <!-- 内容 -->
    </el-col>
  </el-row>
</template>

添加设计组件

  1. src/fauto/designComponents/下创建目录
  2. 添加index.vueindex.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协作建议:优先阅读本文档的"核心技术要点"部分,理解项目的设计理念和实现方式