fix: 修复知识图谱节点信息无法正常渲染问题
This commit is contained in:
@@ -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) {
|
||||
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<string, Record<string, string>> = {
|
||||
'概念': { 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<string, { fill: string; stroke: string }> = {
|
||||
'概念': { 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(() => {
|
||||
|
||||
@@ -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 (
|
||||
<div className="w-80 bg-white border-l border-gray-200 shadow-lg overflow-y-auto">
|
||||
<div className="p-4 border-b border-gray-200 flex justify-between items-center">
|
||||
@@ -46,9 +51,30 @@ export const NodePanel = ({ node, onClose }: NodePanelProps) => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{node.properties && Object.keys(node.properties).length > 0 && (
|
||||
{!node.properties && (
|
||||
<div>
|
||||
<div className="text-xs text-gray-500 uppercase tracking-wide mb-2">属性</div>
|
||||
<div className="text-sm text-gray-400 italic">
|
||||
暂无属性数据
|
||||
</div>
|
||||
<div className="text-xs text-gray-300 italic mt-1">
|
||||
Debug: Node ID: {node.id}, Has properties?: {node.properties ? 'Yes' : 'No'}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{node.properties && Object.keys(node.properties).length === 0 && (
|
||||
<div>
|
||||
<div className="text-xs text-gray-500 uppercase tracking-wide mb-2">属性</div>
|
||||
<div className="text-sm text-gray-400 italic">
|
||||
属性对象存在但为空
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{node.properties && Object.keys(node.properties).length > 0 && (
|
||||
<div>
|
||||
<div className="text-xs text-gray-500 uppercase tracking-wide mb-2">属性 ({Object.keys(node.properties).length})</div>
|
||||
<div className="space-y-2">
|
||||
{Object.entries(node.properties).map(([key, value]) => (
|
||||
<div key={key} className="flex justify-between items-start">
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,9 @@ export const graphApi = {
|
||||
async getData(): Promise<GraphData> {
|
||||
try {
|
||||
const response = await apiClient.get<GraphData>('/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);
|
||||
|
||||
Reference in New Issue
Block a user