Files
cmautobuy/docs/task/41-admin-蝦皮数据页商品级列表.md
T
chengmaandClaude Opus 5 6d40c1e986 docs: 归档 #41 #43,记录 #38 #41 #43 验收通过
#41 归档记录了两条防信息丢失的设计(SKU 数列、待补列),以及最危险的
「部分失败」场景实测:28431952912 颜色4/尺码5 数字看着正常,
里面有 4 个 SKU 解析失败,靠整行标黄才藏不住。

#43 归档记录了实现踩到的 html/template URL 上下文转义坑:
夹在字面量 & 中间的动态内容会被整体当成一个参数值转义,
?/= 变成 %3F/%3D 让链接失效,只有真跑起来看 HTML 才发现。

也记了架构角色第二个变异第一次打偏、显示「跳过」的事——
探针无效和代码有问题是两回事,#38 刚犯过一次。

三份都如实列了「未验证到的部分」,主要是浏览器实机交互和
列宽百分比在 table-cell 上的实际行为。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 10:06:42 +08:00

169 lines
7.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 41 Admin 蝦皮数据页改为商品级列表与规格弹窗
- 类型:需求(界面重构)
- 父级大工单:#14
- 所属 MVP / 版本:#15 / MVP
- 关联:#38(导入)、#18(弹窗机制来源)
- 状态:验收通过
- 日期:2026-08-08
- Gitea 工单:http://ilaer.eicp.net:8418/chengma/cmautobuy/issues/41
## 背景与目标
蝦皮数据页原来是 **SKU 级一行**。问题不在行数(6092 → 5195 只少 15%,
平均每个商品仅 1.17 个 SKU),在**语义错了**:
`pdd_goods_url` / `pdd_goods_id` 在 `shopee_products` 上,是**商品级**字段。
实测商品 `24420648774` 有 **62 个 SKU**——列表里 62 行显示的是**同一个
PDD 链接**,将来双击任意一行编辑的也是**同一个字段**。操作员会以为
「我改的是这一行的链接」。
## 最终方案
```text
☐ │ 商品 ID │ 商品名称 │ 颜色 │ 尺码 │ SKU │ 待补 │ PDD 链接 │ 采集状态 │ 更新时间
15 5 28 2
```
### 必须加「SKU 数」列
`[必须]` 只显示颜色数和尺码数会**严重误导**。实测:
```
颜色数×尺码数 > 实际 SKU 数的商品:602 个(占 11.6%)
goods_id 颜色数 尺码数 相乘 实际 SKU
26886533818 15 5 75 28 ← 差 2.7 倍
24773321934 10 6 60 14
27739534478 12 6 72 36
```
看到「颜色 15 / 尺码 5」,正常人会以为有 75 个规格要匹配,**实际只有 28 个**。
根因:蝦皮报表只含**有销售成绩的** SKU,数据本来就不全。三个数字放在一起,
操作员才看得出「这商品在报表里只有 28 条记录,不是 75 条」。
### 必须加「待补」列并整行标黄
`[必须]` 原来 `parse_ok = 0` 的行显示 `—` 并整行标黄,一眼能看见要人工补。
聚合成数量之后这个信号会丢。实测:
```
23 条解析失败的 SKU,分布在 6 个商品里
4 个是「部分失败」 → 显示「颜色 3」,坏的那几个直接消失
2 个是「全部失败」 → 显示「颜色 0 / 尺码 0」
```
**「部分失败」那 4 个最危险**——数字看着正常,坏数据被吃掉,永远没人去补。
`[必须]` 颜色数 / 尺码数**只统计 `parse_ok = 1`** 的 SKU。
把解析失败的空值算进 DISTINCT 会多出一个「空颜色」。
### 弹窗只读,待补的行显示原文
`[必须]` 待补的行必须显示 `spec_raw` 原文——不显示的话人工不知道该填什么,
保留原文这个设计就白做了。
`[必须]` 弹窗**只读**,`ShopeeSave` 仍是 501。不放一个点了没反应的保存按钮。
复用 #18 的弹窗机制(`data-detail-url` / `data-detail-slot` / `data-detail-id`),
`app.js` **未改动**。
## 与建单方案的差异
1. **详情路由用 `?id=` 而不是工单写的 `?goods_id=`。** `app.js` 里
`fetch(base + "?id=" + ...)` 的参数名是硬编码的,而「不改 `app.js`」是
更高优先级的约束。与 PDD 页的 `/pdd/detail?id=` 也保持了一致。
2. 新增 `admin/service/shopee_list_test.go`(工单预计文件表未列)。
## 改了哪些
- `admin/repository/shopee.go`:`ListShopeeProducts` 商品级聚合查询、
`GetShopeeProductByGoodsID`、`GetShopeeCollectStatus`、
`ListShopeeSKUsByGoodsID`;删除不再使用的 SKU 级查询。
- `admin/service/shopee_list.go`:视图改商品级,新增弹窗用的 `ShopeeProductDetail`。
- `admin/service/shopee_list_test.go`:新建。
- `admin/handler/web/shopee.go`:`ShopeeList` 改写;新增只读 `ShopeeDetail`。
- `admin/handler/web/web.go`:`GET /shopee/detail` 路由。
- `admin/templates/shopee/list.html`:列重写、双击绑定、弹窗壳子。
- `admin/templates/shopee/detail_modal.html`:新建。
- `admin/static/css/app.css`:`.col-title`。
## 验收结果
架构角色独立复跑,用真实样本导入后逐条核对:
| 检查 | 实测结果 |
|---|---|
| 总行数 | `共 5195 个商品` |
| `24420648774` | **1 行**(原 62 行),颜色10 / 尺码8 / SKU**62** / 待补0 |
| `26886533818` | 颜色**15** / 尺码**5** / SKU**28**(不是 75) |
| **`28431952912`(部分失败)** | 颜色4 / 尺码5 / SKU24 / 待补**4**,**整行标黄** |
| `24023581128`(全部失败) | 颜色0 / 尺码0 / SKU1 / 待补1,整行标黄 |
| 弹窗显示原文 | `原文:面膜安全褲3條膚色,【2xl 70-85公斤可穿】` |
| PDD 链接为空 | 显示「未填写」并标红 |
| `app.js` / `shopee_import.go` | 均未改动 |
| `ShopeeSave` / `Delete` / `Collect` | 仍是 501(3 处) |
| 五个页面 | 全部 200 |
`28431952912` 那条是最危险的场景——「部分失败」,颜色尺码数字看着完全正常
(4 和 5),但里面有 4 个 SKU 解析失败。标黄之后藏不住了。
## 测试
架构角色亲自执行,**用 `GOTOOLCHAIN=go1.23.0` 固定工具链**:
```
GOTOOLCHAIN=go1.23.0 go vet ./... 无输出
GOTOOLCHAIN=go1.23.0 gofmt -l . 无输出
GOTOOLCHAIN=go1.23.0 go test ./... -count=1
ok cmautobuy/admin 0.049s
ok cmautobuy/admin/repository 0.753s
ok cmautobuy/admin/service 2.081s
```
### 变异测试(工单未要求,架构角色补做)
| 变异 | 结果 |
|---|---|
| 颜色/尺码数不再过滤 `parse_ok = 1` | 4 个用例变红 |
| 待补数恒为 0(标黄失效) | 4 个用例变红 |
这两条正是本工单加进去防信息丢失的,现在有测试守着。
**未验证到的部分:**
- **浏览器里的真实交互**:双击开弹窗只验证了服务端 HTML 和 `/shopee/detail`
的返回内容,**没在真实浏览器里点过**。
- **1366×768 下的表格横向滚动**未做视觉走查。
- **`max-width` 用百分比作用在 `<td>` 上,浏览器行为不完全一致**——
部分浏览器对 `table-cell` 的 `max-width` 处理比较随意。若实机看下来
宽度完全没变化,需改成固定像素(`.truncate` 用的 `max-width: 280px`
那个路子是确定可行的)。
用户已实机确认并验收通过。
## 追加微调
用户看过实际渲染后要求商品名称列「缩小到现在的 60%」,
`max-width` 从 **30% → 18%**(提交 `ccc146c`)。
理由写进 CSS 注释:蝦皮标题普遍很长(实测最长 60+ 字,全是关键词堆砌),
不收窄的话这一列会把后面的颜色/尺码/SKU/待补几个数字挤出屏幕——
而那几个数字才是这个页面要看的东西。完整标题靠悬停的 `title` 属性看。
数值只写在 `app.css` 一处,模板注释不再重复具体百分比,
免得下次改了数值忘了同步。
## 遗留问题
1. `ShopeeSave` / `ShopeeDelete` / `ShopeeCollect` 仍是 501,属后续工单。
2. 手动新增 SKU(`05` §4.4)未做。蝦皮报表只含有销售成绩的 SKU,
导入进来的数据本身就是不全的。
3. 浏览器实机交互与列宽百分比的实际效果需人工确认。
## 相关提交
- `64d5e74` feat: 蝦皮数据页改为商品级列表与规格弹窗 (#41)
- `ccc146c` style: 蝦皮商品名称列再收窄到 18% (#41)