125 lines
4.0 KiB
TypeScript
125 lines
4.0 KiB
TypeScript
import type { Listing } from '@/api/listings'
|
|
import {
|
|
assetRegions,
|
|
formatHafCoinM,
|
|
getCoinWan,
|
|
getListingResources,
|
|
getListingTitle,
|
|
getOnlineTimeText,
|
|
hasAcceleratedSaleRatio,
|
|
hasGiftResources,
|
|
readAssetNumber,
|
|
readAssetString,
|
|
} from '@/views/mobile/listingDisplay'
|
|
|
|
export interface AdminListingPricing {
|
|
buyerDaily: number
|
|
sellerDaily: number
|
|
sellerRatio: number
|
|
buyerRatio: number
|
|
platformMarkup: number
|
|
}
|
|
|
|
export function ownerName(row: Listing) {
|
|
return row.owner_phone || row.owner_nickname || `号主 ${row.owner_id}`
|
|
}
|
|
|
|
export function listingDisplayTitle(row: Listing) {
|
|
return getListingTitle(row) || row.title
|
|
}
|
|
|
|
export function formatMoney(value: number) {
|
|
return `¥${Number(value || 0).toFixed(2)}`
|
|
}
|
|
|
|
export function getAdminListingPricing(row: Listing): AdminListingPricing {
|
|
const breakdown = readBreakdown(row)
|
|
const buyerDaily = readBreakdownNumber(breakdown, 'buyer_total_price') || Number(row.price_daily || row.price_hourly || 0)
|
|
const sellerDaily = readBreakdownNumber(breakdown, 'seller_total_price') || buyerDaily
|
|
return {
|
|
buyerDaily,
|
|
sellerDaily,
|
|
sellerRatio: readBreakdownNumber(breakdown, 'seller_ratio'),
|
|
buyerRatio: readBreakdownNumber(breakdown, 'buyer_ratio') || readAssetNumber(row, 'publish_ratio'),
|
|
platformMarkup: readBreakdownNumber(breakdown, 'platform_markup_amount'),
|
|
}
|
|
}
|
|
|
|
export function listingBuyerPrice(row: Listing) {
|
|
return formatMoney(getAdminListingPricing(row).buyerDaily)
|
|
}
|
|
|
|
export function listingSellerPrice(row: Listing) {
|
|
return formatMoney(getAdminListingPricing(row).sellerDaily)
|
|
}
|
|
|
|
export function formatRatio(value: number) {
|
|
if (!Number.isFinite(value) || value <= 0) return '-'
|
|
const rounded = Math.round(value * 100) / 100
|
|
return `1:${Number.isInteger(rounded) ? rounded : rounded.toFixed(2)}`
|
|
}
|
|
|
|
export function listingAssetTags(row: Listing) {
|
|
return [
|
|
`哈夫币:${formatHafCoinM(getCoinWan(row))}`,
|
|
tagValue('保险', readAssetString(row, 'season_insurance')),
|
|
tagValue('体力', readAssetString(row, 'stamina_level')),
|
|
tagValue('负重', readAssetString(row, 'load_level')),
|
|
tagValue('段位', row.rank_level),
|
|
tagValue('日损', formatDailyLoss(row)),
|
|
tagValue('烽火', readAssetNumber(row, 'fire_level') || ''),
|
|
tagValue('KD', readAssetString(row, 'secret_kd')),
|
|
].filter(Boolean)
|
|
}
|
|
|
|
export function listingRiskTags(row: Listing) {
|
|
return [
|
|
tagValue('人脸', readAssetString(row, 'face_owner')),
|
|
tagValue('封禁', readAssetString(row, 'ban_record')),
|
|
tagValue('地区', assetRegions(row).join('/')),
|
|
tagValue('在线', getOnlineTimeText(row)),
|
|
].filter(Boolean)
|
|
}
|
|
|
|
export function listingResourceTags(row: Listing, limit = 4) {
|
|
const resources = getListingResources(row).map((resource) => {
|
|
const mode = resource.mode === '赠送' ? '赠送' : '收费'
|
|
return `${resource.label}:${resource.quantity}${mode === '赠送' ? '(赠)' : ''}`
|
|
})
|
|
if (resources.length <= limit) return resources
|
|
return [...resources.slice(0, limit), `+${resources.length - limit}项`]
|
|
}
|
|
|
|
export function listingBadgeTags(row: Listing) {
|
|
return [
|
|
hasAcceleratedSaleRatio(row) ? '特惠' : '',
|
|
hasGiftResources(row) ? '有赠送' : '',
|
|
].filter(Boolean)
|
|
}
|
|
|
|
function formatDailyLoss(row: Listing) {
|
|
const value = readAssetNumber(row, 'daily_loss_m')
|
|
return value > 0 ? `${value}M/天` : ''
|
|
}
|
|
|
|
function tagValue(label: string, value: string | number) {
|
|
const text = String(value || '').trim()
|
|
return text ? `${label}:${text}` : ''
|
|
}
|
|
|
|
function readBreakdown(row: Listing) {
|
|
const breakdown = row.asset_summary?.price_breakdown
|
|
return typeof breakdown === 'object' && breakdown !== null ? (breakdown as Record<string, unknown>) : null
|
|
}
|
|
|
|
function readBreakdownNumber(row: Record<string, unknown> | null, key: string) {
|
|
if (!row) return 0
|
|
const value = row[key]
|
|
if (typeof value === 'number') return Number.isFinite(value) ? value : 0
|
|
if (typeof value === 'string' && value.trim()) {
|
|
const parsed = Number(value)
|
|
return Number.isFinite(parsed) ? parsed : 0
|
|
}
|
|
return 0
|
|
}
|