You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

237 lines
8.5 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import React, { useState, useEffect } from 'react';
import { Card, Row, Col, Button, Input, Select, Table, Badge, Statistic, Typography, Spin } from 'antd';
import { ReloadOutlined, FilterOutlined, EyeOutlined, EyeInvisibleOutlined, ArrowUpOutlined, ArrowDownOutlined } from '@ant-design/icons';
import { allFuturesData, aiAnalysis, marketHotspots, riskAlerts } from '../../utils/mockData';
import useTheme from '../../hooks/useTheme';
const { Title, Text } = Typography;
const { Search } = Input;
const { Option } = Select;
const { Column } = Table;
const Dashboard = () => {
const [futuresData, setFuturesData] = useState(allFuturesData);
const [filteredData, setFilteredData] = useState(allFuturesData);
const [loading, setLoading] = useState(false);
const [viewMode, setViewMode] = useState('card'); // card or list
const [filterType, setFilterType] = useState('');
const [filterKeyword, setFilterKeyword] = useState('');
// 模拟数据刷新
const handleRefresh = () => {
setLoading(true);
setTimeout(() => {
const refreshedData = allFuturesData.map(item => ({
...item,
currentPrice: (parseFloat(item.currentPrice) * (1 + (Math.random() * 0.02 - 0.01))).toFixed(2),
changePercent: (parseFloat(item.changePercent) + (Math.random() * 2 - 1)).toFixed(2)
}));
setFuturesData(refreshedData);
setFilteredData(refreshedData);
setLoading(false);
}, 1000);
};
// 过滤数据
useEffect(() => {
let result = futuresData;
if (filterKeyword) {
const keyword = filterKeyword.toLowerCase();
result = result.filter(item =>
item.code.toLowerCase().includes(keyword) ||
item.name.toLowerCase().includes(keyword)
);
}
if (filterType) {
result = result.filter(item => item.type === filterType);
}
setFilteredData(result);
}, [futuresData, filterKeyword, filterType]);
// 品种类型选项
const typeOptions = Array.from(new Set(allFuturesData.map(item => item.type))).map(type => (
<Option key={type} value={type}>{type}</Option>
));
// 渲染品种卡片
const renderCard = (item) => (
<Card
key={item.code}
style={{ marginBottom: 16, transition: 'all 0.3s', cursor: 'pointer' }}
hoverable
onClick={() => console.log('查看详情:', item.code)}
>
<Row gutter={[16, 16]}>
<Col span={24}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }}>
<div style={{ fontWeight: 'bold', fontSize: '16px' }}>{item.name} ({item.code})</div>
<Badge
status={item.changePercent > 0 ? 'success' : 'error'}
text={`${item.changePercent > 0 ? '+' : ''}${item.changePercent}%`}
/>
</div>
</Col>
<Col span={24}>
<Statistic
title="当前价格"
value={item.currentPrice}
valueStyle={{ color: item.changePercent > 0 ? '#52c41a' : '#ff4d4f' }}
suffix="元"
size="small"
/>
</Col>
<Col span={12}>
<div style={{ fontSize: '12px', color: '#8c8c8c' }}>胜率: {item.winRate}%</div>
</Col>
<Col span={12}>
<div style={{ fontSize: '12px', color: '#8c8c8c' }}>ATR: {item.atr}</div>
</Col>
<Col span={12}>
<div style={{ fontSize: '12px', color: '#8c8c8c' }}>ADX: {item.adx}</div>
</Col>
<Col span={12}>
<div style={{ fontSize: '12px', color: '#8c8c8c' }}>趋势: {item.adxStatus}</div>
</Col>
</Row>
</Card>
);
return (
<div>
{/* 页面头部 */}
<Row gutter={[16, 16]} style={{ marginBottom: 24 }}>
<Col flex="auto">
<Title level={3}>欢迎使用AI期货分析系统</Title>
<Text>当前市场整体处于{aiAnalysis.overallView.split('')[0]}</Text>
</Col>
<Col flex="none">
<div style={{ display: 'flex', gap: 12 }}>
<Button onClick={handleRefresh} icon={<ReloadOutlined />} loading={loading}>
刷新数据
</Button>
<Button
onClick={() => setViewMode(viewMode === 'card' ? 'list' : 'card')}
icon={viewMode === 'card' ? <EyeInvisibleOutlined /> : <EyeOutlined />}
>
{viewMode === 'card' ? '列表视图' : '卡片视图'}
</Button>
</div>
</Col>
</Row>
{/* 筛选栏 */}
<Row gutter={[16, 16]} style={{ marginBottom: 24 }}>
<Col span={8}>
<Search
placeholder="搜索品种代码或名称"
value={filterKeyword}
onChange={(e) => setFilterKeyword(e.target.value)}
style={{ width: '100%' }}
/>
</Col>
<Col span={8}>
<Select
placeholder="按品种类型筛选"
style={{ width: '100%' }}
value={filterType}
onChange={setFilterType}
allowClear
>
{typeOptions}
</Select>
</Col>
</Row>
{/* 品种概览区 */}
<Card title="品种概览" style={{ marginBottom: 24 }}>
<Spin spinning={loading}>
{viewMode === 'card' ? (
<Row gutter={[16, 16]}>
{filteredData.map(item => (
<Col key={item.code} xs={24} sm={12} md={8} lg={6}>
{renderCard(item)}
</Col>
))}
</Row>
) : (
<Table dataSource={filteredData} rowKey="code" pagination={{ pageSize: 10 }}>
<Column title="品种" dataIndex="name" key="name" render={(text, record) => `${text} (${record.code})`} />
<Column title="当前价格" dataIndex="currentPrice" key="currentPrice" />
<Column
title="涨跌幅"
dataIndex="changePercent"
key="changePercent"
render={(text) => (
<span style={{ color: text > 0 ? '#52c41a' : '#ff4d4f' }}>
{text > 0 ? '+' : ''}{text}%
</span>
)}
/>
<Column title="胜率" dataIndex="winRate" key="winRate" render={(text) => `${text}%`} />
<Column title="ATR" dataIndex="atr" key="atr" />
<Column title="ADX" dataIndex="adx" key="adx" />
<Column title="趋势状态" dataIndex="adxStatus" key="adxStatus" />
</Table>
)}
</Spin>
</Card>
{/* 市场热点和AI研判区 */}
<Row gutter={[16, 16]} style={{ marginBottom: 24 }}>
<Col xs={24} lg={12}>
<Card title="AI研判">
<div style={{ marginBottom: 16 }}>
<Text strong>市场整体观点</Text>
<Text>{aiAnalysis.overallView}</Text>
</div>
<div style={{ marginBottom: 16 }}>
<Text strong>投资建议</Text>
<ul style={{ marginLeft: 20, marginTop: 8 }}>
{aiAnalysis.recommendations.map((item, index) => (
<li key={index} style={{ marginBottom: 4 }}>{item}</li>
))}
</ul>
</div>
<div>
<Text strong>置信度</Text>
<Badge status="success" text={`${aiAnalysis.confidence}%`} />
</div>
</Card>
</Col>
<Col xs={24} lg={12}>
<Card title="风险预警">
<Row gutter={[16, 16]}>
{riskAlerts.map(alert => (
<Col key={alert.id} span={24}>
<Card
size="small"
style={{
borderLeft: `4px solid ${alert.level === '高' ? '#ff4d4f' : alert.level === '中等' ? '#faad14' : '#52c41a'}`
}}
>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }}>
<Text strong>{alert.title}</Text>
<Badge
status={alert.level === '高' ? 'error' : alert.level === '中等' ? 'warning' : 'success'}
text={alert.level}
/>
</div>
<Text type="secondary">{alert.message}</Text>
</Card>
</Col>
))}
</Row>
</Card>
</Col>
</Row>
</div>
);
};
export default Dashboard;