import { Heart, Link as LinkIcon } from 'lucide-react'; import Image from 'next/image'; import Link from 'next/link'; import { useRouter } from 'next/navigation'; import React, { useEffect, useState } from 'react'; import { deletePlayRecord, isFavorited, toggleFavorite } from '@/lib/db.client'; import { ImagePlaceholder } from '@/components/ImagePlaceholder'; interface VideoCardProps { id: string; source: string; title: string; poster: string; episodes?: number; source_name: string; progress?: number; year?: string; from?: string; currentEpisode?: number; douban_id?: number; onDelete?: () => void; } function CheckCircleCustom() { return ( ); } function PlayCircleSolid({ className = '', fillColor = 'none', }: { className?: string; fillColor?: string; }) { return ( ); } export default function VideoCard({ id, title, poster, episodes, source, source_name, progress, year, from, currentEpisode, douban_id, onDelete, }: VideoCardProps) { const [playHover, setPlayHover] = useState(false); const [favorited, setFavorited] = useState(false); const [isLoaded, setIsLoaded] = useState(false); const [isDeleting, setIsDeleting] = useState(false); const router = useRouter(); // 检查初始收藏状态 useEffect(() => { (async () => { try { const fav = await isFavorited(source, id); setFavorited(fav); } catch (err) { throw new Error('检查收藏状态失败'); } })(); }, [source, id]); // 切换收藏状态 const handleToggleFavorite = async ( e: React.MouseEvent ) => { e.preventDefault(); e.stopPropagation(); try { const newState = await toggleFavorite(source, id, { title, source_name, year: year || '', cover: poster, total_episodes: episodes ?? 1, save_time: Date.now(), }); setFavorited(newState); } catch (err) { // 如果删除失败且是收藏夹,恢复显示 if (isDeleting) { setIsDeleting(false); } throw new Error('切换收藏状态失败'); } }; // 删除对应播放记录 const handleDeleteRecord = async ( e: React.MouseEvent ) => { e.preventDefault(); e.stopPropagation(); try { await deletePlayRecord(source, id); onDelete?.(); } catch (err) { throw new Error('删除播放记录失败'); } }; const hideCheckCircle = from === 'favorites' || from === 'search'; const alwaysShowHeart = from !== 'favorites'; return (
{/* 海报图片容器 */}
{/* 图片占位符 - 骨架屏效果 */} {title} setIsLoaded(true)} referrerPolicy='no-referrer' priority={false} /> {/* Hover 效果层 */}
{/* 播放按钮 */}
{ e.preventDefault(); e.stopPropagation(); router.push( `/play?source=${source}&id=${id}&title=${encodeURIComponent( title )}${year ? `&year=${year}` : ''}` ); }} onMouseEnter={() => setPlayHover(true)} onMouseLeave={() => setPlayHover(false)} >
{/* 右侧操作按钮组 */}
{!hideCheckCircle && ( )}
{/* 继续观看 - 集数矩形展示框 */} {episodes && episodes > 1 && currentEpisode && (
{currentEpisode} / {episodes}
)} {/* 搜索非聚合 - 集数圆形展示框 */} {episodes && episodes > 1 && !currentEpisode && (
{episodes}
)} {/* 豆瓣链接按钮 */} {douban_id && from === 'search' && ( e.stopPropagation()} className='absolute top-2 left-2 scale-90 group-hover:scale-100 opacity-0 group-hover:opacity-100 transition-all duration-300 cubic-bezier(0.4,0,0.2,1)' >
)}
{/* 播放进度条 - 移至图片容器外部,标题上方 */} {progress !== undefined && (
)} {/* 信息层 */} {title} {/* 来源信息 */} {source && ( {source_name} )}
); }