跳转至

项目架构

本文档详细介绍 EasyKiConverter 项目的架构设计。

架构概览

EasyKiConverter 采用 MVVM (Model-View-ViewModel) 架构模式,提供清晰的职责分离和高效的代码组织。

架构模式

MVVM 架构

项目使用 MVVM 架构模式,将应用程序分为四个主要层次:

┌─────────────────────────────────────────┐
│              View Layer                  │
│         (QML Components)                 │
│  - MainWindow.qml                        │
│  - Components (Card, Button, etc.)       │
│  - Styles (AppStyle)                     │
└──────────────┬──────────────────────────┘
┌──────────────▼──────────────────────────┐
│          ViewModel Layer                │
│  ┌──────────────────────────────────┐   │
│  │ ComponentListViewModel          │   │
│  │ - 管理元件列表状态                │   │
│  │ - 处理用户输入                    │   │
│  │ - 调用 ComponentService          │   │
│  └──────────────────────────────────┘   │
│  ┌──────────────────────────────────┐   │
│  │ ExportSettingsViewModel         │   │
│  │ - 管理导出设置状态                │   │
│  │ - 处理配置更改                    │   │
│  │ - 调用 ConfigService             │   │
│  └──────────────────────────────────┘   │
│  ┌──────────────────────────────────┐   │
│  │ ExportProgressViewModel         │   │
│  │ - 管理导出进度状态                │   │
│  │ - 显示转换结果                    │   │
│  │ - 调用 ExportService             │   │
│  └──────────────────────────────────┘   │
│  ┌──────────────────────────────────┐   │
│  │ ThemeSettingsViewModel          │   │
│  │ - 管理主题设置状态                │   │
│  │ - 处理深色/浅色模式切换           │   │
│  │ - 调用 ConfigService             │   │
│  └──────────────────────────────────┘   │
└──────────────┬──────────────────────────┘
┌──────────────▼──────────────────────────┐
│           Service Layer                  │
│  ┌──────────────────────────────────┐   │
│  │ ComponentService                 │   │
│  │ - 元件数据获取                    │   │
│  │ - 元件验证                        │   │
│  │ - 调用 EasyedaApi                │   │
│  └──────────────────────────────────┘   │
│  ┌──────────────────────────────────┐   │
│  │ ExportService                    │   │
│  │ - 符号/封装/3D模型导出            │   │
│  │ - 并行转换管理                    │   │
│  │ - 调用 Exporter*                 │   │
│  └──────────────────────────────────┘   │
│  ┌──────────────────────────────────┐   │
│  │ ConfigService                    │   │
│  │ - 配置加载/保存                   │   │
│  │ - 主题管理                        │   │
│  │ - 调用 ConfigManager             │   │
│  └──────────────────────────────────┘   │
│  ┌──────────────────────────────────┐   │
│  │ ComponentDataCollector           │   │
│  │ - 状态机模式                      │   │
│  │ - 异步数据收集                    │   │
│  │ - 两阶段导出                      │   │
│  └──────────────────────────────────┘   │
└──────────────┬──────────────────────────┘
┌──────────────▼──────────────────────────┐
│            Model Layer                   │
│  ┌──────────────────────────────────┐   │
│  │ ComponentData                    │   │
│  │ - 元件基本信息                    │   │
│  │ - 符号/封装/3D模型数据            │   │
│  └──────────────────────────────────┘   │
│  ┌──────────────────────────────────┐   │
│  │ SymbolData                       │   │
│  │ - 符号几何数据                    │   │
│  │ - 引脚信息                        │   │
│  └──────────────────────────────────┘   │
│  ┌──────────────────────────────────┐   │
│  │ FootprintData                    │   │
│  │ - 封装几何数据                    │   │
│  │ - 焊盘信息                        │   │
│  └──────────────────────────────────┘   │
│  ┌──────────────────────────────────┐   │
│  │ Model3DData                      │   │
│  │ - 3D模型数据                      │   │
│  │ - 模型UUID                        │   │
│  └──────────────────────────────────┘   │
└─────────────────────────────────────────┘

层次职责

View 层(视图层)

View 层负责用户界面的展示和用户交互,使用 QML 实现。

主要组件: - MainWindow.qml - 主窗口 - components/Card.qml - 卡片容器组件 - components/ModernButton.qml - 现代化按钮组件 - components/Icon.qml - 图标组件 - components/ComponentListItem.qml - 元件列表项组件 - components/ResultListItem.qml - 结果列表项组件 - styles/AppStyle.qml - 全局样式系统

职责: - 界面布局和展示 - 用户输入接收 - 动画效果 - 主题切换

ViewModel 层(视图模型层)

ViewModel 层负责管理 UI 状态和业务逻辑调用,作为 View 和 Model 之间的桥梁。

主要类: - ComponentListViewModel - 元件列表视图模型 - ExportSettingsViewModel - 导出设置视图模型 - ExportProgressViewModel - 导出进度视图模型 - ThemeSettingsViewModel - 主题设置视图模型

职责: - 管理 UI 状态 - 处理用户输入 - 调用 Service 层 - 数据绑定和转换

Service 层(服务层)

Service 层负责业务逻辑的处理,提供核心功能。

主要类: - ComponentService - 元件服务 - ExportService - 导出服务 - ConfigService - 配置服务 - ComponentDataCollector - 元件数据收集器(状态机模式) - ComponentExportTask - 元件导出任务

职责: - 业务逻辑处理 - 数据验证 - 调用底层 API - 管理转换流程

Model 层(模型层)

Model 层负责数据的存储和管理。

主要类: - ComponentData - 元件数据模型 - SymbolData - 符号数据模型 - FootprintData - 封装数据模型 - Model3DData - 3D 模型数据模型

职责: - 数据存储 - 数据验证 - 数据序列化

核心模块

转换引擎(Core)

转换引擎负责实际的转换工作,位于 src/core 目录。

EasyEDA 模块: - EasyedaApi - EasyEDA API 客户端 - EasyedaImporter - 数据导入器 - JLCDatasheet - JLC 数据表解析

KiCad 模块: - ExporterSymbol - 符号导出器 - ExporterFootprint - 封装导出器 - Exporter3DModel - 3D 模型导出器

工具模块: - GeometryUtils - 几何计算工具 - NetworkUtils - 网络请求工具 - LayerMapper - 图层映射工具

工作线程(Workers)

工作线程负责后台任务处理,位于 src/workers 目录。

  • ExportWorker - 导出工作线程(基础)
  • NetworkWorker - 网络工作线程
  • FetchWorker - 抓取工作线程(流水线阶段一)
  • ProcessWorker - 处理工作线程(流水线阶段二)
  • WriteWorker - 写入工作线程(流水线阶段三)

流水线并行架构

架构概述

项目实现了三阶段流水线并行架构,用于批量导出元件数据,最大化性能。

┌─────────────────────────────────────────────────────────────────┐
│                    流水线并行架构                                  │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  ┌─────────────┐    ┌───────────────┐    ┌─────────────┐       │
│  │  Fetch      │───▶│  Process      │───▶│   Write     │       │
│  │  Stage      │    │  Stage        │    │   Stage     │       │
│  │             │    │               │    │             │       │
│  │ • 组件信息  │    │ • 解析 JSON   │    │ • 写符号    │       │
│  │ • CAD 数据  │    │ • 转换格式     │    │ • 写封装    │       │
│  │ • 3D 模型   │    │ • 几何计算     │    │ • 写 3D 模型│       │
│  └─────────────┘    └───────────────┘    └─────────────┘       │
│         │                    │                    │               │
│         ▼                    ▼                    ▼               │
│   32 threads           N cores             8 threads           │
│   (I/O 密集型)        (CPU 密集型)        (磁盘 I/O 密集型)     │
│                                                                  │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │         线程安全有界队列(BoundedThreadSafeQueue)        │   │
│  │  ┌─────────────────────┐    ┌──────────────────────┐     │   │
│  │  │  FetchProcessQueue  │───▶│  ProcessWriteQueue  │     │   │
│  │  │   (大小动态调整)      │    │   (大小动态调整)     │     │   │
│  │  └─────────────────────┘    └──────────────────────┘     │   │
│  └──────────────────────────────────────────────────────────┘   │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

三阶段详解

阶段一:抓取阶段(Fetch Stage)

职责:从网络下载所有原始数据

线程池配置: - 线程数:32(I/O 密集型) - 适合:大量网络请求并发

任务: - 获取组件信息(包含 CAD 数据) - 下载 3D 模型(OBJ 和 STEP 格式) - 处理 GZIP/ZIP 压缩数据 - 使用 QSharedPointer 避免数据拷贝

Worker: FetchWorker

特点: - 纯 I/O 密集型 - 使用同步网络请求(QEventLoop) - 支持自动重试(待实现)


阶段二:处理阶段(Process Stage)

职责:解析和转换数据

线程池配置: - 线程数:等于 CPU 核心数(CPU 密集型) - 适合:大量 CPU 计算

任务: - 解析组件信息 JSON - 解析 CAD 数据 JSON - 解析 3D 模型数据(OBJ 格式) - 生成 KiCad 符号数据 - 生成 KiCad 封装数据 - 几何计算和转换

Worker: ProcessWorker

特点: - 纯 CPU 密集型(不包含任何网络 I/O) - 使用 EasyedaImporter 进行数据导入 - 零数据拷贝(使用 QSharedPointer)


阶段三:写入阶段(Write Stage)

职责:将转换后的数据写入文件

线程池配置: - 线程数:8(磁盘 I/O 密集型) - 适合:大量文件写入

任务: - 写入符号库文件(.kicad_sym) - 写入封装文件(.kicad_mod) - 写入 3D 模型文件(.wrl、.step) - 合并符号库(临时文件) - 导出调试数据(如果启用)

Worker: WriteWorker

特点: - 并行写入:单个组件的符号、封装、3D 模型同时写入 - 使用 QThreadPool 实现并行 - 避免文件写入冲突


阶段间通信

线程安全有界队列

队列类型

BoundedThreadSafeQueue<QSharedPointer<ComponentExportStatus>> *m_queue;

特点: - 线程安全(使用 QMutex 和 QWaitCondition) - 有界(防止内存溢出) - 支持阻塞和非阻塞操作 - 使用 QSharedPointer 避免数据拷贝

队列大小: - 动态调整:任务数的 1/4 - 最小值:100 - 避免队列满导致的阻塞


进度计算

三阶段进度权重: - Fetch 阶段:30% - Process 阶段:50% - Write 阶段:20%

总进度计算

int overallProgress() {
    return (fetchProgress() * 30 + 
            processProgress() * 50 + 
            writeProgress() * 20) / 100;
}

进度反馈: - 实时更新各阶段进度 - 显示当前处理的元件 - 显示预估剩余时间


性能优化

P0 改进(架构优化)

  1. ProcessWorker 移除网络请求
  2. CPU 利用率提升 50-80%
  3. 充分利用多核 CPU

  4. 使用 QSharedPointer 传递数据

  5. 内存占用减少 50-70%
  6. 性能提升 20-30%

  7. 调整 ProcessWorker 为纯 CPU 密集型

  8. CPU 利用率提升 40-60%

P1 改进(性能优化)

  1. 动态队列大小
  2. 避免队列满导致的阻塞
  3. 吞吐量提升 15-25%

  4. 并行写入文件

  5. 写入阶段耗时减少 30-50%
  6. 磁盘 I/O 并发度提升 2-3 倍

数据流

用户输入元件ID
ExportServicePipeline.executeExportPipelineWithStages()
┌─────────────────────────────────────────────┐
│  Fetch Stage (32 threads)                    │
│  • 下载组件信息                              │
│  • 下载 CAD 数据                             │
│  • 下载 3D 模型                              │
└─────────────────────────────────────────────┘
    ↓ (QSharedPointer<ComponentExportStatus>)
┌─────────────────────────────────────────────┐
│  Process Stage (N cores)                     │
│  • 解析 JSON                                 │
│  • 转换格式                                  │
│  • 几何计算                                  │
└─────────────────────────────────────────────┘
    ↓ (QSharedPointer<ComponentExportStatus>)
┌─────────────────────────────────────────────┐
│  Write Stage (8 threads)                     │
│  • 并行写入符号、封装、3D 模型               │
│  • 合并符号库                                │
└─────────────────────────────────────────────┘
完成导出

错误处理

失败诊断: - 精确识别失败阶段(Fetch/Process/Write) - 详细的错误消息 - 调试日志记录

容错机制: - 3D 模型下载失败不影响整体流程 - 单个元件失败不影响其他元件 - 支持部分成功导出


性能指标

预期性能(100 个元件):

指标 改进前 改进后 提升
总耗时 240 秒 110 秒 54%
吞吐量 0.42 组件/秒 0.91 组件/秒 117%
内存使用 400 MB 200 MB 50%
CPU 利用率 60% 90% 50%

设计模式

状态机模式

ComponentDataCollector 使用状态机模式管理数据收集过程。

状态: - Idle - 空闲状态 - Collecting - 收集中 - Completed - 已完成 - Error - 错误状态

两阶段导出策略

优化批量转换性能的两阶段策略。

阶段一:数据收集(并行) - 使用多线程并行收集所有元件数据 - 充分利用多核 CPU 性能 - 异步网络请求

阶段二:数据导出(串行) - 串行导出所有收集到的数据 - 避免文件写入冲突 - 保证数据一致性

单例模式

ConfigService 使用单例模式确保配置管理的一致性。

观察者模式

使用 Qt 信号槽机制实现观察者模式,实现组件间的松耦合通信。

数据流

用户交互流程

  1. 用户在 View 层输入元件编号
  2. ViewModel 接收用户输入,验证数据
  3. ViewModel 调用 Service 层处理业务逻辑
  4. Service 层调用 Core 层的转换引擎
  5. Core 层返回转换结果给 Service 层
  6. Service 层返回结果给 ViewModel
  7. ViewModel 更新状态,View 自动刷新

转换流程

  1. 数据收集阶段
  2. ComponentService 调用 EasyedaApi 获取元件数据
  3. ComponentDataCollector 使用状态机管理收集过程
  4. 多线程并行收集数据

  5. 数据导出阶段

  6. ExportService 调用 Exporter* 进行导出
  7. 串行导出避免文件冲突
  8. 实时更新进度状态

技术栈

编程语言

  • C++17

UI 框架

  • Qt 6.10.1
  • Qt Quick
  • Qt Quick Controls 2

构建系统

  • CMake 3.16+

多线程

  • QThreadPool
  • QRunnable
  • QMutex

网络库

  • Qt Network

压缩库

  • zlib

目录结构

EasyKiConverter_QT/
├── src/
│   ├── core/                   # 核心转换引擎
│   │   ├── easyeda/            # EasyEDA 相关
│   │   ├── kicad/              # KiCad 相关
│   │   └── utils/              # 工具类
│   ├── models/                 # 数据模型
│   ├── services/               # 服务层
│   ├── ui/                     # UI 层
│   │   ├── qml/                # QML 界面
│   │   ├── viewmodels/         # 视图模型
│   │   └── utils/              # UI 工具
│   └── workers/                # 工作线程
├── tests/                      # 测试
├── docs/                       # 文档
└── resources/                  # 资源文件

扩展性

添加新的转换器

  1. src/core/kicad/ 中创建新的导出器类
  2. 继承相应的基类
  3. 实现导出逻辑
  4. 在 ExportService 中注册

添加新的 ViewModel

  1. src/ui/viewmodels/ 中创建新的 ViewModel 类
  2. 继承 QObject
  3. 添加必要的属性和方法
  4. 在 main.cpp 中注册到 QML 上下文

添加新的 Service

  1. src/services/ 中创建新的 Service 类
  2. 实现业务逻辑
  3. 在 ViewModel 中调用

性能优化

并行处理

  • 使用 QThreadPool 管理线程池
  • 多线程并行数据收集
  • 线程安全的数据访问

内存管理

  • 使用智能指针管理资源
  • RAII 原则
  • 避免内存泄漏

网络优化

  • 自动重试机制
  • GZIP 解压缩
  • 连接池管理

安全性

输入验证

  • 元件编号格式验证
  • 文件路径验证
  • 配置参数验证

错误处理

  • 异常捕获
  • 错误日志
  • 用户友好的错误提示

可维护性

代码规范

  • 遵循 Qt 编码规范
  • 使用 Doxygen 注释
  • 代码审查

测试覆盖

  • 单元测试
  • 集成测试
  • 性能测试

文档完整

  • API 文档
  • 架构文档
  • 用户指南