更新依赖项及历史人物相关内容资源
- 更新 package.json 和 package-lock.json 中的依赖项 - 新增/更新陈云、黄炎培、鲁迅、孙中山的音频文件 - 新增场景和组件的图片资源 - 清理未使用的音频和图片文件 - 优化多个组件和页面的实现逻辑
This commit is contained in:
1 parent
b1d55b9464
commit
e0fa47d21a
629 files changed
+24390
-2991
No files matched your search
@@ -0,0 +1,485 @@
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { useNavigate, useParams } from 'react-router-dom'
|
||||
import {
|
||||
Image,
|
||||
Video,
|
||||
type VideoAnchor,
|
||||
type VideoRef,
|
||||
LetterToZhangleping,
|
||||
Narration,
|
||||
EndingOverlay,
|
||||
} from '@/components'
|
||||
import { SuccessAlert } from '@/components/layout'
|
||||
import { MultipleChoiceQuizPanel, SingleChoiceQuizPanel } from '@/components/layout/quiz'
|
||||
import { getBackgroundImage, getPublicPath, getStaticImage } from '@/lib/utils'
|
||||
import { GuideSteps, GuideStepsItem } from '@/components'
|
||||
|
||||
const starName = 'zhangleping'
|
||||
|
||||
const ZhanglepingInternalization = () => {
|
||||
const navigate = useNavigate()
|
||||
const { moduleName } = useParams<{ moduleName: string }>()
|
||||
|
||||
const [narrationVisible, setNarrationVisible] = useState(true)
|
||||
const [visible, setVisible] = useState(false) // 对话引导面板是否可见
|
||||
const [showVideo, setShowVideo] = useState(false) // 内化主视频是否展示
|
||||
const [showLetter, setShowLetter] = useState(false)
|
||||
const [showStudyGuide, setShowStudyGuide] = useState(false)
|
||||
const [postGuideVisible, setPostGuideVisible] = useState(false)
|
||||
|
||||
const videoRef = useRef<VideoRef>(null)
|
||||
|
||||
const [showQuiz, setShowQuiz] = useState(false)
|
||||
const [quizSuccessVisible, setQuizSuccessVisible] = useState(false)
|
||||
|
||||
// 视频锚点题目状态
|
||||
const [activeSuccess, setActiveSuccess] = useState<string | null>(null)
|
||||
const [successContent, setSuccessContent] = useState<string>('')
|
||||
const [resumeCallback, setResumeCallback] = useState<(() => void) | null>(null)
|
||||
|
||||
// 旁白关闭后显示题目(答对后再显示对话引导)
|
||||
useEffect(() => {
|
||||
if (!narrationVisible) {
|
||||
setShowQuiz(true)
|
||||
}
|
||||
}, [narrationVisible])
|
||||
|
||||
const handleVideoCanPlay = () => {
|
||||
if (showVideo && videoRef.current) {
|
||||
videoRef.current.play().catch(() => {})
|
||||
}
|
||||
}
|
||||
|
||||
type QuizOption = {
|
||||
value: string
|
||||
label: string
|
||||
isCorrect?: boolean
|
||||
explanation?: string
|
||||
}
|
||||
|
||||
type QuizAnchor = {
|
||||
id: string
|
||||
time: number
|
||||
type: 'single' | 'multiple'
|
||||
title: string
|
||||
options: QuizOption[]
|
||||
correctAnswer: string | string[]
|
||||
}
|
||||
|
||||
// 视频内题目锚点(时间单位:秒)
|
||||
const QUIZ_ANCHORS: QuizAnchor[] = [
|
||||
{
|
||||
id: 'quiz-1',
|
||||
time: 60 * 1 + 49, // 1:49
|
||||
type: 'multiple',
|
||||
title: '【多选】张乐平的漫画能够比直白的道理说教更吸引人、更易传递美好品质的核心原因是:',
|
||||
options: [
|
||||
{
|
||||
value: 'A',
|
||||
label: 'A. 绘画技巧高超,色彩搭配丰富',
|
||||
explanation:
|
||||
'张乐平的漫画魅力不在于复杂的技巧和色彩,而在于内容的真实性哦!请你再想想吧!',
|
||||
},
|
||||
{
|
||||
value: 'B',
|
||||
label: 'B. 源于生活实际,以贴近现实的“小切片”传递情感与品质',
|
||||
explanation:
|
||||
'艺术源于生活,张乐平的漫画捕捉生活中的真实场景与人物,没有口号式宣传,做到了潜移默化、寓教于乐。',
|
||||
},
|
||||
{
|
||||
value: 'C',
|
||||
label: 'C. 故事情节离奇,充满奇幻色彩',
|
||||
explanation: '张乐平的漫画聚焦普通民众的生活与苦难,并非离奇的奇幻故事。请你再想想吧!',
|
||||
},
|
||||
],
|
||||
correctAnswer: ['A', 'B', 'C'],
|
||||
},
|
||||
{
|
||||
id: 'quiz-2',
|
||||
time: 60 * 3 + 22, // 3:22
|
||||
type: 'multiple',
|
||||
title: '【多选】张乐平“化繁为简、以简为上”的艺术风格主要体现在以下哪些方面?',
|
||||
options: [
|
||||
{
|
||||
value: 'A',
|
||||
label: 'A. 抓住人物表情、动作等细节刻画人物,不事无巨细描摹服装',
|
||||
},
|
||||
{
|
||||
value: 'B',
|
||||
label: 'B. 场景刻画化繁为简,聚焦核心道具与场景,寥寥数笔呈现完整画面',
|
||||
},
|
||||
{
|
||||
value: 'C',
|
||||
label: 'C. 刻意简化故事逻辑,降低读者理解难度',
|
||||
explanation:
|
||||
'张乐平的漫画是“形式简”而非“逻辑简”,核心是通过简洁形式传递深刻内涵。请你再想想吧!',
|
||||
},
|
||||
],
|
||||
correctAnswer: ['A', 'B'],
|
||||
},
|
||||
{
|
||||
id: 'quiz-3',
|
||||
time: 60 * 5 + 1, // 5:01
|
||||
type: 'single',
|
||||
title:
|
||||
'【判断】张乐平创作的“无字漫画”完全依靠人物的动态表情和场景刻画完成叙事,没有任何说明性文字和对话框。',
|
||||
options: [
|
||||
{
|
||||
value: 'A',
|
||||
label: 'A. 正确',
|
||||
explanation: '无字漫画的特点是无说明性文字、无对话框,仅靠画面完成叙事。',
|
||||
},
|
||||
{
|
||||
value: 'B',
|
||||
label: 'B. 错误',
|
||||
explanation:
|
||||
'请回顾汪教授对“无字漫画”的解读,张乐平从1935年塑造三毛起就坚持这种创作形式哦!请你再想想吧!',
|
||||
},
|
||||
],
|
||||
correctAnswer: 'A',
|
||||
},
|
||||
{
|
||||
id: 'quiz-4',
|
||||
time: 60 * 5 + 1, // 5:01,同一时间出现(对应图3、4)
|
||||
type: 'multiple',
|
||||
title: '【多选】以下哪些属于张乐平先生的创作理念与艺术追求?',
|
||||
options: [
|
||||
{
|
||||
value: 'A',
|
||||
label: 'A. 艺术源于生活,注重观察日常细节',
|
||||
},
|
||||
{
|
||||
value: 'B',
|
||||
label: 'B. 化繁为简,追求“以少胜多”的艺术境界',
|
||||
},
|
||||
{
|
||||
value: 'C',
|
||||
label: 'C. 用作品传递善良、正义与真善美',
|
||||
},
|
||||
{
|
||||
value: 'D',
|
||||
label: 'D. 仅专注于个人艺术表达,不关心社会现实',
|
||||
explanation:
|
||||
'张乐平始终以画笔担当社会责任,关注社会现实与民众疾苦,并非只专注个人表达。请你再想想吧!',
|
||||
},
|
||||
],
|
||||
correctAnswer: ['A', 'B', 'C'],
|
||||
},
|
||||
]
|
||||
|
||||
const anchors: VideoAnchor[] = QUIZ_ANCHORS.map((item) => {
|
||||
if (item.type === 'single') {
|
||||
const correct = item.correctAnswer as string
|
||||
|
||||
return {
|
||||
id: item.id,
|
||||
time: item.time,
|
||||
once: true,
|
||||
afterResume: 'remove',
|
||||
render: ({ resume }) => (
|
||||
<>
|
||||
<SingleChoiceQuizPanel
|
||||
visible={activeSuccess !== item.id}
|
||||
zIndex={10000}
|
||||
title={item.title}
|
||||
options={item.options.map((opt) => ({
|
||||
value: opt.value,
|
||||
label: opt.label,
|
||||
}))}
|
||||
correctAnswer={correct}
|
||||
onWrongSelect={(value: string) => {
|
||||
const opt = item.options.find((o) => o.value === value)
|
||||
return opt?.explanation || '再思考一下,选择正确答案。'
|
||||
}}
|
||||
onSubmit={(value: string, isCorrect: boolean) => {
|
||||
if (isCorrect) {
|
||||
const opt = item.options.find((o) => o.value === value)
|
||||
setActiveSuccess(item.id)
|
||||
setSuccessContent(opt?.explanation || '恭喜你,选择正确!')
|
||||
setResumeCallback(() => resume)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<SuccessAlert
|
||||
visible={activeSuccess === item.id}
|
||||
title={item.id === 'quiz-3' ? '恭喜你,判断正确!' : '恭喜你,选择正确!'}
|
||||
content={successContent}
|
||||
onContinue={() => {
|
||||
setActiveSuccess(null)
|
||||
setSuccessContent('')
|
||||
const cb = resumeCallback
|
||||
setResumeCallback(null)
|
||||
cb?.()
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
// 多选题
|
||||
const correctAnswers = item.correctAnswer as string[]
|
||||
|
||||
return {
|
||||
id: item.id,
|
||||
time: item.time,
|
||||
once: true,
|
||||
afterResume: 'remove',
|
||||
render: ({ resume }) => (
|
||||
<>
|
||||
<MultipleChoiceQuizPanel
|
||||
visible={activeSuccess !== item.id}
|
||||
zIndex={10000}
|
||||
title={item.title}
|
||||
options={item.options.map((opt) => ({
|
||||
value: opt.value,
|
||||
label: opt.label,
|
||||
}))}
|
||||
correctAnswer={correctAnswers}
|
||||
errorMessage={(selectedValues: string[]) => {
|
||||
const picked = new Set(selectedValues)
|
||||
|
||||
if (item.id === 'quiz-1') {
|
||||
if (picked.has('A')) {
|
||||
const optA = item.options.find((o) => o.value === 'A')
|
||||
return (
|
||||
optA?.explanation ||
|
||||
'张乐平的漫画魅力不在于复杂的技巧和色彩,而在于内容的真实性哦!请你再想想吧!'
|
||||
)
|
||||
}
|
||||
if (picked.has('C')) {
|
||||
const optC = item.options.find((o) => o.value === 'C')
|
||||
return (
|
||||
optC?.explanation ||
|
||||
'张乐平的漫画聚焦普通民众的生活与苦难,并非离奇的奇幻故事。请你再想想吧!'
|
||||
)
|
||||
}
|
||||
return '你的选择还不够全面哦~请你再想想吧!'
|
||||
}
|
||||
|
||||
if (item.id === 'quiz-2') {
|
||||
if (picked.has('C')) {
|
||||
const optC = item.options.find((o) => o.value === 'C')
|
||||
return (
|
||||
optC?.explanation ||
|
||||
'张乐平的漫画是“形式简”而非“逻辑简”,核心是通过简洁形式传递深刻内涵。请你再想想吧!'
|
||||
)
|
||||
}
|
||||
return '你的选择还不够全面哦~请你再想想吧!'
|
||||
}
|
||||
|
||||
if (item.id === 'quiz-4') {
|
||||
if (picked.has('D')) {
|
||||
const optD = item.options.find((o) => o.value === 'D')
|
||||
return (
|
||||
optD?.explanation ||
|
||||
'张乐平始终以画笔担当社会责任,关注社会现实与民众疾苦,并非只专注个人表达。请你再想想吧!'
|
||||
)
|
||||
}
|
||||
return '你的选择还不够全面哦~请你再想想吧!'
|
||||
}
|
||||
|
||||
return '你的选择还不够全面哦~请你再想想吧!'
|
||||
}}
|
||||
onSubmit={(values: string[], isCorrect: boolean) => {
|
||||
if (isCorrect) {
|
||||
setActiveSuccess(item.id)
|
||||
if (item.id === 'quiz-1') {
|
||||
setSuccessContent(
|
||||
'艺术源于生活,张乐平的漫画捕捉生活中的真实场景与人物,没有口号式宣传,做到了潜移默化、寓教于乐。'
|
||||
)
|
||||
} else if (item.id === 'quiz-2') {
|
||||
setSuccessContent(
|
||||
'先生善于捕捉核心细节展现人物特质,化繁为简的场景刻画让漫画更具感染力,这正是“以少胜多”艺术境界的体现。'
|
||||
)
|
||||
} else if (item.id === 'quiz-4') {
|
||||
setSuccessContent(
|
||||
'张乐平先生坚持艺术扎根生活,以简洁笔墨刻画时代,用作品传递温暖与正义,这些都是他的核心创作理念。'
|
||||
)
|
||||
} else {
|
||||
setSuccessContent('')
|
||||
}
|
||||
setResumeCallback(() => resume)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<SuccessAlert
|
||||
visible={activeSuccess === item.id}
|
||||
content={successContent}
|
||||
onContinue={() => {
|
||||
setActiveSuccess(null)
|
||||
setSuccessContent('')
|
||||
const cb = resumeCallback
|
||||
setResumeCallback(null)
|
||||
cb?.()
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
),
|
||||
}
|
||||
})
|
||||
|
||||
if (!moduleName) return null
|
||||
|
||||
return (
|
||||
<div
|
||||
className="relative h-full w-full bg-black"
|
||||
style={{
|
||||
backgroundImage: getBackgroundImage('components/internalization/bg'),
|
||||
}}
|
||||
>
|
||||
{/* 离开按钮 */}
|
||||
<Image
|
||||
className="absolute right-8 top-8 z-10"
|
||||
src={getStaticImage('components/离开')}
|
||||
button
|
||||
onClick={() => navigate(`/${moduleName}/${starName}/home`)}
|
||||
/>
|
||||
|
||||
{/* 过度语 */}
|
||||
<Narration
|
||||
visible={narrationVisible}
|
||||
audioChannelId="zhangleping-internalization-narration"
|
||||
audioSrc={getPublicPath('audio/zhangleping/mp3_zhangleping_31.mp3')}
|
||||
animationSpeed={200}
|
||||
onClose={() => {
|
||||
setNarrationVisible(false)
|
||||
}}
|
||||
text="从弄堂里的三毛记忆到画室中的笔墨传承,张乐平先生以一支画笔为刃,划破黑暗现实的迷雾;以一颗赤诚之心,守护万千儿童的童真。他笔下的三毛,从流浪儿到新中国少年,是一个民族的成长缩影;他坚持的艺术,源于生活、归于真诚,是跨越时空的精神纽带。今天,我们站在张乐平故居的画桌前,不仅要回望先生以笔为业、以爱为怀的一生,更要让这份艺术精神内化于心、外化于行,成为新时代中职学子践行初心、传递美好的力量。"
|
||||
/>
|
||||
|
||||
{/* 题目弹窗(旁白结束后出现) */}
|
||||
<MultipleChoiceQuizPanel
|
||||
visible={showQuiz && !quizSuccessVisible}
|
||||
zIndex={10000}
|
||||
title="【多选】张乐平笔下的三毛形象能够跨越时代、深入人心,核心是因为承载了哪些精神品质?"
|
||||
options={[
|
||||
{ value: 'A', label: 'A. 善良悲悯,对弱者充满同情' },
|
||||
{ value: 'B', label: 'B. 勇敢坚韧,在困境中顽强生存' },
|
||||
{ value: 'C', label: 'C. 对正义的坚守,对美好生活的向往' },
|
||||
]}
|
||||
correctAnswer={['A', 'B', 'C']}
|
||||
errorMessage="你的选择还不够全面哦~请你再想想吧!"
|
||||
onSubmit={(values, isCorrect) => {
|
||||
if (isCorrect) {
|
||||
setQuizSuccessVisible(true)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<SuccessAlert
|
||||
visible={quizSuccessVisible}
|
||||
title="恭喜你,选择正确!"
|
||||
onContinue={() => {
|
||||
setQuizSuccessVisible(false)
|
||||
setShowQuiz(false)
|
||||
setVisible(true)
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 视频前引导 */}
|
||||
<GuideSteps
|
||||
visible={visible}
|
||||
onVisibleChange={(v) => {
|
||||
setVisible(v)
|
||||
if (!v) {
|
||||
setShowVideo(true)
|
||||
handleVideoCanPlay()
|
||||
}
|
||||
}}
|
||||
showMask={false}
|
||||
>
|
||||
<GuideStepsItem
|
||||
speaker="student"
|
||||
audioSrc={getPublicPath('audio/zhangleping/mp3_zhangleping_32.mp3')}
|
||||
>
|
||||
小沪,刚刚完成“三毛寻忆”的时空任务太有收获了!从童年学艺的老画桌到新中国的画架,我跟着三毛的记忆碎片,真切感受到张乐平先生用画笔记录时代、守护童心的坚守。
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem speaker="student">
|
||||
尤其是先生笔下三毛的形象从流浪儿到少先队员的转变,还有不同年代里“画笔如刀枪、如镜子、如园丁”的力量,都让我特别触动。但我还想从美术这一艺术创作角度出发更多了解张乐平先生,你能给我讲讲吗?
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem
|
||||
speaker="guide"
|
||||
audioSrc={getPublicPath('audio/zhangleping/mp3_zhangleping_33.mp3')}
|
||||
>
|
||||
你的感悟特别深刻!关于你想了解的美术创作,今天我们有幸邀请到了上海大学美术学院设计系副主任、副教授汪宁,汪教授对张乐平漫画艺术开展过专门研究,对先生的创作理念与时代价值有着深入的理解。
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem speaker="guide">
|
||||
接下来,就让我们跟随汪教授一起,探寻张乐平艺术作品和艺术精神的当代意义吧!
|
||||
</GuideStepsItem>
|
||||
</GuideSteps>
|
||||
|
||||
{/* 内化主视频 */}
|
||||
{showVideo && (
|
||||
<Video
|
||||
ref={videoRef}
|
||||
src={getPublicPath('video/zhangleping/zhangleping_neihua.mp4')}
|
||||
className="h-full w-full"
|
||||
anchors={anchors}
|
||||
playsInline
|
||||
controls
|
||||
onSkip={() => {
|
||||
setShowVideo(false)
|
||||
setPostGuideVisible(true)
|
||||
}}
|
||||
onCanPlay={handleVideoCanPlay}
|
||||
onEnded={() => {
|
||||
setShowVideo(false)
|
||||
// 学习视频结束后,先展示对话,再进入写信
|
||||
setPostGuideVisible(true)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* 学习视频结束后的对话引导 */}
|
||||
<GuideSteps
|
||||
visible={postGuideVisible}
|
||||
onVisibleChange={(v) => {
|
||||
setPostGuideVisible(v)
|
||||
if (!v) {
|
||||
setShowLetter(true)
|
||||
}
|
||||
}}
|
||||
showMask={false}
|
||||
zIndex={60}
|
||||
>
|
||||
<GuideStepsItem
|
||||
speaker="guide"
|
||||
audioSrc={getPublicPath('audio/zhangleping/mp3_zhangleping_34.mp3')}
|
||||
>
|
||||
张乐平先生的精神,不是挂在墙上的口号,而是“源于生活”的真诚、“化繁为简”的智慧、“向善向美”的坚守。这份精神,藏在三毛的三根头发里,藏在先生的笔墨春秋中,更藏在我们每一个人的日常行动里。
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem speaker="guide">
|
||||
现在,就让我们站在这座承载着温暖与力量的故居中,把对先生的崇敬、对精神的体悟,浓缩进你想对先生说的话中吧!
|
||||
</GuideStepsItem>
|
||||
</GuideSteps>
|
||||
|
||||
{/* 写信组件 */}
|
||||
<LetterToZhangleping
|
||||
visible={showLetter}
|
||||
onClose={() => {
|
||||
setShowLetter(false)
|
||||
}}
|
||||
onSubmit={() => {}}
|
||||
onAnimationEnd={() => {
|
||||
setShowLetter(false)
|
||||
setShowStudyGuide(true)
|
||||
}}
|
||||
showVideo={true}
|
||||
/>
|
||||
|
||||
{/* 内化结束 */}
|
||||
<EndingOverlay
|
||||
visible={showStudyGuide}
|
||||
audioSrc={getPublicPath('audio/zhangleping/mp3_zhangleping_35.mp3')}
|
||||
text="恭喜你圆满完成张乐平故居的学习之旅,请带着研学感悟,前往荣德生旧居继续探访吧~"
|
||||
animationSpeed={200}
|
||||
onContinue={() => {
|
||||
setShowStudyGuide(false)
|
||||
navigate(`/${moduleName}/${starName}/home`)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ZhanglepingInternalization
|
||||
Reference in new issue
Block a user