# 项目架构 ## 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` 职责: - 读取和保存应用配置。 - 管理默认配置。 - 在配置损坏或缺失时提供安全默认值。 - 持久化用户偏好:输出设置、上次的衣服/印花文件夹(`last_garment_dir`/`last_print_dir`)、上次选择的模板(`last_template`)、上次选择的批量模式(`last_batch_mode`)等。 由主窗口集中使用:启动时加载一次并把初值分发给各面板,面板选择变化时「改一次存一次」回写。各 UI 控件不直接读写配置文件,避免分散解析。 禁止: - 禁止在多个模块中重复解析同一个配置文件。 - 禁止启动时无提示清空用户配置。 - 禁止 UI 控件绕过本服务直接读写配置文件。 ### 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。