feat(listings): 商品列表展示在线时间

This commit is contained in:
2026-11-12 12:07:49 +08:00
parent 58d9f50bac
commit 3337a3b814
3 changed files with 26 additions and 0 deletions
@@ -27,6 +27,7 @@ import { Link } from 'react-router-dom'
import { BrandLogo } from '@/components/BrandLogo'
import { HomePortalRow } from '@/features/home/HomePortalRow'
import { useListings } from '@/features/listings/api'
import { onlineTimeText } from '@/features/listings/labels'
import {
awmRanges,
coinRanges,
@@ -138,6 +139,7 @@ function ListingRow({ item }: { item: Listing }) {
{ label: '段位', value: item.rank_level },
{ label: '登录', value: item.login_platform },
{ label: '区服', value: item.server_region },
{ label: '在线', value: onlineTimeText(item.asset_summary) },
{ label: '折算比', value: ratioText(item) ? `1元≈${ratioText(item)}` : '' },
].filter(spec => spec.value)
const skins = skinNames(item)
@@ -227,6 +229,7 @@ function ListingGridCover({ item }: { item: Listing }) {
}
function ListingGridCard({ item }: { item: Listing }) {
const online = onlineTimeText(item.asset_summary)
return (
<Link to={`/listings/${item.id}`} className="listing-card-link">
<Card className="listing-card" hoverable cover={<ListingGridCover item={item} />}>
@@ -243,6 +246,7 @@ function ListingGridCard({ item }: { item: Listing }) {
<Tag bordered={false}>{item.server_region || '区服待定'}</Tag>
<Tag bordered={false}>{item.login_platform || '登录方式待定'}</Tag>
{item.rank_level ? <Tag bordered={false}>{item.rank_level}</Tag> : null}
{online ? <Tag bordered={false}>在线 {online}</Tag> : null}
</div>
<div className="listing-card__meta">
<span>哈夫币 {formatCoinM(item.haf_coin_amount)}</span>
+19
View File
@@ -64,6 +64,25 @@ function formatOnlineTime(value: unknown) {
return `${start || '—'} 至 ${end || '—'}`
}
/**
* 商品在线时段的统一展示文案,格式与原详情页保持一致(start - end)。
* 空值返回空字符串,由调用方决定是否隐藏或替换为占位符。
*/
export function onlineTimeText(summary?: Record<string, unknown> | null): string {
if (!summary || typeof summary !== 'object') return ''
const value = summary.online_time
if (typeof value === 'string') return value.trim()
if (!value || typeof value !== 'object') return ''
const item = value as { start?: unknown; end?: unknown }
const start = typeof item.start === 'string' ? item.start.trim() : ''
const end = typeof item.end === 'string' ? item.end.trim() : ''
if (!start && !end) return ''
if (start === end) return start
return `${start} - ${end}`
}
export function formatAssetValue(key: string, value: unknown): string {
if (value == null || value === '') return '—'
if (key === 'online_time') {
@@ -15,6 +15,7 @@ import { Link } from 'react-router-dom'
import { BrandLogo } from '@/components/BrandLogo'
import { useListings } from '@/features/listings/api'
import { onlineTimeText } from '@/features/listings/labels'
import {
coinRanges,
emptyListingFilters,
@@ -88,10 +89,12 @@ function MobileChipGroup({
}
function MobileListingCard({ item }: { item: Listing }) {
const online = onlineTimeText(item.asset_summary)
const specs = [
assetText(item, 'season_insurance') ? `保险 ${assetText(item, 'season_insurance')}` : '',
assetText(item, 'stamina_level') ? `体力 ${assetText(item, 'stamina_level')}` : '',
assetText(item, 'load_level') ? `负重 ${assetText(item, 'load_level')}` : '',
online ? `在线 ${online}` : '',
].filter(Boolean)
return (