Files
cmpdd/docs/04-architecture.md
T
chengmaandClaude Opus 4.8 c41f37a27d feat(T-002): 建立核心数据模型与状态枚举
- src/core/status.py: TaskStatus 六态枚举,英文成员 + display_name/from_display
  中英映射(单一事实源),对齐 04-architecture.md §3.4。
- src/core/models.py: OrderTask dataclass,字段集合/类型对齐 §3.3;支付模式不挂模型。
- tests/test_models.py: 枚举完整性/双向映射/未知值报错/默认值/实例独立性。
- 文档同步:04 §3.4 约定补 from_display;tasks/progress/current-state 更新。

验证:compileall OK;unittest Ran 10 tests, OK。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 17:17:52 +08:00

359 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 架构设计
> 本文讲“怎么把技术栈搭起来”:系统结构、职责划分、数据模型、技术难点、开发顺序。
> 具体用了哪些框架 / 库 / 数据库 / 部署方式,见 [技术栈](03-tech-stack.md)。
## 一、系统结构
```text
运营同事
|
v
Windows 桌面 GUI(PySide6)
|
+--> Excel 导入/回写模块(openpyxl)
|
+--> 任务执行器 / 状态机
|
+--> Android 控制模块(uiautomator2 + ADB)
| |
| v
| Android 真机 + 拼多多 App
|
+--> 截图 / UI XML / 日志归档
```
MVP 没有独立后端服务,也没有数据库。Excel 是任务输入和结果输出,日志和截图是排查辅助文件。
## 二、职责划分
**桌面 GUI**
- 导入 Excel 文件。
- 展示任务表格、状态、订单号、失败原因。
- 支持勾选任务、开始、暂停、继续、取消、人工接管和支付模式配置。
- 展示当前手机截图、当前步骤和实时日志。
- 防止执行中重复启动同一批任务。
**Excel 模块**
- 校验固定表头。
- 读取任务行并转换为内部任务模型。
- 生成默认结果文件路径,不默认覆盖原始 Excel。
- 将状态、订单号、失败原因、执行时间、截图路径写回结果文件。
**任务执行器 / 状态机**
- 接收 GUI 选中的任务列表。
- 按顺序逐条执行。
- 管理任务状态流转。
- 根据支付模式决定支付前暂停或受控继续支付。
- 遇到需要人工处理的节点时暂停并通知 GUI。
- 捕获异常并记录失败原因。
**Android 控制模块**
- 连接和检查 Android 真机。
- 打开拼多多商品链接。
- 等待并识别当前页面状态。
- 点击购买按钮、打开 SKU 面板、选择 SKU、设置数量。
- 到支付确认节点时执行二次校验,并根据支付模式暂停或继续。
- 到安全校验节点时停止自动动作并转人工。
- 保存截图和 UI XML。
**拼多多流程模块**
- 封装与拼多多 App 页面相关的选择器、文本匹配和步骤判断。
- 不直接散落在 GUI 或 Excel 模块中。
- 页面变化时优先修改这里。
**日志与归档**
- 每条任务记录开始时间、结束时间、状态、关键步骤。
- 失败时保存截图和 UI XML。
- 日志不记录支付密码、短信验证码、账号密码等敏感信息。
## 三、数据模型
### 3.1 Excel 输入字段
最终字段以用户提供的真实样例为准。MVP 建议固定表头:
| 字段 | 必填 | 说明 |
| --- | --- | --- |
| `任务ID` | 否 | 运营侧任务编号;为空时系统可用行号作为内部编号。 |
| `商品链接` | 是 | 拼多多商品链接。 |
| `商品名称` | 否 | 便于运营识别,不作为自动化唯一依据。 |
| `SKU信息` | 是 | 建议格式:`颜色=黑色;尺码=XL;套餐=单件`。 |
| `数量` | 是 | 下单数量,默认应为正整数。 |
| `收货人` | 否 | MVP 可先使用拼多多账号默认地址;如需要校验地址再启用。 |
| `手机号` | 否 | 同上。 |
| `地址` | 否 | 同上。 |
| `备注` | 否 | 运营备注,不影响自动化。 |
| `预期金额` | 否 | 开启受控自动支付时建议填写,用于支付前比对。 |
| `最高可支付金额` | 否 | 开启受控自动支付时建议填写,作为单笔金额上限。 |
如果业务需要拆分 SKU,可后续支持 `SKU1`、`SKU2`、`SKU3`,但 MVP 优先统一用 `SKU信息`。
### 3.2 Excel 输出字段
结果文件应在原始字段基础上追加或更新:
| 字段 | 说明 |
| --- | --- |
| `状态` | `待执行`、`执行中`、`待人工`、`成功`、`失败`、`已取消`。 |
| `订单号` | 成功后读取到的拼多多订单号。 |
| `失败原因` | 失败或暂停原因。 |
| `执行时间` | 最近一次完成或失败时间。 |
| `截图路径` | 失败或关键节点截图保存路径。 |
| `结果备注` | 可选,记录人工接管说明。 |
### 3.3 内部任务模型
```text
OrderTask
task_id: str
row_index: int
product_url: str
product_name: str | None
sku_text: str
sku_items: dict[str, str]
quantity: int
receiver: str | None
phone: str | None
address: str | None
note: str | None
expected_amount: Decimal | None
max_pay_amount: Decimal | None
status: TaskStatus
order_no: str | None
fail_reason: str | None
screenshot_path: str | None
started_at: datetime | None
finished_at: datetime | None
```
支付模式不挂在单条任务上:是否启用受控自动支付由**全局** `PaymentConfig` 决定(见 §4.4),`OrderTask` 只持有支付前二次校验需要的 `expected_amount` / `max_pay_amount` 等输入数据。
### 3.4 任务状态
```text
待执行 -> 执行中 -> 待人工 -> 执行中 -> 成功
待执行 -> 执行中 -> 失败
待执行 -> 已取消
执行中 -> 已取消
待人工 -> 已取消
```
状态含义:
- `待执行`:已导入但未开始。
- `执行中`:自动化正在处理。
- `待人工`:需要运营在手机或 GUI 中确认/接管。
- `成功`:已获得订单号并写入结果。
- `失败`:无法继续执行,已记录原因。
- `已取消`:用户取消执行。
#### 枚举命名与中英映射
代码标识符使用英文(见 [`05-coding-rules.md`](05-coding-rules.md) §6),中文仅用于 GUI 展示和 Excel 回写。`TaskStatus` 枚举以英文成员名定义,中文为其显示值,映射如下:
| 枚举成员(代码) | 显示值(GUI / Excel) |
| --- | --- |
| `TaskStatus.PENDING` | `待执行` |
| `TaskStatus.RUNNING` | `执行中` |
| `TaskStatus.MANUAL` | `待人工` |
| `TaskStatus.SUCCESS` | `成功` |
| `TaskStatus.FAILED` | `失败` |
| `TaskStatus.CANCELLED` | `已取消` |
约定:
- 中↔英映射只在写入 Excel 或渲染 GUI 的边界处发生,由 `TaskStatus` 的 `display_name` 属性与 `from_display` 反查集中维护(单一事实源),核心逻辑只比较英文枚举成员。
- `OrderTask.status` 字段类型为 `TaskStatus`,不直接存中文字符串。
- 注意区分「任务状态」与「执行器状态」:上表是单条任务的 `status`;批次级的「暂停」属于执行器状态,不进入本枚举(见 §4.5)。
## 四、核心流程
### 4.1 批量执行流程
```text
导入 Excel
-> 校验表头
-> GUI 展示任务
-> 用户勾选任务
-> 点击开始
-> 检查 Android 设备
-> 按顺序执行每条任务
-> 更新 GUI 状态
-> 写入结果 Excel
```
### 4.2 单条任务流程
```text
打开商品链接
-> 跳转拼多多 App
-> 识别商品详情页
-> 点击购买入口
-> 打开 SKU 面板
-> 按 SKU 信息选择规格
-> 设置数量
-> 进入订单确认页
-> 校验商品标题 / SKU / 数量 / 地址 / 实付金额
-> 默认支付前暂停 / 开启受控自动支付时继续支付
-> 如需人工处理则等待人工完成后继续
-> 读取订单号
-> 写回结果
```
### 4.3 异常处理原则
- 找不到按钮、SKU、数量控件:暂停或失败,不使用不确定坐标硬点。
- 出现验证码、风控、人脸、短信、安全验证:进入 `待人工`。
- 价格变化、超过最高可支付金额、库存不足、商品下架:记录明确失败原因。
- 设备断开、App 崩溃、网络异常:失败并保留截图/日志。
- 未读取到订单号:允许人工录入或标记为待核查,MVP 具体交互待实现时确认。
### 4.4 支付模式
支付模式是**全局批次级配置**,不是按行任务字段。整个批次共用一个 `PaymentConfig`,由 GUI 显式设置(默认人工确认),执行中不得悄悄切换。
```text
PaymentConfig
mode: PaymentMode # MANUAL(默认)/ AUTO(受控自动支付)
per_order_limit: Decimal # 单笔金额上限,开启 AUTO 时必填
batch_limit: Decimal | None # 批次金额上限,建议填写
price_tolerance: Decimal # 实付与预期金额的允许偏差,默认 0
```
```text
PaymentMode(枚举,代码用英文名,显示用中文)
MANUAL -> 人工确认支付
AUTO -> 受控自动支付
```
单条任务的支付决策 = 全局 `PaymentConfig` + 该任务行的 `expected_amount` / `max_pay_amount`。MVP 不支持按行覆盖支付模式;如未来需要,再在本文和 `api.md` 中显式扩展,不得在代码里临时加按行开关。
MVP 支持两种支付模式:
```text
人工确认支付(默认)
-> 到支付确认页
-> 校验商品 / SKU / 数量 / 地址 / 金额
-> 进入待人工
-> 运营确认后继续读取订单号
受控自动支付(显式开启)
-> 到支付确认页
-> 校验商品 / SKU / 数量 / 地址 / 金额
-> 检查单笔金额上限和批次金额上限
-> 未触发安全校验时继续支付
-> 触发验证码 / 风控 / 人脸 / 短信时进入待人工
```
受控自动支付约束:
- 必须由 GUI 配置显式开启,不能默认开启。
- 必须配置单笔金额上限;建议配置批次金额上限。
- 如果 Excel 提供 `预期金额`,支付页实付金额必须与预期一致或在允许偏差内。
- 如果 Excel 提供 `最高可支付金额`,支付页实付金额不得超过该值。
- 支付前必须保存截图和 UI XML。
- 不保存支付密码、短信验证码、人脸信息等敏感数据。
- 出现安全校验时只允许转人工,不做绕过。
### 4.5 执行器状态与暂停语义
「暂停」是**执行器(批次)层**的状态,不是单条任务的 `status`。任务级状态只有 §3.4 的六种;GUI 工具栏的「暂停 / 继续」控制的是执行器是否继续领取下一条任务,不会把任何任务改成「已暂停」。
执行器状态(`RunnerState`,与 `TaskStatus` 分离):
```text
IDLE 空闲(未开始或批次已结束)
RUNNING 正在按顺序执行
PAUSED 已暂停;当前任务执行完后不再领取下一条
STOPPING 取消中;正在安全收尾当前任务
```
约定:
- 点「暂停」时,正在执行的任务跑完当前安全步骤后停在边界,执行器进入 `PAUSED`;已进入 `待人工` 的任务不受影响。
- 点「继续」时执行器回到 `RUNNING`,从下一条勾选任务继续。
- 「取消」使执行器进入 `STOPPING`;无法安全中断的当前任务按 §3.4 转 `待人工` 或 `已取消`,不会硬杀。
- `RunnerState` 不写入 Excel;Excel 只记录任务级 `status`。
## 五、关键技术难点
| 难点 | 说明 | 应对 |
| --- | --- | --- |
| 拼多多页面可识别性 | 第三方 App 控件文本和结构可能变化,部分区域可能无法通过 UI XML 获取。 | Phase 1 先做真机原型;必要时保存截图并后续引入 OCR。 |
| SKU 精确匹配 | SKU 文案可能存在同义、缺货、套餐组合、层级顺序问题。 | MVP 用明确文本匹配;匹配失败即暂停/失败,不猜测。 |
| 支付和安全节点 | 涉及真实资金和账号安全。 | 默认人工确认;受控自动支付必须经过二次校验、金额上限和显式开关;安全校验转人工。 |
| 批量执行稳定性 | App 卡顿、网络波动、设备锁屏会导致流程中断。 | 增加超时、重试、截图、状态恢复;先单设备验证。 |
| 结果回写可靠性 | 执行中断可能导致结果丢失。 | 每条任务结束后立即保存结果文件。 |
## 六、推荐开发顺序
1. 初始化 Python 项目骨架和文档约定。
2. 实现 Excel 读取、表头校验、内部任务模型。
3. 实现最小 PySide6 GUI:导入、表格展示、日志区域。
4. 验证 ADB 和 `uiautomator2` 真机连接。
5. 做单条商品链接跳转和截图/UI XML 保存原型。
6. 做 SKU 面板打开和 SKU 文本选择原型。
7. 接入任务执行器,跑通单条任务到支付前校验和默认暂停。
8. 接入批量顺序执行、状态更新和结果 Excel 回写。
9. 完善异常处理、人工接管、受控自动支付开关和打包。
## 七、项目结构建议
```text
cmpdd/
├── docs/
├── src/
│ ├── main.py
│ ├── app/
│ │ ├── main_window.py
│ │ └── widgets/
│ ├── core/
│ │ ├── models.py
│ │ ├── task_runner.py
│ │ └── status.py
│ ├── excel/
│ │ ├── reader.py
│ │ └── writer.py
│ ├── android/
│ │ ├── device.py
│ │ └── pdd_flow.py
│ └── logging_config.py
├── tests/
├── samples/
├── logs/
├── artifacts/
├── requirements.txt
└── README.md
```
- `src/app/`:PySide6 GUI。
- `src/core/`:任务模型、状态机、执行编排。
- `src/excel/`:Excel 导入、校验、回写。
- `src/android/`:设备连接、拼多多 App 自动化流程。
- `logs/`:本地运行日志,默认不提交真实敏感日志。
- `artifacts/`:截图、UI XML、结果文件等运行产物,默认不提交真实数据。
- `samples/`:脱敏样例 Excel。
## 八、架构纪律
- GUI 不直接写 Android 点击细节,必须通过任务执行器和 Android 模块。
- Android 模块不直接读写 Excel。
- Excel 模块不关心拼多多页面状态。
- 状态枚举和字段变化必须同步更新本文、`api.md` 和相关任务验收。
- 支付逻辑必须受显式开关、二次校验和金额上限控制。
- 安全校验、验证码、风控逻辑只能进入人工接管分支。