84 lines
2.9 KiB
TypeScript
84 lines
2.9 KiB
TypeScript
'use client'
|
||
|
||
import { formatNumberToKMB } from '@/lib/utils'
|
||
import Image from 'next/image'
|
||
import { AiChatRankOutput, AiHeartbeatRankOutput, AiGiftRankOutput } from '@/services/home/types'
|
||
import { RankType } from '@/types/global'
|
||
import Link from 'next/link'
|
||
|
||
interface SmallRankCardProps {
|
||
item: AiChatRankOutput | AiHeartbeatRankOutput | AiGiftRankOutput
|
||
rankType: RankType
|
||
rank?: number // 用于显示排名,如果不传则使用item.rankNo
|
||
}
|
||
|
||
export default function SmallRankCard({ item, rankType, rank }: SmallRankCardProps) {
|
||
// 根据排行榜类型获取对应的数值显示
|
||
const getDisplayValue = () => {
|
||
switch (rankType) {
|
||
case RankType.CHAT:
|
||
return formatNumberToKMB((item as AiChatRankOutput).chatNum || 0)
|
||
case RankType.CRUSH:
|
||
return `${(item as AiHeartbeatRankOutput).heartbeatValTotal || 0}℃`
|
||
case RankType.GIFTS:
|
||
return formatNumberToKMB(Math.floor(((item as AiGiftRankOutput).giftCoinNum || 0) / 100))
|
||
default:
|
||
return '0'
|
||
}
|
||
}
|
||
|
||
// 根据排行榜类型获取对应的图标
|
||
const getIcon = () => {
|
||
switch (rankType) {
|
||
case RankType.CHAT:
|
||
return <i className="iconfont icon-Chat !text-[12px]" />
|
||
case RankType.CRUSH:
|
||
return <Image src="/icons/icon-crush.svg" alt="" width={12} height={12} />
|
||
case RankType.GIFTS:
|
||
return <Image src="/icons/diamond.svg" alt="" width={12} height={12} />
|
||
default:
|
||
return <i className="iconfont icon-Chat !text-[12px]" />
|
||
}
|
||
}
|
||
|
||
if (!item) {
|
||
return <div className="flex-1 py-12"></div>
|
||
}
|
||
|
||
const imageUrl = item.homeImageUrl || ''
|
||
const rankNo = rank || item.rankNo || 1
|
||
|
||
return (
|
||
<Link href={`/chat/${item.aiId}`} prefetch={false} key={item.aiId} className="flex-1">
|
||
<div className="flex-1 py-12">
|
||
<div className="relative aspect-[240/360] w-full overflow-hidden rounded-b-lg">
|
||
<div
|
||
className="absolute inset-0"
|
||
style={{
|
||
background: `url(${imageUrl}) #211a2b 50% / cover no-repeat`,
|
||
maskImage: 'linear-gradient(180deg, rgba(255, 255, 255, 0.00) 0%, #FFF 55%)',
|
||
}}
|
||
/>
|
||
<div className="absolute right-0 bottom-0 left-0 aspect-[240/112]">
|
||
<Image
|
||
src={`/images/leaderboard/${rankNo}-st.svg`}
|
||
alt=""
|
||
fill
|
||
className="object-cover"
|
||
/>
|
||
</div>
|
||
<div className="absolute inset-0">
|
||
<div className="absolute right-0 bottom-[44] left-0 flex items-center justify-center gap-1">
|
||
{getIcon()}
|
||
<div className="txt-numMonotype-s">{getDisplayValue()}</div>
|
||
</div>
|
||
<div className="txt-numDisplay-m absolute right-0 bottom-1 left-0 text-center">
|
||
{rankNo === 2 ? '2nd' : '3rd'}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</Link>
|
||
)
|
||
}
|