"use client"; import Link from "next/link"; import { TrendingUp, AlertTriangle } from "lucide-react"; import type { Artist } from "@/types/artist"; import ArtistPortrait from "@/components/cards/ArtistPortrait"; import { cn } from "@/lib/cn"; interface RankingRowProps { artist: Artist; /** 与上一名差距(票数) */ gapAbove?: number; /** 与出道线差距(票数):候补区第一位用于"差 X 票进出道位" */ gapToDebut?: number; /** 是否为出道线下第一位 */ isRescue?: boolean; onVote: (a: Artist) => void; } function formatVotes(v: number): string { if (v >= 10_000) return `${(v / 10_000).toFixed(1)}w`; return v.toLocaleString(); } export default function RankingRow({ artist, gapAbove, gapToDebut, isRescue = false, onVote, }: RankingRowProps) { // 「真正进 Top12」必须有票 —— 0 票时编号兜底不算 const inTop12 = artist.rank <= 12 && artist.votes > 0; return (
{/* 排名 */}
#{artist.rank}
{/* 头像 */}
{/* 姓名 + slogan */}
{artist.name} · {artist.enName}
{/* 票数 */}
{formatVotes(artist.votes)}
{/* 距上一名 / 差出道线 */}
{isRescue && gapToDebut != null ? (
+{gapToDebut.toLocaleString()}
) : gapAbove != null && artist.rank > 1 ? (
−{gapAbove.toLocaleString()}
) : ( )}
{/* 投票按钮(统一紫色实心) */}
); }