'handleNodeSelected', 'clearSelection' => 'clearSelection', ]; public function mount($selectedKpCode = null) { $this->selectedKpCode = $selectedKpCode; $this->loadGraphData(); } public function loadGraphData() { $this->isLoading = true; try { $knowledgeApiBase = config('services.knowledge_api.base_url', 'http://localhost:5011'); $response = Http::timeout(10) ->get($knowledgeApiBase . '/graph/export'); if ($response->successful()) { $data = $response->json(); $allNodes = $data['nodes'] ?? []; $allEdges = $data['edges'] ?? []; // 应用筛选 $filteredNodes = $this->applyFilters($allNodes); $this->nodes = $filteredNodes; $this->edges = $allEdges; // 转换为可视化格式 $this->graphData = $this->formatForVisualization($this->nodes, $this->edges); // 如果指定了选中的知识点,加载详细信息 if ($this->selectedKpCode) { $this->loadNodeDetails($this->selectedKpCode); } } } catch (\Exception $e) { Log::error('加载知识图谱失败', [ 'error' => $e->getMessage() ]); $this->dispatch('error', message: '加载知识图谱失败:' . $e->getMessage()); } $this->isLoading = false; } private function applyFilters($nodes) { $filtered = collect($nodes); if ($this->filterPhase) { $filtered = $filtered->where('phase', $this->filterPhase); } if ($this->filterCategory) { $filtered = $filtered->where('category', $this->filterCategory); } return $filtered->values()->toArray(); } private function formatForVisualization($nodes, $edges) { $formattedNodes = []; $formattedEdges = []; foreach ($nodes as $node) { $formattedNodes[] = [ 'id' => $node['kp_code'], 'label' => $node['cn_name'] ?? $node['kp_code'], 'kp_code' => $node['kp_code'], 'cn_name' => $node['cn_name'] ?? '', 'en_name' => $node['en_name'] ?? '', 'category' => $node['category'] ?? '', 'phase' => $node['phase'] ?? '', 'importance' => $node['importance'] ?? 0, 'description' => $node['description'] ?? '', 'skills_count' => count($node['skills'] ?? []), 'is_selected' => $this->selectedKpCode === $node['kp_code'], ]; } foreach ($edges as $edge) { $formattedEdges[] = [ 'from' => $edge['source'], 'to' => $edge['target'], 'type' => $edge['relation_type'] ?? '', 'direction' => $edge['relation_direction'] ?? '', 'label' => $edge['description'] ?? '', ]; } return [ 'nodes' => $formattedNodes, 'edges' => $formattedEdges, ]; } private function loadNodeDetails($kpCode) { try { $service = app(KnowledgeServiceApi::class); $detail = $service->getKnowledgePointDetail($kpCode); if ($detail) { // 获取上游和下游节点(一级子知识点) $upstream = $service->getUpstreamNodes($kpCode, 1); $downstream = $service->getDownstreamNodes($kpCode, 1); // 获取题目统计数据 $questionService = app(QuestionBankService::class); $stats = $questionService->getKnowledgePointStatistics($kpCode); // 构建详情数据 $detail['upstream_nodes'] = $upstream['nodes'] ?? []; $detail['downstream_nodes'] = $downstream['nodes'] ?? []; $detail['question_stats'] = $stats; $this->dispatch('nodeDetailsLoaded', details: $detail); } } catch (\Exception $e) { Log::error('加载节点详情失败', [ 'kp_code' => $kpCode, 'error' => $e->getMessage() ]); } } public function handleNodeSelected($kpCode) { $this->selectedKpCode = $kpCode; $this->loadNodeDetails($kpCode); // 刷新图谱数据以高亮选中节点 $this->graphData = $this->formatForVisualization($this->nodes, $this->edges); } public function clearSelection() { $this->selectedKpCode = null; $this->graphData = $this->formatForVisualization($this->nodes, $this->edges); $this->dispatch('nodeDetailsCleared'); } public function setLayoutType($type) { $this->layoutType = $type; $this->loadGraphData(); } public function updatedFilterPhase() { $this->loadGraphData(); } public function updatedFilterCategory() { $this->loadGraphData(); } public function getFilterOptionsProperty() { $phases = collect($this->nodes)->pluck('phase')->filter()->unique()->sort()->values()->toArray(); $categories = collect($this->nodes)->pluck('category')->filter()->unique()->sort()->values()->toArray(); return [ 'phases' => $phases, 'categories' => $categories, ]; } public function render() { return view('livewire.integrations.knowledge-graph-visualization'); } }