import { Ionicons } from '@expo/vector-icons'; import { useRouter } from 'expo-router'; import { ActivityIndicator, Pressable, ScrollView, StyleSheet, Text, View, } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import { useGameData } from '../src/hooks'; import { colors } from '../src/theme'; import type { GameLevel, GameLevelStatus, GameProgress } from '../src/types'; /** 关卡状态 → 样式配置 */ const LEVEL_STATUS_STYLE: Record< GameLevelStatus, { bg: string; border: string; icon: string; text: string } > = { locked: { bg: colors.borderLight, border: colors.border, icon: colors.textHint, text: colors.textHint, }, available: { bg: colors.primaryLight, border: colors.primaryBorder, icon: colors.primary, text: colors.primaryText, }, completed: { bg: colors.successLight, border: colors.successBorder, icon: colors.success, text: colors.successText, }, }; /** 根据进度计算关卡状态 */ function getLevelStatus(level: GameLevel, progress: GameProgress | null): GameLevelStatus { if (!progress) return 'locked'; if (progress.results.some((r) => r.levelId === level.id && r.completed)) return 'completed'; if (progress.unlockedLevels.includes(level.id)) return 'available'; return 'locked'; } /* ===================== 子组件:顶部导航 ===================== */ function Header({ onBack }: { onBack: () => void }) { return ( 求职通关 ); } /* ===================== 子组件:进度条 ===================== */ function ProgressBar({ percent }: { percent: number }) { return ( 通关进度 {percent}% ); } /* ===================== 子组件:关卡卡片 ===================== */ function LevelCard({ level, status, onPress, }: { level: GameLevel; status: GameLevelStatus; onPress: () => void; }) { const theme = LEVEL_STATUS_STYLE[status]; const disabled = status === 'locked'; return ( 第 {level.order} 关 {level.title} {level.subtitle} {status === 'completed' ? ( ) : status === 'available' ? ( ) : ( )} ); } /* ===================== 页面 ===================== */ export default function GameScreen() { const router = useRouter(); const { levels, progress, loading, error, refresh } = useGameData(); return (
router.back()} /> {loading ? ( ) : error ? ( 加载失败,请重试 重试 ) : levels.length === 0 ? ( 暂无关卡数据 ) : ( {levels.map((level) => { const status = getLevelStatus(level, progress); return ( router.push(`/game/level?id=${level.id}`)} /> ); })} )} ); } const styles = StyleSheet.create({ safeArea: { flex: 1, backgroundColor: colors.pageBg, }, header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: 8, height: 48, backgroundColor: colors.white, borderBottomWidth: 1, borderBottomColor: colors.borderLight, }, headerBtn: { width: 40, height: 40, alignItems: 'center', justifyContent: 'center', }, headerTitle: { fontSize: 17, fontWeight: '700', color: colors.textPrimary, }, scroll: { flex: 1, }, content: { padding: 8, paddingBottom: 24, }, progressCard: { backgroundColor: colors.white, borderRadius: 8, padding: 16, marginBottom: 8, }, progressHead: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', marginBottom: 10, }, progressLabel: { fontSize: 15, fontWeight: '700', color: colors.textPrimary, }, progressValue: { fontSize: 15, fontWeight: '700', color: colors.primary, }, progressTrack: { height: 8, borderRadius: 4, backgroundColor: colors.border, }, progressFill: { height: 8, borderRadius: 4, backgroundColor: colors.primary, }, levelsSection: { gap: 8, }, levelCard: { flexDirection: 'row', alignItems: 'center', padding: 14, borderRadius: 8, borderWidth: 1, backgroundColor: colors.white, }, levelIconWrap: { width: 44, height: 44, borderRadius: 22, alignItems: 'center', justifyContent: 'center', }, levelBody: { flex: 1, marginLeft: 12, }, levelOrder: { fontSize: 12, fontWeight: '600', marginBottom: 2, }, levelTitle: { fontSize: 16, fontWeight: '700', }, levelSubtitle: { marginTop: 2, fontSize: 13, }, levelRight: { width: 36, alignItems: 'center', justifyContent: 'center', }, stateBox: { flex: 1, alignItems: 'center', justifyContent: 'center', }, stateText: { marginTop: 12, fontSize: 14, color: colors.textSecondary, }, retryBtn: { marginTop: 16, paddingHorizontal: 24, paddingVertical: 8, borderRadius: 18, backgroundColor: colors.primaryBtn, }, retryText: { fontSize: 13, fontWeight: '600', color: colors.white, }, });