// src/views/TradingSimulation/index.js - 模拟盘系统主页面
import React, { useState, useEffect } from 'react';
import {
Box,
Container,
Flex,
Grid,
GridItem,
Tab,
Tabs,
TabList,
TabPanels,
TabPanel,
Card,
CardHeader,
CardBody,
Heading,
Text,
Button,
Badge,
VStack,
HStack,
Stat,
StatLabel,
StatNumber,
StatHelpText,
StatArrow,
useColorModeValue,
Spinner,
Alert,
AlertIcon,
AlertTitle,
AlertDescription,
Link,
} from '@chakra-ui/react';
import { useAuth } from '../../contexts/AuthContext';
import { logger } from '../../utils/logger';
// 导入子组件
import AccountOverview from './components/AccountOverview';
import TradingPanel from './components/TradingPanel';
import PositionsList from './components/PositionsList';
import TradingHistory from './components/TradingHistory';
import MarginTrading from './components/MarginTrading';
// 导入现有的高质量组件
import LineChart from '../../components/Charts/LineChart';
// 导航栏已由 MainLayout 提供,无需在此导入
// 模拟盘账户管理 Hook
import { useTradingAccount } from './hooks/useTradingAccount';
export default function TradingSimulation() {
// ========== 1. 所有 Hooks 必须放在最顶部,不能有任何条件判断 ==========
const { user, isAuthenticated } = useAuth();
const [activeTab, setActiveTab] = useState(0);
const [assetHistory, setAssetHistory] = useState([]); // 移到这里!
// 使用模拟账户管理 Hook
const {
account,
positions,
tradingHistory,
isLoading,
error,
buyStock,
sellStock,
cancelOrder,
refreshAccount,
searchStocks,
getAssetHistory
} = useTradingAccount();
// 所有的 useColorModeValue 也必须在顶部
const bgColor = useColorModeValue('gray.50', 'gray.900');
const cardBg = useColorModeValue('white', 'gray.800');
const xAxisLabelColor = useColorModeValue('#718096', '#A0AEC0');
const yAxisLabelColor = useColorModeValue('#718096', '#A0AEC0');
const gridBorderColor = useColorModeValue('#E2E8F0', '#4A5568');
// ========== 2. 所有 useEffect 也必须在条件返回之前 ==========
useEffect(() => {
// 调试模式:即使没有登录也加载模拟数据
refreshAccount();
}, [refreshAccount]);
// 调试:观察认证状态变化
useEffect(() => {
logger.debug('TradingSimulation', '组件挂载,认证状态检查', {
isAuthenticated,
userId: user?.id,
userName: user?.name
});
}, [isAuthenticated, user?.id]); // 只依赖 user.id,避免无限循环
// 获取资产历史数据的 useEffect
useEffect(() => {
if (account) {
getAssetHistory(30).then(data => {
setAssetHistory(data || []);
logger.debug('TradingSimulation', '资产历史数据加载成功', {
accountId: account.id,
dataPoints: data?.length || 0
});
}).catch(err => {
logger.error('TradingSimulation', 'getAssetHistory', err, {
accountId: account?.id,
days: 30
});
setAssetHistory([]);
});
}
}, [account, getAssetHistory]);
// ========== 3. 数据处理和计算(不是 Hooks,可以放在这里)==========
// 准备资产走势图表数据(使用真实数据,安全处理)
const hasAssetData = Array.isArray(assetHistory) && assetHistory.length > 0;
const assetTrendData = hasAssetData ? [{
name: "总资产",
data: assetHistory.map(item => {
// 安全地获取数据,避免undefined错误
if (!item) return 0;
return item.closing_assets || item.total_assets || 0;
})
}] : [];
const assetTrendOptions = hasAssetData ? {
chart: {
toolbar: { show: false },
height: 350
},
tooltip: {
theme: "dark",
y: {
formatter: function(val) {
return '¥' + (val || 0).toLocaleString()
}
}
},
dataLabels: {
enabled: false,
},
stroke: {
curve: "smooth",
width: 3
},
xaxis: {
type: "datetime",
categories: assetHistory.map(item => {
// 安全地获取日期
if (!item) return '';
return item.date || '';
}),
labels: {
style: {
colors: xAxisLabelColor,
fontSize: "12px",
},
},
axisBorder: {
show: false,
},
axisTicks: {
show: false,
},
},
yaxis: {
labels: {
style: {
colors: yAxisLabelColor,
fontSize: "12px",
},
formatter: function(val) {
return '¥' + ((val || 0) / 10000).toFixed(1) + 'w'
}
},
},
legend: {
show: false,
},
grid: {
strokeDashArray: 5,
borderColor: gridBorderColor
},
fill: {
type: "gradient",
gradient: {
shade: "light",
type: "vertical",
shadeIntensity: 0.5,
gradientToColors: undefined,
inverseColors: true,
opacityFrom: 0.8,
opacityTo: 0,
stops: [],
},
colors: [account?.totalProfit >= 0 ? "#48BB78" : "#F56565"],
},
colors: [account?.totalProfit >= 0 ? "#48BB78" : "#F56565"],
} : {};
// ========== 4. 现在可以安全地进行条件返回了 ==========
if (isLoading) {
return (
正在加载模拟盘数据...
);
}
if (error) {
return (
加载失败
{error}
);
}
// ========== 5. 主要渲染逻辑 ==========
return (
{/* 导航栏已由 MainLayout 提供 */}
{!isAuthenticated ? (
需要登录
请先登录以访问模拟盘系统
) : (
{/* 现代化页面标题 */}
智能模拟交易平台
体验真实交易环境,提升投资技能,零风险练手
{/* 主要功能区域 - 放在上面 */}
💹 交易面板
📊 我的持仓
📋 交易历史
💰 融资融券
{/* 交易面板 */}
{/* 我的持仓 */}
{/* 交易历史 */}
{/* 融资融券 */}
{/* 统计数据区域 - 放在下面 */}
{/* 账户概览统计 */}
📊 账户统计分析
{/* 资产走势图表 - 只在有数据时显示 */}
{hasAssetData && (
📈 资产走势分析
近{assetHistory.length}日
)}
{/* 无数据提示 */}
{!hasAssetData && account && (
📊 暂无历史数据
开始交易后,这里将显示您的资产走势图表和详细统计分析
)}
{/* 风险提示 */}
风险提示
本系统为模拟交易,所有数据仅供学习和练习使用,不构成实际投资建议。
模拟盘起始资金为100万元人民币。
)}
{/* Footer区域 */}
© 2024 价值前沿. 保留所有权利.
京公网安备11010802046286号
京ICP备2025107343号-1
);
}