fix: 增加自选模块

master
Lxy 3 months ago
parent 2ace0e35ef
commit 3263f3ebcb

@ -1,6 +1,6 @@
import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Card, Row, Col, Statistic, Button, Select, Tag, message, Spin, Alert, Dropdown, Menu } from 'antd';
import { Card, Row, Col, Statistic, Button, Select, Tag, message, Spin, Alert } from 'antd';
import { ReloadOutlined, ArrowUpOutlined, ArrowDownOutlined, FireOutlined, AlertOutlined, RobotOutlined } from '@ant-design/icons';
import { fetchFuturesOverview, fetchRiskAlerts, fetchAIMarketAnalysis, toggleWatchlist } from '../../store/futuresSlice';
import { useNavigate } from 'react-router-dom';
@ -11,10 +11,9 @@ const { Option } = Select;
const Dashboard = () => {
const dispatch = useDispatch();
const navigate = useNavigate();
const { overview, riskAlerts, aiAnalysis, loading, watchlists, currentWatchlist } = useSelector(state => state.futures);
const { overview, riskAlerts, aiAnalysis, loading } = useSelector(state => state.futures);
const [filterType, setFilterType] = useState('all');
const [sortBy, setSortBy] = useState('winRate');
const [showWatchlistMenu, setShowWatchlistMenu] = useState(null);
useEffect(() => {
dispatch(fetchFuturesOverview());
@ -35,21 +34,8 @@ const Dashboard = () => {
const handleToggleWatchlist = (future, e) => {
e.stopPropagation();
if (watchlists.length > 1 && !future.isInWatchlist) {
//
setShowWatchlistMenu(future.code);
} else {
//
dispatch(toggleWatchlist({ code: future.code, watchlistId: currentWatchlist }));
message.success(future.isInWatchlist ? '已从自选移除' : '已添加到自选');
}
};
const handleAddToWatchlist = (code, watchlistId, e) => {
e.stopPropagation();
dispatch(toggleWatchlist({ code, watchlistId }));
message.success('已添加到自选');
setShowWatchlistMenu(null);
dispatch(toggleWatchlist(future.code));
message.success(future.isInWatchlist ? '已从自选移除' : '已添加到自选');
};
const getChangeColor = (changePercent) => {
@ -316,41 +302,14 @@ const Dashboard = () => {
<Button type="primary" className="detail-button-new" onClick={() => handleFutureClick(item)}>
查看详细分析
</Button>
{watchlists.length > 1 && !item.isInWatchlist ? (
<Dropdown
open={showWatchlistMenu === item.code}
onOpenChange={(open) => {
if (open) {
setShowWatchlistMenu(item.code);
} else {
setShowWatchlistMenu(null);
}
}}
overlay={
<Menu>
{watchlists.map(watchlist => (
<Menu.Item key={watchlist.id} onClick={(e) => handleAddToWatchlist(item.code, watchlist.id, e)}>
{watchlist.name}
</Menu.Item>
))}
</Menu>
}
trigger={['click']}
>
<Button type="dashed" className="watchlist-button-new">
添加自选
</Button>
</Dropdown>
) : (
<Button
type={item.isInWatchlist ? "default" : "dashed"}
className="watchlist-button-new"
onClick={(e) => handleToggleWatchlist(item, e)}
disabled={item.isInWatchlist}
>
{item.isInWatchlist ? '已添加' : '添加自选'}
</Button>
)}
<Button
type={item.isInWatchlist ? "default" : "dashed"}
className="watchlist-button-new"
onClick={(e) => handleToggleWatchlist(item, e)}
disabled={item.isInWatchlist}
>
{item.isInWatchlist ? '已添加' : '添加自选'}
</Button>
</div>
</Card>
</Col>

@ -9,21 +9,6 @@
margin-bottom: 24px;
}
.watchlist-header-left {
display: flex;
align-items: center;
gap: 16px;
}
.watchlist-selector {
margin-left: 16px;
}
.watchlist-header-actions {
display: flex;
gap: 16px;
}
.watchlist-header h2 {
margin: 0;
color: #262626;

@ -1,8 +1,8 @@
import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Card, Row, Col, Button, Select, Tag, message, Spin, Input, Modal, Popconfirm } from 'antd';
import { ReloadOutlined, ArrowUpOutlined, ArrowDownOutlined, StarOutlined, DeleteOutlined, PlusOutlined, MoreOutlined } from '@ant-design/icons';
import { fetchFuturesOverview, toggleWatchlist, createWatchlist, selectWatchlist, deleteWatchlist } from '../../store/futuresSlice';
import { Card, Row, Col, Button, Select, Tag, message, Spin } from 'antd';
import { ReloadOutlined, ArrowUpOutlined, ArrowDownOutlined, StarOutlined, DeleteOutlined } from '@ant-design/icons';
import { fetchFuturesOverview, toggleWatchlist } from '../../store/futuresSlice';
import { useNavigate } from 'react-router-dom';
import './Watchlist.css';
@ -11,10 +11,8 @@ const { Option } = Select;
const Watchlist = () => {
const dispatch = useDispatch();
const navigate = useNavigate();
const { overview, watchlists, currentWatchlist, loading } = useSelector(state => state.futures);
const { overview, watchlist, loading } = useSelector(state => state.futures);
const [filterType, setFilterType] = useState('all');
const [showCreateModal, setShowCreateModal] = useState(false);
const [newWatchlistName, setNewWatchlistName] = useState('');
useEffect(() => {
dispatch(fetchFuturesOverview());
@ -29,32 +27,11 @@ const Watchlist = () => {
navigate(`/detail/${future.code}`);
};
const handleToggleWatchlist = (future, e) => {
e.stopPropagation();
dispatch(toggleWatchlist({ code: future.code, watchlistId: currentWatchlist }));
const handleToggleWatchlist = (future) => {
dispatch(toggleWatchlist(future.code));
message.success(future.isInWatchlist ? '已从自选移除' : '已添加到自选');
};
const handleCreateWatchlist = () => {
if (newWatchlistName.trim()) {
dispatch(createWatchlist({ name: newWatchlistName.trim() }));
message.success('新自选组合创建成功');
setShowCreateModal(false);
setNewWatchlistName('');
} else {
message.error('请输入自选组合名称');
}
};
const handleSelectWatchlist = (watchlistId) => {
dispatch(selectWatchlist(watchlistId));
};
const handleDeleteWatchlist = (watchlistId) => {
dispatch(deleteWatchlist(watchlistId));
message.success('自选组合删除成功');
};
const getChangeColor = (changePercent) => {
return changePercent >= 0 ? '#52c41a' : '#ff4d4f';
};
@ -70,9 +47,7 @@ const Watchlist = () => {
};
const getWatchlistData = () => {
const currentWl = watchlists.find(wl => wl.id === currentWatchlist);
if (!currentWl) return [];
return overview.filter(item => currentWl.codes.includes(item.code));
return overview.filter(item => watchlist.includes(item.code));
};
if (loading && overview.length === 0) {
@ -89,31 +64,8 @@ const Watchlist = () => {
<div className="watchlist">
{/* 页面头部 */}
<div className="watchlist-header">
<div className="watchlist-header-left">
<h2>自选合约</h2>
<div className="watchlist-selector">
<Select
value={currentWatchlist}
onChange={handleSelectWatchlist}
style={{ width: 200, marginLeft: 16 }}
>
{watchlists.map(watchlist => (
<Option key={watchlist.id} value={watchlist.id}>
{watchlist.name}
</Option>
))}
</Select>
</div>
</div>
<h2>自选合约</h2>
<div className="watchlist-header-actions">
<Button
type="default"
icon={<PlusOutlined />}
onClick={() => setShowCreateModal(true)}
style={{ marginRight: 16 }}
>
新建自选组合
</Button>
<Button
type="primary"
icon={<ReloadOutlined />}
@ -245,28 +197,6 @@ const Watchlist = () => {
</Row>
</>
)}
{/* 创建新自选组合模态框 */}
<Modal
title="创建新自选组合"
open={showCreateModal}
onCancel={() => setShowCreateModal(false)}
footer={[
<Button key="cancel" onClick={() => setShowCreateModal(false)}>
取消
</Button>,
<Button key="create" type="primary" onClick={handleCreateWatchlist}>
创建
</Button>
]}
>
<Input
placeholder="请输入自选组合名称"
value={newWatchlistName}
onChange={(e) => setNewWatchlistName(e.target.value)}
style={{ marginBottom: 16 }}
/>
</Modal>
</div>
);
};

@ -50,14 +50,7 @@ const futuresSlice = createSlice({
aiAnalysis: null,
loading: false,
error: null,
watchlists: [
{
id: 'default',
name: '默认自选',
codes: []
}
],
currentWatchlist: 'default'
watchlist: []
},
reducers: {
selectFuture: (state, action) => {
@ -67,46 +60,21 @@ const futuresSlice = createSlice({
state.selectedFuture = null;
},
toggleWatchlist: (state, action) => {
const { code, watchlistId = state.currentWatchlist } = action.payload;
const targetWatchlist = state.watchlists.find(wl => wl.id === watchlistId);
if (targetWatchlist) {
const index = targetWatchlist.codes.indexOf(code);
if (index > -1) {
targetWatchlist.codes.splice(index, 1);
} else {
targetWatchlist.codes.push(code);
}
const code = action.payload;
const index = state.watchlist.indexOf(code);
if (index > -1) {
state.watchlist.splice(index, 1);
} else {
state.watchlist.push(code);
}
// 更新overview中每个合约的自选状态
state.overview = state.overview.map(item => ({
...item,
isInWatchlist: state.watchlists.some(wl => wl.codes.includes(item.code))
isInWatchlist: state.watchlist.includes(item.code)
}));
// 更新selectedFuture的自选状态
if (state.selectedFuture && state.selectedFuture.code === code) {
state.selectedFuture.isInWatchlist = state.watchlists.some(wl => wl.codes.includes(code));
}
},
createWatchlist: (state, action) => {
const { name } = action.payload;
const newWatchlist = {
id: `wl-${Date.now()}`,
name,
codes: []
};
state.watchlists.push(newWatchlist);
state.currentWatchlist = newWatchlist.id;
},
selectWatchlist: (state, action) => {
state.currentWatchlist = action.payload;
},
deleteWatchlist: (state, action) => {
const watchlistId = action.payload;
if (watchlistId !== 'default') {
state.watchlists = state.watchlists.filter(wl => wl.id !== watchlistId);
if (state.currentWatchlist === watchlistId) {
state.currentWatchlist = 'default';
}
state.selectedFuture.isInWatchlist = state.watchlist.includes(code);
}
}
},
@ -122,7 +90,7 @@ const futuresSlice = createSlice({
// 更新overview数据并添加自选状态
state.overview = action.payload.map(item => ({
...item,
isInWatchlist: state.watchlists.some(wl => wl.codes.includes(item.code))
isInWatchlist: state.watchlist.includes(item.code)
}));
})
.addCase(fetchFuturesOverview.rejected, (state, action) => {
@ -140,7 +108,7 @@ const futuresSlice = createSlice({
// 更新selectedFuture数据并添加自选状态
state.selectedFuture = {
...action.payload,
isInWatchlist: state.watchlists.some(wl => wl.codes.includes(action.payload.code))
isInWatchlist: state.watchlist.includes(action.payload.code)
};
console.log('fetchFutureDetail fulfilled with:', action.payload);
})
@ -180,5 +148,5 @@ const futuresSlice = createSlice({
}
});
export const { selectFuture, clearSelectedFuture, toggleWatchlist, createWatchlist, selectWatchlist, deleteWatchlist } = futuresSlice.actions;
export const { selectFuture, clearSelectedFuture, toggleWatchlist } = futuresSlice.actions;
export default futuresSlice.reducer;

Loading…
Cancel
Save