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

327 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 拖拽面板设计器 - 项目上下文总结
> **用途**:用于在新电脑快速恢复 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 能编辑组件属性
如果以上任一项失败,请参考"已解决的关键问题"章节。
---
**🎉 恭喜!你已经完全掌握了这个项目的上下文,可以继续开发了!**