diff --git a/frontend/src/components/GraphView/index.tsx b/frontend/src/components/GraphView/index.tsx index df36750..7db18ac 100644 --- a/frontend/src/components/GraphView/index.tsx +++ b/frontend/src/components/GraphView/index.tsx @@ -26,85 +26,134 @@ export const GraphView = ({ if (!containerRef.current) return; try { - const graphData = { - nodes: data.nodes.map((node: Node) => ({ - ...node, - id: node.id, - })), - edges: data.edges.map((edge: Edge) => ({ - ...edge, - id: edge.id, - source: edge.source, - target: edge.target, - })), - }; + console.log('🎨 GraphView - Initializing graph with data:', data); + console.log('🎨 GraphView - Container dimensions:', { + width: containerRef.current.clientWidth, + height: height + }); if (graphRef.current) { - graphRef.current.destroy(); + try { + graphRef.current.destroy(); + } catch (e) { + console.log('🎨 GraphView - Destroy error:', e); + } graphRef.current = null; } const processedGraphData = { - nodes: graphData.nodes.map((node: any) => { - const typeColors: Record> = { - '概念': { fill: '#4ECDC4', stroke: '#45B7B0', text: '#2C3E50' }, - '工具': { fill: '#FFA07A', stroke: '#FF7F50', text: '#2C3E50' }, - '应用': { fill: '#2ECC71', stroke: '#27AE60', text: '#2C3E50' }, + nodes: data.nodes.map((node: Node) => { + const typeColors: Record = { + '概念': { fill: '#4ECDC4', stroke: '#45B7B0' }, + '工具': { fill: '#FFA07A', stroke: '#FF7F50' }, + '应用': { fill: '#2ECC71', stroke: '#27AE60' }, }; - const colors = typeColors[node.type] || { fill: '#C6E5FF', stroke: '#5B8FF9', text: '#2C3E50' }; + const colors = typeColors[node.type] || { fill: '#C6E5FF', stroke: '#5B8FF9' }; return { - ...node, - type: 'circle', + id: node.id, + data: { + id: node.id, + label: node.label, + type: node.type, + properties: node.properties, + style: node.style, + }, style: { - size: 40, fill: colors.fill, stroke: colors.stroke, lineWidth: 2, - cursor: 'pointer', - }, - data: { - ...node, - originalType: node.type, - colors, + labelText: node.label, + labelFill: '#2C3E50', + labelFontSize: 14, + labelFontWeight: 'bold', + labelPlacement: 'bottom', }, }; }), - edges: graphData.edges.map((edge: any) => ({ - ...edge, - type: 'cubic-vertical', + edges: data.edges.map((edge: Edge) => ({ + id: edge.id, + source: edge.source, + target: edge.target, + label: edge.label, + data: { + source: edge.source, + target: edge.target, + label: edge.label, + type: edge.type, + properties: edge.properties, + }, style: { stroke: '#95A5A6', lineWidth: 2, - cursor: 'pointer', + labelText: edge.label, + labelFill: '#666', + labelFontSize: 10, }, })), }; - const graph = new Graph({ + console.log('🎨 GraphView - Processed graph data nodes:', processedGraphData.nodes.length); + console.log('🎨 GraphView - Processed graph data edges:', processedGraphData.edges.length); + + const graphConfig: any = { container: containerRef.current, width: containerRef.current.clientWidth, height: height, - data: processedGraphData as any, + data: processedGraphData, autoFit: 'view', + node: { + type: 'circle', + style: { + size: 50, + lineWidth: 2, + }, + }, + edge: { + type: 'line', + style: { + lineWidth: 1, + endArrow: true, + }, + }, layout: { type: layout.type, + nodeSize: 60, preventOverlap: true, - nodeSize: layout.nodeSize || 30, - linkDistance: layout.linkDistance || 100, + linkDistance: 150, }, - behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element', 'hover-activate'], - }); + behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'], + }; + + console.log('🎨 GraphView - Creating graph with config:', graphConfig); + + const graph = new Graph(graphConfig); graphRef.current = graph; - graph.render(); + + console.log('🎨 GraphView - Starting render'); + graph.render() + .then(() => { + console.log('🎨 GraphView - Graph rendered successfully'); + }) + .catch((renderError) => { + console.error('🎨 GraphView - Render error:', renderError); + }); graph.on('node:click', (evt) => { - if (evt.itemId && onNodeClick) { - const nodeData = data.nodes.find((n: Node) => n.id === evt.itemId); + console.log('🔗 G6 - Node clicked, evt:', evt); + const nodeId = evt.itemId; + console.log('🔗 G6 - Node ID:', nodeId); + + if (nodeId && onNodeClick) { + const nodeData = data.nodes.find((n: Node) => n.id === nodeId); + console.log('🔗 G6 - Found node data:', nodeData); if (nodeData) { + console.log('🔗 G6 - Node properties:', nodeData.properties); onNodeClick(nodeData); + } else { + console.log('🔗 G6 - Node data not found for ID:', nodeId); } } }); @@ -154,6 +203,7 @@ export const GraphView = ({ onNodeClick, onEdgeClick, onNodeHover, + data, ]); useEffect(() => { diff --git a/frontend/src/components/NodePanel/index.tsx b/frontend/src/components/NodePanel/index.tsx index adfdae7..a313d4b 100644 --- a/frontend/src/components/NodePanel/index.tsx +++ b/frontend/src/components/NodePanel/index.tsx @@ -8,6 +8,11 @@ interface NodePanelProps { export const NodePanel = ({ node, onClose }: NodePanelProps) => { if (!node) return null; + console.log('📋 NodePanel - Rendering node:', node); + console.log('📋 NodePanel - Node properties:', node.properties); + console.log('📋 NodePanel - Has properties:', !!node.properties); + console.log('📋 NodePanel - Properties keys:', node.properties ? Object.keys(node.properties) : []); + return (
@@ -46,9 +51,30 @@ export const NodePanel = ({ node, onClose }: NodePanelProps) => {
)} - {node.properties && Object.keys(node.properties).length > 0 && ( + {!node.properties && (
属性
+
+ 暂无属性数据 +
+
+ Debug: Node ID: {node.id}, Has properties?: {node.properties ? 'Yes' : 'No'} +
+
+ )} + + {node.properties && Object.keys(node.properties).length === 0 && ( +
+
属性
+
+ 属性对象存在但为空 +
+
+ )} + + {node.properties && Object.keys(node.properties).length > 0 && ( +
+
属性 ({Object.keys(node.properties).length})
{Object.entries(node.properties).map(([key, value]) => (
diff --git a/frontend/src/pages/KnowledgeGraph.tsx b/frontend/src/pages/KnowledgeGraph.tsx index e8e3803..8aa7ffe 100644 --- a/frontend/src/pages/KnowledgeGraph.tsx +++ b/frontend/src/pages/KnowledgeGraph.tsx @@ -49,8 +49,13 @@ export const KnowledgeGraph = () => { setLoading(true); const data = await graphApi.getData(); + console.log('🎯 KnowledgeGraph - Received data:', data); + console.log('🎯 KnowledgeGraph - Node count:', data.nodes.length); + console.log('🎯 KnowledgeGraph - First node properties:', data.nodes[0]?.properties); + // 添加一些示例数据,如果 API 返回空数据 if (data.nodes.length === 0) { + console.log('⚠️ API returned empty data, using sample data'); const sampleData: GraphData = { nodes: [ { id: '1', label: '人工智能', type: '概念', properties: { importance: 1 } }, @@ -74,10 +79,11 @@ export const KnowledgeGraph = () => { }; setGraphData(sampleData); } else { + console.log('✅ Setting graph data from API'); setGraphData(data); } } catch (error) { - console.error('Failed to load graph data:', error); + console.error('❌ Failed to load graph data:', error); } finally { setLoading(false); } diff --git a/frontend/src/services/graphApi.ts b/frontend/src/services/graphApi.ts index 34cd349..c5f11b0 100644 --- a/frontend/src/services/graphApi.ts +++ b/frontend/src/services/graphApi.ts @@ -15,6 +15,9 @@ export const graphApi = { async getData(): Promise { try { const response = await apiClient.get('/graph'); + console.log('🔍 API Response - Graph Data:', JSON.stringify(response.data, null, 2)); + console.log('🔍 API Response - First Node:', response.data.nodes[0]); + console.log('🔍 API Response - First Node Properties:', response.data.nodes[0]?.properties); return response.data; } catch (error) { console.error('Error fetching graph data:', error);