'use client'; import { memo } from 'react'; import Link from 'next/link'; import Image from 'next/image'; import { Card } from '@/components/ui/Card'; import { Badge } from '@/components/ui/Badge'; import { Icons } from '@/components/ui/Icon'; import { LatencyBadge } from '@/components/ui/LatencyBadge'; import { FavoriteButton } from '@/components/favorites/FavoriteButton'; import { Video } from '@/lib/types'; import { parseVideoTitle } from '@/lib/utils/video'; import type { ResolutionInfo } from '@/lib/hooks/useResolutionProbe'; interface VideoCardProps { video: Video; videoUrl: string; cardId: string; isActive: boolean; onCardClick: (e: React.MouseEvent, cardId: string, videoUrl: string) => void; isPremium?: boolean; latencies?: Record; resolution?: ResolutionInfo | null; isProbing?: boolean; } export const VideoCard = memo(({ video, videoUrl, cardId, isActive, onCardClick, isPremium = false, latencies = {}, resolution, isProbing = false, }) => { const displayLatency = latencies[video.source] ?? video.latency; return (
(e.currentTarget.style.zIndex = '100')} onMouseLeave={(e) => (e.currentTarget.style.zIndex = '1')} > onCardClick(e, cardId, videoUrl)} role="listitem" aria-label={`${video.vod_name}${video.vod_remarks ? ` - ${video.vod_remarks}` : ''}`} prefetch={false} data-focusable className="group cursor-pointer hover:translate-y-[-2px] transition-transform duration-200 ease-out block h-full" > {/* Poster */}
{video.vod_pic ? ( {video.vod_name} { const target = e.currentTarget as HTMLImageElement; if (target.dataset.fallback === '1') { target.style.opacity = '0'; return; } target.dataset.fallback = '1'; target.src = '/placeholder-poster.svg'; }} /> ) : ( {video.vod_name} )} {/* Fallback Icon - visible when image fails completely */}
{video.vod_name}
{/* Badge Container */}
{video.sourceName && ( {video.sourceName} )}
{/* Favorite Button - Top Right */}
{/* Overlay */}
{isActive && (
再次点击播放 →
)} {video.type_name && ( {video.type_name} )} {video.vod_year && (
{video.vod_year}
)}
{/* Info */}
{(() => { const { cleanTitle } = parseVideoTitle(video.vod_name); return ( <>

{cleanTitle}

{resolution ? ( {resolution.label} ) : isProbing ? ( ... ) : null} {displayLatency !== undefined && ( )}
{video.vod_lang && (

{video.vod_lang}

)} ); })()}
); }); VideoCard.displayName = 'VideoCard';