Files
fauto-design/draggable-panels/项目设计文档.md
2025-12-22 23:20:40 +08:00

8.8 KiB
Raw Blame History

Vue页面可视化设计器项目文档

项目概述

本项目是一个基于 Vite + Vue3 + TypeScript 的可视化页面设计器通过拖拽操作直接编辑真实的Vue页面文件实现低代码页面快速构建。

核心特性

  1. 直接解析Vue文件 - 动态渲染真实的.vue页面
  2. 拖拽式设计 - 将设计组件拖拽到页面的el-row/el-col上
  3. 层级选择 - 通过键盘方向键切换嵌套元素的选中层级
  4. 实时预览 - 拖拽时显示放置方向(上/下/左/右)
  5. 结构化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页面注入交互事件

核心功能

  1. 自动扫描页面中的el-row和el-col
  2. 为每个元素注入结构化路径IDr1c2
  3. 绑定交互事件(悬停、点击、拖拽)
  4. 使用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-row
  • c: 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(): 获取指定组件的元数据

VueFileStoreVue文件状态

管理页面管理的选中状态:

  • 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页面结构规范

  1. template第一层级有且仅有一个el-row
  2. el-row内只能包含el-col或div设计组件
  3. div使用class="design-component"标识

代码规范

  1. 使用 TypeScript 严格模式
  2. 组件 Props 必须明确定义类型
  3. 使用 Composition API 组织代码逻辑
  4. 样式使用 scoped 避免全局污染

组件开发规范

  1. 遵循物料组件标准化规范
  2. 每个组件包含index.vueindex.json
  3. 插件相关代码放在fauto/plugins目录

状态管理规范

  1. 使用 Pinia 进行全局状态管理
  2. 状态变更必须通过 Store 的方法
  3. 复杂状态逻辑封装在 Store 内部

扩展性设计

新增设计组件

  1. designComponents/ 目录下创建组件文件夹
  2. 实现 index.vueindex.json
  3. 自动在 DesignComponentList 中显示

功能扩展

  1. 拖放后修改源文件 - 通过API将拖放操作写入.vue文件
  2. 属性编辑器 - 展示和编辑设计组件属性
  3. 热更新同步 - 修改后自动刷新页面

总结

本项目实现了一个完整的Vue页面可视化设计器通过直接解析和编辑真实的Vue文件实现了低代码的页面构建方式。

核心亮点

  1. 非侵入式设计 - 通过注入式交互无需修改Vue页面代码
  2. 智能层级选择 - 自动识别嵌套结构,键盘切换层级
  3. 实时视觉反馈 - 拖拽预览 + 拖放区域指示
  4. 结构化路径 - 自动生成可读的元素ID