'handleKpSelected', 'clearSelection' => 'clearSelection', 'refreshNetwork' => 'loadNetworkData', ]; public function mount($selectedKpCode = null) { $this->selectedKpCode = $selectedKpCode; $this->loadNetworkData(); } public function loadNetworkData() { $this->isLoading = true; try { // 获取知识图谱关联关系 $this->loadKpRelations(); // 获取题库关联关系 $this->loadQuestionRelations(); // 整合数据 $this->buildNetworkData(); } catch (\Exception $e) { \Log::error('加载知识网络失败', [ 'kp_code' => $this->selectedKpCode, 'error' => $e->getMessage() ]); $this->dispatch('error', message: '加载知识网络失败'); } $this->isLoading = false; } private function loadKpRelations() { try { $service = app(KnowledgeServiceApi::class); if ($this->selectedKpCode) { // 获取选中知识点的关联关系 $upstream = $service->getUpstreamNodes($this->selectedKpCode, 3); $downstream = $service->getDownstreamNodes($this->selectedKpCode, 3); $related = $service->getRelatedNodes($this->selectedKpCode); $this->kpRelations = [ 'upstream' => $upstream['nodes'] ?? [], 'downstream' => $downstream['nodes'] ?? [], 'related' => $related['nodes'] ?? [], ]; } else { // 获取所有关联关系(从完整图谱中提取) $graphData = $this->getFullGraphData(); $this->kpRelations = $graphData; } } catch (\Exception $e) { \Log::error('获取知识关联关系失败', ['error' => $e->getMessage()]); } } private function loadQuestionRelations() { try { $service = app(QuestionBankService::class); // 获取所有题库统计数据 $stats = $service->getKnowledgePointStatistics(); if ($this->selectedKpCode) { // 只返回选中知识点的统计 $selectedStats = collect($stats)->firstWhere('kp_code', $this->selectedKpCode); $this->questionRelations = $selectedStats ? [$selectedStats] : []; } else { $this->questionRelations = $stats; } } catch (\Exception $e) { \Log::error('获取题库关联关系失败', ['error' => $e->getMessage()]); } } private function getFullGraphData() { try { $knowledgeApiBase = config('services.knowledge_api.base_url', 'http://localhost:5011'); $response = Http::timeout(10) ->get($knowledgeApiBase . '/graph/export'); if ($response->successful()) { return $response->json(); } } catch (\Exception $e) { \Log::error('获取完整图谱失败', ['error' => $e->getMessage()]); } return ['nodes' => [], 'edges' => []]; } private function buildNetworkData() { $network = [ 'nodes' => [], 'links' => [], 'groups' => [ 'knowledge' => ['name' => '知识点', 'color' => '#3B82F6'], 'questions' => ['name' => '题库', 'color' => '#10B981'], 'skills' => ['name' => '技能', 'color' => '#F59E0B'], ], ]; // 添加知识点节点 $nodesMap = []; if ($this->selectedKpCode) { // 选中模式:添加相关知识点 $relatedNodes = array_merge( $this->kpRelations['upstream'] ?? [], $this->kpRelations['downstream'] ?? [], $this->kpRelations['related'] ?? [] ); foreach ($relatedNodes as $node) { $kpCode = $node['kp_code']; $nodesMap[$kpCode] = [ 'id' => $kpCode, 'name' => $node['cn_name'] ?? $kpCode, 'group' => 'knowledge', 'type' => 'knowledge_point', 'data' => $node, ]; } // 添加选中的知识点 $selectedNode = collect($this->kpRelations['upstream'] ?? []) ->merge($this->kpRelations['downstream'] ?? []) ->merge($this->kpRelations['related'] ?? []) ->firstWhere('kp_code', $this->selectedKpCode); if ($selectedNode) { $nodesMap[$this->selectedKpCode] = [ 'id' => $this->selectedKpCode, 'name' => $selectedNode['cn_name'] ?? $this->selectedKpCode, 'group' => 'knowledge', 'type' => 'knowledge_point', 'data' => $selectedNode, ]; } } else { // 完整模式:从题库统计中获取知识点 foreach ($this->questionRelations as $stat) { $kpCode = $stat['kp_code']; if (!$kpCode) continue; $nodesMap[$kpCode] = [ 'id' => $kpCode, 'name' => $stat['cn_name'] ?? $kpCode, 'group' => 'knowledge', 'type' => 'knowledge_point', 'question_count' => $stat['total_questions'] ?? 0, 'data' => $stat, ]; } } // 添加技能节点 foreach ($this->questionRelations as $stat) { if (isset($stat['skills']) && is_array($stat['skills'])) { foreach ($stat['skills'] as $skill) { $skillCode = $skill['skill_code'] ?? ''; if (!$skillCode) continue; $nodesMap[$skillCode] = [ 'id' => $skillCode, 'name' => $skillCode, 'group' => 'skills', 'type' => 'skill', 'data' => $skill, ]; } } } // 添加链接 foreach ($this->questionRelations as $stat) { $kpCode = $stat['kp_code']; if (!$kpCode) continue; // 知识点到题目的链接 if (isset($nodesMap[$kpCode])) { $questionCount = $stat['total_questions'] ?? 0; if ($questionCount > 0) { $network['links'][] = [ 'source' => $kpCode, 'target' => "questions_{$kpCode}", 'value' => $questionCount, 'type' => 'has_questions', ]; } // 知识点到技能点的链接 if (isset($stat['skills']) && is_array($stat['skills'])) { foreach ($stat['skills'] as $skill) { $skillCode = $skill['skill_code'] ?? ''; if ($skillCode && isset($nodesMap[$skillCode])) { $network['links'][] = [ 'source' => $kpCode, 'target' => $skillCode, 'value' => $skill['question_count'] ?? 1, 'type' => 'has_skill', ]; } } } } } $network['nodes'] = array_values($nodesMap); $this->networkData = $network; } public function handleKpSelected($kpCode) { $this->selectedKpCode = $kpCode; $this->loadNetworkData(); } public function clearSelection() { $this->selectedKpCode = null; $this->loadNetworkData(); } public function render() { return view('livewire.integrations.knowledge-network-component', [ 'networkData' => $this->networkData, ]); } }