From 83bafa4e1e90e8a3c37118dfdcbe47d978c140e8 Mon Sep 17 00:00:00 2001 From: fangzhenwu <1040079213@qq.com> Date: Sat, 20 Dec 2025 23:23:21 +0800 Subject: [PATCH] 234 --- draggable-panels/PROJECT_CONTEXT.md | 326 ++++++++++++++++++++++++++++ 1 file changed, 326 insertions(+) create mode 100644 draggable-panels/PROJECT_CONTEXT.md diff --git a/draggable-panels/PROJECT_CONTEXT.md b/draggable-panels/PROJECT_CONTEXT.md new file mode 100644 index 0000000..081736e --- /dev/null +++ b/draggable-panels/PROJECT_CONTEXT.md @@ -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 = {} +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 }) + +// 构建组件映射(用于 ) +const designComponentMap: Record = {} +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 + 加载物料组件 │ +│ → │ +└─────────────────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────┐ +│ DesignComponentList - 点击"文本输入框" │ +│ → designStore.addComponent('TextInput') │ +└─────────────────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────┐ +│ TreeViewer - watch 监听 components 变化 │ +│ → 自动刷新实例列表 │ +└─────────────────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────┐ +│ DesignCenter - 渲染组件预览 │ +│ → │ +└─────────────────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────┐ +│ 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` 获取组件定义 + +--- + +## 📦 依赖清单 + +```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 能编辑组件属性 + +如果以上任一项失败,请参考"已解决的关键问题"章节。 + +--- + +**🎉 恭喜!你已经完全掌握了这个项目的上下文,可以继续开发了!**