/* eslint-disable @typescript-eslint/no-explicit-any, react-hooks/exhaustive-deps, no-console */ 'use client'; import { Bot, ChevronRight, Link as LinkIcon, ListVideo, Music } from 'lucide-react'; import Link from 'next/link'; import { useRouter } from 'next/navigation'; import { Suspense, useEffect, useState } from 'react'; import { BangumiCalendarData, GetBangumiCalendarData, } from '@/lib/bangumi.client'; import { getDoubanCategories } from '@/lib/douban.client'; import { getTMDBImageUrl, TMDBItem } from '@/lib/tmdb.client'; import { DoubanItem } from '@/lib/types'; import { base58Encode, processImageUrl } from '@/lib/utils'; import AIChatPanel from '@/components/AIChatPanel'; import BannerCarousel from '@/components/BannerCarousel'; import ContinueWatching from '@/components/ContinueWatching'; import FireworksCanvas from '@/components/FireworksCanvas'; import HttpWarningDialog from '@/components/HttpWarningDialog'; import PageLayout from '@/components/PageLayout'; import ScrollableRow from '@/components/ScrollableRow'; import { useSite } from '@/components/SiteProvider'; import VideoCard from '@/components/VideoCard'; // 首页模块配置接口 interface HomeModule { id: string; name: string; enabled: boolean; order: number; } function HomeClient() { // 移除了 activeTab 状态,收藏夹功能已移到 UserMenu const [hotMovies, setHotMovies] = useState([]); const [hotTvShows, setHotTvShows] = useState([]); const [hotVarietyShows, setHotVarietyShows] = useState([]); const [hotDuanju, setHotDuanju] = useState([]); const [upcomingContent, setUpcomingContent] = useState([]); const [bangumiCalendarData, setBangumiCalendarData] = useState< BangumiCalendarData[] >([]); const [loading, setLoading] = useState(true); const { announcement } = useSite(); const router = useRouter(); // 首页模块配置状态 const [homeModules, setHomeModules] = useState([ { id: 'hotMovies', name: '热门电影', enabled: true, order: 0 }, { id: 'hotDuanju', name: '热播短剧', enabled: true, order: 1 }, { id: 'bangumiCalendar', name: '新番放送', enabled: true, order: 2 }, { id: 'hotTvShows', name: '热门剧集', enabled: true, order: 3 }, { id: 'hotVarietyShows', name: '热门综艺', enabled: true, order: 4 }, { id: 'upcomingContent', name: '即将上映', enabled: true, order: 5 }, ]); const [homeBannerEnabled, setHomeBannerEnabled] = useState(true); const [homeContinueWatchingEnabled, setHomeContinueWatchingEnabled] = useState(true); const [showAnnouncement, setShowAnnouncement] = useState(false); const [showHttpWarning, setShowHttpWarning] = useState(true); const [showAIChat, setShowAIChat] = useState(false); const [aiEnabled, setAiEnabled] = useState(false); const [aiDefaultMessageNoVideo, setAiDefaultMessageNoVideo] = useState('你好!我是MoonTVPlus的AI影视助手。想看什么电影或剧集?需要推荐吗?'); const [sourceSearchEnabled, setSourceSearchEnabled] = useState(true); const [musicEnabled, setMusicEnabled] = useState(false); const [showDirectPlayDialog, setShowDirectPlayDialog] = useState(false); const [directPlayUrl, setDirectPlayUrl] = useState(''); const handleDirectPlay = () => { setDirectPlayUrl(''); setShowDirectPlayDialog(true); }; const submitDirectPlay = () => { const trimmed = directPlayUrl.trim(); if (!trimmed) return; const encoded = base58Encode(trimmed); if (!encoded) return; setShowDirectPlayDialog(false); setDirectPlayUrl(''); router.push(`/play?source=directplay&id=${encodeURIComponent(encoded)}`); }; const loadHomeLayoutSettings = () => { if (typeof window === 'undefined') return; const savedHomeModules = localStorage.getItem('homeModules'); if (savedHomeModules) { try { setHomeModules(JSON.parse(savedHomeModules)); } catch (error) { console.error('解析首页模块配置失败:', error); } } const savedHomeBannerEnabled = localStorage.getItem('homeBannerEnabled'); if (savedHomeBannerEnabled !== null) { setHomeBannerEnabled(savedHomeBannerEnabled === 'true'); } const savedHomeContinueWatchingEnabled = localStorage.getItem('homeContinueWatchingEnabled'); if (savedHomeContinueWatchingEnabled !== null) { setHomeContinueWatchingEnabled(savedHomeContinueWatchingEnabled === 'true'); } }; // 加载首页模块配置 useEffect(() => { loadHomeLayoutSettings(); }, []); // 监听首页模块配置更新事件 useEffect(() => { const handleHomeModulesUpdated = () => { loadHomeLayoutSettings(); }; window.addEventListener('homeModulesUpdated', handleHomeModulesUpdated); return () => { window.removeEventListener('homeModulesUpdated', handleHomeModulesUpdated); }; }, []); // 检查AI功能是否启用 useEffect(() => { if (typeof window !== 'undefined') { const enabled = (window as any).RUNTIME_CONFIG?.AI_ENABLED && (window as any).RUNTIME_CONFIG?.AI_ENABLE_HOMEPAGE_ENTRY; setAiEnabled(enabled); // 加载AI默认消息配置 const defaultMsg = (window as any).RUNTIME_CONFIG?.AI_DEFAULT_MESSAGE_NO_VIDEO; if (defaultMsg) { setAiDefaultMessageNoVideo(defaultMsg); } } }, []); // 检查源站寻片功能是否启用 useEffect(() => { if (typeof window !== 'undefined') { const enabled = (window as any).RUNTIME_CONFIG?.ENABLE_SOURCE_SEARCH !== false; setSourceSearchEnabled(enabled); } }, []); // 检查音乐功能是否启用 useEffect(() => { if (typeof window !== 'undefined') { const enabled = (window as any).RUNTIME_CONFIG?.TUNEHUB_ENABLED === true; setMusicEnabled(enabled); } }, []); // 检查公告弹窗状态 useEffect(() => { if (typeof window !== 'undefined' && announcement) { const hasSeenAnnouncement = localStorage.getItem('hasSeenAnnouncement'); if (hasSeenAnnouncement !== announcement) { setShowAnnouncement(true); } else { setShowAnnouncement(Boolean(!hasSeenAnnouncement && announcement)); } } }, [announcement]); useEffect(() => { const CACHE_DURATION = 60 * 60 * 1000; // 1小时 const getCache = (key: string) => { try { const cached = localStorage.getItem(key); if (!cached) return null; const { data, timestamp } = JSON.parse(cached); return { data, expired: Date.now() - timestamp > CACHE_DURATION }; } catch { return null; } }; const setCache = (key: string, data: any) => { try { localStorage.setItem(key, JSON.stringify({ data, timestamp: Date.now() })); } catch { // Ignore localStorage errors } }; const moviesCache = getCache('homepage_movies'); const tvShowsCache = getCache('homepage_tvshows'); const varietyCache = getCache('homepage_variety'); const bangumiCache = getCache('homepage_bangumi'); const duanjuCache = getCache('homepage_duanju'); const upcomingCache = getCache('homepage_upcoming'); if (moviesCache?.data) setHotMovies(moviesCache.data); if (tvShowsCache?.data) setHotTvShows(tvShowsCache.data); if (varietyCache?.data) setHotVarietyShows(varietyCache.data); if (bangumiCache?.data) setBangumiCalendarData(bangumiCache.data); if (duanjuCache?.data) setHotDuanju(duanjuCache.data); if (upcomingCache?.data) setUpcomingContent(upcomingCache.data); const hasCache = moviesCache || tvShowsCache || varietyCache || bangumiCache || duanjuCache || upcomingCache; if (hasCache) setLoading(false); const needsRefresh = !moviesCache || moviesCache.expired || !tvShowsCache || tvShowsCache.expired || !varietyCache || varietyCache.expired || !bangumiCache || bangumiCache.expired || !duanjuCache || duanjuCache.expired || !upcomingCache || upcomingCache.expired; if (needsRefresh) { (async () => { try { 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); setCache('homepage_movies', moviesData.list); } if (tvShowsData.code === 200) { setHotTvShows(tvShowsData.list); setCache('homepage_tvshows', tvShowsData.list); } if (varietyShowsData.code === 200) { setHotVarietyShows(varietyShowsData.list); setCache('homepage_variety', varietyShowsData.list); } setBangumiCalendarData(bangumiCalendarData); setCache('homepage_bangumi', bangumiCalendarData); try { const duanjuResponse = await fetch('/api/duanju/recommends'); if (duanjuResponse.ok) { const duanjuResult = await duanjuResponse.json(); if (duanjuResult.code === 200 && duanjuResult.data) { setHotDuanju(duanjuResult.data); setCache('homepage_duanju', duanjuResult.data); } } } catch (error) { console.error('获取热播短剧数据失败:', error); } try { const response = await fetch('/api/tmdb/upcoming'); if (response.ok) { const result = await response.json(); if (result.code === 200 && result.data) { const sorted = [...result.data].sort((a, b) => { const dateA = new Date(a.release_date || '9999-12-31').getTime(); const dateB = new Date(b.release_date || '9999-12-31').getTime(); return dateA - dateB; }); setUpcomingContent(sorted); setCache('homepage_upcoming', sorted); } } } catch (error) { console.error('获取TMDB即将上映数据失败:', error); } setLoading(false); } catch (error) { console.error('获取推荐数据失败:', error); setLoading(false); } })(); } }, []); const handleCloseAnnouncement = (announcement: string) => { setShowAnnouncement(false); localStorage.setItem('hasSeenAnnouncement', announcement); // 记录已查看弹窗 }; // 渲染模块的函数 const renderModule = (moduleId: string) => { switch (moduleId) { case 'hotMovies': return (

热门电影

查看更多
{loading ? Array.from({ length: 8 }).map((_, index) => (
)) : hotMovies.map((movie) => (
))}
); case 'hotDuanju': if (hotDuanju.length === 0) return null; return (

热播短剧

{loading ? Array.from({ length: 8 }).map((_, index) => (
)) : hotDuanju.map((duanju) => (
))}
); case 'bangumiCalendar': return (

新番放送

查看更多
{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.filter((anime) => anime.images) || []; return todayAnimes.map((anime, index) => (
)); })()}
); case 'hotTvShows': return (

热门剧集

查看更多
{loading ? Array.from({ length: 8 }).map((_, index) => (
)) : hotTvShows.map((tvShow) => (
))}
); case 'hotVarietyShows': return (

热门综艺

查看更多
{loading ? Array.from({ length: 8 }).map((_, index) => (
)) : hotVarietyShows.map((varietyShow) => (
))}
); case 'upcomingContent': if (upcomingContent.length === 0) return null; return (

即将上映

{upcomingContent.map((item) => (
0 ? item.vote_average.toFixed(1) : '' } type={item.media_type === 'tv' ? 'tv' : 'movie'} from='douban' releaseDate={item.release_date} isUpcoming={true} />
))}
); default: return null; } }; return ( {/* TMDB 热门轮播图 */} {homeBannerEnabled && (
)}
{/* 首页内容 */} <> {/* 源站寻片和AI问片入口 */}
{/* 音乐视听入口 */} {musicEnabled && ( )} {/* 源站寻片入口 */} {sourceSearchEnabled && ( )} {/* AI问片入口 */} {aiEnabled && ( )}
{/* 继续观看 */} {homeContinueWatchingEnabled && } {/* 根据配置动态渲染首页模块 */} {homeModules .filter(module => module.enabled) .sort((a, b) => a.order - b.order) .map(module => renderModule(module.id))}
{/* HTTP 环境警告弹窗 */} {showHttpWarning && ( setShowHttpWarning(false)} /> )} {/* AI问片面板 */} {aiEnabled && ( setShowAIChat(false)} welcomeMessage={aiDefaultMessageNoVideo} /> )} {/* 公告弹窗 */} {showAnnouncement && (

公告

{announcement}
)} {showDirectPlayDialog && (
setShowDirectPlayDialog(false)} >
event.stopPropagation()} >

直链播放

请输入可直接播放的视频链接。
setDirectPlayUrl(event.target.value)} onKeyDown={(event) => { if (event.key === 'Enter') { submitDirectPlay(); } }} placeholder='https://example.com/video.m3u8' className='w-full px-3 py-2 rounded-lg border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500' />
)}
); } export default function Home() { return ( ); }