168 lines
5.2 KiB
TypeScript
168 lines
5.2 KiB
TypeScript
/**
|
||
* Header 组件 - 增强版
|
||
* 基于 xinyong-web 的 header 组件重建
|
||
* 功能包括:
|
||
* - 顶部导航栏(logo、搜索、用户按钮)
|
||
* - 左侧菜单(侧边栏)
|
||
* - 登录/注册弹窗
|
||
* - 钱包信息显示
|
||
* - 主题适配
|
||
*/
|
||
|
||
import React, { useState, useCallback, useMemo } from 'react';
|
||
import {
|
||
View,
|
||
Text,
|
||
StyleSheet,
|
||
TouchableOpacity,
|
||
TextInput,
|
||
Image,
|
||
Dimensions,
|
||
Modal,
|
||
ScrollView,
|
||
SafeAreaView,
|
||
} from 'react-native';
|
||
import { useColorScheme, useThemeColors } from '@/theme';
|
||
import { useIsLoggedIn, useUser } from '@/stores/userStore';
|
||
import { useLogo } from '@/stores/tenantStore';
|
||
import { Ionicons, AntDesign } from '@expo/vector-icons';
|
||
import LeftMenu from './LeftMenu';
|
||
import LoginRegisterModal from './LoginRegisterModal';
|
||
import WalletAmount from '../WalletAmount';
|
||
import { styles } from './styles';
|
||
|
||
const { width } = Dimensions.get('window');
|
||
|
||
interface HeaderProps {
|
||
onSearch?: (keyword: string) => void;
|
||
onMessagePress?: () => void;
|
||
onMenuPress?: () => void;
|
||
unreadCount?: number;
|
||
}
|
||
|
||
/**
|
||
* Header 组件 - 增强版
|
||
*/
|
||
export default function Header({
|
||
onSearch,
|
||
onMessagePress,
|
||
onMenuPress,
|
||
unreadCount = 0,
|
||
}: HeaderProps) {
|
||
const colorScheme = useColorScheme();
|
||
const s = styles[colorScheme];
|
||
const themeColors = useThemeColors();
|
||
const isLoggedIn = useIsLoggedIn();
|
||
const user = useUser();
|
||
const logoUrl = useLogo();
|
||
|
||
const [searchText, setSearchText] = useState('');
|
||
const [showLeftMenu, setShowLeftMenu] = useState(false);
|
||
const [showLoginModal, setShowLoginModal] = useState(false);
|
||
|
||
const handleSearch = useCallback(() => {
|
||
if (searchText.trim()) {
|
||
onSearch?.(searchText);
|
||
setSearchText('');
|
||
}
|
||
}, [searchText, onSearch]);
|
||
|
||
const handleMenuPress = useCallback(() => {
|
||
setShowLeftMenu(true);
|
||
onMenuPress?.();
|
||
}, [onMenuPress]);
|
||
|
||
const handleLoginPress = useCallback(() => {
|
||
setShowLoginModal(true);
|
||
}, []);
|
||
|
||
return (
|
||
<>
|
||
<View style={s.container}>
|
||
{/* 左侧部分 */}
|
||
<View style={s.leftSection}>
|
||
{/* 菜单按钮 */}
|
||
<TouchableOpacity style={s.menuButton} onPress={handleMenuPress} activeOpacity={0.7}>
|
||
<AntDesign name="menu-unfold" size={22} color={themeColors.text} />
|
||
</TouchableOpacity>
|
||
|
||
{/* Logo */}
|
||
{logoUrl ? <Image source={{ uri: logoUrl }} style={s.logoImage} /> : null}
|
||
</View>
|
||
|
||
{/* 搜索框 */}
|
||
{/*<View style={s.searchContainer}>*/}
|
||
{/* <Ionicons name="search" size={16} color={themeColors.text + '60'} />*/}
|
||
{/* <TextInput*/}
|
||
{/* style={s.searchInput}*/}
|
||
{/* placeholder="搜索游戏..."*/}
|
||
{/* placeholderTextColor={themeColors.text + '60'}*/}
|
||
{/* value={searchText}*/}
|
||
{/* onChangeText={setSearchText}*/}
|
||
{/* onSubmitEditing={handleSearch}*/}
|
||
{/* returnKeyType="search"*/}
|
||
{/* />*/}
|
||
{/* {searchText ? (*/}
|
||
{/* <TouchableOpacity onPress={() => setSearchText('')}>*/}
|
||
{/* <Ionicons name="close" size={16} color={themeColors.text} />*/}
|
||
{/* </TouchableOpacity>*/}
|
||
{/* ) : null}*/}
|
||
{/*</View>*/}
|
||
|
||
{/* 右侧部分 */}
|
||
<View style={s.rightSection}>
|
||
{isLoggedIn && user ? (
|
||
<>
|
||
{/* 消息按钮 */}
|
||
<TouchableOpacity style={s.iconButton} onPress={onMessagePress} activeOpacity={0.7}>
|
||
<Ionicons name="chatbubble-outline" size={20} color={themeColors.text} />
|
||
{unreadCount > 0 && (
|
||
<View style={s.badge}>
|
||
<Text style={s.badgeText}>{unreadCount > 99 ? '99+' : unreadCount}</Text>
|
||
</View>
|
||
)}
|
||
</TouchableOpacity>
|
||
|
||
{/* 用户头像 */}
|
||
<TouchableOpacity style={s.iconButton} activeOpacity={0.7}>
|
||
{user.avatar ? (
|
||
<Image
|
||
source={{ uri: user.avatar }}
|
||
style={{ width: 32, height: 32, borderRadius: 16 }}
|
||
/>
|
||
) : (
|
||
<Ionicons name="person-circle" size={24} color={themeColors.primary} />
|
||
)}
|
||
</TouchableOpacity>
|
||
</>
|
||
) : (
|
||
/* 登录/注册按钮 */
|
||
<View style={s.authButtons}>
|
||
<TouchableOpacity
|
||
style={[s.authButton, s.registerButton]}
|
||
onPress={() => setShowLoginModal(true)}
|
||
activeOpacity={0.7}
|
||
>
|
||
<Text style={s.registerButtonText}>注册</Text>
|
||
</TouchableOpacity>
|
||
<TouchableOpacity
|
||
style={[s.authButton, s.loginButton]}
|
||
onPress={() => setShowLoginModal(true)}
|
||
activeOpacity={0.7}
|
||
>
|
||
<Text style={s.loginButtonText}>登录</Text>
|
||
</TouchableOpacity>
|
||
</View>
|
||
)}
|
||
</View>
|
||
</View>
|
||
|
||
{/* 左侧菜单 */}
|
||
<LeftMenu visible={showLeftMenu} onClose={() => setShowLeftMenu(false)} />
|
||
|
||
{/* 登录/注册弹窗 */}
|
||
<LoginRegisterModal visible={showLoginModal} onClose={() => setShowLoginModal(false)} />
|
||
</>
|
||
);
|
||
}
|