From 5668eb745f47f524f980af0a5dbf90bc67ed677f Mon Sep 17 00:00:00 2001 From: yml2213 Date: Thu, 23 Jul 2026 17:06:06 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=A4=96=E9=83=A8=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0=E5=92=8C=E5=A4=87=E6=B3=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/internal/modules/listing/dto.go | 1 + .../modules/listing/external_upload.go | 66 +++++++++++++++---- .../internal/modules/listing/service_test.go | 34 +++++++++- .../listings/views/ListingDetailView.vue | 2 + .../views/MobileListingDetailView.vue | 2 + .../views/MobileSellerListingDetailView.vue | 2 + .../seller/views/SellerListingDetailView.vue | 2 + frontend/src/shared/utils/listingDisplay.ts | 2 + 8 files changed, 97 insertions(+), 14 deletions(-) diff --git a/backend/internal/modules/listing/dto.go b/backend/internal/modules/listing/dto.go index 127cdf5..9c7d591 100644 --- a/backend/internal/modules/listing/dto.go +++ b/backend/internal/modules/listing/dto.go @@ -174,6 +174,7 @@ type ExternalAccountData struct { CommonRegion string `json:"commonRegion"` ContactPhone string `json:"contactPhone"` OwnerOnlineTime string `json:"ownerOnlineTime"` + Remark string `json:"remark"` Currency ExternalUploadCurrency `json:"currency"` DailyConsumption ExternalDailyConsumption `json:"dailyConsumption"` Inventory ExternalUploadInventory `json:"inventory"` diff --git a/backend/internal/modules/listing/external_upload.go b/backend/internal/modules/listing/external_upload.go index e2a4eb1..a814d6f 100644 --- a/backend/internal/modules/listing/external_upload.go +++ b/backend/internal/modules/listing/external_upload.go @@ -227,6 +227,7 @@ func externalAccountToCreateRequest(uploaderName string, uploadTime int64, item staminaLevel := levelText(item.DailyConsumption.Stamina) loadLevel := levelText(item.DailyConsumption.Weight) skins := cleanStrings(item.Inventory.Skins) + remark := strings.TrimSpace(item.Remark) assetSummary := map[string]any{ "face_owner": "", "secret_kd": item.SecretKD, @@ -241,7 +242,7 @@ func externalAccountToCreateRequest(uploaderName string, uploadTime int64, item "online_time_text": strings.TrimSpace(item.OwnerOnlineTime), "ban_record": normalizeBanRecord(item.BanRecord), "common_regions": commonRegions(item.CommonRegion), - "remark": "开放接口自动上传,等待后台审核。", + "remark": remark, "import_meta": map[string]any{ "uploader_name": uploaderName, "client_upload_time": uploadTime, @@ -262,7 +263,7 @@ func externalAccountToCreateRequest(uploaderName string, uploadTime int64, item } return CreateRequest{ Title: externalUploadTitle(item, insurance, hafCoinM), - Description: "开放接口自动上传,等待后台审核。", + Description: remark, ServerRegion: serverRegionFromLoginMethod(item.LoginMethod), LoginPlatform: strings.TrimSpace(item.LoginMethod), RankLevel: strings.TrimSpace(item.Rank), @@ -337,32 +338,71 @@ func externalResources(inventory ExternalUploadInventory) []any { return resources } +// 与 systemconfig 默认 publish_options 皮肤分组保持一致,避免详情页出现英文分组名。 +var externalSkinCatalog = []struct { + key string + names []string +}{ + {"melee", []string{"坠星者", "暗星", "龙牙", "信条", "怜悯", "赤枭", "影锋", "黑海", "北极星", "电锯惊魂", "处刑者"}}, + {"operatorGold", []string{ + "露娜-古墓丽影联动", "蛊-不羁人生", "红狼-电锯惊魂", "露娜-金牌射手", + "牧羊人-街头之星", "蜂医-危险物质", "蜂医-送葬人", "无名-夜鹰", + "威龙-壮志凌云", "威龙-蛟龙特战队", "威龙-铁面判官", "威龙-吴彦祖", + }}, + {"operatorRed", []string{"凌霄成卫", "蚀金玫瑰", "水墨云图", "午夜邮差", "天际线", "维什戴尔"}}, + {"weapon", []string{ + "M7棱镜攻势S2", "腾龙气象感应", "MP7电玩高手S2", "M250电玩高手S2", + "AS Val悬赏令", "K416命运", "M4A1棱镜攻势", "SCAR-H电玩高手", + "QBZ95王牌之剑", "AUG气象感应", "Vector美杜莎", "KC17-造物纪元", + }}, +} + func externalSkinGroups(skins []string) map[string][]string { - groups := map[string][]string{ - "melee": {}, - "imported": {}, - } + groups := map[string][]string{} for _, skin := range skins { - switch skin { - case "坠星者", "暗星", "龙牙", "信条", "怜悯", "赤枭", "影锋", "黑海", "北极星", "电锯惊魂", "处刑者": - groups["melee"] = append(groups["melee"], skin) - default: - groups["imported"] = append(groups["imported"], skin) + skin = strings.TrimSpace(skin) + if skin == "" { + continue } + key := classifyExternalSkin(skin) + groups[key] = append(groups[key], skin) } return groups } +func classifyExternalSkin(skin string) string { + // 先精确匹配,再做包含匹配,兼容“红狼-电锯惊魂 / 电锯惊魂”这类写法。 + for _, group := range externalSkinCatalog { + for _, name := range group.names { + if skin == name { + return group.key + } + } + } + for _, group := range externalSkinCatalog { + for _, name := range group.names { + if strings.Contains(skin, name) || strings.Contains(name, skin) { + return group.key + } + } + } + return "other" +} + func normalizeBanRecord(value string) string { value = strings.TrimSpace(value) switch value { - case "", "无", "无封禁", "无封禁记录": + case "", "无", "无封禁", "无封禁记录", "否", "没有": return "无封禁记录" + case "有", "是", "有封禁", "有封禁记录": + return "有封禁记录" default: - return value + // 兼容历史详情文案:非空即视为有封禁 + return "有封禁记录" } } + func commonRegions(value string) []string { return cleanStrings(strings.Split(value, ",")) } diff --git a/backend/internal/modules/listing/service_test.go b/backend/internal/modules/listing/service_test.go index fa6eed1..20b7118 100644 --- a/backend/internal/modules/listing/service_test.go +++ b/backend/internal/modules/listing/service_test.go @@ -355,8 +355,9 @@ func TestExternalAccountToCreateRequestMapsUploadFields(t *testing.T) { SecretKD: 1.6, DailyLossM: 7, Deposit: 400, - BanRecord: "无", + BanRecord: "有", CommonRegion: "郑州", + Remark: "有语音封禁\n封禁历史:2026/01/23封禁3天", Currency: ExternalUploadCurrency{ HafuCoin: 197.1, RecycleRatio: 43, @@ -371,6 +372,15 @@ func TestExternalAccountToCreateRequestMapsUploadFields(t *testing.T) { }, }) + if req.Description != "有语音封禁\n封禁历史:2026/01/23封禁3天" { + t.Fatalf("Description = %q", req.Description) + } + if req.AssetSummary["remark"] != "有语音封禁\n封禁历史:2026/01/23封禁3天" { + t.Fatalf("remark = %#v", req.AssetSummary["remark"]) + } + if req.AssetSummary["ban_record"] != "有封禁记录" { + t.Fatalf("ban_record = %#v", req.AssetSummary["ban_record"]) + } if req.ServerRegion != "QQ" { t.Fatalf("expected QQ server region, got %q", req.ServerRegion) } @@ -393,11 +403,33 @@ func TestExternalAccountToCreateRequestMapsUploadFields(t *testing.T) { if len(groups["melee"]) != 2 { t.Fatalf("expected melee skins mapped, got %#v", groups) } + if _, ok := groups["imported"]; ok { + t.Fatalf("did not expect imported group, got %#v", groups) + } if len(req.ScreenshotURLS) != 1 || req.ScreenshotURLS[0] != defaultUploadScreenshot { t.Fatalf("expected default screenshot, got %#v", req.ScreenshotURLS) } } +func TestExternalSkinGroupsClassifiesKnownSkins(t *testing.T) { + groups := externalSkinGroups([]string{"暗星", "凌霄成卫", "蛊-不羁人生", "未知皮肤X"}) + if got := groups["melee"]; len(got) != 1 || got[0] != "暗星" { + t.Fatalf("melee = %#v", got) + } + if got := groups["operatorRed"]; len(got) != 1 || got[0] != "凌霄成卫" { + t.Fatalf("operatorRed = %#v", got) + } + if got := groups["operatorGold"]; len(got) != 1 || got[0] != "蛊-不羁人生" { + t.Fatalf("operatorGold = %#v", got) + } + if got := groups["other"]; len(got) != 1 || got[0] != "未知皮肤X" { + t.Fatalf("other = %#v", got) + } + if _, ok := groups["imported"]; ok { + t.Fatalf("unexpected imported group: %#v", groups) + } +} + func validExternalUploadDataJSON() string { return `{ "loginMethod":"QQ账号密码", diff --git a/frontend/src/features/listings/views/ListingDetailView.vue b/frontend/src/features/listings/views/ListingDetailView.vue index 8b2d8ce..12a35d3 100644 --- a/frontend/src/features/listings/views/ListingDetailView.vue +++ b/frontend/src/features/listings/views/ListingDetailView.vue @@ -164,6 +164,8 @@ const detailSkinGroups = computed(() => { operatorGold: '干员金皮', operatorRed: '干员红皮', weapon: '武器皮肤', + other: '其他皮肤', + imported: '其他皮肤', } return Object.entries(groups as Record) .map(([key, value]) => ({ diff --git a/frontend/src/features/listings/views/MobileListingDetailView.vue b/frontend/src/features/listings/views/MobileListingDetailView.vue index f1ae552..95f8d15 100644 --- a/frontend/src/features/listings/views/MobileListingDetailView.vue +++ b/frontend/src/features/listings/views/MobileListingDetailView.vue @@ -166,6 +166,8 @@ const detailSkinGroups = computed(() => { operatorGold: '干员金皮', operatorRed: '干员红皮', weapon: '武器皮肤', + other: '其他皮肤', + imported: '其他皮肤', } return Object.entries(groups as Record) .map(([key, value]) => ({ diff --git a/frontend/src/features/seller/views/MobileSellerListingDetailView.vue b/frontend/src/features/seller/views/MobileSellerListingDetailView.vue index cf7d547..5422a36 100644 --- a/frontend/src/features/seller/views/MobileSellerListingDetailView.vue +++ b/frontend/src/features/seller/views/MobileSellerListingDetailView.vue @@ -114,6 +114,8 @@ const detailSkinGroups = computed(() => { operatorGold: '干员金皮', operatorRed: '干员红皮', weapon: '武器皮肤', + other: '其他皮肤', + imported: '其他皮肤', } return Object.entries(groups as Record) .map(([key, value]) => ({ diff --git a/frontend/src/features/seller/views/SellerListingDetailView.vue b/frontend/src/features/seller/views/SellerListingDetailView.vue index 9cc986d..b5ab015 100644 --- a/frontend/src/features/seller/views/SellerListingDetailView.vue +++ b/frontend/src/features/seller/views/SellerListingDetailView.vue @@ -99,6 +99,8 @@ const detailSkinGroups = computed(() => { operatorGold: '干员金皮', operatorRed: '干员红皮', weapon: '武器皮肤', + other: '其他皮肤', + imported: '其他皮肤', } return Object.entries(groups as Record) .map(([key, value]) => ({ diff --git a/frontend/src/shared/utils/listingDisplay.ts b/frontend/src/shared/utils/listingDisplay.ts index 94e368f..5eb2209 100644 --- a/frontend/src/shared/utils/listingDisplay.ts +++ b/frontend/src/shared/utils/listingDisplay.ts @@ -219,6 +219,8 @@ export function getListingSkinGroups(item: Listing): ListingDisplaySkinGroup[] { operatorGold: '金皮', operatorRed: '红皮', weapon: '武器', + other: '其他', + imported: '其他', } return Object.entries(skinGroups as Record) .map(([key, value]) => ({