update pay function

This commit is contained in:
2025-11-23 21:42:48 +08:00
parent 134897c3aa
commit 1f1aa896d1
3 changed files with 387 additions and 1 deletions

3
app.py
View File

@@ -13639,6 +13639,9 @@ def get_prediction_topics():
}) })
except Exception as e: except Exception as e:
import traceback
print(f"[ERROR] 获取话题列表失败: {str(e)}")
print(traceback.format_exc())
return jsonify({'success': False, 'error': str(e)}), 500 return jsonify({'success': False, 'error': str(e)}), 500

View File

@@ -11,7 +11,7 @@ export const lazyComponents = {
// Home 模块 // Home 模块
HomePage: React.lazy(() => import('../views/Home/HomePage')), HomePage: React.lazy(() => import('../views/Home/HomePage')),
CenterDashboard: React.lazy(() => import('../views/Dashboard/Center')), CenterDashboard: React.lazy(() => import('../views/Dashboard/Center')),
ProfilePage: React.lazy(() => import('../views/Profile/ProfilePage')), ProfilePage: React.lazy(() => import('../views/Profile')),
SettingsPage: React.lazy(() => import('../views/Settings/SettingsPage')), SettingsPage: React.lazy(() => import('../views/Settings/SettingsPage')),
Subscription: React.lazy(() => import('../views/Pages/Account/Subscription')), Subscription: React.lazy(() => import('../views/Pages/Account/Subscription')),
PrivacyPolicy: React.lazy(() => import('../views/Pages/PrivacyPolicy')), PrivacyPolicy: React.lazy(() => import('../views/Pages/PrivacyPolicy')),

383
src/views/Profile/index.js Normal file
View File

@@ -0,0 +1,383 @@
/**
* 个人中心页面
* 包含用户信息、积分系统、交易记录等
*/
import React, { useState, useEffect } from 'react';
import {
Box,
Container,
Grid,
GridItem,
Heading,
Text,
VStack,
HStack,
Avatar,
Button,
Card,
CardBody,
CardHeader,
Stat,
StatLabel,
StatNumber,
StatHelpText,
StatArrow,
Badge,
Tabs,
TabList,
TabPanels,
Tab,
TabPanel,
Table,
Thead,
Tbody,
Tr,
Th,
Td,
Icon,
useToast,
Spinner,
Divider,
} from '@chakra-ui/react';
import {
Wallet,
TrendingUp,
Gift,
History,
Award,
Calendar,
DollarSign,
Activity,
} from 'lucide-react';
import { useAuth } from '@contexts/AuthContext';
import { getUserAccount, claimDailyBonus } from '@services/predictionMarketService.api';
import { forumColors } from '@theme/forumTheme';
const ProfilePage = () => {
const toast = useToast();
const { user } = useAuth();
// 状态管理
const [account, setAccount] = useState(null);
const [loading, setLoading] = useState(true);
const [claiming, setClaiming] = useState(false);
// 加载用户积分账户
useEffect(() => {
const fetchAccount = async () => {
if (!user) return;
try {
setLoading(true);
const response = await getUserAccount();
if (response.success) {
setAccount(response.data);
}
} catch (error) {
console.error('获取账户失败:', error);
toast({
title: '加载失败',
description: '无法加载账户信息',
status: 'error',
duration: 3000,
});
} finally {
setLoading(false);
}
};
fetchAccount();
}, [user, toast]);
// 领取每日奖励
const handleClaimDailyBonus = async () => {
try {
setClaiming(true);
const response = await claimDailyBonus();
if (response.success) {
toast({
title: '领取成功!',
description: `获得 ${response.data.bonus_amount} 积分`,
status: 'success',
duration: 3000,
});
// 刷新账户数据
const accountResponse = await getUserAccount();
if (accountResponse.success) {
setAccount(accountResponse.data);
}
}
} catch (error) {
toast({
title: '领取失败',
description: error.response?.data?.error || '今日奖励已领取或系统错误',
status: 'error',
duration: 3000,
});
} finally {
setClaiming(false);
}
};
if (loading) {
return (
<Box minH="80vh" display="flex" alignItems="center" justifyContent="center">
<VStack spacing="4">
<Spinner size="xl" color={forumColors.primary[500]} />
<Text color={forumColors.text.secondary}>加载中...</Text>
</VStack>
</Box>
);
}
return (
<Box bg={forumColors.background.main} minH="100vh" py="8">
<Container maxW="container.xl">
{/* 用户信息头部 */}
<Card
bg={forumColors.background.card}
borderRadius="xl"
border="1px solid"
borderColor={forumColors.border.default}
mb="6"
>
<CardBody>
<HStack spacing="6" align="start">
<Avatar
size="2xl"
name={user?.nickname || user?.username}
src={user?.avatar_url}
bg={forumColors.gradients.goldPrimary}
color={forumColors.background.main}
/>
<VStack align="start" spacing="3" flex="1">
<Heading size="lg" color={forumColors.text.primary}>
{user?.nickname || user?.username}
</Heading>
<HStack spacing="4">
<Badge
bg={forumColors.gradients.goldSubtle}
color={forumColors.primary[500]}
px="3"
py="1"
borderRadius="full"
>
<Icon as={Award} boxSize="14px" mr="1" />
会员
</Badge>
<Text fontSize="sm" color={forumColors.text.secondary}>
{user?.email}
</Text>
</HStack>
</VStack>
</HStack>
</CardBody>
</Card>
{/* 积分概览 */}
<Grid templateColumns={{ base: '1fr', md: 'repeat(4, 1fr)' }} gap="6" mb="6">
{/* 总余额 */}
<GridItem>
<Card
bg={forumColors.gradients.goldSubtle}
borderRadius="xl"
border="1px solid"
borderColor={forumColors.border.gold}
>
<CardBody>
<Stat>
<StatLabel fontSize="sm" color={forumColors.text.secondary}>
<Icon as={Wallet} boxSize="16px" mr="1" />
总余额
</StatLabel>
<StatNumber fontSize="3xl" fontWeight="bold" color={forumColors.primary[500]}>
{account?.balance?.toFixed(0) || 0}
</StatNumber>
<StatHelpText color={forumColors.text.tertiary}>积分</StatHelpText>
</Stat>
</CardBody>
</Card>
</GridItem>
{/* 可用余额 */}
<GridItem>
<Card
bg={forumColors.background.card}
borderRadius="xl"
border="1px solid"
borderColor={forumColors.border.default}
>
<CardBody>
<Stat>
<StatLabel fontSize="sm" color={forumColors.text.secondary}>
<Icon as={DollarSign} boxSize="16px" mr="1" />
可用余额
</StatLabel>
<StatNumber fontSize="2xl" color={forumColors.text.primary}>
{account?.available_balance?.toFixed(0) || 0}
</StatNumber>
<StatHelpText color={forumColors.text.tertiary}>积分</StatHelpText>
</Stat>
</CardBody>
</Card>
</GridItem>
{/* 累计收益 */}
<GridItem>
<Card
bg={forumColors.background.card}
borderRadius="xl"
border="1px solid"
borderColor={forumColors.border.default}
>
<CardBody>
<Stat>
<StatLabel fontSize="sm" color={forumColors.text.secondary}>
<Icon as={TrendingUp} boxSize="16px" mr="1" />
累计收益
</StatLabel>
<StatNumber fontSize="2xl" color={forumColors.success[500]}>
+{account?.total_earned?.toFixed(0) || 0}
</StatNumber>
<StatHelpText>
<StatArrow type="increase" />
积分
</StatHelpText>
</Stat>
</CardBody>
</Card>
</GridItem>
{/* 累计消费 */}
<GridItem>
<Card
bg={forumColors.background.card}
borderRadius="xl"
border="1px solid"
borderColor={forumColors.border.default}
>
<CardBody>
<Stat>
<StatLabel fontSize="sm" color={forumColors.text.secondary}>
<Icon as={Activity} boxSize="16px" mr="1" />
累计消费
</StatLabel>
<StatNumber fontSize="2xl" color={forumColors.text.primary}>
{account?.total_spent?.toFixed(0) || 0}
</StatNumber>
<StatHelpText color={forumColors.text.tertiary}>积分</StatHelpText>
</Stat>
</CardBody>
</Card>
</GridItem>
</Grid>
{/* 每日签到 */}
<Card
bg={forumColors.background.card}
borderRadius="xl"
border="1px solid"
borderColor={forumColors.border.default}
mb="6"
>
<CardHeader>
<HStack justify="space-between">
<HStack spacing="2">
<Icon as={Gift} boxSize="20px" color={forumColors.primary[500]} />
<Heading size="md" color={forumColors.text.primary}>
每日签到
</Heading>
</HStack>
<Button
bg={forumColors.gradients.goldPrimary}
color={forumColors.background.main}
fontWeight="bold"
onClick={handleClaimDailyBonus}
isLoading={claiming}
loadingText="领取中..."
_hover={{ opacity: 0.9 }}
leftIcon={<Icon as={Calendar} />}
>
领取今日奖励
</Button>
</HStack>
</CardHeader>
<CardBody>
<VStack align="start" spacing="3">
<HStack spacing="2">
<Icon as={Calendar} boxSize="16px" color={forumColors.text.secondary} />
<Text fontSize="sm" color={forumColors.text.secondary}>
每日登录可领取 100 积分奖励
</Text>
</HStack>
{account?.last_daily_bonus_at && (
<Text fontSize="xs" color={forumColors.text.tertiary}>
上次领取时间{new Date(account.last_daily_bonus_at).toLocaleString('zh-CN')}
</Text>
)}
</VStack>
</CardBody>
</Card>
{/* 详细信息标签页 */}
<Card
bg={forumColors.background.card}
borderRadius="xl"
border="1px solid"
borderColor={forumColors.border.default}
>
<CardBody>
<Tabs colorScheme="yellow" variant="soft-rounded">
<TabList mb="4">
<Tab
_selected={{
bg: forumColors.gradients.goldPrimary,
color: forumColors.background.main,
}}
>
<Icon as={History} boxSize="16px" mr="2" />
交易记录
</Tab>
<Tab
_selected={{
bg: forumColors.gradients.goldPrimary,
color: forumColors.background.main,
}}
>
<Icon as={Activity} boxSize="16px" mr="2" />
积分明细
</Tab>
</TabList>
<TabPanels>
{/* 交易记录 */}
<TabPanel>
<Box>
<Text color={forumColors.text.secondary} textAlign="center" py="10">
暂无交易记录
</Text>
</Box>
</TabPanel>
{/* 积分明细 */}
<TabPanel>
<Box>
<Text color={forumColors.text.secondary} textAlign="center" py="10">
暂无积分明细
</Text>
</Box>
</TabPanel>
</TabPanels>
</Tabs>
</CardBody>
</Card>
</Container>
</Box>
);
};
export default ProfilePage;