/* eslint-disable react-hooks/exhaustive-deps */
'use client';
import { ChevronRight } from 'lucide-react';
import Link from 'next/link';
import { Suspense, useEffect, useState } from 'react';
// 客户端收藏 API
import {
type Favorite,
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 PaginatedRow from '@/components/PaginatedRow';
import { useSite } from '@/components/SiteProvider';
import VideoCard from '@/components/VideoCard';
// 主内容区大型 KatelyaTV Logo 组件
const MainKatelyaLogo = () => {
return (
{/* 背景光效 */}
{/* 主 Logo */}
KatelyaTV
{/* 副标题 */}
{/* 装饰性粒子效果 */}
);
};
// KatelyaTV 底部 Logo 组件
const BottomKatelyaLogo = () => {
return (
{/* 浮动几何形状装饰 */}
KatelyaTV
Powered by KatelyaTV Core
);
};
function HomeClient() {
const [activeTab, setActiveTab] = useState<'home' | 'favorites'>('home');
const [hotMovies, setHotMovies] = useState([]);
const [hotTvShows, setHotTvShows] = useState([]);
const [hotVarietyShows, setHotVarietyShows] = useState([]);
const [loading, setLoading] = useState(true);
const { announcement } = useSite();
// 分页状态管理
const [moviePage, setMoviePage] = useState(0);
const [tvShowPage, setTvShowPage] = useState(0);
const [varietyShowPage, setVarietyShowPage] = useState(0);
const [loadingMore, setLoadingMore] = useState({
movies: false,
tvShows: false,
varietyShows: false,
});
const [hasMoreData, setHasMoreData] = useState({
movies: true,
tvShows: true,
varietyShows: true,
});
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;
};
const [favoriteItems, setFavoriteItems] = useState([]);
useEffect(() => {
const fetchDoubanData = async () => {
try {
setLoading(true);
// 并行获取热门电影、热门剧集和热门综艺
const [moviesData, tvShowsData, varietyShowsData] = await Promise.all([
getDoubanCategories({
kind: 'movie',
category: '热门',
type: '全部',
}),
getDoubanCategories({ kind: 'tv', category: 'tv', type: 'tv' }),
getDoubanCategories({ kind: 'tv', category: 'show', type: 'show' }),
]);
if (moviesData.code === 200) {
setHotMovies(moviesData.list);
}
if (tvShowsData.code === 200) {
setHotTvShows(tvShowsData.list);
}
if (varietyShowsData.code === 200) {
setHotVarietyShows(varietyShowsData.list);
}
} catch (error) {
// 静默处理错误,避免控制台警告
// console.error('获取豆瓣数据失败:', error);
} finally {
setLoading(false);
}
};
fetchDoubanData();
}, []);
// 加载更多电影
const loadMoreMovies = async () => {
if (loadingMore.movies || !hasMoreData.movies) return;
setLoadingMore(prev => ({ ...prev, movies: true }));
try {
const nextPage = moviePage + 1;
const moviesData = await getDoubanCategories({
kind: 'movie',
category: '热门',
type: '全部',
pageStart: nextPage * 20,
pageLimit: 20,
});
if (moviesData.code === 200 && moviesData.list.length > 0) {
setHotMovies(prev => [...prev, ...moviesData.list]);
setMoviePage(nextPage);
// 如果返回的数据少于请求的数量,说明没有更多数据了
if (moviesData.list.length < 20) {
setHasMoreData(prev => ({ ...prev, movies: false }));
}
} else {
setHasMoreData(prev => ({ ...prev, movies: false }));
}
} catch (error) {
// 静默处理错误
} finally {
setLoadingMore(prev => ({ ...prev, movies: false }));
}
};
// 加载更多剧集
const loadMoreTvShows = async () => {
if (loadingMore.tvShows || !hasMoreData.tvShows) return;
setLoadingMore(prev => ({ ...prev, tvShows: true }));
try {
const nextPage = tvShowPage + 1;
const tvShowsData = await getDoubanCategories({
kind: 'tv',
category: 'tv',
type: 'tv',
pageStart: nextPage * 20,
pageLimit: 20,
});
if (tvShowsData.code === 200 && tvShowsData.list.length > 0) {
setHotTvShows(prev => [...prev, ...tvShowsData.list]);
setTvShowPage(nextPage);
if (tvShowsData.list.length < 20) {
setHasMoreData(prev => ({ ...prev, tvShows: false }));
}
} else {
setHasMoreData(prev => ({ ...prev, tvShows: false }));
}
} catch (error) {
// 静默处理错误
} finally {
setLoadingMore(prev => ({ ...prev, tvShows: false }));
}
};
// 加载更多综艺
const loadMoreVarietyShows = async () => {
if (loadingMore.varietyShows || !hasMoreData.varietyShows) return;
setLoadingMore(prev => ({ ...prev, varietyShows: true }));
try {
const nextPage = varietyShowPage + 1;
const varietyShowsData = await getDoubanCategories({
kind: 'tv',
category: 'show',
type: 'show',
pageStart: nextPage * 20,
pageLimit: 20,
});
if (varietyShowsData.code === 200 && varietyShowsData.list.length > 0) {
setHotVarietyShows(prev => [...prev, ...varietyShowsData.list]);
setVarietyShowPage(nextPage);
if (varietyShowsData.list.length < 20) {
setHasMoreData(prev => ({ ...prev, varietyShows: false }));
}
} else {
setHasMoreData(prev => ({ ...prev, varietyShows: false }));
}
} catch (error) {
// 静默处理错误
} finally {
setLoadingMore(prev => ({ ...prev, varietyShows: false }));
}
};
// 处理收藏数据更新的函数
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,
} 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 (
{/* 主内容区大型 KatelyaTV Logo - 仅在首页显示 */}
{activeTab === 'home' &&
}
{/* 顶部 Tab 切换 */}
setActiveTab(value as 'home' | 'favorites')}
/>
{/* 主内容区域 - 优化为完全居中布局 */}
{activeTab === 'favorites' ? (
// 收藏夹视图
<>
我的收藏
{favoriteItems.length > 0 && (
)}
{/* 优化收藏夹网格布局,确保在新的居中布局下完美对齐 */}
{favoriteItems.map((item) => (
1 ? 'tv' : ''}
/>
))}
{favoriteItems.length === 0 && (
暂无收藏内容
)}
{/* 收藏夹页面底部 Logo */}
>
) : (
// 首页视图
<>
{/* 继续观看 */}
{/* 热门电影 */}
热门电影
查看更多
{loading
? // 加载状态显示灰色占位数据 (显示10个,2行x5列)
Array.from({ length: 10 }).map((_, index) => (
))
: // 显示真实数据
hotMovies.map((movie, index) => (
))}
{/* 热门剧集 */}
热门剧集
查看更多
{loading
? // 加载状态显示灰色占位数据 (显示10个,2行x5列)
Array.from({ length: 10 }).map((_, index) => (
))
: // 显示真实数据
hotTvShows.map((show, index) => (
))}
{/* 热门综艺 */}
热门综艺
查看更多
{loading
? // 加载状态显示灰色占位数据 (显示10个,2行x5列)
Array.from({ length: 10 }).map((_, index) => (
))
: // 显示真实数据
hotVarietyShows.map((show, index) => (
))}
{/* 首页底部 Logo */}
>
)}
{announcement && showAnnouncement && (
提示
)}
);
}
export default function Home() {
return (
);
}