import { Card } from "@/components/ui/card"; import { Progress } from "@/components/ui/progress"; import { formatDateTime } from "@/components/SearchResults"; import { addHoursToNow, formatHours } from "../song/[id]/info"; import { milestoneConfig, type CloseMilestoneInfo, type MilestoneType } from "./Milestone"; import { DAY, HOUR, MINUTE, SECOND } from "@core/lib"; function timeAgo(timeStamp: Date | number, now: Date | number = Date.now()): string { const pastTime = typeof timeStamp === "number" ? timeStamp : timeStamp.getTime(); const currentTime = typeof now === "number" ? now : now.getTime(); const diffMs = Math.abs(currentTime - pastTime); if (diffMs < MINUTE) { const seconds = Math.floor(diffMs / SECOND); return `${seconds} 秒`; } if (diffMs < HOUR) { const minutes = Math.floor(diffMs / MINUTE); if (diffMs % MINUTE === 0) { return `${minutes} 分钟`; } return `${minutes} 分钟`; } if (diffMs < DAY) { const hours = Math.floor(diffMs / HOUR); const minutes = Math.floor((diffMs % HOUR) / MINUTE); return `${hours} 时 ${minutes} 分`; } if (diffMs >= DAY) { const days = Math.floor(diffMs / DAY); const hours = Math.floor((diffMs % DAY) / HOUR); return `${days} 天 ${hours} 时`; } return "刚刚"; } export const MilestoneVideoCard = ({ video, milestoneType, }: { video: NonNullable[number]; milestoneType: MilestoneType; }) => { const config = milestoneConfig[milestoneType]; const remainingViews = config.target - video.eta.currentViews; const progressPercentage = (video.eta.currentViews / config.target) * 100; return (
{video.bilibili_metadata.coverUrl && ( 视频封面 )}

{video.bilibili_metadata.title}

当前播放: {video.eta.currentViews.toLocaleString()} 目标: {config.target.toLocaleString()}

剩余播放: {remainingViews.toLocaleString()}

预计达成: {formatHours(video.eta.eta)}

播放速度: {Math.round(video.eta.speed)}/小时

达成时间: {addHoursToNow(video.eta.eta)}

{video.bilibili_metadata.publishedAt && ( 发布于 {formatDateTime(new Date(video.bilibili_metadata.publishedAt))} )} 数据更新于 {timeAgo(new Date(video.eta.updatedAt))}前 观看视频 查看详情
); };