StudentAnalysis.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. <?php
  2. namespace App\Filament\Pages;
  3. use App\Services\KnowledgeGraphService;
  4. use App\Services\LearningAnalyticsService;
  5. use BackedEnum;
  6. use Filament\Pages\Page;
  7. use UnitEnum;
  8. class StudentAnalysis extends Page
  9. {
  10. protected static ?string $title = '学生掌握度分析';
  11. protected static string|BackedEnum|null $navigationIcon = 'heroicon-o-chart-bar';
  12. protected static ?string $navigationLabel = '学生分析';
  13. protected static string|UnitEnum|null $navigationGroup = '学习分析';
  14. protected static ?int $navigationSort = 1;
  15. protected string $view = 'filament.pages.student-analysis-simple';
  16. // 当前选中的学生
  17. public ?string $selectedStudentId = null;
  18. public array $studentInfo = [];
  19. public array $masteryData = [];
  20. public array $weaknesses = [];
  21. public array $skills = [];
  22. public array $learningPath = [];
  23. /**
  24. * 获取所有学生列表
  25. */
  26. public function students(): array
  27. {
  28. return \App\Models\Student::all()->toArray();
  29. }
  30. public function updatedSelectedStudentId($value)
  31. {
  32. if ($value) {
  33. $this->loadAnalysisData();
  34. } else {
  35. $this->reset(['studentInfo', 'masteryData', 'weaknesses', 'skills', 'learningPath']);
  36. }
  37. }
  38. public function loadAnalysisData()
  39. {
  40. if (!$this->selectedStudentId) {
  41. return;
  42. }
  43. $learningService = app(LearningAnalyticsService::class);
  44. // 1. 获取学生掌握度数据
  45. $this->studentInfo = $learningService->getStudentMastery($this->selectedStudentId);
  46. // 2. 获取薄弱点列表
  47. $this->weaknesses = $learningService->getStudentWeaknesses($this->selectedStudentId, 15);
  48. // 3. 获取技能熟练度(如果有API的话)
  49. $this->skills = $this->getSkillsData($this->selectedStudentId);
  50. // 4. 获取学习路径建议
  51. $pathData = $learningService->recommendLearningPaths($this->selectedStudentId, 5);
  52. $this->learningPath = $pathData['recommendations'] ?? [];
  53. // 5. 获取知识点掌握度详情
  54. $this->masteryData = $this->getMasteryDetails($this->selectedStudentId);
  55. }
  56. private function getSkillsData(string $studentId): array
  57. {
  58. // TODO: 从LearningAnalytics服务获取技能熟练度数据
  59. return [];
  60. }
  61. private function getMasteryDetails(string $studentId): array
  62. {
  63. try {
  64. // 从MySQL直接查询学生掌握度详情
  65. $db = app('db');
  66. $db->connection('remote_mysql');
  67. $masteryRecords = \Illuminate\Support\Facades\DB::connection('remote_mysql')
  68. ->table('student_mastery as sm')
  69. ->join('knowledge_points as kp', 'sm.kp', '=', 'kp.kp')
  70. ->where('sm.student_id', $studentId)
  71. ->select([
  72. 'sm.kp as kp_code',
  73. 'kp.cn_name as kp_name',
  74. 'sm.mastery',
  75. 'sm.stability',
  76. 'sm.update_time'
  77. ])
  78. ->orderBy('sm.mastery', 'asc')
  79. ->limit(50)
  80. ->get()
  81. ->toArray();
  82. return array_map(function ($record) {
  83. return [
  84. 'kp_code' => $record->kp_code,
  85. 'kp_name' => $record->kp_name,
  86. 'mastery' => (float) $record->mastery,
  87. 'stability' => (float) $record->stability,
  88. 'update_time' => $record->update_time,
  89. 'mastery_level' => $this->getMasteryLevel((float) $record->mastery),
  90. 'weakness_score' => 1.0 - (float) $record->mastery
  91. ];
  92. }, $masteryRecords);
  93. } catch (\Exception $e) {
  94. \Illuminate\Support\Facades\Log::error('获取掌握度详情失败', [
  95. 'student_id' => $studentId,
  96. 'error' => $e->getMessage()
  97. ]);
  98. return [];
  99. }
  100. }
  101. private function getMasteryLevel(float $mastery): string
  102. {
  103. if ($mastery >= 0.9) return '优秀';
  104. if ($mastery >= 0.8) return '良好';
  105. if ($mastery >= 0.7) return '中等';
  106. if ($mastery >= 0.6) return '及格';
  107. return '需提升';
  108. }
  109. public function getMasteryColor(float $mastery): string
  110. {
  111. if ($mastery >= 0.9) return '#10b981'; // emerald-500
  112. if ($mastery >= 0.8) return '#34d399'; // emerald-400
  113. if ($mastery >= 0.7) return '#fbbf24'; // amber-400
  114. if ($mastery >= 0.6) return '#fb923c'; // orange-400
  115. return '#ef4444'; // red-500
  116. }
  117. public function getMasteryBgColor(float $mastery): string
  118. {
  119. if ($mastery >= 0.9) return 'bg-emerald-100';
  120. if ($mastery >= 0.8) return 'bg-emerald-50';
  121. if ($mastery >= 0.7) return 'bg-amber-100';
  122. if ($mastery >= 0.6) return 'bg-orange-100';
  123. return 'bg-red-100';
  124. }
  125. public function generateStudyPlan()
  126. {
  127. if (!$this->selectedStudentId || empty($this->weaknesses)) {
  128. return;
  129. }
  130. // TODO: 调用LearningAnalytics服务生成学习计划
  131. // 这里可以调用专门的API来生成个性化学习计划
  132. return redirect()->route('filament.admin.auth.learning-plan', [
  133. 'student_id' => $this->selectedStudentId
  134. ]);
  135. }
  136. public function exportAnalysis()
  137. {
  138. if (!$this->selectedStudentId) {
  139. return;
  140. }
  141. // TODO: 导出分析报告为PDF或Excel
  142. // 可以调用专门的导出服务
  143. }
  144. }