[注意]
实测导入真实样本后打开 /shopee:
/shopee
HTML 大小 3.4 MB 表格行数 5195
商品总数 5195 未填 PDD 链接 5195 (100%) 有待补规格 6
要找出那 6 个待补的商品,得翻 260 页。
现在页面上只有「商品 ID 搜索」——得先知道 ID 才能搜。但「哪些商品需要我处理」 这个问题,恰恰是不知道 ID 的时候才要问的。
只做分页,情况会从「5195 行糊在一起」变成「260 页里藏着 6 个」,两种都找不到。
PDD 商品页(05 §5.1)已经踩过这个坑,那里写着:
05
[必须] 这个筛选是刚需,不是锦上添花:这个页面的主要用途是维护 (找出失败的重采、找出还没采的),只按 ID 搜的话要翻页去找。
[必须]
蝦皮页是同样的性质。
做:
docs/admin/05
不做(各自独立工单):
ShopeeSave
ShopeeDelete
ShopeeCollect
[必须] 每页 20 条。docs/admin/05 §3 现在写的是 [建议] 一页 50 条, 要改成 20 并写清理由:20 行在 1366×768 上正好一屏不用滚动。
[建议]
不改规范的话,下一个人做顺运宝页会照着 50 做,五个页面又不一致。
[必须] LIMIT ? OFFSET ?,不得把 5195 行查出来再在 Go 里切片。 这正是现在 3.4MB 的成因。
LIMIT ? OFFSET ?
[必须] 总数用单独的 COUNT(*) 查询,和列表查询共用同一套筛选条件 (抽成共用函数)。分开写两份 WHERE,迟早有一天会忘了给 COUNT 也加条件, 页码算错而且没人发现。这条 #19 已经踩过一次。
COUNT(*)
✗ 共 20 个商品 ← 只数了本页,操作员以为总共就 20 个 ✓ 共 5195 个商品 · 第 1/260 页
[必须] 筛选后显示筛选结果的总数:
待补规格:6 个商品 · 第 1/1 页
不是本页的 6。这与 #19 的「统计跟随筛选」是同一条规则。
parse_ok = 0
EXISTS (SELECT 1 FROM shopee_skus s WHERE s.goods_id = p.goods_id AND s.parse_ok = 0)
pdd_goods_url IS NULL OR pdd_goods_url = ''
pdd_goods_url IS NOT NULL AND pdd_goods_url <> ''
[必须] 「待补规格」用 EXISTS,不要用 JOIN + DISTINCT—— 一个商品有多个失败 SKU 时 JOIN 会出重复行,DISTINCT 又会让 LIMIT/OFFSET 的行为变得难推理。
EXISTS
JOIN
DISTINCT
LIMIT/OFFSET
[必须] 筛选参数认不出来的一律当「全部」,不要报错。 用户手改 URL 或者旧书签不该把页面搞崩。
[必须] ?page=N,从 1 开始(不是 0)。给操作员看的东西不要 0-based。
?page=N
[必须] 越界要兜住:
page < 1
page > 总页数
第 1/1 页
第 1/0 页
[必须] 翻页时保留当前筛选和关键词。丢了的话操作员翻到第二页 筛选就没了,还以为数据变了。
共 5195 个商品 · 第 3/260 页 [首页] [上一页] [下一页] [末页]
[必须] 用 <a href> 链接,不要用 JS。这是纯 GET 导航, 浏览器的前进后退和书签都该正常工作。
<a href>
[必须] 第一页时「首页 / 上一页」禁用,最后一页时「下一页 / 末页」禁用。 禁用要用视觉 + 语义(不可点的元素不要还是 <a>),不能只靠颜色。
<a>
[建议] 不要做 1 2 3 ... 260 这种页码列表。260 页列出来没有意义, 操作员靠筛选定位而不是靠翻页。
1 2 3 ... 260
admin/repository/shopee.go
ListShopeeProducts
CountShopeeProductsFiltered
admin/service/shopee_list.go
admin/handler/web/shopee.go
page
status
admin/templates/shopee/list.html
admin/static/css/app.css
docs/admin/05-ui-specification.md
docs/admin/01-requirements.md
[必须] 分页规则写成 §3 下的通用小节(像 §3.1 搜索框宽度那样), 不要写在蝦皮页那一节里——后面四个页面都要照抄,写在某一页下面别人看不到。 这个错误 #34 刚犯过一次。
分页
page=0
page=abc
page=9999
筛选
状态条
其他
shopee_import.go
GOTOOLCHAIN=go1.23.0
go vet
gofmt -l .
go test ./...
cd D:\chengma\cmautobuy\admin $env:GOTOOLCHAIN="go1.23.0" go vet ./...; gofmt -l .; go test ./... -count=1 Remove-Item Env:GOTOOLCHAIN go run .
导入真实样本后:
共 5195 个商品 · 第 1/260 页
/shopee?page=9999
/shopee?page=abc
/shopee?status=pending_spec
/shopee?status=no_link
UPDATE shopee_products SET pdd_goods_url='https://x/1' WHERE goods_id='<任选>'
status=has_link
[必须] 第 1、2、4 步的实际输出要贴出来,以及 HTML 大小的前后对比。
回退:git revert。纯展示层改动,不影响已导入的数据。
git revert
用户实机确认通过。归档状态已更新(6d40c1e)。
6d40c1e
edfe39c
docs/task/43-admin-蝦皮数据页分页与状态筛选.md
另外四个页面(PDD / 顺运宝 / 采集采购 / 客户端)尚未接入分页。通用逻辑已放 service/pagination.go,规则已写进 05 §3.2,后续各自开工单接入即可。
service/pagination.go
No dependencies set.
The note is not visible to the blocked user.
基本信息
[注意]全项目第一个做分页的页面,本工单定下的模式后面四个页面要照抄要解决什么
① 一次吐 3.4MB
实测导入真实样本后打开
/shopee:② 但只加分页会制造一个新问题
要找出那 6 个待补的商品,得翻 260 页。
现在页面上只有「商品 ID 搜索」——得先知道 ID 才能搜。但「哪些商品需要我处理」
这个问题,恰恰是不知道 ID 的时候才要问的。
只做分页,情况会从「5195 行糊在一起」变成「260 页里藏着 6 个」,两种都找不到。
PDD 商品页(
05§5.1)已经踩过这个坑,那里写着:蝦皮页是同样的性质。
做什么 / 不做什么
做:
docs/admin/05§3 的每页条数(现在写的是 50)不做(各自独立工单):
ShopeeSave/ShopeeDelete/ShopeeCollect(保持 501)怎么做
每页 20 条,规范要一起改
[必须]每页 20 条。docs/admin/05§3 现在写的是[建议]一页 50 条,要改成 20 并写清理由:20 行在 1366×768 上正好一屏不用滚动。
不改规范的话,下一个人做顺运宝页会照着 50 做,五个页面又不一致。
分页必须在数据库做,不在内存里切
[必须]LIMIT ? OFFSET ?,不得把 5195 行查出来再在 Go 里切片。这正是现在 3.4MB 的成因。
[必须]总数用单独的COUNT(*)查询,和列表查询共用同一套筛选条件(抽成共用函数)。分开写两份 WHERE,迟早有一天会忘了给 COUNT 也加条件,
页码算错而且没人发现。这条 #19 已经踩过一次。
状态条必须显示全量,不是本页
[必须][必须]筛选后显示筛选结果的总数:不是本页的 6。这与 #19 的「统计跟随筛选」是同一条规则。
状态筛选的四个取值
parse_ok = 0的 SKUEXISTS (SELECT 1 FROM shopee_skus s WHERE s.goods_id = p.goods_id AND s.parse_ok = 0)pdd_goods_url IS NULL OR pdd_goods_url = ''pdd_goods_url IS NOT NULL AND pdd_goods_url <> ''[必须]「待补规格」用EXISTS,不要用JOIN+DISTINCT——一个商品有多个失败 SKU 时 JOIN 会出重复行,
DISTINCT又会让LIMIT/OFFSET的行为变得难推理。[必须]筛选参数认不出来的一律当「全部」,不要报错。用户手改 URL 或者旧书签不该把页面搞崩。
页码参数
[必须]?page=N,从 1 开始(不是 0)。给操作员看的东西不要 0-based。[必须]越界要兜住:page < 1或非数字 → 当作 1page > 总页数→ 显示最后一页,不要显示空表格第 1/1 页,不要出现第 1/0 页[必须]翻页时保留当前筛选和关键词。丢了的话操作员翻到第二页筛选就没了,还以为数据变了。
分页控件
[必须]用<a href>链接,不要用 JS。这是纯 GET 导航,浏览器的前进后退和书签都该正常工作。
[必须]第一页时「首页 / 上一页」禁用,最后一页时「下一页 / 末页」禁用。禁用要用视觉 + 语义(不可点的元素不要还是
<a>),不能只靠颜色。[建议]不要做1 2 3 ... 260这种页码列表。260 页列出来没有意义,操作员靠筛选定位而不是靠翻页。
预计修改文件
admin/repository/shopee.goListShopeeProducts加LIMIT/OFFSET;CountShopeeProductsFilteredadmin/service/shopee_list.goadmin/handler/web/shopee.gopage/status参数admin/templates/shopee/list.htmladmin/static/css/app.cssdocs/admin/05-ui-specification.mddocs/admin/01-requirements.md[必须]分页规则写成 §3 下的通用小节(像 §3.1 搜索框宽度那样),不要写在蝦皮页那一节里——后面四个页面都要照抄,写在某一页下面别人看不到。
这个错误 #34 刚犯过一次。
验收标准
分页
LIMIT/OFFSET在 SQL 里,不是查全量再切片page=0/page=abc/ 负数 → 当作第 1 页,不报错page=9999→ 显示最后一页,不是空表格<a href>,浏览器后退可用筛选
状态条
第 1/1 页,不出现第 1/0 页其他
ShopeeSave/ShopeeDelete/ShopeeCollect仍是 501shopee_import.go未改动05§3 的通用小节,不是蝦皮页那一节05§3 的每页条数已从 50 改为 20 并写清理由GOTOOLCHAIN=go1.23.0下go vet/gofmt -l ./go test ./...全过怎么验证
导入真实样本后:
/shopee→ 20 行,状态条共 5195 个商品 · 第 1/260 页/shopee?page=9999→ 最后一页,有数据/shopee?page=abc→ 第 1 页/shopee?status=pending_spec→ 6 个商品,状态条显示 6 不是 20/shopee?status=no_link→ 5195 个UPDATE shopee_products SET pdd_goods_url='https://x/1' WHERE goods_id='<任选>'→
status=has_link筛出 1 个[必须]第 1、2、4 步的实际输出要贴出来,以及 HTML 大小的前后对比。风险和回退
page越界显示空表格,操作员以为数据没了回退:
git revert。纯展示层改动,不影响已导入的数据。验收通过,关闭
用户实机确认通过。归档状态已更新(
6d40c1e)。edfe39cdocs/task/43-admin-蝦皮数据页分页与状态筛选.md遗留
另外四个页面(PDD / 顺运宝 / 采集采购 / 客户端)尚未接入分页。通用逻辑已放
service/pagination.go,规则已写进05§3.2,后续各自开工单接入即可。