2025-11-11 18:48:54 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 快速底部导航组件
|
|
|
|
|
|
*
|
|
|
|
|
|
* 深色主题特有,提供快速导航,使用真实数据
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
import React, { useState, useEffect } from 'react';
|
|
|
|
|
|
import {
|
|
|
|
|
|
View,
|
|
|
|
|
|
Text,
|
|
|
|
|
|
StyleSheet,
|
|
|
|
|
|
TouchableOpacity,
|
|
|
|
|
|
ScrollView,
|
|
|
|
|
|
Animated,
|
|
|
|
|
|
} from 'react-native';
|
|
|
|
|
|
import { createThemeStyles } from '@/theme';
|
2025-11-12 00:13:26 +08:00
|
|
|
|
import { useColorScheme } from '@/hooks';
|
2025-11-11 18:48:54 +08:00
|
|
|
|
import { mockNavItems } from '@/services/mockHomeService';
|
|
|
|
|
|
import type { NavItem } from '@/types/home';
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 创建主题样式
|
|
|
|
|
|
*/
|
|
|
|
|
|
const styles = createThemeStyles((colors) => ({
|
|
|
|
|
|
container: {
|
|
|
|
|
|
backgroundColor: colors.backgroundSecondary,
|
|
|
|
|
|
paddingVertical: 12,
|
|
|
|
|
|
paddingHorizontal: 12,
|
|
|
|
|
|
borderTopWidth: 1,
|
|
|
|
|
|
borderTopColor: colors.border,
|
|
|
|
|
|
},
|
|
|
|
|
|
scrollView: {
|
|
|
|
|
|
paddingHorizontal: 0,
|
|
|
|
|
|
},
|
|
|
|
|
|
navItem: {
|
|
|
|
|
|
paddingHorizontal: 14,
|
|
|
|
|
|
paddingVertical: 10,
|
|
|
|
|
|
marginRight: 10,
|
|
|
|
|
|
borderRadius: 8,
|
|
|
|
|
|
backgroundColor: colors.background,
|
|
|
|
|
|
justifyContent: 'center',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
minWidth: 75,
|
|
|
|
|
|
elevation: 2,
|
|
|
|
|
|
shadowColor: colors.cardShadow,
|
|
|
|
|
|
shadowOffset: { width: 0, height: 1 },
|
|
|
|
|
|
shadowOpacity: 0.1,
|
|
|
|
|
|
shadowRadius: 2,
|
|
|
|
|
|
},
|
|
|
|
|
|
navItemActive: {
|
|
|
|
|
|
backgroundColor: colors.primary,
|
|
|
|
|
|
},
|
|
|
|
|
|
navIcon: {
|
|
|
|
|
|
fontSize: 22,
|
|
|
|
|
|
marginBottom: 4,
|
|
|
|
|
|
},
|
|
|
|
|
|
navText: {
|
|
|
|
|
|
fontSize: 12,
|
|
|
|
|
|
color: colors.text,
|
|
|
|
|
|
textAlign: 'center',
|
|
|
|
|
|
fontWeight: '500',
|
|
|
|
|
|
},
|
|
|
|
|
|
navTextActive: {
|
|
|
|
|
|
color: '#FFFFFF',
|
|
|
|
|
|
},
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
interface FastFootNavProps {
|
|
|
|
|
|
items?: NavItem[];
|
|
|
|
|
|
onTabPress?: (tabId: string, action: string) => void;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 快速底部导航组件
|
|
|
|
|
|
*/
|
2025-11-12 00:13:26 +08:00
|
|
|
|
export default function FastFootNav({ items: propItems, onTabPress }: FastFootNavProps) {
|
|
|
|
|
|
const colorScheme = useColorScheme();
|
|
|
|
|
|
const s = styles[colorScheme];
|
2025-11-11 18:48:54 +08:00
|
|
|
|
const [items, setItems] = useState<NavItem[]>(propItems || []);
|
|
|
|
|
|
const [selectedId, setSelectedId] = useState<string | null>(null);
|
|
|
|
|
|
|
|
|
|
|
|
// 加载导航项数据
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
if (propItems && propItems.length > 0) {
|
|
|
|
|
|
setItems(propItems);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const loadItems = async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
// const data = await getNavItems();
|
|
|
|
|
|
// setItems(data.length > 0 ? data : mockNavItems);
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('加载导航项失败:', error);
|
|
|
|
|
|
setItems(mockNavItems);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
loadItems();
|
|
|
|
|
|
}, [propItems]);
|
|
|
|
|
|
|
|
|
|
|
|
const handleNavPress = (item: NavItem) => {
|
|
|
|
|
|
setSelectedId(item.id);
|
|
|
|
|
|
onTabPress?.(item.id, item.action);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if (items.length === 0) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<View style={s.container}>
|
|
|
|
|
|
<ScrollView
|
|
|
|
|
|
style={s.scrollView}
|
|
|
|
|
|
horizontal
|
|
|
|
|
|
showsHorizontalScrollIndicator={false}
|
|
|
|
|
|
scrollEventThrottle={16}
|
|
|
|
|
|
>
|
|
|
|
|
|
{items.map((item) => (
|
|
|
|
|
|
<TouchableOpacity
|
|
|
|
|
|
key={item.id}
|
|
|
|
|
|
style={[
|
|
|
|
|
|
s.navItem,
|
|
|
|
|
|
selectedId === item.id && s.navItemActive,
|
|
|
|
|
|
]}
|
|
|
|
|
|
onPress={() => handleNavPress(item)}
|
|
|
|
|
|
activeOpacity={0.7}
|
|
|
|
|
|
>
|
|
|
|
|
|
<Text style={s.navIcon}>{item.icon || '🎮'}</Text>
|
|
|
|
|
|
<Text
|
|
|
|
|
|
style={[
|
|
|
|
|
|
s.navText,
|
|
|
|
|
|
selectedId === item.id && s.navTextActive,
|
|
|
|
|
|
]}
|
|
|
|
|
|
>
|
|
|
|
|
|
{item.name}
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
</TouchableOpacity>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</ScrollView>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|