update ui

This commit is contained in:
2025-11-14 08:03:33 +08:00
parent 8c93606769
commit 98d063bcfe

View File

@@ -35,6 +35,7 @@ import ReactECharts from 'echarts-for-react';
import { eventService } from '../../../services/eventService';
import CitedContent from '../../../components/Citation/CitedContent';
import { logger } from '../../../utils/logger';
import { PROFESSIONAL_COLORS } from '../../../constants/professionalTheme';
// 节点样式配置 - 完全复刻Flask版本
const NODE_STYLES = {
@@ -402,8 +403,8 @@ const TransmissionChainAnalysis = ({ eventId }) => {
});
const containerRef = useRef(null);
const modalBgColor = useColorModeValue('white', 'gray.800');
const modalBorderColor = useColorModeValue('gray.200', 'gray.600');
const modalBgColor = PROFESSIONAL_COLORS.background.card;
const modalBorderColor = PROFESSIONAL_COLORS.border.default;
// 关闭弹窗并清空状态
const handleCloseModal = () => {
@@ -638,31 +639,38 @@ const TransmissionChainAnalysis = ({ eventId }) => {
return (
<Box p={6}>
{/* 统计信息条 */}
<Box mb={4}>
<Box
mb={4}
p={4}
borderRadius="lg"
border="1px solid"
borderColor={PROFESSIONAL_COLORS.border.default}
bg={PROFESSIONAL_COLORS.background.secondary}
>
<HStack spacing={6} wrap="wrap">
<Stat>
<StatLabel>总节点数</StatLabel>
<StatNumber>{stats.totalNodes}</StatNumber>
<StatLabel color={PROFESSIONAL_COLORS.text.secondary}>总节点数</StatLabel>
<StatNumber color={PROFESSIONAL_COLORS.text.primary}>{stats.totalNodes}</StatNumber>
</Stat>
<Stat>
<StatLabel>涉及行业</StatLabel>
<StatNumber>{stats.involvedIndustries}</StatNumber>
<StatLabel color={PROFESSIONAL_COLORS.text.secondary}>涉及行业</StatLabel>
<StatNumber color={PROFESSIONAL_COLORS.text.primary}>{stats.involvedIndustries}</StatNumber>
</Stat>
<Stat>
<StatLabel>相关公司</StatLabel>
<StatNumber>{stats.relatedCompanies}</StatNumber>
<StatLabel color={PROFESSIONAL_COLORS.text.secondary}>相关公司</StatLabel>
<StatNumber color={PROFESSIONAL_COLORS.text.primary}>{stats.relatedCompanies}</StatNumber>
</Stat>
<Stat>
<StatLabel>正向影响</StatLabel>
<StatNumber color="green.500">{stats.positiveImpact}</StatNumber>
<StatLabel color={PROFESSIONAL_COLORS.text.secondary}>正向影响</StatLabel>
<StatNumber color="#10B981">{stats.positiveImpact}</StatNumber>
</Stat>
<Stat>
<StatLabel>负向影响</StatLabel>
<StatNumber color="red.500">{stats.negativeImpact}</StatNumber>
<StatLabel color={PROFESSIONAL_COLORS.text.secondary}>负向影响</StatLabel>
<StatNumber color="#EF4444">{stats.negativeImpact}</StatNumber>
</Stat>
<Stat>
<StatLabel>循环效应</StatLabel>
<StatNumber color="purple.500">{stats.circularEffect}</StatNumber>
<StatLabel color={PROFESSIONAL_COLORS.text.secondary}>循环效应</StatLabel>
<StatNumber color="#A855F7">{stats.circularEffect}</StatNumber>
</Stat>
</HStack>
</Box>
@@ -671,7 +679,14 @@ const TransmissionChainAnalysis = ({ eventId }) => {
<Box mb={4}>
<HStack spacing={4} wrap="wrap">
{Object.entries(NODE_STYLES).map(([type, style]) => (
<Tag key={type} size="md">
<Tag
key={type}
size="md"
bg={PROFESSIONAL_COLORS.background.secondary}
color={PROFESSIONAL_COLORS.text.primary}
borderWidth="1px"
borderColor={PROFESSIONAL_COLORS.border.default}
>
<Box w={3} h={3} bg={style.color} borderRadius="sm" mr={2} />
{NODE_TYPE_LABELS[type] || type}
</Tag>
@@ -682,16 +697,28 @@ const TransmissionChainAnalysis = ({ eventId }) => {
{/* 视图切换按钮 */}
<Flex mb={4} gap={2}>
<Button
colorScheme={viewMode === 'graph' ? 'blue' : 'gray'}
bg={viewMode === 'graph' ? PROFESSIONAL_COLORS.gold[500] : PROFESSIONAL_COLORS.background.secondary}
color={viewMode === 'graph' ? 'black' : PROFESSIONAL_COLORS.text.primary}
_hover={{
bg: viewMode === 'graph' ? PROFESSIONAL_COLORS.gold[600] : PROFESSIONAL_COLORS.background.cardHover,
}}
onClick={() => setViewMode('graph')}
size="sm"
borderWidth="1px"
borderColor={PROFESSIONAL_COLORS.border.default}
>
力导向图
</Button>
<Button
colorScheme={viewMode === 'sankey' ? 'blue' : 'gray'}
bg={viewMode === 'sankey' ? PROFESSIONAL_COLORS.gold[500] : PROFESSIONAL_COLORS.background.secondary}
color={viewMode === 'sankey' ? 'black' : PROFESSIONAL_COLORS.text.primary}
_hover={{
bg: viewMode === 'sankey' ? PROFESSIONAL_COLORS.gold[600] : PROFESSIONAL_COLORS.background.cardHover,
}}
onClick={() => setViewMode('sankey')}
size="sm"
borderWidth="1px"
borderColor={PROFESSIONAL_COLORS.border.default}
>
桑基图
</Button>
@@ -705,7 +732,15 @@ const TransmissionChainAnalysis = ({ eventId }) => {
)}
{error && (
<Alert status="error" mb={4}>
<Alert
status="error"
mb={4}
bg="rgba(239, 68, 68, 0.1)"
color="#EF4444"
borderWidth="1px"
borderColor="#EF4444"
borderRadius="md"
>
<AlertIcon />
{error}
</Alert>
@@ -714,22 +749,30 @@ const TransmissionChainAnalysis = ({ eventId }) => {
{!loading && !error && (
<Box>
{/* 提示信息 */}
<Alert status="info" mb={4} borderRadius="md">
<Alert
status="info"
mb={4}
borderRadius="md"
bg="rgba(59, 130, 246, 0.1)"
color="#3B82F6"
borderWidth="1px"
borderColor="#3B82F6"
>
<AlertIcon />
<Text fontSize="sm">
<Text fontSize="sm" color={PROFESSIONAL_COLORS.text.secondary}>
<Icon as={ViewIcon} mr={2} />
点击图表中的节点可以查看详细信息
</Text>
</Alert>
{/* 图表容器 */}
<Box
<Box
h={viewMode === 'sankey' ? "600px" : "700px"}
border="1px solid"
borderColor="gray.300"
borderColor={PROFESSIONAL_COLORS.border.default}
borderRadius="lg"
boxShadow="md"
bg="white"
boxShadow="0 4px 12px rgba(0, 0, 0, 0.3)"
bg={PROFESSIONAL_COLORS.background.card}
p={4}
ref={containerRef}
>
@@ -785,9 +828,16 @@ const TransmissionChainAnalysis = ({ eventId }) => {
<ModalContent maxH="80vh" bg={modalBgColor}>
<ModalHeader borderBottom="1px solid" borderColor={modalBorderColor}>
<HStack justify="space-between">
<Text>{selectedNode ? '节点详情' : '传导链分析'}</Text>
<Text color={PROFESSIONAL_COLORS.text.primary}>{selectedNode ? '节点详情' : '传导链分析'}</Text>
{selectedNode && (
<Badge colorScheme="blue">{NODE_TYPE_LABELS[selectedNode.extra?.node_type] || selectedNode.extra?.node_type}</Badge>
<Badge
bg="rgba(59, 130, 246, 0.15)"
color="#3B82F6"
borderWidth="1px"
borderColor="#3B82F6"
>
{NODE_TYPE_LABELS[selectedNode.extra?.node_type] || selectedNode.extra?.node_type}
</Badge>
)}
</HStack>
</ModalHeader>
@@ -798,50 +848,103 @@ const TransmissionChainAnalysis = ({ eventId }) => {
<VStack align="stretch" spacing={4}>
{/* 节点基本信息 */}
<Box>
<Text fontWeight="bold" mb={2} color="blue.600">基本信息</Text>
<Text fontWeight="bold" mb={2} color={PROFESSIONAL_COLORS.gold[500]}>基本信息</Text>
<VStack align="stretch" spacing={2}>
<HStack align="center">
<Text fontSize="sm"><strong>名称:</strong> {selectedNode.name}</Text>
<Text fontSize="sm" color={PROFESSIONAL_COLORS.text.primary}>
<strong>名称:</strong> {selectedNode.name}
</Text>
{selectedNode.extra?.is_main_event && (
<Badge colorScheme="red" variant="solid" size="sm">主事件</Badge>
<Badge
bg="rgba(239, 68, 68, 0.15)"
color="#EF4444"
borderWidth="1px"
borderColor="#EF4444"
size="sm"
>
主事件
</Badge>
)}
</HStack>
<Text fontSize="sm"><strong>类型:</strong> {NODE_TYPE_LABELS[selectedNode.extra?.node_type] || selectedNode.extra?.node_type}</Text>
<Text fontSize="sm"><strong>重要性评分:</strong> {selectedNode.extra?.importance_score || 'N/A'}</Text>
<Text fontSize="sm" color={PROFESSIONAL_COLORS.text.primary}>
<strong>类型:</strong> {NODE_TYPE_LABELS[selectedNode.extra?.node_type] || selectedNode.extra?.node_type}
</Text>
<Text fontSize="sm" color={PROFESSIONAL_COLORS.text.primary}>
<strong>重要性评分:</strong> {selectedNode.extra?.importance_score || 'N/A'}
</Text>
{selectedNode.extra?.stock_code && (
<Text fontSize="sm"><strong>股票代码:</strong>
<Badge colorScheme="cyan" ml={2}>{selectedNode.extra.stock_code}</Badge>
<Text fontSize="sm" color={PROFESSIONAL_COLORS.text.primary}>
<strong>股票代码:</strong>
<Badge
bg="rgba(6, 182, 212, 0.15)"
color="#06B6D4"
borderWidth="1px"
borderColor="#06B6D4"
ml={2}
>
{selectedNode.extra.stock_code}
</Badge>
</Text>
)}
{nodeDetail ? (
<HStack spacing={4}>
<Badge colorScheme="gray">
<Badge
bg={PROFESSIONAL_COLORS.background.secondary}
color={PROFESSIONAL_COLORS.text.primary}
borderWidth="1px"
borderColor={PROFESSIONAL_COLORS.border.default}
>
总连接: {nodeDetail.node.total_connections || 0}
</Badge>
<Badge colorScheme="green">
<Badge
bg="rgba(16, 185, 129, 0.15)"
color="#10B981"
borderWidth="1px"
borderColor="#10B981"
>
来源: {nodeDetail.node.incoming_connections || 0}
</Badge>
<Badge colorScheme="orange">
<Badge
bg="rgba(251, 146, 60, 0.15)"
color="#FB923C"
borderWidth="1px"
borderColor="#FB923C"
>
目标: {nodeDetail.node.outgoing_connections || 0}
</Badge>
</HStack>
) : (
<HStack spacing={4}>
<Badge colorScheme="gray">
总连接: {graphData ? graphData.edges.filter(e =>
<Badge
bg={PROFESSIONAL_COLORS.background.secondary}
color={PROFESSIONAL_COLORS.text.primary}
borderWidth="1px"
borderColor={PROFESSIONAL_COLORS.border.default}
>
总连接: {graphData ? graphData.edges.filter(e =>
String(e.source) === String(selectedNode.id) || String(e.target) === String(selectedNode.id)
).length : 0}
</Badge>
<Badge colorScheme="green">
来源: {graphData ? graphData.edges.filter(e =>
<Badge
bg="rgba(16, 185, 129, 0.15)"
color="#10B981"
borderWidth="1px"
borderColor="#10B981"
>
来源: {graphData ? graphData.edges.filter(e =>
String(e.target) === String(selectedNode.id)
).length : 0}
</Badge>
<Badge colorScheme="orange">
目标: {graphData ? graphData.edges.filter(e =>
<Badge
bg="rgba(251, 146, 60, 0.15)"
color="#FB923C"
borderWidth="1px"
borderColor="#FB923C"
>
目标: {graphData ? graphData.edges.filter(e =>
String(e.source) === String(selectedNode.id)
).length : 0}
</Badge>
@@ -853,14 +956,14 @@ const TransmissionChainAnalysis = ({ eventId }) => {
{/* 节点描述 */}
{selectedNode.extra?.description && (
<Box>
<Text fontWeight="bold" mb={2} color="blue.600">描述</Text>
<Text fontWeight="bold" mb={2} color={PROFESSIONAL_COLORS.gold[500]}>描述</Text>
<Box
fontSize="sm"
color="gray.600"
color={PROFESSIONAL_COLORS.text.secondary}
borderLeft="3px solid"
borderColor="blue.200"
borderColor="#3B82F6"
pl={3}
bg="gray.50"
bg={PROFESSIONAL_COLORS.background.secondary}
p={2}
borderRadius="md"
fontStyle="italic"
@@ -880,11 +983,17 @@ const TransmissionChainAnalysis = ({ eventId }) => {
{/* 传导路径 */}
{transmissionPath && transmissionPath.length > 0 && (
<Box>
<Text fontWeight="bold" mb={2} color="blue.600">传导路径</Text>
<Box bg="gray.50" p={3} borderRadius="md" borderLeft="4px solid" borderColor="blue.500">
<Text fontWeight="bold" mb={2} color={PROFESSIONAL_COLORS.gold[500]}>传导路径</Text>
<Box
bg={PROFESSIONAL_COLORS.background.secondary}
p={3}
borderRadius="md"
borderLeft="4px solid"
borderColor="#3B82F6"
>
<List spacing={1}>
{transmissionPath.map((node, index) => (
<ListItem key={index} fontSize="sm">
<ListItem key={index} fontSize="sm" color={PROFESSIONAL_COLORS.text.primary}>
{index === 0 && '🚀 '}
{index === transmissionPath.length - 1 && '🎯 '}
{index > 0 && index < transmissionPath.length - 1 && '➡️ '}
@@ -906,19 +1015,38 @@ const TransmissionChainAnalysis = ({ eventId }) => {
if (sourcesFromAPI) {
return (
<Box>
<Text fontWeight="bold" mb={2} color="blue.600">
<Text fontWeight="bold" mb={2} color={PROFESSIONAL_COLORS.gold[500]}>
影响来源 ({nodeDetail.parents.length})AI合成
</Text>
<List spacing={2}>
{nodeDetail.parents.map((parent, index) => (
<ListItem key={index} p={2} bg="gray.50" borderRadius="md" borderLeft="3px solid" borderColor="green.300" position="relative">
<ListItem
key={index}
p={2}
bg={PROFESSIONAL_COLORS.background.secondary}
borderRadius="md"
borderLeft="3px solid"
borderColor="#10B981"
position="relative"
>
<HStack position="absolute" top={2} right={2} spacing={2} zIndex={1}>
{parent.direction && (
<Badge
colorScheme={
parent.direction === 'positive' ? 'green' :
parent.direction === 'negative' ? 'red' :
'gray'
bg={
parent.direction === 'positive' ? 'rgba(16, 185, 129, 0.15)' :
parent.direction === 'negative' ? 'rgba(239, 68, 68, 0.15)' :
'rgba(107, 114, 128, 0.15)'
}
color={
parent.direction === 'positive' ? '#10B981' :
parent.direction === 'negative' ? '#EF4444' :
'#6B7280'
}
borderWidth="1px"
borderColor={
parent.direction === 'positive' ? '#10B981' :
parent.direction === 'negative' ? '#EF4444' :
'#6B7280'
}
size="sm"
>
@@ -928,11 +1056,26 @@ const TransmissionChainAnalysis = ({ eventId }) => {
</Badge>
)}
{parent.is_circular && (
<Badge colorScheme="purple" size="sm">🔄 循环</Badge>
<Badge
bg="rgba(168, 85, 247, 0.15)"
color="#A855F7"
borderWidth="1px"
borderColor="#A855F7"
size="sm"
>
🔄 循环
</Badge>
)}
</HStack>
<VStack align="stretch" spacing={1}>
<Text fontWeight="bold" fontSize="sm" pr={parent.direction || parent.is_circular ? 20 : 0}>{parent.name}</Text>
<Text
fontWeight="bold"
fontSize="sm"
color={PROFESSIONAL_COLORS.text.primary}
pr={parent.direction || parent.is_circular ? 20 : 0}
>
{parent.name}
</Text>
{parent.transmission_mechanism?.data ? (
<CitedContent
data={parent.transmission_mechanism}