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>
This commit is contained in:
chengma
2026-08-06 11:44:39 +08:00
co-authored by Claude Opus 5
commit 0b645ee8b3
14 changed files with 2842 additions and 0 deletions
+116
View File
@@ -0,0 +1,116 @@
# Client 子项目规则
本文件适用于 `client/` 下的全部代码和测试,并继承仓库根目录 `AGENTS.md` 的工作流、Git、安全、文档和初级程序员维护规则。
## 开始工作前
- 从仓库根目录执行 Client 任务时,也必须先读取本文件。
- 第一次接手本项目,先看这两份:
- 环境和运行:[00 上手指南](../docs/client/00-getting-started.md)
- 看不懂的词:[00 术语表](../docs/client/00-glossary.md)
- 只读取与当前任务有关的长期基线,不必每次加载全部文档:
- 需求边界:[01 产品需求基线](../docs/client/01-requirements.md)
- 模块和线程:[02 系统架构](../docs/client/02-architecture.md)
- SQLite 与 JSON:[03 数据模型](../docs/client/03-data-model.md)
- Admin 对接:[04 接口契约](../docs/client/04-admin-api-contract.md)
- 页面和交互:[05 界面规范](../docs/client/05-ui-specification.md)
- 测试和采购安全:[06 质量与安全](../docs/client/06-quality-security.md)
- 文档仍是草案或存在未决事项时,不得自行选择会改变业务结果的答案,应按根目录工单流程确认。
## 技术栈
- 固定使用 **Python 3.10 + PyQt5 + Qt Widgets + PyQt-Fluent-Widgets**。
- 界面组件优先使用 `qfluentwidgets`;没有合适组件时再使用 PyQt5 标准控件。
- 只有两者都无法满足明确需求时才创建自定义控件,并说明原因。
- 不得混用 PyQt6、PySide2 或 PySide6,也不得安装其他 Qt 绑定对应的 Fluent Widgets 包。
- 当前开发和验证解释器为 `C:/Python310/python.exe`。
- 依赖及版本以 `client/requirements.txt` 为准,版本必须固定。
- 新增或升级依赖前先检查准确版本、许可证和打包影响,并经过工单确认;确认后同步更新 `requirements.txt`。
## 代码分层
- 界面层只负责显示和输入转发,不直接调用 Admin、SQLite 长查询或 uiautomator2。
- `src/ui_main.py` 负责应用和窗口装配;事件绑定放在 `src/ui_event.py` 或后续应用层服务中。
- 领域模型不导入 Qt、uiautomator2 或具体 HTTP 客户端。
- Admin 通过 Gateway 接口隔离,Mock 和 HTTP 实现必须遵守相同契约。
- SQLite 通过 Repository 访问,不在页面或自动化函数中散落业务 SQL。
- PDD 页面识别、采集和采购函数放在 PDD 适配层;演示脚本不得被正式流程直接导入。
- 类和函数骨架遵循根目录的初级程序员维护规则,优先补全现有清晰边界,不随意重做架构。
## 数据与接口
- 数据库字段、任务状态和 `pdd_data` 结构以 `docs/client/03-data-model.md` 为准。
- Admin 路径、字段和幂等语义以 `docs/client/04-admin-api-contract.md` 为准;Admin 未完成时使用 Mock,不臆造正式响应。
- Client 与 Admin 只有三个调用:领取、提交结果、提交失败。**不得新增"向 Admin 查询状态"类接口。**
- 金额使用人民币分整数,时间使用带时区 ISO 8601,稳定任务编号不得使用表格行号代替。
- 文件路径一律通过 `data_dir()`(可写数据)和 `app_dir()`(只读资源)获取,见 [03 数据模型 §2.2](../docs/client/03-data-model.md)。**不许硬编码路径,不许用 `os.getcwd()` 或 `__file__` 直接拼**,打包成 exe 后会失效。
- PDD 结果必须先写入 SQLite,再通过 Outbox 提交 Admin。
- 任务领取后中途不查 Admin 状态;Admin 取消或重派一律不感知,做完照常提交。
## 线程与自动化
- QWidget 只能在 Qt 主线程创建和访问。
- 禁止在主线程执行 Admin 请求、uiautomator2/ADB、`time.sleep()`、轮询、大型 XML 解析或文件批量写入。
- 长任务统一使用 `QObject` + `moveToThread` 的 Worker 写法,模板见 [02 架构 §5.1](../docs/client/02-architecture.md);不得混用 `QThread` 子类、`QRunnable` 或 `threading`。
- 后台结果通过信号回到主线程;窗口关闭时按 [02 架构 §5.2](../docs/client/02-architecture.md) 断开连接,防止迟到结果访问已销毁控件。
- 一个 Android 设备同一时间只由一个工作线程控制,不跨线程共享 uiautomator2 Device 对象。
- 自动化任务必须处理启动、运行、安全停止、成功、失败、取消、超时、设备断开和迟到结果。
- 窗口或页面销毁后,后台回调不得再访问对应控件。
## 采购安全
- 真实下单开关默认关闭;未满足质量文档中的采购安全门禁不得启用。
- 高风险点击前必须使用最新页面状态重新校验商品、规格、数量、价格和目标坐标。
- 进入不可逆下单阶段前先持久化执行步骤。
- 不可逆阶段发生崩溃或结果不确定时,只能核对订单或转人工处理,禁止自动重新下单。
- 多个订单候选、验证码、登录失效、未知弹窗、价格超限或规格不确定时停止自动执行。
## 界面规则
- 顶级模块保持为“PDD 任务”和“设置”,页面使用唯一且稳定的 `objectName`。
- 优先使用 `FluentWindow`、Fluent 导航、主题和图标;不得使用表情符号充当结构图标。
- 使用布局、尺寸策略和伸缩项,不用固定坐标排列常规界面。
- 任务表格使用模型/视图和稳定任务编号,不把完整 `pdd_data` 放入隐藏列,也不为每个单元格创建常驻 QWidget。
- “开始自动获取”是界面上唯一会产生外部后果的命令;其余操作只读本地数据库。
- 本地只保存已领取的任务,不缓存 Admin 任务池;已完成任务永久保留,不得清理。
- 普通成功更新页面状态即可;可恢复错误使用 `InfoBar`,只有必须阻断决策时才使用模态对话框。
- 主要流程必须支持键盘;表单具有可见标签;状态和错误不能只依赖颜色。
- 验证浅色、深色、Windows 贴靠和 100%–200% 显示缩放。
- 避免全局 QSS 覆盖 Fluent 控件;局部样式必须保留悬停、按下、焦点和禁用状态。
## 验证
全部命令从 `client/` 目录执行,可直接复制。
**1. 语法检查**(改了哪个文件就换成哪个)
```powershell
C:/Python310/python.exe -m py_compile src/ui_main.py
```
**2. 界面离屏冒烟测试**(不弹窗口,跑完自动退出,CI 和本地都用这条)
```powershell
$env:QT_QPA_PLATFORM="offscreen"
C:/Python310/python.exe -c "from src.ui_main import MainWindow; from PyQt5.QtWidgets import QApplication; app=QApplication([]); w=MainWindow(); print('OK'); app.quit()"
Remove-Item Env:QT_QPA_PLATFORM
```
打印 `OK` 即通过。
**3. 手动看界面**
```powershell
C:/Python310/python.exe buyer_main.py
```
当前 `buyer_main.py` 只装配并显示窗口,**不连接设备、不执行任何自动化**,可以随时运行。
将来"开始自动获取"接上真实设备后,**启动自动化的命令会产生真实外部操作,届时不得作为普通冒烟测试运行**;那时的日常验证仍以第 2 条离屏测试为准。
**4. 其他情况**
- 修改数据库时测试首次建库和从上一版本迁移。
- 修改 Admin Gateway 时运行 Mock 与 HTTP 共用的契约测试。
- 修改 PDD 解析时优先使用脱敏 XML 固件;真实设备测试必须单独标记并说明是否执行真实下单。
- 交付时说明已运行的命令、结果、未验证的设备行为和新增依赖。
+19
View File
@@ -0,0 +1,19 @@
# Client 运行依赖
#
# 安装方法(在 client 目录下执行):
# C:/Python310/python.exe -m pip install -r requirements.txt
#
# 版本必须固定,不要改成不带 == 的写法(发布门禁要求,见 docs/client/06-quality-security.md §10)。
# 如果 pip 报"找不到该版本",处理办法见 docs/client/00-getting-started.md §2。
#
# 只支持 PyQt5。禁止安装 PyQt6 / PySide2 / PySide6,会和 PyQt-Fluent-Widgets 冲突。
# 界面
PyQt5==5.15.11
PyQt-Fluent-Widgets==1.11.3
# 安卓自动化
uiautomator2==3.2.5
# 后续接入 Admin HTTP 接口时再放开(当前只用 Mock,不需要装):
# requests==2.32.3