Files
vue-desktop/.qoder/quests/ui-modularization.md
2025-09-28 14:32:00 +08:00

9.9 KiB
Raw Blame History

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 现有架构分析

项目当前已具备良好的分层架构,但存在部分逻辑混合的情况:

  1. UI层包含Vue组件和部分业务逻辑
  2. 状态管理层使用Pinia管理全局状态
  3. 核心服务层SystemServiceIntegration统一管理系统服务
  4. 依赖注入通过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机制实现服务注入

  1. 在main.ts中创建并提供SystemServiceIntegration实例
  2. UI组件通过inject获取系统服务
  3. 系统服务提供统一的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模块独立化步骤

  1. 创建独立的UI模块目录结构

    • 将现有的UI组件按功能重新组织
    • 分离展示组件和容器组件
  2. 抽离业务逻辑到核心服务

    • 将应用启动逻辑移至SystemServiceIntegration
    • 将状态管理移至Pinia stores
  3. 重构组件数据流

    • 使用props传递数据
    • 使用emit触发事件
    • 通过状态管理实现响应式更新

6.2 现有组件优化

  1. DesktopContainer组件

    • 保持现有的inject机制获取系统服务
    • 将应用启动逻辑完全委托给系统服务
    • 通过响应式数据驱动UI更新
  2. AppIcon组件

    • 保持纯展示组件特性
    • 通过事件与父组件通信
  3. WindowManager组件

    • 保持现有的窗口管理逻辑
    • 通过inject获取系统服务
  4. AppRenderer组件

    • 负责应用渲染逻辑
    • 支持内置应用和外部应用渲染
    • 内置应用使用Vue组件直接渲染
    • 外部应用使用iframe加载渲染

6.3 核心改造点

6.3.1 DesktopContainer组件改造

当前的DesktopContainer组件包含了太多业务逻辑需要进行以下优化

  1. 保持组件结构:无需拆分为多个组件,但需明确职责划分
  2. 业务逻辑委托:将应用启动等业务逻辑完全委托给系统服务
  3. 状态管理优化通过响应式数据驱动UI更新

6.3.2 应用启动流程优化

graph TD
    A[用户双击图标] --> B[DesktopContainer组件]
    B --> C[调用系统服务]
    C --> D[SystemServiceIntegration]
    D --> E[ApplicationLifecycleManager]
    E --> F[创建应用实例]

6.3.3 子应用加载机制

项目需要支持两种类型的应用加载:

  1. 内置应用加载

    • 直接使用Vue 3组件加载机制
    • 通过AppRegistry获取应用组件
    • 无需异步加载,立即渲染
  2. 外部应用加载

    • 使用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 现有测试策略优化

项目已具备基本的测试框架,建议:

  1. 增加对展示组件的单元测试
  2. 完善容器组件与服务的集成测试
  3. 建立端到端测试覆盖核心用户场景