fix: 基本功能导航正确

master
Lxy 3 months ago
parent f19d765d5f
commit d95cf103a7

@ -16,7 +16,7 @@ function App() {
<MainLayout>
<Routes>
<Route path="/" element={<Dashboard />} />
<Route path="/detail" element={<Detail />} />
<Route path="/detail/:code" element={<Detail />} />
<Route path="/risk-control" element={<RiskControl />} />
<Route path="/config" element={<Config />} />
</Routes>

@ -0,0 +1,14 @@
import React from 'react';
function TestComponent() {
return (
<div style={{ padding: '24px' }}>
<h1>Hello World!</h1>
<p>This is a simple test component.</p>
<p>It doesn't use any Redux, React Router, or complex logic.</p>
<p>If you see this page, it means the React app is working correctly.</p>
</div>
);
}
export default TestComponent;

@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React from 'react';
import { Layout, Menu, Button, Input, Avatar, Badge, Switch, ConfigProvider } from 'antd';
import { SearchOutlined, BellOutlined, UserOutlined, MenuFoldOutlined, MenuUnfoldOutlined, HomeOutlined, BarChartOutlined, SafetyOutlined, SettingOutlined } from '@ant-design/icons';
import { Link, useLocation } from 'react-router-dom';
@ -8,18 +8,8 @@ const { Header, Sider, Content } = Layout;
const { Search } = Input;
const MainLayout = ({ children }) => {
const [collapsed, setCollapsed] = useState(false);
const [darkMode, setDarkMode] = useState(false);
const location = useLocation();
const toggleCollapsed = () => {
setCollapsed(!collapsed);
};
const toggleDarkMode = () => {
setDarkMode(!darkMode);
};
const getSelectedKey = () => {
const path = location.pathname;
if (path === '/') return '1';
@ -29,54 +19,48 @@ const MainLayout = ({ children }) => {
return '1';
};
const menuItems = [
{
key: '1',
icon: <HomeOutlined />,
label: <Link to="/">Dashboard</Link>,
},
{
key: '2',
icon: <BarChartOutlined />,
label: <Link to="/detail">详情分析</Link>,
},
{
key: '3',
icon: <SafetyOutlined />,
label: <Link to="/risk-control">风控管理</Link>,
},
{
key: '4',
icon: <SettingOutlined />,
label: <Link to="/config">配置管理</Link>,
},
];
return (
<ConfigProvider theme={darkMode ? { token: { colorScheme: 'dark' } } : {}}>
<ConfigProvider theme={{ token: { colorScheme: 'light' } }}>
<Layout style={{ minHeight: '100vh' }}>
<Header className="header">
<div className="header-left">
<Button
type="text"
icon={collapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
onClick={toggleCollapsed}
style={{ marginRight: 16, color: '#fff' }}
/>
<h1 className="logo">AI期货分析系统</h1>
</div>
<div className="header-right">
<Search
placeholder="搜索品种"
className="header-search"
style={{ width: 200 }}
/>
<Badge count={3} style={{ marginLeft: 16 }}>
<Button type="text" icon={<BellOutlined />} style={{ color: '#fff' }} />
</Badge>
<span className="dark-mode-toggle">
<Switch checked={darkMode} onChange={toggleDarkMode} checkedChildren="暗" unCheckedChildren="亮" />
</span>
<Avatar icon={<UserOutlined />} style={{ marginLeft: 16 }} />
<Avatar icon={<UserOutlined />} />
</div>
</Header>
<Layout>
<Sider width={200} theme="light" trigger={null} collapsible collapsed={collapsed}>
<Sider width={200} theme="light">
<Menu
mode="inline"
selectedKeys={[getSelectedKey()]}
style={{ height: '100%', borderRight: 0 }}
>
<Menu.Item key="1" icon={<HomeOutlined />}>
<Link to="/">Dashboard</Link>
</Menu.Item>
<Menu.Item key="2" icon={<BarChartOutlined />}>
<Link to="/detail">详情分析</Link>
</Menu.Item>
<Menu.Item key="3" icon={<SafetyOutlined />}>
<Link to="/risk-control">风控管理</Link>
</Menu.Item>
<Menu.Item key="4" icon={<SettingOutlined />}>
<Link to="/config">配置管理</Link>
</Menu.Item>
</Menu>
items={menuItems}
/>
</Sider>
<Content className="content">
<div className="content-inner">

@ -1,3 +1,6 @@
/* 确保antd样式正确加载 */
@import 'antd/dist/reset.css';
/* 全局样式 */
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
@ -16,8 +19,6 @@
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
@ -31,6 +32,3 @@ body {
ul, ol {
list-style: none;
}
/* 确保antd样式正确加载 */
@import 'antd/dist/reset.css';

@ -29,7 +29,7 @@ const Dashboard = () => {
};
const handleFutureClick = (future) => {
navigate(`/detail?code=${future.code}&name=${future.name}`);
navigate(`/detail/${future.code}`);
};
const getChangeColor = (changePercent) => {

@ -6,54 +6,97 @@
margin-bottom: 24px;
}
.detail-header h2 {
margin: 8px 0 0 0;
.header-info h2 {
margin: 8px 0 16px 0;
color: #262626;
}
.detail-card {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.09);
border-radius: 4px;
.price-info {
display: flex;
gap: 32px;
flex-wrap: wrap;
}
/* 加载容器 */
.loading-container {
/* 图表相关样式 */
.chart-header {
margin-bottom: 16px;
}
.chart-title {
display: flex;
justify-content: center;
justify-content: space-between;
align-items: center;
height: 400px;
width: 100%;
}
/* 错误容器 */
.error-container {
.chart-title h3 {
margin: 0;
}
.chart-controls {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 8px;
}
.kline-chart {
width: 100%;
height: 400px;
background-color: #fafafa;
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
}
/* 图表标题 */
.chart-title {
.chart-placeholder {
text-align: center;
color: #8c8c8c;
}
/* 区域头部样式 */
.section-header {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
margin-bottom: 16px;
}
.chart-title h3 {
.section-header h3 {
margin: 0;
color: #262626;
}
/* K线图表 */
.kline-chart {
width: 100%;
height: 400px;
/* 技术指标样式 */
.indicator-item {
display: flex;
flex-direction: column;
align-items: center;
padding: 16px;
background: #fafafa;
border-radius: 4px;
height: 100%;
text-align: center;
}
/* 趋势卡片 */
.indicator-label {
font-size: 14px;
color: #8c8c8c;
margin-bottom: 8px;
}
.indicator-value {
font-size: 16px;
font-weight: 500;
color: #262626;
}
/* 趋势卡片样式 */
.trend-card {
height: 100%;
padding: 16px;
background: #fafafa;
border-radius: 4px;
text-align: center;
}
@ -67,6 +110,7 @@
.trend-header h4 {
margin: 0;
color: #262626;
font-size: 14px;
}
.trend-status {
@ -80,8 +124,44 @@
color: #8c8c8c;
}
/* 技术指标 */
.indicator-item {
/* AI分析样式 */
.ai-analysis {
display: flex;
flex-direction: column;
gap: 20px;
}
.ai-overview {
display: flex;
gap: 24px;
flex-wrap: wrap;
}
.ai-details h4 {
margin: 0 0 8px 0;
color: #262626;
}
.ai-details p {
margin: 0 0 16px 0;
color: #262626;
line-height: 1.5;
}
.factor-tags {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
/* 交易建议样式 */
.trading-advice {
display: flex;
flex-direction: column;
gap: 20px;
}
.advice-item {
display: flex;
flex-direction: column;
align-items: center;
@ -89,36 +169,90 @@
background: #fafafa;
border-radius: 4px;
height: 100%;
text-align: center;
}
.indicator-label {
.advice-label {
font-size: 14px;
color: #8c8c8c;
margin-bottom: 8px;
}
.indicator-value {
.advice-value {
font-size: 16px;
font-weight: 500;
color: #262626;
}
/* 风险评估 */
.advice-details h4 {
margin: 0 0 8px 0;
color: #262626;
}
.advice-details p {
margin: 0;
color: #262626;
line-height: 1.5;
}
/* 风险评估样式 */
.risk-assessment {
display: flex;
flex-direction: column;
gap: 20px;
}
.risk-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
padding: 16px;
background: #fafafa;
border-radius: 4px;
height: 100%;
text-align: center;
}
.risk-label {
font-size: 14px;
color: #8c8c8c;
margin-bottom: 8px;
}
.risk-value {
font-size: 16px;
font-weight: 500;
color: #262626;
}
.risk-details h4 {
margin: 0 0 8px 0;
color: #262626;
}
/* 加载容器 */
.loading-container {
display: flex;
justify-content: center;
align-items: center;
height: 400px;
}
/* 错误容器 */
.error-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 400px;
}
/* 详情卡片样式 */
.detail-card {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.09);
border-radius: 4px;
}
/* 响应式设计 */
@media (max-width: 768px) {
.detail-header {
@ -127,22 +261,60 @@
gap: 8px;
}
.price-info {
flex-direction: column;
gap: 16px;
width: 100%;
}
.chart-title {
flex-direction: column;
align-items: flex-start;
gap: 8px;
gap: 16px;
}
.chart-controls {
width: 100%;
flex-wrap: wrap;
}
.kline-chart {
height: 300px;
}
.trend-card {
margin-bottom: 16px;
.ai-overview {
flex-direction: column;
gap: 16px;
}
.section-header {
flex-direction: column;
align-items: flex-start;
gap: 8px;
}
.indicator-item,
.trend-card,
.advice-item,
.risk-item {
margin-bottom: 16px;
}
}
@media (max-width: 480px) {
.price-info {
flex-direction: column;
gap: 12px;
}
.chart-controls {
flex-direction: column;
align-items: flex-start;
gap: 12px;
}
.chart-controls Select {
width: 100% !important;
margin-right: 0 !important;
}
}

@ -1,164 +1,62 @@
import React, { useEffect, useRef, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Card, Row, Col, Button, Select, Tag, Statistic, Alert, Spin } from 'antd';
import { ArrowUpOutlined, ArrowDownOutlined, LineChartOutlined, BarChartOutlined, AlertOutlined, CalculatorOutlined } from '@ant-design/icons';
import { fetchFutureDetail } from '../../store/futuresSlice';
import { useLocation, useNavigate } from 'react-router-dom';
import { generateKlineData, generateFutureData } from '../../utils/mockData';
import React, { useState, useEffect } from 'react';
import { Card, Button, Row, Col, Select, Tabs, Tag, Statistic, Alert, Spin } from 'antd';
import { useParams, useNavigate } from 'react-router-dom';
import { LineChartOutlined, BarChartOutlined, AreaChartOutlined, ArrowUpOutlined, AlertOutlined, RobotOutlined, SafetyOutlined } from '@ant-design/icons';
import { generateFutureData } from '../../utils/mockData';
import './Detail.css';
// TradingView Lightweight Charts
import { createChart } from 'lightweight-charts';
const { Option } = Select;
const { TabPane } = Tabs;
const Detail = () => {
const dispatch = useDispatch();
const navigate = useNavigate();
const location = useLocation();
const chartRef = useRef(null);
const chartInstance = useRef(null);
const { selectedFuture, loading, error } = useSelector(state => state.futures);
const [timeframe, setTimeframe] = useState('1D');
const [localData, setLocalData] = useState(null);
// URL
const getQueryParams = () => {
const params = new URLSearchParams(location.search);
return {
code: params.get('code') || 'MA',
name: params.get('name') || '甲醇'
};
};
const { code, name } = getQueryParams();
const { code } = useParams();
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [currentPeriod, setCurrentPeriod] = useState('1H');
const [currentIndicator, setCurrentIndicator] = useState('MA');
//
console.log('Detail page loaded with:', { code, name });
console.log('Detail page loaded with code:', code);
useEffect(() => {
// 使
const fallbackData = generateFutureData(code, name);
setLocalData(fallbackData);
console.log('Generated fallback data:', fallbackData);
// Redux
console.log('Dispatching fetchFutureDetail with:', { code, name });
dispatch(fetchFutureDetail({ code, name }));
}, [dispatch, code, name]);
useEffect(() => {
// K线
const dataToUse = selectedFuture || localData;
if (chartRef.current && dataToUse) {
console.log('Initializing chart with data:', dataToUse);
if (chartInstance.current) {
chartInstance.current.destroy();
}
const chart = createChart(chartRef.current, {
width: chartRef.current.clientWidth,
height: 400,
layout: {
backgroundColor: '#fff',
textColor: '#262626'
},
grid: {
vertLines: {
color: '#f0f0f0'
},
horzLines: {
color: '#f0f0f0'
}
},
priceScale: {
borderColor: '#f0f0f0'
},
timeScale: {
borderColor: '#f0f0f0',
timeVisible: true,
secondsVisible: false
}
});
// K线
const candlestickSeries = chart.addCandlestickSeries({
upColor: '#52c41a',
downColor: '#ff4d4f',
borderUpColor: '#52c41a',
borderDownColor: '#ff4d4f',
wickUpColor: '#52c41a',
wickDownColor: '#ff4d4f'
});
// K线
const klineData = generateKlineData(30);
candlestickSeries.setData(klineData);
//
const volumeSeries = chart.addHistogramSeries({
color: '#82ca9d',
lineWidth: 1,
priceScaleId: '',
scaleMargins: {
top: 0.8,
bottom: 0
}
});
const volumeData = klineData.map(item => ({
time: item.time,
value: item.volume,
color: item.close >= item.open ? '#52c41a' : '#ff4d4f'
}));
volumeSeries.setData(volumeData);
//
chart.timeScale().fitContent();
chartInstance.current = chart;
//
const handleResize = () => {
if (chartInstance.current) {
chartInstance.current.resize(chartRef.current.clientWidth, 400);
}
};
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
if (chartInstance.current) {
chartInstance.current.destroy();
}
};
}
}, [selectedFuture, localData]);
//
setTimeout(() => {
const futureData = generateFutureData(code, '测试品种');
setData(futureData);
setLoading(false);
}, 500);
}, [code]);
const handleBack = () => {
navigate('/');
};
const getChangeColor = (changePercent) => {
return changePercent >= 0 ? '#52c41a' : '#ff4d4f';
const handlePeriodChange = (value) => {
setCurrentPeriod(value);
};
const getChangeIcon = (changePercent) => {
return changePercent >= 0 ? <ArrowUpOutlined /> : <ArrowDownOutlined />;
const handleIndicatorChange = (value) => {
setCurrentIndicator(value);
};
const getTrendColor = (direction) => {
if (direction === '看多') return '#52c41a';
if (direction === '看空') return '#ff4d4f';
return '#faad14';
};
// 使Redux
const dataToDisplay = selectedFuture || localData;
if (loading) {
return (
<div className="loading-container">
<Spin size="large" tip="加载数据中..." />
</div>
);
}
// 使
console.log('Rendering Detail component with state:', { loading, selectedFuture, localData, error });
if (!data) {
return (
<div className="error-container">
<Alert message="未找到品种数据" type="error" />
<Button type="primary" onClick={handleBack} style={{ marginTop: 16 }}>
返回主页
</Button>
</div>
);
}
return (
<div className="detail">
@ -167,235 +65,286 @@ const Detail = () => {
<Button type="default" onClick={handleBack} style={{ marginBottom: 16 }}>
返回主页
</Button>
<h2>{dataToDisplay ? dataToDisplay.fullName : `${name}-${code}`}</h2>
</div>
{/* 错误信息 */}
{error && (
<Alert message="加载失败" description={error} type="error" showIcon style={{ marginBottom: 24 }} />
)}
{/* 加载状态 */}
{loading && !dataToDisplay && (
<div className="loading-container">
<Spin size="large" tip="加载数据中..." />
</div>
)}
{/* 数据内容 */}
{dataToDisplay && (
<>
{/* 基本信息 */}
<Card className="detail-card" style={{ marginBottom: 24 }}>
<Row gutter={[16, 16]}>
<Col span={8}>
<div className="header-info">
<h2>{data.name} ({data.code})</h2>
<div className="price-info">
<Statistic
title="当前价格"
value={dataToDisplay.currentPrice}
valueStyle={{ color: '#262626' }}
value={data.currentPrice}
precision={2}
valueStyle={{ color: data.changePercent >= 0 ? '#52c41a' : '#ff4d4f' }}
/>
</Col>
<Col span={8}>
<Statistic
title="涨跌幅"
value={Math.abs(dataToDisplay.changePercent)}
value={data.changePercent}
suffix="%"
valueStyle={{ color: getChangeColor(dataToDisplay.changePercent) }}
prefix={getChangeIcon(dataToDisplay.changePercent)}
valueStyle={{ color: data.changePercent >= 0 ? '#52c41a' : '#ff4d4f' }}
/>
</Col>
<Col span={8}>
<Statistic
title="胜率"
value={dataToDisplay.winRate}
value={data.winRate}
suffix="%"
valueStyle={{ color: dataToDisplay.winRate > 60 ? '#52c41a' : dataToDisplay.winRate > 40 ? '#faad14' : '#ff4d4f' }}
/>
</Col>
<Col span={8}>
<Statistic
title="ATR"
value={dataToDisplay.atr}
valueStyle={{ color: '#1890ff' }}
/>
</Col>
<Col span={8}>
<Statistic
title="ADX"
value={dataToDisplay.adx}
valueStyle={{ color: '#1890ff' }}
/>
</Col>
<Col span={8}>
<Statistic
title="趋势状态"
value={dataToDisplay.adxStatus}
valueStyle={{ color: '#1890ff' }}
/>
</Col>
</Row>
</Card>
</div>
</div>
</div>
{/* K线图表 */}
<Card
title={
{/* K线图表区 */}
<Card className="detail-card" style={{ marginBottom: 24 }}>
<div className="chart-header">
<div className="chart-title">
<LineChartOutlined /> K线图表
<h3>K线图表</h3>
<div className="chart-controls">
<span style={{ marginRight: 16 }}>周期:</span>
<Select
defaultValue="1D"
style={{ width: 120, marginLeft: 16 }}
onChange={setTimeframe}
value={currentPeriod}
onChange={handlePeriodChange}
style={{ width: 120, marginRight: 16 }}
>
<Option value="5MIN">5分钟</Option>
<Option value="30MIN">30分钟</Option>
<Option value="5M">5分钟</Option>
<Option value="30M">30分钟</Option>
<Option value="1H">1小时</Option>
<Option value="1D">1</Option>
<Option value="1W">1</Option>
</Select>
</div>
}
className="detail-card"
style={{ marginBottom: 24 }}
>
<div ref={chartRef} className="kline-chart"></div>
</Card>
{/* 多周期趋势分析 */}
<Card
title={<span><BarChartOutlined /> 多周期趋势分析</span>}
className="detail-card"
style={{ marginBottom: 24 }}
<span style={{ marginRight: 16 }}>指标:</span>
<Select
value={currentIndicator}
onChange={handleIndicatorChange}
style={{ width: 120 }}
>
<Row gutter={[16, 16]}>
{Object.entries(dataToDisplay.trends).map(([period, trend]) => (
<Col span={6} key={period}>
<Card className="trend-card">
<div className="trend-header">
<h4>{period}</h4>
<Tag color={getTrendColor(trend.direction)}>
{trend.direction}
</Tag>
<Option value="MA">MA</Option>
<Option value="MACD">MACD</Option>
<Option value="KDJ">KDJ</Option>
<Option value="RSI">RSI</Option>
<Option value="BOLL">布林带</Option>
</Select>
</div>
<div className="trend-status">
{trend.status}
</div>
<div className="trend-rsi">
RSI: {trend.rsi}
</div>
</Card>
</Col>
))}
</Row>
<div className="kline-chart">
{/* 这里将集成TradingView Lightweight Charts */}
<div className="chart-placeholder">
<LineChartOutlined style={{ fontSize: 48, color: '#1890ff', marginBottom: 16 }} />
<p>K线图表区域</p>
<p>周期: {currentPeriod} | 指标: {currentIndicator}</p>
</div>
</div>
</Card>
{/* 技术指标 */}
<Card
title="技术指标"
className="detail-card"
style={{ marginBottom: 24 }}
>
{/* 技术指标 */}
<Card className="detail-card" style={{ marginBottom: 24 }}>
<div className="section-header">
<h3>技术指标</h3>
<BarChartOutlined />
</div>
<Row gutter={[16, 16]}>
<Col span={6}>
<Col xs={24} sm={12} md={8} lg={6}>
<div className="indicator-item">
<div className="indicator-label">MA5</div>
<div className="indicator-value">{data.technicalIndicators?.ma5 || 'N/A'}</div>
</div>
</Col>
<Col xs={24} sm={12} md={8} lg={6}>
<div className="indicator-item">
<div className="indicator-label">MA10</div>
<div className="indicator-value">{data.technicalIndicators?.ma10 || 'N/A'}</div>
</div>
</Col>
<Col xs={24} sm={12} md={8} lg={6}>
<div className="indicator-item">
<div className="indicator-label">MACD</div>
<div className="indicator-value">{dataToDisplay.indicators.macd}</div>
<div className="indicator-value">{data.technicalIndicators?.macd || 'N/A'}</div>
</div>
</Col>
<Col span={6}>
<Col xs={24} sm={12} md={8} lg={6}>
<div className="indicator-item">
<div className="indicator-label">RSI</div>
<div className="indicator-value">{dataToDisplay.indicators.rsi}</div>
<div className="indicator-value">{data.technicalIndicators?.rsi || 'N/A'}</div>
</div>
</Col>
<Col span={6}>
<Col xs={24} sm={12} md={8} lg={6}>
<div className="indicator-item">
<div className="indicator-label">KDJ</div>
<div className="indicator-value">{data.technicalIndicators?.kdj || 'N/A'}</div>
</div>
</Col>
<Col xs={24} sm={12} md={8} lg={6}>
<div className="indicator-item">
<div className="indicator-label">布林带</div>
<div className="indicator-value">{dataToDisplay.indicators.bollinger}</div>
<div className="indicator-value">{data.technicalIndicators?.bollinger || 'N/A'}</div>
</div>
</Col>
<Col span={6}>
<Col xs={24} sm={12} md={8} lg={6}>
<div className="indicator-item">
<div className="indicator-label">KDJ</div>
<div className="indicator-value">{dataToDisplay.indicators.kdj}</div>
<div className="indicator-label">ATR</div>
<div className="indicator-value">{data.atr}</div>
</div>
</Col>
<Col xs={24} sm={12} md={8} lg={6}>
<div className="indicator-item">
<div className="indicator-label">ADX</div>
<div className="indicator-value">{data.adx}</div>
</div>
</Col>
</Row>
</Card>
{/* 交易建议 */}
<Card
title={<span><CalculatorOutlined /> 交易建议</span>}
className="detail-card"
style={{ marginBottom: 24 }}
>
{/* 多周期趋势和AI研判区 */}
<Row gutter={[16, 16]} style={{ marginBottom: 24 }}>
{/* 多周期趋势 */}
<Col xs={24} lg={12}>
<Card className="detail-card">
<div className="section-header">
<h3>多周期趋势</h3>
<AreaChartOutlined />
</div>
<Row gutter={[16, 16]}>
<Col span={8}>
{data.trends && Object.entries(data.trends).map(([period, trend]) => (
<Col xs={12} sm={6} key={period}>
<div className="trend-card">
<div className="trend-header">
<h4>{period.replace('MIN', 'min').replace('HOUR', 'min')}</h4>
<Tag color={trend.direction === '看多' ? 'green' : trend.direction === '看空' ? 'red' : 'orange'}>
{trend.direction}
</Tag>
</div>
<div className="trend-status">{trend.status}</div>
<div className="trend-rsi">RSI: {trend.rsi}</div>
</div>
</Col>
))}
</Row>
</Card>
</Col>
{/* AI研判区 */}
<Col xs={24} lg={12}>
<Card className="detail-card">
<div className="section-header">
<h3>AI研判</h3>
<RobotOutlined />
</div>
<div className="ai-analysis">
<div className="ai-overview">
<Statistic
title="入场价"
value={dataToDisplay.tradingAdvice.entry}
valueStyle={{ color: '#1890ff' }}
title="趋势预测"
value={data.aiPrediction?.trend || '中性'}
valueStyle={{ color: data.aiPrediction?.trend === '上涨' ? '#52c41a' : data.aiPrediction?.trend === '下跌' ? '#ff4d4f' : '#1890ff' }}
/>
</Col>
<Col span={8}>
<Statistic
title="止损价"
value={dataToDisplay.tradingAdvice.stopLoss}
valueStyle={{ color: '#ff4d4f' }}
title="预测胜率"
value={data.aiPrediction?.winRate || 0}
suffix="%"
valueStyle={{ color: '#1890ff' }}
/>
</Col>
<Col span={8}>
<Statistic
title="目标价"
value={dataToDisplay.tradingAdvice.target}
title="预期收益"
value={data.aiPrediction?.expectedReturn || 0}
suffix="%"
valueStyle={{ color: '#52c41a' }}
/>
</div>
<div className="ai-details">
<h4>AI分析</h4>
<p>{data.aiAnalysis || 'AI正在分析中...'}</p>
<h4>关键因素</h4>
<div className="factor-tags">
{data.aiPrediction?.keyFactors?.map((factor, index) => (
<Tag key={index} color="blue">{factor}</Tag>
))}
</div>
</div>
</div>
</Card>
</Col>
</Row>
{/* 交易建议区和风险评估区 */}
<Row gutter={[16, 16]} style={{ marginBottom: 24 }}>
{/* 交易建议区 */}
<Col xs={24} lg={12}>
<Card className="detail-card">
<div className="section-header">
<h3>交易建议</h3>
<ArrowUpOutlined />
</div>
<div className="trading-advice">
<Row gutter={[16, 16]}>
<Col xs={24} sm={8}>
<div className="advice-item">
<div className="advice-label">入场价</div>
<div className="advice-value">{data.tradingAdvice?.entryPrice || 'N/A'}</div>
</div>
</Col>
<Col xs={24} sm={8}>
<div className="advice-item">
<div className="advice-label">止损价</div>
<div className="advice-value" style={{ color: '#ff4d4f' }}>
{data.tradingAdvice?.stopLoss || 'N/A'}
</div>
</div>
</Col>
<Col xs={24} sm={8}>
<div className="advice-item">
<div className="advice-label">目标价</div>
<div className="advice-value" style={{ color: '#52c41a' }}>
{data.tradingAdvice?.targetPrice || 'N/A'}
</div>
</div>
</Col>
</Row>
<div className="advice-details">
<h4>操作建议</h4>
<p>{data.tradingAdvice?.strategy || 'AI正在生成策略...'}</p>
</div>
</div>
</Card>
</Col>
{/* 风险评估 */}
<Card
title={<span><AlertOutlined /> 风险评估</span>}
className="detail-card"
>
{/* 风险评估区 */}
<Col xs={24} lg={12}>
<Card className="detail-card">
<div className="section-header">
<h3>风险评估</h3>
<SafetyOutlined />
</div>
<div className="risk-assessment">
<Row gutter={[16, 16]}>
<Col span={12}>
<Col xs={24} sm={8}>
<div className="risk-item">
<div className="risk-label">风险等级</div>
<Tag color={dataToDisplay.riskLevel === '高' ? 'red' : dataToDisplay.riskLevel === '中等' ? 'orange' : 'green'}>
{dataToDisplay.riskLevel}
<Tag color={data.riskLevel === '高' ? 'red' : data.riskLevel === '中等' ? 'orange' : 'green'}>
{data.riskLevel}
</Tag>
</div>
</Col>
<Col span={12}>
<Col xs={24} sm={8}>
<div className="risk-item">
<div className="risk-label">波动率</div>
<Tag color={dataToDisplay.volatility === '高' ? 'red' : dataToDisplay.volatility === '中等' ? 'orange' : 'green'}>
{dataToDisplay.volatility}
</Tag>
<div className="risk-value">{data.volatility || 'N/A'}%</div>
</div>
</Col>
<Col xs={24} sm={8}>
<div className="risk-item">
<div className="risk-label">最大回撤</div>
<div className="risk-value">{data.maxDrawdown || 'N/A'}%</div>
</div>
</Col>
</Row>
<div className="risk-details">
<h4>风险提示</h4>
<Alert
message="风险提示"
description="期货交易具有高风险,请根据自身风险承受能力合理控制仓位,严格执行止损策略。"
type="warning"
message={data.riskAlert || '无明显风险'}
type={data.riskLevel === '高' ? 'error' : data.riskLevel === '中等' ? 'warning' : 'info'}
showIcon
style={{ marginTop: 16 }}
/>
</Card>
</>
)}
{/* 无数据状态 */}
{!loading && !dataToDisplay && !error && (
<div className="error-container">
<Alert message="未找到品种数据" type="error" />
<Button type="primary" onClick={handleBack} style={{ marginTop: 16 }}>
返回主页
</Button>
</div>
)}
</div>
</Card>
</Col>
</Row>
</div>
);
};

@ -0,0 +1,50 @@
import React from 'react';
import { Card, Button, Alert } from 'antd';
import { useParams, useNavigate } from 'react-router-dom';
const TestDetail = () => {
const navigate = useNavigate();
const { code } = useParams();
console.log('TestDetail page loaded with code:', code);
const handleBack = () => {
navigate('/');
};
return React.createElement('div', {
className: 'detail'
}, [
React.createElement('div', {
key: 'header',
className: 'detail-header'
}, [
React.createElement(Button, {
key: 'back-button',
type: 'default',
onClick: handleBack,
style: { marginBottom: 16 }
}, '返回主页'),
React.createElement('h2', {
key: 'title'
}, `测试详情页面 - ${code}`)
]),
React.createElement(Card, {
key: 'card',
className: 'detail-card',
style: { marginBottom: 24 }
}, [
React.createElement('h3', {
key: 'subtitle'
}, '测试信息'),
React.createElement('p', {
key: 'code'
}, '代码: ', code),
React.createElement('p', {
key: 'message'
}, '如果您看到此页面,说明路由和基本组件正常工作。')
])
]);
};
export default TestDetail;
Loading…
Cancel
Save