import { useMemo, useState, useRef, useEffect } from 'react' import { useNavigate, useParams } from 'react-router-dom' import { Image, Video, type VideoAnchor, type VideoRef, type DragFillResult, LetterToChenyun, EndingOverlay, Narration, } from '@/components' import { getBackgroundImage, getPublicPath, getStaticImage } from '@/lib/utils' import { SuccessAlert, DragQuizPanel } from '@/components/layout' import { MultipleChoiceQuizPanel, SingleChoiceQuizPanel } from '@/components/layout/quiz' import { GuideSteps, GuideStepsItem } from '@/components' import { usePuzzleAnimation } from '@/contexts/PuzzleAnimationContext' import { setCourseTimeProgress } from '@/lib/utils/api-common' type QuizOption = { value: string label: string isCorrect?: boolean explanation?: string // 错误选项的解释 } type QuizAnchor = { id: string time: number title: string prompt: string type: 'single' | 'multiple' | 'drag' options: QuizOption[] // 拖拽题专用 blanks?: { id: string; label: string }[] explanation?: string } // 星名固定为 chenyun const starName = 'chenyun' // 通用提示文案 const MULTIPLE_DEFAULT_ERROR = '你的选择还不够全面哦~请你再想想吧!' // 锚点数据:可根据实际视频时长调整 time const QUIZ_ANCHORS: QuizAnchor[] = [ { id: 'quiz-1', time: 60 * 5 + 53, //5.52分钟 title: '题目1', prompt: '陈云经济思想的核心内容包括:', type: 'multiple', options: [ { value: 'A', label: '综合平衡', isCorrect: true }, { value: 'B', label: '鸟笼比喻', }, { value: 'C', label: '正确地处理好计划与市场的关系', isCorrect: true }, { value: 'D', label: '经济建设的目的论', isCorrect: true }, ], explanation: '鸟笼比喻是陈云提出的一个比喻。请你再想想吧!', }, { id: 'quiz-2', time: 60 * 10 + 2, //10.01分钟 title: '题目2', prompt: '陈云说过以下哪些话能着重体现出他的经济思想?', type: 'multiple', options: [ { value: 'A', label: '不唯上、不唯书、只唯实,交换、比较、反复', isCorrect: true, }, { value: 'B', label: '无农不稳,无粮则乱', isCorrect: true }, { value: 'C', label: '个人名利淡如水,党的事业重如山', isCorrect: true }, { value: 'D', label: '领导机关制定政策,要用百分之九十以上的时间作调查研究工作', isCorrect: true, }, ], explanation: '你的选择还不够全面哦~请你再想想吧!', }, { id: 'quiz-3', time: 16 * 60 + 31, //16:26 title: '题目3', prompt: '新时代的青年可以从陈云身上学习到', type: 'drag', options: [ { value: '积极的人生态度', label: 'A.积极的人生态度', isCorrect: true }, { value: '刻苦的学习精神', label: 'B.刻苦的学习精神', isCorrect: true }, { value: '朴素的节俭精神', label: 'C.朴素的节俭精神', isCorrect: true }, { value: '只唯上的工作作风', label: 'D.只唯上的工作作风' }, ], blanks: [ { id: 'blank-1', label: '____' }, { id: 'blank-2', label: '____' }, { id: 'blank-3', label: '____' }, ], }, { id: 'quiz-4', time: 60 * 5 + 21, // 5:21 title: '题目4', prompt: '陈云讲:“经济建设最终目的,是为了改善____的生活水平。”', type: 'single', options: [ { value: 'A', label: '为官者', explanation: '这不是陈云提倡的经济建设的最终目的。请你再想想吧!', }, { value: 'B', label: '老百姓', isCorrect: true }, ], }, { id: 'quiz-5', time: 60 * 16 + 23, // 16:23 title: '题目5', prompt: '以下哪些陈云的生活小事值得我们学习?', type: 'multiple', options: [ { value: 'A', label: '光盘行动,不浪费粮食', isCorrect: true }, { value: 'B', label: '打了 32 个补丁的棉坎肩他穿了 38 年', isCorrect: true }, { value: 'C', label: '2-3 厘米长的铅笔头仍然留用', isCorrect: true }, { value: 'D', label: '搓肥皂时关闭水龙头,节约用水', isCorrect: true }, ], explanation: MULTIPLE_DEFAULT_ERROR, }, ] const ChenyunInternalization = () => { const navigate = useNavigate() const { moduleName } = useParams<{ moduleName: string }>() // 获取碎片动画触发方法 const { triggerPuzzleAnimation } = usePuzzleAnimation() const [activeSuccess, setActiveSuccess] = useState(null) const [resumeCallback, setResumeCallback] = useState<(() => void) | null>(null) // 拖拽题状态 const [dragQuizValues, setDragQuizValues] = useState>({}) const [dragQuizErrors, setDragQuizErrors] = useState>({}) const [narrationVisible, setNarrationVisible] = useState(false) const [visible, setVisible] = useState(false) const [showVideo, setShowVideo] = useState(false) const [postGuideVisible, setPostGuideVisible] = useState(false) const [showLetter, setShowLetter] = useState(false) const [showStudyGuide, setShowStudyGuide] = useState(false) const videoRef = useRef(null) useEffect(() => { setNarrationVisible(true) }, []) // 视频加载完成后自动播放 const handleVideoCanPlay = () => { if (showVideo && videoRef.current) { videoRef.current.play().catch((error) => { console.warn('视频播放失败:', error) }) } } const anchors: VideoAnchor[] = useMemo( () => QUIZ_ANCHORS.map((item) => { const correctAnswers = item.options.filter((opt) => opt.isCorrect).map((opt) => opt.value) // 拖拽题处理 if (item.type === 'drag' && item.blanks) { return { id: item.id, time: item.time, once: true, afterResume: 'remove', render: ({ resume }) => { // 拖拽题:处理选项拖拽与校验 const handleDragChange = (val: DragFillResult[]) => { setDragQuizValues((prev) => ({ ...prev, [item.id]: val })) setDragQuizErrors((prev) => ({ ...prev, [item.id]: '' })) if (val.length < correctAnswers.length) return // 检查是否包含了所有正确答案(不要求顺序) const filledAnswers = val.map((v) => v.optionValue) const answerSet = new Set(correctAnswers) const filledSet = new Set(filledAnswers) const isCorrect = answerSet.size === filledSet.size && [...answerSet].every((answer) => filledSet.has(answer)) if (isCorrect) { setActiveSuccess(item.id) setResumeCallback(() => resume) } else { setDragQuizErrors((prev) => ({ ...prev, [item.id]: '这不是陈云的工作作风。请你再想想吧!', })) } } return ( <> ({ value: opt.value, label: opt.label, }))} blanks={item.blanks || []} value={dragQuizValues[item.id] || []} error={dragQuizErrors[item.id]} onChange={handleDragChange} /> { setActiveSuccess(null) triggerPuzzleAnimation(16) setDragQuizValues((prev) => { const next = { ...prev } delete next[item.id] return next }) setDragQuizErrors((prev) => { const next = { ...prev } delete next[item.id] return next }) const cb = resumeCallback setResumeCallback(null) cb?.() }} /> ) }, } } // 多选题处理 if (item.type === 'multiple') { return { id: item.id, time: item.time, once: true, afterResume: 'remove', render: ({ resume }) => ( <> ({ value: opt.value, label: `${opt.value}. ${opt.label}`, }))} correctAnswer={correctAnswers} errorMessage={(selectedValues) => { // 题目1:选到“鸟笼比喻(B)”给专属提示;否则未选全给“还不够全面”提示 if (item.id === 'quiz-1') { if (selectedValues.includes('B')) { return item.explanation || '鸟笼比喻是陈云提出的一个比喻。请你再想想吧!' } return MULTIPLE_DEFAULT_ERROR } // 题目5:选到“D”给专属提示;否则未选全给“还不够全面”提示 if (item.id === 'quiz-5') { if (selectedValues.includes('D')) { const pickedD = item.options.find((o) => o.value === 'D') return pickedD?.explanation || MULTIPLE_DEFAULT_ERROR } return MULTIPLE_DEFAULT_ERROR } return item.explanation || MULTIPLE_DEFAULT_ERROR }} onSubmit={(values: string[], isCorrect: boolean) => { if (isCorrect) { setActiveSuccess(item.id) if (item.id === 'quiz-1') triggerPuzzleAnimation(15) setResumeCallback(() => resume) } }} /> { setActiveSuccess(null) const cb = resumeCallback setResumeCallback(null) cb?.() }} /> ), } } if (item.type === 'single') { return { id: item.id, time: item.time, once: true, afterResume: 'remove', render: ({ resume }) => ( <> ({ value: opt.value, label: `${opt.value}. ${opt.label}`, }))} correctAnswer={correctAnswers[0]} onWrongSelect={(value) => item.options.find((opt) => opt.value === value)?.explanation } onSubmit={(_, isCorrect) => { if (isCorrect) { setActiveSuccess(item.id) setResumeCallback(() => resume) } }} /> { setActiveSuccess(null) const cb = resumeCallback setResumeCallback(null) cb?.() }} /> ), } } return { id: item.id, time: item.time, once: true, afterResume: 'remove', render: () => null, } }), [activeSuccess, resumeCallback, dragQuizValues, dragQuizErrors, triggerPuzzleAnimation] ) if (!moduleName) return null return (
{/* 离开按钮 */} navigate(`/${moduleName}/${starName}/home`)} /> { setNarrationVisible(false) setVisible(true) }} text={`从练塘水乡的少年时光,到商务印书馆的革命启航;从苏区与延安的经济破局,到新中国成立之初打赢“银元之战”“米棉之战”,再到建设与改革岁月里擘画实业、奠基兴国,我们已循着陈云同志的足迹,走过一段波澜壮阔的奋斗征程。那些“全国一盘棋”的统筹智慧、“不唯上、不唯书、只唯实”的务实品格、“为老百姓做事”的为民初心,穿越历史烟云,依旧闪耀着时代光芒。历史的回响已在耳畔,精神的传承更需躬身践行。新时代的青年,应该从历史感悟走向思想内化,读懂陈云经济思想的深刻内涵,汲取指引青春成长、担当时代使命的精神力量,让伟人风范在新时代薪火相传。`} animationSpeed={200} /> {showVideo && (
) } export default ChenyunInternalization