You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
209 lines
4.5 KiB
209 lines
4.5 KiB
/** |
|
* 游戏大厅组件 |
|
* |
|
* 展示游戏列表,使用真实数据 |
|
*/ |
|
|
|
import React, { useState, useEffect, useMemo } from 'react'; |
|
import { |
|
View, |
|
Text, |
|
StyleSheet, |
|
FlatList, |
|
TouchableOpacity, |
|
Image, |
|
ActivityIndicator, |
|
Dimensions, |
|
} from 'react-native'; |
|
import { createThemeStyles } from '@/theme'; |
|
import Colors from '@/constants/Colors'; |
|
import { getMockGamesByCategory } from '@/services/mockHomeService'; |
|
import type { Game } from '@/types/home'; |
|
|
|
const { width } = Dimensions.get('window'); |
|
|
|
/** |
|
* 创建主题样式 |
|
*/ |
|
const styles = createThemeStyles((colors) => ({ |
|
container: { |
|
flex: 1, |
|
backgroundColor: colors.background, |
|
paddingHorizontal: 12, |
|
paddingVertical: 12, |
|
}, |
|
gameGrid: { |
|
paddingBottom: 20, |
|
}, |
|
gameCard: { |
|
flex: 1, |
|
margin: 6, |
|
borderRadius: 12, |
|
overflow: 'hidden', |
|
backgroundColor: colors.card, |
|
elevation: 3, |
|
shadowColor: colors.cardShadow, |
|
shadowOffset: { width: 0, height: 3 }, |
|
shadowOpacity: 0.15, |
|
shadowRadius: 6, |
|
}, |
|
gameCardPressed: { |
|
opacity: 0.8, |
|
}, |
|
gameImage: { |
|
width: '100%', |
|
height: 140, |
|
backgroundColor: colors.backgroundSecondary, |
|
justifyContent: 'center', |
|
alignItems: 'center', |
|
}, |
|
gameIcon: { |
|
fontSize: 48, |
|
}, |
|
gameInfo: { |
|
padding: 10, |
|
}, |
|
gameName: { |
|
fontSize: 13, |
|
fontWeight: '600', |
|
color: colors.text, |
|
marginBottom: 6, |
|
}, |
|
gameButton: { |
|
backgroundColor: colors.primary, |
|
paddingVertical: 8, |
|
borderRadius: 6, |
|
alignItems: 'center', |
|
marginTop: 6, |
|
}, |
|
gameButtonText: { |
|
color: '#FFFFFF', |
|
fontSize: 12, |
|
fontWeight: '600', |
|
}, |
|
emptyContainer: { |
|
flex: 1, |
|
justifyContent: 'center', |
|
alignItems: 'center', |
|
paddingVertical: 40, |
|
}, |
|
emptyText: { |
|
fontSize: 14, |
|
color: colors.textSecondary, |
|
marginTop: 12, |
|
}, |
|
loadingContainer: { |
|
flex: 1, |
|
justifyContent: 'center', |
|
alignItems: 'center', |
|
}, |
|
})); |
|
|
|
interface LobbyProps { |
|
theme: 'light' | 'dark'; |
|
games?: Game[]; |
|
selectedCategory?: number; |
|
onGamePress?: (game: Game) => void; |
|
topHeight?: number; |
|
} |
|
|
|
/** |
|
* 游戏大厅组件 |
|
*/ |
|
export default function Lobby({ |
|
theme, |
|
games: propGames, |
|
selectedCategory = 0, |
|
onGamePress, |
|
topHeight = 0, |
|
}: LobbyProps) { |
|
const s = styles[theme]; |
|
const [games, setGames] = useState<Game[]>(propGames || []); |
|
const [loading, setLoading] = useState(true); |
|
|
|
// 加载游戏数据 |
|
useEffect(() => { |
|
if (propGames && propGames.length > 0) { |
|
setGames(propGames); |
|
setLoading(false); |
|
return; |
|
} |
|
|
|
const loadGames = async () => { |
|
try { |
|
setLoading(true); |
|
// const response = await getGames(selectedCategory); |
|
// setGames(response.games.length > 0 ? response.games : getMockGamesByCategory(selectedCategory)); |
|
} catch (error) { |
|
console.error('加载游戏失败:', error); |
|
setGames(getMockGamesByCategory(selectedCategory)); |
|
} finally { |
|
setLoading(false); |
|
} |
|
}; |
|
loadGames(); |
|
}, [propGames, selectedCategory]); |
|
|
|
const renderGameCard = ({ item }: { item: Game }) => ( |
|
<TouchableOpacity |
|
style={s.gameCard} |
|
activeOpacity={0.7} |
|
onPress={() => onGamePress?.(item)} |
|
> |
|
<View style={s.gameImage}> |
|
{item.icon ? ( |
|
<Image |
|
source={{ uri: item.icon }} |
|
style={{ width: '100%', height: '100%' }} |
|
resizeMode="cover" |
|
/> |
|
) : ( |
|
<Text style={s.gameIcon}>🎮</Text> |
|
)} |
|
</View> |
|
<View style={s.gameInfo}> |
|
<Text style={s.gameName} numberOfLines={2}> |
|
{item.play_up_name} |
|
{item.play_cname ? ` - ${item.play_cname}` : ''} |
|
</Text> |
|
<TouchableOpacity |
|
style={s.gameButton} |
|
onPress={() => onGamePress?.(item)} |
|
> |
|
<Text style={s.gameButtonText}>进入游戏</Text> |
|
</TouchableOpacity> |
|
</View> |
|
</TouchableOpacity> |
|
); |
|
|
|
if (loading) { |
|
return ( |
|
<View style={s.loadingContainer}> |
|
<ActivityIndicator size="large" color={Colors[theme].primary} /> |
|
</View> |
|
); |
|
} |
|
|
|
if (games.length === 0) { |
|
return ( |
|
<View style={s.emptyContainer}> |
|
<Text style={{ fontSize: 40 }}>🎮</Text> |
|
<Text style={s.emptyText}>暂无游戏</Text> |
|
</View> |
|
); |
|
} |
|
|
|
return ( |
|
<View style={s.container}> |
|
<FlatList |
|
data={games} |
|
renderItem={renderGameCard} |
|
keyExtractor={(item) => item.id} |
|
numColumns={2} |
|
scrollEnabled={false} |
|
contentContainerStyle={s.gameGrid} |
|
/> |
|
</View> |
|
); |
|
} |
|
|
|
|