- 在 Cursor 组件中添加禁用状态,增强用户交互体验。 - 更新多个场景以使用新的光标控制逻辑,确保光标的启用状态与展品访问状态相匹配。 - 在信件组件中添加输入校验功能,提升用户填写体验。 - 调整文本内容和引导对话,确保信息准确性和一致性。
187 lines
5.8 KiB
TypeScript
187 lines
5.8 KiB
TypeScript
import { useState, useRef } from "react";
|
|
import {
|
|
ExhibitOverlay,
|
|
Title,
|
|
Image,
|
|
Cursor,
|
|
Video,
|
|
GuideSteps,
|
|
GuideStepsItem,
|
|
} from "@/components";
|
|
import { getBackgroundImage, getStaticImage, getPublicPath } from "@/lib/utils";
|
|
import { useNavigate, useParams } from "react-router-dom";
|
|
import type { VideoRef } from "@/components/video";
|
|
import { useChenyunStore } from "@/store/chenyunStore";
|
|
import { usePuzzleAnimation } from "@/contexts/PuzzleAnimationContext";
|
|
|
|
// starName 固定为 chenyun
|
|
const starName = "chenyun";
|
|
|
|
// 展品 ID 与资源路径映射
|
|
const exhibitSrcMap: Record<1, string> = {
|
|
1: "chenyun/place9/场景9展品1",
|
|
};
|
|
const ChenyunPlace9 = () => {
|
|
const navigate = useNavigate();
|
|
const { moduleName } = useParams<{
|
|
moduleName: string;
|
|
}>();
|
|
|
|
// 获取碎片动画触发方法
|
|
const { triggerPuzzleAnimation } = usePuzzleAnimation();
|
|
|
|
const [activeExhibitId, setActiveExhibitId] = useState<1 | null>(null);
|
|
|
|
// 使用持久化的访问状态
|
|
const place = "place9";
|
|
const { isExhibitVisited, markExhibitVisited, getVisitedExhibits } =
|
|
useChenyunStore();
|
|
|
|
// 从 store 获取已访问的展品,转换为 Set 用于兼容现有代码
|
|
const visitedExhibits = getVisitedExhibits(place);
|
|
const visited = new Set(visitedExhibits);
|
|
// 视频播放状态
|
|
const [videoVisible, setVideoVisible] = useState(false);
|
|
const [videoPlaying, setVideoPlaying] = useState(false);
|
|
const videoRef = useRef<VideoRef>(null);
|
|
// 对话引导状态
|
|
const [guideVisible, setGuideVisible] = useState(false);
|
|
const [guideStep, setGuideStep] = useState(0);
|
|
|
|
const handleOpenExhibit = (_index: 1) => {
|
|
// 展品1:播放视频
|
|
setVideoVisible(true);
|
|
setVideoPlaying(true);
|
|
};
|
|
|
|
// 监听对话引导步骤变化
|
|
const handleGuideStepChange = (step: number) => {
|
|
setGuideStep(step);
|
|
};
|
|
|
|
// 监听对话引导完成
|
|
const handleGuideVisibleChange = (visible: boolean) => {
|
|
setGuideVisible(visible);
|
|
if (!visible && videoVisible) {
|
|
setVideoVisible(false);
|
|
}
|
|
};
|
|
|
|
const progressCount = visited.size;
|
|
const total = 1;
|
|
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;
|
|
return (
|
|
<div
|
|
className="w-full h-full bg-cover bg-center bg-no-repeat"
|
|
style={{
|
|
backgroundImage: getBackgroundImage(`chenyun/place9/场景9`),
|
|
}}
|
|
>
|
|
{/* 标题 */}
|
|
<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={() => {
|
|
if (moduleName && starName) {
|
|
navigate(`/${moduleName}/${starName}/place8`);
|
|
}
|
|
}}
|
|
/>
|
|
|
|
{/* 展品1 */}
|
|
<Cursor
|
|
className="absolute right-26 top-88"
|
|
onClick={() => handleOpenExhibit(1)}
|
|
read={visited.has(1)}
|
|
/>
|
|
|
|
{/* 离开场景 - 仅在完成所有展品后显示 */}
|
|
{completed && (
|
|
<Image
|
|
className="absolute bottom-0 right-0"
|
|
src={getStaticImage("chenyun/place9/离开场景")}
|
|
button
|
|
onClick={() => {
|
|
navigate(`/${moduleName}/${starName}/home`);
|
|
}}
|
|
/>
|
|
)}
|
|
|
|
{/* 展品1视频播放(全屏) */}
|
|
{videoVisible && (
|
|
<div className="fixed inset-0 z-[9999] bg-black">
|
|
<Video
|
|
ref={videoRef}
|
|
src={getPublicPath("video/chenyun/chenyun_14.mp4")}
|
|
className="w-full h-full"
|
|
autoPlay={videoPlaying}
|
|
playsInline
|
|
preload="auto"
|
|
muted={!videoPlaying}
|
|
showSkipButton
|
|
skipText="跳过"
|
|
onEnded={() => {
|
|
setVideoPlaying(false);
|
|
markExhibitVisited(place, 1);
|
|
// 视频播放完成后,显示对话引导
|
|
setGuideVisible(true);
|
|
setGuideStep(0);
|
|
triggerPuzzleAnimation(12);
|
|
}}
|
|
/>
|
|
</div>
|
|
)}
|
|
|
|
{/* 视频播放完成后的对话引导 */}
|
|
<GuideSteps
|
|
visible={guideVisible}
|
|
onVisibleChange={handleGuideVisibleChange}
|
|
currentStep={guideStep}
|
|
onStepChange={handleGuideStepChange}
|
|
showMask={false}
|
|
highlightSelectors={[]}
|
|
zIndex={10001}
|
|
>
|
|
<GuideStepsItem speaker="guide">
|
|
我们已经沿着陈云的足迹,从练塘水乡走到改革开放的前沿,读懂了他"适合老百姓的要求,做了一点事"的初心。
|
|
</GuideStepsItem>
|
|
<GuideStepsItem speaker="guide">
|
|
接下来,请你跨越时空,走进1949年刚解放时期的上海,参与到当时那场轰轰烈烈的"银元之战"和"米棉之战"之中去。
|
|
</GuideStepsItem>
|
|
<GuideStepsItem speaker="guide">
|
|
在实践决策中体会陈云"多谋善断""敢闯务实"的卓越智慧与战略魄力,感受我国集中力量办大事的制度优势如何在经济战场中彰显威力。
|
|
</GuideStepsItem>
|
|
</GuideSteps>
|
|
|
|
{/* 遮罩层 */}
|
|
<ExhibitOverlay
|
|
visible={activeExhibitId !== null}
|
|
src={activeExhibitId ? exhibitSrcMap[activeExhibitId] : ""}
|
|
onClose={() => {
|
|
if (activeExhibitId !== null) {
|
|
markExhibitVisited(place, activeExhibitId);
|
|
}
|
|
setActiveExhibitId(null);
|
|
}}
|
|
/>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default ChenyunPlace9;
|