'required|exists:students,student_id', ]; public function mount() { $this->loadStudents(); } public function updatedSelectedStudentId($value) { if ($value) { $this->loadStudentData($value); } else { $this->resetData(); } } public function loadStudents() { $query = DB::table('students') ->select('student_id', 'name', 'grade', 'class_name') ->orderBy('grade') ->orderBy('class_name') ->orderBy('name'); // 如果是老师,只加载自己的学生 $currentUser = auth()->user(); if ($currentUser?->isTeacher() ?? false) { $teacherId = $currentUser->teacher?->teacher_id; if ($teacherId) { $query->where('teacher_id', $teacherId); } } $this->students = $query ->get() ->map(function ($student) { return [ 'id' => $student->student_id, 'label' => "{$student->name} ({$student->grade}-{$student->class_name})", ]; }) ->toArray(); } public function loadStudentData($studentId) { $this->isLoading = true; try { // 获取学生信息 $this->selectedStudent = DB::table('students') ->where('student_id', $studentId) ->first(); // 调用LearningAnalytics API获取知识图谱数据 $this->fetchKnowledgeGraphData($studentId); } catch (\Exception $e) { session()->flash('error', '加载数据失败:' . $e->getMessage()); \Log::error('加载学生知识图谱失败', [ 'student_id' => $studentId, 'error' => $e->getMessage(), ]); } $this->isLoading = false; } private function fetchKnowledgeGraphData($studentId) { $baseUrl = config('services.learning_analytics.url', 'http://localhost:5010'); try { // 获取掌握度数据 $masteryResponse = Http::timeout(10)->get($baseUrl . '/api/mastery/' . $studentId); if ($masteryResponse->successful()) { $this->masteryData = $masteryResponse->json(); } // 获取依赖关系 $dependencyResponse = Http::timeout(10)->get($baseUrl . '/api/knowledge/dependencies'); if ($dependencyResponse->successful()) { $this->dependencies = $dependencyResponse->json(); } // 获取统计信息 $statsResponse = Http::timeout(10)->get($baseUrl . '/api/mastery/' . $studentId . '/statistics'); if ($statsResponse->successful()) { $this->statistics = $statsResponse->json(); } // 获取学习路径 $pathResponse = Http::timeout(10)->get($baseUrl . '/api/learning-path/' . $studentId); if ($pathResponse->successful()) { $this->learningPath = $pathResponse->json(); } // 构建知识点图谱数据 $this->buildKnowledgeGraphData(); } catch (\Exception $e) { \Log::warning('LearningAnalytics API调用失败,使用本地数据', [ 'error' => $e->getMessage(), ]); // 如果API调用失败,使用本地模拟数据 $this->loadMockData($studentId); } } private function buildKnowledgeGraphData() { $nodes = []; $links = []; // 处理掌握度数据,构建节点 if (isset($this->masteryData['masteries'])) { foreach ($this->masteryData['masteries'] as $mastery) { $nodes[] = [ 'id' => $mastery['kp_code'], 'label' => $mastery['kp_code'], 'mastery' => $mastery['mastery_level'], 'color' => $this->getMasteryColor($mastery['mastery_level']), 'size' => $this->getMasterySize($mastery['mastery_level']), ]; } } // 处理依赖关系,构建边 if (isset($this->dependencies['dependencies'])) { foreach ($this->dependencies['dependencies'] as $dep) { $links[] = [ 'source' => $dep['prerequisite_kp'], 'target' => $dep['dependent_kp'], 'strength' => $dep['influence_weight'], 'type' => $dep['dependency_type'], ]; } } $this->knowledgePoints = [ 'nodes' => $nodes, 'links' => $links, ]; } private function loadMockData($studentId) { // 模拟数据,用于演示 $mockKnowledgePoints = [ 'R01' => ['name' => '有理数', 'mastery' => 0.85], 'R02' => ['name' => '整式运算', 'mastery' => 0.72], 'R03' => ['name' => '一元一次方程', 'mastery' => 0.65], 'R04' => ['name' => '因式分解', 'mastery' => 0.45], 'R05' => ['name' => '二次方程', 'mastery' => 0.30], 'R06' => ['name' => '二次函数', 'mastery' => 0.25], 'R07' => ['name' => '几何图形', 'mastery' => 0.78], 'R08' => ['name' => '三角形', 'mastery' => 0.68], ]; $nodes = []; foreach ($mockKnowledgePoints as $code => $data) { $nodes[] = [ 'id' => $code, 'label' => $data['name'], 'mastery' => $data['mastery'], 'color' => $this->getMasteryColor($data['mastery']), 'size' => $this->getMasterySize($data['mastery']), ]; } $links = [ ['source' => 'R01', 'target' => 'R02', 'strength' => 0.9, 'type' => 'must'], ['source' => 'R02', 'target' => 'R03', 'strength' => 0.8, 'type' => 'must'], ['source' => 'R02', 'target' => 'R04', 'strength' => 0.7, 'type' => 'should'], ['source' => 'R03', 'target' => 'R05', 'strength' => 0.9, 'type' => 'must'], ['source' => 'R04', 'target' => 'R05', 'strength' => 0.8, 'type' => 'should'], ['source' => 'R05', 'target' => 'R06', 'strength' => 0.9, 'type' => 'must'], ['source' => 'R07', 'target' => 'R08', 'strength' => 0.8, 'type' => 'should'], ]; $this->knowledgePoints = [ 'nodes' => $nodes, 'links' => $links, ]; $this->masteryData = [ 'masteries' => array_map(function ($code, $data) use ($studentId) { return [ 'student_id' => $studentId, 'kp_code' => $code, 'mastery_level' => $data['mastery'], 'confidence_level' => 0.8, ]; }, array_keys($mockKnowledgePoints), $mockKnowledgePoints), ]; $this->statistics = [ 'total_knowledge_points' => count($mockKnowledgePoints), 'average_mastery' => array_sum(array_column($mockKnowledgePoints, 'mastery')) / count($mockKnowledgePoints), 'high_mastery_count' => count(array_filter($mockKnowledgePoints, fn($d) => $d['mastery'] >= 0.7)), 'medium_mastery_count' => count(array_filter($mockKnowledgePoints, fn($d) => $d['mastery'] >= 0.4 && $d['mastery'] < 0.7)), 'low_mastery_count' => count(array_filter($mockKnowledgePoints, fn($d) => $d['mastery'] < 0.4)), ]; } private function getMasteryColor($mastery) { if ($mastery >= 0.8) return '#10b981'; // 绿色 - 优秀 if ($mastery >= 0.6) return '#3b82f6'; // 蓝色 - 良好 if ($mastery >= 0.4) return '#f59e0b'; // 黄色 - 中等 if ($mastery >= 0.2) return '#f97316'; // 橙色 - 待提高 return '#ef4444'; // 红色 - 薄弱 } private function getMasterySize($mastery) { return max(10, $mastery * 40); // 最小10px,最大40px } private function resetData() { $this->selectedStudent = null; $this->knowledgePoints = []; $this->dependencies = []; $this->masteryData = []; $this->statistics = []; $this->learningPath = []; } public function render() { return view('livewire.student-knowledge-graph'); } }