update pay function
This commit is contained in:
3
app.py
3
app.py
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
383
src/views/Profile/index.js
Normal 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;
|
||||||
Reference in New Issue
Block a user