feat: 日志优化

This commit is contained in:
zdl
2025-10-18 12:12:02 +08:00
parent 87b77af187
commit 4ebb17190f
8 changed files with 206 additions and 134 deletions

View File

@@ -34,6 +34,7 @@ import { InfoIcon, ViewIcon } from '@chakra-ui/icons';
import ReactECharts from 'echarts-for-react';
import { eventService } from '../../../services/eventService';
import CitedContent from '../../../components/Citation/CitedContent';
import { logger } from '../../../utils/logger';
// 节点样式配置 - 完全复刻Flask版本
const NODE_STYLES = {
@@ -67,40 +68,39 @@ const NODE_TYPE_LABELS = {
// 过滤孤立节点 - 完全复刻Flask版本
function filterIsolatedNodes(nodes, edges) {
console.log('开始过滤孤立节点');
console.log('输入节点:', nodes);
console.log('输入边:', edges);
logger.debug('TransmissionChain', '开始过滤孤立节点', {
nodesCount: nodes?.length,
edgesCount: edges?.length
});
if (!nodes || !edges) {
console.log('节点或边数据为空');
logger.debug('TransmissionChain', '节点或边数据为空');
return [];
}
const connectedNodeIds = new Set();
edges.forEach(edge => {
console.log('处理边:', edge, '从', edge.source, '到', edge.target);
connectedNodeIds.add(String(edge.source));
connectedNodeIds.add(String(edge.target));
});
console.log('连接的节点ID集合:', connectedNodeIds);
// 如果图中只有一个节点且是主事件,也显示它
const mainEventNode = nodes.find(n => n.extra?.is_main_event);
console.log('主事件节点:', mainEventNode);
if (mainEventNode) {
connectedNodeIds.add(String(mainEventNode.id));
console.log('添加主事件节点ID:', String(mainEventNode.id));
}
const filteredNodes = nodes.filter(node => {
const shouldKeep = connectedNodeIds.has(String(node.id));
console.log(`节点 ${node.name}(${node.id}[${String(node.id)}]): ${shouldKeep ? '保留' : '过滤'}`);
return shouldKeep;
return connectedNodeIds.has(String(node.id));
});
console.log('过滤后的节点:', filteredNodes);
logger.debug('TransmissionChain', '过滤完成', {
originalCount: nodes.length,
filteredCount: filteredNodes.length,
connectedNodesCount: connectedNodeIds.size
});
return filteredNodes;
}
@@ -146,30 +146,34 @@ function calculateEdgeWidth(strength) {
// 力导向图配置 - 完全复刻Flask版本
function getGraphOption(data) {
console.log('getGraphOption 被调用,输入数据:', data);
logger.debug('TransmissionChain', 'getGraphOption被调用', {
hasData: !!data,
nodesCount: data?.nodes?.length,
edgesCount: data?.edges?.length
});
if (!data || !data.nodes || !data.edges || data.nodes.length === 0) {
console.log('数据为空或无效');
return {
logger.debug('TransmissionChain', '数据为空或无效');
return {
title: { text: '暂无传导链数据', left: 'center', top: 'center' },
graphic: { type: 'text', left: 'center', top: '60%', style: { text: '当前事件暂无传导链分析数据', fontSize: 14 } }
};
}
console.log('原始节点数:', data.nodes.length);
console.log('原始边数:', data.edges.length);
const filteredNodes = filterIsolatedNodes(data.nodes, data.edges);
console.log('过滤后节点数:', filteredNodes.length);
console.log('过滤后的节点:', filteredNodes);
// 进一步过滤:不显示事件类型的节点
const nonEventNodes = filteredNodes.filter(node => node.extra?.node_type !== 'event');
console.log('排除事件节点后:', nonEventNodes.length);
logger.debug('TransmissionChain', '节点过滤结果', {
originalCount: data.nodes.length,
filteredCount: filteredNodes.length,
nonEventCount: nonEventNodes.length
});
if (nonEventNodes.length === 0) {
console.log('过滤后没有有效节点');
return {
logger.debug('TransmissionChain', '过滤后没有有效节点');
return {
title: { text: '暂无有效节点数据', left: 'center', top: 'center' },
graphic: { type: 'text', left: 'center', top: '60%', style: { text: '当前事件的传导链节点均为孤立节点', fontSize: 14 } }
};
@@ -180,17 +184,13 @@ function getGraphOption(data) {
name: NODE_TYPE_LABELS[type] || type,
itemStyle: { color: NODE_STYLES[type]?.color || NODE_STYLES.other.color }
}));
console.log('节点类别:', categories);
// 构建图表节点数据 - 完全复刻Flask版本样式排除事件节点
const chartNodes = nonEventNodes.map(node => {
const nodeType = node.extra?.node_type || 'other';
const nodeStyle = NODE_STYLES[nodeType] || NODE_STYLES['other'];
const connectionCount = calculateNodeConnections(node.id, data.edges);
console.log(`节点 ${node.name} (${node.id}): 类型=${nodeType}, 连接数=${connectionCount}`);
return {
id: String(node.id),
name: node.name,
@@ -433,39 +433,46 @@ const TransmissionChainAnalysis = ({ eventId }) => {
setLoading(true);
setError(null);
try {
console.log('开始加载传导链数据eventId:', eventId);
logger.debug('TransmissionChain', '开始加载传导链数据', { eventId });
const [graphRes, sankeyRes] = await Promise.all([
eventService.getTransmissionChainAnalysis(eventId),
eventService.getSankeyData(eventId)
]);
console.log('传导链数据API响应:', graphRes);
console.log('桑基图数据API响应:', sankeyRes);
logger.debug('TransmissionChain', 'API响应', {
graphSuccess: graphRes.success,
graphNodesCount: graphRes.data?.nodes?.length,
graphEdgesCount: graphRes.data?.edges?.length,
sankeySuccess: sankeyRes.success
});
if (graphRes.success && graphRes.data) {
console.log('传导链节点数据:', graphRes.data.nodes);
console.log('传导链边数据:', graphRes.data.edges);
setGraphData(graphRes.data);
} else {
console.log('传导链数据加载失败:', graphRes);
logger.warn('TransmissionChain', '传导链数据加载失败', {
success: graphRes.success,
eventId
});
setGraphData(null);
}
if (sankeyRes.success && sankeyRes.data) {
console.log('桑基图数据:', sankeyRes.data);
setSankeyData(sankeyRes.data);
} else {
console.log('桑基图数据加载失败:', sankeyRes);
logger.warn('TransmissionChain', '桑基图数据加载失败', {
success: sankeyRes.success,
eventId
});
setSankeyData(null);
}
} catch (e) {
console.error('传导链数据加载异常:', e);
logger.error('TransmissionChain', 'fetchData', e, { eventId });
setError('加载传导链数据失败');
} finally {
setLoading(false);
}
}
if (eventId) {
fetchData();
}
@@ -509,28 +516,37 @@ const TransmissionChainAnalysis = ({ eventId }) => {
if (result.success) {
return result.data;
} else {
console.error('获取节点详情失败:', result.message);
logger.error('TransmissionChain', 'getChainNodeDetail', new Error(result.message), {
nodeId,
eventId
});
return null;
}
} catch (error) {
console.error('API调用异常:', error);
logger.error('TransmissionChain', 'getChainNodeDetail', error, {
nodeId,
eventId
});
return null;
}
}
// 力导向图节点点击事件
const handleGraphNodeClick = async (params) => {
console.log('点击事件详情:', params);
logger.debug('TransmissionChain', '图表节点点击', {
dataType: params.dataType,
componentType: params.componentType,
hasData: !!params.data,
nodeId: params.data?.id
});
// 处理节点点击(包括节点本体和标签)
if ((params.dataType === 'node' || params.componentType === 'series') && params.data && params.data.id) {
console.log('点击图表节点:', params.data.id, 'dataType:', params.dataType, 'componentType:', params.componentType);
// 获取基本节点信息
const clickedNode = graphData.nodes.find(n => String(n.id) === String(params.data.id));
if (clickedNode) {
setSelectedNode(clickedNode);
// 计算传导路径
const mainEventNode = graphData?.nodes?.find(n => n.extra?.is_main_event);
if (mainEventNode && String(clickedNode.id) !== String(mainEventNode.id)) {
@@ -539,36 +555,34 @@ const TransmissionChainAnalysis = ({ eventId }) => {
} else {
setTransmissionPath([]);
}
// 获取详细节点信息包括parents和children
console.log('开始获取节点详情节点ID:', params.data.id);
logger.debug('TransmissionChain', '获取节点详情', {
nodeId: params.data.id,
nodeName: clickedNode.name
});
const detail = await getChainNodeDetail(params.data.id);
console.log('获取到的节点详情:', detail);
setNodeDetail(detail);
// 打开弹窗
setIsModalOpen(true);
}
}
// 如果点击的是空白区域,也尝试查找最近的节点
else if (params.componentType === 'series' && !params.data) {
console.log('点击了图表空白区域');
// 这里可以添加点击空白区域的处理逻辑
}
};
// 桑基图节点点击事件
const handleSankeyNodeClick = async (params) => {
if (params.dataType === 'node' && params.data && params.data.name) {
console.log('点击桑基图节点:', params.data.name);
logger.debug('TransmissionChain', '桑基图节点点击', {
nodeName: params.data.name
});
// 通过名称在原始数据中查找对应的节点
if (graphData && graphData.nodes) {
const clickedNode = graphData.nodes.find(n => n.name === params.data.name);
if (clickedNode) {
console.log('找到对应节点:', clickedNode);
setSelectedNode(clickedNode);
// 计算传导路径
const mainEventNode = graphData?.nodes?.find(n => n.extra?.is_main_event);
if (mainEventNode && String(clickedNode.id) !== String(mainEventNode.id)) {
@@ -577,17 +591,21 @@ const TransmissionChainAnalysis = ({ eventId }) => {
} else {
setTransmissionPath([]);
}
// 获取详细节点信息包括parents和children
console.log('开始获取桑基图节点详情节点ID:', clickedNode.id);
logger.debug('TransmissionChain', '获取桑基图节点详情', {
nodeId: clickedNode.id,
nodeName: clickedNode.name
});
const detail = await getChainNodeDetail(clickedNode.id);
console.log('获取到的桑基图节点详情:', detail);
setNodeDetail(detail);
// 打开弹窗
setIsModalOpen(true);
} else {
console.log('未找到对应的节点数据');
logger.warn('TransmissionChain', '未找到对应的节点数据', {
nodeName: params.data.name
});
// 创建一个临时节点信息用于显示
const tempNode = {
id: params.data.name,
@@ -601,7 +619,7 @@ const TransmissionChainAnalysis = ({ eventId }) => {
setSelectedNode(tempNode);
setTransmissionPath([]);
setNodeDetail(null);
// 打开弹窗
setIsModalOpen(true);
}
@@ -710,19 +728,11 @@ const TransmissionChainAnalysis = ({ eventId }) => {
{chartReady && (
<>
{viewMode === 'graph' ? (
<ReactECharts
<ReactECharts
option={graphData ? getGraphOption(graphData) : {}}
style={{ height: '100%', width: '100%' }}
style={{ height: '100%', width: '100%' }}
onEvents={{
click: handleGraphNodeClick,
// 添加更多事件以提高点击敏感性
mouseover: (params) => {
console.log('鼠标悬停:', params);
// 可以在这里添加悬停效果
},
mouseout: (params) => {
// 鼠标离开的处理
}
click: handleGraphNodeClick
}}
opts={{
renderer: 'canvas',
@@ -736,19 +746,11 @@ const TransmissionChainAnalysis = ({ eventId }) => {
}}
/>
) : (
<ReactECharts
<ReactECharts
option={sankeyData ? getSankeyOption(sankeyData) : {}}
style={{ height: '100%', width: '100%' }}
onEvents={{
click: handleSankeyNodeClick,
// 添加更多事件以提高点击敏感性
mouseover: (params) => {
console.log('桑基图鼠标悬停:', params);
// 可以在这里添加悬停效果
},
mouseout: (params) => {
// 鼠标离开的处理
}
click: handleSankeyNodeClick
}}
opts={{
renderer: 'canvas',