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

12 KiB
Raw Blame History

拖拽面板设计器 - 项目上下文总结

用途:用于在新电脑快速恢复 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[] = []

新增物料步骤

  1. materials/ 下创建新目录(如 MyWidget/
  2. 添加 index.vue(组件实现)
  3. 添加 index.json(元数据)
  4. 无需修改任何注册代码,自动生效!

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/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 获取组件定义


📦 依赖清单

{
  "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

📝 后续可优化方向

🔧 功能增强

  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.vueindex.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 能编辑组件属性

如果以上任一项失败,请参考"已解决的关键问题"章节。


🎉 恭喜!你已经完全掌握了这个项目的上下文,可以继续开发了!