Client 采集回来的数据里要加两样现在契约没有的东西:
PDD 的规格面板只显示当前选中组合的价格(实测样本 client/image_xml/737116531267_size.xml:8 个颜色选项旁边没有各自价格, 整屏只有一处 折后¥4.7 / ¥19.9)。
client/image_xml/737116531267_size.xml
折后¥4.7
¥19.9
要拿每个颜色的价格必须逐个点击。已定案:按颜色采样(点 8 次), 而不是按颜色×尺码全遍历(点约 48 次)。
这意味着「黑色/2XL」的价格是从「黑色/某个尺码」推出来的,不是实测的。 如果该商品大码加价,记录的价格会偏低,下单时的价格保护会误判。
[必须] 所以必须把这件事标进数据里,不能让下游以为每个价格都是实测的。
[必须]
做:
pdd_products
shop_name
submit.go
不做:
skus[]
[必须] 新增 v4,ALTER TABLE pdd_products ADD COLUMN shop_name TEXT。
ALTER TABLE pdd_products ADD COLUMN shop_name TEXT
理由见 #20:#16 曾经原地改写 v1,导致已经建过库的机器版本号越过它、 永远不重跑,程序拿着对不上的库静默启动,点到页面才 500。 admin/AGENTS.md 已写死「migrations 只追加」这条 [必须]。
admin/AGENTS.md
[必须] #20 建立的三起点收敛测试要把 v4 覆盖进去—— 全新库 / v2 老结构库 / v2 新结构库,迁到最新后 schema 必须一致。
[必须] shop_name 可空。老数据没有它;Client 采不到时也留空。 不要加 NOT NULL DEFAULT ''——空字符串和「没采到」会分不清。
NOT NULL DEFAULT ''
Client 提交的 pdd_data 增加:
pdd_data
{ "goods_id": "737116531267", "title": "【店铺热销】冰丝吊带裙女夏季薄款内搭连衣裙宽松a字裙中长款打底裙衬裙纯色", "shop_name": "XX旗舰店", "price_granularity": "color", "dimensions": [ {"key": "color", "name": "颜色分类"}, {"key": "size", "name": "尺码"} ], "skus": [ { "options": {"color": "黑色中长款", "size": "2XL"}, "price_cent": 470, "list_price_cent": 1990, "price_observed_at": {"color": "黑色中长款", "size": "2XL"}, "available": true, "raw_price": "折后¥4.7" } ] }
[必须] price_granularity 取值 "color" 或 "sku"。 "color" 表示价格是按颜色采样的,同颜色下所有尺码共用一个价格。
price_granularity
"color"
"sku"
[必须] price_observed_at 记录读到这个价格时实际选中的是哪个组合。 「黑色/M」和「黑色/2XL」都写 470,但只有其中一个是实测的—— 这个字段说清是哪个。下单时价格保护据此判断「这个价格是实测还是推断」。
price_observed_at
[建议] list_price_cent 是划线价(样本里的 ¥19.9),可选。
[建议]
list_price_cent
[必须] price_cent 存的是实付价(样本里的 折后¥4.7 / 券后¥4.7), 不是划线价。价格保护比的是会真的花出去的钱。
price_cent
券后¥4.7
[必须] 未知字段照旧忽略(Go 的 json.Unmarshal 默���行为), 老版本 Client 不带这些字段时不得报错。
json.Unmarshal
[必须] shop_name 落到 pdd_products.shop_name 列。
pdd_products.shop_name
[必须] price_granularity 和 price_observed_at 不单独建列, 留在 skus_json 里。理由:它们是随采集结果整体变化的, 拆出来会和 skus_json 各存一份、可能不一致。
skus_json
[必须] 采集结果里没有 shop_name 时不要覆盖已有值。 Client 这次没采到不代表上次采到的作废了。
列表页表格加一列「店铺」,截断显示,未采到显示 —。
—
详情弹窗在商品信息区显示店铺名。
[必须] price_granularity == "color" 时,规格表上方给一句提示:
price_granularity == "color"
价格按颜色采样,同一颜色下各尺码显示同一价格。 标 ✓ 的是实测价,其余为推断值。
并在实测的那一行(options 与 price_observed_at 相同)标记出来。
options
理由:不标的话,操作员会以为每个价格都是实测的。 将来大码加价的商品会按低价下单,而没人知道数据是推断来的。
[必须] 状态和标记不能只靠颜色(docs/admin/05 §10)。
docs/admin/05
admin/repository/db.go
CheckSchema
admin/repository/migrate_test.go
admin/repository/pdd.go
pddColumns
SetCollectResult
admin/model/model.go
PddProduct.ShopName
admin/service/submit.go
collectedData
ShopName
admin/service/pdd.go
admin/templates/pdd/list.html
edit_modal.html
docs/admin/03-data-model.md
04-client-api.md
docs/client/04-admin-api-contract.md
go vet
gofmt -l .
go test ./...
cd D:\chengma\cmautobuy\admin go vet ./...; gofmt -l .; go test ./... -count=1 go test ./repository/ -run Migrate -v -count=1
端到端:建商品 → 建采集任务 → curl 模拟客户端提交上面那段带 shop_name / price_granularity 的报文 → 打开 /pdd 确认店铺列有值、 弹窗有粒度提示和实测标记。
/pdd
再提交一次不带 shop_name 的报文,确认原值还在。
回退:git revert。已迁到 v4 的库回退后会因「版本高于程序支持」拒绝启动, 这是 Migrate 已有的正确行为。
git revert
Migrate
已完成:
pdd_products.shop_name TEXT
验证结果:
gofmt -l . 通过(无输出) go vet ./... 通过 go build ./... 通过 go test ./... -count=1 通过 go test ./repository/ -run Migrate -v -count=1 通过 git diff --check 通过
五个主页面 /shopee、/pdd、/syb、/tasks、/clients 均由 httptest 验证为 200;PDD 详情同时验证店铺名、粒度提示、“✓ 实测”和“推断”均已渲染。
/shopee
/syb
/tasks
/clients
httptest
93beef8
feat: 保存并展示 PDD 店铺与价格采样信息 (#31)
61d8d1b
docs: 归档任务 #31
docs/task/31-admin-pdd-店铺与价格采样粒度.md
自动验证全部通过。未执行的仅有:真实 Client/Android 端到端提交(由 #32 接通)和真实浏览器 1366×768 人工视觉检查。工单保持开启,等待用户验收。
4022fee
架构角色复核要点:
ALTER TABLE pdd_products ADD COLUMN shop_name
SkuResult
sales(已拼数量)和 reviews(评价数量)Client 已在采集并提交(#28 #40),但 Admin 的 collectedData 未解析——数据保留在 skus_json blob 里没有丢,但没有列、不显示、不可查。
sales
reviews
这两个是商品热度参考,不参与下单和价格保护,优先级低。要在界面上显示的话需另开工单。
No dependencies set.
The note is not visible to the blocked user.
基本信息
要解决什么
Client 采集回来的数据里要加两样现在契约没有的东西:
操作员要能核对「是不是我要的那家店」,光看标题分不出来。
为什么需要粒度标记
PDD 的规格面板只显示当前选中组合的价格(实测样本
client/image_xml/737116531267_size.xml:8 个颜色选项旁边没有各自价格,整屏只有一处
折后¥4.7/¥19.9)。要拿每个颜色的价格必须逐个点击。已定案:按颜色采样(点 8 次),
而不是按颜色×尺码全遍历(点约 48 次)。
这意味着「黑色/2XL」的价格是从「黑色/某个尺码」推出来的,不是实测的。
如果该商品大码加价,记录的价格会偏低,下单时的价格保护会误判。
[必须]所以必须把这件事标进数据里,不能让下游以为每个价格都是实测的。做什么 / 不做什么
做:
pdd_products增加shop_name列(新增 migration v4)submit.go从采集结果里取出shop_name落库不做:
skus[]里已有的字段含义怎么做
migration 只能追加,不许改 v1/v2/v3
[必须]新增 v4,ALTER TABLE pdd_products ADD COLUMN shop_name TEXT。理由见 #20:#16 曾经原地改写 v1,导致已经建过库的机器版本号越过它、
永远不重跑,程序拿着对不上的库静默启动,点到页面才 500。
admin/AGENTS.md已写死「migrations 只追加」这条[必须]。[必须]#20 建立的三起点收敛测试要把 v4 覆盖进去——全新库 / v2 老结构库 / v2 新结构库,迁到最新后 schema 必须一致。
[必须]shop_name可空。老数据没有它;Client 采不到时也留空。不要加
NOT NULL DEFAULT ''——空字符串和「没采到」会分不清。契约新增两个字段
Client 提交的
pdd_data增加:[必须]price_granularity取值"color"或"sku"。"color"表示价格是按颜色采样的,同颜色下所有尺码共用一个价格。[必须]price_observed_at记录读到这个价格时实际选中的是哪个组合。「黑色/M」和「黑色/2XL」都写 470,但只有其中一个是实测的——
这个字段说清是哪个。下单时价格保护据此判断「这个价格是实测还是推断」。
[建议]list_price_cent是划线价(样本里的¥19.9),可选。[必须]price_cent存的是实付价(样本里的折后¥4.7/券后¥4.7),不是划线价。价格保护比的是会真的花出去的钱。
[必须]未知字段照旧忽略(Go 的json.Unmarshal默���行为),老版本 Client 不带这些字段时不得报错。
落库
[必须]shop_name落到pdd_products.shop_name列。[必须]price_granularity和price_observed_at不单独建列,留在
skus_json里。理由:它们是随采集结果整体变化的,拆出来会和
skus_json各存一份、可能不一致。[必须]采集结果里没有shop_name时不要覆盖已有值。Client 这次没采到不代表上次采到的作废了。
界面
列表页表格加一列「店铺」,截断显示,未采到显示
—。详情弹窗在商品信息区显示店铺名。
[必须]price_granularity == "color"时,规格表上方给一句提示:并在实测的那一行(
options与price_observed_at相同)标记出来。理由:不标的话,操作员会以为每个价格都是实测的。
将来大码加价的商品会按低价下单,而没人知道数据是推断来的。
[必须]状态和标记不能只靠颜色(docs/admin/05§10)。预计修改文件
admin/repository/db.goCheckSchema覆盖新列admin/repository/migrate_test.goadmin/repository/pdd.gopddColumns加shop_name;SetCollectResult落库admin/model/model.goPddProduct.ShopNameadmin/service/submit.gocollectedData加ShopNameadmin/service/pdd.goadmin/templates/pdd/list.html/edit_modal.htmldocs/admin/03-data-model.md/04-client-api.mddocs/client/04-admin-api-contract.md验收标准
shop_name可空,老库迁移后为 NULL 不报错shop_name→ 落库并在列表和弹窗显示shop_name→ 不覆盖已有值,不报错price_granularity == "color"时弹窗有提示文字price_cent取实付价的规则写进文档go vet/gofmt -l ./go test ./...全过怎么验证
端到端:建商品 → 建采集任务 → curl 模拟客户端提交上面那段带
shop_name/price_granularity的报文 → 打开/pdd确认店铺列有值、弹窗有粒度提示和实测标记。
再提交一次不带
shop_name的报文,确认原值还在。风险和回退
shop_name被空值覆盖回退:
git revert。已迁到 v4 的库回退后会因「版本高于程序支持」拒绝启动,这是
Migrate已有的正确行为。实施进度:代码完成,待提交
已完成:
pdd_products.shop_name TEXT,v1/v2 迁移原文和 v3 建表 SQL 未改写;shop_name关键列检查;shop_name、price_granularity、price_observed_at;pdd_data继续保存在skus_json,未拆分粒度字段;验证结果:
五个主页面
/shopee、/pdd、/syb、/tasks、/clients均由httptest验证为 200;PDD 详情同时验证店铺名、粒度提示、“✓ 实测”和“推断”均已渲染。实施完成,等待用户验收
93beef8feat: 保存并展示 PDD 店铺与价格采样信息 (#31)61d8d1bdocs: 归档任务 #31docs/task/31-admin-pdd-店铺与价格采样粒度.md自动验证全部通过。未执行的仅有:真实 Client/Android 端到端提交(由 #32 接通)和真实浏览器 1366×768 人工视觉检查。工单保持开启,等待用户验收。
验收通过,关闭
93beef8feat: 保存并展示 PDD 店铺与价格采样信息 (#31)docs/task/31-admin-pdd-店铺与价格采样粒度.md(状态已更新,4022fee)架构角色复核要点:
ALTER TABLE pdd_products ADD COLUMN shop_name,v1/v2 原文未动,注释里写明了「已经发布的 v1/v2 原文保持不动,老库才能可靠地逐版升级」CheckSchema覆盖了shop_name新列collectedData解析shop_name/price_granularity/list_price_cent/price_observed_at,字段名与 Client 侧SkuResult完全一致遗留
sales(已拼数量)和reviews(评价数量)Client 已在采集并提交(#28 #40),但 Admin 的collectedData未解析——数据保留在skus_jsonblob 里没有丢,但没有列、不显示、不可查。这两个是商品热度参考,不参与下单和价格保护,优先级低。要在界面上显示的话需另开工单。