feat: 实现故居续学弹窗功能

新增功能:
- 统一续学逻辑:8个故居首页接入自动续学提示弹窗
- 完成判定:基于拼图碎片统一判断对话/体悟/内化是否完成
- 断点续学:对话回lastVisitedPlace、体悟回reflectionRoute、内化回internalization
- 触发条件:会话内每故居仅提示一次 + 首页视频播完后 + store加载成功/空时
- 安全防护:组件卸载后不再setState、同步失败不弹窗避免用旧状态误导

新增组件:
- ContinueLearningModal:纯CSS哑光米纸+朱红古籍风弹窗
- useResidenceContinue:封装触发逻辑+跳转+去重的共享hook

涉及文件:
- src/config/progression.ts:getResidenceStageCompletion、resolveResidenceContinueTarget
- src/hooks/useResidenceContinue.ts:统一续学hook
- src/components/layout/alert/continue-learning-modal.tsx:弹窗组件
- src/pages/*/home.tsx:8个故居首页接入

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
zhongyidianandClaude Opus 4.8 committed 2026-06-21 21:44:27 +08:00
1 parent 49ecabbf3a
commit 73d02eb62d
13 files changed
+539 -500

No files matched your search

+75
View File
@@ -77,3 +77,78 @@ export const getResidenceStageUnlocks = (residence: string, puzzles: PuzzleProgr
arePiecesUnlocked(residence, puzzles, getPieceIdsByRoute(residence, 'reflection')),
}
}
export interface ResidenceStageCompletion {
dialogueComplete: boolean
reflectionComplete: boolean
internalizationComplete: boolean
residenceComplete: boolean
}
/**
* 基于拼图碎片统一判定每个故居三阶段是否完成。
* 每个故居 16 块碎片天然按 route 分为 place* / reflection* / internalization 三段,
* 收齐对应碎片即视为该阶段完成。
*/
export const getResidenceStageCompletion = (
residence: string,
puzzles: PuzzleProgress
): ResidenceStageCompletion => {
const dialogueComplete = arePiecesUnlocked(
residence,
puzzles,
getPieceIdsByRoute(residence, 'place')
)
const reflectionComplete = arePiecesUnlocked(
residence,
puzzles,
getPieceIdsByRoute(residence, 'reflection')
)
const internalizationComplete = arePiecesUnlocked(
residence,
puzzles,
getPieceIdsByRoute(residence, 'internalization')
)
return {
dialogueComplete,
reflectionComplete,
internalizationComplete,
residenceComplete: dialogueComplete && reflectionComplete && internalizationComplete,
}
}
export interface ResidenceContinueInput {
completion: ResidenceStageCompletion
/** 对话模块断点(place1~placeN),各故居 store 均有 */
lastVisitedPlace?: string | null
/** 体悟模块断点路由,仅部分多场景故居(孙中山/鲁迅/黄炎培)有 */
reflectionRoute?: string | null
}
/**
* 计算「继续学习」应跳转到的目标路由——取第一个未完成的阶段。
* - 对话未完成 → lastVisitedPlace || 'place1'
* - 体悟未完成 → reflectionRoute || 'reflection'
* - 内化未完成 → 'internalization'
* - 全部完成 → null(无需续学)
*
* 这些路由都是各故居 home/场景现有逻辑已经在用的跳转目标,
* 单场景体悟(毛泽东/陈云/聂耳/荣德生)统一落到 'reflection' 由页面自管进度。
*/
export const resolveResidenceContinueTarget = ({
completion,
lastVisitedPlace,
reflectionRoute,
}: ResidenceContinueInput): string | null => {
if (!completion.dialogueComplete) {
return lastVisitedPlace || 'place1'
}
if (!completion.reflectionComplete) {
return reflectionRoute || 'reflection'
}
if (!completion.internalizationComplete) {
return 'internalization'
}
return null
}