Files
cmbot/docs/05-project-architecture.md
T

422 lines
9.4 KiB
Markdown

# 项目架构
## 1. 文档定位
本文档定义项目代码结构、模块职责和依赖方向。后续 AI 或开发者在新增功能、修复问题、重构代码时,必须遵守本文档。
本文档不描述具体 UI 细节和图像编辑算法细节。拖动、缩放、旋转、坐标换算等细节应放在图像编辑器设计文档中。
## 2. 架构目标
- 避免所有逻辑集中在一个窗口类或一个入口文件中。
- 让 UI、图片合成、模板、配置、批量任务、日志职责清晰分离。
- 让核心图片合成逻辑可以脱离 GUI 单独测试。
- 让单张合成和批量合成复用同一套核心逻辑。
- 让后续 AI 执行小任务时能快速定位应修改的模块。
## 3. 推荐目录结构
```text
src/
main.py
version.py
app/
__init__.py
main_window.py
widgets/
__init__.py
image_canvas.py
image_list_panel.py
template_panel.py
transform_panel.py
export_panel.py
core/
__init__.py
models.py
composer.py
batch.py
services/
__init__.py
config_service.py
template_service.py
file_service.py
log_service.py
resources/
icons/
styles/
tests/
test_composer.py
test_templates.py
docs/
```
说明:
- `src/main.py` 是程序入口,只负责创建应用和主窗口。
- `src/version.py` 统一维护软件名称和版本号。
- `app/` 放 GUI 相关代码。
- `core/` 放与 GUI 无关的核心模型、合成和批量处理逻辑。
- `services/` 放配置、模板、文件扫描、日志等服务。
- `resources/` 放图标、样式等静态资源。
- `tests/` 放自动化测试。
## 4. 模块职责
### 4.1 `src/main.py`
职责:
- 初始化 Qt 应用。
- 初始化日志。
- 创建并显示主窗口。
- 进入应用事件循环。
禁止:
- 禁止在入口文件中写图片合成逻辑。
- 禁止在入口文件中写复杂 UI 布局。
- 禁止在入口文件中直接读写模板和配置细节。
### 4.2 `src/version.py`
职责:
- 统一定义软件名称。
- 统一定义当前版本号。
- 为标题栏、关于信息、打包发布配置提供版本来源。
建议字段:
```text
APP_NAME
APP_VERSION
```
禁止:
- 禁止在其他模块重复硬编码软件名称和版本号。
- 禁止让 UI 显示版本号与打包发布版本号不一致。
### 4.3 `app/main_window.py`
职责:
- 组织主界面布局。
- 协调各 UI 面板。
- 连接用户操作与服务调用。
- 管理当前选中的衣服图、印花图和模板状态。
禁止:
- 禁止直接实现底层图片合成算法。
- 禁止直接写入配置文件细节。
- 禁止堆叠大量按钮事件中的业务逻辑。
### 4.4 `app/widgets/image_canvas.py`
职责:
- 显示衣服底图和印花图。
- 承载印花拖动、缩放、旋转交互。
- 将 UI 交互结果转换为统一的变换状态。
- 通知外部坐标、尺寸、角度变化。
禁止:
- 禁止直接导出最终图片文件。
- 禁止直接管理批量任务。
- 禁止把屏幕坐标直接作为最终合成坐标。
### 4.5 `app/widgets/image_list_panel.py`
职责:
- 显示衣服图片列表和印花图片列表。
- 支持选择文件夹、全选、取消全选。
- 通知主窗口当前选择变化。
禁止:
- 禁止直接执行图片合成。
- 禁止直接修改图片文件。
### 4.6 `app/widgets/template_panel.py`
职责:
- 显示内置模板和自定义模板。
- 处理模板选择、新增、重命名、删除等 UI 操作。
- 通过 `template_service` 读取和保存模板。
禁止:
- 禁止在 UI 控件中硬编码所有模板逻辑。
- 禁止直接绕过 `template_service` 修改模板文件。
### 4.7 `app/widgets/transform_panel.py`
职责:
- 显示和编辑印花的 X/Y 坐标、宽度、高度、旋转角度。
- 用户修改参数后通知预览区更新。
- 预览区交互变化后同步显示最新参数。
禁止:
- 禁止自己维护一套与预览区不一致的状态。
- 禁止只更新输入框但不更新预览。
### 4.8 `app/widgets/export_panel.py`
职责:
- 选择输出目录。
- 设置输出格式和质量。
- 触发单张合成和批量合成。
- 显示合成进度和结果摘要。
禁止:
- 禁止直接写底层图像合成算法。
- 禁止批量处理时阻塞主界面且没有进度反馈。
### 4.9 `core/models.py`
职责:
- 定义核心数据模型。
- 统一表示图片文件、印花变换参数、模板、导出选项、批量任务结果。
建议模型:
```text
ImageAsset
TransformState
Template
ExportOptions
BatchOptions
ComposeResult
BatchResult
```
禁止:
- 禁止在模型文件中引入 PySide6 UI 控件。
- 禁止在模型文件中执行文件扫描或图片导出。
### 4.10 `core/composer.py`
职责:
- 实现单张图片合成。
- 根据衣服底图、印花图、变换参数和导出选项生成结果图。
- 保证透明 PNG 正确叠加。
- 保证导出结果与预览参数一致。
禁止:
- 禁止依赖 PySide6 UI 控件。
- 禁止读取 UI 输入框。
- 禁止处理文件夹批量遍历逻辑。
### 4.11 `core/batch.py`
职责:
- 实现批量合成任务编排。
- 支持一一匹配和全组合模式。
- 复用 `core/composer.py` 的单张合成能力。
- 汇总成功、失败和错误信息。
禁止:
- 禁止复制一套独立于 `composer.py` 的合成算法。
- 禁止因单个文件失败中断整个批量任务。
### 4.12 `services/config_service.py`
职责:
- 读取和保存应用配置。
- 管理默认配置。
- 在配置损坏或缺失时提供安全默认值。
禁止:
- 禁止在多个模块中重复解析同一个配置文件。
- 禁止启动时无提示清空用户配置。
### 4.13 `services/template_service.py`
职责:
- 加载内置模板。
- 加载、保存、重命名、删除自定义模板。
- 校验模板字段是否合法。
禁止:
- 禁止让 UI 直接操作模板 JSON 文件。
- 禁止单个模板损坏导致全部模板不可用。
### 4.14 `services/file_service.py`
职责:
- 扫描图片文件夹。
- 过滤支持的图片格式。
- 生成安全输出文件名。
- 处理 Windows 中文路径。
禁止:
- 禁止在 UI 层重复实现文件扫描规则。
- 禁止默认覆盖已有输出文件,除非用户确认。
### 4.15 `services/log_service.py`
职责:
- 初始化日志系统。
- 统一日志格式。
- 管理日志文件路径。
禁止:
- 禁止业务模块各自创建不一致的日志配置。
- 禁止用 `print` 代替正式日志。
## 5. 依赖方向
允许的依赖方向:
```text
main.py -> app
app -> core
app -> services
core -> services 仅限必要的纯工具能力
services -> core models 可选
tests -> core
tests -> services
```
推荐依赖关系:
```text
UI 层负责收集用户输入
UI 层把输入转换为 core models
core 层执行合成或批量任务
services 层处理配置、模板、文件和日志
UI 层展示结果和错误信息
```
禁止的依赖方向:
```text
core -> app
services -> app
models -> app
composer -> PySide6 UI 控件
batch -> PySide6 UI 控件
```
## 6. 状态管理
主窗口维护当前工作状态:
- 当前衣服图片。
- 当前印花图片。
- 当前印花变换参数。
- 当前模板。
- 当前输出配置。
印花变换参数必须使用统一模型表示,例如:
```text
TransformState
x
y
width
height
rotation
keep_aspect_ratio
```
规则:
- 预览区变化后更新 `TransformState`。
- 参数面板变化后更新同一个 `TransformState`。
- 单张导出和批量导出都读取同一个 `TransformState` 或模板转换结果。
- 不允许 UI 面板各自维护互不一致的状态。
## 7. 单张合成流程
```text
用户选择衣服图和印花图
-> 主窗口更新当前状态
-> 预览区显示衣服和印花
-> 用户拖动、缩放、旋转或输入参数
-> 更新 TransformState
-> 用户点击单张导出
-> export_panel 构造 ExportOptions
-> core.composer 执行合成
-> file_service 生成输出路径
-> 保存结果
-> UI 显示成功或失败
```
## 8. 批量合成流程
```text
用户选择多张衣服图和印花图
-> 用户选择批量模式
-> 用户选择模板或当前参数
-> export_panel 构造 BatchOptions
-> core.batch 生成任务列表
-> 每个任务调用 core.composer
-> 失败项记录错误并继续
-> UI 显示进度
-> 任务完成后显示成功数量和失败数量
```
## 9. 错误处理
错误处理分两层:
- 用户提示:简洁、可理解,说明用户可以做什么。
- 日志信息:详细记录异常类型、文件路径、调用阶段和堆栈信息。
规则:
- 文件不存在、格式不支持、输出目录不可写必须提示用户。
- 单张导出失败应提示用户并记录日志。
- 批量任务中单个文件失败应记录失败原因并继续处理。
- 全局不可恢复错误才允许终止批量任务。
## 10. 测试边界
优先测试:
- `core/composer.py` 的单张合成。
- 透明 PNG 印花叠加。
- 坐标、尺寸、旋转参数应用。
- 输出文件名生成。
- 模板 JSON 读写。
- 批量一一匹配模式。
- 批量全组合模式。
UI 测试可以后置,但核心合成逻辑必须尽量可测试。
## 11. 后续扩展点
架构应允许后续增加:
- 图像编辑器专项模块。
- 局域网版本分发模块。
- 多版本启动器。
- 更多输出格式。
- 更多模板类型。
- 素材目录记忆。
新增扩展时必须遵守现有依赖方向,不得让核心模块依赖 UI。