- Implemented functions to manage puzzle progress including checking if residences are started, complete, and unlocked. - Added utility functions to retrieve piece IDs based on residence and route. - Introduced a new TypeScript file for progression management. - Integrated puzzle data configuration and residence data for seamless progression tracking.
201 lines
5.4 KiB
TypeScript
201 lines
5.4 KiB
TypeScript
import { getBackgroundImage, getStaticImage } from '@/lib/utils'
|
|
import { useNavigate, useParams } from 'react-router-dom'
|
|
import { Image } from '@/components'
|
|
import { isResidenceStarted, isResidenceUnlocked } from '@/config/progression'
|
|
import { usePuzzleStore } from '@/store/puzzleStore'
|
|
//英文命名 "革命先驱" | "文化名人" | "艺术名家" | "经济巨擘"
|
|
type ModuleName = 'revolutionary' | 'cultural' | 'artistic' | 'economic'
|
|
type EntranceActionState = 'locked' | 'unvisited' | 'visited'
|
|
type EntranceSide = 'left' | 'right'
|
|
|
|
interface Star {
|
|
name: string
|
|
starName: string
|
|
}
|
|
|
|
interface EntranceBackground {
|
|
backgroundImage: string
|
|
//Star1
|
|
Star: {
|
|
Star1: Star
|
|
Star2: Star
|
|
}
|
|
}
|
|
|
|
const entranceActionConfig: Record<
|
|
EntranceActionState,
|
|
{
|
|
image: string
|
|
position: Record<EntranceSide, string>
|
|
}
|
|
> = {
|
|
locked: {
|
|
image: 'entrance/暂未解锁',
|
|
position: {
|
|
left: 'absolute left-95 bottom-58',
|
|
right: 'absolute right-106 bottom-58',
|
|
},
|
|
},
|
|
unvisited: {
|
|
image: 'entrance/点击前往浏览',
|
|
position: {
|
|
left: 'absolute left-90.5 bottom-37',
|
|
right: 'absolute right-90.5 bottom-37',
|
|
},
|
|
},
|
|
visited: {
|
|
image: 'entrance/该故居已访问',
|
|
position: {
|
|
left: 'absolute left-95 bottom-58',
|
|
right: 'absolute right-102 bottom-58',
|
|
},
|
|
},
|
|
}
|
|
|
|
/**
|
|
* 故居入口页
|
|
* 根据模块名称显示不同的背景图
|
|
* 根据模块名称显示不同的进入按钮
|
|
* 革命先驱:毛泽东、孙中山
|
|
* 文化名人:鲁迅、黄炎培
|
|
* 艺术名家:聂耳、刘海栗
|
|
* 经济巨擘:荣德生、陈云
|
|
*
|
|
*/
|
|
const EntranceBackgroundMap: Record<ModuleName, EntranceBackground> = {
|
|
revolutionary: {
|
|
backgroundImage: getBackgroundImage('entrance/革命先驱'),
|
|
Star: {
|
|
Star1: {
|
|
name: '毛泽东',
|
|
starName: 'maozedong',
|
|
},
|
|
Star2: {
|
|
name: '孙中山',
|
|
starName: 'sunzhongshan',
|
|
},
|
|
},
|
|
},
|
|
cultural: {
|
|
backgroundImage: getBackgroundImage('entrance/文教名人'),
|
|
Star: {
|
|
Star1: {
|
|
name: '鲁迅',
|
|
starName: 'luxun',
|
|
},
|
|
Star2: {
|
|
name: '黄炎培',
|
|
starName: 'huangyanpei',
|
|
},
|
|
},
|
|
},
|
|
artistic: {
|
|
backgroundImage: getBackgroundImage('entrance/艺术名家'),
|
|
Star: {
|
|
Star1: {
|
|
name: '聂耳',
|
|
starName: 'nieer',
|
|
},
|
|
Star2: {
|
|
name: '张乐平',
|
|
starName: 'zhangleping',
|
|
},
|
|
},
|
|
},
|
|
economic: {
|
|
backgroundImage: getBackgroundImage('entrance/经济巨擎'),
|
|
Star: {
|
|
Star1: {
|
|
name: '荣德生',
|
|
starName: 'rongdesheng',
|
|
},
|
|
Star2: {
|
|
name: '陈云',
|
|
starName: 'chenyun',
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
const Entrance = () => {
|
|
const { moduleName } = useParams()
|
|
const navigate = useNavigate()
|
|
const puzzles = usePuzzleStore((state) => state.puzzles)
|
|
// const decodedModuleName = decodeURIComponent(moduleName || "");
|
|
const { backgroundImage, Star } = EntranceBackgroundMap[moduleName as ModuleName] || {}
|
|
if (!Star) {
|
|
return null
|
|
}
|
|
const { Star1, Star2 } = Star
|
|
const isStar1Unlocked = isResidenceUnlocked(Star1.starName, puzzles)
|
|
const isStar2Unlocked = isResidenceUnlocked(Star2.starName, puzzles)
|
|
const isStar1Started = isResidenceStarted(Star1.starName, puzzles)
|
|
const isStar2Started = isResidenceStarted(Star2.starName, puzzles)
|
|
const getStarImage = (star: Star, isUnlocked: boolean) =>
|
|
getStaticImage(`entrance/${star.name}-${isUnlocked ? '解锁' : '未解锁'}`)
|
|
const getEntranceActionState = (isUnlocked: boolean, isStarted: boolean): EntranceActionState => {
|
|
if (!isUnlocked) return 'locked'
|
|
return isStarted ? 'visited' : 'unvisited'
|
|
}
|
|
const getEntranceAction = (side: EntranceSide, state: EntranceActionState) => {
|
|
const config = entranceActionConfig[state]
|
|
return {
|
|
className: config.position[side],
|
|
image: config.image,
|
|
}
|
|
}
|
|
const star1Action = getEntranceAction(
|
|
'left',
|
|
getEntranceActionState(isStar1Unlocked, isStar1Started)
|
|
)
|
|
const star2Action = getEntranceAction(
|
|
'right',
|
|
getEntranceActionState(isStar2Unlocked, isStar2Started)
|
|
)
|
|
|
|
return (
|
|
<div className="w-full h-full bg-cover bg-center bg-no-repeat" style={{ backgroundImage }}>
|
|
<Image
|
|
className="absolute bottom-5 right-5"
|
|
src={getStaticImage('entrance/入口-返回')}
|
|
button
|
|
onClick={() => navigate('/menu')}
|
|
/>
|
|
{/* 名人1 */}
|
|
<Image
|
|
className="absolute left-73 top-[calc(50%+38px)] -translate-y-1/2"
|
|
src={getStarImage(Star1, isStar1Unlocked)}
|
|
/>
|
|
<Image
|
|
className={star1Action.className}
|
|
src={getStaticImage(star1Action.image)}
|
|
button={isStar1Unlocked}
|
|
onClick={() => {
|
|
if (!isStar1Unlocked) return
|
|
navigate(`/${moduleName}/${Star1.starName}/home`)
|
|
}}
|
|
/>
|
|
{/* 名人2 */}
|
|
<Image
|
|
className="absolute right-77.5 top-[calc(50%+39px)] -translate-y-1/2"
|
|
src={getStarImage(Star2, isStar2Unlocked)}
|
|
/>
|
|
<Image
|
|
className={star2Action.className}
|
|
src={getStaticImage(star2Action.image)}
|
|
button={isStar2Unlocked}
|
|
onClick={() => {
|
|
if (!isStar2Unlocked) return
|
|
navigate(`/${moduleName}/${Star2.starName}/home`)
|
|
}}
|
|
/>
|
|
{/* <Image
|
|
className="absolute right-5 top-1/2 -translate-y-1/2"
|
|
src={Star2.image}
|
|
/> */}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default Entrance
|