Files
hfb_sys/frontend/src/views/mobile/mobileHomeFallback.ts
T
2026-05-23 01:24:05 +08:00

178 lines
6.3 KiB
TypeScript

import {
defaultListingPublishOptions,
type ListingPublishOptions,
} from "@/api/listingOptions";
import type { Listing } from "@/api/listings";
const fallbackRegionOptions = ["广东", "上海", "江苏", "四川", "北京", "浙江"];
const coinWanOptions = [
1800, 3200, 5800, 9600, 12000, 18000, 26000, 36000, 52000, 68000,
];
const depositOptions = [60, 80, 100, 120, 160, 200];
const secretKdOptions = [1.2, 1.6, 2.1, 2.8, 3.4, 4.2];
const onlineWindows = [
["09:00", "23:30"],
["10:30", "01:00"],
["12:00", "24:00"],
["18:00", "02:00"],
] as const;
const resourceQuantityPresets: Record<string, number[]> = {
awmAmmo: [0, 20, 48, 80, 120, 180],
helmet6: [0, 2, 4, 6, 10, 16],
armor6: [0, 1, 3, 5, 8, 12],
kit5: [0, 3, 6, 10, 15, 24],
level6Ammo: [0, 120, 240, 360, 520, 800],
gridCard9: [0, 1, 2, 4, 6, 10],
};
function pick<T>(items: readonly T[], index: number, fallback: T): T {
if (!items.length) return fallback;
return items[index % items.length] ?? fallback;
}
function pickMany(items: string[], start: number, count: number) {
if (!items.length) return [];
const fallback = items[0] || "";
return Array.from({ length: Math.min(count, items.length) }, (_, idx) =>
pick(items, start + idx, fallback)
).filter(Boolean);
}
function buildResources(options: ListingPublishOptions, seed: number) {
return options.quantity_items.map((item, index) => ({
key: item.key,
label: item.label,
quantity: pick(
resourceQuantityPresets[item.key] || [0, 1, 3, 6],
seed + index,
0
),
mode: "收费",
}));
}
function buildSkinGroups(options: ListingPublishOptions, seed: number) {
return options.skin_groups.reduce<Record<string, string[]>>((groups, group, index) => {
const count = group.key === "melee" ? 2 : index % 2 === 0 ? 3 : 2;
groups[group.key] = pickMany(group.options, seed + index * 2, count);
return groups;
}, {});
}
function buildScreenshotMap(options: ListingPublishOptions, seed: number) {
return options.screenshot_slots.reduce<Record<string, string>>((screenshots, slot, index) => {
screenshots[slot.key] = `https://picsum.photos/seed/hfb-${slot.key}-${seed + index}/960/540`;
return screenshots;
}, {});
}
function flattenSkinGroups(groups: Record<string, string[]>) {
return Object.values(groups).flat();
}
function calculateRentDays(coinWan: number) {
return coinWan >= 30000 ? 7 : coinWan >= 10000 ? 3 : 1;
}
function calculateDailyLoss(coinWan: number) {
return coinWan >= 30000 ? "30M" : coinWan >= 10000 ? "20M" : "10M";
}
function roundMoney(value: number) {
return Math.round(value * 100) / 100;
}
function formatHafCoinM(coinWan: number) {
const coinM = Math.round((coinWan / 100) * 10) / 10;
return `${Number.isInteger(coinM) ? coinM : coinM.toFixed(1)}M`;
}
export function buildFallbackListings(
options: ListingPublishOptions = defaultListingPublishOptions
): Listing[] {
return Array.from({ length: 10 }, (_, index) => {
const seed = index + 1;
const server = pick(options.server_options, index, "QQ");
const loginMethod = pick(options.login_method_options, index + 1, "账号密码");
const rank = pick(options.rank_options, index + 3, "钻石");
const insurance = pick(options.insurance_options, index + 1, "2*2");
const stamina = pick(options.level_options, index + 4, "5级");
const load = pick(options.level_options, index + 5, "5级");
const faceOwner = pick(options.face_options, index, "是");
const coinWan = pick(coinWanOptions, index, 12000);
const ratio = 5 + (index % 4);
const rentDays = calculateRentDays(coinWan);
const finalPrice = roundMoney(coinWan / ratio);
const settlementAmount = finalPrice;
const dailyPrice = roundMoney(finalPrice / rentDays);
const hourlyPrice = Math.max(roundMoney(dailyPrice / 24), 0.01);
const deposit = pick(depositOptions, index, 100);
const skinGroups = buildSkinGroups(options, seed);
const screenshots = buildScreenshotMap(options, seed);
const commonRegions = pickMany(
options.region_options.length ? options.region_options : fallbackRegionOptions,
index * 2,
2
);
const [onlineStart, onlineEnd] = pick(onlineWindows, index, onlineWindows[0]);
return {
id: 9100 + seed,
account_id: 0,
owner_id: 0,
title: `${server} ${rank} ${formatHafCoinM(coinWan)}哈夫币`,
description: `${loginMethod}交接,${insurance}保险,体力${stamina}、负重${load},示例数据按发布表单随机生成。`,
game_name: "三角洲行动",
server_region: server,
login_platform: loginMethod,
rank_level: rank,
haf_coin_amount: coinWan * 10000,
asset_summary: {
face_owner: faceOwner,
haf_coin_wan: coinWan,
total_asset_wan: Math.round(coinWan * (1.08 + (index % 4) * 0.04)),
secret_kd: pick(secretKdOptions, index, 1.6),
fire_level: 38 + seed * 3,
season_insurance: insurance,
stamina_level: stamina,
load_level: load,
daily_loss: calculateDailyLoss(coinWan),
ratio,
login_method: loginMethod,
common_regions: commonRegions,
resources: buildResources(options, seed),
skins: flattenSkinGroups(skinGroups),
skin_groups: skinGroups,
online_time: {
start: onlineStart,
end: onlineEnd,
},
ban_record: index % 4 === 0 ? "无封禁记录,近期登录稳定" : "",
screenshots,
deposit_amount: deposit,
price: finalPrice,
settlement_amount: settlementAmount,
rent_days: rentDays,
remark:
index % 3 === 0
? "部分仓库材料请勿使用,下单后会在群聊再次提醒。"
: "",
},
screenshot_urls: Object.values(screenshots),
price_hourly: hourlyPrice,
price_daily: dailyPrice,
price_weekly: Math.round(dailyPrice * 7 * 10) / 10,
deposit_amount: deposit,
min_rent_hours: coinWan >= 10000 ? 24 : 8,
max_rent_hours: coinWan >= 30000 ? 168 : 72,
status: "published",
review_status: "approved",
review_reason: "",
published_at: new Date(Date.now() - seed * 18 * 60 * 1000).toISOString(),
created_at: new Date(Date.now() - seed * 20 * 60 * 1000).toISOString(),
updated_at: new Date(Date.now() - seed * 10 * 60 * 1000).toISOString(),
};
});
}