"use client" import { useState, useEffect } from "react" import { useRouter } from "next/navigation" import { ChevronLeft, Lock, Share2, Sparkles } from "lucide-react" import { type Section, getFullBookPrice, getTotalSectionCount } from "@/lib/book-data" import { useStore } from "@/lib/store" import { PaymentModal } from "./payment-modal" import { AuthModal } from "./modules/auth/auth-modal" interface ChapterContentProps { section: Section & { filePath: string } partTitle: string chapterTitle: string } export function ChapterContent({ section, partTitle, chapterTitle }: ChapterContentProps) { const router = useRouter() const [content, setContent] = useState("") const [isLoading, setIsLoading] = useState(true) const [isPaymentOpen, setIsPaymentOpen] = useState(false) const [isAuthOpen, setIsAuthOpen] = useState(false) const [paymentType, setPaymentType] = useState<"section" | "fullbook">("section") const [readingProgress, setReadingProgress] = useState(0) const [showPaywall, setShowPaywall] = useState(false) const { user, isLoggedIn, hasPurchased } = useStore() const fullBookPrice = getFullBookPrice() const totalSections = getTotalSectionCount() const hasFullBook = user?.hasFullBook || false const canAccess = section.isFree || hasFullBook || (isLoggedIn && hasPurchased(section.id)) // 阅读进度追踪 useEffect(() => { const handleScroll = () => { const scrollTop = window.scrollY const docHeight = document.documentElement.scrollHeight - window.innerHeight const progress = docHeight > 0 ? Math.min((scrollTop / docHeight) * 100, 100) : 0 setReadingProgress(progress) if (progress >= 20 && !canAccess) { setShowPaywall(true) } } window.addEventListener("scroll", handleScroll) return () => window.removeEventListener("scroll", handleScroll) }, [canAccess]) // 加载内容 useEffect(() => { async function loadContent() { try { if (section.content) { setContent(section.content) setIsLoading(false) return } const response = await fetch(`/api/content?path=${encodeURIComponent(section.filePath)}`) if (response.ok) { const data = await response.json() setContent(data.content || "") } } catch (error) { console.error("Failed to load content:", error) } finally { setIsLoading(false) } } loadContent() }, [section.filePath, section.content]) const handlePurchaseClick = (type: "section" | "fullbook") => { if (!isLoggedIn) { setIsAuthOpen(true) return } setPaymentType(type) setIsPaymentOpen(true) } const contentLines = content.split("\n").filter((line) => line.trim()) const previewLineCount = Math.ceil(contentLines.length * 0.2) // 改为20% const previewContent = contentLines.slice(0, previewLineCount).join("\n") return (
{/* 顶部导航 */}
{partTitle &&

{partTitle}

} {chapterTitle &&

{chapterTitle}

}
{/* 阅读内容 */}
{section.id} {section.isFree && 免费}

{section.title}

{isLoading ? (
{[...Array(8)].map((_, i) => (
))}
) : canAccess ? ( // 完整内容
{content.split("\n").map( (paragraph, index) => paragraph.trim() && (

{paragraph}

), )}
) : (
{/* 免费预览部分 */}
{previewContent.split("\n").map( (paragraph, index) => paragraph.trim() && (

{paragraph}

), )}
{showPaywall && ( <> {/* 渐变遮罩 */}

解锁完整内容

已阅读20%,{isLoggedIn ? "购买后继续阅读" : "登录并购买后继续阅读"}

{/* 购买选项 */}

分享给好友购买,你可获得90%佣金

)}
)}
{/* 登录弹窗 */} setIsAuthOpen(false)} /> {/* 支付弹窗 */} setIsPaymentOpen(false)} type={paymentType} sectionId={section.id} sectionTitle={section.title} amount={paymentType === "section" ? section.price : fullBookPrice} onSuccess={() => window.location.reload()} />
) }