更新依赖项及历史人物相关内容资源
- 更新 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,176 @@
|
||||
import {
|
||||
EndingOverlay,
|
||||
ExhibitOverlay,
|
||||
GuideSteps,
|
||||
GuideStepsItem,
|
||||
Image,
|
||||
Title,
|
||||
} from '@/components'
|
||||
import Cursor from '@/components/cursor'
|
||||
import { getBackgroundImage, getPublicPath, getStaticImage } from '@/lib/utils'
|
||||
import { useRef, useState } from 'react'
|
||||
import { useNavigate, useParams } from 'react-router-dom'
|
||||
import { useNieerStore, saveNieerStore } from '@/store/nieerStore'
|
||||
import { useCursorController } from '@/hooks/useCursorController'
|
||||
|
||||
const NieerPlace6 = () => {
|
||||
const navigate = useNavigate()
|
||||
const { moduleName } = useParams<{ moduleName: string }>()
|
||||
|
||||
const starName = 'nieer'
|
||||
const place = 'place6'
|
||||
const { markExhibitVisited, getVisitedExhibits } = useNieerStore()
|
||||
|
||||
const [activeExhibitId, setActiveExhibitId] = useState<1 | 2 | null>(null)
|
||||
const [guide1Visible, setGuide1Visible] = useState(false)
|
||||
const [guide1Step, setGuide1Step] = useState(0)
|
||||
|
||||
const total = 2
|
||||
const visitedExhibits = getVisitedExhibits(place)
|
||||
const visited = new Set(visitedExhibits)
|
||||
const progressCount = visited.size
|
||||
const completed = progressCount >= total
|
||||
|
||||
const [endingVisible, setEndingVisible] = useState(false)
|
||||
// 是否已展示过结束语(用于控制“离开场景”按钮出现时机)
|
||||
// 若用户刷新页面且已完成,则默认视为结束语已展示,避免卡住无法离开
|
||||
const [endingShown, setEndingShown] = useState(() => completed)
|
||||
const endingShownRef = useRef(false)
|
||||
const subtitle = completed ? '已完成' : `${progressCount}/${total}`
|
||||
|
||||
const { isEnabled } = useCursorController({
|
||||
initialEnabled: [1],
|
||||
dependencies: {
|
||||
2: [1],
|
||||
},
|
||||
visited: visitedExhibits,
|
||||
})
|
||||
|
||||
if (!moduleName) return null
|
||||
|
||||
const exhibitSrcMap: Record<1 | 2, string> = {
|
||||
1: 'nieer/place6/场景6展品1',
|
||||
2: 'nieer/place6/场景6展品2',
|
||||
}
|
||||
|
||||
const handleOpenExhibit = (id: 1 | 2) => {
|
||||
setActiveExhibitId(id)
|
||||
if (id === 1) {
|
||||
setGuide1Step(0)
|
||||
setGuide1Visible(true)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className="w-full h-full bg-cover bg-center bg-no-repeat"
|
||||
style={{
|
||||
backgroundImage: getBackgroundImage(`${starName}/${place}/场景6`),
|
||||
}}
|
||||
>
|
||||
<Title
|
||||
title="伟大复兴的主旋律"
|
||||
subtitle={subtitle}
|
||||
className="absolute top-10 left-1/2 -translate-x-1/2"
|
||||
/>
|
||||
|
||||
<Image
|
||||
className="absolute right-5 top-5"
|
||||
src={getStaticImage('components/离开')}
|
||||
button
|
||||
onClick={() => navigate(`/${moduleName}/${starName}/place5`)}
|
||||
/>
|
||||
|
||||
<Cursor
|
||||
className="absolute left-90 bottom-130"
|
||||
onClick={() => handleOpenExhibit(1)}
|
||||
read={visited.has(1)}
|
||||
disabled={!isEnabled(1)}
|
||||
/>
|
||||
<Cursor
|
||||
className="absolute right-240 bottom-135"
|
||||
onClick={() => handleOpenExhibit(2)}
|
||||
read={visited.has(2)}
|
||||
disabled={!isEnabled(2)}
|
||||
/>
|
||||
|
||||
{/* 最后一个场景:完成后不显示“前进”按钮 */}
|
||||
{completed && endingShown && !endingVisible && (
|
||||
<Image
|
||||
className="absolute bottom-0 right-0"
|
||||
src={getStaticImage('components/place/离开场景')}
|
||||
button
|
||||
onClick={() => navigate(`/${moduleName}/${starName}/home`)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<ExhibitOverlay
|
||||
visible={activeExhibitId !== null}
|
||||
src={activeExhibitId ? exhibitSrcMap[activeExhibitId] : ''}
|
||||
onClose={() => {
|
||||
const closingId = activeExhibitId
|
||||
setActiveExhibitId(null)
|
||||
setGuide1Visible(false)
|
||||
|
||||
if (closingId !== null) {
|
||||
markExhibitVisited(place, closingId)
|
||||
saveNieerStore()
|
||||
|
||||
// 仅在“关闭展品”这一刻触发结束语:当本次关闭导致完成时,弹出 EndingOverlay
|
||||
const nextVisitedSize = visited.has(closingId) ? visited.size : visited.size + 1
|
||||
const willComplete = nextVisitedSize >= total
|
||||
if (willComplete && !endingShownRef.current) {
|
||||
endingShownRef.current = true
|
||||
setEndingShown(true)
|
||||
setEndingVisible(true)
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 光标1对话(图1) */}
|
||||
<GuideSteps
|
||||
visible={guide1Visible}
|
||||
currentStep={guide1Step}
|
||||
onStepChange={setGuide1Step}
|
||||
onVisibleChange={setGuide1Visible}
|
||||
showMask={false}
|
||||
highlightSelectors={[]}
|
||||
zIndex={10001}
|
||||
>
|
||||
<GuideStepsItem
|
||||
speaker="student"
|
||||
audioSrc={getPublicPath('audio/nieer/mp3_nieer_place6_01.mp3')}
|
||||
>
|
||||
小沪,这些不同场景下奏响国歌的画面太让人感动了!在和平年代,这首歌还有什么特别的意义呢?
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem
|
||||
speaker="guide"
|
||||
audioSrc={getPublicPath('audio/nieer/mp3_nieer_place6_02.mp3')}
|
||||
>
|
||||
和平年代里,它的精神力量依然不减。你看这张许海峰奥运夺金的照片,国歌奏响时,是民族自豪的宣告;神舟飞船升空时的国歌,是航天人攻坚克难的礼赞;
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem
|
||||
speaker="guide"
|
||||
audioSrc={getPublicPath('audio/nieer/mp3_nieer_place6_03.mp3')}
|
||||
>
|
||||
抗震救灾现场的国歌,是全国人民众志成城的誓言。它就像一根精神纽带,无论在高光时刻还是艰难关头,都能凝聚起全国人民的力量,提醒我们不忘历史、砥砺前行。
|
||||
</GuideStepsItem>
|
||||
</GuideSteps>
|
||||
|
||||
{/* completed 后的结束语:统一使用 EndingOverlay */}
|
||||
<EndingOverlay
|
||||
visible={endingVisible}
|
||||
text={
|
||||
'从民族危机中觉醒的热血青年,到《义勇军进行曲》的谱曲者,聂耳用音符奏响了“救亡图存”的时代强音。' +
|
||||
'而《义勇军进行曲》的影响远不止于此,接下来,请你化身国歌时空旅行者,踏入6个散落于岁月中的故事现场,' +
|
||||
'一路聆听、一路共鸣,亲身体验这首旋律如何跨越时空,成为永远激荡在国人心中的精神号角吧!'
|
||||
}
|
||||
animationSpeed={200}
|
||||
onContinue={() => setEndingVisible(false)}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default NieerPlace6
|
||||
Reference in new issue
Block a user