fix: 修复开发/测试包模拟进度被易班同步覆盖的问题
进度模拟面板写入 puzzleStore 后,App 启动时易班同步会将其覆盖; 现在在同步完成后按 sessionStorage 中保存的模式重放模拟进度, 确保测试包的"到达某故居/全流程完成"调试入口生效。 同时纳入近期未提交的页面、组件、资源与环境变量改动。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
6d40e19346
commit
49ecabbf3a
155 files changed
+1956
-724
No files matched your search
@@ -4,7 +4,24 @@ import { Image } from '@/components'
|
||||
import { usePuzzleStore } from '@/store/puzzleStore'
|
||||
import { getResidenceStageUnlocks, isResidenceUnlocked } from '@/config/progression'
|
||||
import { useNavigate, useParams } from 'react-router-dom'
|
||||
import { useRongdeshengStore } from '@/store/rongdeshengStore'
|
||||
import { getUserDefineResult } from '@/lib/utils/api-common'
|
||||
import { showYibanSyncErrorPrompt, showYibanUnauthenticatedPrompt } from '@/components'
|
||||
import {
|
||||
RONGDESHENG_KEY,
|
||||
RONGDESHENG_LESSON_ID,
|
||||
useRongdeshengStore,
|
||||
} from '@/store/rongdeshengStore'
|
||||
|
||||
const deserializeVisitedExhibits = (
|
||||
data: Record<string, number[]> | undefined
|
||||
): Record<string, Set<number>> => {
|
||||
if (!data || typeof data !== 'object') return {}
|
||||
const visitedExhibits: Record<string, Set<number>> = {}
|
||||
for (const [place, exhibits] of Object.entries(data)) {
|
||||
visitedExhibits[place] = new Set(Array.isArray(exhibits) ? exhibits : [])
|
||||
}
|
||||
return visitedExhibits
|
||||
}
|
||||
|
||||
const RongdeshengHome = () => {
|
||||
const navigate = useNavigate()
|
||||
@@ -25,6 +42,64 @@ const RongdeshengHome = () => {
|
||||
}
|
||||
}, [isLoaded, navigate, puzzles, starName])
|
||||
|
||||
useEffect(() => {
|
||||
;(async () => {
|
||||
try {
|
||||
const result = await getUserDefineResult(RONGDESHENG_LESSON_ID, RONGDESHENG_KEY)
|
||||
|
||||
if (result.status !== 'success') {
|
||||
useRongdeshengStore.setState((prev) => ({
|
||||
...prev,
|
||||
visitedExhibits: {},
|
||||
lastVisitedPlace: null,
|
||||
reflectionCompleted: {},
|
||||
reflectionVideoViewed: {},
|
||||
reflectionFinalCompleted: false,
|
||||
reflectionGuideShown: false,
|
||||
}))
|
||||
|
||||
if (result.status === 'unauthenticated') {
|
||||
showYibanUnauthenticatedPrompt()
|
||||
} else if (result.status === 'error') {
|
||||
showYibanSyncErrorPrompt()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const data = JSON.parse(result.content) as {
|
||||
visitedExhibits?: Record<string, number[]>
|
||||
lastVisitedPlace?: string | null
|
||||
reflectionCompleted?: Record<string, boolean>
|
||||
reflectionVideoViewed?: Record<string, Record<string, boolean>>
|
||||
reflectionFinalCompleted?: boolean
|
||||
reflectionGuideShown?: boolean
|
||||
}
|
||||
|
||||
useRongdeshengStore.setState((prev) => ({
|
||||
...prev,
|
||||
visitedExhibits: deserializeVisitedExhibits(data.visitedExhibits),
|
||||
lastVisitedPlace: data.lastVisitedPlace ?? null,
|
||||
reflectionCompleted: data.reflectionCompleted ?? {},
|
||||
reflectionVideoViewed: data.reflectionVideoViewed ?? {},
|
||||
reflectionFinalCompleted: data.reflectionFinalCompleted ?? false,
|
||||
reflectionGuideShown: data.reflectionGuideShown ?? false,
|
||||
}))
|
||||
} catch (error) {
|
||||
useRongdeshengStore.setState((prev) => ({
|
||||
...prev,
|
||||
visitedExhibits: {},
|
||||
lastVisitedPlace: null,
|
||||
reflectionCompleted: {},
|
||||
reflectionVideoViewed: {},
|
||||
reflectionFinalCompleted: false,
|
||||
reflectionGuideShown: false,
|
||||
}))
|
||||
showYibanSyncErrorPrompt()
|
||||
console.error('Failed to load Rongdesheng store', error)
|
||||
}
|
||||
})()
|
||||
}, [])
|
||||
|
||||
if (!moduleName) return null
|
||||
|
||||
return (
|
||||
|
||||
Reference in new issue
Block a user