/* eslint-disable @typescript-eslint/no-explicit-any, react-hooks/exhaustive-deps, no-console */ 'use client'; import { ChevronRight } from 'lucide-react'; import Link from 'next/link'; import { Suspense, useEffect, useState } from 'react'; import { BangumiCalendarData, GetBangumiCalendarData, } from '@/lib/bangumi.client'; // 客户端收藏 API import { clearAllFavorites, getAllFavorites, getAllPlayRecords, subscribeToDataUpdates, } from '@/lib/db.client'; import { getDoubanCategories } from '@/lib/douban.client'; import { DoubanItem } from '@/lib/types'; import CapsuleSwitch from '@/components/CapsuleSwitch'; import ContinueWatching from '@/components/ContinueWatching'; import PageLayout from '@/components/PageLayout'; import { useThemeInit } from '@/hooks/useTheme'; import ScrollableRow from '@/components/ScrollableRow'; import { useSite } from '@/components/SiteProvider'; import VideoCard from '@/components/VideoCard'; function HomeClient() { const [activeTab, setActiveTab] = useState<'home' | 'favorites'>('home'); const [hotMovies, setHotMovies] = useState([]); const [hotTvShows, setHotTvShows] = useState([]); const [hotVarietyShows, setHotVarietyShows] = useState([]); const [bangumiCalendarData, setBangumiCalendarData] = useState< BangumiCalendarData[] >([]); const [loading, setLoading] = useState(true); const { announcement } = useSite(); const [showAnnouncement, setShowAnnouncement] = useState(false); // 检查公告弹窗状态 useEffect(() => { if (typeof window !== 'undefined' && announcement) { const hasSeenAnnouncement = localStorage.getItem('hasSeenAnnouncement'); if (hasSeenAnnouncement !== announcement) { setShowAnnouncement(true); } else { setShowAnnouncement(Boolean(!hasSeenAnnouncement && announcement)); } } }, [announcement]); // 收藏夹数据 type FavoriteItem = { id: string; source: string; title: string; poster: string; episodes: number; source_name: string; currentEpisode?: number; search_title?: string; origin?: 'vod' | 'live'; }; const [favoriteItems, setFavoriteItems] = useState([]); useEffect(() => { const fetchRecommendData = async () => { try { setLoading(true); // 并行获取热门电影、热门剧集和热门综艺 const [moviesData, tvShowsData, varietyShowsData, bangumiCalendarData] = await Promise.all([ getDoubanCategories({ kind: 'movie', category: '热门', type: '全部', }), getDoubanCategories({ kind: 'tv', category: 'tv', type: 'tv' }), getDoubanCategories({ kind: 'tv', category: 'show', type: 'show' }), GetBangumiCalendarData(), ]); if (moviesData.code === 200) { setHotMovies(moviesData.list); } if (tvShowsData.code === 200) { setHotTvShows(tvShowsData.list); } if (varietyShowsData.code === 200) { setHotVarietyShows(varietyShowsData.list); } setBangumiCalendarData(bangumiCalendarData); } catch (error) { console.error('获取推荐数据失败:', error); } finally { setLoading(false); } }; fetchRecommendData(); }, []); // 处理收藏数据更新的函数 const updateFavoriteItems = async (allFavorites: Record) => { const allPlayRecords = await getAllPlayRecords(); // 根据保存时间排序(从近到远) const sorted = Object.entries(allFavorites) .sort(([, a], [, b]) => b.save_time - a.save_time) .map(([key, fav]) => { const plusIndex = key.indexOf('+'); const source = key.slice(0, plusIndex); const id = key.slice(plusIndex + 1); // 查找对应的播放记录,获取当前集数 const playRecord = allPlayRecords[key]; const currentEpisode = playRecord?.index; return { id, source, title: fav.title, year: fav.year, poster: fav.cover, episodes: fav.total_episodes, source_name: fav.source_name, currentEpisode, search_title: fav?.search_title, origin: fav?.origin, } as FavoriteItem; }); setFavoriteItems(sorted); }; // 当切换到收藏夹时加载收藏数据 useEffect(() => { if (activeTab !== 'favorites') return; const loadFavorites = async () => { const allFavorites = await getAllFavorites(); await updateFavoriteItems(allFavorites); }; loadFavorites(); // 监听收藏更新事件 const unsubscribe = subscribeToDataUpdates( 'favoritesUpdated', (newFavorites: Record) => { updateFavoriteItems(newFavorites); } ); return unsubscribe; }, [activeTab]); const handleCloseAnnouncement = (announcement: string) => { setShowAnnouncement(false); localStorage.setItem('hasSeenAnnouncement', announcement); // 记录已查看弹窗 }; return (
{/* 顶部 Tab 切换 */}
setActiveTab(value as 'home' | 'favorites')} />
{activeTab === 'favorites' ? ( // 收藏夹视图

我的收藏

{favoriteItems.length > 0 && ( )}
{favoriteItems.map((item) => (
1 ? 'tv' : ''} />
))} {favoriteItems.length === 0 && (
暂无收藏内容
)}
) : ( // 首页视图 <> {/* 继续观看 */} {/* 热门电影 */}

热门电影

查看更多
{loading ? // 加载状态显示灰色占位数据 Array.from({ length: 8 }).map((_, index) => (
)) : // 显示真实数据 hotMovies.map((movie, index) => (
))}
{/* 热门剧集 */}

热门剧集

查看更多
{loading ? // 加载状态显示灰色占位数据 Array.from({ length: 8 }).map((_, index) => (
)) : // 显示真实数据 hotTvShows.map((show, index) => (
))}
{/* 每日新番放送 */}

新番放送

查看更多
{loading ? // 加载状态显示灰色占位数据 Array.from({ length: 8 }).map((_, index) => (
)) : // 展示当前日期的番剧 (() => { // 获取当前日期对应的星期 const today = new Date(); const weekdays = [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', ]; const currentWeekday = weekdays[today.getDay()]; // 找到当前星期对应的番剧数据 const todayAnimes = bangumiCalendarData.find( (item) => item.weekday.en === currentWeekday )?.items || []; return todayAnimes.map((anime, index) => (
)); })()}
{/* 热门综艺 */}

热门综艺

查看更多
{loading ? // 加载状态显示灰色占位数据 Array.from({ length: 8 }).map((_, index) => (
)) : // 显示真实数据 hotVarietyShows.map((show, index) => (
))}
)}
{announcement && showAnnouncement && (
{ // 如果点击的是背景区域,阻止触摸事件冒泡,防止背景滚动 if (e.target === e.currentTarget) { e.preventDefault(); } }} onTouchMove={(e) => { // 如果触摸的是背景区域,阻止触摸移动,防止背景滚动 if (e.target === e.currentTarget) { e.preventDefault(); e.stopPropagation(); } }} onTouchEnd={(e) => { // 如果触摸的是背景区域,阻止触摸结束事件,防止背景滚动 if (e.target === e.currentTarget) { e.preventDefault(); } }} style={{ touchAction: 'none', // 禁用所有触摸操作 }} >
{ // 允许公告内容区域正常滚动,阻止事件冒泡到外层 e.stopPropagation(); }} style={{ touchAction: 'auto', // 允许内容区域的正常触摸操作 }} >

提示

{announcement}

)}
); } export default function Home() { // 初始化主题 useThemeInit(); return ( ); }