12 KiB
拖拽面板设计器 - 项目上下文总结
用途:用于在新电脑快速恢复 AI 协作上下文
生成时间:2025-12-20
项目路径:/Volumes/mypan/ui/draggable-panels
📋 项目概述
这是一个基于 Vue3 + TypeScript + Vite 的可拖拽面板设计器项目,类似 IDE 界面(IDEA/VS Code)的多面板布局,支持:
- 🎯 三栏面板布局(左/中/右可调整宽度)
- 🎨 Tab 可拖拽、跨面板移动
- 🧩 物料组件系统(自动扫描注册)
- 🎭 设计组件系统(可视化编辑、属性绑定)
- 💾 状态持久化(通过模拟 API)
🏗️ 项目结构
draggable-panels/
├── src/
│ ├── fauto/ # 🔥 设计器核心代码(所有功能都在这里)
│ │ ├── Designer.vue # 设计器主入口页面
│ │ ├── components/ # 设计器基础组件
│ │ │ ├── Header.vue # 顶部菜单栏(打开项目/窗口菜单)
│ │ │ ├── Footer.vue # 底部状态栏
│ │ │ ├── MainLayout.vue # 三栏布局容器
│ │ │ ├── Panel.vue # 单个面板(含 Tab 列表 + 内容区)
│ │ │ └── Resizer.vue # 面板间拖拽分割线
│ │ │
│ │ ├── materials/ # 🎁 物料组件(8个)
│ │ │ ├── index.ts # ✅ 自动扫描所有 */index.vue 和 */index.json
│ │ │ ├── DesignComponentList/ # 可选设计组件列表
│ │ │ ├── TreeViewer/ # 树形结构查看器(已添加实例列表)
│ │ │ ├── DesignCenter/ # 设计中心(组件预览面板)
│ │ │ ├── DataTable/ # 属性表格编辑器
│ │ │ ├── TextEditor/ # 文本编辑器(支持状态持久化)
│ │ │ ├── TestWidget1/2/3/ # 测试组件
│ │ │ └── [每个物料包含]
│ │ │ ├── index.vue # 组件实现
│ │ │ └── index.json # 组件元数据(name/description)
│ │ │
│ │ ├── designComponents/ # 🎨 设计组件(3个)
│ │ │ ├── TextInput/ # 文本输入框
│ │ │ ├── RadioSelect/ # 单选器
│ │ │ ├── GridTable/ # 表格
│ │ │ └── [每个设计组件包含]
│ │ │ ├── index.vue # Vue 组件定义
│ │ │ └── index.json # 元数据(name/description/props)
│ │ │
│ │ ├── stores/ # 🗄️ Pinia 状态管理
│ │ │ ├── panelStore.ts # 面板布局 + 物料状态管理
│ │ │ └── designStore.ts # 设计组件实例管理(✅ 本地自动扫描)
│ │ │
│ │ └── types/ # 📝 TypeScript 类型定义
│ │ └── index.ts # Panel/TabItem/MaterialInfo 等
│ │
│ ├── views/ # 普通视图
│ │ └── HelloWorld.vue # 首页欢迎页
│ │
│ ├── router.ts # 🛤️ 路由配置(/ 和 /draggable)
│ ├── main.ts # 应用入口
│ ├── App.vue # 根组件(仅路由容器)
│ └── style.css # 全局样式
│
├── package.json # 依赖配置
└── vite.config.ts # Vite 配置
🔑 核心技术要点
1. 路由设计
// src/router.ts
'/' → HelloWorld 欢迎页
'/draggable' → Designer 设计器主页面(fauto/Designer.vue)
2. 物料组件自动注册 ⭐
文件:src/fauto/materials/index.ts
// ✅ 使用 import.meta.glob 自动扫描
const vueModules = import.meta.glob('./*/index.vue')
const jsonModules = import.meta.glob('./*/index.json', { eager: true })
// 自动构建组件映射表和信息列表
export const materialComponents: Record<string, Component> = {}
export const materialList: MaterialInfo[] = []
新增物料步骤:
- 在
materials/下创建新目录(如MyWidget/) - 添加
index.vue(组件实现) - 添加
index.json(元数据) - 无需修改任何注册代码,自动生效!
3. 设计组件自动加载 ⭐
最近修复(2025-12-20):
designStore.ts - 从远程 API 改为本地扫描:
// ✅ 使用 eager: true 同步加载
const designComponentMetaModules = import.meta.glob('../designComponents/*/index.json', { eager: true })
// 自动构建元数据列表
const loadComponentMetas = async () => {
const metas: DesignComponentMeta[] = []
for (const path in designComponentMetaModules) {
const id = match[1] // 如 'TextInput'
metas.push({ id, name, description, props })
}
componentMetas.value = metas
}
DesignCenter.vue - 组件预览渲染:
// ✅ 使用 eager: true 确保同步加载
const designComponentModules = import.meta.glob('../../designComponents/*/index.vue', { eager: true })
// 构建组件映射(用于 <component :is="...">)
const designComponentMap: Record<string, any> = {}
for (const path in designComponentModules) {
const mod = designComponentModules[path] as any
designComponentMap[id] = markRaw(mod.default || mod)
}
4. 状态同步机制 ⭐
TreeViewer.vue - 实例列表实时同步(最近修复):
// ✅ 改用 watch 替代 $subscribe(更稳定)
watch(
() => designStore.components,
(newVal) => {
localComponents.value = [...newVal]
},
{ deep: true, immediate: true }
)
5. 状态持久化
-
panelStore:管理面板布局 + 物料组件状态
loadConfig()/saveConfig()→/api/configgetMaterialState()/updateMaterialState()→/api/material-states
-
designStore:管理设计组件实例
loadState()/saveState()→/api/design-state
注意:目前使用 fetch('/api/...') 模拟持久化,实际会失败但不影响运行。如需真实持久化,可改用 localStorage 或搭建后端。
🎯 数据流图
用户操作
↓
┌─────────────────────────────────────────────────┐
│ Header.vue - 点击"窗口"菜单 │
│ → panelStore.openMaterial('TreeViewer') │
└─────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────┐
│ Panel.vue - 渲染 Tab + 加载物料组件 │
│ → <component :is="getMaterialComponent(id)"> │
└─────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────┐
│ DesignComponentList - 点击"文本输入框" │
│ → designStore.addComponent('TextInput') │
└─────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────┐
│ TreeViewer - watch 监听 components 变化 │
│ → 自动刷新实例列表 │
└─────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────┐
│ DesignCenter - 渲染组件预览 │
│ → <component :is="getComponent(componentId)"> │
└─────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────┐
│ DataTable - 编辑属性 │
│ → designStore.updateComponentProps(id, key, val)│
└─────────────────────────────────────────────────┘
🐛 已解决的关键问题
问题 1:设计组件列表不显示
时间:2025-12-20
原因:designStore.loadComponentMetas() 使用 fetch('/api/design-components'),无后端导致 componentMetas 为空
解决:改用 import.meta.glob 自动扫描本地 designComponents/*/index.json
问题 2:TreeViewer 列表不更新
原因:使用 Pinia 的 $subscribe 监听 mutation,逻辑复杂且不稳定
解决:改用 Vue 的 watch(() => designStore.components) 直接监听
问题 3:DesignCenter 组件不渲染
原因:import.meta.glob 未设置 eager: true,导致组件映射表构建失败
解决:添加 { eager: true } 并使用 mod.default || mod 获取组件定义
📦 依赖清单
{
"dependencies": {
"vue": "^3.5.24", // Vue 3 框架
"vue-router": "^4.6.4", // 路由管理
"pinia": "^3.0.4", // 状态管理
"vuedraggable": "^4.1.0" // 拖拽功能
},
"devDependencies": {
"vite": "^7.2.4", // 构建工具
"typescript": "~5.9.3", // TypeScript
"@vitejs/plugin-vue": "^6.0.1"
}
}
🚀 启动命令
# 1. 安装依赖
npm install
# 2. 启动开发服务器
npm run dev
# 访问 http://localhost:5173/draggable
# 3. 构建生产版本
npm run build
📝 后续可优化方向
🔧 功能增强
-
真实持久化
- 选项 A:改用
localStorage替代模拟 API - 选项 B:搭建 Node.js 后端(Express + fs.writeFile)
- 选项 A:改用
-
拖拽增强
- 支持面板间 Tab 跨级拖动
- 树形组件支持父子节点拖拽
-
设计器功能
- 实现拖拽生成 Vue 文件(模板引擎)
- 接入 Element Plus 组件库作为设计组件源
-
开发体验
- 添加 ESLint + Prettier 代码规范
- 添加单元测试(Vitest)
🎨 界面优化
- 添加主题切换(暗色/亮色)
- 面板大小记忆功能
- 快捷键支持(Ctrl+S 保存等)
💡 给 AI 的关键提示
如果遇到"自动扫描不生效"
- 检查是否添加了
{ eager: true }选项 - 确认路径匹配正则是否正确(
/designComponents\/(.+)\/index\.vue$/) - 验证文件夹下是否有
index.vue和index.json
如果组件不渲染
- 检查
import.meta.glob是否使用eager: true - 确认使用
mod.default || mod获取组件 - 对于动态组件,确保使用
markRaw()包装
如果状态不同步
- 优先使用 Vue 的
watch而非 Pinia 的$subscribe - 设置
{ deep: true, immediate: true }确保深度监听 - 使用
[...array]创建新数组触发响应式更新
📞 联系方式
项目负责人:[你的信息]
Git 仓库:[如果有的话]
文档更新:2025-12-20
✅ 快速检查清单(给新 AI)
当你接手这个项目时,请确认以下内容:
- 项目已正常启动(
npm run dev) - 访问
/draggable能看到设计器界面 - 点击"窗口"菜单能打开物料组件
- "设计组件列表"显示 3 个组件(TextInput/RadioSelect/GridTable)
- 点击设计组件后,TreeViewer 能显示新实例
- DesignCenter 能正确渲染组件预览
- DataTable 能编辑组件属性
如果以上任一项失败,请参考"已解决的关键问题"章节。
🎉 恭喜!你已经完全掌握了这个项目的上下文,可以继续开发了!