'use client'; import { BookOpen, CheckCircle2, Compass, Library, Search, Sparkles, XCircle, } from 'lucide-react'; import Link from 'next/link'; import { useEffect, useMemo, useState } from 'react'; import { BookSource } from '@/lib/book.types'; function BooksHomeSkeleton() { return (
{Array.from({ length: 6 }).map((_, index) => (
))}
); } function CapabilityPill({ enabled, children, }: { enabled?: boolean; children: React.ReactNode; }) { const Icon = enabled ? CheckCircle2 : XCircle; return ( {children} ); } export default function BooksHomePage() { const [sources, setSources] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); useEffect(() => { if ( typeof window !== 'undefined' && !(window as Window & { RUNTIME_CONFIG?: { BOOKS_ENABLED?: boolean } }) .RUNTIME_CONFIG?.BOOKS_ENABLED ) { window.location.href = '/'; return; } fetch('/api/books/sources') .then((res) => res.json()) .then((data) => setSources(data.sources || [])) .catch((err) => setError(err.message || '加载书源失败')) .finally(() => setLoading(false)); }, []); const stats = useMemo(() => { const catalogCount = sources.filter( (source) => source.capabilities?.catalogSupported ).length; const searchCount = sources.filter( (source) => source.capabilities?.searchSupported ).length; return [ { label: '可用书源', value: sources.length }, { label: '支持目录', value: catalogCount }, { label: '支持搜索', value: searchCount }, ]; }, [sources]); return (
MoonTVPlus Reading Library

电子书馆

搜索书籍 我的书架
{stats.map((stat) => (
{stat.value}
{stat.label}
))}

书源入口

选择一个书源开始浏览,或直接进入搜索。

{loading ? : null} {error ? (
{error}
) : null}
{sources.map((source) => (
{source.name}
{source.type === 'legado' ? 'Legado' : 'OPDS'}
分类{source.capabilities?.catalogSupported ? '可用' : '不可用'} 搜索{source.capabilities?.searchSupported ? '可用' : '不可用'}
{source.capabilities?.catalogSupported && ( 浏览目录 )} {source.capabilities?.searchSupported && ( 搜索书籍 )}
))}
{!loading && !error && sources.length === 0 ? (
暂无可用书源
) : null}
); }