GradingPanel.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. <?php
  2. namespace App\Livewire\UploadExam;
  3. use Livewire\Component;
  4. use App\Services\LearningAnalyticsService;
  5. use Filament\Notifications\Notification;
  6. class GradingPanel extends Component
  7. {
  8. public ?string $teacherId = null;
  9. public ?string $studentId = null;
  10. public ?string $selectedPaperId = null;
  11. public array $questions = [];
  12. public array $gradingData = [];
  13. public ?string $paperName = null;
  14. public ?string $paperClass = null;
  15. public ?string $paperStudent = null;
  16. public ?string $paperDate = null;
  17. protected $listeners = [
  18. 'loadPaper' => 'loadPaper',
  19. 'submitManualGrading' => 'handleSubmitFromParent',
  20. ];
  21. // 接收从父组件传递的参数
  22. public function mount(
  23. ?string $teacherId = null,
  24. ?string $studentId = null,
  25. ?string $selectedPaperId = null,
  26. array $questions = []
  27. ): void {
  28. $this->teacherId = $teacherId;
  29. $this->studentId = $studentId;
  30. $this->selectedPaperId = $selectedPaperId;
  31. $this->questions = $questions;
  32. }
  33. #[On('loadPaper')]
  34. public function loadPaper(string $paperId, string $teacherId, string $studentId): void
  35. {
  36. $this->selectedPaperId = $paperId;
  37. $this->teacherId = $teacherId;
  38. $this->studentId = $studentId;
  39. }
  40. public function updatedSelectedPaperId($value): void
  41. {
  42. if (!empty($value)) {
  43. // 清空评分数据
  44. $this->gradingData = [];
  45. }
  46. }
  47. public function setChoiceAnswer(int $index, bool $isCorrect)
  48. {
  49. if (!isset($this->gradingData[$index])) {
  50. $this->gradingData[$index] = [];
  51. }
  52. $this->gradingData[$index]['is_correct'] = $isCorrect;
  53. // 选择题自动计算分数
  54. if ($isCorrect && isset($this->questions[$index]['score'])) {
  55. $this->gradingData[$index]['score'] = $this->questions[$index]['score'];
  56. } else {
  57. $this->gradingData[$index]['score'] = 0;
  58. }
  59. }
  60. public function resetGrading()
  61. {
  62. $this->gradingData = array_fill(0, count($this->questions), ['score' => null, 'is_correct' => null]);
  63. Notification::make()
  64. ->title('已重置评分')
  65. ->success()
  66. ->send();
  67. }
  68. public function submitGrading()
  69. {
  70. try {
  71. // 数据验证和处理
  72. $this->convertGradingDataToQuestionGrades();
  73. \Log::info('GradingPanel: 转换后的评分数据', [
  74. 'questionGrades' => $this->questionGrades
  75. ]);
  76. if (empty($this->questionGrades)) {
  77. Notification::make()
  78. ->title('请至少为一道题目评分')
  79. ->danger()
  80. ->send();
  81. return;
  82. }
  83. // dispatch 事件让父页面处理提交
  84. $this->dispatch('submitManualGrading',
  85. questionGrades: $this->questionGrades,
  86. gradingData: $this->gradingData,
  87. questions: $this->questions
  88. );
  89. } catch (\Exception $e) {
  90. \Log::error('GradingPanel: 提交失败', [
  91. 'error' => $e->getMessage(),
  92. 'trace' => $e->getTraceAsString()
  93. ]);
  94. Notification::make()
  95. ->title('提交失败')
  96. ->body($e->getMessage())
  97. ->danger()
  98. ->send();
  99. }
  100. }
  101. private function convertGradingDataToQuestionGrades()
  102. {
  103. $this->questionGrades = [];
  104. foreach ($this->questions as $index => $question) {
  105. $grading = $this->gradingData[$index] ?? null;
  106. // 检查 grading 数据是否存在且有评分信息
  107. if ($grading && (
  108. (isset($grading['is_correct']) && $grading['is_correct'] !== null) ||
  109. (isset($grading['score']) && $grading['score'] !== null)
  110. )) {
  111. $questionId = $question['id'];
  112. // 处理评分数据...
  113. $this->questionGrades[$questionId] = [
  114. 'is_correct' => $grading['is_correct'] ?? null,
  115. 'score' => $grading['score'] ?? null,
  116. 'student_answer' => '',
  117. ];
  118. }
  119. }
  120. }
  121. public function render()
  122. {
  123. // 直接复用父页面的逻辑获取题目数据
  124. if (!empty($this->selectedPaperId)) {
  125. $this->questions = $this->loadPaperQuestionsDirectly();
  126. }
  127. return view('livewire.upload-exam.grading-panel');
  128. }
  129. // 直接加载题目数据(复用父页面逻辑)
  130. private function loadPaperQuestionsDirectly(): array
  131. {
  132. try {
  133. \Log::info('GradingPanel: 开始加载题目', ['paper_id' => $this->selectedPaperId]);
  134. $paper = \App\Models\Paper::where('paper_id', $this->selectedPaperId)->first();
  135. if (!$paper) {
  136. \Log::warning('GradingPanel: 试卷不存在', ['paper_id' => $this->selectedPaperId]);
  137. return [];
  138. }
  139. $questions = $paper->questions()->orderBy('question_number')->get();
  140. \Log::info('GradingPanel: 查询到题目', ['count' => $questions->count()]);
  141. if ($questions->isEmpty()) {
  142. \Log::warning('GradingPanel: 题目为空');
  143. // 直接返回空数组,不要返回提示信息
  144. return [];
  145. }
  146. // 无论如何都返回题目数据,即使API失败
  147. $processedQuestions = $questions->map(function($q) {
  148. return [
  149. 'id' => $q->id,
  150. 'question_number' => $q->question_number,
  151. 'question_type' => $q->question_type,
  152. 'content' => $q->question_text,
  153. 'answer' => '', // 可以为空
  154. 'score' => $q->score ?? 5,
  155. 'question_bank_id' => $q->question_bank_id,
  156. 'is_empty' => false
  157. ];
  158. })->toArray();
  159. \Log::info('GradingPanel: 处理后的题目', ['count' => count($processedQuestions)]);
  160. return $processedQuestions;
  161. } catch (\Exception $e) {
  162. \Log::error('GradingPanel: 加载失败', ['error' => $e->getMessage()]);
  163. return [];
  164. }
  165. }
  166. }