- src/paths.py: 集中管理 logs/、artifacts/ 路径与产物命名 (artifacts/<task_id>/<时间戳>_<step>.png|.xml),_safe 安全化防路径穿越, 运行时自动创建且被 .gitignore 忽略。 - src/logging_config.py: 统一日志格式(含 task_id/step),控制台 + logs/app.log, 缺上下文时由 filter 补默认值,setup 幂等;约定不记录敏感信息。 - src/main.py: 启动时初始化运行目录与日志。 - 运行方式统一为 python -m src.main(绝对导入下的唯一干净入口), 同步替换 00/03/05/current-state 文档命令与 dev.bat。 - 文档:04 §七 补 paths.py 与产物命名规则;tasks/progress/current-state 更新。 验证:compileall OK;unittest Ran 17 tests OK;python -m src.main exit=0,logs/app.log 写入正常。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
362 lines
14 KiB
Markdown
362 lines
14 KiB
Markdown
# 架构设计
|
||
|
||
> 本文讲“怎么把技术栈搭起来”:系统结构、职责划分、数据模型、技术难点、开发顺序。
|
||
> 具体用了哪些框架 / 库 / 数据库 / 部署方式,见 [技术栈](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
|
||
│ └── paths.py
|
||
├── tests/
|
||
├── samples/
|
||
├── logs/
|
||
├── artifacts/
|
||
├── requirements.txt
|
||
└── README.md
|
||
```
|
||
|
||
- `src/app/`:PySide6 GUI。
|
||
- `src/core/`:任务模型、状态机、执行编排。
|
||
- `src/excel/`:Excel 导入、校验、回写。
|
||
- `src/android/`:设备连接、拼多多 App 自动化流程。
|
||
- `src/logging_config.py`:统一日志格式(含 `task_id`、`step`),输出到控制台与 `logs/app.log`;不记录敏感信息。
|
||
- `src/paths.py`:集中管理运行时路径与产物命名;截图与 UI XML 按 `artifacts/<task_id>/<时间戳>_<step>.png|.xml` 归档,`task_id`/`step` 入路径前安全化以防穿越。
|
||
- `logs/`:本地运行日志(`app.log`),运行时自动创建并被 `.gitignore` 忽略,不提交真实敏感日志。
|
||
- `artifacts/`:截图、UI XML、结果文件等运行产物,运行时自动创建并被 `.gitignore` 忽略,不提交真实数据。
|
||
- `samples/`:脱敏样例 Excel。
|
||
|
||
## 八、架构纪律
|
||
|
||
- GUI 不直接写 Android 点击细节,必须通过任务执行器和 Android 模块。
|
||
- Android 模块不直接读写 Excel。
|
||
- Excel 模块不关心拼多多页面状态。
|
||
- 状态枚举和字段变化必须同步更新本文、`api.md` 和相关任务验收。
|
||
- 支付逻辑必须受显式开关、二次校验和金额上限控制。
|
||
- 安全校验、验证码、风控逻辑只能进入人工接管分支。
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|