diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..35410ca --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/MarsCodeWorkspaceAppSettings.xml b/.idea/MarsCodeWorkspaceAppSettings.xml new file mode 100644 index 0000000..e2a065b --- /dev/null +++ b/.idea/MarsCodeWorkspaceAppSettings.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/fauto-design.iml b/.idea/fauto-design.iml new file mode 100644 index 0000000..d6ebd48 --- /dev/null +++ b/.idea/fauto-design.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..07115cd --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..72ea6d1 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/draggable-panels/IMPLEMENTATION_PLAN.md b/draggable-panels/IMPLEMENTATION_PLAN.md new file mode 100644 index 0000000..dd00606 --- /dev/null +++ b/draggable-panels/IMPLEMENTATION_PLAN.md @@ -0,0 +1,702 @@ +# 🎯 可视化拖拽设计器 - 整体实施计划 + +> **目标**:将当前的设计器升级为可直接解析和编辑真实Vue文件的可视化拖拽编辑器 +> **核心技术**:Vue编译时AST转换 + Element Plus布局 + 实时文件修改 +> **参考实现**:plugins示例项目的拖拽机制 + +--- + +## 📋 项目总体架构设计 + +### **整体技术栈升级** + +``` +现有架构 → 目标架构 +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +设计组件 (虚拟对象) → 真实Vue文件解析 +DesignCenter (模拟预览) → 实时渲染的Vue页面 +属性编辑 (内存状态) → 直接修改源文件 +拖拽排序 (组件实例) → 拖拽修改el-row/el-col布局 +``` + +### **核心功能模块划分** + +``` +┌─────────────────────────────────────────────────────────┐ +│ 可视化拖拽设计器 │ +└─────────────────────────────────────────────────────────┘ + │ + ├─ 模块1: Vue文件解析引擎 + │ ├─ AST解析与遍历 + │ ├─ 组件树结构提取 + │ └─ 元数据生成 (_material路径ID) + │ + ├─ 模块2: 编译时增强插件系统 + │ ├─ Vite插件配置 + │ ├─ Vue模板AST转换 + │ ├─ 拖拽指令自动注入 + │ └─ 结构化ID生成 + │ + ├─ 模块3: 运行时拖拽交互系统 + │ ├─ 自定义拖拽指令 (v-auto-drag) + │ ├─ 拖拽事件处理 (dragstart/drop/over) + │ ├─ 元素选中与高亮 + │ └─ 滚轮切换父子元素 + │ + ├─ 模块4: 可视化画布系统 + │ ├─ 实时渲染Vue页面 + │ ├─ el-row/el-col布局展示 + │ ├─ 拖拽预览与占位符 + │ └─ 组件边界高亮 + │ + ├─ 模块5: 源文件修改引擎 + │ ├─ 模板字符串操作 + │ ├─ 元素位置计算与插入 + │ ├─ 代码格式化与清理 + │ └─ 文件写入API (后端支持) + │ + └─ 模块6: 设计器UI增强 + ├─ 左侧: 组件树查看器 + ├─ 中间: 可视化画布 + ├─ 右侧: 属性编辑器 + └─ 顶部: 文件选择与工具栏 +``` + +--- + +## 🗂️ 项目文件结构设计 + +``` +draggable-panels/ +├── src/ +│ ├── fauto/ +│ │ ├── Designer.vue # 设计器主入口 +│ │ │ +│ │ ├── components/ +│ │ │ ├── Header.vue # ✨新增: 文件选择工具栏 +│ │ │ ├── MainLayout.vue # (保持原有) +│ │ │ └── Panel.vue # (保持原有) +│ │ │ +│ │ ├── materials/ +│ │ │ ├── VueFileExplorer/ # ✨新增: Vue文件浏览器 +│ │ │ │ ├── index.vue +│ │ │ │ └── index.json +│ │ │ │ +│ │ │ ├── ComponentTreeViewer/ # ✨新增: 组件结构树 +│ │ │ │ ├── index.vue +│ │ │ │ └── index.json +│ │ │ │ +│ │ │ ├── VisualCanvas/ # ✨新增: 可视化画布 +│ │ │ │ ├── index.vue # (实时渲染目标Vue文件) +│ │ │ │ └── index.json +│ │ │ │ +│ │ │ ├── PropertyEditor/ # ✨新增: 属性编辑器 +│ │ │ │ ├── index.vue +│ │ │ │ └── index.json +│ │ │ │ +│ │ │ └── (保留原有物料组件...) +│ │ │ +│ │ ├── designComponents/ # (保留,但不再是主要编辑对象) +│ │ │ +│ │ ├── core/ # ✨新增: 核心功能模块 +│ │ │ ├── parser/ # Vue文件解析器 +│ │ │ │ ├── vueParser.ts # SFC解析入口 +│ │ │ │ ├── templateParser.ts # template AST解析 +│ │ │ │ ├── componentTreeBuilder.ts # 组件树构建 +│ │ │ │ └── pathGenerator.ts # 结构化路径生成 +│ │ │ │ +│ │ │ ├── modifier/ # 源文件修改器 +│ │ │ │ ├── templateModifier.ts # 模板修改逻辑 +│ │ │ │ ├── elementExtractor.ts # 元素提取与定位 +│ │ │ │ ├── codeFormatter.ts # 代码格式化 +│ │ │ │ └── fileWriter.ts # 文件写入API封装 +│ │ │ │ +│ │ │ └── directives/ # 自定义指令 +│ │ │ ├── autoDrag.ts # 拖拽指令实现 +│ │ │ └── elementSelect.ts # 元素选中指令 +│ │ │ +│ │ ├── stores/ +│ │ │ ├── panelStore.ts # (保留) +│ │ │ ├── designStore.ts # (保留,但角色调整) +│ │ │ │ +│ │ │ ├── vueFileStore.ts # ✨新增: Vue文件状态管理 +│ │ │ │ # - 当前打开的Vue文件路径 +│ │ │ │ # - 解析后的组件树结构 +│ │ │ │ # - 当前选中的元素 +│ │ │ │ # - 文件缓存与同步 +│ │ │ │ +│ │ │ └── canvasStore.ts # ✨新增: 画布交互状态 +│ │ │ # - 拖拽状态管理 +│ │ │ # - 选中元素路径 +│ │ │ # - 悬停目标信息 +│ │ │ +│ │ └── types/ +│ │ ├── index.ts # (保留原有) +│ │ ├── vueFile.ts # ✨新增: Vue文件相关类型 +│ │ └── canvas.ts # ✨新增: 画布相关类型 +│ │ +│ └── plugins/ # ✨新增: Vite/Vue插件 +│ ├── index.ts # 插件总入口 +│ ├── vite/ +│ │ └── vueFilePlugin.ts # Vite插件 (文件写入API) +│ └── vue/ +│ ├── dragPlugin.ts # Vue编译时插件 +│ ├── autoDrag.ts # 拖拽指令实现 +│ └── dragStyles.css # 拖拽样式 +│ +├── vite.config.ts # ✨修改: 集成新插件 +├── package.json # ✨修改: 新增依赖 +└── IMPLEMENTATION_PLAN.md # 本文档 +``` + +--- + +## 📦 阶段性实施计划 + +### **阶段1: 基础设施搭建** (第1-2天) + +#### **任务1.1: 安装依赖与环境准备** +- [ ] 安装Element Plus (`npm install element-plus`) +- [ ] 安装@vue/compiler-sfc (用于AST解析) +- [ ] 配置vite.config.ts引入插件系统 +- [ ] 创建测试用的TestPage.vue文件 + +#### **任务1.2: 创建插件系统框架** +- [ ] 创建 `src/plugins/` 目录结构 +- [ ] 实现 `vite/vueFilePlugin.ts` - 文件写入API中间件 +- [ ] 实现 `vue/dragPlugin.ts` - Vue编译时节点转换器 +- [ ] 配置vite.config.ts加载插件 + +**验收标准**: +- ✅ Vite能正常启动,插件加载无报错 +- ✅ 访问 `/api/write-file` 能收到响应 +- ✅ TestPage.vue编译时能看到插件日志 + +--- + +### **阶段2: Vue文件解析引擎** (第3-4天) + +#### **任务2.1: 实现SFC解析器** +- [ ] 创建 `core/parser/vueParser.ts` + - 解析Vue单文件组件 + - 提取template/script/style + - 缓存原始代码 + +#### **任务2.2: 实现template AST解析** +- [ ] 创建 `core/parser/templateParser.ts` + - 使用@vue/compiler-dom解析template + - 遍历AST节点 + - 识别el-row和el-col元素 + +#### **任务2.3: 实现组件树构建器** +- [ ] 创建 `core/parser/componentTreeBuilder.ts` + - 递归构建树形结构 + - 生成结构化路径ID (r1c2r1c1...) + - 提取组件属性信息 + +#### **任务2.4: 创建vueFileStore** +- [ ] 创建 `stores/vueFileStore.ts` + - 管理当前打开的Vue文件 + - 存储解析后的组件树 + - 提供文件加载/保存接口 + +**验收标准**: +- ✅ 能解析TestPage.vue并生成组件树 +- ✅ 每个el-row/el-col都有唯一的路径ID +- ✅ vueFileStore能正确缓存解析结果 + +--- + +### **阶段3: 编译时增强系统** (第5-6天) + +#### **任务3.1: 实现路径ID生成算法** +- [ ] 创建 `core/parser/pathGenerator.ts` + - 实现plugins示例中的路径生成逻辑 + - 递归计算父子关系 + - 生成r1c2格式的ID + +#### **任务3.2: 实现Vue编译时转换器** +- [ ] 完善 `plugins/vue/dragPlugin.ts` + - 在编译时遍历AST + - 自动为el-row/el-col注入v-auto-drag指令 + - 注入_material属性 + +#### **任务3.3: 实现拖拽指令** +- [ ] 创建 `plugins/vue/autoDrag.ts` + - 实现dragstart/dragover/drop事件处理 + - 实现元素选中逻辑 + - 实现滚轮切换父子元素 + - 添加拖拽样式 + +**验收标准**: +- ✅ 编译后的Vue组件自动包含拖拽功能 +- ✅ 每个el-col都能被拖拽 +- ✅ 点击元素能高亮选中 +- ✅ 滚轮能切换选中父子元素 + +--- + +### **阶段4: 可视化画布系统** (第7-8天) + +#### **任务4.1: 创建VisualCanvas物料组件** +- [ ] 创建 `materials/VisualCanvas/index.vue` + - 动态加载目标Vue文件 + - 使用iframe或动态组件渲染 + - 应用拖拽样式 + +#### **任务4.2: 实现画布交互状态管理** +- [ ] 创建 `stores/canvasStore.ts` + - 管理拖拽状态(拖拽元素ID、目标位置) + - 管理选中状态(当前选中元素路径) + - 提供拖拽预览数据 + +#### **任务4.3: 实现拖拽视觉反馈** +- [ ] 创建 `plugins/vue/dragStyles.css` + - 拖拽中的半透明效果 + - 拖拽进入的高亮边框 + - 元素选中的蓝色描边 + - 拖拽占位符样式 + +**验收标准**: +- ✅ 画布能正确渲染TestPage.vue +- ✅ 拖拽时有清晰的视觉反馈 +- ✅ 选中元素有蓝色描边 +- ✅ 悬停目标有红色高亮 + +--- + +### **阶段5: 源文件修改引擎** (第9-10天) + +#### **任务5.1: 实现元素提取与定位** +- [ ] 创建 `core/modifier/elementExtractor.ts` + - 根据_material ID定位元素 + - 提取完整的元素字符串(含子元素) + - 计算元素在模板中的位置 + +#### **任务5.2: 实现模板修改逻辑** +- [ ] 创建 `core/modifier/templateModifier.ts` + - 移除源元素 + - 根据方向插入到目标位置 + - 处理嵌套结构的移动 + +#### **任务5.3: 实现代码格式化与清理** +- [ ] 创建 `core/modifier/codeFormatter.ts` + - 清除运行时注入的_material属性 + - 保持原有代码缩进 + - 移除多余的空行 + +#### **任务5.4: 实现文件写入封装** +- [ ] 创建 `core/modifier/fileWriter.ts` + - 调用/api/write-file接口 + - 错误处理与重试 + - 写入成功后刷新页面 + +**验收标准**: +- ✅ 拖拽后能正确修改Vue源文件 +- ✅ 修改后的代码格式正确 +- ✅ 不会破坏原有代码结构 +- ✅ 页面自动刷新显示修改结果 + +--- + +### **阶段6: 设计器UI增强** (第11-12天) + +#### **任务6.1: 创建VueFileExplorer** +- [ ] 创建 `materials/VueFileExplorer/index.vue` + - 显示项目中的所有.vue文件 + - 点击文件加载到画布 + - 显示当前打开的文件路径 + +#### **任务6.2: 创建ComponentTreeViewer** +- [ ] 创建 `materials/ComponentTreeViewer/index.vue` + - 展示当前Vue文件的组件树 + - 显示el-row/el-col的层级结构 + - 点击树节点选中画布中的元素 + - 支持拖拽调整顺序(可选) + +#### **任务6.3: 创建PropertyEditor** +- [ ] 创建 `materials/PropertyEditor/index.vue` + - 显示选中元素的属性(span、gutter等) + - 支持修改属性值 + - 实时更新到源文件 + +#### **任务6.4: 升级Header工具栏** +- [ ] 修改 `components/Header.vue` + - 添加"打开文件"按钮 + - 显示当前文件名 + - 添加"保存"、"撤销"按钮(可选) + +**验收标准**: +- ✅ 能浏览并选择Vue文件 +- ✅ 组件树能实时同步画布状态 +- ✅ 属性编辑器能修改元素属性 +- ✅ 工具栏显示当前操作状态 + +--- + +### **阶段7: 功能完善与优化** (第13-14天) + +#### **任务7.1: 实现撤销/重做功能** +- [ ] 创建历史记录栈 +- [ ] 实现Ctrl+Z撤销 +- [ ] 实现Ctrl+Shift+Z重做 + +#### **任务7.2: 实现拖拽位置预览** +- [ ] 拖拽时显示插入位置占位符 +- [ ] 左右方向箭头指示 +- [ ] 不合法拖拽的禁止光标 + +#### **任务7.3: 实现快捷键支持** +- [ ] Delete键删除选中元素 +- [ ] Ctrl+C/V 复制粘贴(可选) +- [ ] 方向键微调位置(可选) + +#### **任务7.4: 性能优化** +- [ ] 大文件解析性能优化 +- [ ] 拖拽事件节流 +- [ ] 组件树虚拟滚动(如果元素很多) + +**验收标准**: +- ✅ 撤销/重做功能正常 +- ✅ 拖拽预览清晰直观 +- ✅ 快捷键响应流畅 +- ✅ 大文件(100+元素)操作流畅 + +--- + +### **阶段8: 测试与文档** (第15天) + +#### **任务8.1: 编写单元测试** +- [ ] 测试Vue文件解析器 +- [ ] 测试路径ID生成算法 +- [ ] 测试模板修改逻辑 + +#### **任务8.2: 编写集成测试** +- [ ] 端到端拖拽测试 +- [ ] 文件加载与保存测试 +- [ ] 多文件切换测试 + +#### **任务8.3: 更新项目文档** +- [ ] 更新PROJECT_CONTEXT.md +- [ ] 编写用户使用指南 +- [ ] 编写开发者文档 + +--- + +## 🔧 技术实现关键点 + +### **1. Vue编译时AST转换** + +```typescript +// plugins/vue/dragPlugin.ts +export function dragNodeTransform(node, context) { + // 1. 只处理el-row和el-col元素 + if (node.type === 1 && (node.tag === 'el-row' || node.tag === 'el-col')) { + + // 2. 生成结构化路径ID + const materialId = generateStructuredPath(node, context) + + // 3. 注入v-auto-drag指令 + node.props.push({ + type: 7, // 指令类型 + name: 'auto-drag', + exp: undefined, + modifiers: [] + }) + + // 4. 注入_material属性 + node.props.push({ + type: 6, // 属性类型 + name: '_material', + value: { type: 2, content: materialId } + }) + } +} +``` + +### **2. 结构化路径ID生成算法** + +```typescript +// core/parser/pathGenerator.ts +/** + * 生成结构化路径ID + * 例如: r1c2r1 表示 第1个row -> 第2个col -> 第1个row + */ +function generateStructuredPath(node, context) { + // 1. 递归查找父节点路径 + const parent = findParentNode(node, context.root) + let parentPath = parent ? generateStructuredPath(parent) : '' + + // 2. 计算当前节点在同级中的索引 + if (node.tag === 'el-row') { + const rowIndex = calculateSiblingIndex(node, parent, 'el-row') + return `${parentPath}r${rowIndex}` + } else if (node.tag === 'el-col') { + const colIndex = calculateSiblingIndex(node, parent, 'el-col') + return `${parentPath}c${colIndex}` + } + + return parentPath +} +``` + +### **3. 拖拽事件处理流程** + +```typescript +// plugins/vue/autoDrag.ts +// 拖拽开始 +function onDragStart(e, elementId) { + __dragElement.value = elementId + e.target.classList.add('drag-overlay') +} + +// 拖拽悬停 +function onDragOver(e, targetId) { + const rect = e.target.getBoundingClientRect() + const direction = e.clientX - rect.left < rect.width / 2 ? 'left' : 'right' + __dropInfo.value = { targetId, direction } + e.target.classList.add('drag-enter') +} + +// 拖拽放置 +function onDrop(e, targetId) { + // 调用模板修改器 + modifyVueTemplate(__dragElement.value, targetId, __dropInfo.value.direction) + + // 清理状态 + cleanupDragState() +} +``` + +### **4. 模板字符串修改逻辑** + +```typescript +// core/modifier/templateModifier.ts +function modifyTemplate(sourceId, targetId, direction) { + // 1. 提取源元素 + const sourceElement = extractElementById(template, sourceId) + + // 2. 从模板中移除源元素 + template = template.replace(sourceElement, '') + + // 3. 查找目标元素位置 + const targetPosition = findElementPosition(template, targetId) + + // 4. 根据方向插入源元素 + if (direction === 'left') { + template = insertBefore(template, targetPosition, sourceElement) + } else { + template = insertAfter(template, targetPosition, sourceElement) + } + + // 5. 清理_material属性 + template = template.replace(/\s+_material="[^"]*"/g, '') + + return template +} +``` + +### **5. 文件写入API** + +```typescript +// plugins/vite/vueFilePlugin.ts +configureServer(server) { + server.middlewares.use('/api/write-file', async (req, res) => { + const { filePath, content } = await parseBody(req) + const fullPath = path.resolve(process.cwd(), filePath) + fs.writeFileSync(fullPath, content, 'utf8') + res.end(JSON.stringify({ success: true })) + }) +} +``` + +--- + +## 🎯 核心数据流 + +``` +1. 用户打开Vue文件 + ↓ +2. vueFileStore.loadFile(path) + ↓ +3. vueParser解析SFC → 提取template + ↓ +4. templateParser解析AST → 构建组件树 + ↓ +5. 组件树显示在ComponentTreeViewer + ↓ +6. VisualCanvas渲染Vue文件(编译时已注入拖拽指令) + ↓ +7. 用户在画布中拖拽el-col + ↓ +8. dragStart → 记录源ID + ↓ +9. dragOver → 计算目标ID和方向 + ↓ +10. drop → 调用templateModifier + ↓ +11. 修改template字符串 + ↓ +12. 调用/api/write-file写入文件 + ↓ +13. Vite热更新 → 页面自动刷新 + ↓ +14. 显示修改后的布局 ✅ +``` + +--- + +## 📊 关键类型定义 + +```typescript +// types/vueFile.ts +export interface VueFileInfo { + path: string // 文件路径 + name: string // 文件名 + content: string // 原始内容 + template: string // 模板部分 + componentTree: ComponentNode[] // 组件树 + lastModified: number // 最后修改时间 +} + +export interface ComponentNode { + id: string // 结构化路径ID (r1c2) + tag: 'el-row' | 'el-col' // 标签类型 + attrs: Record // 属性 (span, gutter等) + children: ComponentNode[] // 子节点 + parent: ComponentNode | null // 父节点引用 + depth: number // 深度(用于树形展示) +} + +// types/canvas.ts +export interface DragState { + dragElementId: string | null // 正在拖拽的元素ID + targetElementId: string | null // 目标元素ID + direction: 'left' | 'right' | null // 插入方向 + isDragging: boolean // 是否正在拖拽 +} + +export interface SelectState { + selectedElementId: string | null // 选中的元素ID + selectedElementPath: ComponentNode[] // 选中元素的父级路径 + hoverElementId: string | null // 鼠标悬停的元素ID +} +``` + +--- + +## ⚠️ 技术难点与解决方案 + +### **难点1: AST节点父级查找** +**问题**:Vue编译时AST节点没有parent引用 +**解决**:递归遍历根节点,构建节点关系映射表 + +### **难点2: 字符串操作的准确性** +**问题**:正则匹配可能误删嵌套元素 +**解决**:使用深度计数器,精确匹配开始/结束标签 + +### **难点3: 热更新与拖拽状态冲突** +**问题**:文件修改后页面刷新,拖拽状态丢失 +**解决**:将拖拽状态保存到sessionStorage,刷新后恢复 + +### **难点4: 大文件性能问题** +**问题**:100+元素的Vue文件解析缓慢 +**解决**:使用Web Worker后台解析,分片渲染组件树 + +### **难点5: 跨iframe通信** +**问题**:如果画布使用iframe,事件监听复杂 +**解决**:使用动态组件代替iframe,或通过postMessage通信 + +--- + +## 🚀 启动指南(实施后) + +```bash +# 1. 安装依赖 +npm install + +# 2. 启动开发服务器 +npm run dev + +# 3. 访问设计器 +http://localhost:5173/draggable + +# 4. 操作流程 +- 点击"窗口" → 打开"Vue文件浏览器"(左侧) +- 点击"窗口" → 打开"可视化画布"(中间) +- 点击"窗口" → 打开"组件树查看器"(左侧) +- 在文件浏览器中选择TestPage.vue +- 在画布中拖拽el-col调整布局 +- 查看源文件自动更新 +``` + +--- + +## 📝 后续可扩展功能 + +### **功能增强** +1. **组件库集成** + - 支持从Element Plus组件库拖拽添加组件 + - 不仅限于el-row/el-col,支持所有组件 + +2. **多文件项目管理** + - 项目文件树浏览 + - 多文件同时编辑(Tab切换) + - 文件依赖关系分析 + +3. **智能布局** + - 自动计算span总和 + - 响应式布局预览(xs/sm/md/lg) + - 对齐辅助线 + +4. **团队协作** + - Git集成(提交/拉取) + - 实时协作编辑(WebSocket) + - 版本历史对比 + +### **开发体验** +1. **代码生成** + - 自动生成配套的script代码 + - 自动导入组件 + - 自动生成数据绑定 + +2. **预设模板** + - 常用布局模板库 + - 一键应用模板 + - 自定义模板保存 + +--- + +## ✅ 验收清单(最终) + +- [ ] 能浏览并选择项目中的.vue文件 +- [ ] 能在画布中实时渲染Vue文件 +- [ ] 能通过拖拽调整el-row/el-col布局 +- [ ] 拖拽操作能正确修改源文件 +- [ ] 文件修改后页面自动刷新 +- [ ] 点击元素能高亮选中 +- [ ] 滚轮能切换父子元素选中 +- [ ] 组件树能实时同步画布状态 +- [ ] 属性编辑器能修改元素属性 +- [ ] 支持撤销/重做操作 +- [ ] 所有操作流畅无明显卡顿 +- [ ] 代码格式保持规范 + +--- + +## 🎉 总结 + +本计划将分**8个阶段、15天**完成,核心思路是: + +1. **编译时增强**:通过Vue编译器插件自动注入拖拽能力 +2. **运行时交互**:通过自定义指令实现拖拽逻辑 +3. **字符串操作**:精确修改模板字符串 +4. **文件同步**:通过Vite中间件实现文件写入 + +相比于传统的虚拟组件设计器,这种方案的优势是: +- ✅ **所见即所得**:直接编辑真实的Vue文件 +- ✅ **零学习成本**:开发者无需学习DSL或JSON配置 +- ✅ **完全可控**:生成的代码就是手写的代码 +- ✅ **灵活扩展**:可以支持任意Vue组件 + +**让我们开始实施吧!** 🚀 diff --git a/draggable-panels/STAGE1_COMPLETED.md b/draggable-panels/STAGE1_COMPLETED.md new file mode 100644 index 0000000..d7a11a7 --- /dev/null +++ b/draggable-panels/STAGE1_COMPLETED.md @@ -0,0 +1,253 @@ +# 第一阶段完成说明 + +## ✅ 已完成的功能 + +### 1. 创建了5个测试页面 + +#### 根目录页面: +- **TestPage1.vue** - 基础布局测试页面(左右两列 + 三列布局) +- **TestPage2.vue** - 表单布局测试页面(标题 + 表单字段 + 提交按钮) + +#### 文件夹分类页面: +- **dashboard/Overview.vue** - 仪表板概览页面(统计卡片 + 图表区域) +- **user/Profile.vue** - 用户资料页面(头像 + 个人信息) + +所有测试页面都使用了 **el-row** 和 **el-col** 进行布局。 + +--- + +### 2. 创建了"页面管理"物料组件 + +**位置**: `src/fauto/materials/PageManager/` + +**功能**: +- ✅ 自动扫描 `src/views/` 目录下的所有Vue文件 +- ✅ 以树形结构展示文件夹和Vue文件 +- ✅ 点击Vue文件后,会选中该文件并通知设计中心 +- ✅ 显示当前选中的文件名 +- ✅ 文件夹默认展开 +- ✅ 使用Element Plus的el-tree组件 + +**特点**: +- 📁 文件夹图标 +- 📄 Vue文件图标 +- 🔵 选中文件高亮显示 +- 自动分类显示(文件夹在前,文件在后) + +--- + +### 3. 升级了"设计中心"物料组件 + +**位置**: `src/fauto/materials/DesignCenter/` + +**新增功能**: +- ✅ **动态渲染选中的Vue页面**:当从"页面管理"选择文件后,自动加载并渲染该页面 +- ✅ 显示当前渲染的文件名 +- ✅ 保留了原有的设计组件实例预览功能 +- ✅ 智能切换显示模式: + - 如果选中了Vue页面 → 显示页面预览 + - 如果没有选中页面但有设计组件 → 显示设计组件列表 + - 如果都没有 → 显示提示信息 + +**渲染方式**: +- 使用 `defineAsyncComponent` 动态加载Vue组件 +- 使用 `import.meta.glob` 扫描所有views下的文件 +- 实时响应文件选择变化 + +--- + +### 4. 创建了vueFileStore状态管理 + +**位置**: `src/fauto/stores/vueFileStore.ts` + +**管理的状态**: +- `selectedFilePath` - 当前选中的文件路径 +- `selectedFileName` - 当前选中的文件名 +- `fileTree` - 文件树结构 + +**提供的方法**: +- `selectFile(path, name)` - 选中文件 +- `clearSelection()` - 清除选中 +- `buildFileTree(modules)` - 从import.meta.glob结果构建树形结构 + +--- + +### 5. 集成了Element Plus + +**安装的依赖**: +- `element-plus@^2.8.8` + +**配置位置**: +- `src/main.ts` - 全局注册Element Plus +- 自动导入Element Plus样式 + +**使用的组件**: +- `el-tree` - 树形组件(页面管理) +- `el-row` / `el-col` - 布局组件(测试页面) + +--- + +## 🎯 使用方法 + +### 启动项目 +```bash +cd draggable-panels +npm install # 已完成 +npm run dev # 已启动,访问 http://localhost:5173 +``` + +### 操作步骤 + +1. **访问设计器** + ``` + http://localhost:5173/draggable + ``` + +2. **打开页面管理** + - 点击顶部"窗口"菜单 + - 选择"页面管理" + - 面板会在左侧或中间打开 + +3. **打开设计中心** + - 点击顶部"窗口"菜单 + - 选择"设计中心" + - 建议拖到中间面板 + +4. **选择并预览页面** + - 在"页面管理"中点击任意Vue文件(如 TestPage1.vue) + - "设计中心"会立即显示该页面的实时渲染效果 + - 可以在树中切换不同的页面查看效果 + +--- + +## 📂 项目文件结构(新增部分) + +``` +draggable-panels/ +├── src/ +│ ├── views/ # ✨测试页面目录 +│ │ ├── HelloWorld.vue # (原有) +│ │ ├── TestPage1.vue # ✨新增:基础布局 +│ │ ├── TestPage2.vue # ✨新增:表单布局 +│ │ ├── dashboard/ # ✨新增文件夹 +│ │ │ └── Overview.vue # 仪表板概览 +│ │ └── user/ # ✨新增文件夹 +│ │ └── Profile.vue # 用户资料 +│ │ +│ ├── fauto/ +│ │ ├── materials/ +│ │ │ ├── PageManager/ # ✨新增:页面管理物料 +│ │ │ │ ├── index.vue +│ │ │ │ └── index.json +│ │ │ └── DesignCenter/ # ✨修改:升级为动态渲染 +│ │ │ ├── index.vue # (已修改) +│ │ │ └── index.json # (已修改) +│ │ │ +│ │ └── stores/ +│ │ └── vueFileStore.ts # ✨新增:Vue文件状态管理 +│ │ +│ └── main.ts # ✨修改:集成Element Plus +│ +└── package.json # ✨修改:添加element-plus依赖 +``` + +--- + +## 🎨 界面预览 + +### 页面管理物料组件 +``` +┌─────────────────────────────┐ +│ 页面管理 5 项 │ +├─────────────────────────────┤ +│ 当前文件: TestPage1.vue │ +├─────────────────────────────┤ +│ 📁 dashboard │ +│ 📄 Overview.vue │ +│ 📄 HelloWorld.vue │ +│ 📄 TestPage1.vue ←选中 │ +│ 📄 TestPage2.vue │ +│ 📁 user │ +│ 📄 Profile.vue │ +└─────────────────────────────┘ +``` + +### 设计中心(渲染Vue页面) +``` +┌─────────────────────────────────────┐ +│ 设计中心 📄 TestPage1.vue │ +├─────────────────────────────────────┤ +│ ┌───────────────────────────────┐ │ +│ │ 测试页面 1 │ │ +│ │ ┌────────┐ ┌────────┐ │ │ +│ │ │左侧内容│ │右侧内容│ │ │ +│ │ └────────┘ └────────┘ │ │ +│ │ ┌──┐ ┌──┐ ┌──┐ │ │ +│ │ │列1│ │列2│ │列3│ │ │ +│ │ └──┘ └──┘ └──┘ │ │ +│ └───────────────────────────────┘ │ +└─────────────────────────────────────┘ +``` + +--- + +## ✨ 技术亮点 + +1. **自动扫描机制** + - 使用 `import.meta.glob` 自动扫描views目录 + - 无需手动注册新页面 + - 支持嵌套文件夹结构 + +2. **动态组件加载** + - 使用 `defineAsyncComponent` 按需加载 + - 节省初始加载时间 + - 支持代码分割 + +3. **状态同步** + - vueFileStore 和 DesignCenter 通过 Pinia 实时同步 + - 选择文件后立即响应 + - 使用 `watch` 监听状态变化 + +4. **智能UI切换** + - 根据不同状态显示不同内容 + - 优先显示Vue页面预览 + - 保留原有设计组件功能 + +--- + +## 🔍 验证功能是否正常 + +### 检查清单: +- [ ] 访问 http://localhost:5173/draggable 能看到设计器界面 +- [ ] 点击"窗口"菜单能看到"页面管理"选项 +- [ ] 打开"页面管理"能看到5个Vue文件 +- [ ] 文件按文件夹分类显示(dashboard、user) +- [ ] 点击TestPage1.vue后,设计中心显示该页面 +- [ ] 页面中能看到蓝色和绿色的布局区块 +- [ ] 切换不同文件,设计中心实时更新 +- [ ] 当前选中的文件在树中高亮显示 + +--- + +## 📝 后续步骤 + +下一阶段我们将: +1. 创建Vite插件系统,实现编译时AST转换 +2. 为el-row和el-col自动注入拖拽指令 +3. 实现拖拽交互逻辑 +4. 实现文件修改引擎 + +--- + +## 🎉 第一阶段完成! + +现在你可以: +- ✅ 浏览views目录下的所有Vue文件 +- ✅ 点击文件后在设计中心实时预览 +- ✅ 查看包含el-row/el-col布局的测试页面 + +**测试建议**: +1. 先打开"页面管理"(左侧面板) +2. 再打开"设计中心"(中间面板) +3. 依次点击不同的Vue文件查看效果 +4. 观察不同页面的布局样式 diff --git a/draggable-panels/config.json b/draggable-panels/config.json index bcb2d46..4465315 100644 --- a/draggable-panels/config.json +++ b/draggable-panels/config.json @@ -3,20 +3,20 @@ "leftPanel": { "id": "left", "tabs": [ + { + "id": "6hfm9ux", + "title": "页面管理", + "content": "新窗口内容", + "materialId": "PageManager" + }, { "id": "up60643", "title": "设计组件列表", "content": "新窗口内容", "materialId": "DesignComponentList" - }, - { - "id": "78ikdz5", - "title": "测试组件B", - "content": "新窗口内容", - "materialId": "TestWidget2" } ], - "activeTabId": "up60643" + "activeTabId": "6hfm9ux" }, "centerPanel": { "id": "center", @@ -144,8 +144,8 @@ } } ], - "activeTabId": "vrh9bl2" + "activeTabId": "mxfx11j" } }, - "lastUpdated": "2025-12-20T14:50:20.652Z" + "lastUpdated": "2025-12-21T12:24:13.100Z" } \ No newline at end of file diff --git a/draggable-panels/design-state.json b/draggable-panels/design-state.json index db0148a..1de3092 100644 --- a/draggable-panels/design-state.json +++ b/draggable-panels/design-state.json @@ -55,5 +55,5 @@ } ], "selectedId": "xazr6j9", - "lastUpdated": "2025-12-20T15:21:31.411Z" + "lastUpdated": "2025-12-21T12:22:52.464Z" } \ No newline at end of file diff --git a/draggable-panels/package-lock.json b/draggable-panels/package-lock.json index b60d0cb..7219317 100644 --- a/draggable-panels/package-lock.json +++ b/draggable-panels/package-lock.json @@ -8,6 +8,7 @@ "name": "draggable-panels", "version": "0.0.0", "dependencies": { + "element-plus": "^2.8.8", "pinia": "^3.0.4", "vue": "^3.5.24", "vue-router": "^4.6.4", @@ -68,6 +69,24 @@ "node": ">=6.9.0" } }, + "node_modules/@ctrl/tinycolor": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", + "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/@element-plus/icons-vue": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-2.3.2.tgz", + "integrity": "sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A==", + "license": "MIT", + "peerDependencies": { + "vue": "^3.2.0" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", @@ -510,12 +529,48 @@ "node": ">=18" } }, + "node_modules/@floating-ui/core": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", + "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz", + "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.3", + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", + "license": "MIT" + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "license": "MIT" }, + "node_modules/@popperjs/core": { + "name": "@sxzz/popperjs-es", + "version": "2.11.7", + "resolved": "https://registry.npmjs.org/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz", + "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-beta.53", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.53.tgz", @@ -838,6 +893,21 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-FOvQ0YPD5NOfPgMzJihoT+Za5pdkDJWcbpuj1DjaKZIr/gxodQjY/uWEFlTNqW2ugXHUiL8lRQgw63dzKHZdeQ==", + "license": "MIT" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", + "license": "MIT", + "dependencies": { + "@types/lodash": "*" + } + }, "node_modules/@types/node": { "version": "24.10.4", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.4.tgz", @@ -848,6 +918,12 @@ "undici-types": "~7.16.0" } }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz", + "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==", + "license": "MIT" + }, "node_modules/@vitejs/plugin-vue": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.3.tgz", @@ -1070,6 +1146,94 @@ } } }, + "node_modules/@vueuse/core": { + "version": "10.11.1", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.11.1.tgz", + "integrity": "sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww==", + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.20", + "@vueuse/metadata": "10.11.1", + "@vueuse/shared": "10.11.1", + "vue-demi": ">=0.14.8" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/core/node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@vueuse/metadata": { + "version": "10.11.1", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.11.1.tgz", + "integrity": "sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "10.11.1", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.11.1.tgz", + "integrity": "sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==", + "license": "MIT", + "dependencies": { + "vue-demi": ">=0.14.8" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared/node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, "node_modules/alien-signals": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-3.1.1.tgz", @@ -1077,6 +1241,12 @@ "dev": true, "license": "MIT" }, + "node_modules/async-validator": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz", + "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==", + "license": "MIT" + }, "node_modules/birpc": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz", @@ -1107,6 +1277,37 @@ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "license": "MIT" }, + "node_modules/dayjs": { + "version": "1.11.19", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz", + "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", + "license": "MIT" + }, + "node_modules/element-plus": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.13.0.tgz", + "integrity": "sha512-qjxS+SBChvqCl6lU6ShiliLMN6WqFHiXQENYbAY3GKNflG+FS3jqn8JmQq0CBZq4koFqsi95NT1M6SL4whZfrA==", + "license": "MIT", + "dependencies": { + "@ctrl/tinycolor": "^3.4.1", + "@element-plus/icons-vue": "^2.3.2", + "@floating-ui/dom": "^1.0.1", + "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7", + "@types/lodash": "^4.17.20", + "@types/lodash-es": "^4.17.12", + "@vueuse/core": "^10.11.0", + "async-validator": "^4.2.5", + "dayjs": "^1.11.19", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "lodash-unified": "^1.0.3", + "memoize-one": "^6.0.0", + "normalize-wheel-es": "^1.2.0" + }, + "peerDependencies": { + "vue": "^3.3.0" + } + }, "node_modules/entities": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.0.tgz", @@ -1218,6 +1419,29 @@ "url": "https://github.com/sponsors/mesqueeb" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.17.22", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.22.tgz", + "integrity": "sha512-XEawp1t0gxSi9x01glktRZ5HDy0HXqrM0x5pXQM98EaI0NxO6jVM7omDOxsuEo5UIASAnm2bRp1Jt/e0a2XU8Q==", + "license": "MIT" + }, + "node_modules/lodash-unified": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/lodash-unified/-/lodash-unified-1.0.3.tgz", + "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==", + "license": "MIT", + "peerDependencies": { + "@types/lodash-es": "*", + "lodash": "*", + "lodash-es": "*" + } + }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", @@ -1227,6 +1451,12 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", + "license": "MIT" + }, "node_modules/mitt": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", @@ -1258,6 +1488,12 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/normalize-wheel-es": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz", + "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==", + "license": "BSD-3-Clause" + }, "node_modules/path-browserify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", diff --git a/draggable-panels/package.json b/draggable-panels/package.json index 6add1be..3a37466 100644 --- a/draggable-panels/package.json +++ b/draggable-panels/package.json @@ -9,6 +9,7 @@ "preview": "vite preview" }, "dependencies": { + "element-plus": "^2.8.8", "pinia": "^3.0.4", "vue": "^3.5.24", "vue-router": "^4.6.4", diff --git a/draggable-panels/src/fauto/materials/DesignCenter/index.json b/draggable-panels/src/fauto/materials/DesignCenter/index.json index 1e14e73..93b8afd 100644 --- a/draggable-panels/src/fauto/materials/DesignCenter/index.json +++ b/draggable-panels/src/fauto/materials/DesignCenter/index.json @@ -1,4 +1,4 @@ { "name": "设计中心", - "description": "展示已添加的设计组件实例" + "description": "实时预览选中的Vue页面或设计组件" } diff --git a/draggable-panels/src/fauto/materials/DesignCenter/index.vue b/draggable-panels/src/fauto/materials/DesignCenter/index.vue index cc2db29..9c2aff0 100644 --- a/draggable-panels/src/fauto/materials/DesignCenter/index.vue +++ b/draggable-panels/src/fauto/materials/DesignCenter/index.vue @@ -1,9 +1,11 @@