fix: 修复顺运宝采集任务孤儿状态 (#165)

This commit is contained in:
chengma
2026-08-11 17:00:33 +08:00
parent c8b1fd686a
commit 9e328984e9
17 changed files with 508 additions and 67 deletions
+2 -1
View File
@@ -266,7 +266,8 @@ PDD 商品之所以单独一个模块,是因为它在数据上就是**独立
- **类型**:全部 / 采集 / 采购。
- **状态**:全部 + 7 个状态,见 §6.2。
- **关键词**:同时匹配任务编号、订单号、PDD 商品 ID。
- **关键词**:同时匹配任务编号、采购订单号、PDD 商品 ID;从顺运宝创建的采集任务
还要匹配其全部来源顺运宝订单号和明细 ID。
- **创建人**:仅管理员显示,可选全部账号(包含已禁用账号)或“历史任务”。
`[必须]` 采购员登录后只可查看自己创建的任务;URL 参数不能扩大范围。管理员查看
+31 -3
View File
@@ -108,6 +108,10 @@ SQLite 同一时刻只允许一个写事务,连接放太开会互相抢锁、
| v8(#59) | 顺运宝同步记录:新增 `syb_sync_runs` 和开始时间倒序索引;未改写 v1–v7。 |
| v9(#151) | `syb_orders` 增加可空 `shop_name`,从有效 `syb_data.stock.shopName` 回填历史店铺名;无效 JSON、缺字段和空白值保持 `NULL`。 |
生产 MySQL 迁移继续独立追加;v12(#165)新增 `task_syb_sources`,并把没有任何
有效采集任务的孤立 `pdd_products.collect_status='collecting'` 回收到 `pending`。
历史 SQLite migrations 保持冻结,不追加该表。
**v3 为什么丢弃旧 `sku_mappings` 数据(见 #20):** 新主键需要 `pdd_option_key`,
这是 Go 的 `service.OptionKey()` 用 `json.Marshal` 算出来的规范化键,SQL 语句
复现不了。硬凑一个键出来有两种后果:算错了会让映射静默失效,需要人工重新匹配一遍;
@@ -290,8 +294,8 @@ CREATE INDEX idx_pdd_products_status ON pdd_products(collect_status);
`collect_status` 就永远卡在 `collecting`,界面上没有任何入口能救回来,
只能改数据库(见 #24)。
修复:`collecting` 状态超过 `model.CollectStaleAfter`(15 分钟)**也允许**
重新建采集任务:
修复:`collecting` 状态超过 `model.CollectStaleAfter`(15 分钟),或已经找不到
`pending/assigned/claimed` 采集任务时,**也允许**重新建采集任务:
```sql
-- repository.MarkCollecting,简化版
@@ -299,7 +303,8 @@ UPDATE pdd_products
SET collect_status = 'collecting', updated_at = ?
WHERE goods_id = ? AND deleted_at IS NULL
AND ( collect_status IN ('pending', 'failed')
OR (collect_status = 'collecting' AND updated_at < ?) )
OR (collect_status = 'collecting' AND
(updated_at < ? OR NOT EXISTS (有效采集任务))) )
```
`[必须]` 15 分钟为什么是这个数:采集本身几十秒到两分钟,加上排队等客户端来领,
@@ -698,6 +703,29 @@ CREATE INDEX idx_tasks_order ON tasks(order_no);
状态含义见 [01 需求](01-requirements.md) §6.2。
### 7.1 `task_syb_sources` 采集任务来源(生产 MySQL v12)
从顺运宝创建采集任务时,同一个 PDD 商品可能对应多个货运单明细。来源使用关联表,
不能压进 `tasks.syb_id` 单列;后者仍只表示采购任务自身的顺运宝明细。
```sql
CREATE TABLE task_syb_sources (
task_id VARCHAR(191) COLLATE utf8mb4_bin NOT NULL,
syb_id VARCHAR(191) COLLATE utf8mb4_bin NOT NULL,
created_at VARCHAR(35) NOT NULL,
PRIMARY KEY (task_id, syb_id),
KEY idx_task_syb_sources_syb (syb_id, task_id),
FOREIGN KEY (task_id) REFERENCES tasks(task_id) ON DELETE CASCADE,
FOREIGN KEY (syb_id) REFERENCES syb_orders(syb_id) ON DELETE CASCADE
);
```
- `[必须]` 任务和全部来源在同一事务写入;按 PDD 商品去重后仍要保留每条来源。
- `[必须]` 采集采购关键字搜索通过本表支持顺运宝订单号和明细 ID。
- `[必须]` 删除任务后若同商品已无 `pending/assigned/claimed` 采集任务,必须在同一事务
把仍为 `collecting` 的商品回收到 `pending`;有其他有效任务时不得回收。
- 历史任务没有可靠来源,不做猜测回填,仍可按任务号和 PDD 商品 ID 查询。
## 8. `task_claims` 领取历史
记录"哪台客户端领过哪个任务"。
+6 -3
View File
@@ -526,8 +526,10 @@ HTML 片段,只替换弹窗内部的表格、总数和分页。主货运单表
- 图片显示小缩略图。点击缩略图在弹窗中按比例查看顺运宝原图,并提供新窗口打开入口;
图片加载失败时显示可读提示。`[必须]` 只存 URL,不代理、缓存或把图片塞进数据库。
- 处理阶段是按当前关联事实**算出来的**,不是存一份容易过期的状态字段。阶段至少区分:
采购数据异常(顺运宝未提供规格)、未关联 PDD、PDD 待采集、采集中、
采购数据异常(顺运宝未提供规格)、未关联 PDD、PDD 待采集、采集中、采集中(超时)、
采集失败、规格待匹配、可采购和已创建任务。
- `collecting` 已超过 15 分钟,或已找不到 `pending/assigned/claimed` 采集任务时,
显示“PDD 采集中(超时)”和“重新创建采集任务”,不能继续伪装成正常进行中。
- 每行显示一个有文字的“下一步”按钮。商品标题是服务端渲染处理弹窗的明确入口,
支持鼠标和键盘;双击其他普通单元格不执行动作。图片入口只负责查看原图,不能打开处理详情。
- “下一步”随实时阶段变化:未关联 PDD、待采集、采集中、采集失败、规格待匹配、
@@ -536,7 +538,8 @@ HTML 片段,只替换弹窗内部的表格、总数和分页。主货运单表
- 规格原文为空时不显示匹配表单,明确提示“顺运宝未提供规格”,并禁止建立映射或创建采购任务。
- 完整货运单 JSON 不作为列显示,落在 `syb_data` 里,供后续排查用。
复选框按批量动作能力启用,不再等同于“可采购”:PDD 待采集、PDD 采集失败行可用于
复选框按批量动作能力启用,不再等同于“可采购”:PDD 待采集、PDD 采集失败、
PDD 采集中(超时)行可用于
“创建 PDD 采集任务”,可创建采购任务行可用于“创建采购任务”,其他阶段继续禁用并通过
`title` 和无障碍标签说明原因。混合勾选时两个按钮分别统计和提交自身兼容的行,不能把
待采集商品带进采购确认,也不能把采购就绪商品带进采集请求。
@@ -639,7 +642,7 @@ ID 和在线状态;所有可见 Client 都可选择且只有一个时自动选
- **类型**:全部 / 采集 / 采购。
- **状态**:全部 + 7 个状态,见 [01 需求](01-requirements.md) §6.2。
- **关键词**:同时匹配任务编号、订单号、PDD 商品 ID。
- **关键词**:同时匹配任务编号、采购订单号、PDD 商品 ID、来源顺运宝订单号和明细 ID。
- **创建人**:仅管理员显示;包含全部账号、已禁用账号和“历史任务”。采购员不显示
此控件,服务端固定只查询本人创建的任务。