- 在 ClueBookModal 组件中添加线索提示图像功能,增强互动性。 - 更新多个场景中的引导对话文本,确保信息准确性和一致性。 - 替换和更新多个图像资源,提升视觉内容的准确性。 - 调整完成提示弹窗文本,优化用户体验。
186 lines
6.5 KiB
TypeScript
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>
|
|
);
|
|
};
|