fix: 统一顺运宝单条采集客户端选择 (#174)
This commit is contained in:
@@ -207,8 +207,13 @@ func (h *Handler) SybDetail(c *gin.Context) {
|
||||
fail(c, http.StatusNotFound, "顺运宝货运单明细不存在。")
|
||||
return
|
||||
}
|
||||
assignableClients, err := service.ListAssignableClients(h.db, currentUser(c), h.onlineThreshold)
|
||||
if err != nil {
|
||||
fail(c, http.StatusInternalServerError, "读取可分配客户端失败,数据没有被改动。")
|
||||
return
|
||||
}
|
||||
c.HTML(http.StatusOK, "syb/detail_modal", gin.H{
|
||||
"D": detail, "CSRFToken": csrfToken(c),
|
||||
"D": detail, "CSRFToken": csrfToken(c), "AssignableClients": assignableClients,
|
||||
"Keyword": c.Query("order_no"), "ShopFilter": c.Query("shop"), "StageFilter": c.Query("stage"),
|
||||
"CurrentPage": service.ParsePage(c.Query("page")),
|
||||
})
|
||||
@@ -603,7 +608,8 @@ func (h *Handler) SybAssociatePdd(c *gin.Context) {
|
||||
|
||||
// SybCollectPdd 为货运单当前关联的 PDD 商品创建采集任务。
|
||||
func (h *Handler) SybCollectPdd(c *gin.Context) {
|
||||
result, err := service.CreateSybPddCollectTaskForUser(h.db, currentUser(c), c.PostForm("syb_id"))
|
||||
result, err := service.CreateSybPddCollectTasksForUser(
|
||||
h.db, currentUser(c), []string{c.PostForm("syb_id")}, c.PostForm("client_id"))
|
||||
if err != nil {
|
||||
h.sybRedirect(c, "采集任务未创建:"+err.Error())
|
||||
return
|
||||
|
||||
@@ -143,6 +143,15 @@ func TestCreateSybPddCollectTasksForUser_同一PDD商品去重(t *testing.T) {
|
||||
if err := db.QueryRow(`SELECT COUNT(*) FROM tasks WHERE task_type='collect'`).Scan(&taskCount); err != nil || taskCount != 1 {
|
||||
t.Fatalf("同一 PDD 商品应只建一条任务,count=%d err=%v", taskCount, err)
|
||||
}
|
||||
var status model.TaskStatus
|
||||
var assignedClient sql.NullString
|
||||
if err := db.QueryRow(`SELECT status,assigned_client FROM tasks WHERE task_type='collect'`).
|
||||
Scan(&status, &assignedClient); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if status != model.TaskPending || assignedClient.Valid {
|
||||
t.Fatalf("不指定客户端时应为无主待领,status=%q client=%+v", status, assignedClient)
|
||||
}
|
||||
var sourceCount int
|
||||
if err := db.QueryRow(`SELECT COUNT(*) FROM task_syb_sources`).Scan(&sourceCount); err != nil || sourceCount != 2 {
|
||||
t.Fatalf("去重任务应保留两条顺运宝来源,count=%d err=%v", sourceCount, err)
|
||||
@@ -158,6 +167,34 @@ func TestCreateSybPddCollectTasksForUser_同一PDD商品去重(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateSybPddCollectTasksForUser_指定可见客户端(t *testing.T) {
|
||||
db := newTestDB(t)
|
||||
admin, _, _ := insertTaskUsers(t, db)
|
||||
if err := RegisterClient(db, model.Client{ClientID: "client-chosen", Name: "仓库手机"}, true); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
seedShopeeProduct(t, db, "1001", "商品一")
|
||||
if _, err := AssociateShopeePdd(db, "1001", pddURLA, false); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
seedSybCollectOrder(t, db, "SYB-CHOSEN", "1001")
|
||||
|
||||
result, err := CreateSybPddCollectTasksForUser(
|
||||
db, admin, []string{"SYB-CHOSEN"}, "client-chosen")
|
||||
if err != nil || result.Created != 1 {
|
||||
t.Fatalf("指定客户端创建结果=%+v err=%v", result, err)
|
||||
}
|
||||
var status model.TaskStatus
|
||||
var assignedClient string
|
||||
if err := db.QueryRow(`SELECT status,assigned_client FROM tasks WHERE task_type='collect' AND pdd_goods_id='737116531267'`).
|
||||
Scan(&status, &assignedClient); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if status != model.TaskAssigned || assignedClient != "client-chosen" {
|
||||
t.Fatalf("指定客户端任务状态=%q client=%q", status, assignedClient)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateSybPddCollectTasksForUser_无任务的采集中状态可恢复(t *testing.T) {
|
||||
db := newTestDB(t)
|
||||
admin, _, _ := insertTaskUsers(t, db)
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"cmautobuy/admin/model"
|
||||
"cmautobuy/admin/service"
|
||||
)
|
||||
|
||||
@@ -87,3 +88,37 @@ func TestSybListTemplate_区分标题图片与阶段动作(t *testing.T) {
|
||||
t.Error("顺运宝列表不应继续使用含义模糊的整行双击入口")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSybDetailTemplate_单条采集可选执行客户端(t *testing.T) {
|
||||
tmpl, err := template.ParseFS(templateFS, "templates/*/*.html")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
data := map[string]any{
|
||||
"D": &service.SybProcessingDetail{
|
||||
SybID: "SYB-1", OrderNo: "ORDER-1", Title: "待采集商品",
|
||||
PddGoodsID: "737116531267", CanCollect: true,
|
||||
},
|
||||
"CSRFToken": "test-csrf",
|
||||
"AssignableClients": []service.ClientView{{
|
||||
Client: model.Client{ClientID: "CLIENT-1", Name: "仓库手机"}, Status: "在线",
|
||||
}},
|
||||
}
|
||||
var output bytes.Buffer
|
||||
if err := tmpl.ExecuteTemplate(&output, "syb/detail_modal", data); err != nil {
|
||||
t.Fatalf("渲染顺运宝详情失败: %v", err)
|
||||
}
|
||||
body := output.String()
|
||||
for _, want := range []string{
|
||||
`action="/syb/collect-pdd"`,
|
||||
`label for="syb-detail-collect-client"`,
|
||||
`select id="syb-detail-collect-client" name="client_id"`,
|
||||
`option value="">不指定(任意客户端可领取)`,
|
||||
`option value="CLIENT-1">仓库手机(CLIENT-1,在线)`,
|
||||
`指定后任务只等待该客户端领取`,
|
||||
} {
|
||||
if !strings.Contains(body, want) {
|
||||
t.Errorf("顺运宝详情缺少 %q", want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
</form>
|
||||
|
||||
{{if .PddGoodsID}}
|
||||
<form method="post" action="/syb/collect-pdd" class="inline">
|
||||
<form method="post" action="/syb/collect-pdd" class="form-stack">
|
||||
<input type="hidden" name="csrf_token" value="{{$.CSRFToken}}">
|
||||
<input type="hidden" name="syb_id" value="{{.SybID}}">
|
||||
<input type="hidden" name="order_no" value="{{$.Keyword}}">
|
||||
@@ -47,7 +47,17 @@
|
||||
<input type="hidden" name="stage" value="{{$.StageFilter}}">
|
||||
<input type="hidden" name="page" value="{{$.CurrentPage}}">
|
||||
{{if .CanCollect}}
|
||||
<button type="submit">{{if or (eq .CollectStatus "failed") (eq .Stage "pdd_collecting_stale")}}重新创建采集任务{{else}}创建采集任务{{end}}</button>
|
||||
<div class="field">
|
||||
<label for="syb-detail-collect-client">执行客户端</label>
|
||||
<select id="syb-detail-collect-client" name="client_id">
|
||||
<option value="">不指定(任意客户端可领取)</option>
|
||||
{{range $.AssignableClients}}
|
||||
<option value="{{.ClientID}}">{{.Name}}({{.ClientID}},{{.Status}})</option>
|
||||
{{end}}
|
||||
</select>
|
||||
<small>通常保持不指定即可;指定后任务只等待该客户端领取。</small>
|
||||
</div>
|
||||
<div><button type="submit">{{if or (eq .CollectStatus "failed") (eq .Stage "pdd_collecting_stale")}}重新创建采集任务{{else}}创建采集任务{{end}}</button></div>
|
||||
{{else}}
|
||||
<span class="hint">{{if eq .CollectStatus "collecting"}}采集任务正在执行,请稍后刷新。{{else}}PDD 数据已采集,下一步匹配采购规格。{{end}}</span>
|
||||
{{end}}
|
||||
|
||||
@@ -561,6 +561,12 @@ PDD 采集中(超时)行可用于
|
||||
标准商品链接并按 `goods_id` 复用已有档案;换成其他商品需要明确确认。待采集或采集失败时显示
|
||||
“创建采集任务”或“重新创建采集任务”,采集中和已采集状态只显示说明。
|
||||
|
||||
单条创建和重新创建采集任务时,按钮上方显示有可见标签的“执行客户端”
|
||||
下拉框,只列出当前账号可见的 Client,并显示名称、Client ID 和在线状态。
|
||||
默认为“不指定(任意客户端可领取)”;指定后只等待该 Client 领取。持续
|
||||
帮助文字必须说清两种选择的后果,不依赖 placeholder 或颜色。该入口与列表
|
||||
顶部批量创建共用同一套服务端阶段、客户端可见范围和重复任务校验。
|
||||
|
||||
```text
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ 规格匹配 · 订单 SO-20260806-001 │
|
||||
|
||||
Reference in New Issue
Block a user