"use client"; import { useState, useEffect } from "react"; import Link from "next/link"; import { getTopicCurriculum } from "../config"; import { canWatchLesson } from "@/app/cloudphone/lib/payment"; import { isBookmarked, toggleBookmark, getBookmarks, getCompletedLessons } from "@/app/cloudphone/lib/learning"; type TopicCurriculumProps = { topicId: string; }; export function TopicCurriculum({ topicId }: TopicCurriculumProps) { const [expanded, setExpanded] = useState>({}); const [bookmarks, setBookmarks] = useState>(new Set()); const [completed, setCompleted] = useState>(new Set()); const curriculum = getTopicCurriculum(topicId); useEffect(() => { setBookmarks(getBookmarks()); setCompleted(getCompletedLessons()); const onB = () => setBookmarks(getBookmarks()); const onP = () => setCompleted(getCompletedLessons()); window.addEventListener("learning:bookmarks", onB); window.addEventListener("learning:progress", onP); return () => { window.removeEventListener("learning:bookmarks", onB); window.removeEventListener("learning:progress", onP); }; }, []); useEffect(() => { const curr = getTopicCurriculum(topicId); if (curr?.modules?.length) { setExpanded((prev) => { const next = { ...prev }; curr.modules.forEach((_, i) => { if (next[i] === undefined) next[i] = i === 0; }); return next; }); } }, [topicId]); const toggle = (i: number) => { setExpanded((prev) => ({ ...prev, [i]: !prev[i] })); }; if (!curriculum?.hasContent || !curriculum.modules.length) return null; const modules = curriculum.modules; return (

实战课程

从入门到进阶,完整学习路径

{modules.map((module, i) => { const isOpen = expanded[i] ?? true; return (
{isOpen && (
    {module.lessons.map((lesson, li) => { const origMod = module.originalModuleIndex; const free = origMod === 0 && li < 2; const unlocked = canWatchLesson(origMod, li); const key = `${origMod}-${li}`; const bookmarked = isBookmarked(origMod, li); const isCompleted = completed.has(key); return (
  • {lesson.name} {free && ( 试看 )} {isCompleted && ( )} {!unlocked && ( 🔒 )} {lesson.duration}
  • ); })}
)}
); })}
); }