StudentKnowledgeGraph.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. <?php
  2. namespace App\Livewire;
  3. use Livewire\Component;
  4. use App\Models\Student;
  5. use App\Services\KnowledgeMasteryService;
  6. use App\Services\MasteryCalculator;
  7. use Illuminate\Support\Facades\DB;
  8. class StudentKnowledgeGraph extends Component
  9. {
  10. public $selectedStudentId = null;
  11. public $selectedStudent = null;
  12. public $knowledgePoints = [];
  13. public $dependencies = [];
  14. public $masteryData = [];
  15. public $statistics = [];
  16. public $learningPath = [];
  17. public $isLoading = false;
  18. public $students = [];
  19. protected $rules = [
  20. 'selectedStudentId' => 'required|exists:students,student_id',
  21. ];
  22. public function mount()
  23. {
  24. $this->loadStudents();
  25. }
  26. public function updatedSelectedStudentId($value)
  27. {
  28. if ($value) {
  29. $this->loadStudentData($value);
  30. } else {
  31. $this->resetData();
  32. }
  33. }
  34. public function loadStudents()
  35. {
  36. $query = DB::table('students')
  37. ->select('student_id', 'name', 'grade', 'class_name')
  38. ->orderBy('grade')
  39. ->orderBy('class_name')
  40. ->orderBy('name');
  41. // 如果是老师,只加载自己的学生
  42. $currentUser = auth()->user();
  43. if ($currentUser?->isTeacher() ?? false) {
  44. $teacherId = $currentUser->teacher?->teacher_id;
  45. if ($teacherId) {
  46. $query->where('teacher_id', $teacherId);
  47. }
  48. }
  49. $this->students = $query
  50. ->get()
  51. ->map(function ($student) {
  52. return [
  53. 'id' => $student->student_id,
  54. 'label' => "{$student->name} ({$student->grade}-{$student->class_name})",
  55. ];
  56. })
  57. ->toArray();
  58. }
  59. public function loadStudentData($studentId)
  60. {
  61. $this->isLoading = true;
  62. try {
  63. // 获取学生信息
  64. $this->selectedStudent = DB::table('students')
  65. ->where('student_id', $studentId)
  66. ->first();
  67. // 使用本地的KnowledgeMasteryService获取知识图谱数据
  68. $this->fetchKnowledgeGraphData($studentId);
  69. } catch (\Exception $e) {
  70. session()->flash('error', '加载数据失败:' . $e->getMessage());
  71. \Log::error('加载学生知识图谱失败', [
  72. 'student_id' => $studentId,
  73. 'error' => $e->getMessage(),
  74. ]);
  75. }
  76. $this->isLoading = false;
  77. }
  78. private function fetchKnowledgeGraphData($studentId)
  79. {
  80. try {
  81. // 使用本地的KnowledgeMasteryService
  82. $masteryService = app(KnowledgeMasteryService::class);
  83. $masteryCalculator = app(MasteryCalculator::class);
  84. // 获取掌握度概览
  85. $overview = $masteryCalculator->getStudentMasteryOverview($studentId);
  86. // 获取图谱数据
  87. $graphResult = $masteryService->getGraph($studentId);
  88. // 设置掌握度数据
  89. $this->masteryData = $graphResult['success'] ? $graphResult['data'] : [
  90. 'nodes' => [],
  91. 'edges' => [],
  92. ];
  93. // 设置统计信息
  94. $this->statistics = [
  95. 'total_knowledge_points' => $overview['total_knowledge_points'] ?? 0,
  96. 'average_mastery' => $overview['average_mastery_level'] ?? 0,
  97. 'mastered_count' => $overview['mastered_knowledge_points'] ?? 0,
  98. 'good_count' => $overview['good_knowledge_points'] ?? 0,
  99. 'weak_count' => $overview['weak_knowledge_points'] ?? 0,
  100. ];
  101. // 构建学习路径(基于薄弱点)
  102. $this->buildLearningPath($overview);
  103. // 构建知识点数据(用于兼容性)
  104. $this->buildKnowledgePointsData($overview);
  105. } catch (\Exception $e) {
  106. \Log::error('获取知识图谱数据失败', [
  107. 'student_id' => $studentId,
  108. 'error' => $e->getMessage(),
  109. ]);
  110. // 使用空数据作为fallback
  111. $this->masteryData = [
  112. 'nodes' => [],
  113. 'edges' => [],
  114. ];
  115. $this->statistics = [];
  116. }
  117. }
  118. /**
  119. * 构建学习路径
  120. */
  121. private function buildLearningPath(array $overview)
  122. {
  123. $this->learningPath = [];
  124. // 从薄弱点生成学习建议
  125. foreach ($overview['weak_knowledge_points_list'] ?? [] as $weakPoint) {
  126. $this->learningPath[] = [
  127. 'kp_code' => $weakPoint->kp_code ?? '',
  128. 'current_mastery' => floatval($weakPoint->mastery_level ?? 0),
  129. 'target_mastery' => 0.7,
  130. 'priority' => 'high',
  131. 'estimated_hours' => 2,
  132. 'recommendation' => '重点练习此知识点',
  133. ];
  134. }
  135. }
  136. /**
  137. * 构建知识点数据(用于兼容性)
  138. */
  139. private function buildKnowledgePointsData(array $overview)
  140. {
  141. $this->knowledgePoints = [];
  142. foreach ($overview['details'] ?? [] as $detail) {
  143. $kpCode = $detail->kp_code ?? '';
  144. $mastery = floatval($detail->mastery_level ?? 0);
  145. $this->knowledgePoints[$kpCode] = [
  146. 'name' => $kpCode,
  147. 'mastery' => $mastery,
  148. 'color' => $this->getMasteryColor($mastery),
  149. 'size' => $this->getMasterySize($mastery),
  150. ];
  151. }
  152. }
  153. private function getMasteryColor($mastery)
  154. {
  155. if ($mastery >= 0.8) return '#10b981'; // 绿色 - 优秀
  156. if ($mastery >= 0.6) return '#3b82f6'; // 蓝色 - 良好
  157. if ($mastery >= 0.4) return '#f59e0b'; // 黄色 - 中等
  158. if ($mastery >= 0.2) return '#f97316'; // 橙色 - 待提高
  159. return '#ef4444'; // 红色 - 薄弱
  160. }
  161. private function getMasterySize($mastery)
  162. {
  163. return max(10, $mastery * 40); // 最小10px,最大40px
  164. }
  165. private function resetData()
  166. {
  167. $this->selectedStudent = null;
  168. $this->knowledgePoints = [];
  169. $this->dependencies = [];
  170. $this->masteryData = [];
  171. $this->statistics = [];
  172. $this->learningPath = [];
  173. }
  174. public function render()
  175. {
  176. return view('livewire.student-knowledge-graph');
  177. }
  178. }