Files
rn-app/components/Header/LeftMenu.tsx
2025-11-13 16:47:10 +08:00

297 lines
7.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 左侧菜单组件
* 基于 react-native-paper Drawer 组件重建
* 功能包括:
* - 用户钱包信息
* - 菜单项导航
* - 利息宝显示
* - 登录状态判断
*/
import React, { useState, useCallback, useMemo } from 'react';
import { View, Text, ScrollView, Modal, TouchableOpacity, Dimensions } from 'react-native';
import { Drawer, Button, Divider } from 'react-native-paper';
import { useColorScheme, useThemeColors } from '@/theme';
import { createThemeStyles } from '@/theme';
import { useIsLoggedIn, useUser } from '@/stores';
import Ionicons from '@expo/vector-icons/Ionicons';
import WalletAmount from '../WalletAmount';
const { width } = Dimensions.get('window');
/**
* 创建主题样式
*/
const styles = createThemeStyles((colors) => ({
overlay: {
flex: 1,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
},
drawerContainer: {
flex: 1,
backgroundColor: colors.background,
width: width * 0.65,
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
},
container: {
flex: 1,
backgroundColor: colors.background,
},
walletSection: {
paddingHorizontal: 16,
paddingVertical: 16,
backgroundColor: colors.card,
marginHorizontal: 12,
marginVertical: 12,
borderRadius: 12,
},
walletLabel: {
fontSize: 12,
color: colors.text + '80',
marginBottom: 8,
},
walletButtons: {
flexDirection: 'row',
gap: 8,
marginTop: 12,
},
buttonText: {
fontSize: 12,
fontWeight: '600',
},
lixibaoSection: {
marginHorizontal: 12,
marginVertical: 12,
paddingHorizontal: 12,
paddingVertical: 12,
borderRadius: 12,
borderWidth: 2,
borderColor: colors.primary,
backgroundColor: colors.card,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
},
lixibaoLeft: {
flexDirection: 'row',
alignItems: 'center',
flex: 1,
},
lixibaoInfo: {
flex: 1,
},
lixibaoLabel: {
fontSize: 12,
color: colors.text + '80',
},
lixibaoValue: {
fontSize: 14,
fontWeight: '700',
color: colors.primary,
marginTop: 4,
},
emptyText: {
textAlign: 'center',
fontSize: 14,
color: colors.text + '80',
paddingVertical: 40,
},
}));
interface LeftMenuProps {
visible: boolean;
onClose: () => void;
}
interface MenuItem {
id: string;
title: string;
icon: string;
route?: string;
requireLogin?: boolean;
}
/**
* 左侧菜单组件
*/
export default function LeftMenu({ visible, onClose }: LeftMenuProps) {
const colorScheme = useColorScheme();
const s = styles[colorScheme];
const themeColors = useThemeColors();
const isLoggedIn = useIsLoggedIn();
const user = useUser();
const [walletBalance] = useState(0); // 从 store 获取
const [interestBalance] = useState(0); // 从 store 获取
// 菜单项配置
const menuItems: MenuItem[] = useMemo(
() => [
{ id: 'balance', title: '利息宝', icon: 'gift' },
{
id: 'services',
title: '客服',
icon: 'headset',
route: '/services',
},
{
id: 'collect',
title: '收藏',
icon: 'star',
route: '/collect',
},
{
id: 'recent',
title: '最近',
icon: 'time',
route: '/recent',
},
{
id: 'betRecord',
title: '投注记录',
icon: 'document-text',
route: '/betRecord',
requireLogin: true,
},
{
id: 'activity',
title: '任务中心',
icon: 'checkmark-circle',
route: '/activity',
},
{
id: 'bonus',
title: '福利中心',
icon: 'gift',
route: '/bonus',
},
{
id: 'rebate',
title: '自助返水',
icon: 'cash',
route: '/rebate',
},
{
id: 'findBalance',
title: '找回余额',
icon: 'search',
route: '/findBalance',
},
{
id: 'message',
title: '消息中心',
icon: 'mail',
route: '/message',
},
{
id: 'promotion',
title: '推广赚钱',
icon: 'share-social',
route: '/promotion',
},
{
id: 'backup',
title: '备用网站',
icon: 'link',
route: '/backup',
},
],
[]
);
const handleMenuItemPress = useCallback(
(item: MenuItem) => {
if (item.requireLogin && !isLoggedIn) {
// 显示登录提示
return;
}
// 导航到对应页面
console.log('Navigate to:', item.route);
onClose();
},
[isLoggedIn, onClose]
);
const handleDeposit = useCallback(() => {
console.log('Navigate to deposit');
onClose();
}, [onClose]);
const handleWithdraw = useCallback(() => {
console.log('Navigate to withdraw');
onClose();
}, [onClose]);
return (
<Modal visible={visible} transparent animationType="fade" onRequestClose={onClose}>
<View style={s.overlay}>
<TouchableOpacity style={{ flex: 1 }} activeOpacity={1} onPress={onClose} />
<View style={s.drawerContainer}>
<ScrollView showsVerticalScrollIndicator={false}>
{/* 用户信息或登录提示 */}
{isLoggedIn && user ? (
<>
{/* 钱包信息 */}
<View style={s.walletSection}>
<Text style={s.walletLabel}></Text>
<WalletAmount balance={walletBalance} />
<View style={s.walletButtons}>
<Button
mode="contained"
onPress={handleDeposit}
style={{ flex: 1 }}
labelStyle={s.buttonText}
>
</Button>
<Button
mode="outlined"
onPress={handleWithdraw}
style={{ flex: 1 }}
labelStyle={s.buttonText}
>
</Button>
</View>
</View>
</>
) : (
<Text style={s.emptyText}></Text>
)}
<Divider style={{ marginVertical: 8 }} />
{/* 菜单项 */}
<Drawer.Section title="">
{menuItems.map((item) => (
<Drawer.Item
key={item.id}
label={item.title}
icon={({ color, size }) => (
<Ionicons name={item.icon as any} size={size} color={color} />
)}
onPress={() => handleMenuItemPress(item)}
active={false}
right={() => (
<Ionicons
name="chevron-forward"
size={20}
color={themeColors.text + '60'}
style={{ marginRight: -10 }}
/>
)}
style={{ marginHorizontal: 0 }}
/>
))}
</Drawer.Section>
</ScrollView>
</View>
</View>
</Modal>
);
}