This commit is contained in:
2025-12-20 23:23:21 +08:00
parent 7d2ce711dd
commit 83bafa4e1e

View File

@@ -0,0 +1,326 @@
# 拖拽面板设计器 - 项目上下文总结
> **用途**:用于在新电脑快速恢复 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. **路由设计**
```typescript
// src/router.ts
'/' HelloWorld
'/draggable' Designer fauto/Designer.vue
```
### 2. **物料组件自动注册** ⭐
**文件**`src/fauto/materials/index.ts`
```typescript
// ✅ 使用 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[] = []
```
**新增物料步骤**
1.`materials/` 下创建新目录(如 `MyWidget/`
2. 添加 `index.vue`(组件实现)
3. 添加 `index.json`(元数据)
4. **无需修改任何注册代码**,自动生效!
### 3. **设计组件自动加载** ⭐
**最近修复**2025-12-20
**designStore.ts** - 从远程 API 改为本地扫描:
```typescript
// ✅ 使用 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** - 组件预览渲染:
```typescript
// ✅ 使用 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** - 实例列表实时同步(最近修复):
```typescript
// ✅ 改用 watch 替代 $subscribe更稳定
watch(
() => designStore.components,
(newVal) => {
localComponents.value = [...newVal]
},
{ deep: true, immediate: true }
)
```
### 5. **状态持久化**
- **panelStore**:管理面板布局 + 物料组件状态
- `loadConfig()` / `saveConfig()``/api/config`
- `getMaterialState()` / `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`
### 问题 2TreeViewer 列表不更新
**原因**:使用 Pinia 的 `$subscribe` 监听 mutation逻辑复杂且不稳定
**解决**:改用 Vue 的 `watch(() => designStore.components)` 直接监听
### 问题 3DesignCenter 组件不渲染
**原因**`import.meta.glob` 未设置 `eager: true`,导致组件映射表构建失败
**解决**:添加 `{ eager: true }` 并使用 `mod.default || mod` 获取组件定义
---
## 📦 依赖清单
```json
{
"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"
}
}
```
---
## 🚀 启动命令
```bash
# 1. 安装依赖
npm install
# 2. 启动开发服务器
npm run dev
# 访问 http://localhost:5173/draggable
# 3. 构建生产版本
npm run build
```
---
## 📝 后续可优化方向
### 🔧 功能增强
1. **真实持久化**
- 选项 A改用 `localStorage` 替代模拟 API
- 选项 B搭建 Node.js 后端Express + fs.writeFile
2. **拖拽增强**
- 支持面板间 Tab 跨级拖动
- 树形组件支持父子节点拖拽
3. **设计器功能**
- 实现拖拽生成 Vue 文件(模板引擎)
- 接入 Element Plus 组件库作为设计组件源
4. **开发体验**
- 添加 ESLint + Prettier 代码规范
- 添加单元测试Vitest
### 🎨 界面优化
- 添加主题切换(暗色/亮色)
- 面板大小记忆功能
- 快捷键支持Ctrl+S 保存等)
---
## 💡 给 AI 的关键提示
### 如果遇到"自动扫描不生效"
1. 检查是否添加了 `{ eager: true }` 选项
2. 确认路径匹配正则是否正确(`/designComponents\/(.+)\/index\.vue$/`
3. 验证文件夹下是否有 `index.vue``index.json`
### 如果组件不渲染
1. 检查 `import.meta.glob` 是否使用 `eager: true`
2. 确认使用 `mod.default || mod` 获取组件
3. 对于动态组件,确保使用 `markRaw()` 包装
### 如果状态不同步
1. 优先使用 Vue 的 `watch` 而非 Pinia 的 `$subscribe`
2. 设置 `{ deep: true, immediate: true }` 确保深度监听
3. 使用 `[...array]` 创建新数组触发响应式更新
---
## 📞 联系方式
**项目负责人**[你的信息]
**Git 仓库**[如果有的话]
**文档更新**2025-12-20
---
## ✅ 快速检查清单(给新 AI
当你接手这个项目时,请确认以下内容:
- [ ] 项目已正常启动(`npm run dev`
- [ ] 访问 `/draggable` 能看到设计器界面
- [ ] 点击"窗口"菜单能打开物料组件
- [ ] "设计组件列表"显示 3 个组件TextInput/RadioSelect/GridTable
- [ ] 点击设计组件后TreeViewer 能显示新实例
- [ ] DesignCenter 能正确渲染组件预览
- [ ] DataTable 能编辑组件属性
如果以上任一项失败,请参考"已解决的关键问题"章节。
---
**🎉 恭喜!你已经完全掌握了这个项目的上下文,可以继续开发了!**