Files
knowledge-graph-agent/frontend/src/hooks/useGraphData.ts
T

110 lines
3.7 KiB
TypeScript

import { useState, useCallback, useEffect } from 'react';
import type { GraphData, Node, SearchNode } from '../types/graph';
import { graphApi } from '../services/graphApi';
import { SAMPLE_GRAPH_DATA } from '../config/sampleData';
import { resetColorAssignment } from '../config/colors';
/**
* 知识图谱数据管理 Hook
* 负责图谱数据的加载、搜索和节点选择
*/
export const useGraphData = () => {
const [graphData, setGraphData] = useState<GraphData>({ nodes: [], edges: [] });
const [selectedNode, setSelectedNode] = useState<Node | null>(null);
const [hoveredNode, setHoveredNode] = useState<Node | null>(null);
const [searchResults, setSearchResults] = useState<SearchNode[]>([]);
const [loading, setLoading] = useState(true);
// 从后端加载图谱数据
const loadGraphData = useCallback(async () => {
try {
setLoading(true);
const data = await graphApi.getData();
// 重置颜色分配缓存,确保每次加载数据时颜色分配一致
resetColorAssignment();
// 如果后端返回空数据,使用示例数据
if (data.nodes.length === 0) {
setGraphData({ ...SAMPLE_GRAPH_DATA, id: `sample-${Date.now()}` });
} else {
setGraphData({ ...data, id: `data-${Date.now()}` });
}
} catch (error) {
console.error('Failed to load graph data:', error);
// 重置颜色分配缓存
resetColorAssignment();
// API 失败时使用示例数据作为降级方案
setGraphData({ ...SAMPLE_GRAPH_DATA, id: `fallback-${Date.now()}` });
} finally {
setLoading(false);
}
}, []);
// 搜索节点(前端过滤,可根据需要切换到后端搜索)
const handleSearch = useCallback((query: string) => {
const results = graphData.nodes
.filter((node: Node) =>
node.label.toLowerCase().includes(query.toLowerCase()) ||
node.id.toLowerCase().includes(query.toLowerCase())
)
.map((node: Node) => ({
id: node.id,
label: node.label,
type: node.type,
matched: true,
}));
setSearchResults(results);
}, [graphData]);
// 通过 ID 选择节点(用于搜索结果点击)
const handleNodeSelectById = useCallback((nodeId: string) => {
console.log('[useGraphData] handleNodeSelectById called with id:', nodeId);
const node = graphData.nodes.find((n: Node) => n.id === nodeId);
console.log('[useGraphData] Found node:', node);
if (node) {
console.log('[useGraphData] Setting selectedNode:', node);
setSelectedNode(node);
} else {
console.log('[useGraphData] Node not found with id:', nodeId);
}
}, [graphData.nodes]);
// 选择节点(用于图谱点击)
const handleNodeSelect = useCallback((node: Node | null) => {
console.log('[useGraphData] handleNodeSelect called with node:', node);
console.log('[useGraphData] About to call setSelectedNode');
setSelectedNode(node);
console.log('[useGraphData] setSelectedNode called');
}, []);
// 悬停节点(用于图谱悬停)
const handleNodeHover = useCallback((node: Node | null) => {
setHoveredNode(node);
}, []);
// 监听 selectedNode 变化,用于调试
useEffect(() => {
console.log('[useGraphData] selectedNode state changed:', selectedNode);
console.log('[useGraphData] selectedNode truthiness:', !!selectedNode);
}, [selectedNode]);
// 组件挂载时加载数据
useEffect(() => {
loadGraphData();
}, [loadGraphData]);
return {
graphData,
selectedNode,
hoveredNode,
searchResults,
loading,
setSelectedNode,
handleSearch,
handleNodeSelectById,
handleNodeSelect,
handleNodeHover,
};
};