diff --git a/.gitignore b/.gitignore index 16bf8b8..141afdc 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,11 @@ admin/admin ~$*.xlsx ~$*.xls +# 蝦皮原始报表:含逐商品台币销售额等商业数据,不进 Git +# 需要样本时找项目负责人要,放到 raw_data/ 下 +# 自动化测试用 admin/testdata/ 下已脱敏的小样本 +raw_data/ + # Python __pycache__/ *.py[cod] diff --git a/admin/AGENTS.md b/admin/AGENTS.md index 14d051e..f02d1d8 100644 --- a/admin/AGENTS.md +++ b/admin/AGENTS.md @@ -96,4 +96,5 @@ go run . - 修改数据库时测试首次建库和从上一版本迁移。 - 修改给 Client 的接口时,跑契约测试,确认仍满足 Client 侧 §6.1 的无条件接受。 - 修改 Excel 导入时用 `raw_data/` 下的样本跑一遍,核对导入条数。 + 该样本含商业数据、**不在仓库里**,需向项目负责人索取;自动化测试用 `testdata/` 下的脱敏小样本。 - 交付时说明已运行的命令、结果和未验证的部分。 diff --git a/client/AGENTS.md b/client/AGENTS.md index 6110ec4..678001f 100644 --- a/client/AGENTS.md +++ b/client/AGENTS.md @@ -72,7 +72,7 @@ - 优先使用 `FluentWindow`、Fluent 导航、主题和图标;不得使用表情符号充当结构图标。 - 使用布局、尺寸策略和伸缩项,不用固定坐标排列常规界面。 - 任务表格使用模型/视图和稳定任务编号,不把完整 `pdd_data` 放入隐藏列,也不为每个单元格创建常驻 QWidget。 -- “开始自动获取”是界面上唯一会产生外部后果的命令;其余操作只读本地数据库。 +- “获取任务”(启动后变为“停止获取”)是界面上唯一会产生外部后果的命令;其余操作只读本地数据库。 - 本地只保存已领取的任务,不缓存 Admin 任务池;已完成任务永久保留,不得清理。 - 普通成功更新页面状态即可;可恢复错误使用 `InfoBar`,只有必须阻断决策时才使用模态对话框。 - 主要流程必须支持键盘;表单具有可见标签;状态和错误不能只依赖颜色。 @@ -107,7 +107,7 @@ C:/Python310/python.exe buyer_main.py 当前 `buyer_main.py` 只装配并显示窗口,**不连接设备、不执行任何自动化**,可以随时运行。 -将来"开始自动获取"接上真实设备后,**启动自动化的命令会产生真实外部操作,届时不得作为普通冒烟测试运行**;那时的日常验证仍以第 2 条离屏测试为准。 +将来“获取任务”接上真实设备后,**启动自动化的命令会产生真实外部操作,届时不得作为普通冒烟测试运行**;那时的日常验证仍以第 2 条离屏测试为准。 **4. 其他情况** diff --git a/client/src/pdd_ui_event.py b/client/src/pdd_ui_event.py index f9d9228..00ad228 100644 --- a/client/src/pdd_ui_event.py +++ b/client/src/pdd_ui_event.py @@ -13,7 +13,7 @@ - 窗口关闭时要断开信号并置标志位,否则迟到的后台结果会访问 已经销毁的控件、直接崩溃。做法见同文档 §5.2。 - 数据库读写走 Repository,**不要在这里拼业务 SQL**。 -- “开始自动获取”会真的去操作手机、可能下单;“搜索”只读本地数据库。 +- “获取任务”会真的去操作手机、可能下单;“搜索”只读本地数据库。 两者必须分开,不得共用入口。 - 普通成功不弹窗,更新界面即可;可恢复错误用 `InfoBar` (模板见 `docs/client/05-ui-specification.md` §9.1); diff --git a/docs/admin/00-getting-started.md b/docs/admin/00-getting-started.md index 4ba0577..f97e66a 100644 --- a/docs/admin/00-getting-started.md +++ b/docs/admin/00-getting-started.md @@ -113,14 +113,20 @@ admin/data/ ## 7. 拿样本数据试一下导入 -仓库里有一份真实的蝦皮导出样本: +蝦皮的真实报表**不在仓库里**——里面有逐商品的台币销售额,属于商业数据, +已在 `.gitignore` 里排除。 + +需要的话**找项目负责人要一份**,放到仓库根目录的 `raw_data/` 下: ```text raw_data/蝦皮数据样本.xlsx ``` -11287 行,其中 5195 行是商品汇总行、6092 行是 SKU 行。 -导入后应该得到 **5195 条商品 + 6092 条 SKU**。数字对不上就是解析有问题。 +参考样本是 11287 行 = 5195 商品汇总行 + 6092 SKU 行, +导入后应得到 **5195 条商品 + 6092 条 SKU**。数字对不上就是解析有问题。 + +> 写自动化测试**不要**用这份大文件,用 `admin/testdata/` 下已脱敏的小样本, +> 见 [06 质量与安全](06-quality-security.md) §2.1。 解析规则见 [03 数据模型](03-data-model.md) §3.3,那里说明了为什么一个文件要拆成两张表。 diff --git a/docs/admin/03-data-model.md b/docs/admin/03-data-model.md index 3eb7a95..4f38c40 100644 --- a/docs/admin/03-data-model.md +++ b/docs/admin/03-data-model.md @@ -105,7 +105,10 @@ CREATE INDEX idx_shopee_skus_parse ON shopee_skus(parse_ok); | 商品汇总行 | `商品規格ID` 是 `-` 或空 | 5195 | `shopee_products` | | SKU 行 | `商品規格ID` 是数字 | 6092 | `shopee_skus` | -导入 `raw_data/蝦皮数据样本.xlsx` 应得到 **5195 商品 + 6092 SKU**,数字对不上就是解析有问题。 +拿参考样本(11287 行)导入应得到 **5195 商品 + 6092 SKU**,数字对不上就是解析有问题。 + +> 样本文件含商业数据,**不在仓库里**,找项目负责人要,放 `raw_data/` 下。 +> 自动化测试用 `admin/testdata/` 里的小样本,别读大文件。 **第二步:按列名找索引,不要写死列号** diff --git a/docs/admin/06-quality-security.md b/docs/admin/06-quality-security.md index be86afe..4499fe6 100644 --- a/docs/admin/06-quality-security.md +++ b/docs/admin/06-quality-security.md @@ -29,8 +29,15 @@ - SKU 映射复用:第二次匹配同一 SKU 应自动带出; - 在线状态派生:`last_seen_at` 刚好在边界前后。 -`[必须]` 导入相关的测试用 `testdata/` 下的**小样本**(几十行), -不要每次跑测试都读 1.9MB 的完整报表。 +`[必须]` 导入相关的测试用 `admin/testdata/` 下的**小样本**(几十行), +不要读完整报表。 + +`[必须]` 这份小样本**必须提交进 Git**,否则别人拉下来测试跑不了。 +制作方法:从真实报表里挑几十行,**删掉全部销售额、曝光、转化率等指标列**, +只保留导入用得到的字段(商品ID、商品名稱、商品規格ID、商品規格、貨號等), +并把商品名称改成无意义的占位文字。 + +完整报表含商业数据,**不进 Git**(见 `.gitignore`)。 ### 2.2 集成测试 @@ -144,7 +151,7 @@ | 2 | `go vet ./...` 无告警 | | 开发者 | | 3 | `go test ./...` 全绿 | 不允许有跳过而未说明的用例 | 开发者 | | 4 | 四个页面能正常打开 | 起服务跑一遍 | 开发者 | -| 5 | 样本导入条数正确 | 导 `raw_data/蝦皮数据样本.xlsx`,应得 5195 商品 + 6092 SKU | 开发者 | +| 5 | 样本导入条数正确 | 导入参考样本(需向项目负责人索取,放 `raw_data/`),应得 5195 商品 + 6092 SKU | 开发者 | | 6 | 数据库从上一版本迁移成功 | 拿旧 `admin.db` 副本启动新版本,人工数据不丢 | 开发者 | | 7 | 契约测试通过 | [04 §9 清单](04-client-api.md)逐条 | 开发者 | | 8 | 干净环境启动 | 没装过本项目的机器上 `go run .` 或跑 exe | 开发者 | diff --git a/docs/client/01-requirements.md b/docs/client/01-requirements.md index 7e416e4..3f4e4f9 100644 --- a/docs/client/01-requirements.md +++ b/docs/client/01-requirements.md @@ -83,8 +83,8 @@ Client 应执行: ### 5.1 顶部命令区 -- “开始自动获取”是持续任务引擎的主操作,启动后切换为“停止自动获取”。 -- 停止自动获取只停止领取新任务;当前任务应运行到安全停止点。 +- “获取任务”是持续任务引擎的主操作,启动后按钮文字切换为“停止获取”。 +- 停止只停止领取新任务;当前任务应运行到安全停止点。 - 搜索条件至少支持任务类型、任务状态和关键词。 - 关键词搜索任务编号、商品编号和商品标题。 - “搜索”只查询本地数据库,不触发任务执行。 diff --git a/docs/client/02-architecture.md b/docs/client/02-architecture.md index fb020c7..71c9924 100644 --- a/docs/client/02-architecture.md +++ b/docs/client/02-architecture.md @@ -89,7 +89,7 @@ client/ | 主窗口文件 | `src/ui/main_window.py` | `src/ui_main.py` | | 目录分层 | domain / application / infrastructure / workers / ui | 只有 `src/`、`src/util/`、`src/demo1/` | | PDD 任务页 | 任务表格 + 搜索 + 状态栏 | 单个商品的输入表单(链接/颜色/尺码 + 开始按钮) | -| 主按钮文案 | 「开始自动获取」 | 「开始任务」 | +| 主按钮文案 | 「获取任务」⇄「停止获取」 | 构造时是「获取任务」,但状态机(`pdd_ui.py` 485/487 行)仍写着「开始自动获取」/「停止自动获取」,会覆盖掉,**待修** | | 页面与事件层 | `ui/` 下按页面分文件 | `src/pdd_ui.py`、`src/pdd_ui_event.py`、`src/settings_ui.py`、`src/settings_ui_event.py`,目前只有约束 docstring,尚无实现 | | SQLite / Admin / Outbox / 任务协调器 | 见 §4 | 尚未实现 | | PDD 自动化 | `infrastructure/pdd/` 适配层 | `src/util/` 下的独立函数 + `src/demo1/auto_v1.py` 演示脚本 | @@ -151,7 +151,7 @@ Qt 主线程 - `[必须]` QWidget 只能在 Qt 主线程创建和访问。 - `[必须]` 一个 Android 设备由一个工作线程独占,不跨线程共享 uiautomator2 Device 对象。 - `[必须]` 后台信号只传递不可变数据、稳定编号或轻量视图模型。 -- `[必须]` 停止自动获取时停止领取新任务,当前任务在定义的安全点退出。 +- `[必须]` 点“停止获取”后不再领取新任务,当前任务在定义的安全点退出。 - `[建议]` 关闭窗口时应选择停止、等待或后台继续;MVP 默认安全停止并持久化状态。 ### 5.1 Worker 模板(项目统一写法,照抄即可) diff --git a/docs/client/05-ui-specification.md b/docs/client/05-ui-specification.md index 06b87e6..ff13c87 100644 --- a/docs/client/05-ui-specification.md +++ b/docs/client/05-ui-specification.md @@ -9,7 +9,7 @@ ## 1. 设计目标 - 让操作人员在一个页面完成任务监控、搜索和异常定位。 -- 界面上只有一个会产生外部后果的命令:“开始自动获取”。其余操作全部只读本地数据库。 +- 界面上只有一个会产生外部后果的命令:“获取任务”。其余操作全部只读本地数据库。 - 长任务状态始终可找到,不使用连续模态弹窗打断工作。 - 任务表格在数据增长后仍保持响应速度、稳定选择和可访问性。 - 界面只展示任务状态,不在 Qt 主线程执行 Admin 或手机自动化。 @@ -35,7 +35,7 @@ ```text ┌─────────────────────────────────────────────────────────────┐ │ PDD 任务 │ -│ [开始自动获取] [类型▼] [状态▼] [关键词............] [搜索] │ +│ [获取任务] [类型▼] [状态▼] [关键词................] [搜索] │ ├─────────────────────────────────────────────────────────────┤ │ 类型 │ 商品标题 │ 颜色 │ 尺码 │ 价格 │ 数量 │ 状态 │ 更新时间 │详情│ │ │ @@ -50,11 +50,12 @@ ## 4. 顶部命令区 -### 4.1 开始/停止自动获取 +### 4.1 获取任务 / 停止获取 - 使用 `PrimaryPushButton`,是页面唯一主要强调操作。 -- 初始文本为“开始自动获取”,图标表达开始。 -- 启动成功后文本变为“停止自动获取”,按钮位置和宽度尽量稳定。 +- 初始文本为“获取任务”,图标表达开始。 +- 启动成功后文本变为“停止获取”,按钮位置和宽度尽量稳定。 +- `[必须]` 这两个文案是**按钮标签**。状态栏里的“自动获取:已开启/已停止”说的是**功能状态**,两者不是一回事,不要混改。 - 启动过程中禁用重复点击,显示“正在启动”。 - 停止表示不再领取新任务;当前任务进入安全停止流程。 - 如果设备、Admin 或必要设置无效,按钮可禁用,但附近必须说明缺少的条件。 @@ -100,7 +101,7 @@ - “详情”使用委托或链接语义,不为每行创建常驻 QWidget。 - 空状态要分情况,文案不能一样: - 加载中; - - **从没领取过任务** —— “还没有领取过任务,点击‘开始自动获取’开始领取”(不要写“暂无数据”,操作人员会以为是出错了); + - **从没领取过任务** —— “还没有领取过任务,点击‘获取任务’开始领取”(不要写“暂无数据”,操作人员会以为是出错了); - 筛选无结果 —— 提供清除条件入口; - Admin 离线 —— 本地数据照常显示,只在信息条说明领取失败; - 加载失败。