chengmaandClaude Opus 5 998c06a2bf feat: PDD 商品数据独立成表 (#16)
原来 pdd_data 是 shopee_products 上的一个 JSON 字段,两个蝦皮商品指向
同一个 PDD 链接时会各存一份、各采一次;collect_status 描述的是 PDD 商品的
状态,却挂在蝦皮商品上,两份可能不一致。

更要紧的是 PDD 商品变动频繁(A 下架就得换 B),而 sku_mappings 只按
shopee_sku_id 做键——换商品后旧映射还在,B 恰好有同名规格但完全是另一件货
时会静默买错,事后查不出来。

改动
- 新增 pdd_products 表:id 主键 + goods_id UNIQUE + 4 个状态值(去掉
  no_link,「未填链接」改由 shopee_products.pdd_goods_id 为空表达)+
  软删除可复活
- shopee_products 去掉 pdd_data / collect_status / collect_error /
  collected_at,pdd_goods_id 改为引用
- sku_mappings 主键改为 (shopee_sku_id, pdd_goods_id),新增 pdd_option_key。
  查映射永远带上当前 PDD 商品,换商品后天然查不到旧映射,不需要删数据;
  换回原商品时旧映射直接复用
- 新增 OptionKey():用 json.Marshal 实现(Go 序列化 map 按键名排序,
  天然规范化),不自己拼字符串——规格文字里可能含 = 或 ;。
  存映射和查 SKU 必须用同一个函数,各写一遍会静默算出不同结果
- 采集结果改落 pdd_products,新增两条校验:
  返回的 goods_id 与请求不符 → 整体回滚拒绝(422),不静默存下;
  skus 为空数组 → 置 failed 而非 collected,否则界面显示"已采集"
  但数据毫无用处

实施时超出工单但必要的三处
- TaskExists 重构为 GetTaskInfo:原函数只返回蝦皮 goods_id,
  而采集结果要按 PDD goods_id 落库,不改取不到正确的键
- 复活时一并清空旧采集结果(skus_json / collect_msg / collected_at),
  否则复活后会显示"已采集"但数据是删除前的
- 删除 repository/shopee.go:两个函数签名全变且已迁到 pdd.go,留着是死代码

已验证(Go 1.23.0)
- go vet / gofmt / go test 全过,55 个测试
- 端到端补验了工单未覆盖的 HTTP 层:goods_id 不符返回 422
  COLLECT_GOODS_MISMATCH 且整体回滚(skus_json 空、任务仍 claimed、
  幂等记录 0 条);skus 为空返回 200 但状态 failed

遗留
- MarkCollecting / SoftDeletePddProduct 暂无调用方,等界面工单接上
- artifact_ref 存 diagnostics 原始 JSON,未按 client-001:artifacts/... 规范化,
  因 Client 侧尚未定义 diagnostics 结构
- 界面未实现(工单明确排除),四个页面仍为骨架

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 10:27:39 +08:00
2026-08-06 15:51:05 +08:00

项目文档索引

本目录保存项目级文档。长期稳定的基线文档按子项目放在 docs/client 和 docs/admin, 实施过程和完成记录放在 docs/task,两者不得混用。

项目由两部分组成

子项目 是什么 技术栈 规则文件
Client Windows 桌面客户端,控制安卓设备在拼多多采集和下单 Python 3.10 + PyQt5 client/AGENTS.md
Admin 本地 Web 管理端,管理商品、货运单、采购任务和客户端 Go + Gin + HTML 模板 admin/AGENTS.md

两者通过三个 HTTP 接口交互,契约以 Client 侧的接口契约 为准。

两个子项目技术栈完全不同,规则不通用。 别拿 Client 的经验套 Admin,反之亦然。

新人从这里开始

我要做 先读
上手 Client Client 上手指南 + Client 术语表
上手 Admin Admin 上手指南 + Admin 术语表
搞清楚整条业务链路 Admin 需求 §3

按任务找文档

不用通读全部文档,按你要做的事挑:

Client(桌面客户端)

我要做的事 主要看 顺带看
第一次把项目跑起来 00 上手指南 —
改界面、加页面、调表格 05 界面交互规范 02 架构 §5 线程
加字段、改表、写 SQL 03 数据模型 02 架构 §7 数据所有权
对接 Admin、写 Gateway 04 接口契约 07 联调手册
写自动化、控制手机 02 架构 §9 06 质量与安全 §4
碰采购、下单相关代码 06 质量与安全 §3 01 需求 §4.2
写测试 06 质量与安全 §2 —
搞不清这功能到底要不要做 01 产品需求基线 —
打包成 exe、改文件路径 01 需求 §8.1 03 数据模型 §2

Admin(Web 管理端)

我要做的事 主要看 顺带看
第一次把项目跑起来 00 上手指南 —
改页面、加表格列 05 界面规范 02 架构 §4 模板
加字段、改表、写 SQL 03 数据模型 02 架构 §2 分层
改 Excel 导入 03 数据模型 §3.3 00 术语表 §3 upsert
改给 Client 的接口 04 Client 接口实现 Client 侧契约
和 Admin 联调、登记新设备 07 设备登记联调手册 Client 侧契约 §5
写测试 06 质量与安全 §2 —
搞不清这功能到底要不要做 01 产品需求基线 —

通用

我要做的事 看这里
建工单、写归档 模板 + 根目录 AGENTS.md

无论做哪一样,都必须先看一遍对应子项目的 AGENTS.md(技术栈和红线)。

Client 基线文档

文档 用途
00 上手指南 装环境、连手机、跑起来、常见报错
00 术语表 Outbox、幂等、不可逆阶段等
01 产品需求基线 目标、范围、任务类型、打包策略
02 系统架构 分层、线程模型、Worker 模板
03 数据模型 SQLite 表、状态机、pdd_data 结构
04 Admin 接口契约 两个子项目的接口边界,改动需同步 Admin
05 界面交互规范 PDD 任务页、设置页、表格交互
06 质量、安全与测试 测试策略、采购安全、发布门禁

Admin 基线文档

文档 用途
00 上手指南 装 Go、跑起来、常见报错
00 术语表 货运单、upsert、SKU 映射等
01 产品需求基线 业务链路、四个模块、状态定义
02 系统架构 分层、目录、模板组织、前端约束
03 数据模型 SQLite 表、Excel 导入规则
04 Client 接口实现 服务端怎么实现那三个接口
05 界面规范 三段式布局、四个页面、弹窗
06 质量、安全与测试 测试、Web 安全、发布门禁
07 设备登记联调手册 给 Client 开发者:怎么让新设备登记成功

文档标注说明

基线文档中的条目按下面三档标注,没有标注的默认是 [必须]:

标注 含义
[必须] 不许改。要改先走工单,并经用户确认
[建议] 默认这么做;有更合适的做法可以换,但要在工单里说明原因
[待定] 还没定下来。文档会给一个临时默认值,先按临时值做,别停工

文档生命周期

  • docs/client 和 docs/admin 只记录不随单个任务频繁变化的产品和技术基线。
  • 日常需求、缺陷、进度、阻塞和方案变更以 Gitea 工单为事实来源。
  • 单元任务完成后,按 AGENTS.md 归档到 docs/task/<工单号>-<简短名称>.md。
  • 基线发生实质变化时,必须先更新对应 Gitea 工单并完成评审,再在同一任务中更新这里的相关文档。
  • 接口契约改动必须两边同步:docs/client/04-* 和 docs/admin/04-* 在同一个工单里一起改。

文档和代码对不上怎么办

现在的代码还没做到文档描述的目标状态,对不上是正常的。 Client 的已知差异列在 02 架构 §3.1; Admin 目前尚未开始编码。

按下面处理,不要一发现不一致就停工:

情况 怎么办
差异已经列在差异清单里 按代码现状继续做,不用停
差异不在清单里,但只影响写法、不影响业务结果 按文档做,并在工单里记一句
差异会影响业务结果(金额、数量、状态、下单与否、数据结构) 停下来,在工单里说明,等用户确认哪边是对的

判断不了算不算"影响业务结果"时,按最后一行处理。

文档状态

Client 和 Admin 文档均为 基线草案。

Admin 尚未开始编码;顺运宝同步方式、认证方式和部分字段仍需确认, 这些事项已在对应文档中标注为 [待定],并给出了临时默认值。

S
Description
No description provided
Readme
96 KiB
Languages
Markdown 100%