Files
hfb_sys/frontend/src/views/admin/listingAdminDisplay.ts
T
2026-05-24 01:01:04 +08:00

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
}