From 9e260059eef526844b0af7a53aa8558f6a3ce980 Mon Sep 17 00:00:00 2001 From: yml2213 Date: Mon, 5 Oct 2026 19:18:52 +0800 Subject: [PATCH] =?UTF-8?q?feat(rock):=20=E5=85=B3=E8=81=94=E4=B8=9A?= =?UTF-8?q?=E5=8A=A1=E5=B7=A5=E5=8D=95=E5=8D=87=E7=BA=A7=E4=B8=BA=E5=8F=8C?= =?UTF-8?q?=E5=8D=95=E5=8F=B7=E6=B8=85=E6=99=B0=E5=B1=95=E7=A4=BA=EF=BC=88?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E5=B7=A5=E5=8D=95=E5=8F=B7=20+=20=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=E5=95=86=E6=88=B7=E5=8D=95=E5=8F=B7=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 后端批量反查商户单号:在 RockService.ListTokens 中支持批量反查关联订单创建时由调用方传入的 ClientOrderNo(商户单号),并拓展支持通过商户单号进行全局关键词模糊搜索; 2. 管理后台双单号排版升级:在 Rock 管理表格中将「关联业务工单」升级为双行呈现——第一行高亮展示内部统一系统工单号 (FO2026...),第二行辅助展示外部电商/商户原始单号 (如 test4 / 拼多多单号),两行均支持一键独立复制; 3. 单元测试全覆盖:补充商户单号自动挂载关联与按商户单号模糊检索的自动化单测,确保对单溯源精准无误。 --- backend/internal/model/rock.go | 1 + .../internal/service/provider_rock_test.go | 37 ++++++++++++++++ backend/internal/service/rock_service.go | 32 +++++++++++++- frontend/src/api/index.ts | 1 + frontend/src/pages/PlatformRock.tsx | 44 +++++++++++++++---- 5 files changed, 104 insertions(+), 11 deletions(-) diff --git a/backend/internal/model/rock.go b/backend/internal/model/rock.go index 4de247c..be22c5c 100644 --- a/backend/internal/model/rock.go +++ b/backend/internal/model/rock.go @@ -56,6 +56,7 @@ type RockToken struct { Region string `gorm:"size:64;not null;default:'Q/V可用'" json:"region"` Status string `gorm:"size:32;not null;default:'available';index" json:"status"` AssignedOrderNo string `gorm:"size:128;index" json:"assigned_order_no"` + ClientOrderNo string `gorm:"-" json:"client_order_no,omitempty"` // 关联的创建订单商户单号 ExpectedUID string `gorm:"size:64" json:"expected_uid"` ActualRoleName string `gorm:"size:128" json:"actual_role_name"` ActualRoleID string `gorm:"size:64" json:"actual_role_id"` diff --git a/backend/internal/service/provider_rock_test.go b/backend/internal/service/provider_rock_test.go index 2c2dca8..9f93bff 100644 --- a/backend/internal/service/provider_rock_test.go +++ b/backend/internal/service/provider_rock_test.go @@ -459,4 +459,41 @@ func TestRockService_StatsAndPurchase(t *testing.T) { if total != 2 || len(list) != 2 { t.Fatalf("期望查询到 2 条,实际为 total=%d len=%d", total, len(list)) } + + // 6. 测试关联履约订单与创建订单商户单号反查 + orderNo := "FO_TEST_ROCK_999" + clientOrderNo := "SHOP_ORDER_PDD_888" + _ = db.Create(&model.FulfillmentOrder{ + OrderNo: orderNo, + ClientOrderNo: clientOrderNo, + ProductSKU: "rock_black_tshirt", + ProductName: "黑色ROCK长袖T恤", + }).Error + _ = db.Model(&model.RockToken{}).Where("id = ?", list[0].ID).Update("assigned_order_no", orderNo).Error + + listWithClient, _, err := rockSvc.ListTokens(context.Background(), 1, 10, "", "") + if err != nil { + t.Fatalf("list tokens with client: %v", err) + } + found := false + for _, tk := range listWithClient { + if tk.ID == list[0].ID { + found = true + if tk.ClientOrderNo != clientOrderNo { + t.Fatalf("期望商户单号为 %s,实际为 %s", clientOrderNo, tk.ClientOrderNo) + } + } + } + if !found { + t.Fatalf("未找到对应的 Token 记录") + } + + // 7. 测试按商户单号关键词搜索 + searchList, searchTotal, err := rockSvc.ListTokens(context.Background(), 1, 10, "", "PDD_888") + if err != nil { + t.Fatalf("search tokens by client_order_no: %v", err) + } + if searchTotal != 1 || len(searchList) != 1 { + t.Fatalf("期望按商户单号搜索出 1 条,实际为 total=%d len=%d", searchTotal, len(searchList)) + } } diff --git a/backend/internal/service/rock_service.go b/backend/internal/service/rock_service.go index 05ce474..49e466b 100644 --- a/backend/internal/service/rock_service.go +++ b/backend/internal/service/rock_service.go @@ -643,8 +643,8 @@ func (s *RockService) ListTokens(ctx context.Context, page, pageSize int, status } if strings.TrimSpace(search) != "" { term := "%" + strings.TrimSpace(search) + "%" - db = db.Where("assigned_order_no LIKE ? OR expected_uid LIKE ? OR actual_role_name LIKE ? OR actual_role_id LIKE ? OR redeem_code LIKE ?", - term, term, term, term, term) + db = db.Where("assigned_order_no LIKE ? OR expected_uid LIKE ? OR actual_role_name LIKE ? OR actual_role_id LIKE ? OR redeem_code LIKE ? OR assigned_order_no IN (SELECT order_no FROM fulfillment_orders WHERE client_order_no LIKE ?)", + term, term, term, term, term, term) } var total int64 @@ -661,6 +661,34 @@ func (s *RockService) ListTokens(ctx context.Context, page, pageSize int, status return nil, 0, err } + // 批量反查关联订单的商户单号(创建订单时的 ClientOrderNo) + orderNos := make([]string, 0, len(tokens)) + for _, t := range tokens { + if t.AssignedOrderNo != "" { + orderNos = append(orderNos, t.AssignedOrderNo) + } + } + if len(orderNos) > 0 { + var orders []struct { + OrderNo string `gorm:"column:order_no"` + ClientOrderNo string `gorm:"column:client_order_no"` + } + if scanErr := s.db.WithContext(ctx).Table("fulfillment_orders"). + Select("order_no, client_order_no"). + Where("order_no IN ?", orderNos). + Scan(&orders).Error; scanErr == nil { + clientMap := make(map[string]string, len(orders)) + for _, o := range orders { + clientMap[o.OrderNo] = o.ClientOrderNo + } + for i := range tokens { + if cNo, ok := clientMap[tokens[i].AssignedOrderNo]; ok && cNo != "" { + tokens[i].ClientOrderNo = cNo + } + } + } + } + return tokens, total, nil } diff --git a/frontend/src/api/index.ts b/frontend/src/api/index.ts index a52e81b..d8a4ffe 100644 --- a/frontend/src/api/index.ts +++ b/frontend/src/api/index.ts @@ -301,6 +301,7 @@ export interface RockTokenItem { region: string status: string assigned_order_no?: string + client_order_no?: string expected_uid?: string actual_role_name?: string actual_role_id?: string diff --git a/frontend/src/pages/PlatformRock.tsx b/frontend/src/pages/PlatformRock.tsx index 395aa0a..d76a79d 100644 --- a/frontend/src/pages/PlatformRock.tsx +++ b/frontend/src/pages/PlatformRock.tsx @@ -357,15 +357,41 @@ export default function PlatformRock() { { title: '关联业务工单', dataIndex: 'assigned_order_no', - width: 190, - render: (orderNo) => - orderNo ? ( - - {orderNo} - - ) : ( - - - ), + width: 220, + render: (orderNo, record) => { + if (!orderNo) { + return - + } + return ( + + {/* 系统履约工单号 */} +
+ + {orderNo} + +
+ {/* 创建订单时的商户单号 */} + {record.client_order_no ? ( +
+ 商户: + + {record.client_order_no} + +
+ ) : null} +
+ ) + }, }, { title: '预期 UID vs 扫码角色 (风控门禁)',