Files
cmautobuy/admin/templates/pdd/edit_modal.html
T
chengmaandClaude Opus 5 eb8d357f5a 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>
2026-08-07 11:27:06 +08:00

93 lines
3.5 KiB
HTML
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.
{{define "pdd/edit_modal"}}
{{/* 双击一行时弹出的内容。
这是一个**片段**,不是整页——外面的弹窗壳子在 pdd/list.html 里。
规格表由服务端渲染是有意的:维度顺序、价格格式、price_cent 为 null
的处理都是业务规则,放到前端去拼就没人维护得住了。 */}}
{{with .D}}
<div class="modal-head">
<h2>PDD 商品 {{.GoodsID}}</h2>
<button type="button" class="modal-x" data-modal-close aria-label="关闭">×</button>
</div>
{{/* 「重新采集」自己一个表单,只提交这一个商品。
HTML 不允许表单套表单,所以它写在保存表单外面,
按钮靠 form="pdd-recollect-form" 挂过来。 */}}
<form id="pdd-recollect-form" method="post" action="/pdd/collect" hidden>
<input type="hidden" name="csrf_token" value="{{$.CSRFToken}}">
<input type="hidden" name="ids" value="{{.GoodsID}}">
</form>
<form method="post" action="/pdd/save">
<input type="hidden" name="csrf_token" value="{{$.CSRFToken}}">
<input type="hidden" name="id" value="{{.ID}}">
<div class="modal-body">
<dl class="detail">
<dt>商品 ID</dt><dd>{{.GoodsID}}<small>(只读,由链接解析得出,不能改)</small></dd>
<dt><label for="detail-url">PDD 链接</label></dt>
<dd><input id="detail-url" type="text" name="url" value="{{.URL}}"
autocomplete="off" class="wide"></dd>
<dt>标题</dt><dd>{{.Title}}<small>(只读,采集后自动回填)</small></dd>
<dt>采集状态</dt><dd>{{.StatusText}}</dd>
<dt>失败原因</dt><dd>{{.CollectMsg}}</dd>
<dt>采集时间</dt><dd>{{.CollectedAt}}</dd>
{{if .ArtifactRef}}
{{/* 诊断产物只报位置、不上传文件:告诉操作员去哪台机器的哪个目录捞截图 */}}
<dt>诊断产物</dt><dd><code>{{.ArtifactRef}}</code></dd>
{{end}}
</dl>
<h3>规格{{if .Collected}}({{len .SKUs}} 个){{end}}</h3>
{{if .SkusError}}
<p class="missing">{{.SkusError}}</p>
{{else if not .Collected}}
<p class="hint">
尚未采集。关掉这个弹窗,勾选这一行再点「创建采集任务」,
等客户端领走执行完,规格和价格就会出现在这里。
</p>
{{else if not .SKUs}}
<p class="missing">
采集完成但一个规格都没有。这通常说明商品已下架,或者采集时没点开规格面板——
建议重新采集一次。
</p>
{{else}}
<div class="table-wrap">
<table>
<thead>
<tr>
{{/* 列顺序按采集结果里的 dimensions 定,不是 Go map 的随机顺序 */}}
{{range .DimensionNames}}<th>{{.}}</th>{{end}}
<th>价格</th>
<th>有货</th>
</tr>
</thead>
<tbody>
{{range .SKUs}}
<tr>
{{range .Options}}<td>{{.}}</td>{{end}}
{{/* 价格底层存的是整数分。采不到价格显示「未采到」,
绝不显示 ¥0.00——那会让人以为是白菜价 */}}
<td>{{.PriceText}}</td>
<td>{{.Available}}</td>
</tr>
{{end}}
</tbody>
</table>
</div>
{{end}}
</div>
<div class="modal-foot">
<button type="submit" form="pdd-recollect-form">重新采集</button>
<span class="grow"></span>
<button type="button" data-modal-close>取消</button>
<button type="submit" class="primary">保存</button>
</div>
</form>
{{end}}
{{end}}