// 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 ); }