Files
cmautobuy/docs/client/01-requirements.md
T
chengmaandClaude Opus 5 0b645ee8b3 docs: 建立面向初级程序员的文档基线
按初级程序员可读、可维护的目标重写项目文档,并定案三项设计决策。

新增
- docs/client/00-getting-started.md 上手指南:装环境、跑起来、常见报错
- docs/client/00-glossary.md 术语表:Outbox、幂等、不可逆阶段等
- docs/templates/task.md 工单与归档模板
- client/requirements.txt 固定依赖版本
- .gitignore 屏蔽 data/、打包产物和调试产物

设计定案
- 本地库只存已领取任务,不再镜像 Admin 任务池;已完成任务永久保留
- 去掉租约、心跳和状态回查;Admin 接口从 5 个降到 3 个
  (本项目人工付款,重复下单只产生未付款订单,由人工审核处理)
- 打包采用 PyInstaller one-dir:launcher.exe + app/ + data/,便携模式

文档改进
- 补齐可直接抄的代码模板:Worker 线程、事务写库、幂等键、增量加载、错误提示、路径解析
- 状态机由 ASCII 图改为完整转换表,并补充崩溃恢复规则
- 消除文档与现有代码的冲突,02 新增“现状与目标差异”清单
- 待确认事项一律给出临时默认值,避免阻塞开发
- AGENTS.md 新增“小改动直通”,工单必填项由 8 项压缩到 6 项

说明:Gitea 尚未配置,本次无对应工单号;AGENTS.md §0 的 Gitea 信息待补。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 11:44:39 +08:00

12 KiB
Raw Blame History

01 Client 产品需求基线

  • 文档状态:基线草案,待需求评审
  • 适用范围:client/
  • 产品类型:Windows 桌面自动化客户端

本文档中 [必须] / [建议] / [待定] 的含义见 文档索引。没有标注的默认是 [必须]。看不懂的词查 术语表。

1. 背景与目标

Client 从 Admin 获取拼多多任务,在一台已授权的 Android 设备上通过 uiautomator2 执行商品数据采集或采购操作,并将结果可靠地提交回 Admin。

产品目标:

  1. 在统一界面中查看、搜索和跟踪本机已领取的全部 PDD 任务(含正在做的和做完的)。
  2. 自动领取并串行执行采集任务和采购任务。
  3. 在 Admin 或网络暂时不可用时保存结果并安全重试,不能丢失采集结果或重复采购。
  4. 为失败、异常页面和不确定订单提供可诊断、可恢复的人工处理入口。
  5. 在 Admin 尚未完成时,通过本地模拟接口完成大部分 Client 开发和测试。

2. 用户与外部系统

  • **操作人员:**配置 Admin 和 Android 设备,启动或停止自动获取任务,查看状态和详情,处理异常。
  • **Admin:**创建任务、分配任务、维护任务状态,并接收 Client 执行结果。
  • **Android 设备:**登录并运行拼多多应用,由 Client 独占一个自动化执行会话。
  • **拼多多应用:**被自动化操作的外部系统,不属于本项目控制范围。

3. 产品范围

Client 顶级导航仅包含:

  1. PDD 任务:本机已领取任务的展示、搜索、自动执行和详情查看。
  2. 设置:Admin、Android 设备、自动化、安全和诊断设置。

设备连接不作为独立顶级模块,统一放入设置页。

Client 不显示 Admin 任务池。 本地只保存本机已领取的任务(含执行中和已完成), 不缓存"待领取"的任务。要拿新任务只有一条路——由任务引擎向 Admin 领取。 操作人员想知道队列里还有多少活没派下来,去 Admin 自己的界面看。 这条决定的完整理由见 03 数据模型 §3.1。

4. 任务类型

4.1 采集任务

输入至少包含远程任务编号和商品链接。Client 应采集:

  • 商品编号、商品链接和商品标题;
  • 店铺名称;
  • 已拼数量及原始显示文字;
  • 评价数量及原始显示文字;
  • 所有规格维度及其可见值;
  • 每个规格组合对应的价格、币种和可用状态;
  • 采集时间、设备及必要诊断产物引用。

颜色、尺码和价格不能只保存为互不关联的列表,必须以 SKU 规格组合保存价格关系。对于“1.2 万+”等近似数值,同时保存规范化数值、原始文字和近似标记。

4.2 采购任务

输入至少包含:

  • 远程任务编号;
  • 商品编号或商品链接;
  • 目标颜色和尺码;
  • 采购数量;
  • 预期价格或最高允许价格;
  • 任务版本及幂等信息。

Client 应执行:

  1. 校验商品、规格、数量、库存和价格保护条件。
  2. 选择指定颜色、尺码和数量。
  3. 进入订单提交前状态并再次校验价格。
  4. 在允许真实下单时提交订单。
  5. 获取并核对订单编号和下单时间。
  6. 保存本地结果并提交 Admin。

仅凭“我的订单”列表中的最新一条记录不能认定为当前任务订单。必须结合任务开始时间、商品、规格、数量和金额核对;存在多个候选时进入人工处理状态,不得猜测或重新下单。

5. PDD 任务页需求

页面分为三个稳定区域。

5.1 顶部命令区

  • “开始自动获取”是持续任务引擎的主操作,启动后切换为“停止自动获取”。
  • 停止自动获取只停止领取新任务;当前任务应运行到安全停止点。
  • 搜索条件至少支持任务类型、任务状态和关键词。
  • 关键词搜索任务编号、商品编号和商品标题。
  • “搜索”只查询本地数据库,不触发任务执行。

5.2 中部任务表格

表格显示的是本机已领取的全部任务,包括正在做的和早已做完的。已完成的任务永久保留,不会被清理。

表格要让操作人员一眼看出:这是什么任务、买的什么、什么规格、多少钱、现在到哪一步了。

具体列有哪些、每列怎么显示,以 05 界面交互规范 §5.1 为准(那是唯一权威定义,改列只改那一处)。

本文只规定不可动摇的业务要求:

  • 默认按 updated_at DESC, id DESC 稳定排序。
  • 所有任务可通过增量加载访问,禁止为每个单元格创建常驻复杂控件。
  • pdd_data 是详情数据,不作为隐藏表格列整体加载;表格模型只保留稳定任务编号,查看详情时从数据库读取。
  • 单击行只选择,双击、Enter 或“详情”打开任务详情。

5.3 底部状态区

持续显示:

  • 自动获取是否开启;
  • 当前任务编号和类型;
  • 当前执行步骤;
  • 最近一次领取到任务的时间;
  • 最近一次成功或可恢复错误摘要。

重要错误应同时使用持久信息条提供重试或进入设置的入口,不能只依赖自动消失提示。

6. 设置页需求

设置分为以下组:

  1. **Admin:**服务地址、Client 编号、认证状态、请求超时和测试连接。
  2. **Android 设备:**ADB 地址、拼多多包名、设备测试连接。
  3. **自动化:**轮询周期、任务超时、最大重试次数和演练模式。
  4. **安全与诊断:**价格允许偏差、最大购买数量、日志目录、截图/XML 保留周期。

密码和访问令牌不得以明文写入普通 SQLite 设置或日志。

7. 任务状态

任务共有 8 个标准状态:claimed、running、result_pending、retry_wait、manual_review、succeeded、failed、cancelled。

没有"待领取"状态——任务在领取成功那一刻才写进本地库,见 03 数据模型 §3.1。

每个状态的中文显示、含义和允许的转换,以 03 数据模型 §7 为准(那是唯一权威定义,写代码和写测试都看那一张表)。

本文只强调两条产品级红线:

  • 任何自动流程都不许把 manual_review 改回执行中状态,必须由人处理。
  • Client 拿到任务就做完。中途 Admin 取消了这个任务,Client 不管,照做完照提交,由人工审核时处理。
  • 程序崩溃后,处于不可逆采购阶段的任务只能执行订单核对,不能重新下单。

8. MVP 范围

MVP 包含:

  • 两模块 Fluent 界面;
  • SQLite 数据库和迁移;
  • 本地任务表格、搜索、筛选和详情;
  • Mock Admin 接口;
  • 任务领取与串行执行;
  • 后台任务协调器、轮询、停止、重试和结果待提交队列;
  • 真实商品采集及 SKU 数据组装;
  • 采购演练模式,完成规格和数量选择但不执行最终下单;
  • 重启恢复、断网、设备断开和重复提交测试。

MVP 之后:

  • 接入真实 Admin HTTP 接口;
  • 经过安全验收后启用真实订单提交;
  • 完成订单核对和人工处理流程;
  • 打包成 exe 并做生产环境验证(策略见 §8.1)。

8.1 打包策略

打包动作属于 MVP 之后,但策略现在就定下来,避免写代码时留下不好打包的结构。

工具: PyInstaller 6.x,one-dir 模式(不是 one-file)。 one-file 每次启动都要解压到临时目录,启动慢,出错几乎没法排查;one-dir 缺什么文件一眼就能看见。

产出目录结构:

CMAutoBuy/                    整个文件夹拷到任何机器都能用
├── launcher.exe              双击这个启动
├── app/                      运行时依赖,用户不要动
│   ├── python310.dll
│   ├── PyQt5/Qt5/
│   │   ├── bin/              Qt5Core.dll / Qt5Gui.dll / Qt5Widgets.dll …
│   │   └── plugins/platforms/qwindows.dll
│   ├── qfluentwidgets/       qss 样式、字体、图标资源
│   ├── adbutils/binaries/    adb.exe
│   └── …
└── data/                     本地数据,升级时保留(见 [03 数据模型](03-data-model.md) §2.1)
    ├── client.db
    ├── logs/
    └── artifacts/

app/ 这个名字来自 PyInstaller 的 --contents-directory app 参数(默认叫 _internal)。

升级方式: 删掉 launcher.exe 和 app/,换成新版本,data/ 原样不动。 数据库靠 PRAGMA user_version 自动迁移,见 03 §2.3。

已知风险点(打包工单必须逐项验证):

风险 症状
Qt 平台插件没收集到 启动即报 could not find or load the Qt platform plugin "windows"
qfluentwidgets 资源没收集到 能启动,但界面全白、控件没样式
adbutils 的 adb 二进制没收集到 界面正常,但连不上手机
uiautomator2 初始化流程 打包后没有 python -m uiautomator2 init 这条命令,需确认辅助 App 怎么装
杀软误报 空白版本信息的 exe 最容易被拦。必须给 exe 加图标和版本信息(产品名、版本号)。根治需要代码签名证书
装到 C:\Program Files\ 无写权限,数据被重定向到 VirtualStore,设置改了不生效

具体的 PyInstaller 参数和 hook 配置跟依赖版本强相关,不在本文档固化, 由打包工单在真实 Windows 环境上验证后写进归档。

9. 非目标

  • 不开发 Admin 管理界面或 Admin 数据库。
  • 不自动注册、登录或绕过拼多多验证码、风控和安全机制。
  • 不自动完成支付;当前采购范围止于创建订单并获取订单信息。
  • MVP 不支持一台 Client 同时并行控制多台设备。
  • 不保证拼多多未公开界面在所有版本中保持兼容,必须通过版本化适配和诊断产物处理变化。

10. 非功能需求

  • 所有网络、数据库长操作和 uiautomator2 操作不得阻塞 Qt 主线程。
  • 同一设备同一时间只执行一个任务。
  • 任务领取、结果提交和采购操作必须具有去重或幂等保护。
  • 结果先本地持久化,再提交 Admin;Admin 暂时不可用不能导致重新采购。
  • 时间在数据库和接口中使用带时区的 ISO 8601,内部优先使用 UTC,界面转换为本地时间。
  • 金额以人民币分的整数保存,禁止使用浮点数作为业务金额。
  • 任务、日志和诊断信息不得包含密码、访问令牌、Cookie 或不必要的个人信息。

11. 待确认事项

这些还没定下来,但不许因此停工。先按"临时默认值"做,等定了再按工单改。

# 待确认什么 临时默认值(先这么做) 定下来之前会卡住什么
1 Admin 的认证方式和 Client 注册方式 Mock Gateway 不做认证;HTTP 实现预留 Authorization: Bearer 请求头,token 从设置读 只卡真实 HTTP 联调,不卡 MVP
2 真实采购启用条件和人工确认策略 真实下单开关保持关闭,一律走演练模式 卡真实下单,不卡 MVP
3 价格允许偏差 默认 0 分(即实际价格必须等于预期价格才继续),可在设置页改 不卡。先按最严的来
4 是否存在颜色、尺码之外的第三个规格维度 按"可能有任意多个维度"实现,用 dimensions 数组,不要写死两个 不卡。写死才会返工

第 4 条特别注意:即使目前见到的商品都只有颜色和尺码两个维度,也不许把数据结构写成两个固定字段。见 03 数据模型 §8.1。

已定案(不再是待确认项):

  • Admin 只分配任务给指定 Client,Client 不读全局任务池。见 04 §5.1。
  • 没有租约、没有心跳、没有状态回查。 Client 只有领取、提交结果、提交失败三个调用。见 04 §1.1。
  • 本地只存已领取任务,已完成任务永久保留。诊断产物(截图、XML、日志)仍按 diagnostics.retention_days 清理,两者不是一回事。见 03 §3.1。