9.9 KiB
9.9 KiB
UI模块化设计方案
1. 概述
本方案旨在将当前项目中的UI组件与核心业务逻辑进行彻底分离,实现UI层只负责数据渲染,核心层专注于数据处理的架构模式。通过模块化重构,提高代码的可维护性、可测试性和可扩展性。
1.1 设计目标
- 实现UI层与核心业务逻辑的完全解耦
- UI组件只负责接收数据并渲染,不包含任何业务逻辑
- 核心服务层提供统一的数据接口和状态管理
- 通过响应式数据绑定实现UI与数据的自动同步
1.2 核心原则
- 数据驱动: UI组件通过props接收数据,通过事件触发操作
- 单一职责: UI组件只负责渲染,核心服务只负责数据处理
- 响应式更新: 数据变化自动触发UI更新
- 模块化设计: 各模块职责清晰,依赖关系明确
1.3 项目现状分析
当前项目已经具备良好的分层架构:
- 使用Pinia进行状态管理
- 通过依赖注入提供系统服务
- UI组件与核心服务之间通过明确定义的接口交互
- 采用Vue 3 Composition API实现逻辑复用
2. 架构设计
2.1 整体架构图
graph TD
A[UI层] --> B[状态管理层]
B --> C[核心服务层]
C --> D[数据源]
C --> E[外部API]
B --> A
subgraph UI层
A
end
subgraph 核心层
B
C
D
E
end
2.2 现有架构分析
项目当前已具备良好的分层架构,但存在部分逻辑混合的情况:
- UI层:包含Vue组件和部分业务逻辑
- 状态管理层:使用Pinia管理全局状态
- 核心服务层:SystemServiceIntegration统一管理系统服务
- 依赖注入:通过Vue的provide/inject机制传递系统服务
2.3 模块划分优化
| 模块 | 职责 | 包含内容 |
|---|---|---|
| UI组件模块 | 负责界面展示和用户交互 | 所有Vue组件、样式文件 |
| 状态管理模块 | 管理应用状态和数据流 | Pinia stores、响应式数据 |
| 核心服务模块 | 处理业务逻辑和数据操作 | 系统服务、应用管理、窗体管理等 |
| 工具模块 | 提供通用工具函数 | 工具函数、类型定义 |
3. UI模块重构方案
3.1 当前结构分析
当前项目UI相关代码分散在以下目录中:
src/ui/: 主要UI组件src/apps/: 内置应用组件src/common/: 通用UI工具和组件
3.2 重构后的UI模块结构
src/
├── ui/
│ ├── components/ # 通用UI组件
│ ├── containers/ # 容器组件
│ ├── views/ # 页面视图组件
│ ├── composables/ # UI专用组合式函数
│ ├── styles/ # 样式文件
│ └── types/ # UI相关类型定义
├── core/ # 核心业务逻辑(从UI中抽离)
├── stores/ # 状态管理
└── services/ # 核心服务层
3.3 UI组件分类
3.3.1 展示组件(Pure Components)
展示组件只负责接收数据并渲染,不包含任何业务逻辑:
| 组件名称 | 职责 | 输入数据 | 输出事件 |
|---|---|---|---|
| AppIcon | 应用图标展示 | iconInfo, gridTemplate | dragStart, dragEnd, doubleClick |
| AppRenderer | 应用渲染器 | appId, windowId | loaded, error |
3.3.2 容器组件(Container Components)
容器组件负责连接展示组件与状态管理:
| 组件名称 | 职责 | 连接状态 | 业务逻辑 |
|---|---|---|---|
| DesktopContainer | 桌面容器 | appIcons, systemStatus | 应用启动、状态更新 |
| WindowManager | 窗口管理器 | windows | 窗口创建、销毁 |
| AppRenderer | 应用渲染器 | appComponent, iframeUrl | 应用加载、错误处理 |
4. 数据流设计
4.1 数据流向图
graph LR
A[核心服务] --> B[状态管理]
B --> C[UI组件]
C --> D[用户操作]
D --> E[事件处理]
E --> A
style A fill:#cde4ff
style B fill:#ffd7c1
style C fill:#d3f8d3
style D fill:#fff2c1
style E fill:#e6d7ff
4.2 状态管理设计
项目已使用Pinia进行状态管理,建议继续沿用并扩展:
4.2.1 桌面状态
interface DesktopState {
appIcons: IDesktopAppIcon[]
gridTemplate: IGridTemplateParams
systemStatus: SystemStatus
showSystemStatus: boolean
}
4.2.2 窗口状态
interface WindowState {
windows: BuiltInWindow[]
activeWindowId: string | null
}
4.3 数据获取与更新流程
sequenceDiagram
participant U as UI组件
participant S as 状态管理
participant C as 核心服务
U->>S: 读取状态数据
S-->>U: 返回响应式数据
U->>U: 渲染界面
U->>C: 触发用户操作
C->>S: 更新状态
S->>U: 自动更新界面
4.4 依赖注入机制
项目通过Vue的provide/inject机制实现服务注入:
- 在main.ts中创建并提供SystemServiceIntegration实例
- UI组件通过inject获取系统服务
- 系统服务提供统一的API访问核心功能
5. 接口设计
5.1 UI组件接口规范
5.1.1 展示组件接口
// AppIcon组件接口
interface AppIconProps {
iconInfo: IDesktopAppIcon
gridTemplate: IGridTemplateParams
}
interface AppIconEvents {
(e: 'dragStart', event: DragEvent): void
(e: 'dragEnd', event: DragEvent): void
(e: 'doubleClick'): void
}
// AppRenderer组件接口
interface AppRendererProps {
appId: string
windowId?: string
}
interface AppRendererEvents {
(e: 'loaded'): void
(e: 'error', error: Error): void
}
5.1.2 容器组件接口
// DesktopContainer组件接口
interface DesktopContainerProps {
// 无需props,直接从状态管理获取数据
}
interface DesktopContainerMethods {
refreshApps(): Promise<void>
runApp(appId: string): Promise<void>
}
5.2 状态管理接口
5.2.1 桌面状态接口
interface DesktopStore {
// 状态
appIcons: Ref<IDesktopAppIcon[]>
gridTemplate: Ref<IGridTemplateParams>
systemStatus: Ref<SystemStatus>
showSystemStatus: Ref<boolean>
// Getters
gridStyle: ComputedRef<GridStyle>
// Actions
updateAppIcons(icons: IDesktopAppIcon[]): void
updateSystemStatus(status: SystemStatus): void
toggleSystemStatus(show: boolean): void
saveIconPositions(): void
}
6. 实现方案
6.1 UI模块独立化步骤
-
创建独立的UI模块目录结构
- 将现有的UI组件按功能重新组织
- 分离展示组件和容器组件
-
抽离业务逻辑到核心服务
- 将应用启动逻辑移至SystemServiceIntegration
- 将状态管理移至Pinia stores
-
重构组件数据流
- 使用props传递数据
- 使用emit触发事件
- 通过状态管理实现响应式更新
6.2 现有组件优化
-
DesktopContainer组件
- 保持现有的inject机制获取系统服务
- 将应用启动逻辑完全委托给系统服务
- 通过响应式数据驱动UI更新
-
AppIcon组件
- 保持纯展示组件特性
- 通过事件与父组件通信
-
WindowManager组件
- 保持现有的窗口管理逻辑
- 通过inject获取系统服务
-
AppRenderer组件
- 负责应用渲染逻辑
- 支持内置应用和外部应用渲染
- 内置应用使用Vue组件直接渲染
- 外部应用使用iframe加载渲染
6.3 核心改造点
6.3.1 DesktopContainer组件改造
当前的DesktopContainer组件包含了太多业务逻辑,需要进行以下优化:
- 保持组件结构:无需拆分为多个组件,但需明确职责划分
- 业务逻辑委托:将应用启动等业务逻辑完全委托给系统服务
- 状态管理优化:通过响应式数据驱动UI更新
6.3.2 应用启动流程优化
graph TD
A[用户双击图标] --> B[DesktopContainer组件]
B --> C[调用系统服务]
C --> D[SystemServiceIntegration]
D --> E[ApplicationLifecycleManager]
E --> F[创建应用实例]
6.3.3 子应用加载机制
项目需要支持两种类型的应用加载:
-
内置应用加载:
- 直接使用Vue 3组件加载机制
- 通过AppRegistry获取应用组件
- 无需异步加载,立即渲染
-
外部应用加载:
- 使用iframe沙箱环境加载
- 通过ExternalAppDiscovery发现应用
- 异步加载应用资源
- 外部加载逻辑可暂时留空,后期实现
6.4 依赖注入优化
项目已通过Vue的provide/inject机制实现服务注入,建议保持现有模式并进行优化:
// main.ts - 保持现有实现
app.provide('systemService', systemService)
// UI组件中使用 - 保持现有实现
const systemService = inject<SystemServiceIntegration>('systemService')
// 建议添加类型安全检查
const systemService = inject<SystemServiceIntegration>('systemService')
if (!systemService) {
throw new Error('系统服务未正确注入')
}
7. 测试策略
7.1 UI组件测试
- 展示组件:测试不同props输入下的渲染结果
- 容器组件:测试与状态管理和服务的交互
7.2 状态管理测试
- 测试状态更新的正确性
- 测试响应式数据的自动更新
7.3 集成测试
- 测试完整的数据流和用户操作流程
- 验证UI与核心服务的交互正确性
7.4 现有测试策略优化
项目已具备基本的测试框架,建议:
- 增加对展示组件的单元测试
- 完善容器组件与服务的集成测试
- 建立端到端测试覆盖核心用户场景