community增加事件详情

This commit is contained in:
2026-01-07 13:21:31 +08:00
parent 7f9705ac11
commit 66e623d473

View File

@@ -3,6 +3,8 @@
// 点击日期弹出详情弹窗TAB切换历史涨停/未来事件) // 点击日期弹出详情弹窗TAB切换历史涨停/未来事件)
import React, { useEffect, useState, useCallback, useMemo, memo } from 'react'; import React, { useEffect, useState, useCallback, useMemo, memo } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { loadWatchlist, toggleWatchlist } from '@store/slices/stockSlice';
import { import {
Box, Box,
Card, Card,
@@ -34,7 +36,7 @@ import {
DrawerBody, DrawerBody,
DrawerCloseButton, DrawerCloseButton,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import { Table, Tabs, Tag, Space, Button, Spin, Typography } from 'antd'; import { Table, Tabs, Tag, Space, Button, Spin, Typography, message } from 'antd';
import { import {
CalendarOutlined, CalendarOutlined,
StarFilled, StarFilled,
@@ -44,6 +46,8 @@ import {
ClockCircleOutlined, ClockCircleOutlined,
RobotOutlined, RobotOutlined,
FireOutlined, FireOutlined,
LineChartOutlined,
StarOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
import { AlertCircle, Clock, Info, Calendar, ChevronLeft, ChevronRight, Flame, TrendingUp, TrendingDown, FileText, Star } from 'lucide-react'; import { AlertCircle, Clock, Info, Calendar, ChevronLeft, ChevronRight, Flame, TrendingUp, TrendingDown, FileText, Star } from 'lucide-react';
import { GLASS_BLUR } from '@/constants/glassConfig'; import { GLASS_BLUR } from '@/constants/glassConfig';
@@ -51,6 +55,7 @@ import { eventService } from '@services/eventService';
import { getApiBase } from '@utils/apiConfig'; import { getApiBase } from '@utils/apiConfig';
import ReactMarkdown from 'react-markdown'; import ReactMarkdown from 'react-markdown';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import KLineChartModal from '@components/StockChart/KLineChartModal';
const { TabPane } = Tabs; const { TabPane } = Tabs;
const { Text: AntText } = Typography; const { Text: AntText } = Typography;
@@ -407,6 +412,9 @@ CalendarCell.displayName = 'CalendarCell';
* 详情弹窗组件 - 完整展示涨停分析和事件详情 * 详情弹窗组件 - 完整展示涨停分析和事件详情
*/ */
const DetailModal = ({ isOpen, onClose, selectedDate, ztDetail, events, loading }) => { const DetailModal = ({ isOpen, onClose, selectedDate, ztDetail, events, loading }) => {
const dispatch = useDispatch();
const reduxWatchlist = useSelector(state => state.stock.watchlist);
const [detailDrawerVisible, setDetailDrawerVisible] = useState(false); const [detailDrawerVisible, setDetailDrawerVisible] = useState(false);
const [selectedContent, setSelectedContent] = useState(null); const [selectedContent, setSelectedContent] = useState(null);
const [ztViewMode, setZtViewMode] = useState('sector'); // 'sector' | 'stock' const [ztViewMode, setZtViewMode] = useState('sector'); // 'sector' | 'stock'
@@ -417,6 +425,8 @@ const DetailModal = ({ isOpen, onClose, selectedDate, ztDetail, events, loading
const [stockQuotes, setStockQuotes] = useState({}); const [stockQuotes, setStockQuotes] = useState({});
const [stockQuotesLoading, setStockQuotesLoading] = useState(false); const [stockQuotesLoading, setStockQuotesLoading] = useState(false);
const [expandedReasons, setExpandedReasons] = useState({}); const [expandedReasons, setExpandedReasons] = useState({});
const [klineModalVisible, setKlineModalVisible] = useState(false);
const [selectedKlineStock, setSelectedKlineStock] = useState(null);
// 板块数据处理 - 必须在条件返回之前调用所有hooks // 板块数据处理 - 必须在条件返回之前调用所有hooks
const sectorList = useMemo(() => { const sectorList = useMemo(() => {
@@ -549,6 +559,64 @@ const DetailModal = ({ isOpen, onClose, selectedDate, ztDetail, events, loading
loadStockQuotes(sortedStocks); loadStockQuotes(sortedStocks);
}; };
// 添加交易所后缀
const addExchangeSuffix = (code) => {
const sixDigitCode = getSixDigitCode(code);
if (code.includes('.')) return code;
if (sixDigitCode.startsWith('6')) {
return `${sixDigitCode}.SH`;
} else if (sixDigitCode.startsWith('0') || sixDigitCode.startsWith('3')) {
return `${sixDigitCode}.SZ`;
}
return sixDigitCode;
};
// 检查股票是否已在自选中
const isStockInWatchlist = useCallback((stockCode) => {
const sixDigitCode = getSixDigitCode(stockCode);
return reduxWatchlist?.some(item =>
getSixDigitCode(item.stock_code) === sixDigitCode
);
}, [reduxWatchlist]);
// 显示K线图
const showKline = (stock) => {
const code = stock.code;
const name = stock.name;
const stockCode = addExchangeSuffix(code);
setSelectedKlineStock({
stock_code: stockCode,
stock_name: name,
});
setKlineModalVisible(true);
};
// 添加单只股票到自选
const addSingleToWatchlist = async (stock) => {
const code = stock.code;
const name = stock.name;
const stockCode = getSixDigitCode(code);
if (isStockInWatchlist(code)) {
message.info(`${name} 已在自选中`);
return;
}
try {
await dispatch(toggleWatchlist({
stockCode,
stockName: name,
isInWatchlist: false
})).unwrap();
message.success(`已将 ${name}(${stockCode}) 添加到自选`);
} catch (error) {
console.error('添加自选失败:', error);
message.error('添加失败,请重试');
}
};
// 相关股票表格列定义(和投资日历保持一致) // 相关股票表格列定义(和投资日历保持一致)
const stockColumns = [ const stockColumns = [
{ {
@@ -702,6 +770,40 @@ const DetailModal = ({ isOpen, onClose, selectedDate, ztDetail, events, loading
); );
} }
}, },
{
title: 'K线图',
key: 'kline',
width: 80,
render: (_, record) => (
<Button
type="primary"
size="small"
icon={<LineChartOutlined />}
onClick={() => showKline(record)}
>
查看
</Button>
)
},
{
title: '操作',
key: 'action',
width: 90,
render: (_, record) => {
const inWatchlist = isStockInWatchlist(record.code);
return (
<Button
type={inWatchlist ? 'primary' : 'default'}
size="small"
icon={inWatchlist ? <StarFilled /> : <StarOutlined />}
onClick={() => addSingleToWatchlist(record)}
disabled={inWatchlist}
>
{inWatchlist ? '已添加' : '加自选'}
</Button>
);
}
},
]; ];
// 涨停板块表格列 // 涨停板块表格列
@@ -1250,6 +1352,20 @@ const DetailModal = ({ isOpen, onClose, selectedDate, ztDetail, events, loading
</ModalBody> </ModalBody>
</ModalContent> </ModalContent>
</Modal> </Modal>
{/* K线图弹窗 */}
{selectedKlineStock && (
<KLineChartModal
isOpen={klineModalVisible}
onClose={() => {
setKlineModalVisible(false);
setSelectedKlineStock(null);
}}
stock={selectedKlineStock}
eventTime={selectedEventTime}
size="5xl"
/>
)}
</> </>
); );
}; };