From c4507caf37fc87d49a9f4436778c78c93fa75094 Mon Sep 17 00:00:00 2001 From: yml2213 Date: Tue, 18 Aug 2026 20:39:13 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=B4=A6=E5=8F=B7=E5=87=8C?= =?UTF-8?q?=E6=99=A8=E5=93=8D=E5=BA=94=E6=A0=87=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/listing/external_upload.go | 8 +-- .../internal/modules/listing/public_filter.go | 54 +++---------------- .../modules/listing/public_filter_test.go | 32 +++++------ .../internal/modules/listing/service_test.go | 3 ++ .../src/features/listings/views/HomeView.vue | 2 +- .../listings/views/MobileHomeView.vue | 2 +- .../seller/composables/usePublishDraft.ts | 1 + .../seller/composables/usePublishForm.ts | 5 ++ .../views/MobileSellerListingCreateView.css | 4 ++ .../views/MobileSellerListingCreateView.vue | 22 ++++++++ .../seller/views/SellerListingCreateView.css | 4 ++ .../seller/views/SellerListingCreateView.vue | 10 ++++ frontend/src/shared/types/publish.ts | 2 + 13 files changed, 79 insertions(+), 70 deletions(-) diff --git a/backend/internal/modules/listing/external_upload.go b/backend/internal/modules/listing/external_upload.go index 3c467cd..83832ca 100644 --- a/backend/internal/modules/listing/external_upload.go +++ b/backend/internal/modules/listing/external_upload.go @@ -275,9 +275,11 @@ func externalAccountToCreateRequest( "resources": resources, "skin_groups": externalSkinGroups(skins), "online_time_text": onlineTimeText, - "ban_record": normalizeBanRecord(item.BanRecord), - "common_regions": commonRegions(item.CommonRegion), - "remark": remark, + // 外部导入没有该字段时按不可凌晨响应处理,避免旧数据误入夜间专区。 + "early_morning_response": "否", + "ban_record": normalizeBanRecord(item.BanRecord), + "common_regions": commonRegions(item.CommonRegion), + "remark": remark, "import_meta": map[string]any{ "uploader_name": uploaderName, "client_upload_time": uploadTime, diff --git a/backend/internal/modules/listing/public_filter.go b/backend/internal/modules/listing/public_filter.go index 701de0e..2a0647a 100644 --- a/backend/internal/modules/listing/public_filter.go +++ b/backend/internal/modules/listing/public_filter.go @@ -403,53 +403,13 @@ func isNightAvailableSummary(summary map[string]any) bool { if summary == nil { return false } - onlineTime, ok := summary["online_time"].(map[string]any) - if !ok { + // 夜间专区只认号主明确确认的凌晨响应能力,旧数据缺失时默认不进入专区。 + switch value := summary["early_morning_response"].(type) { + case string: + return strings.TrimSpace(value) == "是" + case bool: + return value + default: return false } - start, okStart := parseTimeMinuteValue(onlineTime["start"]) - end, okEnd := parseTimeMinuteValue(onlineTime["end"]) - if !okStart || !okEnd { - return false - } - return timeRangeOverlapsMinutes(start, end, 0, 8*60) -} - -func parseTimeMinuteValue(value any) (int, bool) { - text, ok := value.(string) - if !ok { - return 0, false - } - parts := strings.Split(text, ":") - if len(parts) != 2 { - return 0, false - } - hour, err := strconv.Atoi(parts[0]) - if err != nil || hour < 0 || hour > 23 { - return 0, false - } - minute, err := strconv.Atoi(parts[1]) - if err != nil || minute < 0 || minute > 59 { - return 0, false - } - return hour*60 + minute, true -} - -func timeRangeOverlapsMinutes(start int, end int, targetStart int, targetEnd int) bool { - if start == end { - return true - } - for _, segment := range splitMinuteRange(start, end) { - if segment[0] <= targetEnd && segment[1] >= targetStart { - return true - } - } - return false -} - -func splitMinuteRange(start int, end int) [][2]int { - if start < end { - return [][2]int{{start, end}} - } - return [][2]int{{start, 23*60 + 59}, {0, end}} } diff --git a/backend/internal/modules/listing/public_filter_test.go b/backend/internal/modules/listing/public_filter_test.go index 7eb5145..bf8e9bb 100644 --- a/backend/internal/modules/listing/public_filter_test.go +++ b/backend/internal/modules/listing/public_filter_test.go @@ -178,31 +178,27 @@ func TestSortPublicListingsDefaultUsesShuffleKey(t *testing.T) { } } -func TestIsNightAvailableSummaryUsesMidnightToEight(t *testing.T) { +func TestIsNightAvailableSummaryUsesEarlyMorningResponse(t *testing.T) { tests := []struct { - name string - start string - end string - want bool + name string + response any + want bool }{ - {name: "全天可上号", start: "00:00", end: "23:59", want: true}, - {name: "覆盖夜间新区间", start: "00:00", end: "08:00", want: true}, - {name: "刚好八点开始", start: "08:00", end: "12:00", want: true}, - {name: "八点半开始不算夜间", start: "08:30", end: "12:00", want: false}, - {name: "跨零点覆盖夜间", start: "23:00", end: "02:00", want: true}, - {name: "旧夜间晚间时段不再命中", start: "22:00", end: "23:00", want: false}, + {name: "明确响应", response: "是", want: true}, + {name: "明确不响应", response: "否", want: false}, + {name: "兼容布尔值", response: true, want: true}, + {name: "缺失字段", response: nil, want: false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got := isNightAvailableSummary(map[string]any{ - "online_time": map[string]any{ - "start": tt.start, - "end": tt.end, - }, - }) + summary := map[string]any{} + if tt.response != nil { + summary["early_morning_response"] = tt.response + } + got := isNightAvailableSummary(summary) if got != tt.want { - t.Fatalf("isNightAvailableSummary(%s-%s) = %v, want %v", tt.start, tt.end, got, tt.want) + t.Fatalf("isNightAvailableSummary(%#v) = %v, want %v", tt.response, got, tt.want) } }) } diff --git a/backend/internal/modules/listing/service_test.go b/backend/internal/modules/listing/service_test.go index c623461..21a014a 100644 --- a/backend/internal/modules/listing/service_test.go +++ b/backend/internal/modules/listing/service_test.go @@ -530,6 +530,9 @@ func TestExternalAccountToCreateRequestMapsUploadFields(t *testing.T) { if req.AssetSummary["online_time_text"] != "08:00 至 01:00" { t.Fatalf("online_time_text = %#v", req.AssetSummary["online_time_text"]) } + if req.AssetSummary["early_morning_response"] != "否" { + t.Fatalf("early_morning_response = %#v, want 否", req.AssetSummary["early_morning_response"]) + } onlineTime, ok := req.AssetSummary["online_time"].(map[string]any) if !ok { t.Fatalf("online_time missing: %#v", req.AssetSummary["online_time"]) diff --git a/frontend/src/features/listings/views/HomeView.vue b/frontend/src/features/listings/views/HomeView.vue index 507927d..8856452 100644 --- a/frontend/src/features/listings/views/HomeView.vue +++ b/frontend/src/features/listings/views/HomeView.vue @@ -136,7 +136,7 @@ const zoneOptions = computed(() => [ { key: 'night', label: '夜间专区', - hint: '0-8点可上号', + hint: '0-2点可响应上号', count: zoneCount('night'), }, { diff --git a/frontend/src/features/listings/views/MobileHomeView.vue b/frontend/src/features/listings/views/MobileHomeView.vue index 5caab05..d646fd6 100644 --- a/frontend/src/features/listings/views/MobileHomeView.vue +++ b/frontend/src/features/listings/views/MobileHomeView.vue @@ -104,7 +104,7 @@ const zoneOptions = [ { key: 'all', label: '全部', hint: '当前可租' }, { key: 'sale', label: '特惠', hint: '价格更划算' }, { key: 'gift', label: '赠送', hint: '含赠送物品' }, - { key: 'night', label: '夜间', hint: '0-8点可上号' }, + { key: 'night', label: '夜间', hint: '0-2点可响应上号' }, { key: 'password', label: '账密', hint: '交接更快' }, { key: 'highCoin', label: '高币', hint: '100M以上' }, ] diff --git a/frontend/src/features/seller/composables/usePublishDraft.ts b/frontend/src/features/seller/composables/usePublishDraft.ts index 6ef97e8..08048de 100644 --- a/frontend/src/features/seller/composables/usePublishDraft.ts +++ b/frontend/src/features/seller/composables/usePublishDraft.ts @@ -17,6 +17,7 @@ export function defaultPublishForm(): PublishForm { login_method: '', online_start: '', online_end: '', + early_morning_response: '否', can_change_game_name: '', all_hero: '', ban_record: '', diff --git a/frontend/src/features/seller/composables/usePublishForm.ts b/frontend/src/features/seller/composables/usePublishForm.ts index cf343cd..23dd391 100644 --- a/frontend/src/features/seller/composables/usePublishForm.ts +++ b/frontend/src/features/seller/composables/usePublishForm.ts @@ -308,6 +308,7 @@ export function usePublishForm(options: UsePublishFormOptions) { login_method: listing.login_platform || '', online_start: stringValue(onlineTime.start), online_end: stringValue(onlineTime.end), + early_morning_response: stringValue(summary.early_morning_response) || '否', can_change_game_name: stringValue(summary.can_change_game_name), all_hero: stringValue(summary.all_hero), ban_record: stringValue(summary.ban_record), @@ -700,6 +701,9 @@ export function usePublishForm(options: UsePublishFormOptions) { if (!dailyLossOptions.includes(pricing.dailyLossMAmount.value)) return '请选择每日损耗' const onlineTimeError = validateOnlineTime() if (onlineTimeError) return onlineTimeError + if (form.early_morning_response !== '是' && form.early_morning_response !== '否') { + return '请选择凌晨0-2点是否可响应上号' + } if (pricing.hasAcceleratedSaleRatioInput()) { const ratio = Number(form.accelerated_sale_ratio) if (!Number.isFinite(ratio) || ratio <= 0) return '加速出售比例格式不正确' @@ -818,6 +822,7 @@ export function usePublishForm(options: UsePublishFormOptions) { start: form.online_start, end: form.online_end, }, + early_morning_response: form.early_morning_response, can_change_game_name: form.can_change_game_name, all_hero: form.all_hero, ban_record: form.ban_record, diff --git a/frontend/src/features/seller/views/MobileSellerListingCreateView.css b/frontend/src/features/seller/views/MobileSellerListingCreateView.css index d5e03f7..6e6c8e0 100644 --- a/frontend/src/features/seller/views/MobileSellerListingCreateView.css +++ b/frontend/src/features/seller/views/MobileSellerListingCreateView.css @@ -88,6 +88,10 @@ font-size: 16px; } +.early-morning-response-field :deep(.van-field__label) { + width: 128px; +} + .hint-label, .backend-hint-target.has-hint, .upload-title.has-hint { diff --git a/frontend/src/features/seller/views/MobileSellerListingCreateView.vue b/frontend/src/features/seller/views/MobileSellerListingCreateView.vue index 120c630..b9bd082 100644 --- a/frontend/src/features/seller/views/MobileSellerListingCreateView.vue +++ b/frontend/src/features/seller/views/MobileSellerListingCreateView.vue @@ -121,6 +121,7 @@ function selectRadio(value: T, setter: (value: T) => void) { const canChangeGameNameOptions = ['是', '否'] const allHeroOptions = ['是', '否'] +const earlyMorningResponseOptions = ['是', '否'] // 在线时间:通栏自定义块 + 底部时间选择,避免 van-field 窄列截断原生 time const onlineTimePickerVisible = ref(false) @@ -481,6 +482,27 @@ const screenshotGuides: Record = { 请填写能百分百联系上您的时间。该时段联系不上可能影响上架或扣款,请预留扫码与冻结人脸时间。

+ + + + activeAgreement.value?.content || const canChangeGameNameOptions = ['是', '否'] const allHeroOptions = ['是', '否'] +const earlyMorningResponseOptions = ['是', '否'] // 截图槽位的指导示例图(仅展示、点击放大,不占用上传数量) const screenshotGuides: Record = { @@ -396,6 +397,15 @@ function selectDailyLoss(value: string | number) { +
+ + +
+