- Implemented functions to manage puzzle progress including checking if residences are started, complete, and unlocked. - Added utility functions to retrieve piece IDs based on residence and route. - Introduced a new TypeScript file for progression management. - Integrated puzzle data configuration and residence data for seamless progression tracking.
259 lines
7.4 KiB
TypeScript
259 lines
7.4 KiB
TypeScript
import { useState, useEffect } from 'react'
|
|
import { Title, Image, Cursor, StudyGuideModal } from '@/components'
|
|
import { SuccessAlert } from '@/components/layout'
|
|
import { getBackgroundImage, getPublicPath, getStaticImage } from '@/lib/utils'
|
|
import { useNavigate, useParams } from 'react-router-dom'
|
|
import ChoiceDialog1 from './scene2/ChoiceDialog1'
|
|
import ChoiceDialog2 from './scene2/ChoiceDialog2'
|
|
import QuizDialog from './scene2/QuizDialog'
|
|
import {
|
|
useHuangyanpeiStore,
|
|
saveHuangyanpeiStore,
|
|
loadHuangyanpeiStore,
|
|
} from '@/store/huangyanpeiStore'
|
|
import { useCursorController } from '@/hooks/useCursorController'
|
|
|
|
const starName = 'huangyanpei'
|
|
|
|
const HuangyanpeiReflectionScene2 = () => {
|
|
const navigate = useNavigate()
|
|
const { moduleName } = useParams<{
|
|
moduleName: string
|
|
}>()
|
|
|
|
const [showGuideModal, setShowGuideModal] = useState(true)
|
|
const [showDialog1, setShowDialog1] = useState(false)
|
|
const [showDialog2, setShowDialog2] = useState(false)
|
|
const [choice2, setChoice2] = useState<'铁工科' | '商科' | null>(null)
|
|
const [showCompleteGuide, setShowCompleteGuide] = useState(false)
|
|
// 题目显示状态(ChoiceDialog1关闭后)
|
|
const [showQuiz, setShowQuiz] = useState(false)
|
|
// 题目成功提示状态
|
|
const [showQuizSuccess, setShowQuizSuccess] = useState(false)
|
|
|
|
// 使用持久化的reflection cursor状态
|
|
const scene = 'scene2'
|
|
const {
|
|
markReflectionCursorVisited,
|
|
getVisitedReflectionCursors,
|
|
setReflectionRoute,
|
|
reflectionScene2Choice,
|
|
setReflectionScene2Choice,
|
|
hasShownReflectionCompletionGuide,
|
|
markReflectionCompletionGuideShown,
|
|
} = useHuangyanpeiStore()
|
|
|
|
// 从 store 获取已完成的cursor,转换为 Set 用于兼容现有代码
|
|
const visitedCursors = getVisitedReflectionCursors(scene)
|
|
const visited = new Set(visitedCursors)
|
|
|
|
const { isEnabled } = useCursorController({
|
|
initialEnabled: [1],
|
|
dependencies: { 2: [1] },
|
|
visited: visitedCursors,
|
|
})
|
|
|
|
const progressCount = visited.size
|
|
const total = 2
|
|
const completed = progressCount >= total
|
|
const subtitle = completed ? '已完成' : `${progressCount}/${total}`
|
|
const subtitleClassName = completed
|
|
? 'text-[#fff998] [text-shadow:_0_8px_8px_rgba(0,0,0,0.35),_0_0_16px_rgba(0,0,0,0.25)]'
|
|
: undefined
|
|
|
|
// 进入页面时读取缓存中的 choice2
|
|
useEffect(() => {
|
|
let mounted = true
|
|
|
|
const syncChoice2FromCache = async () => {
|
|
await loadHuangyanpeiStore()
|
|
if (!mounted) {
|
|
return
|
|
}
|
|
const latestChoice2 = useHuangyanpeiStore.getState().reflectionScene2Choice
|
|
if (latestChoice2) {
|
|
setChoice2(latestChoice2)
|
|
}
|
|
}
|
|
|
|
void syncChoice2FromCache()
|
|
|
|
return () => {
|
|
mounted = false
|
|
}
|
|
}, [])
|
|
|
|
// 本地状态与 store 中的 choice2 保持同步
|
|
useEffect(() => {
|
|
if (reflectionScene2Choice && reflectionScene2Choice !== choice2) {
|
|
setChoice2(reflectionScene2Choice)
|
|
}
|
|
}, [reflectionScene2Choice, choice2])
|
|
|
|
// 两个任务都完成后,显示完成提示(仅一次)
|
|
useEffect(() => {
|
|
if (completed && choice2 && !hasShownReflectionCompletionGuide(scene)) {
|
|
const timer = setTimeout(() => {
|
|
setShowCompleteGuide(true)
|
|
markReflectionCompletionGuideShown(scene)
|
|
saveHuangyanpeiStore()
|
|
}, 500)
|
|
return () => clearTimeout(timer)
|
|
}
|
|
}, [
|
|
completed,
|
|
choice2,
|
|
scene,
|
|
hasShownReflectionCompletionGuide,
|
|
markReflectionCompletionGuideShown,
|
|
])
|
|
|
|
// 处理完成提示的继续按钮点击
|
|
const handleCompleteGuideContinue = () => {
|
|
setShowCompleteGuide(false)
|
|
// 根据选择决定导航目标
|
|
if (choice2 === '铁工科') {
|
|
setReflectionRoute('reflection3')
|
|
saveHuangyanpeiStore()
|
|
navigate(`/${moduleName}/${starName}/reflection3`)
|
|
} else if (choice2 === '商科') {
|
|
setReflectionRoute('reflection4')
|
|
saveHuangyanpeiStore()
|
|
navigate(`/${moduleName}/${starName}/reflection4`)
|
|
}
|
|
}
|
|
|
|
if (!moduleName) {
|
|
return null
|
|
}
|
|
|
|
return (
|
|
<div
|
|
className="w-full h-full bg-cover bg-center bg-no-repeat"
|
|
style={{
|
|
backgroundImage: getBackgroundImage(`huangyanpei/reflection/scene2/10_001`),
|
|
}}
|
|
>
|
|
<Title
|
|
title="跨越时空"
|
|
subtitle={subtitle}
|
|
subtitleClassName={subtitleClassName}
|
|
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}/home`)
|
|
}}
|
|
/>
|
|
|
|
{completed && (
|
|
<Image
|
|
className="absolute bottom-0 right-0 z-20"
|
|
src={getStaticImage('components/place/继续前进')}
|
|
button
|
|
onClick={() => handleCompleteGuideContinue()}
|
|
/>
|
|
)}
|
|
|
|
<StudyGuideModal
|
|
visible={showGuideModal}
|
|
onContinue={() => setShowGuideModal(false)}
|
|
audioSrc={getPublicPath('audio/huangyanpei/mp3_huangyanpei_24.mp3')}
|
|
firstLineIndent="2em"
|
|
>
|
|
欢迎来到浦东中学!{'\n'}
|
|
这是近代上海第一所完全中学,黄炎培先生当首任校长,在这里能学到更多实用知识,还能树立成才的理想哦。
|
|
</StudyGuideModal>
|
|
|
|
{choice2 && (
|
|
<img
|
|
className="absolute right-[234px] bottom-12.5"
|
|
src={getStaticImage('huangyanpei/reflection/scene2/10_003')}
|
|
alt="已解锁指示牌盖板"
|
|
/>
|
|
)}
|
|
|
|
{/* 互动展品光标1:显示第一个选择弹窗 */}
|
|
<Cursor
|
|
className="absolute left-118 bottom-105"
|
|
onClick={() => {
|
|
setShowDialog1(true)
|
|
}}
|
|
read={visited.has(1)}
|
|
disabled={!isEnabled(1)}
|
|
/>
|
|
|
|
{/* 互动展品光标2:显示第二个选择弹窗 */}
|
|
<Cursor
|
|
className="absolute right-74 bottom-68"
|
|
onClick={() => {
|
|
setShowDialog2(true)
|
|
}}
|
|
read={visited.has(2)}
|
|
disabled={!isEnabled(2)}
|
|
/>
|
|
|
|
{/* 第一个选择弹窗 */}
|
|
<ChoiceDialog1
|
|
visible={showDialog1}
|
|
onClose={() => {
|
|
setShowDialog1(false)
|
|
setShowQuiz(true)
|
|
}}
|
|
onSelect={() => {
|
|
markReflectionCursorVisited(scene, 1)
|
|
}}
|
|
/>
|
|
|
|
{/* 第二个选择弹窗 */}
|
|
<ChoiceDialog2
|
|
visible={showDialog2}
|
|
onClose={() => setShowDialog2(false)}
|
|
onSelect={(choice) => {
|
|
setChoice2(choice)
|
|
setReflectionScene2Choice(choice)
|
|
markReflectionCursorVisited(scene, 2)
|
|
saveHuangyanpeiStore()
|
|
}}
|
|
/>
|
|
|
|
<QuizDialog
|
|
visible={showQuiz}
|
|
onClose={() => setShowQuiz(false)}
|
|
onComplete={() => {
|
|
setShowQuiz(false)
|
|
setShowQuizSuccess(true)
|
|
}}
|
|
/>
|
|
|
|
{/* 题目成功提示 */}
|
|
<SuccessAlert
|
|
visible={showQuizSuccess}
|
|
title=""
|
|
content="恭喜你!选择正确。不愧是从川沙小学堂走出来!"
|
|
onContinue={() => {
|
|
setShowQuizSuccess(false)
|
|
}}
|
|
onClose={() => {
|
|
setShowQuizSuccess(false)
|
|
}}
|
|
/>
|
|
|
|
{/* 完成提示 */}
|
|
<StudyGuideModal
|
|
visible={showCompleteGuide}
|
|
onContinue={handleCompleteGuideContinue}
|
|
verticalAlign="center"
|
|
>
|
|
第二关完成!“职业方向锁定!”去新学校了解你的专业吧。
|
|
</StudyGuideModal>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default HuangyanpeiReflectionScene2
|