Files
cmautobuy/client/AGENTS.md
T

8.1 KiB
Raw Blame History

Client 子项目规则

本文件适用于 client/ 下的全部代码和测试,并继承仓库根目录 AGENTS.md 的工作流、Git、安全、文档和初级程序员维护规则。

开始工作前

技术栈

  • 固定使用 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.py,事件绑定放 src/<页面>_ui_event.py(当前有 pdd_ui / settings_ui 两组)。
  • 每个文件顶部的模块 docstring 写明了该文件的约束,动手前先读那几行。
  • 领域模型不导入 Qt、uiautomator2 或具体 HTTP 客户端。
  • Admin 通过 Gateway 接口隔离,Mock 和 HTTP 实现必须遵守相同契约。
  • SQLite 通过 Repository 访问,不在页面或自动化函数中散落业务 SQL。
  • PDD 页面识别、采集和采购函数放在 PDD 适配层;演示脚本不得被正式流程直接导入。
  • 类和函数骨架遵循根目录的初级程序员维护规则,优先补全现有清晰边界,不随意重做架构。

数据与接口

  • Client 软件更新的公开引导默认密码固定为 chengma,必须以单一常量写入源码并随 Git 管理;没有已保存 Windows 凭据时允许把它填入隐藏回显的密码框。该值是根红线第 4 条的唯一例外,其他密码、Token 和 Cookie 仍不得进入源码、Git、SQLite、日志、工单或文档。
  • 数据库字段、任务状态和 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。不许硬编码路径,不许用 os.getcwd() 或 __file__ 直接拼,打包成 exe 后会失效。
  • PDD 结果必须先写入 SQLite,再通过 Outbox 提交 Admin。
  • 任务领取后中途不查 Admin 状态;Admin 取消或重派一律不感知,做完照常提交。

线程与自动化

  • QWidget 只能在 Qt 主线程创建和访问。
  • 禁止在主线程执行 Admin 请求、uiautomator2/ADB、time.sleep()、轮询、大型 XML 解析或文件批量写入。
  • 长任务统一使用 QObject + moveToThread 的 Worker 写法,模板见 02 架构 §5.1;不得混用 QThread 子类、QRunnable 或 threading。
  • 后台结果通过信号回到主线程;窗口关闭时按 02 架构 §5.2 断开连接,防止迟到结果访问已销毁控件。
  • 一个 Android 设备同一时间只由一个工作线程控制,不跨线程共享 uiautomator2 Device 对象。
  • 自动化任务必须处理启动、运行、安全停止、成功、失败、取消、超时、设备断开和迟到结果。
  • 窗口或页面销毁后,后台回调不得再访问对应控件。

采购安全

  • Admin 新建采购任务固定下发 live;Client 不提供手工启用或关闭真实采购的请求、设置或调试开关。Client 身份、已选 Android 设备和真实采购执行器就绪时自动声明 live;任一项未就绪时不得领取真实采购任务。
  • 高风险点击前必须使用最新页面状态重新校验商品、规格、数量、价格和目标坐标。
  • 进入不可逆下单阶段前先持久化执行步骤。
  • 不可逆阶段发生崩溃或结果不确定时,只能核对订单或转人工处理,禁止自动重新下单。
  • 多个订单候选、验证码、登录失效、未知弹窗、价格超限或规格不确定时停止自动执行。

界面规则

  • 顶级模块保持为“PDD 任务”和“设置”,页面使用唯一且稳定的 objectName。
  • 优先使用 FluentWindow、Fluent 导航、主题和图标;不得使用表情符号充当结构图标。
  • 使用布局、尺寸策略和伸缩项,不用固定坐标排列常规界面。
  • 任务表格使用模型/视图和稳定任务编号,不把完整 pdd_data 放入隐藏列,也不为每个单元格创建常驻 QWidget。
  • 会产生外部后果的命令只有“获取任务”“重新执行”和“重新上报”:重新执行只允许单条采集任务;重新上报只重发既有 Outbox(优先未发送事件),不操作手机、不创建新事件。搜索、筛选、刷新和详情仍只读本地数据库。
  • 本地只保存已领取的任务,不缓存 Admin 任务池;已完成任务永久保留,不得清理。
  • 普通成功更新页面状态即可;可恢复错误使用 InfoBar,只有必须阻断决策时才使用模态对话框。
  • 主要流程必须支持键盘;表单具有可见标签;状态和错误不能只依赖颜色。
  • 验证浅色、深色、Windows 贴靠和 100%–200% 显示缩放。
  • 避免全局 QSS 覆盖 Fluent 控件;局部样式必须保留悬停、按下、焦点和禁用状态。

验证

全部命令从 client/ 目录执行,可直接复制。

1. 语法检查(改了哪个文件就换成哪个)

C:/Python310/python.exe -m py_compile src/ui_main.py

2. 界面离屏冒烟测试(不弹窗口,跑完自动退出,CI 和本地都用这条)

$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. 手动看界面

C:/Python310/python.exe buyer_main.py

当前 buyer_main.py 只装配并显示窗口,不连接设备、不执行任何自动化,可以随时运行。

将来“获取任务”接上真实设备后,启动自动化的命令会产生真实外部操作,届时不得作为普通冒烟测试运行;那时的日常验证仍以第 2 条离屏测试为准。

4. 其他情况

  • 修改数据库时测试首次建库和从上一版本迁移。
  • 修改 Admin Gateway 时运行 Mock 与 HTTP 共用的契约测试。
  • 修改 PDD 解析时优先使用脱敏 XML 固件;真实设备测试必须单独标记并说明是否执行真实下单。
  • 交付时说明已运行的命令、结果、未验证的设备行为和新增依赖。