From 367f26ffd164d5ab2eedf8d803f450637c55ae6d Mon Sep 17 00:00:00 2001 From: yml2213 Date: Sat, 23 May 2026 11:31:28 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=8F=91=E5=B8=83=E7=95=8C?= =?UTF-8?q?=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/systemconfig/publish_options.go | 15 +- .../modules/systemconfig/repository.go | 44 ++++ backend/seeds/dev_orders.sql | 26 +- docs/发布比例计算.md | 61 +++++ docs/额外消耗品_5.12.jpg | Bin 0 -> 46821 bytes frontend/src/api/homeConfig.ts | 3 +- frontend/src/api/listingOptions.ts | 154 ++++++------ .../views/admin/AdminSystemConfigsView.vue | 31 +-- frontend/src/views/mobile/MobileHomeView.vue | 6 +- .../views/mobile/MobileListingDetailView.vue | 2 +- .../mobile/MobileSellerListingCreateView.css | 13 +- .../mobile/MobileSellerListingCreateView.vue | 227 ++++++++++-------- frontend/src/views/public/HomeView.vue | 6 +- 13 files changed, 348 insertions(+), 240 deletions(-) create mode 100644 docs/发布比例计算.md create mode 100644 docs/额外消耗品_5.12.jpg diff --git a/backend/internal/modules/systemconfig/publish_options.go b/backend/internal/modules/systemconfig/publish_options.go index 87a4924..7997c3b 100644 --- a/backend/internal/modules/systemconfig/publish_options.go +++ b/backend/internal/modules/systemconfig/publish_options.go @@ -58,12 +58,15 @@ func DefaultPublishOptions() PublishOptionsDTO { }, }, QuantityItems: []PublishQuantityItem{ - {Key: "awmAmmo", Label: "AWM子弹", Price: "0.8元/发"}, - {Key: "helmet6", Label: "6头数量", Price: "2元/个"}, - {Key: "armor6", Label: "6甲数量", Price: "3元/个"}, - {Key: "kit5", Label: "5级全装套数量", Price: "5元/个"}, - {Key: "level6Ammo", Label: "6级子弹", Price: "0.26元/发"}, - {Key: "gridCard9", Label: "9格体验卡", Price: "5元/张", Placeholder: "如果是赛季9格,此处填0即可"}, + {Key: "level6Ammo", Label: "6级弹", Price: "0.1元/发", Placeholder: "按单发数量填写,60发=6元"}, + {Key: "awmAmmo", Label: "AWM子弹", Price: "0.6元/发"}, + {Key: "barrettAmmo", Label: "巴雷特子弹", Price: "0.3元/发"}, + {Key: "armor6", Label: "6甲", Price: "2.5元/个"}, + {Key: "helmet6", Label: "6头", Price: "1.5元/个"}, + {Key: "gridCard9", Label: "9格体验卡", Price: "3元/张", Placeholder: "如果是赛季9格,此处填0即可"}, + {Key: "redPacket45", Label: "45格大红包", Price: "1.5元/个"}, + {Key: "coffeeBean", Label: "高级咖啡豆", Price: "2.5元/个"}, + {Key: "bulletPart", Label: "高级子弹零件", Price: "3元/个"}, }, ScreenshotSlots: []PublishScreenshotSlot{ {Key: "coin", Label: "纯币截图", Required: true, Hint: "请上传纯币截图(必传)"}, diff --git a/backend/internal/modules/systemconfig/repository.go b/backend/internal/modules/systemconfig/repository.go index faf1451..081b6da 100644 --- a/backend/internal/modules/systemconfig/repository.go +++ b/backend/internal/modules/systemconfig/repository.go @@ -3,6 +3,7 @@ package systemconfig import ( "encoding/json" "errors" + "strings" "hfb_sys/backend/internal/model" @@ -132,11 +133,54 @@ func (r *Repository) ensureDefaults() error { if err := tx.Clauses(clause.OnConflict{DoNothing: true}).Create(&row).Error; err != nil { return err } + if item.Key == publishOptionsConfigKey { + if err := updateLegacyPublishOptions(tx, item); err != nil { + return err + } + } } return nil }) } +func updateLegacyPublishOptions(tx *gorm.DB, item defaultConfig) error { + var row model.SystemConfig + if err := tx.Where("`key` = ?", item.Key).First(&row).Error; err != nil { + return err + } + if !isLegacyPublishOptionsValue(row.Value) { + return nil + } + row.Value = item.Value + row.Description = item.Description + return tx.Save(&row).Error +} + +func isLegacyPublishOptionsValue(value string) bool { + legacyMarkers := []string{ + `"kit5"`, + "5级全装套", + "6级子弹", + "6头数量", + "6甲数量", + "0.26元/发", + "0.8元/发", + "çº", + "å¼", + "å…", + "å¤", + "ä½", + "é«", + "ï¼", + } + for _, marker := range legacyMarkers { + if strings.Contains(value, marker) { + return true + } + } + return false +} + func appendAuditLog(tx *gorm.DB, actorID uint64, action string, bizID uint64, meta AuditMeta, detail map[string]any) error { raw, err := json.Marshal(detail) if err != nil { diff --git a/backend/seeds/dev_orders.sql b/backend/seeds/dev_orders.sql index c98ed76..65689a3 100644 --- a/backend/seeds/dev_orders.sql +++ b/backend/seeds/dev_orders.sql @@ -78,9 +78,9 @@ VALUES 'ban_record', '无封禁记录', 'resources', JSON_ARRAY( JSON_OBJECT('key', 'awmAmmo', 'label', 'AWM子弹', 'quantity', 80, 'mode', '收费'), - JSON_OBJECT('key', 'helmet6', 'label', '6头数量', 'quantity', 6, 'mode', '收费'), - JSON_OBJECT('key', 'armor6', 'label', '6甲数量', 'quantity', 4, 'mode', '收费'), - JSON_OBJECT('key', 'level6Ammo', 'label', '6级子弹', 'quantity', 360, 'mode', '收费') + JSON_OBJECT('key', 'helmet6', 'label', '6头', 'quantity', 6, 'mode', '收费'), + JSON_OBJECT('key', 'armor6', 'label', '6甲', 'quantity', 4, 'mode', '收费'), + JSON_OBJECT('key', 'level6Ammo', 'label', '6级弹', 'quantity', 360, 'mode', '收费') ), 'skin_groups', JSON_OBJECT( 'melee', JSON_ARRAY('龙牙', '信条'), @@ -116,7 +116,7 @@ VALUES 'ban_record', '无封禁记录', 'resources', JSON_ARRAY( JSON_OBJECT('key', 'awmAmmo', 'label', 'AWM子弹', 'quantity', 30, 'mode', '收费'), - JSON_OBJECT('key', 'helmet6', 'label', '6头数量', 'quantity', 2, 'mode', '收费') + JSON_OBJECT('key', 'helmet6', 'label', '6头', 'quantity', 2, 'mode', '收费') ), 'skin_groups', JSON_OBJECT( 'melee', JSON_ARRAY('怜悯'), @@ -187,9 +187,9 @@ VALUES 'ban_record', '无封禁记录', 'resources', JSON_ARRAY( JSON_OBJECT('key', 'awmAmmo', 'label', 'AWM子弹', 'quantity', 120, 'mode', '收费'), - JSON_OBJECT('key', 'helmet6', 'label', '6头数量', 'quantity', 10, 'mode', '收费'), - JSON_OBJECT('key', 'armor6', 'label', '6甲数量', 'quantity', 8, 'mode', '收费'), - JSON_OBJECT('key', 'level6Ammo', 'label', '6级子弹', 'quantity', 800, 'mode', '收费') + JSON_OBJECT('key', 'helmet6', 'label', '6头', 'quantity', 10, 'mode', '收费'), + JSON_OBJECT('key', 'armor6', 'label', '6甲', 'quantity', 8, 'mode', '收费'), + JSON_OBJECT('key', 'level6Ammo', 'label', '6级弹', 'quantity', 800, 'mode', '收费') ), 'skin_groups', JSON_OBJECT( 'melee', JSON_ARRAY('坠星者', '处刑者'), @@ -225,7 +225,7 @@ VALUES 'ban_record', '无封禁记录', 'resources', JSON_ARRAY( JSON_OBJECT('key', 'awmAmmo', 'label', 'AWM子弹', 'quantity', 80, 'mode', '赠送'), - JSON_OBJECT('key', 'kit5', 'label', '5级全装套数量', 'quantity', 6, 'mode', '收费') + JSON_OBJECT('key', 'redPacket45', 'label', '45格大红包', 'quantity', 6, 'mode', '收费') ), 'skin_groups', JSON_OBJECT( 'melee', JSON_ARRAY('影锋'), @@ -259,8 +259,8 @@ VALUES 'online_time', JSON_OBJECT('start', '14:00', 'end', '01:00'), 'ban_record', '无封禁记录', 'resources', JSON_ARRAY( - JSON_OBJECT('key', 'kit5', 'label', '5级全装套数量', 'quantity', 3, 'mode', '收费'), - JSON_OBJECT('key', 'helmet6', 'label', '6头数量', 'quantity', 1, 'mode', '收费') + JSON_OBJECT('key', 'coffeeBean', 'label', '高级咖啡豆', 'quantity', 3, 'mode', '收费'), + JSON_OBJECT('key', 'helmet6', 'label', '6头', 'quantity', 1, 'mode', '收费') ), 'skin_groups', JSON_OBJECT( 'melee', JSON_ARRAY('北极星'), @@ -295,8 +295,8 @@ VALUES 'ban_record', '无封禁记录', 'resources', JSON_ARRAY( JSON_OBJECT('key', 'awmAmmo', 'label', 'AWM子弹', 'quantity', 48, 'mode', '收费'), - JSON_OBJECT('key', 'armor6', 'label', '6甲数量', 'quantity', 3, 'mode', '收费'), - JSON_OBJECT('key', 'helmet6', 'label', '6头数量', 'quantity', 4, 'mode', '收费') + JSON_OBJECT('key', 'armor6', 'label', '6甲', 'quantity', 3, 'mode', '收费'), + JSON_OBJECT('key', 'helmet6', 'label', '6头', 'quantity', 4, 'mode', '收费') ), 'skin_groups', JSON_OBJECT( 'melee', JSON_ARRAY('赤枭', '黑海'), @@ -331,7 +331,7 @@ VALUES 'online_time', JSON_OBJECT('start', '10:00', 'end', '24:00'), 'ban_record', '无封禁记录', 'resources', JSON_ARRAY( - JSON_OBJECT('key', 'level6Ammo', 'label', '6级子弹', 'quantity', 520, 'mode', '赠送'), + JSON_OBJECT('key', 'level6Ammo', 'label', '6级弹', 'quantity', 520, 'mode', '赠送'), JSON_OBJECT('key', 'awmAmmo', 'label', 'AWM子弹', 'quantity', 100, 'mode', '收费'), JSON_OBJECT('key', 'gridCard9', 'label', '9格体验卡', 'quantity', 2, 'mode', '收费') ), diff --git a/docs/发布比例计算.md b/docs/发布比例计算.md new file mode 100644 index 0000000..95db984 --- /dev/null +++ b/docs/发布比例计算.md @@ -0,0 +1,61 @@ +好的,咱们把所有的账目和加减逻辑全部锁死,整理出一套最严密、绝对不会看错的最终版逻辑总览。 + +整体的核心逻辑是:**账号底子越差(缺配置)或包里哈夫币越多,比例数字就越大($1:\text{数字}$,数字越大代表给客户的哈夫币越多,号越便宜、越容易租)。** + +以下是最终的完整逻辑链条: + +--- + +### 1. 核心大框架:基础比例(对标保险箱) + +这是账号在配置全满(完美状态)下的初始比例: + +* **9 格保险箱**:基础比例为 **$1:40$** +* **6 格保险箱**:基础比例为 **$1:42$** +* **4 格保险箱**:基础比例为 **$1:47$** +* **2 格保险箱**:基础比例为 **$1:48$** + +--- + +### 2. 账号配置浮动逻辑(5项标准) + +完美的“理想账号”有 5 个指标:**红皮、刀皮、满体力、满负重、砖皮**。 +规则是:**每缺少其中任意 1 项,比例数字直接 $+1$**。 + +以 **9 格保险箱** 为例,随着配置缺失,比例梯队如下: + +* **5项完美全满**:**$1:40$** +* **缺 1 项**(剩4项):**$1:41$** +* **缺 2 项**(剩3项):**$1:42$** +* **缺 3 项**(比如**只满足了满体力+满负重**):**$1:43$** +* **缺 4 项**(剩1项):**$1:44$** +* **5项全无**(白号):**$1:45$** + +*(注:如果是 6格/4格/2格 保箱,则在此基础上各自的初始值往上加项即可。)* + +--- + +### 3. 大额哈夫币“再叠加”逻辑(高币号修正) + +当号里的哈夫币过多时(由于需求少、难成交),在上面算出的“配置比例”基础上,还要**额外再加上大额币的修正值**: + +* **哈夫币 $> 130\text{M}$**:最终比例再 **$+1$** +* **哈夫币 $> 230\text{M}$**:最终比例再 **$+2.5$** +* **哈夫币 $> 380\text{M}$**:最终比例再 **$+4$** +* **哈夫币 $> 530\text{M}$**:最终比例再 **$+5$** + +--- + +### 🛠️ 终极公式计算演示 + +> **最终出租比例 = 该保箱基础比例 + (5 - 实际拥有项数) + 大额币修正值** + +**实战看盘举例:** +一个客户来放号,是个 **9格保箱** 账号(基础 40),包里有 **$250\text{M}$ 哈夫币**,账号里**只有满体和满负重**。 + +1. **查保箱基础**:9格 = $40$ +2. **算缺失项**:5项里只有2项,缺了3项 = $+3$ (此时比例来到 $43$) +3. **叠大额币**:$250\text{M}$ 触发了 $> 230\text{M}$ 的档位 = $+2.5$ +4. **总计**:$40 + 3 + 2.5 = 45.5$ + +**最终该号的出租比例就是:$1:45.5$** \ No newline at end of file diff --git a/docs/额外消耗品_5.12.jpg b/docs/额外消耗品_5.12.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e7ca467ca84fbfc0b43ec911d3feae0b6d9cbad2 GIT binary patch literal 46821 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: MobileHomeC return { announcements: announcements.length ? announcements : defaultHomeAnnouncements, banners: banners.length ? banners : defaultHomeBanners, - publish_options: mergeListingPublishOptions(config?.publish_options || defaultListingPublishOptions), + publish_options: mergeListingPublishOptions(config?.publish_options), } } diff --git a/frontend/src/api/listingOptions.ts b/frontend/src/api/listingOptions.ts index f41020e..ff467c6 100644 --- a/frontend/src/api/listingOptions.ts +++ b/frontend/src/api/listingOptions.ts @@ -2,17 +2,11 @@ import { apiClient } from './client' export type ChargeMode = '赠送' | '收费' -export type QuantityKey = - | 'awmAmmo' - | 'helmet6' - | 'armor6' - | 'kit5' - | 'level6Ammo' - | 'gridCard9' +export type QuantityKey = string -export type ScreenshotKey = 'coin' | 'gameId' | 'totalAsset' | 'tencentSecurity' | 'skin' +export type ScreenshotKey = string -export type SkinCategoryKey = 'melee' | 'operator' | 'weapon' +export type SkinCategoryKey = string export interface PublishOptionGroup { key: SkinCategoryKey | string @@ -53,63 +47,17 @@ interface ApiResponse { data: T } -export const defaultListingPublishOptions: ListingPublishOptions = { - server_options: ['QQ', '微信', 'Steam'], - face_options: ['是', '否'], - rank_options: ['青铜', '白银', '黄金', '铂金', '钻石', '黑鹰', '三角洲巅峰'], - insurance_options: ['2*1', '2*2', '2*3', '3*3'], - level_options: ['1级', '2级', '3级', '4级', '5级', '6级', '7级'], - login_method_options: ['扫码', '账号密码'], - region_options: [ - '北京', '天津', '河北', '山西', '内蒙古', '辽宁', '吉林', '黑龙江', - '上海', '江苏', '浙江', '安徽', '福建', '江西', '山东', '河南', - '湖北', '湖南', '广东', '广西', '海南', '重庆', '四川', '贵州', - '云南', '陕西', '甘肃', '青海', '宁夏', '新疆', '西藏', '香港', - '澳门', '台湾', - ], - skin_groups: [ - { - key: 'melee', - title: '近战皮肤', - options: ['坠星者', '暗星', '龙牙', '信条', '怜悯', '赤枭', '影锋', '黑海', '北极星', '电锯惊魂', '处刑者'], - }, - { - key: 'operator', - title: '干员皮肤', - options: [ - '威龙-凌霄戍卫', '红狼-蚀金玫瑰', '露娜-黑天际线', '蛊-能天使午夜邮差', - '骇爪-维什戴尔', '骇爪-水墨云图', '威龙-吴彦祖', '威龙-铁面判官', - '威龙-壮志凌云', '威龙-蛟龙特战队', '蜂医-送葬人', '蜂医-危险物质', - '蜂医-黑鹰坠落', '牧羊人-街头之星', '牧羊人-黑鹰坠落', '乌鲁鲁-黑鹰坠落', - '红狼-黑鹰坠落', '无名-夜鹰', '深蓝-不破誓约', '红狼-电锯惊魂', - '露娜-古墓丽影劳拉', '赛伊德', - ], - }, - { - key: 'weapon', - title: '武器皮肤', - options: [ - 'M7棱镜攻势S2', '腾龙气象感应', 'MP7电玩高手S2', 'M250电玩高手S2', - 'AS Val悬赏令', 'K416命运', 'M4A1棱镜攻势', 'SCAR-H电玩高手', - 'QBZ95王牌之剑', 'AUG气象感应', 'Vector美杜莎', 'KC17-造物纪元', - ], - }, - ], - quantity_items: [ - { key: 'awmAmmo', label: 'AWM子弹', price: '0.8元/发' }, - { key: 'helmet6', label: '6头数量', price: '2元/个' }, - { key: 'armor6', label: '6甲数量', price: '3元/个' }, - { key: 'kit5', label: '5级全装套数量', price: '5元/个' }, - { key: 'level6Ammo', label: '6级子弹', price: '0.26元/发' }, - { key: 'gridCard9', label: '9格体验卡', price: '5元/张', placeholder: '如果是赛季9格,此处填0即可' }, - ], - screenshot_slots: [ - { key: 'coin', label: '纯币截图', required: true, hint: '请上传纯币截图(必传)' }, - { key: 'gameId', label: '游戏ID截图', required: true, hint: '请上传游戏ID截图(必传)' }, - { key: 'totalAsset', label: '总资产截图', required: true, hint: '请上传总资产截图(必传)' }, - { key: 'tencentSecurity', label: '腾讯安全中心截图', required: true, hint: '请上传腾讯安全中心截图(必传)' }, - { key: 'skin', label: '皮肤截图', required: false, hint: '请上传皮肤截图(选传)' }, - ], +export const emptyListingPublishOptions: ListingPublishOptions = { + server_options: [], + face_options: [], + rank_options: [], + insurance_options: [], + level_options: [], + login_method_options: [], + region_options: [], + skin_groups: [], + quantity_items: [], + screenshot_slots: [], } export async function fetchListingPublishOptions() { @@ -119,15 +67,69 @@ export async function fetchListingPublishOptions() { export function mergeListingPublishOptions(options?: Partial): ListingPublishOptions { return { - server_options: options?.server_options?.length ? options.server_options : defaultListingPublishOptions.server_options, - face_options: options?.face_options?.length ? options.face_options : defaultListingPublishOptions.face_options, - rank_options: options?.rank_options?.length ? options.rank_options : defaultListingPublishOptions.rank_options, - insurance_options: options?.insurance_options?.length ? options.insurance_options : defaultListingPublishOptions.insurance_options, - level_options: options?.level_options?.length ? options.level_options : defaultListingPublishOptions.level_options, - login_method_options: options?.login_method_options?.length ? options.login_method_options : defaultListingPublishOptions.login_method_options, - region_options: options?.region_options?.length ? options.region_options : defaultListingPublishOptions.region_options, - skin_groups: options?.skin_groups?.length ? options.skin_groups : defaultListingPublishOptions.skin_groups, - quantity_items: options?.quantity_items?.length ? options.quantity_items as PublishQuantityItem[] : defaultListingPublishOptions.quantity_items, - screenshot_slots: options?.screenshot_slots?.length ? options.screenshot_slots as PublishScreenshotSlot[] : defaultListingPublishOptions.screenshot_slots, + server_options: normalizeStringList(options?.server_options), + face_options: normalizeStringList(options?.face_options), + rank_options: normalizeStringList(options?.rank_options), + insurance_options: normalizeStringList(options?.insurance_options), + level_options: normalizeStringList(options?.level_options), + login_method_options: normalizeStringList(options?.login_method_options), + region_options: normalizeStringList(options?.region_options), + skin_groups: normalizeOptionGroups(options?.skin_groups), + quantity_items: normalizeQuantityItems(options?.quantity_items), + screenshot_slots: normalizeScreenshotSlots(options?.screenshot_slots), } } + +function normalizeStringList(values?: unknown[]) { + return Array.isArray(values) + ? values.map((item) => (typeof item === 'string' ? item.trim() : '')).filter(Boolean) + : [] +} + +function normalizeOptionGroups(values?: unknown[]): PublishOptionGroup[] { + if (!Array.isArray(values)) return [] + return values + .map((item) => { + const group = isRecord(item) ? item : {} + return { + key: typeof group.key === 'string' ? group.key.trim() : '', + title: typeof group.title === 'string' ? group.title.trim() : '', + options: normalizeStringList(Array.isArray(group.options) ? group.options : []), + } + }) + .filter((item) => item.key && item.title) +} + +function normalizeQuantityItems(values?: unknown[]): PublishQuantityItem[] { + if (!Array.isArray(values)) return [] + return values + .map((item) => { + const row = isRecord(item) ? item : {} + return { + key: typeof row.key === 'string' ? row.key.trim() : '', + label: typeof row.label === 'string' ? row.label.trim() : '', + price: typeof row.price === 'string' ? row.price.trim() : '', + placeholder: typeof row.placeholder === 'string' ? row.placeholder.trim() : undefined, + } + }) + .filter((item) => item.key && item.label) +} + +function normalizeScreenshotSlots(values?: unknown[]): PublishScreenshotSlot[] { + if (!Array.isArray(values)) return [] + return values + .map((item) => { + const row = isRecord(item) ? item : {} + return { + key: typeof row.key === 'string' ? row.key.trim() : '', + label: typeof row.label === 'string' ? row.label.trim() : '', + required: row.required === true, + hint: typeof row.hint === 'string' ? row.hint.trim() : '', + } + }) + .filter((item) => item.key && item.label) +} + +function isRecord(value: unknown): value is Record { + return typeof value === 'object' && value !== null +} diff --git a/frontend/src/views/admin/AdminSystemConfigsView.vue b/frontend/src/views/admin/AdminSystemConfigsView.vue index 512a418..b54dc7a 100644 --- a/frontend/src/views/admin/AdminSystemConfigsView.vue +++ b/frontend/src/views/admin/AdminSystemConfigsView.vue @@ -3,7 +3,7 @@ import { ElMessage } from 'element-plus' import { computed, onMounted, ref } from 'vue' import { - defaultListingPublishOptions, + emptyListingPublishOptions, mergeListingPublishOptions, type ListingPublishOptions, } from '@/api/listingOptions' @@ -23,7 +23,7 @@ const configs = ref([]) const activeConfig = ref(null) const value = ref('') const description = ref('') -const publishOptionsDraft = ref(cloneOptions(defaultListingPublishOptions)) +const publishOptionsDraft = ref(cloneOptions(emptyListingPublishOptions)) const homeAnnouncementLines = ref(itemsToLines(defaultHomeAnnouncements)) const homeBannersDraft = ref(cloneHomeBanners(defaultHomeBanners)) const uploadingBannerIndex = ref(null) @@ -141,20 +141,20 @@ async function handleSave() { function parsePublishOptions(raw: string) { try { - const parsed = raw.trim() ? JSON.parse(raw) : defaultListingPublishOptions + const parsed = raw.trim() ? JSON.parse(raw) : emptyListingPublishOptions return cloneOptions(mergeListingPublishOptions(parsed)) } catch { - ElMessage.warning('发布选项 JSON 解析失败,已使用默认配置') - return cloneOptions(defaultListingPublishOptions) + ElMessage.warning('发布选项 JSON 解析失败,已清空草稿') + return cloneOptions(emptyListingPublishOptions) } } function safeParsePublishOptions(raw: string) { try { - const parsed = raw.trim() ? JSON.parse(raw) : defaultListingPublishOptions + const parsed = raw.trim() ? JSON.parse(raw) : emptyListingPublishOptions return cloneOptions(mergeListingPublishOptions(parsed)) } catch { - return cloneOptions(defaultListingPublishOptions) + return cloneOptions(emptyListingPublishOptions) } } @@ -222,7 +222,7 @@ function removeSkinGroup(index: number) { function addQuantityItem() { publishOptionsDraft.value.quantity_items.push({ - key: `item_${Date.now()}` as never, + key: `item_${Date.now()}`, label: '', price: '', }) @@ -234,7 +234,7 @@ function removeQuantityItem(index: number) { function addScreenshotSlot() { publishOptionsDraft.value.screenshot_slots.push({ - key: `screenshot_${Date.now()}` as never, + key: `screenshot_${Date.now()}`, label: '', required: false, hint: '', @@ -245,10 +245,6 @@ function removeScreenshotSlot(index: number) { publishOptionsDraft.value.screenshot_slots.splice(index, 1) } -function resetPublishOptions() { - publishOptionsDraft.value = cloneOptions(defaultListingPublishOptions) -} - function addHomeBanner() { homeBannersDraft.value.push({ eyebrow: '首页推荐', @@ -330,7 +326,7 @@ function readError(error: unknown, fallback: string) {

Publish Options

发布表单选项

- 管理移动端发布页的区服、段位、皮肤、资源道具、截图材料和地区选项。 + 管理移动端发布页的区服、段位、皮肤、额外消耗品、截图材料和地区选项。
编辑发布选项 @@ -345,7 +341,7 @@ function readError(error: unknown, fallback: string) {
{{ publishStats.resourceCount }} - 资源道具 + 额外消耗品
{{ publishStats.screenshotCount }} @@ -421,7 +417,6 @@ function readError(error: unknown, fallback: string) {
发布页选项配置 - 恢复默认选项
@@ -512,8 +507,8 @@ function readError(error: unknown, fallback: string) {
- 资源道具 - 添加道具 + 额外消耗品 + 添加消耗品
diff --git a/frontend/src/views/mobile/MobileHomeView.vue b/frontend/src/views/mobile/MobileHomeView.vue index 6779877..964da3c 100644 --- a/frontend/src/views/mobile/MobileHomeView.vue +++ b/frontend/src/views/mobile/MobileHomeView.vue @@ -4,7 +4,7 @@ import { RouterLink, useRoute } from "vue-router"; import { showToast } from "vant"; import { - defaultListingPublishOptions, + emptyListingPublishOptions, type ListingPublishOptions, } from "@/api/listingOptions"; import { fetchListings, type Listing } from "@/api/listings"; @@ -39,7 +39,7 @@ const route = useRoute(); const loading = ref(false); const loadFailed = ref(false); const listings = ref([]); -const publishOptions = ref(defaultListingPublishOptions); +const publishOptions = ref(emptyListingPublishOptions); const sortOpen = ref(false); const activeSort = ref("comprehensive"); const filterOpen = ref(false); @@ -176,7 +176,7 @@ async function loadHomeConfig() { } catch { announcements.value = defaultHomeAnnouncements; bannerSlides.value = defaultHomeBanners; - publishOptions.value = defaultListingPublishOptions; + publishOptions.value = emptyListingPublishOptions; } } diff --git a/frontend/src/views/mobile/MobileListingDetailView.vue b/frontend/src/views/mobile/MobileListingDetailView.vue index 267656f..2c0b73f 100644 --- a/frontend/src/views/mobile/MobileListingDetailView.vue +++ b/frontend/src/views/mobile/MobileListingDetailView.vue @@ -268,7 +268,7 @@ function isNavActive(path: string) {
-

资源道具

+

额外消耗品

(defaultListingPublishOptions); +const publishOptions = ref(emptyListingPublishOptions); function isNavActive(path: string) { if (path === "/m") return route.path === "/m"; @@ -74,43 +71,20 @@ function defaultForm(): PublishForm { ban_record: "", common_regions: [], deposit_amount: "", - ratio: "", - final_price: 0, - rent_days: 0, remark: "", }; } function defaultQuantityValues(): Record { - return { - awmAmmo: 0, - helmet6: 0, - armor6: 0, - kit5: 0, - level6Ammo: 0, - gridCard9: 0, - }; + return {}; } function defaultQuantityModes(): Record { - return { - awmAmmo: "收费", - helmet6: "收费", - armor6: "收费", - kit5: "收费", - level6Ammo: "收费", - gridCard9: "收费", - }; + return {}; } function defaultScreenshotFiles(): Record { - return { - coin: "", - gameId: "", - totalAsset: "", - tencentSecurity: "", - skin: "", - }; + return {}; } const form = reactive(defaultForm()); @@ -138,10 +112,17 @@ const skinGroups = computed(() => publishOptions.value.skin_groups); const quantityItems = computed(() => publishOptions.value.quantity_items); const screenshotSlots = computed(() => publishOptions.value.screenshot_slots); const screenshotUrls = computed(() => - screenshotSlots.value.map((item) => screenshotFiles[item.key]).filter(Boolean) + screenshotSlots.value + .map((item) => screenshotFiles[item.key]) + .filter((url): url is string => Boolean(url)) ); -const dailyLossText = computed(() => - form.rent_days ? calculateDailyLoss(Number(form.haf_coin_amount || 0)) : "" +const coinWanAmount = computed(() => Number(form.haf_coin_amount || 0)); +const calculatedRatio = computed(() => calculatePublishRatio()); +const calculatedFinalPrice = computed(() => + calculatedRatio.value > 0 ? roundMoney(coinWanAmount.value / calculatedRatio.value) : 0 +); +const calculatedRentDays = computed(() => + coinWanAmount.value > 0 ? calculateRentDays(coinWanAmount.value) : 0 ); onMounted(() => { @@ -161,7 +142,7 @@ async function loadPublishOptions() { try { publishOptions.value = await fetchListingPublishOptions(); } catch { - publishOptions.value = defaultListingPublishOptions; + publishOptions.value = emptyListingPublishOptions; } } @@ -188,10 +169,7 @@ function restoreDraft() { if (!raw) return; try { const draft = JSON.parse(raw) as Partial; - Object.assign(form, defaultForm(), draft.form || {}); - form.common_regions = Array.isArray(draft.form?.common_regions) - ? [...draft.form.common_regions] - : []; + Object.assign(form, normalizeDraftForm(draft.form)); Object.assign(quantityValues, defaultQuantityValues(), draft.quantityValues || {}); Object.assign(quantityModes, defaultQuantityModes(), draft.quantityModes || {}); Object.assign(screenshotFiles, defaultScreenshotFiles(), draft.screenshotFiles || {}); @@ -203,6 +181,27 @@ function restoreDraft() { } } +function normalizeDraftForm(value: unknown): PublishForm { + const next = defaultForm(); + if (!isRecord(value)) return next; + + for (const key of Object.keys(next) as Array) { + if (key === "common_regions") continue; + const draftValue = value[key]; + if (draftValue !== undefined) { + next[key] = draftValue as never; + } + } + next.common_regions = Array.isArray(value.common_regions) + ? value.common_regions.filter((region): region is string => typeof region === "string") + : []; + return next; +} + +function isRecord(value: unknown): value is Record { + return typeof value === "object" && value !== null; +} + function resetDraftState() { Object.assign(form, defaultForm()); Object.assign(quantityValues, defaultQuantityValues()); @@ -288,23 +287,6 @@ function handleFireLevelInput(value: string | number) { form.fire_level = Math.trunc(level); } -function calculatePrice() { - const coinWan = Number(form.haf_coin_amount || 0); - const ratio = Number(form.ratio || 0); - if (coinWan <= 0) { - showToast({ message: "请先填写哈夫币/万", icon: "warning-o" }); - return; - } - if (ratio <= 0) { - showToast({ message: "比例需大于0", icon: "warning-o" }); - return; - } - const finalPrice = roundMoney(coinWan / ratio); - const rentDays = coinWan >= 30000 ? 7 : coinWan >= 10000 ? 3 : 1; - form.final_price = finalPrice; - form.rent_days = rentDays; -} - async function handleSubmit() { const error = validateForm(); if (error) { @@ -314,8 +296,8 @@ async function handleSubmit() { loading.value = true; try { const title = `${form.server_region} ${form.rank_level} ${form.haf_coin_amount}万哈夫币`; - const rentDays = Math.max(Number(form.rent_days || 1), 1); - const dailyPrice = roundMoney(Number(form.final_price) / rentDays); + const rentDays = Math.max(calculatedRentDays.value, 1); + const dailyPrice = roundMoney(calculatedFinalPrice.value / rentDays); const hourlyPrice = Math.max(roundMoney(dailyPrice / 24), 0.01); await createListing({ @@ -359,8 +341,8 @@ function validateForm() { if (form.deposit_amount === "" || Number(form.deposit_amount) < 0) { return "请填写押金"; } - if (!form.final_price || !form.rent_days) { - return "请先点击计算价格"; + if (!calculatedFinalPrice.value || !calculatedRentDays.value) { + return "请完善币数、保险、体力和负重后再发布"; } for (const item of screenshotSlots.value) { if (item.required && !screenshotFiles[item.key]) { @@ -382,7 +364,7 @@ function buildAssetSummary() { key: item.key, label: item.label, quantity: Number(quantityValues[item.key] || 0), - mode: quantityModes[item.key], + mode: quantityModes[item.key] || "收费", })), skin_groups: skinGroups.value.reduce>((groups, group) => { groups[group.key] = group.options.filter((skin) => @@ -404,10 +386,79 @@ function roundMoney(value: number) { return Math.round(value * 100) / 100; } -function calculateDailyLoss(coinWan: number) { - if (coinWan >= 30000) return "30M"; - if (coinWan >= 10000) return "20M"; - return "10M"; +function calculatePublishRatio() { + if ( + coinWanAmount.value <= 0 || + !form.season_insurance || + !form.stamina_level || + !form.load_level + ) { + return 0; + } + const baseRatio = getInsuranceBaseRatio(form.season_insurance); + if (baseRatio <= 0) return 0; + + return baseRatio + (5 - getConfigHitCount()) + getCoinCorrection(coinWanAmount.value); +} + +function getInsuranceBaseRatio(insurance: string) { + const slots = getInsuranceSlots(insurance); + const ratioBySlots: Record = { + 9: 40, + 6: 42, + 4: 47, + 2: 48, + }; + return ratioBySlots[slots] || 0; +} + +function getInsuranceSlots(insurance: string) { + const match = insurance.match(/^(\d+)\*(\d+)$/); + if (!match) return 0; + return Number(match[1]) * Number(match[2]); +} + +function getConfigHitCount() { + const checks = [ + hasSelectedSkinGroup("operator"), + hasSelectedSkinGroup("melee"), + isMaxLevel(form.stamina_level), + isMaxLevel(form.load_level), + hasSelectedSkinGroup("weapon"), + ]; + return checks.filter(Boolean).length; +} + +function hasSelectedSkinGroup(groupKey: string) { + const group = skinGroups.value.find((item) => item.key === groupKey); + if (!group) return false; + return group.options.some((skin) => selectedSkins.value.includes(skin)); +} + +function isMaxLevel(value: string) { + const currentLevel = readLevelNumber(value); + const maxLevel = Math.max(...levelOptions.value.map(readLevelNumber).filter(Boolean)); + if (currentLevel > 0 && maxLevel > 0) return currentLevel >= maxLevel; + return value === levelOptions.value[levelOptions.value.length - 1]; +} + +function readLevelNumber(value: string) { + const match = value.match(/\d+/); + return match ? Number(match[0]) : 0; +} + +function getCoinCorrection(coinWan: number) { + if (coinWan > 53000) return 5; + if (coinWan > 38000) return 4; + if (coinWan > 23000) return 2.5; + if (coinWan > 13000) return 1; + return 0; +} + +function calculateRentDays(coinWan: number) { + if (coinWan >= 30000) return 7; + if (coinWan >= 10000) return 3; + return 1; } function readError(error: unknown, fallback: string) { @@ -562,7 +613,7 @@ function readError(error: unknown, fallback: string) {
-

资源道具

+

额外消耗品

@@ -588,7 +639,7 @@ function readError(error: unknown, fallback: string) {
-

价格结算

+

押金与价格

- - - - - - 计算价格 - -
- - -
diff --git a/frontend/src/views/public/HomeView.vue b/frontend/src/views/public/HomeView.vue index 2445e8c..df09f1b 100644 --- a/frontend/src/views/public/HomeView.vue +++ b/frontend/src/views/public/HomeView.vue @@ -16,7 +16,7 @@ import { type HomeBannerSlide, } from "@/api/homeConfig"; import { - defaultListingPublishOptions, + emptyListingPublishOptions, type ListingPublishOptions, } from "@/api/listingOptions"; import { fetchListings, type Listing } from "@/api/listings"; @@ -37,7 +37,7 @@ const loading = ref(false); const listings = ref([]); const announcements = ref(defaultHomeAnnouncements); const banners = ref(defaultHomeBanners); -const publishOptions = ref(defaultListingPublishOptions); +const publishOptions = ref(emptyListingPublishOptions); const filters = reactive({ keyword: "", server: "", @@ -131,7 +131,7 @@ async function loadHome() { } catch { announcements.value = defaultHomeAnnouncements; banners.value = defaultHomeBanners; - publishOptions.value = defaultListingPublishOptions; + publishOptions.value = emptyListingPublishOptions; } finally { loading.value = false; }