6.7 KiB
6.7 KiB
可拖拽子窗口项目设计文档
项目概述
本项目是一个基于 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)
规范标准
遵循统一的物料组件规范:
- 每个组件独立文件夹
- 包含
index.vue(组件实现)和index.json(元数据) index.json定义:名称、描述、属性及默认值
组件状态管理
- 使用
materialState属性传递组件状态 - 通过
update:state事件实现状态更新 - 物料组件状态独立存储,组件关闭后状态仍保留
状态持久化
通过自定义 Vite 插件实现 API 中间件:
/api/config: 布局配置读写/api/material-states: 物料组件状态读写/api/design-components: 设计组件元数据读取/api/design-state: 设计中心状态读写
3. 设计组件系统 (Design System)
组件构成
-
设计组件库 (
designComponents/)- TextInput: 文本输入框(属性:label, width, maxLength)
- RadioSelect: 单选器(属性:options)
- GridTable: 表格(属性:rows, columns, headers)
-
物料组件
- DesignComponentList: 展示可用设计组件
- DesignCenter: 展示已添加的设计组件实例
- TreeViewer: 展示设计中心组件列表(支持拖拽排序)
- DataTable: 展示选中组件的属性(支持编辑)
跨组件联动机制
- 点击 DesignComponentList 中的组件添加到 DesignCenter
- 点击 DesignCenter 中的组件,在 DataTable 中展示其属性
- 在 TreeViewer 中拖拽组件调整 DesignCenter 的顺序
- 在 DataTable 中双击属性值进行编辑
状态管理设计
PanelStore (面板状态)
管理整个应用的布局和物料组件状态:
layout: 三区域面板配置materialStates: 物料组件状态独立存储- 提供 Tab 操作 API(添加、关闭、移动、激活)
DesignStore (设计中心状态)
管理设计组件系统的状态:
components: 已添加的设计组件实例列表selectedId: 当前选中的组件实例IDcomponentMetas: 设计组件元数据缓存
实现细节
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 # 保存设计中心状态
开发规范
代码规范
- 使用 TypeScript 严格模式
- 组件 Props 必须明确定义类型
- 使用 Composition API 组织代码逻辑
- 样式使用 scoped 避免全局污染
组件开发规范
- 遵循物料组件标准化规范
- 状态通过
materialState接收,通过update:state更新 - 实现防抖保存机制避免频繁 IO
- 提供清晰的组件文档(index.json)
状态管理规范
- 使用 Pinia 进行全局状态管理
- 状态变更必须通过 Store 的方法
- 复杂状态逻辑封装在 Store 内部
- 状态持久化与 UI 逻辑分离
扩展性设计
新增物料组件
- 在
materials/目录下创建组件文件夹 - 实现
index.vue和index.json - 在
materials/index.ts中注册组件
新增设计组件
- 在
designComponents/目录下创建组件文件夹 - 实现
index.vue和index.json - 在 DesignComponentList 中会自动显示
功能扩展
- 面板系统支持更多布局模式
- 物料组件支持更多交互类型
- 设计系统支持更复杂的属性编辑器
总结
本项目实现了完整的可拖拽子窗口系统,具备良好的架构设计和扩展性。通过物料组件系统和设计组件系统的分离,既满足了基础的窗口管理需求,又提供了高级的设计能力。状态持久化机制确保了用户体验的连续性,而规范化的开发流程保证了项目的可维护性。