feat: replace detail page with play page

This commit is contained in:
shinya
2025-07-07 23:46:58 +08:00
parent 43d2bd27cf
commit 33dd8dc4e9
5 changed files with 39 additions and 423 deletions

View File

@@ -53,8 +53,9 @@ const EpisodeSelector: React.FC<EpisodeSelectorProps> = ({
const pageCount = Math.ceil(totalEpisodes / episodesPerPage);
// 主要的 tab 状态:'episodes' 或 'sources'
// 当只有一集时默认展示 "换源",并隐藏 "选集" 标签
const [activeTab, setActiveTab] = useState<'episodes' | 'sources'>(
'episodes'
totalEpisodes > 1 ? 'episodes' : 'sources'
);
// 当前分页索引0 开始)
@@ -118,6 +119,20 @@ const EpisodeSelector: React.FC<EpisodeSelectorProps> = ({
[onSourceChange]
);
// 如果组件初始即显示 "换源",自动触发搜索一次
useEffect(() => {
if (
activeTab === 'sources' &&
availableSources.length === 0 &&
videoTitle &&
onSearchSources
) {
onSearchSources(videoTitle);
}
// 只在依赖变化时尝试availableSources 长度变化可阻止重复搜索
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [activeTab, availableSources.length, videoTitle]);
const currentStart = currentPage * episodesPerPage + 1;
const currentEnd = Math.min(
currentStart + episodesPerPage - 1,
@@ -128,18 +143,20 @@ const EpisodeSelector: React.FC<EpisodeSelectorProps> = ({
<div className='md:ml-2 px-4 py-0 h-full rounded-xl bg-black/10 dark:bg-white/5 flex flex-col border border-white/0 dark:border-white/30 overflow-hidden'>
{/* 主要的 Tab 切换 - 无缝融入设计 */}
<div className='flex mb-1 -mx-6 flex-shrink-0'>
<div
onClick={() => setActiveTab('episodes')}
className={`flex-1 py-3 px-6 text-center cursor-pointer transition-all duration-200 font-medium
${
activeTab === 'episodes'
? 'text-green-500 dark:text-green-400'
: 'text-gray-700 hover:text-green-600 bg-black/5 dark:bg-white/5 dark:text-gray-300 dark:hover:text-green-400 hover:bg-black/3 dark:hover:bg-white/3'
}
`.trim()}
>
</div>
{totalEpisodes > 1 && (
<div
onClick={() => setActiveTab('episodes')}
className={`flex-1 py-3 px-6 text-center cursor-pointer transition-all duration-200 font-medium
${
activeTab === 'episodes'
? 'text-green-500 dark:text-green-400'
: 'text-gray-700 hover:text-green-600 bg-black/5 dark:bg-white/5 dark:text-gray-300 dark:hover:text-green-400 hover:bg-black/3 dark:hover:bg-white/3'
}
`.trim()}
>
</div>
)}
<div
onClick={handleSourceTabClick}
className={`flex-1 py-3 px-6 text-center cursor-pointer transition-all duration-200 font-medium

View File

@@ -14,7 +14,9 @@ const PageLayout = ({ children, activePath = '/' }: PageLayoutProps) => {
return (
<div className='w-full min-h-screen'>
{/* 移动端头部 */}
<MobileHeader showBackButton={activePath === '/play'} />
<MobileHeader
showBackButton={['/play', '/aggregate'].includes(activePath)}
/>
{/* 主要布局容器 */}
<div className='flex md:grid md:grid-cols-[auto_1fr] w-full min-h-screen md:min-h-auto'>
@@ -26,9 +28,11 @@ const PageLayout = ({ children, activePath = '/' }: PageLayoutProps) => {
{/* 主内容区域 */}
<div className='relative min-w-0 flex-1 transition-all duration-300'>
{/* 桌面端左上角返回按钮 */}
<div className='absolute top-3 left-1 z-20 hidden md:flex'>
<BackButton />
</div>
{['/play', '/aggregate'].includes(activePath) && (
<div className='absolute top-3 left-1 z-20 hidden md:flex'>
<BackButton />
</div>
)}
{/* 桌面端顶部按钮 */}
<div className='absolute top-2 right-4 z-20 hidden md:flex items-center gap-2'>

View File

@@ -153,7 +153,7 @@ export default function VideoCard({
return (
<Link
href={`/detail?source=${source}&id=${id}&title=${encodeURIComponent(
href={`/play?source=${source}&id=${id}&title=${encodeURIComponent(
title.trim()
)}${year ? `&year=${year}` : ''}${from ? `&from=${from}` : ''}`}
>