studentId = $studentId; $this->loadGraphData(); } public function loadGraphData(): void { $this->isLoading = true; $this->errorMessage = ''; try { // 获取掌握度数据 $learningService = app(LearningAnalyticsService::class); $masteryList = $learningService->getStudentMasteryList($this->studentId); // 获取知识点依赖关系 $dependencies = $this->getKnowledgeDependencies(); if ($masteryList && isset($masteryList['data']) && !empty($dependencies)) { $this->graphData = $this->processGraphData($masteryList['data'], $dependencies); } else { $this->graphData = []; } } catch (\Exception $e) { $this->errorMessage = '加载依赖关系图数据失败:' . $e->getMessage(); $this->graphData = []; } finally { $this->isLoading = false; } } /** * 获取知识依赖关系 */ private function getKnowledgeDependencies(): array { try { // 使用现有的 KnowledgeServiceApi $knowledgeService = app(KnowledgeServiceApi::class); $allPoints = $knowledgeService->listKnowledgePoints(); $dependencies = []; foreach ($allPoints as $point) { $kpCode = $point['kp_code'] ?? null; $parents = $point['parents'] ?? []; if ($kpCode && !empty($parents)) { foreach ($parents as $parentCode) { $dependencies[] = [ 'prerequisite_kp_code' => $parentCode, 'dependent_kp_code' => $kpCode, 'influence_weight' => 1.0, // 默认权重 'dependency_type' => 'prerequisite', ]; } } } return $dependencies; } catch (\Exception $e) { \Log::error('获取知识依赖关系失败: ' . $e->getMessage()); return []; } } /** * 处理图数据 */ private function processGraphData(array $masteryList, array $dependencies): array { $nodes = []; $edges = []; $masteryMap = []; // 创建掌握度映射 foreach ($masteryList as $mastery) { $masteryMap[$mastery['kp_code']] = $mastery['mastery_level']; } // 构建节点 foreach ($dependencies as $dep) { $sourceCode = $dep['prerequisite_kp_code']; $targetCode = $dep['dependent_kp_code']; if (!isset($masteryMap[$sourceCode])) { $masteryMap[$sourceCode] = 0.0; } if (!isset($masteryMap[$targetCode])) { $masteryMap[$targetCode] = 0.0; } // 添加源节点 if (!isset($nodes[$sourceCode])) { $nodes[$sourceCode] = [ 'id' => $sourceCode, 'label' => $this->getKnowledgePointName($sourceCode), 'mastery' => $masteryMap[$sourceCode], 'color' => $this->getMasteryColor($masteryMap[$sourceCode]), 'size' => $this->getNodeSize($masteryMap[$sourceCode]), ]; } // 添加目标节点 if (!isset($nodes[$targetCode])) { $nodes[$targetCode] = [ 'id' => $targetCode, 'label' => $this->getKnowledgePointName($targetCode), 'mastery' => $masteryMap[$targetCode], 'color' => $this->getMasteryColor($masteryMap[$targetCode]), 'size' => $this->getNodeSize($masteryMap[$targetCode]), ]; } // 添加边 $edges[] = [ 'from' => $sourceCode, 'to' => $targetCode, 'width' => $dep['influence_weight'] * 3, 'color' => $this->getEdgeColor($masteryMap[$sourceCode], $masteryMap[$targetCode]), 'label' => '权重: ' . number_format($dep['influence_weight'], 2), ]; } return [ 'nodes' => array_values($nodes), 'edges' => array_values($edges), ]; } /** * 获取知识点名称 */ private function getKnowledgePointName(string $kpCode): string { // 简单的名称映射,实际应从数据库获取 $names = [ 'KP1001' => '因式分解基础', 'KP1002' => '公因式提取', 'KP1003' => '分组分解法', 'KP1004' => '十字相乘法', 'KP1005' => '公式法', 'KP2001' => '完全平方公式', 'KP2002' => '平方差公式', 'default' => $kpCode, ]; return $names[$kpCode] ?? $names['default']; } /** * 根据掌握度获取颜色 */ private function getMasteryColor(float $masteryLevel): string { if ($masteryLevel < 0.3) { return '#ef4444'; // 红色 - 薄弱 } elseif ($masteryLevel < 0.5) { return '#f97316'; // 橙色 - 需要改进 } elseif ($masteryLevel < 0.7) { return '#eab308'; // 黄色 - 一般 } elseif ($masteryLevel < 0.85) { return '#22c55e'; // 绿色 - 良好 } else { return '#3b82f6'; // 蓝色 - 掌握 } } /** * 获取节点大小 */ private function getNodeSize(float $masteryLevel): int { return (int) (20 + $masteryLevel * 30); // 20-50像素 } /** * 获取边的颜色 */ private function getEdgeColor(float $sourceMastery, float $targetMastery): string { // 根据源节点掌握度设置边的颜色 if ($sourceMastery >= 0.7) { return '#22c55e'; // 绿色 - 源节点掌握良好 } elseif ($sourceMastery >= 0.5) { return '#eab308'; // 黄色 - 源节点一般 } else { return '#ef4444'; // 红色 - 源节点薄弱 } } /** * 选择节点 */ public function selectNode(?string $nodeId): void { $this->selectedNode = $nodeId; } public function render() { return view('livewire.knowledge-dependency-graph'); } }