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.
180 lines
4.1 KiB
180 lines
4.1 KiB
/** |
|
* 首页 Header 组件 |
|
* 包含搜索、用户信息、消息等功能 |
|
*/ |
|
|
|
import React, { useState, useCallback } from 'react'; |
|
import { |
|
View, |
|
Text, |
|
StyleSheet, |
|
TouchableOpacity, |
|
TextInput, |
|
Image, |
|
Dimensions, |
|
} from 'react-native'; |
|
import { useColorScheme } from '@/hooks'; |
|
import { createThemeStyles } from '@/theme'; |
|
import Colors from '@/constants/Colors'; |
|
|
|
const { width } = Dimensions.get('window'); |
|
|
|
/** |
|
* 创建主题样式 |
|
*/ |
|
const styles = createThemeStyles((colors) => ({ |
|
container: { |
|
backgroundColor: colors.background, |
|
paddingHorizontal: 12, |
|
paddingVertical: 8, |
|
borderBottomWidth: 1, |
|
borderBottomColor: colors.border, |
|
}, |
|
header: { |
|
flexDirection: 'row', |
|
alignItems: 'center', |
|
justifyContent: 'space-between', |
|
paddingVertical: 8, |
|
}, |
|
logo: { |
|
fontSize: 18, |
|
fontWeight: '600', |
|
color: colors.primary, |
|
}, |
|
searchContainer: { |
|
flex: 1, |
|
marginHorizontal: 12, |
|
flexDirection: 'row', |
|
alignItems: 'center', |
|
backgroundColor: colors.card, |
|
borderRadius: 20, |
|
paddingHorizontal: 12, |
|
height: 36, |
|
}, |
|
searchInput: { |
|
flex: 1, |
|
marginLeft: 8, |
|
fontSize: 14, |
|
color: colors.text, |
|
}, |
|
searchPlaceholder: { |
|
color: colors.text + '80', |
|
}, |
|
iconButton: { |
|
width: 36, |
|
height: 36, |
|
borderRadius: 18, |
|
justifyContent: 'center', |
|
alignItems: 'center', |
|
marginLeft: 8, |
|
}, |
|
badge: { |
|
position: 'absolute', |
|
top: -4, |
|
right: -4, |
|
backgroundColor: colors.primary, |
|
borderRadius: 8, |
|
minWidth: 16, |
|
height: 16, |
|
justifyContent: 'center', |
|
alignItems: 'center', |
|
}, |
|
badgeText: { |
|
color: '#fff', |
|
fontSize: 10, |
|
fontWeight: '600', |
|
textAlign: 'center', |
|
}, |
|
})); |
|
|
|
interface HeaderProps { |
|
theme?: 'light' | 'dark'; |
|
onSearch?: (keyword: string) => void; |
|
onMessagePress?: () => void; |
|
onUserPress?: () => void; |
|
unreadCount?: number; |
|
} |
|
|
|
/** |
|
* Header 组件 |
|
*/ |
|
export default function Header({ |
|
theme = 'light', |
|
onSearch, |
|
onMessagePress, |
|
onUserPress, |
|
unreadCount = 0, |
|
}: HeaderProps) { |
|
const colorScheme = useColorScheme(); |
|
const actualTheme = theme === 'light' || theme === 'dark' ? theme : colorScheme; |
|
const s = styles[actualTheme]; |
|
const colors = Colors[actualTheme]; |
|
|
|
const [searchText, setSearchText] = useState(''); |
|
const [isSearching, setIsSearching] = useState(false); |
|
|
|
const handleSearch = useCallback(() => { |
|
if (searchText.trim()) { |
|
onSearch?.(searchText); |
|
} |
|
}, [searchText, onSearch]); |
|
|
|
const handleClearSearch = useCallback(() => { |
|
setSearchText(''); |
|
}, []); |
|
|
|
return ( |
|
<View style={s.container}> |
|
{/* 顶部栏 */} |
|
<View style={s.header}> |
|
{/* Logo */} |
|
<Text style={s.logo}>🎮 游戏大厅</Text> |
|
|
|
{/* 搜索框 */} |
|
<View style={s.searchContainer}> |
|
<Text style={{ color: colors.text + '60', fontSize: 16 }}>🔍</Text> |
|
<TextInput |
|
style={[s.searchInput, s.searchPlaceholder]} |
|
placeholder="搜索游戏..." |
|
placeholderTextColor={colors.text + '60'} |
|
value={searchText} |
|
onChangeText={setSearchText} |
|
onSubmitEditing={handleSearch} |
|
returnKeyType="search" |
|
/> |
|
{searchText ? ( |
|
<TouchableOpacity onPress={handleClearSearch}> |
|
<Text style={{ fontSize: 16 }}>✕</Text> |
|
</TouchableOpacity> |
|
) : null} |
|
</View> |
|
|
|
{/* 消息按钮 */} |
|
<TouchableOpacity |
|
style={s.iconButton} |
|
onPress={onMessagePress} |
|
activeOpacity={0.7} |
|
> |
|
<Text style={{ fontSize: 18 }}>💬</Text> |
|
{unreadCount > 0 && ( |
|
<View style={s.badge}> |
|
<Text style={s.badgeText}> |
|
{unreadCount > 99 ? '99+' : unreadCount} |
|
</Text> |
|
</View> |
|
)} |
|
</TouchableOpacity> |
|
|
|
{/* 用户按钮 */} |
|
<TouchableOpacity |
|
style={s.iconButton} |
|
onPress={onUserPress} |
|
activeOpacity={0.7} |
|
> |
|
<Text style={{ fontSize: 18 }}>👤</Text> |
|
</TouchableOpacity> |
|
</View> |
|
</View> |
|
); |
|
} |
|
|
|
|