feat: update residence learning flows
Commit non-media application and asset changes while leaving audio, video, and environment files out of version control. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
68ba22a33f
commit
6d40e19346
184 files changed
+7663
-2203
No files matched your search
@@ -1,9 +1,9 @@
|
||||
import { EndingOverlay, Image, StudyGuideModal } from '@/components'
|
||||
import { EndingOverlay, Image, StudyGuideModal, Video } from '@/components'
|
||||
import { cn, getBackgroundImage, getPublicPath, getStaticImage } from '@/lib/utils'
|
||||
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { useNavigate, useParams } from 'react-router-dom'
|
||||
import { useLocation, useNavigate, useParams } from 'react-router-dom'
|
||||
import { LOBBY_COLUMNS, LOBBY_LAYOUT, LOBBY_TIMELINE } from './lobby.config'
|
||||
import { useNieerStore } from '@/store/nieerStore'
|
||||
import { saveNieerStore, useNieerStore } from '@/store/nieerStore'
|
||||
import { useDialogReducer } from './useDialogReducer'
|
||||
import DialogLayer from './DialogLayer'
|
||||
import {
|
||||
@@ -15,11 +15,16 @@ import {
|
||||
getUnlockVideoSrcForScene,
|
||||
getUnlockedByIdMap,
|
||||
} from './reflectionProgress'
|
||||
import { usePuzzleAnimation } from '@/contexts/PuzzleAnimationContext'
|
||||
import { setCourseTimeProgress } from '@/lib/utils/api-common'
|
||||
|
||||
const starName = 'nieer'
|
||||
|
||||
const NieerReflection = () => {
|
||||
const navigate = useNavigate()
|
||||
const location = useLocation()
|
||||
const fromReflectionSubpage = !!(location.state as { fromReflectionSubpage?: boolean } | null)
|
||||
?.fromReflectionSubpage
|
||||
const { moduleName } = useParams<{ moduleName: string }>()
|
||||
const debugLobby = new URLSearchParams(window.location.search).get('debugLobby') === '1'
|
||||
const visitedReflectionCursors = useNieerStore((state) => state.visitedReflectionCursors)
|
||||
@@ -27,7 +32,14 @@ const NieerReflection = () => {
|
||||
const setReflectionWork = useNieerStore((state) => state.setReflectionWork)
|
||||
const hasSeenReflectionGuide = useNieerStore((state) => state.hasSeenReflectionGuide)
|
||||
const markReflectionGuideSeen = useNieerStore((state) => state.markReflectionGuideSeen)
|
||||
const showGuideModal = !hasSeenReflectionGuide
|
||||
const hasSeenBoxHint = useNieerStore((state) => state.hasSeenBoxHint)
|
||||
const markBoxHintSeen = useNieerStore((state) => state.markBoxHintSeen)
|
||||
const [showOpeningVideo, setShowOpeningVideo] = useState(!fromReflectionSubpage)
|
||||
const showGuideModal = !showOpeningVideo && !hasSeenReflectionGuide
|
||||
const showBoxHint = !showOpeningVideo && !showGuideModal && !hasSeenBoxHint
|
||||
|
||||
// 获取碎片动画触发方法
|
||||
const { triggerPuzzleAnimation } = usePuzzleAnimation()
|
||||
|
||||
const {
|
||||
state: dialogState,
|
||||
@@ -59,10 +71,11 @@ const NieerReflection = () => {
|
||||
dialogState.mode === 'idle' &&
|
||||
allPlacesCompleted
|
||||
) {
|
||||
triggerPuzzleAnimation(14)
|
||||
setEndingVisible(true)
|
||||
}
|
||||
prevDialogModeRef.current = dialogState.mode
|
||||
}, [dialogState.mode, allPlacesCompleted])
|
||||
}, [dialogState.mode, allPlacesCompleted, triggerPuzzleAnimation])
|
||||
|
||||
const handleResultShare = (sceneId: number, payload?: Record<string, unknown>) => {
|
||||
handleShare({
|
||||
@@ -78,6 +91,21 @@ const NieerReflection = () => {
|
||||
className="w-full h-full relative bg-cover bg-center bg-no-repeat overflow-hidden"
|
||||
style={{ backgroundImage: getBackgroundImage(`${starName}/reflection/lobby/场景首页底图`) }}
|
||||
>
|
||||
{showOpeningVideo && (
|
||||
<div className="fixed inset-0 z-10000 w-full h-full bg-black">
|
||||
<Video
|
||||
src={getPublicPath('video/reflection/nieer_tiwu_00.mp4')}
|
||||
autoPlay
|
||||
playsInline
|
||||
showSkipButton
|
||||
skipText="跳过"
|
||||
onEnded={() => setShowOpeningVideo(false)}
|
||||
onSkip={() => setShowOpeningVideo(false)}
|
||||
onError={() => setShowOpeningVideo(false)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Image
|
||||
className="absolute right-6 top-5 z-30"
|
||||
src={getStaticImage('components/返回')}
|
||||
@@ -198,7 +226,7 @@ const NieerReflection = () => {
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="absolute left-0 bottom-0 w-full h-[201px] z-20 flex justify-center items-center pt-20 gap-10"
|
||||
className="absolute left-0 bottom-0 w-full h-[201px] z-1 flex justify-center items-center pt-20 gap-10 pointer-events-none"
|
||||
style={{
|
||||
backgroundImage: getBackgroundImage(`${starName}/reflection/lobby/footer`),
|
||||
}}
|
||||
@@ -227,13 +255,30 @@ const NieerReflection = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Image
|
||||
button
|
||||
src={getStaticImage(`${starName}/reflection/lobby/icon/旅行箱`)}
|
||||
className="absolute right-0 bottom-0 z-30"
|
||||
alt="旅行箱"
|
||||
onClick={() => navigate(`/${moduleName}/${starName}/reflection/box`)}
|
||||
/>
|
||||
<div className="absolute right-0 bottom-0 z-30">
|
||||
{showBoxHint && (
|
||||
<>
|
||||
<div className="absolute -left-85 -top-45 flex flex-col items-center bg-[#3a2a1a]/85 rounded-xl px-8 py-5 border-2 border-[#fcc419] animate-pulse">
|
||||
<span className="text-4xl text-white font-bold [text-shadow:_0_0_10px_rgba(252,196,25,0.8)] whitespace-nowrap">
|
||||
点击「领取旅行箱」
|
||||
</span>
|
||||
<br />
|
||||
<span className="text-3xl text-[#fcc419] font-bold [text-shadow:_0_0_10px_rgba(0,0,0,0.8)] whitespace-nowrap">
|
||||
旅行箱会记录你每段旅行的成果哦!
|
||||
</span>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<Image
|
||||
button
|
||||
src={getStaticImage(`${starName}/reflection/lobby/icon/旅行箱`)}
|
||||
alt="旅行箱"
|
||||
onClick={() => {
|
||||
markBoxHintSeen()
|
||||
navigate(`/${moduleName}/${starName}/reflection/box`)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{debugLobby && (
|
||||
<div
|
||||
@@ -260,9 +305,10 @@ const NieerReflection = () => {
|
||||
audioSrc={getPublicPath('audio/nieer/mp3_nieer_28.mp3')}
|
||||
firstLineIndent="2em"
|
||||
>
|
||||
{`同学你好,欢迎来到“跨越时空·体悟”学习模块!
|
||||
请登陆“时空回溯・亲历时代”体验仓,下一站:1936年,上海。
|
||||
请带上你的旅行包,穿越时空解锁6个国歌故事,集齐精神徽章,绘制属于你的国歌精神图谱吧~时空门已开,请出发吧!`}
|
||||
{`同学你好,欢迎来到”跨越时空·体悟”学习模块!
|
||||
请登陆”时空回溯・亲历时代”体验仓,下一站:1936年,上海。
|
||||
请带上你的旅行包,穿越时空解锁6个国歌故事,集齐精神徽章,绘制属于你的国歌精神图谱吧~
|
||||
别忘了右下角的旅行箱哦,它会记录你每段旅行的成果!时空门已开,请出发吧!`}
|
||||
</StudyGuideModal>
|
||||
|
||||
<EndingOverlay
|
||||
@@ -272,6 +318,8 @@ const NieerReflection = () => {
|
||||
text={`恭喜你完成所有时空旅行!成功绘制“国歌精神图谱”,解锁6个跨越时空的国歌故事~国歌的故事还在继续,它的精神藏在每一次唱响、每一次坚守中。愿你带着这份精神力量,做国歌的传承者、爱国的践行者!`}
|
||||
onContinue={() => {
|
||||
setEndingVisible(false)
|
||||
saveNieerStore()
|
||||
setCourseTimeProgress(14)
|
||||
navigate(`/${moduleName}/${starName}/home`)
|
||||
}}
|
||||
/>
|
||||
|
||||
Reference in new issue
Block a user