Files
shanghai-residences/src/components/clue/ClueBookModal.tsx
T
zhongyidian 9184c41cc7 feat: 更新线索提示功能和图像资源,提升用户体验
- 在 ClueBookModal 组件中添加线索提示图像功能,增强互动性。
- 更新多个场景中的引导对话文本,确保信息准确性和一致性。
- 替换和更新多个图像资源,提升视觉内容的准确性。
- 调整完成提示弹窗文本,优化用户体验。
2026-01-18 12:29:04 +08:00

186 lines
6.5 KiB
TypeScript

import { useState, useEffect } from "react";
import { Image } from "@/components";
import { getBackgroundImage, getStaticImage } from "@/lib/utils";
import { cn } from "@/lib/utils";
import type { Clue } from "@/store/clueStore";
export interface ClueBookModalProps {
visible: boolean;
clues: Clue[];
onClose: () => void;
getClueImage: (clueId: string) => string;
getClueDetailImage: (clueId: string) => string;
getClueHintImage?: (clueId: string) => string | null;
}
/**
* 线索簿组件 - 显示已收集的线索和详情
*/
export const ClueBookModal = ({
visible,
clues,
onClose,
getClueImage,
getClueDetailImage,
getClueHintImage,
}: ClueBookModalProps) => {
const [selectedClueId, setSelectedClueId] = useState<string | null>(null);
const [showClueHint, setShowClueHint] = useState(false);
// 默认选中第一个已收集的线索
useEffect(() => {
if (visible && clues.length > 0 && !selectedClueId) {
const firstCollected = clues.find((c) => c.collected);
if (firstCollected) {
setSelectedClueId(firstCollected.id);
}
}
}, [visible, clues, selectedClueId]);
// 当切换线索时,关闭线索提示
useEffect(() => {
setShowClueHint(false);
}, [selectedClueId]);
// 检查当前线索是否有提示
const hasClueHint = (clueId: string): boolean => {
if (!getClueHintImage) return false;
const hintImage = getClueHintImage(clueId);
return hintImage !== null && hintImage !== undefined;
};
if (!visible) return null;
const selectedClue = clues.find((c) => c.id === selectedClueId);
return (
<div className="absolute inset-0 z-50 flex items-center justify-center">
{/* 蒙版背景 */}
{/* <div
className="absolute inset-0 bg-black/50 backdrop-blur-sm"
onClick={onClose}
/> */}
{/* 线索簿内容 */}
<div className="relative w-full h-full bg-cover bg-center bg-no-repeat">
{/* 背景图片 - 线索簿 */}
<div
className="absolute inset-0 bg-cover bg-center bg-no-repeat"
style={{
backgroundImage: getBackgroundImage(
"sunzhongshan/reflection/详情线索簿背景"
),
}}
/>
{/* 内容区域 */}
<div className="relative z-10 w-full h-full flex px-40 pb-40">
{/* 左侧:线索列表 */}
<div className="grid grid-cols-2 gap-x-10 pt-36">
{clues.length === 0 ? (
<div className="text-center text-gray-500 mt-8">暂无线索</div>
) : (
clues.map((clue) => {
const isSelected = clue.id === selectedClueId;
const isCollected = clue.collected;
return (
<div
key={clue.id}
// className={cn(
// "relative cursor-pointer transition-all duration-300",
// "hover:scale-105",
// isSelected && "scale-110 z-10",
//
// )}
onClick={() => {
if (isCollected) {
setSelectedClueId(clue.id);
}
}}
>
{/* 线索缩略图 - 带倾斜效果 */}
<Image
src={
isCollected
? getClueImage(clue.id)
: getClueImage(clue.id)
}
className={cn(
"hover:scale-110 hover:brightness-115 cursor-pointer transition-all duration-300",
isSelected &&
"scale-115 brightness-115 z-10 grayscale-0",
!isCollected &&
"opacity-50 grayscale cursor-not-allowed hover:scale-100 hover:brightness-100"
)}
/>
</div>
);
})
)}
</div>
{/* 右侧:线索详情或对话 */}
<div className="flex-1 px-10 flex items-center justify-center pt-58">
{selectedClue && selectedClue.collected ? (
<div className="w-full h-full flex flex-col items-center justify-center relative">
{/* 显示线索详情图片 */}
<div className="relative h-full text-center">
<Image
src={getClueDetailImage(selectedClue.id)}
className="h-full"
/>
{/* 线索提示描述(覆盖在详情图片上) */}
{showClueHint &&
hasClueHint(selectedClue.id) &&
getClueHintImage && (
<div className="absolute inset-0 z-20 flex items-center justify-center">
<div className="relative h-full">
<Image
src={getClueHintImage(selectedClue.id)!}
className="h-full"
/>
{/* 关闭按钮 */}
<Image
className="absolute top-0 right-0 z-30"
src={getStaticImage(`sunzhongshan/reflection/关闭`)}
button
onClick={() => setShowClueHint(false)}
/>
</div>
</div>
)}
{/* 线索提示按钮(右下角) */}
{hasClueHint(selectedClue.id) && (
<div className="absolute bottom-10 right-0 z-10">
<Image
src={getStaticImage(
`sunzhongshan/reflection/内置线索提示按钮`
)}
button
onClick={() => setShowClueHint(true)}
/>
</div>
)}
</div>
</div>
) : (
<div className="text-center text-gray-500 text-4xl">
{selectedClue ? "该线索尚未收集" : "请选择一个线索查看详情"}
</div>
)}
</div>
</div>
{/* 关闭按钮 */}
<Image
className="absolute top-0 right-0 z-10"
src={getStaticImage(`sunzhongshan/reflection/关闭`)}
button
onClick={onClose}
/>
</div>
</div>
);
};