Files
fauto-design/draggable-panels/项目设计文档.md
2025-12-20 23:16:23 +08:00

6.7 KiB
Raw Blame History

可拖拽子窗口项目设计文档

项目概述

本项目是一个基于 Vite + Vue3 + TypeScript 的可拖拽子窗口系统,模仿 IDE如 IntelliJ IDEA、Visual Studio的界面设计提供多区域可拖拽的窗口管理功能。

技术架构

核心技术栈

  • 构建工具: Vite 7.3.0
  • 前端框架: Vue 3.5.24 (Composition API)
  • 状态管理: Pinia 3.0.4
  • 类型系统: TypeScript
  • 拖拽库: vuedraggable 4.1.0
  • 样式: CSS Modules + Scoped Styles

项目结构

src/
├── assets/                 # 静态资源
├── components/             # 核心UI组件
│   ├── Header.vue         # 顶部菜单栏
│   ├── Footer.vue         # 底部状态栏
│   ├── MainLayout.vue     # 主布局容器
│   ├── Panel.vue          # 面板容器
│   └── Resizer.vue        # 面板分隔器
├── materials/             # 物料组件系统
│   ├── index.ts           # 物料组件注册中心
│   ├── TextEditor/        # 文本编辑器
│   ├── TreeViewer/        # 树形展示器
│   ├── DataTable/         # 数据表格
│   ├── TestWidget*/       # 测试组件
│   ├── DesignComponentList/ # 设计组件列表
│   └── DesignCenter/      # 设计中心
├── designComponents/       # 设计组件库
│   ├── TextInput/         # 文本输入框
│   ├── RadioSelect/       # 单选器
│   └── GridTable/         # 表格组件
├── stores/                 # 状态管理
│   ├── panelStore.ts      # 面板布局状态
│   └── designStore.ts     # 设计中心状态
├── types/                  # TypeScript 类型定义
└── App.vue                # 应用入口

核心功能模块

1. 面板系统 (Panel System)

布局结构

  • Header: 固定顶部,包含菜单和新增窗口按钮
  • MainLayout: 三区域布局(左/中/右)
  • Panel: 可拖拽的面板容器
  • Footer: 固定底部,显示时间和状态信息

拖拽实现

使用 vuedraggable 库实现跨面板的 Tab 拖拽:

<draggable
  :list="panel.tabs"
  group="tabs"
  item-key="id"
  :animation="150"
>

2. 物料组件系统 (Material System)

规范标准

遵循统一的物料组件规范:

  1. 每个组件独立文件夹
  2. 包含 index.vue(组件实现)和 index.json(元数据)
  3. index.json 定义:名称、描述、属性及默认值

组件状态管理

  • 使用 materialState 属性传递组件状态
  • 通过 update:state 事件实现状态更新
  • 物料组件状态独立存储,组件关闭后状态仍保留

状态持久化

通过自定义 Vite 插件实现 API 中间件:

  • /api/config: 布局配置读写
  • /api/material-states: 物料组件状态读写
  • /api/design-components: 设计组件元数据读取
  • /api/design-state: 设计中心状态读写

3. 设计组件系统 (Design System)

组件构成

  1. 设计组件库 (designComponents/)

    • TextInput: 文本输入框属性label, width, maxLength
    • RadioSelect: 单选器属性options
    • GridTable: 表格属性rows, columns, headers
  2. 物料组件

    • DesignComponentList: 展示可用设计组件
    • DesignCenter: 展示已添加的设计组件实例
    • TreeViewer: 展示设计中心组件列表(支持拖拽排序)
    • DataTable: 展示选中组件的属性(支持编辑)

跨组件联动机制

  1. 点击 DesignComponentList 中的组件添加到 DesignCenter
  2. 点击 DesignCenter 中的组件,在 DataTable 中展示其属性
  3. 在 TreeViewer 中拖拽组件调整 DesignCenter 的顺序
  4. 在 DataTable 中双击属性值进行编辑

状态管理设计

PanelStore (面板状态)

管理整个应用的布局和物料组件状态:

  • layout: 三区域面板配置
  • materialStates: 物料组件状态独立存储
  • 提供 Tab 操作 API添加、关闭、移动、激活

DesignStore (设计中心状态)

管理设计组件系统的状态:

  • components: 已添加的设计组件实例列表
  • selectedId: 当前选中的组件实例ID
  • componentMetas: 设计组件元数据缓存

实现细节

1. 拖拽功能优化

  • 使用 :list 属性而非 v-model 解决拖拽位置问题
  • 实现跨面板 Tab 拖拽
  • 面板宽度可调整(通过 Resizer 组件)

2. 状态持久化策略

  • 布局配置和物料状态分别存储
  • 使用防抖机制避免频繁保存TextEditor 500ms
  • 组件移除后状态仍保留

3. 组件通信机制

  • 父子组件Props / Events
  • 兄弟组件:通过 Pinia Store
  • 物料组件:materialState / update:state

4. 性能优化

  • 使用 defineAsyncComponent 异步加载物料组件
  • 使用 markRaw 避免不必要的响应式转换
  • 使用 computed 缓存派生数据

API 设计

配置管理 API

GET  /api/config          # 获取布局配置
POST /api/config          # 保存布局配置
GET  /api/material-states # 获取物料组件状态
POST /api/material-states # 保存物料组件状态

设计系统 API

GET  /api/design-components # 获取设计组件元数据
GET  /api/design-state      # 获取设计中心状态
POST /api/design-state      # 保存设计中心状态

开发规范

代码规范

  1. 使用 TypeScript 严格模式
  2. 组件 Props 必须明确定义类型
  3. 使用 Composition API 组织代码逻辑
  4. 样式使用 scoped 避免全局污染

组件开发规范

  1. 遵循物料组件标准化规范
  2. 状态通过 materialState 接收,通过 update:state 更新
  3. 实现防抖保存机制避免频繁 IO
  4. 提供清晰的组件文档index.json

状态管理规范

  1. 使用 Pinia 进行全局状态管理
  2. 状态变更必须通过 Store 的方法
  3. 复杂状态逻辑封装在 Store 内部
  4. 状态持久化与 UI 逻辑分离

扩展性设计

新增物料组件

  1. materials/ 目录下创建组件文件夹
  2. 实现 index.vueindex.json
  3. materials/index.ts 中注册组件

新增设计组件

  1. designComponents/ 目录下创建组件文件夹
  2. 实现 index.vueindex.json
  3. 在 DesignComponentList 中会自动显示

功能扩展

  1. 面板系统支持更多布局模式
  2. 物料组件支持更多交互类型
  3. 设计系统支持更复杂的属性编辑器

总结

本项目实现了完整的可拖拽子窗口系统,具备良好的架构设计和扩展性。通过物料组件系统和设计组件系统的分离,既满足了基础的窗口管理需求,又提供了高级的设计能力。状态持久化机制确保了用户体验的连续性,而规范化的开发流程保证了项目的可维护性。