"use client"; import { useEffect, useState } from "react"; // 禁用静态生成 export const dynamic = 'force-dynamic'; import { useRouter } from "next/navigation"; import { useAuthStore } from "@/store/auth"; import MobileNav from "@/components/layout/mobile-nav"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Alert, AlertDescription } from "@/components/ui/alert"; import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, } from "@/components/ui/accordion"; import { Loader2, BookOpen, GraduationCap, Lightbulb, Target, Network, List } from "lucide-react"; import { courseContentAPI } from "@/lib/api"; import { BookStructure } from "@/types"; import dynamicImport from "next/dynamic"; import NodeDetailDialog from "@/components/course-content/node-detail-dialog"; import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Button } from "@/components/ui/button"; import { FileText, ChevronRight } from "lucide-react"; // 动态导入 KnowledgeGraph 组件,禁用 SSR const KnowledgeGraph = dynamicImport( () => import("@/components/course-content/knowledge-graph"), { ssr: false } ); export default function CourseContentPage() { const router = useRouter(); const { isAuthenticated, isLoading: authLoading } = useAuthStore(); const [bookStructure, setBookStructure] = useState(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); const [viewMode, setViewMode] = useState<'graph' | 'list'>('graph'); const [selectedNode, setSelectedNode] = useState<{ type: 'chapter' | 'section' | 'subsection'; id: number; title: string; subsections?: Array<{ id: number; title: string }>; } | null>(null); const [isDialogOpen, setIsDialogOpen] = useState(false); useEffect(() => { if (!authLoading && !isAuthenticated) { router.push("/login"); return; } if (isAuthenticated) { loadCourseContent(); } }, [isAuthenticated, authLoading, router]); const loadCourseContent = async () => { try { setIsLoading(true); setError(null); const structure = await courseContentAPI.getCourseContent(); setBookStructure(structure); } catch (err) { console.error("加载课程内容失败:", err); setError("加载课程内容失败: " + (err instanceof Error ? err.message : String(err))); } finally { setIsLoading(false); } }; if (authLoading || isLoading) { return (
); } if (!isAuthenticated) { return null; } return (
{/* 视图切换 */}
setViewMode(v as 'graph' | 'list')}> 知识图谱 列表视图
{/* 错误提示 */} {error && ( {error} )} {/* 课程内容展示 */} {!bookStructure ? (

暂无课程内容

课程内容正在准备中,请稍后再来查看

) : ( <> {/* 知识图谱视图 */} {viewMode === 'graph' && (
)} {/* 列表视图 */} {viewMode === 'list' && (
{bookStructure.chapters.map((chapter) => (
第{chapter.chapter_number}章 {chapter.title}
{chapter.sections.map((section) => (
{section.title}
{section.subsections.length === 0 ? (

暂无小节(知识点)

) : ( <>

小节(知识点) ({section.subsections.length} 个)

    {section.subsections.map((subsection) => (
  • {subsection.title}
  • ))}
)}
))}
))}
)} )}
{/* 节点详情对话框 */} {selectedNode && ( )} {/* 移动端导航 */}
); }