feat:修改英文双引号

This commit is contained in:
kevinzhu committed 2026-04-30 09:17:31 +08:00
commit 4a2be3b4d0
1351 files changed
+56547

No files matched your search

+342
View File
@@ -0,0 +1,342 @@
import { useState, useEffect } from 'react'
import { useNavigate, useParams } from 'react-router-dom'
import { Image, StudyGuideModal } from '@/components'
import SuccessAlert from '@/components/layout/alert/success-alert'
import { getBackgroundImage, getPublicPath, getStaticImage } from '@/lib/utils'
import { usePuzzleAnimation } from '@/contexts/PuzzleAnimationContext'
import { useLuxunStore, saveLuxunStore } from '@/store/luxunStore'
const starName = 'luxun'
// 城市配置 - 根据效果图调整位置
// 布局:北京(上) -> 上海(中上) -> 绍兴(中) -> 广州(左下) -> 厦门(右下)
const cityConfig = [
{
id: 1,
name: '绍兴',
location: '绍兴三味书屋',
imagePath: 'luxun/reflection/scene1/绍兴',
position: { top: '65%', left: '65%' }, // 中间
iconPosition: { top: '0%', left: '0%' },
time: '1892年-1898年',
description: '少年鲁迅在此求学,为《从百草园到三味书屋》埋下创作种子。',
},
{
id: 2,
name: '北京',
location: '北京八道湾胡同',
imagePath: 'luxun/reflection/scene1/北京',
position: { top: '14%', left: '62%' }, // 顶部
iconPosition: { top: '43%', left: '0%' },
time: '1919-1923年',
description: '鲁迅参与新文化运动的核心时期,《阿Q正传》等经典作品在此酝酿创作。',
},
{
id: 3,
name: '厦门',
location: '厦门大学',
imagePath: 'luxun/reflection/scene1/厦门',
position: { top: '83%', left: '78%' }, // 右下
iconPosition: { top: '16%', left: '40%' },
time: '1926年9-12月',
description: '鲁迅应邀前往厦门大学任教,期间写下多篇批判现实的杂文,关注底层民众命运。',
},
{
id: 4,
name: '广州',
location: '广州白云楼',
imagePath: 'luxun/reflection/scene1/广州',
position: { top: '88%', left: '35%' }, // 左下
iconPosition: { top: '16%', left: '30%' },
time: '1927年3-9月',
description: '先生在此整理旧作,思考民族觉醒之路,《朝花夕拾》部分篇章定稿于此。',
},
{
id: 5,
name: '上海',
location: '上海鲁迅故居',
imagePath: 'luxun/reflection/scene1/上海',
position: { top: '48%', left: '70%' }, // 中上
iconPosition: { top: '0%', left: '0%' },
time: '1933-1936年',
description:
'鲁迅晚年定居地,先生在此写下《故事新编》等作品,与进步文人并肩,以文字为刃批判黑暗。',
},
]
const LuxunReflectionScene1 = () => {
const navigate = useNavigate()
const { moduleName } = useParams<{
moduleName: string
}>()
//碎片动画触发方法
const { triggerPuzzleAnimation } = usePuzzleAnimation()
const { setReflectionRoute } = useLuxunStore()
// 已点击的城市ID集合
const [clickedCities, setClickedCities] = useState<Set<number>>(new Set())
// 是否显示成功提示(全部完成时)
const [showSuccessAlert, setShowSuccessAlert] = useState(false)
// 当前显示的城市提示ID(单个地点点击后)
const [currentCityAlertId, setCurrentCityAlertId] = useState<number | null>(null)
// 是否全部完成
const [allCompleted, setAllCompleted] = useState(false)
// 学习引导对话是否显示
const [showGuideModal, setShowGuideModal] = useState(true)
const progress = clickedCities.size
// 当前应当点亮的城市索引(按照 cityConfig 顺序)
const nextCityIndex = progress
const nextCityId = cityConfig[nextCityIndex]?.id
const totalTasks = cityConfig.length
// 检查是否全部完成
useEffect(() => {
if (progress === totalTasks && !allCompleted) {
setAllCompleted(true)
}
}, [progress, totalTasks, allCompleted])
const handleCityClick = (cityId: number) => {
// 仅允许按照 cityConfig 顺序点击
if (clickedCities.has(cityId)) return // 已点击过的不再处理
if (cityId !== nextCityId) return // 不是当前应点击的城市则不响应
setClickedCities((prev) => {
const next = new Set(prev)
next.add(cityId)
return next
})
// 显示当前城市的成功提示
setCurrentCityAlertId(cityId)
}
const handleSuccessAlertClose = () => {
setShowSuccessAlert(false)
}
const handleCityAlertClose = () => {
const cityId = currentCityAlertId
setCurrentCityAlertId(null)
// 如果关闭的是最后一个城市(上海鲁迅故居,id=5),则显示全部完成的提示
const lastCity = cityConfig[cityConfig.length - 1]
if (lastCity && cityId === lastCity.id) {
triggerPuzzleAnimation(14)
setShowSuccessAlert(true)
}
}
// 获取当前显示的城市信息
const currentCity = currentCityAlertId
? cityConfig.find((city) => city.id === currentCityAlertId)
: null
return (
<div
className="flex justify-between w-full h-full bg-cover bg-center bg-no-repeat gap-8 relative"
style={{
backgroundImage: getBackgroundImage(`${starName}/reflection/scene1/底图`),
}}
>
{/* 离开按钮 */}
<Image
className="absolute right-5 top-5 z-10"
src={getStaticImage(`${starName}/reflection/scene1/离开`)}
button
onClick={() => {
if (moduleName && starName) {
navigate(`/${moduleName}/${starName}/home`)
}
}}
/>
{/* 左侧:鲁迅的文学足迹 - 地图区域 */}
<div className="w-[45%] relative">
{/* 地图容器 */}
<div className="relative w-full h-full">
{cityConfig.map((city) => {
const isClicked = clickedCities.has(city.id)
const isNext = city.id === nextCityId
return (
<div
key={city.id}
className="absolute flex flex-col items-center cursor-pointer hover:scale-110 transition-all duration-300"
style={{
top: city.position.top,
left: city.position.left,
transform: 'translate(-50%, -50%)',
}}
onClick={() => handleCityClick(city.id)}
>
{/* 城市图片容器 */}
<div className="relative">
<img
src={getStaticImage(city.imagePath)}
alt={city.name}
className={`transition-all duration-300 ${
isClicked ? 'brightness-100' : 'brightness-50 grayscale'
}`}
style={{
filter: isClicked ? 'none' : 'grayscale(100%) brightness(0.5)',
}}
/>
{/* 点击图标和提示 - 覆盖在城市图片上 */}
<div
className="absolute -translate-x-full -translate-y-full flex flex-col items-center z-10 pointer-events-none"
style={{
left: city.iconPosition.left,
top: city.iconPosition.top,
}}
>
{/* 点一点提示 - 始终显示 */}
{/* 仅对当前应点击的城市显示点一点提示 */}
{!isClicked && isNext && (
<div className="flex items-center">
<img
src={getStaticImage(`${starName}/reflection/scene1/鲁迅体悟改版点一点`)}
alt="点一点"
/>
<img
className="animate-finger-bounce scale-y-[-1]"
src={getStaticImage(`${starName}/reflection/scene1/鲁迅体悟点一点图标`)}
alt="点一点图标"
/>
</div>
)}
</div>
</div>
</div>
)
})}
</div>
</div>
{/* 导航栏 */}
<div className="absolute top-5 left-[37%] w-80 space-y-4 z-99">
{/* 任务1点亮图标 */}
<div className="text-4xl font-bold h-16 cursor-pointer"></div>
{/* 任务2漫集美学 */}
<div
className="text-4xl font-bold h-16 cursor-pointer relative"
onClick={() => {
if (moduleName && allCompleted) {
setReflectionRoute('reflection2')
saveLuxunStore()
navigate(`/${moduleName}/${starName}/reflection2`)
}
}}
>
{/* 任务完成后显示点一点图标 */}
{allCompleted && (
<div className="absolute -right-20 top-1/2 flex items-center gap-2 z-10 pointer-events-none">
<img
className="animate-finger-bounce scale-x-[-1]"
src={getStaticImage(`${starName}/reflection/scene1/鲁迅体悟点一点图标`)}
alt="点一点图标"
/>
</div>
)}
</div>
{/* 任务3学习精神 */}
<div className="text-4xl font-bold h-16 cursor-pointer"></div>
</div>
{/* 右侧区域 */}
<div className="flex-1 relative">
{/* 任务进度 */}
<div className="absolute top-5 left-[24%] w-[445px] h-55 flex justify-center items-center">
<span className="text-white text-[54px] font-bold [text-shadow:_0px_0px_4px_#b37921,_6px_6px_4px_#b37921,_6px_6px_4px_#b37921,_6px_6px_4px_#b37921]">
{allCompleted ? '任务进度已完成' : `任务进度:(${progress}/${totalTasks})`}
</span>
</div>
{/* 任务展示窗口 */}
<div className="absolute bottom-0 right-7 w-[995px] h-[728px] font-bold text-6xl px-10 py-10 ">
{allCompleted ? (
// 全部完成后显示详细信息
<div className="space-y-10 h-full overflow-y-auto custom-scrollbar">
{cityConfig.map((city) => (
<div key={city.id} className="space-y-2">
<div className="text-red-600 text-3xl flex items-end gap-6">
<div>{city.location}</div>
<div className="text-gray-600 text-2xl font-normal">{city.time}</div>
</div>
<div className="text-black text-2xl font-normal leading-relaxed">
{city.description}
</div>
</div>
))}
</div>
) : (
<div className="space-y-16">
{
// 未完成时显示任务列表
cityConfig.map((city, index) => {
const isCompleted = clickedCities.has(city.id)
return (
<div key={city.id} className={isCompleted ? 'text-green-600' : ''}>
{index + 1}.{city.location}
</div>
)
})
}
</div>
)}
</div>
</div>
{/* 单个地点点击成功提示弹窗 */}
{currentCity && (
<SuccessAlert
visible={true}
title=""
// title={`你找到了${currentCity.location}!`}
content={`${currentCity.time},\n${currentCity.description}`}
onClose={handleCityAlertClose}
onContinue={handleCityAlertClose}
/>
)}
{/* 全部完成成功提示弹窗 */}
<SuccessAlert
visible={showSuccessAlert}
title="你找到了鲁迅创作的足迹,接下来,填充文字里的故事吧!"
onClose={handleSuccessAlertClose}
onContinue={handleSuccessAlertClose}
/>
{/* 学习引导对话 */}
{/* <GuideSteps
visible={guideVisible}
onVisibleChange={setGuideVisible}
showMask={false}
highlightSelectors={[]}
zIndex={10000}
>
<GuideStepsItem speaker="guide">
跟着先生的脚步, 解锁文字里的温度与力量!
</GuideStepsItem>
<GuideStepsItem speaker="guide">
请根据年代由远及近的顺序,依“手指提示”点亮先生的创作足迹,解锁更多的故事背景!
</GuideStepsItem>
</GuideSteps> */}
<StudyGuideModal
visible={showGuideModal}
onContinue={() => {
setShowGuideModal(false)
}}
audioSrc={getPublicPath('audio/luxun/mp3_luxun_31.mp3')}
contentPaddingLeft="2em"
// firstLineIndent="2em"
>
{`同学你好,欢迎来到“跨越时空·体悟”学习模块!
请登陆“时空回溯・亲历时代”体验仓,下一站:1892年,绍兴三味书屋。
请按照年代由远及近的顺序,依“手指提示”,点亮先生的创作足迹,解锁更多故事背景!时空门已开,请做好准备吧!`}
</StudyGuideModal>
</div>
)
}
export default LuxunReflectionScene1