StudentAnalysis.php 5.7 KB

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