"use client"; import { useMemo, useState } from "react"; import { Sparkles } from "lucide-react"; import Top3Podium from "@/components/ranking/Top3Podium"; import RankingRow from "@/components/ranking/RankingRow"; import DebutLineDivider from "@/components/ranking/DebutLineDivider"; import VoteModal from "@/components/VoteModal"; import Countdown from "@/components/ui/Countdown"; import { ARTISTS, getActivityEndTime, sortArtists } from "@/lib/mock-data"; import type { Artist } from "@/types/artist"; export default function RankingPage() { const [voteTarget, setVoteTarget] = useState(null); const sorted = useMemo(() => sortArtists(ARTISTS, "votes"), []); const endTime = useMemo(() => getActivityEndTime(), []); const top3 = sorted.slice(0, 3); const top4to12 = sorted.slice(3, 12); const candidates = sorted.slice(12); // 计算 #13 与第 12 名的差距,用于"救援投票" const debutCutoff = sorted[11]?.votes ?? 0; const handleVote = async (a: Artist, count: number) => { await new Promise((r) => setTimeout(r, 400)); console.log(`Vote: ${a.name} × ${count}`); setVoteTarget(null); }; return ( <>
{/* 头部 */}

Live Ranking · 2026

Top 35

35 位候选人 · 实时排名

{/* Top3 领奖台 */} {/* Top 4-12 标题 */}

出道位 · Top 4 ~ 12

{/* 表头 */}
排名 头像 艺人 票数 距上一名 操作
{/* Top4-12 行 */}
{top4to12.map((a, idx) => { const prev = idx === 0 ? top3[2] : top4to12[idx - 1]; const gap = prev ? prev.votes - a.votes : undefined; return ( ); })}
{/* 出道线 */} {/* 候补区 */}
{candidates.map((a, idx) => { const prev = idx === 0 ? top4to12[top4to12.length - 1] : candidates[idx - 1]; const gap = prev ? prev.votes - a.votes : undefined; const isRescue = idx === 0; // 第 13 位 const gapToDebut = isRescue ? debutCutoff - a.votes + 1 : undefined; return ( ); })}
{/* 底部提示 */}

排名每分钟更新一次 · 投票后立即生效

setVoteTarget(null)} onConfirm={handleVote} /> ); }