feat: 重构 TradingSimulation 和 Dashboard 组件

This commit is contained in:
zdl
2025-10-18 09:03:10 +08:00
parent ea627f867e
commit 32121c416e
8 changed files with 119 additions and 60 deletions

View File

@@ -54,6 +54,7 @@ import { FiTrendingUp, FiTrendingDown, FiMinus, FiBarChart2, FiPieChart } from '
import BarChart from '../../../components/Charts/BarChart';
import PieChart from '../../../components/Charts/PieChart';
import IconBox from '../../../components/Icons/IconBox';
import { logger } from '../../../utils/logger';
// 计算涨跌幅的辅助函数
const calculateChange = (currentPrice, avgPrice) => {
@@ -118,6 +119,13 @@ export default function PositionsList({ positions, account, onSellStock }) {
);
if (result.success) {
logger.info('PositionsList', '卖出成功', {
stockCode: selectedPosition.stockCode,
stockName: selectedPosition.stockName,
quantity: sellQuantity,
orderType,
orderId: result.orderId
});
toast({
title: '卖出成功',
description: `已卖出 ${selectedPosition.stockName} ${sellQuantity}`,
@@ -128,6 +136,12 @@ export default function PositionsList({ positions, account, onSellStock }) {
onClose();
}
} catch (error) {
logger.error('PositionsList', 'handleSellConfirm', error, {
stockCode: selectedPosition?.stockCode,
stockName: selectedPosition?.stockName,
quantity: sellQuantity,
orderType
});
toast({
title: '卖出失败',
description: error.message,

View File

@@ -32,6 +32,7 @@ import {
useToast
} from '@chakra-ui/react';
import { FiSearch, FiFilter, FiClock, FiTrendingUp, FiTrendingDown } from 'react-icons/fi';
import { logger } from '../../../utils/logger';
export default function TradingHistory({ history, onCancelOrder }) {
const [filterType, setFilterType] = useState('ALL'); // ALL, BUY, SELL
@@ -147,6 +148,7 @@ export default function TradingHistory({ history, onCancelOrder }) {
const handleCancelOrder = async (orderId) => {
try {
await onCancelOrder(orderId);
logger.info('TradingHistory', '撤单成功', { orderId });
toast({
title: '撤单成功',
description: `订单 ${orderId} 已撤销`,
@@ -155,6 +157,7 @@ export default function TradingHistory({ history, onCancelOrder }) {
isClosable: true,
});
} catch (error) {
logger.error('TradingHistory', 'handleCancelOrder', error, { orderId });
toast({
title: '撤单失败',
description: error.message,

View File

@@ -1,5 +1,6 @@
// src/views/TradingSimulation/components/TradingPanel.js - 交易面板组件(现代化版本)
import React, { useState, useRef, useEffect } from 'react';
import { logger } from '../../../utils/logger';
import {
Box,
Card,
@@ -97,7 +98,7 @@ export default function TradingPanel({ account, onBuyStock, onSellStock, searchS
setFilteredStocks(formattedResults);
setShowStockList(true);
} catch (error) {
console.error('搜索股票失败:', error);
logger.error('TradingPanel', 'handleStockSearch', error, { searchTerm });
setFilteredStocks([]);
setShowStockList(false);
}
@@ -189,6 +190,14 @@ export default function TradingPanel({ account, onBuyStock, onSellStock, searchS
}
if (result.success) {
logger.info('TradingPanel', `${activeTab === 0 ? '买入' : '卖出'}成功`, {
orderId: result.orderId,
stockCode: selectedStock.code,
quantity,
orderType
});
// ✅ 保留交易成功toast关键用户操作反馈
toast({
title: activeTab === 0 ? '买入成功' : '卖出成功',
description: `订单号: ${result.orderId}`,
@@ -202,6 +211,13 @@ export default function TradingPanel({ account, onBuyStock, onSellStock, searchS
clearSelection();
}
} catch (error) {
logger.error('TradingPanel', `${activeTab === 0 ? '买入' : '卖出'}失败`, error, {
stockCode: selectedStock?.code,
quantity,
orderType
});
// ✅ 保留交易失败toast关键用户操作错误反馈
toast({
title: activeTab === 0 ? '买入失败' : '卖出失败',
description: error.message,

View File

@@ -1,6 +1,7 @@
// src/views/TradingSimulation/hooks/useTradingAccount.js - 模拟盘账户管理 Hook
import { useState, useCallback } from 'react';
import { useAuth } from '../../../contexts/AuthContext';
import { logger } from '../../../utils/logger';
// API 基础URL - 修复HTTPS混合内容问题
const API_BASE_URL = process.env.NODE_ENV === 'production'
@@ -108,7 +109,7 @@ export function useTradingAccount() {
const searchStocks = useCallback(async (keyword) => {
// 调试模式:返回模拟数据
if (!user || user.id === 'demo') {
console.log('🔧 调试模式:模拟股票搜索', keyword);
logger.debug('useTradingAccount', '调试模式:模拟股票搜索', { keyword });
const mockStocks = [
{
stock_code: '000001',
@@ -147,7 +148,7 @@ export function useTradingAccount() {
const response = await apiRequest(`/api/stocks/search?q=${encodeURIComponent(keyword)}&limit=10`);
return response.data || [];
} catch (error) {
console.error('搜索股票失败:', error);
logger.error('useTradingAccount', 'searchStocks', error, { keyword });
return [];
}
}, [user]);
@@ -156,7 +157,7 @@ export function useTradingAccount() {
const refreshAccount = useCallback(async () => {
// 调试模式使用模拟数据因为后端API可能有CORS问题
if (!user || user.id === 'demo') {
console.log('🔧 调试模式:使用模拟账户数据');
logger.debug('useTradingAccount', '调试模式:使用模拟账户数据', { userId: user?.id });
setAccount({
id: 'demo',
accountName: '演示账户',
@@ -198,7 +199,7 @@ export function useTradingAccount() {
setTradingHistory(mapOrderData(ordersResponse.data || []));
} catch (err) {
console.error('刷新账户数据失败:', err);
logger.error('useTradingAccount', 'refreshAccount', err, { userId: user?.id });
setError('加载账户数据失败: ' + err.message);
} finally {
setIsLoading(false);
@@ -213,7 +214,7 @@ export function useTradingAccount() {
// 调试模式:模拟买入成功
if (!user || user.id === 'demo') {
console.log('🔧 调试模式:模拟买入', { stockCode, quantity, orderType });
logger.debug('useTradingAccount', '调试模式:模拟买入', { stockCode, quantity, orderType });
return { success: true, orderId: 'demo_' + Date.now() };
}
@@ -251,7 +252,7 @@ export function useTradingAccount() {
// 调试模式:模拟卖出成功
if (!user || user.id === 'demo') {
console.log('🔧 调试模式:模拟卖出', { stockCode, quantity, orderType });
logger.debug('useTradingAccount', '调试模式:模拟卖出', { stockCode, quantity, orderType });
return { success: true, orderId: 'demo_' + Date.now() };
}
@@ -311,7 +312,7 @@ export function useTradingAccount() {
const response = await apiRequest(`/api/simulation/transactions?${params.toString()}`);
return response.data || [];
} catch (error) {
console.error('获取交易记录失败:', error);
logger.error('useTradingAccount', 'getTransactions', error, options);
return [];
}
}, []);
@@ -334,7 +335,7 @@ export function useTradingAccount() {
const response = await apiRequest(`/api/simulation/statistics?days=${days}`);
return response.data?.daily_returns || [];
} catch (error) {
console.error('获取资产历史失败:', error);
logger.error('useTradingAccount', 'getAssetHistory', error, { days, userId: user?.id });
return [];
}
}, [user]);
@@ -359,7 +360,7 @@ export function useTradingAccount() {
}
return {};
} catch (error) {
console.error('获取股票行情失败:', error);
logger.error('useTradingAccount', 'getStockQuotes', error, { stockCodes });
return {};
}
}, []);

View File

@@ -34,6 +34,7 @@ import {
Link,
} from '@chakra-ui/react';
import { useAuth } from '../../contexts/AuthContext';
import { logger } from '../../utils/logger';
// 导入子组件
import AccountOverview from './components/AccountOverview';
@@ -86,9 +87,11 @@ export default function TradingSimulation() {
// 调试:观察认证状态变化
useEffect(() => {
try {
console.log('🔍 TradingSimulation mounted. isAuthenticated=', isAuthenticated, 'user=', user);
} catch {}
logger.debug('TradingSimulation', '组件挂载,认证状态检查', {
isAuthenticated,
userId: user?.id,
userName: user?.name
});
}, [isAuthenticated, user]);
// 获取资产历史数据的 useEffect
@@ -96,8 +99,15 @@ export default function TradingSimulation() {
if (account) {
getAssetHistory(30).then(data => {
setAssetHistory(data || []);
logger.debug('TradingSimulation', '资产历史数据加载成功', {
accountId: account.id,
dataPoints: data?.length || 0
});
}).catch(err => {
console.error('获取资产历史失败:', err);
logger.error('TradingSimulation', 'getAssetHistory', err, {
accountId: account?.id,
days: 30
});
setAssetHistory([]);
});
}