community增加事件详情
This commit is contained in:
@@ -418,7 +418,9 @@ const DetailModal = ({ isOpen, onClose, selectedDate, ztDetail, events, loading
|
|||||||
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'
|
||||||
const [expandedSectors, setExpandedSectors] = useState({}); // 跟踪展开的板块
|
const [sectorStocksModalVisible, setSectorStocksModalVisible] = useState(false); // 板块股票弹窗
|
||||||
|
const [selectedSectorInfo, setSelectedSectorInfo] = useState(null); // 选中的板块信息
|
||||||
|
const [selectedSectorFilter, setSelectedSectorFilter] = useState(null); // 按个股视图的板块筛选
|
||||||
const [stocksDrawerVisible, setStocksDrawerVisible] = useState(false);
|
const [stocksDrawerVisible, setStocksDrawerVisible] = useState(false);
|
||||||
const [selectedEventStocks, setSelectedEventStocks] = useState([]);
|
const [selectedEventStocks, setSelectedEventStocks] = useState([]);
|
||||||
const [selectedEventTime, setSelectedEventTime] = useState(null);
|
const [selectedEventTime, setSelectedEventTime] = useState(null);
|
||||||
@@ -464,6 +466,16 @@ const DetailModal = ({ isOpen, onClose, selectedDate, ztDetail, events, loading
|
|||||||
.sort((a, b) => b._continuousDays - a._continuousDays); // 降序排列
|
.sort((a, b) => b._continuousDays - a._continuousDays); // 降序排列
|
||||||
}, [ztDetail]);
|
}, [ztDetail]);
|
||||||
|
|
||||||
|
// 筛选后的股票列表(按板块筛选)
|
||||||
|
const filteredStockList = useMemo(() => {
|
||||||
|
if (!selectedSectorFilter) return stockList;
|
||||||
|
// 根据选中板块筛选
|
||||||
|
const sectorData = ztDetail?.sector_data?.[selectedSectorFilter];
|
||||||
|
if (!sectorData?.stock_codes) return stockList;
|
||||||
|
const sectorStockCodes = new Set(sectorData.stock_codes);
|
||||||
|
return stockList.filter(stock => sectorStockCodes.has(stock.scode));
|
||||||
|
}, [stockList, selectedSectorFilter, ztDetail]);
|
||||||
|
|
||||||
// 热门关键词
|
// 热门关键词
|
||||||
const hotKeywords = useMemo(() => {
|
const hotKeywords = useMemo(() => {
|
||||||
if (!ztDetail?.word_freq_data) return [];
|
if (!ztDetail?.word_freq_data) return [];
|
||||||
@@ -956,89 +968,99 @@ const DetailModal = ({ isOpen, onClose, selectedDate, ztDetail, events, loading
|
|||||||
dataIndex: 'stocks',
|
dataIndex: 'stocks',
|
||||||
key: 'stocks',
|
key: 'stocks',
|
||||||
render: (stocks, record) => {
|
render: (stocks, record) => {
|
||||||
// 根据股票代码查找股票详情
|
// 根据股票代码查找股票详情,并按连板天数排序
|
||||||
const getStockInfo = (code) => {
|
const getStockInfoList = () => {
|
||||||
const stockInfo = stockList.find(s => s.scode === code);
|
return stocks
|
||||||
return stockInfo || { sname: code, scode: code };
|
.map(code => {
|
||||||
|
const stockInfo = stockList.find(s => s.scode === code);
|
||||||
|
return stockInfo || { sname: code, scode: code, _continuousDays: 1 };
|
||||||
|
})
|
||||||
|
.sort((a, b) => (b._continuousDays || 1) - (a._continuousDays || 1));
|
||||||
};
|
};
|
||||||
|
|
||||||
const sectorName = record.name;
|
const stockInfoList = getStockInfoList();
|
||||||
const isExpanded = expandedSectors[sectorName];
|
const displayStocks = stockInfoList.slice(0, 4);
|
||||||
const displayStocks = isExpanded ? stocks : stocks.slice(0, 5);
|
|
||||||
const hasMore = stocks.length > 5;
|
|
||||||
|
|
||||||
const toggleExpand = (e) => {
|
const handleShowAll = (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setExpandedSectors(prev => ({
|
setSelectedSectorInfo({
|
||||||
...prev,
|
name: record.name,
|
||||||
[sectorName]: !prev[sectorName]
|
count: record.count,
|
||||||
}));
|
stocks: stockInfoList,
|
||||||
|
});
|
||||||
|
setSectorStocksModalVisible(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<VStack align="start" spacing={1}>
|
<HStack spacing={1} flexWrap="wrap" align="center">
|
||||||
<HStack spacing={2} flexWrap="wrap">
|
{displayStocks.map((info) => (
|
||||||
{displayStocks.map((code) => {
|
<Tooltip
|
||||||
const info = getStockInfo(code);
|
key={info.scode}
|
||||||
return (
|
title={
|
||||||
<Tooltip
|
<Box>
|
||||||
key={code}
|
<div style={{ fontWeight: 'bold', marginBottom: 4 }}>{info.sname}</div>
|
||||||
title={
|
<div style={{ fontSize: '12px', color: '#888' }}>{info.scode}</div>
|
||||||
<Box>
|
{info.continuous_days && (
|
||||||
<div style={{ fontWeight: 'bold', marginBottom: 4 }}>{info.sname}</div>
|
<div style={{ fontSize: '12px', marginTop: 4, color: '#fa8c16' }}>
|
||||||
<div style={{ fontSize: '12px', color: '#888' }}>{code}</div>
|
{info.continuous_days}
|
||||||
{info.core_sectors && (
|
</div>
|
||||||
<div style={{ fontSize: '11px', marginTop: 4 }}>
|
)}
|
||||||
{info.core_sectors.slice(0, 2).join(' · ')}
|
</Box>
|
||||||
</div>
|
}
|
||||||
)}
|
placement="top"
|
||||||
{info.continuous_days && (
|
>
|
||||||
<div style={{ fontSize: '11px', marginTop: 2, color: '#fa8c16' }}>
|
<Tag
|
||||||
{info.continuous_days}
|
style={{
|
||||||
</div>
|
cursor: 'pointer',
|
||||||
)}
|
margin: '2px',
|
||||||
</Box>
|
background: info._continuousDays >= 3
|
||||||
}
|
? 'rgba(255, 77, 79, 0.2)'
|
||||||
placement="top"
|
: info._continuousDays >= 2
|
||||||
|
? 'rgba(250, 140, 22, 0.2)'
|
||||||
|
: 'rgba(59, 130, 246, 0.15)',
|
||||||
|
border: info._continuousDays >= 3
|
||||||
|
? '1px solid rgba(255, 77, 79, 0.4)'
|
||||||
|
: info._continuousDays >= 2
|
||||||
|
? '1px solid rgba(250, 140, 22, 0.4)'
|
||||||
|
: '1px solid rgba(59, 130, 246, 0.3)',
|
||||||
|
borderRadius: '6px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href={`https://valuefrontier.cn/company?scode=${info.scode}`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
style={{
|
||||||
|
color: info._continuousDays >= 3 ? '#ff4d4f' : info._continuousDays >= 2 ? '#fa8c16' : '#60A5FA',
|
||||||
|
fontSize: '13px'
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Tag
|
{info.sname}
|
||||||
style={{
|
{info._continuousDays > 1 && (
|
||||||
cursor: 'pointer',
|
<span style={{ fontSize: '10px', marginLeft: 2 }}>
|
||||||
margin: '2px',
|
({info._continuousDays}板)
|
||||||
background: 'rgba(59, 130, 246, 0.15)',
|
</span>
|
||||||
border: '1px solid rgba(59, 130, 246, 0.3)',
|
)}
|
||||||
borderRadius: '6px',
|
</a>
|
||||||
}}
|
</Tag>
|
||||||
>
|
</Tooltip>
|
||||||
<a
|
))}
|
||||||
href={`https://valuefrontier.cn/company?scode=${code}`}
|
{stocks.length > 4 && (
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
style={{ color: '#60A5FA', fontSize: '13px' }}
|
|
||||||
>
|
|
||||||
{info.sname}
|
|
||||||
</a>
|
|
||||||
</Tag>
|
|
||||||
</Tooltip>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</HStack>
|
|
||||||
{hasMore && (
|
|
||||||
<Button
|
<Button
|
||||||
type="link"
|
type="link"
|
||||||
size="small"
|
size="small"
|
||||||
onClick={toggleExpand}
|
onClick={handleShowAll}
|
||||||
style={{
|
style={{
|
||||||
padding: 0,
|
padding: '0 4px',
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
fontSize: '12px',
|
fontSize: '12px',
|
||||||
color: isExpanded ? '#888' : '#FFD700',
|
color: '#FFD700',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{isExpanded ? '收起 ▲' : `展开全部 ${stocks.length} 只 ▼`}
|
查看全部 {stocks.length} 只 →
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</VStack>
|
</HStack>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -1702,20 +1724,97 @@ const DetailModal = ({ isOpen, onClose, selectedDate, ztDetail, events, loading
|
|||||||
|
|
||||||
{/* 个股视图 */}
|
{/* 个股视图 */}
|
||||||
{ztViewMode === 'stock' && (
|
{ztViewMode === 'stock' && (
|
||||||
<Box
|
<VStack spacing={3} align="stretch">
|
||||||
borderRadius="xl"
|
{/* 板块筛选器 */}
|
||||||
border="1px solid rgba(59,130,246,0.15)"
|
<Box>
|
||||||
overflow="hidden"
|
<HStack spacing={2} mb={2}>
|
||||||
>
|
<Text fontSize="xs" color="whiteAlpha.500">板块筛选:</Text>
|
||||||
<Table
|
<Box
|
||||||
dataSource={stockList}
|
as="button"
|
||||||
columns={ztStockColumns}
|
px={3}
|
||||||
rowKey="scode"
|
py={1}
|
||||||
size="middle"
|
borderRadius="full"
|
||||||
pagination={false}
|
bg={!selectedSectorFilter ? 'rgba(255,215,0,0.2)' : 'rgba(255,255,255,0.05)'}
|
||||||
scroll={{ x: 950, y: 380 }}
|
border={!selectedSectorFilter ? '1px solid rgba(255,215,0,0.4)' : '1px solid rgba(255,255,255,0.1)'}
|
||||||
/>
|
color={!selectedSectorFilter ? '#FFD700' : '#888'}
|
||||||
</Box>
|
fontSize="xs"
|
||||||
|
onClick={() => setSelectedSectorFilter(null)}
|
||||||
|
transition="all 0.2s"
|
||||||
|
_hover={{ bg: 'rgba(255,215,0,0.15)' }}
|
||||||
|
>
|
||||||
|
全部 ({stockList.length})
|
||||||
|
</Box>
|
||||||
|
</HStack>
|
||||||
|
<HStack spacing={2} flexWrap="wrap">
|
||||||
|
{sectorList.slice(0, 10).map((sector) => (
|
||||||
|
<Box
|
||||||
|
key={sector.name}
|
||||||
|
as="button"
|
||||||
|
px={2.5}
|
||||||
|
py={1}
|
||||||
|
borderRadius="full"
|
||||||
|
bg={selectedSectorFilter === sector.name
|
||||||
|
? 'rgba(59,130,246,0.2)'
|
||||||
|
: 'rgba(255,255,255,0.03)'}
|
||||||
|
border={selectedSectorFilter === sector.name
|
||||||
|
? '1px solid rgba(59,130,246,0.4)'
|
||||||
|
: '1px solid rgba(255,255,255,0.08)'}
|
||||||
|
color={selectedSectorFilter === sector.name ? '#60A5FA' : '#888'}
|
||||||
|
fontSize="xs"
|
||||||
|
onClick={() => setSelectedSectorFilter(
|
||||||
|
selectedSectorFilter === sector.name ? null : sector.name
|
||||||
|
)}
|
||||||
|
transition="all 0.2s"
|
||||||
|
_hover={{ bg: 'rgba(59,130,246,0.1)' }}
|
||||||
|
>
|
||||||
|
{sector.name} ({sector.count})
|
||||||
|
</Box>
|
||||||
|
))}
|
||||||
|
</HStack>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* 筛选结果提示 */}
|
||||||
|
{selectedSectorFilter && (
|
||||||
|
<HStack
|
||||||
|
px={3}
|
||||||
|
py={2}
|
||||||
|
bg="rgba(59,130,246,0.1)"
|
||||||
|
borderRadius="lg"
|
||||||
|
border="1px solid rgba(59,130,246,0.2)"
|
||||||
|
>
|
||||||
|
<TagsOutlined style={{ color: '#60A5FA' }} />
|
||||||
|
<Text fontSize="sm" color="#60A5FA">
|
||||||
|
当前筛选:<strong>{selectedSectorFilter}</strong>
|
||||||
|
</Text>
|
||||||
|
<Text fontSize="sm" color="whiteAlpha.600">
|
||||||
|
共 {filteredStockList.length} 只
|
||||||
|
</Text>
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
onClick={() => setSelectedSectorFilter(null)}
|
||||||
|
style={{ color: '#888', fontSize: '12px' }}
|
||||||
|
>
|
||||||
|
清除筛选
|
||||||
|
</Button>
|
||||||
|
</HStack>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Box
|
||||||
|
borderRadius="xl"
|
||||||
|
border="1px solid rgba(59,130,246,0.15)"
|
||||||
|
overflow="hidden"
|
||||||
|
>
|
||||||
|
<Table
|
||||||
|
dataSource={filteredStockList}
|
||||||
|
columns={ztStockColumns}
|
||||||
|
rowKey="scode"
|
||||||
|
size="middle"
|
||||||
|
pagination={false}
|
||||||
|
scroll={{ x: 950, y: selectedSectorFilter ? 320 : 380 }}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</VStack>
|
||||||
)}
|
)}
|
||||||
</VStack>
|
</VStack>
|
||||||
) : (
|
) : (
|
||||||
@@ -1885,6 +1984,285 @@ const DetailModal = ({ isOpen, onClose, selectedDate, ztDetail, events, loading
|
|||||||
size="5xl"
|
size="5xl"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* 板块股票弹窗 */}
|
||||||
|
<Modal
|
||||||
|
isOpen={sectorStocksModalVisible}
|
||||||
|
onClose={() => {
|
||||||
|
setSectorStocksModalVisible(false);
|
||||||
|
setSelectedSectorInfo(null);
|
||||||
|
}}
|
||||||
|
size="4xl"
|
||||||
|
scrollBehavior="inside"
|
||||||
|
>
|
||||||
|
<ModalOverlay bg="blackAlpha.700" backdropFilter={GLASS_BLUR.sm} />
|
||||||
|
<ModalContent
|
||||||
|
maxW="900px"
|
||||||
|
maxH="85vh"
|
||||||
|
bg="linear-gradient(135deg, rgba(15,15,30,0.98) 0%, rgba(25,25,50,0.98) 100%)"
|
||||||
|
border="1px solid rgba(255,215,0,0.2)"
|
||||||
|
borderRadius="2xl"
|
||||||
|
>
|
||||||
|
<ModalHeader borderBottom="1px solid rgba(255,215,0,0.2)" py={4}>
|
||||||
|
<HStack spacing={3}>
|
||||||
|
<Box
|
||||||
|
p={2}
|
||||||
|
bg="rgba(255,215,0,0.15)"
|
||||||
|
borderRadius="lg"
|
||||||
|
border="1px solid rgba(255,215,0,0.3)"
|
||||||
|
>
|
||||||
|
<TagsOutlined style={{ color: '#FFD700', fontSize: '18px' }} />
|
||||||
|
</Box>
|
||||||
|
<VStack align="start" spacing={0}>
|
||||||
|
<HStack spacing={2}>
|
||||||
|
<Text fontSize="lg" fontWeight="bold" color="#FFD700">
|
||||||
|
{selectedSectorInfo?.name}
|
||||||
|
</Text>
|
||||||
|
<Badge
|
||||||
|
colorScheme="red"
|
||||||
|
fontSize="sm"
|
||||||
|
px={2}
|
||||||
|
borderRadius="full"
|
||||||
|
>
|
||||||
|
{selectedSectorInfo?.count} 只涨停
|
||||||
|
</Badge>
|
||||||
|
</HStack>
|
||||||
|
<Text fontSize="xs" color="whiteAlpha.500">
|
||||||
|
按连板天数降序排列
|
||||||
|
</Text>
|
||||||
|
</VStack>
|
||||||
|
</HStack>
|
||||||
|
</ModalHeader>
|
||||||
|
<ModalCloseButton color="whiteAlpha.600" _hover={{ color: 'white' }} />
|
||||||
|
<ModalBody py={4} className="hero-panel-modal">
|
||||||
|
{selectedSectorInfo?.stocks?.length > 0 ? (
|
||||||
|
<VStack spacing={3} align="stretch">
|
||||||
|
{/* 快速统计 */}
|
||||||
|
<HStack spacing={4} flexWrap="wrap">
|
||||||
|
{(() => {
|
||||||
|
const stats = { '首板': 0, '2连板': 0, '3连板': 0, '4连板+': 0 };
|
||||||
|
selectedSectorInfo.stocks.forEach(s => {
|
||||||
|
const days = s._continuousDays || 1;
|
||||||
|
if (days === 1) stats['首板']++;
|
||||||
|
else if (days === 2) stats['2连板']++;
|
||||||
|
else if (days === 3) stats['3连板']++;
|
||||||
|
else stats['4连板+']++;
|
||||||
|
});
|
||||||
|
return Object.entries(stats).map(([key, value]) => (
|
||||||
|
value > 0 && (
|
||||||
|
<Box
|
||||||
|
key={key}
|
||||||
|
px={3}
|
||||||
|
py={1}
|
||||||
|
borderRadius="full"
|
||||||
|
bg={key === '4连板+' ? 'rgba(255,77,79,0.15)' : key === '3连板' ? 'rgba(250,84,28,0.15)' : key === '2连板' ? 'rgba(250,140,22,0.15)' : 'rgba(255,255,255,0.05)'}
|
||||||
|
border={`1px solid ${key === '4连板+' ? 'rgba(255,77,79,0.3)' : key === '3连板' ? 'rgba(250,84,28,0.3)' : key === '2连板' ? 'rgba(250,140,22,0.3)' : 'rgba(255,255,255,0.1)'}`}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
fontSize="sm"
|
||||||
|
color={key === '4连板+' ? '#ff4d4f' : key === '3连板' ? '#fa541c' : key === '2连板' ? '#fa8c16' : '#888'}
|
||||||
|
>
|
||||||
|
{key}: <strong>{value}</strong>
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
));
|
||||||
|
})()}
|
||||||
|
</HStack>
|
||||||
|
|
||||||
|
{/* 股票列表 */}
|
||||||
|
<Box
|
||||||
|
borderRadius="xl"
|
||||||
|
border="1px solid rgba(255,215,0,0.15)"
|
||||||
|
overflow="hidden"
|
||||||
|
>
|
||||||
|
<Table
|
||||||
|
dataSource={selectedSectorInfo.stocks}
|
||||||
|
columns={[
|
||||||
|
{
|
||||||
|
title: '股票',
|
||||||
|
key: 'stock',
|
||||||
|
width: 130,
|
||||||
|
render: (_, record) => (
|
||||||
|
<VStack align="start" spacing={0}>
|
||||||
|
<a
|
||||||
|
href={`https://valuefrontier.cn/company?scode=${record.scode}`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
style={{ color: '#FFD700', fontWeight: 'bold', fontSize: '14px' }}
|
||||||
|
>
|
||||||
|
{record.sname}
|
||||||
|
</a>
|
||||||
|
<AntText style={{ color: '#60A5FA', fontSize: '12px' }}>{record.scode}</AntText>
|
||||||
|
</VStack>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '连板',
|
||||||
|
dataIndex: 'continuous_days',
|
||||||
|
key: 'continuous',
|
||||||
|
width: 90,
|
||||||
|
align: 'center',
|
||||||
|
render: (text, record) => {
|
||||||
|
const days = record._continuousDays || 1;
|
||||||
|
const getDaysStyle = (d) => {
|
||||||
|
if (d >= 5) return { bg: 'linear-gradient(135deg, #ff4d4f 0%, #ff7875 100%)', text: '#fff' };
|
||||||
|
if (d >= 3) return { bg: 'linear-gradient(135deg, #fa541c 0%, #ff7a45 100%)', text: '#fff' };
|
||||||
|
if (d >= 2) return { bg: 'linear-gradient(135deg, #fa8c16 0%, #ffc53d 100%)', text: '#fff' };
|
||||||
|
return { bg: 'rgba(255,255,255,0.1)', text: '#888' };
|
||||||
|
};
|
||||||
|
const style = getDaysStyle(days);
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
px={3}
|
||||||
|
py={1}
|
||||||
|
borderRadius="md"
|
||||||
|
bg={style.bg}
|
||||||
|
fontSize="13px"
|
||||||
|
fontWeight="bold"
|
||||||
|
color={style.text}
|
||||||
|
display="inline-block"
|
||||||
|
>
|
||||||
|
{text || '首板'}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '涨停时间',
|
||||||
|
dataIndex: 'formatted_time',
|
||||||
|
key: 'time',
|
||||||
|
width: 90,
|
||||||
|
align: 'center',
|
||||||
|
render: (time) => {
|
||||||
|
const getTimeStyle = (t) => {
|
||||||
|
if (t <= '09:30:00') return { bg: '#ff4d4f', text: '#fff' };
|
||||||
|
if (t <= '09:35:00') return { bg: '#fa541c', text: '#fff' };
|
||||||
|
if (t <= '10:00:00') return { bg: '#fa8c16', text: '#fff' };
|
||||||
|
return { bg: 'rgba(255,255,255,0.1)', text: '#888' };
|
||||||
|
};
|
||||||
|
const style = getTimeStyle(time || '15:00:00');
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
px={2}
|
||||||
|
py={0.5}
|
||||||
|
borderRadius="md"
|
||||||
|
bg={style.bg}
|
||||||
|
fontSize="12px"
|
||||||
|
color={style.text}
|
||||||
|
>
|
||||||
|
{time?.substring(0, 5) || '-'}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '核心板块',
|
||||||
|
dataIndex: 'core_sectors',
|
||||||
|
key: 'sectors',
|
||||||
|
render: (sectors) => (
|
||||||
|
<HStack spacing={1} flexWrap="wrap">
|
||||||
|
{(sectors || []).slice(0, 2).map((sector, idx) => (
|
||||||
|
<Tag
|
||||||
|
key={idx}
|
||||||
|
style={{
|
||||||
|
margin: '2px',
|
||||||
|
background: 'rgba(255,215,0,0.1)',
|
||||||
|
border: '1px solid rgba(255,215,0,0.2)',
|
||||||
|
borderRadius: '4px',
|
||||||
|
color: '#D4A84B',
|
||||||
|
fontSize: '11px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{sector}
|
||||||
|
</Tag>
|
||||||
|
))}
|
||||||
|
</HStack>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'K线图',
|
||||||
|
key: 'kline',
|
||||||
|
width: 80,
|
||||||
|
align: 'center',
|
||||||
|
render: (_, record) => (
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
icon={<LineChartOutlined />}
|
||||||
|
onClick={() => {
|
||||||
|
const code = record.scode;
|
||||||
|
let stockCode = code;
|
||||||
|
if (!code.includes('.')) {
|
||||||
|
if (code.startsWith('6')) stockCode = `${code}.SH`;
|
||||||
|
else if (code.startsWith('0') || code.startsWith('3')) stockCode = `${code}.SZ`;
|
||||||
|
}
|
||||||
|
setSelectedKlineStock({
|
||||||
|
stock_code: stockCode,
|
||||||
|
stock_name: record.sname
|
||||||
|
});
|
||||||
|
setKlineModalVisible(true);
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
background: 'linear-gradient(135deg, #3B82F6 0%, #8B5CF6 100%)',
|
||||||
|
border: 'none',
|
||||||
|
borderRadius: '6px',
|
||||||
|
fontSize: '12px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
查看
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
width: 90,
|
||||||
|
align: 'center',
|
||||||
|
render: (_, record) => {
|
||||||
|
const code = record.scode;
|
||||||
|
const inWatchlist = isStockInWatchlist(code);
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
type={inWatchlist ? 'primary' : 'default'}
|
||||||
|
size="small"
|
||||||
|
icon={inWatchlist ? <StarFilled /> : <StarOutlined />}
|
||||||
|
onClick={() => addSingleToWatchlist({ code, name: record.sname })}
|
||||||
|
disabled={inWatchlist}
|
||||||
|
style={inWatchlist ? {
|
||||||
|
background: 'linear-gradient(135deg, #faad14 0%, #fa8c16 100%)',
|
||||||
|
border: 'none',
|
||||||
|
borderRadius: '6px',
|
||||||
|
fontSize: '12px',
|
||||||
|
} : {
|
||||||
|
background: 'rgba(255,255,255,0.1)',
|
||||||
|
border: '1px solid rgba(255,215,0,0.3)',
|
||||||
|
borderRadius: '6px',
|
||||||
|
color: '#FFD700',
|
||||||
|
fontSize: '12px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{inWatchlist ? '已添加' : '加自选'}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
rowKey="scode"
|
||||||
|
size="small"
|
||||||
|
pagination={false}
|
||||||
|
scroll={{ y: 400 }}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</VStack>
|
||||||
|
) : (
|
||||||
|
<Center h="200px">
|
||||||
|
<Text color="whiteAlpha.500">暂无股票数据</Text>
|
||||||
|
</Center>
|
||||||
|
)}
|
||||||
|
</ModalBody>
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user