diff --git a/src/assets/images/luxun/reflection/scene1/上海.png b/src/assets/images/luxun/reflection/scene1/上海.png new file mode 100644 index 0000000..6a91fda Binary files /dev/null and b/src/assets/images/luxun/reflection/scene1/上海.png differ diff --git a/src/assets/images/luxun/reflection/scene1/北京.png b/src/assets/images/luxun/reflection/scene1/北京.png new file mode 100644 index 0000000..371ed39 Binary files /dev/null and b/src/assets/images/luxun/reflection/scene1/北京.png differ diff --git a/src/assets/images/luxun/reflection/scene1/厦门.png b/src/assets/images/luxun/reflection/scene1/厦门.png new file mode 100644 index 0000000..29b479c Binary files /dev/null and b/src/assets/images/luxun/reflection/scene1/厦门.png differ diff --git a/src/assets/images/luxun/reflection/scene1/广州.png b/src/assets/images/luxun/reflection/scene1/广州.png new file mode 100644 index 0000000..8b17213 Binary files /dev/null and b/src/assets/images/luxun/reflection/scene1/广州.png differ diff --git a/src/assets/images/luxun/reflection/scene1/底图.png b/src/assets/images/luxun/reflection/scene1/底图.png new file mode 100644 index 0000000..255a0bc Binary files /dev/null and b/src/assets/images/luxun/reflection/scene1/底图.png differ diff --git a/src/assets/images/luxun/reflection/scene1/效果图1.jpg b/src/assets/images/luxun/reflection/scene1/效果图1.jpg new file mode 100644 index 0000000..8093c01 Binary files /dev/null and b/src/assets/images/luxun/reflection/scene1/效果图1.jpg differ diff --git a/src/assets/images/luxun/reflection/scene1/效果图2.jpg b/src/assets/images/luxun/reflection/scene1/效果图2.jpg new file mode 100644 index 0000000..f3c9bff Binary files /dev/null and b/src/assets/images/luxun/reflection/scene1/效果图2.jpg differ diff --git a/src/assets/images/luxun/reflection/scene1/离开.png b/src/assets/images/luxun/reflection/scene1/离开.png new file mode 100644 index 0000000..1a07f7d Binary files /dev/null and b/src/assets/images/luxun/reflection/scene1/离开.png differ diff --git a/src/assets/images/luxun/reflection/scene1/绍兴.png b/src/assets/images/luxun/reflection/scene1/绍兴.png new file mode 100644 index 0000000..b7ec71d Binary files /dev/null and b/src/assets/images/luxun/reflection/scene1/绍兴.png differ diff --git a/src/assets/images/luxun/reflection/scene1/鲁迅体悟改版点一点.png b/src/assets/images/luxun/reflection/scene1/鲁迅体悟改版点一点.png new file mode 100644 index 0000000..174a5df Binary files /dev/null and b/src/assets/images/luxun/reflection/scene1/鲁迅体悟改版点一点.png differ diff --git a/src/assets/images/luxun/reflection/scene1/鲁迅体悟点一点图标.png b/src/assets/images/luxun/reflection/scene1/鲁迅体悟点一点图标.png new file mode 100644 index 0000000..6644d1b Binary files /dev/null and b/src/assets/images/luxun/reflection/scene1/鲁迅体悟点一点图标.png differ diff --git a/src/assets/images/luxun/reflection/scene2/上海.png b/src/assets/images/luxun/reflection/scene2/上海.png new file mode 100644 index 0000000..6a91fda Binary files /dev/null and b/src/assets/images/luxun/reflection/scene2/上海.png differ diff --git a/src/assets/images/luxun/reflection/scene2/关注底层.png b/src/assets/images/luxun/reflection/scene2/关注底层.png new file mode 100644 index 0000000..b4ac213 Binary files /dev/null and b/src/assets/images/luxun/reflection/scene2/关注底层.png differ diff --git a/src/assets/images/luxun/reflection/scene2/北京.png b/src/assets/images/luxun/reflection/scene2/北京.png new file mode 100644 index 0000000..371ed39 Binary files /dev/null and b/src/assets/images/luxun/reflection/scene2/北京.png differ diff --git a/src/assets/images/luxun/reflection/scene2/厦门.png b/src/assets/images/luxun/reflection/scene2/厦门.png new file mode 100644 index 0000000..29b479c Binary files /dev/null and b/src/assets/images/luxun/reflection/scene2/厦门.png differ diff --git a/src/assets/images/luxun/reflection/scene2/广州.png b/src/assets/images/luxun/reflection/scene2/广州.png new file mode 100644 index 0000000..8b17213 Binary files /dev/null and b/src/assets/images/luxun/reflection/scene2/广州.png differ diff --git a/src/assets/images/luxun/reflection/scene2/底图.png b/src/assets/images/luxun/reflection/scene2/底图.png new file mode 100644 index 0000000..4421cd8 Binary files /dev/null and b/src/assets/images/luxun/reflection/scene2/底图.png differ diff --git a/src/assets/images/luxun/reflection/scene2/拖拽-故事新编.png b/src/assets/images/luxun/reflection/scene2/拖拽-故事新编.png new file mode 100644 index 0000000..1e2a79c Binary files /dev/null and b/src/assets/images/luxun/reflection/scene2/拖拽-故事新编.png differ diff --git a/src/assets/images/luxun/reflection/scene2/拖拽-朝花夕拾.png b/src/assets/images/luxun/reflection/scene2/拖拽-朝花夕拾.png new file mode 100644 index 0000000..7c83706 Binary files /dev/null and b/src/assets/images/luxun/reflection/scene2/拖拽-朝花夕拾.png differ diff --git a/src/assets/images/luxun/reflection/scene2/拖拽-润土.png b/src/assets/images/luxun/reflection/scene2/拖拽-润土.png new file mode 100644 index 0000000..f0694e7 Binary files /dev/null and b/src/assets/images/luxun/reflection/scene2/拖拽-润土.png differ diff --git a/src/assets/images/luxun/reflection/scene2/拖拽-百草园到三味书屋.png b/src/assets/images/luxun/reflection/scene2/拖拽-百草园到三味书屋.png new file mode 100644 index 0000000..1255596 Binary files /dev/null and b/src/assets/images/luxun/reflection/scene2/拖拽-百草园到三味书屋.png differ diff --git a/src/assets/images/luxun/reflection/scene2/拖拽-精神胜利法.png b/src/assets/images/luxun/reflection/scene2/拖拽-精神胜利法.png new file mode 100644 index 0000000..bf35b8e Binary files /dev/null and b/src/assets/images/luxun/reflection/scene2/拖拽-精神胜利法.png differ diff --git a/src/assets/images/luxun/reflection/scene2/拖拽-阿Q正传.png b/src/assets/images/luxun/reflection/scene2/拖拽-阿Q正传.png new file mode 100644 index 0000000..4b1ef72 Binary files /dev/null and b/src/assets/images/luxun/reflection/scene2/拖拽-阿Q正传.png differ diff --git a/src/assets/images/luxun/reflection/scene2/效果图1.jpg b/src/assets/images/luxun/reflection/scene2/效果图1.jpg new file mode 100644 index 0000000..1ecf48d Binary files /dev/null and b/src/assets/images/luxun/reflection/scene2/效果图1.jpg differ diff --git a/src/assets/images/luxun/reflection/scene2/效果图2.jpg b/src/assets/images/luxun/reflection/scene2/效果图2.jpg new file mode 100644 index 0000000..256f5bf Binary files /dev/null and b/src/assets/images/luxun/reflection/scene2/效果图2.jpg differ diff --git a/src/assets/images/luxun/reflection/scene2/离开.png b/src/assets/images/luxun/reflection/scene2/离开.png new file mode 100644 index 0000000..1a07f7d Binary files /dev/null and b/src/assets/images/luxun/reflection/scene2/离开.png differ diff --git a/src/assets/images/luxun/reflection/scene2/笔为刀枪.png b/src/assets/images/luxun/reflection/scene2/笔为刀枪.png new file mode 100644 index 0000000..860f550 Binary files /dev/null and b/src/assets/images/luxun/reflection/scene2/笔为刀枪.png differ diff --git a/src/assets/images/luxun/reflection/scene2/绍兴.png b/src/assets/images/luxun/reflection/scene2/绍兴.png new file mode 100644 index 0000000..b7ec71d Binary files /dev/null and b/src/assets/images/luxun/reflection/scene2/绍兴.png differ diff --git a/src/assets/images/luxun/reflection/scene2/鲁迅体悟拖一拖.png b/src/assets/images/luxun/reflection/scene2/鲁迅体悟拖一拖.png new file mode 100644 index 0000000..4d91800 Binary files /dev/null and b/src/assets/images/luxun/reflection/scene2/鲁迅体悟拖一拖.png differ diff --git a/src/assets/images/luxun/reflection/scene2/鲁迅体悟拖一拖图标.png b/src/assets/images/luxun/reflection/scene2/鲁迅体悟拖一拖图标.png new file mode 100644 index 0000000..8240ca7 Binary files /dev/null and b/src/assets/images/luxun/reflection/scene2/鲁迅体悟拖一拖图标.png differ diff --git a/src/assets/images/luxun/reflection/scene2/鲁迅体悟改版点一点.png b/src/assets/images/luxun/reflection/scene2/鲁迅体悟改版点一点.png new file mode 100644 index 0000000..174a5df Binary files /dev/null and b/src/assets/images/luxun/reflection/scene2/鲁迅体悟改版点一点.png differ diff --git a/src/assets/images/luxun/reflection/scene2/鲁迅体悟点一点图标.png b/src/assets/images/luxun/reflection/scene2/鲁迅体悟点一点图标.png new file mode 100644 index 0000000..6644d1b Binary files /dev/null and b/src/assets/images/luxun/reflection/scene2/鲁迅体悟点一点图标.png differ diff --git a/src/assets/images/luxun/reflection/scene3/北京到厦门.png b/src/assets/images/luxun/reflection/scene3/北京到厦门.png new file mode 100644 index 0000000..58eb0eb Binary files /dev/null and b/src/assets/images/luxun/reflection/scene3/北京到厦门.png differ diff --git a/src/assets/images/luxun/reflection/scene3/厦门广州.png b/src/assets/images/luxun/reflection/scene3/厦门广州.png new file mode 100644 index 0000000..ad245eb Binary files /dev/null and b/src/assets/images/luxun/reflection/scene3/厦门广州.png differ diff --git a/src/assets/images/luxun/reflection/scene3/家国情怀.png b/src/assets/images/luxun/reflection/scene3/家国情怀.png new file mode 100644 index 0000000..2018f93 Binary files /dev/null and b/src/assets/images/luxun/reflection/scene3/家国情怀.png differ diff --git a/src/assets/images/luxun/reflection/scene3/广州上海.png b/src/assets/images/luxun/reflection/scene3/广州上海.png new file mode 100644 index 0000000..e4ae82b Binary files /dev/null and b/src/assets/images/luxun/reflection/scene3/广州上海.png differ diff --git a/src/assets/images/luxun/reflection/scene3/底图.png b/src/assets/images/luxun/reflection/scene3/底图.png new file mode 100644 index 0000000..86a570c Binary files /dev/null and b/src/assets/images/luxun/reflection/scene3/底图.png differ diff --git a/src/assets/images/luxun/reflection/scene3/批判现实.png b/src/assets/images/luxun/reflection/scene3/批判现实.png new file mode 100644 index 0000000..87bc386 Binary files /dev/null and b/src/assets/images/luxun/reflection/scene3/批判现实.png differ diff --git a/src/assets/images/luxun/reflection/scene3/离开.png b/src/assets/images/luxun/reflection/scene3/离开.png new file mode 100644 index 0000000..1a07f7d Binary files /dev/null and b/src/assets/images/luxun/reflection/scene3/离开.png differ diff --git a/src/assets/images/luxun/reflection/scene3/绍兴到北京.png b/src/assets/images/luxun/reflection/scene3/绍兴到北京.png new file mode 100644 index 0000000..1b6489d Binary files /dev/null and b/src/assets/images/luxun/reflection/scene3/绍兴到北京.png differ diff --git a/src/assets/images/luxun/reflection/scene3/鲁迅1.png b/src/assets/images/luxun/reflection/scene3/鲁迅1.png new file mode 100644 index 0000000..76efcbd Binary files /dev/null and b/src/assets/images/luxun/reflection/scene3/鲁迅1.png differ diff --git a/src/assets/images/luxun/reflection/scene3/鲁迅2.png b/src/assets/images/luxun/reflection/scene3/鲁迅2.png new file mode 100644 index 0000000..a98bee7 Binary files /dev/null and b/src/assets/images/luxun/reflection/scene3/鲁迅2.png differ diff --git a/src/assets/images/luxun/reflection/scene3/鲁迅体悟改版点一点.png b/src/assets/images/luxun/reflection/scene3/鲁迅体悟改版点一点.png new file mode 100644 index 0000000..174a5df Binary files /dev/null and b/src/assets/images/luxun/reflection/scene3/鲁迅体悟改版点一点.png differ diff --git a/src/assets/images/luxun/reflection/scene3/鲁迅体悟点一点图标.png b/src/assets/images/luxun/reflection/scene3/鲁迅体悟点一点图标.png new file mode 100644 index 0000000..6644d1b Binary files /dev/null and b/src/assets/images/luxun/reflection/scene3/鲁迅体悟点一点图标.png differ diff --git a/src/pages/luxun/reflection.tsx b/src/pages/luxun/reflection.tsx deleted file mode 100644 index e7f6bf1..0000000 --- a/src/pages/luxun/reflection.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { useNavigate, useParams } from "react-router-dom"; -import { Image } from "@/components"; -import { getBackgroundImage, getStaticImage } from "@/lib/utils"; - -const starName = "luxun"; - -const LuxunReflection = () => { - const navigate = useNavigate(); - const { moduleName } = useParams<{ - moduleName: string; - }>(); - - return ( -
- { - if (moduleName && starName) { - navigate(`/${moduleName}/${starName}/home`); - } - }} - /> -
-
鲁迅故居-体悟模块(待完善)
-
-
- ); -}; - -export default LuxunReflection; - diff --git a/src/pages/luxun/reflection/scene1.tsx b/src/pages/luxun/reflection/scene1.tsx new file mode 100644 index 0000000..bccd090 --- /dev/null +++ b/src/pages/luxun/reflection/scene1.tsx @@ -0,0 +1,100 @@ +import { useState } from "react"; +import { useNavigate, useParams } from "react-router-dom"; +import { Image } from "@/components"; +import { getBackgroundImage, getStaticImage } from "@/lib/utils"; + +const starName = "luxun"; + +const cityMap: Record<1 | 2 | 3 | 4 | 5, string> = { + 1: "luxun/reflection/scene1/绍兴", + 2: "luxun/reflection/scene1/北京", + 3: "luxun/reflection/scene1/厦门", + 4: "luxun/reflection/scene1/广州", + 5: "luxun/reflection/scene1/上海", +}; + +const LuxunReflectionScene1 = () => { + const navigate = useNavigate(); + const { moduleName } = useParams<{ + moduleName: string; + }>(); + + return ( +
+ { + if (moduleName && starName) { + navigate(`/${moduleName}/${starName}/home`); + } + }} + /> + + {/* 左侧 */} +
+
+ + {/* 两个拖拽接收区域 */} +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ {/* 右侧 */} +
+ {/* 任务进度 */} +
+ + 任务进度:(0/8) + +
+ {/* 鲁迅画廊-拖拽区域 */} +
+ {/* 任务展示窗口 */} +
+
任务展示窗口
+
+
+
+
+ ); +}; + +export default LuxunReflectionScene1; diff --git a/src/pages/luxun/reflection/scene2.tsx b/src/pages/luxun/reflection/scene2.tsx new file mode 100644 index 0000000..89ad1f6 --- /dev/null +++ b/src/pages/luxun/reflection/scene2.tsx @@ -0,0 +1,265 @@ +import { useState, useCallback, useMemo, useEffect, useRef } from "react"; +import { useNavigate, useParams } from "react-router-dom"; +import { createPortal } from "react-dom"; +import { AnimatePresence, motion } from "framer-motion"; +import { Title, Image, Cursor, DragFill } from "@/components"; +import type { DragFillResult } from "@/components"; +import { cn, getBackgroundImage, getStaticImage } from "@/lib/utils"; +import { useScale } from "@/contexts/ScaleContext"; + +const starName = "luxun"; + +// 文学作品拖拽选项 +const literatureOptions = [ + { value: "朝花夕拾", label: "朝花夕拾", image: "luxun/reflection/scene2/拖拽-朝花夕拾" }, + { value: "阿Q正传", label: "阿Q正传", image: "luxun/reflection/scene2/拖拽-阿Q正传" }, + { value: "故事新编", label: "故事新编", image: "luxun/reflection/scene2/拖拽-故事新编" }, + { value: "百草园到三味书屋", label: "百草园到三味书屋", image: "luxun/reflection/scene2/拖拽-百草园到三味书屋" }, + { value: "精神胜利法", label: "精神胜利法", image: "luxun/reflection/scene2/拖拽-精神胜利法" }, + { value: "润土", label: "润土", image: "luxun/reflection/scene2/拖拽-润土" }, +]; + +// 目标位置 +const targetBlanks = [ + { id: "blank1", label: "位置1" }, + { id: "blank2", label: "位置2" }, + { id: "blank3", label: "位置3" }, +]; + +const LuxunReflectionScene2 = () => { + const navigate = useNavigate(); + const { moduleName } = useParams<{ + moduleName: string; + }>(); + + const [showDialog, setShowDialog] = useState(false); + const [visited, setVisited] = useState>(new Set()); + const [dragValue, setDragValue] = useState([]); + const completedRef = useRef(false); + const { scale, offsetX, offsetY, DESIGN_WIDTH, DESIGN_HEIGHT } = useScale(); + const [mounted, setMounted] = useState(false); + + useEffect(() => { + setMounted(true); + }, []); + + // 重置游戏状态 + useEffect(() => { + if (showDialog) { + setDragValue([]); + completedRef.current = false; + } + }, [showDialog]); + + // 检查是否完成 + useEffect(() => { + if (dragValue.length === 3 && !completedRef.current) { + completedRef.current = true; + setTimeout(() => { + setVisited((prev) => { + const next = new Set(prev); + next.add(1); + return next; + }); + setShowDialog(false); + }, 500); + } + }, [dragValue]); + + 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; + + const handleValueChange = useCallback((newValue: DragFillResult[]) => { + if (newValue.length <= 3) { + setDragValue(newValue); + } + }, []); + + const maskSrc = getStaticImage("components/蒙版遮罩"); + const backSrc = getStaticImage("components/关闭"); + + const overlayStyle = useMemo( + () => ({ + position: "fixed", + inset: 0, + zIndex: 9999, + pointerEvents: "none", + }), + [] + ); + + const scaledContainerStyle = useMemo( + () => ({ + position: "absolute", + width: `${DESIGN_WIDTH}px`, + height: `${DESIGN_HEIGHT}px`, + left: `${offsetX}px`, + top: `${offsetY}px`, + transform: `scale(${scale})`, + transformOrigin: "top left", + overflow: "hidden", + }), + [scale, offsetX, offsetY, DESIGN_WIDTH, DESIGN_HEIGHT] + ); + + return ( +
+ + + <Image + className="absolute right-5 top-5" + src={getStaticImage(`${starName}/reflection/scene2/离开`)} + button + onClick={() => { + if (moduleName && starName) { + navigate(`/${moduleName}/${starName}/home`); + } + }} + /> + + {/* 点击区域 - 打开拖拽弹窗 */} + <Cursor + className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2" + onClick={() => setShowDialog(true)} + read={visited.has(1)} + /> + + {completed && ( + <Image + className="absolute bottom-0 right-0" + src={getStaticImage("components/place/继续前进")} + button + onClick={() => { + if (moduleName && starName) { + navigate(`/${moduleName}/${starName}/reflection3`); + } + }} + /> + )} + + {/* 拖拽弹窗 */} + {mounted && + createPortal( + <AnimatePresence> + {showDialog && ( + <motion.div + key="literature-drag-dialog" + style={overlayStyle} + initial={{ opacity: 0 }} + animate={{ opacity: 1 }} + exit={{ opacity: 0 }} + transition={{ duration: 0.3, ease: "easeInOut" }} + > + <div style={scaledContainerStyle}> + <div + className={cn("absolute inset-0 flex flex-col", "bg-black/70")} + style={{ pointerEvents: "auto" }} + > + {/* 背景蒙版 */} + {maskSrc && ( + <Image + src={maskSrc} + className="absolute inset-0 w-full h-full object-cover select-none pointer-events-none" + aria-hidden + /> + )} + + {/* 返回按钮 */} + <Image + src={backSrc} + onClick={() => setShowDialog(false)} + alt="返回" + className="absolute top-5 right-5 z-20" + button + /> + + {/* 内容区域 */} + <div className="relative z-10 w-full h-full flex items-center justify-center px-30 py-16 pt-30"> + <div className="w-full max-w-6xl"> + <div className="text-5xl font-bold text-white mb-8 text-center"> + 将文学作品拖拽到对应位置 + </div> + + <DragFill + options={literatureOptions.map((opt) => ({ + value: opt.value, + label: opt.label, + }))} + blanks={targetBlanks} + value={dragValue} + onChange={handleValueChange} + allowDuplicate={false} + renderOption={(option) => { + const opt = literatureOptions.find( + (o) => o.value === option.value + ); + return ( + <div className="flex flex-col items-center gap-2"> + <Image + src={getStaticImage(opt?.image || "")} + className="w-32 h-32 object-contain" + /> + <span className="text-2xl text-white">{option.label}</span> + </div> + ); + }} + renderBlank={(blank, filledValue, isHovered) => { + const filledOption = filledValue + ? literatureOptions.find((opt) => opt.value === filledValue) + : null; + return ( + <div + className={cn( + "w-48 h-48 border-2 rounded-lg flex flex-col items-center justify-center gap-2 transition-all", + filledValue + ? "border-white bg-white/20" + : "border-dashed border-white/50 bg-white/10", + isHovered && "border-white bg-white/30" + )} + > + {filledOption ? ( + <> + <Image + src={getStaticImage(filledOption.image)} + className="w-24 h-24 object-contain" + /> + <span className="text-white text-lg">{filledOption.label}</span> + </> + ) : ( + <span className="text-white text-xl">{blank.label}</span> + )} + </div> + ); + }} + /> + </div> + </div> + </div> + </div> + </motion.div> + )} + </AnimatePresence>, + document.body + )} + </div> + ); +}; + +export default LuxunReflectionScene2; diff --git a/src/pages/luxun/reflection/scene3.tsx b/src/pages/luxun/reflection/scene3.tsx new file mode 100644 index 0000000..f28c805 --- /dev/null +++ b/src/pages/luxun/reflection/scene3.tsx @@ -0,0 +1,142 @@ +import { useState } from "react"; +import { useNavigate, useParams } from "react-router-dom"; +import { Title, Image, Cursor, ExhibitOverlay } from "@/components"; +import { getBackgroundImage, getStaticImage } from "@/lib/utils"; + +const starName = "luxun"; + +const routeMap: Record<1 | 2 | 3 | 4, string> = { + 1: "luxun/reflection/scene3/绍兴到北京", + 2: "luxun/reflection/scene3/北京到厦门", + 3: "luxun/reflection/scene3/厦门广州", + 4: "luxun/reflection/scene3/广州上海", +}; + +const themeMap: Record<5 | 6, string> = { + 5: "luxun/reflection/scene3/家国情怀", + 6: "luxun/reflection/scene3/批判现实", +}; + +const LuxunReflectionScene3 = () => { + const navigate = useNavigate(); + const { moduleName } = useParams<{ + moduleName: string; + }>(); + + const [activeRouteId, setActiveRouteId] = useState<1 | 2 | 3 | 4 | null>(null); + const [activeThemeId, setActiveThemeId] = useState<5 | 6 | null>(null); + const [visited, setVisited] = useState<Set<number>>(new Set()); + + const handleOpenRoute = (routeId: 1 | 2 | 3 | 4) => { + setActiveRouteId(routeId); + }; + + const handleOpenTheme = (themeId: 5 | 6) => { + setActiveThemeId(themeId); + }; + + const progressCount = visited.size; + const total = 6; + 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(`${starName}/reflection/scene3/底图`), + }} + > + <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(`${starName}/reflection/scene3/离开`)} + button + onClick={() => { + if (moduleName && starName) { + navigate(`/${moduleName}/${starName}/home`); + } + }} + /> + + {/* 路线点击区域 - 根据实际位置调整 */} + <Cursor + className="absolute left-20 top-30" + onClick={() => handleOpenRoute(1)} + read={visited.has(1)} + /> + <Cursor + className="absolute left-40 top-35" + onClick={() => handleOpenRoute(2)} + read={visited.has(2)} + /> + <Cursor + className="absolute left-60 top-40" + onClick={() => handleOpenRoute(3)} + read={visited.has(3)} + /> + <Cursor + className="absolute left-50 top-50" + onClick={() => handleOpenRoute(4)} + read={visited.has(4)} + /> + + {/* 主题点击区域 */} + <Cursor + className="absolute left-30 top-60" + onClick={() => handleOpenTheme(5)} + read={visited.has(5)} + /> + <Cursor + className="absolute left-70 top-55" + onClick={() => handleOpenTheme(6)} + read={visited.has(6)} + /> + + {/* 路线展品弹窗 */} + <ExhibitOverlay + visible={activeRouteId !== null} + src={activeRouteId ? routeMap[activeRouteId] : ""} + onClose={() => { + if (activeRouteId !== null) { + setVisited((prev) => { + const next = new Set(prev); + next.add(activeRouteId); + return next; + }); + } + setActiveRouteId(null); + }} + /> + + {/* 主题展品弹窗 */} + <ExhibitOverlay + visible={activeThemeId !== null} + src={activeThemeId ? themeMap[activeThemeId] : ""} + onClose={() => { + if (activeThemeId !== null) { + setVisited((prev) => { + const next = new Set(prev); + next.add(activeThemeId); + return next; + }); + } + setActiveThemeId(null); + }} + /> + </div> + ); +}; + +export default LuxunReflectionScene3; diff --git a/src/router/modules/luxun.tsx b/src/router/modules/luxun.tsx index 288014d..f11763a 100644 --- a/src/router/modules/luxun.tsx +++ b/src/router/modules/luxun.tsx @@ -8,7 +8,13 @@ const LuxunPlace2 = lazy(() => import("@/pages/luxun/place/place2")); const LuxunPlace3 = lazy(() => import("@/pages/luxun/place/place3")); const LuxunPlace4 = lazy(() => import("@/pages/luxun/place/place4")); const LuxunPlace5 = lazy(() => import("@/pages/luxun/place/place5")); -const LuxunReflection = lazy(() => import("@/pages/luxun/reflection")); +const LuxunReflection = lazy(() => import("@/pages/luxun/reflection/scene1")); +const LuxunReflection2 = lazy( + () => import("@/pages/luxun/reflection/scene2") +); +const LuxunReflection3 = lazy( + () => import("@/pages/luxun/reflection/scene3") +); const LuxunInternalization = lazy( () => import("@/pages/luxun/internalization") ); @@ -73,6 +79,14 @@ export const LuxunRoutes: RouteObject[] = [ path: "reflection", element: <LuxunReflection />, }, + { + path: "reflection2", + element: <LuxunReflection2 />, + }, + { + path: "reflection3", + element: <LuxunReflection3 />, + }, { path: "internalization", element: <LuxunInternalization />,