feat: PDD 商品页面 (#18)
打通 Client↔Admin 闭环的一环:录入 PDD 链接 → 创建采集任务 → 客户端领走去采 → 规格和价格显示在页面上。#16 写的 MarkCollecting 和 SoftDeletePddProduct 至此才有生产调用方。 链接解析严格、不做容错兜底:goods_id 上有 UNIQUE 约束,防重全靠它。 猜一个的话同一商品会存成好几行、采好几遍,规格映射还说不清指向哪一行。 短链一律拒绝,卡域名是为了拦"粘了淘宝链接"这种失误。 创建采集任务先占状态再建任务:MarkCollecting 只在 pending/failed 时成功, 同时充当"有没有人已经在采"的判断,与建任务在同一事务里, 所以并发点多次只会建出一个任务(实测 4 并发 → 1 条)。 submit.go 的 collectedData 增加 Dimensions —— 没有它就只能按 Go 的 map 遍历,而 map 无序,同一商品每次刷新"颜色/尺码"的先后都可能变。 顺带修 #16 一处缺陷:EnsurePddProduct 复活分支清空了 skus_json 却漏了 title,导致复活后状态显示"未采集"但标题还留着旧值。 审查打回一次:清理"PDD 链接唯一的录入口"这一过期说法(全库 5 处), 以及 shopee.go 里"空 → no_link"的过期 TODO —— no_link 已在 #16 从 CHECK 约束删除,照写会直接撞约束。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -26,9 +26,9 @@ type Handler struct {
|
||||
onlineThreshold time.Duration
|
||||
}
|
||||
|
||||
// Register 把四个模块的页面路由挂上去。
|
||||
// Register 把五个模块的页面路由挂上去。
|
||||
//
|
||||
// 四个模块的页面结构完全一致(顶部工具条 / 中间带勾选的表格 / 底部状态条),
|
||||
// 五个模块的页面结构完全一致(顶部工具条 / 中间带勾选的表格 / 底部状态条),
|
||||
// 这是有意的,见 docs/admin/05-ui-specification.md §2。
|
||||
func Register(r *gin.Engine, db *sql.DB, onlineThreshold time.Duration) {
|
||||
h := &Handler{db: db, onlineThreshold: onlineThreshold}
|
||||
@@ -49,18 +49,26 @@ func Register(r *gin.Engine, db *sql.DB, onlineThreshold time.Duration) {
|
||||
pages.POST("/shopee/delete", h.ShopeeDelete)
|
||||
pages.POST("/shopee/collect", h.ShopeeCollect)
|
||||
|
||||
// 2. 顺运宝数据
|
||||
// 2. PDD 商品
|
||||
pages.GET("/pdd", h.PddList)
|
||||
pages.GET("/pdd/detail", h.PddDetail) // 双击行时前端来取弹窗内容
|
||||
pages.POST("/pdd/create", h.PddCreate)
|
||||
pages.POST("/pdd/save", h.PddSave)
|
||||
pages.POST("/pdd/collect", h.PddCollect)
|
||||
pages.POST("/pdd/delete", h.PddDelete)
|
||||
|
||||
// 3. 顺运宝数据
|
||||
pages.GET("/syb", h.SybList)
|
||||
pages.POST("/syb/sync", h.SybSync)
|
||||
pages.POST("/syb/match", h.SybMatch)
|
||||
pages.POST("/syb/create-task", h.SybCreateTask)
|
||||
pages.POST("/syb/delete", h.SybDelete)
|
||||
|
||||
// 3. 采购任务
|
||||
// 4. 采购任务
|
||||
pages.GET("/tasks", h.TaskList)
|
||||
pages.POST("/tasks/delete", h.TaskDelete)
|
||||
|
||||
// 4. 客户端列表
|
||||
// 5. 客户端列表
|
||||
pages.GET("/clients", h.ClientList)
|
||||
pages.POST("/clients/delete", h.ClientDelete)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user