grading-panel.blade.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. <div>
  2. <div class="bg-white shadow-md rounded-lg p-6">
  3. <h2 class="text-xl font-semibold text-gray-900 mb-6">试卷评分</h2>
  4. {{-- 评分列表 --}}
  5. @if(!empty($questions))
  6. <div class="space-y-6">
  7. @foreach($questions as $index => $question)
  8. <div class="border border-gray-200 rounded-lg p-6 hover:border-blue-300 transition-colors">
  9. {{-- 题目顶部信息 --}}
  10. <div class="flex items-center justify-between mb-4">
  11. <div class="flex items-center">
  12. <span class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-blue-100 text-blue-800 mr-3">
  13. 第 {{ $question['question_number'] ?? ($index + 1) }} 题
  14. </span>
  15. <span class="text-sm text-gray-600">
  16. {{ ($question['question_type'] ?? '未知') }}
  17. </span>
  18. <span class="ml-2 text-sm font-medium text-gray-700">
  19. ({{ $question['score'] ?? 0 }} 分)
  20. </span>
  21. </div>
  22. {{-- 当前评分状态(实时更新,放在左上角) --}}
  23. <div class="flex items-center">
  24. @if($question['question_type'] === 'choice')
  25. <span class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium
  26. {{ ($gradingData[$index]['is_correct'] ?? null) === true
  27. ? 'bg-green-100 text-green-800'
  28. : (($gradingData[$index]['is_correct'] ?? null) === false
  29. ? 'bg-red-100 text-red-800'
  30. : 'bg-gray-100 text-gray-800') }}">
  31. {{ ($gradingData[$index]['is_correct'] ?? null) === true
  32. ? '正确'
  33. : (($gradingData[$index]['is_correct'] ?? null) === false
  34. ? '错误'
  35. : '未评分') }}
  36. @if(($gradingData[$index]['is_correct'] ?? null) !== null)
  37. ({{ ($gradingData[$index]['is_correct'] ?? false) ? ($question['score'] ?? 0) : 0 }} 分)
  38. @endif
  39. </span>
  40. @else
  41. @php
  42. $score = floatval($gradingData[$index]['score'] ?? 0);
  43. $maxScore = floatval($question['score'] ?? 0);
  44. $isCorrect = $maxScore > 0 ? ($score >= $maxScore && $score > 0) : false;
  45. $isEmpty = ($gradingData[$index]['score'] ?? null) === null;
  46. @endphp
  47. <span class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium
  48. {{ $isEmpty
  49. ? 'bg-gray-100 text-gray-800'
  50. : ($isCorrect ? 'bg-green-100 text-green-800' : 'bg-yellow-100 text-yellow-800') }}">
  51. {{ $isEmpty
  52. ? '未评分'
  53. : ($isCorrect ? '完全正确' : '部分得分') }}
  54. @if(!$isEmpty)
  55. ({{ $score }} / {{ $maxScore }} 分)
  56. @endif
  57. </span>
  58. @endif
  59. </div>
  60. </div>
  61. {{-- 左右布局:题目内容 | 评分操作 --}}
  62. <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
  63. {{-- 左侧:题目内容 --}}
  64. <div class="lg:col-span-2">
  65. {{-- 题目内容 --}}
  66. <div class="mb-4">
  67. <p class="text-gray-800">{{ $question['content'] ?? $question['question_text'] ?? '' }}</p>
  68. {{-- 选择题选项 --}}
  69. @if(($question['question_type'] ?? '') === 'choice' && !empty($question['options']))
  70. <div class="mt-3 grid grid-cols-1 md:grid-cols-2 gap-2">
  71. @foreach($question['options'] as $option)
  72. <div class="text-sm text-gray-700 bg-gray-50 px-3 py-2 rounded">
  73. <span class="font-medium">{{ $option['key'] ?? '' }}.</span>
  74. <span class="ml-1">{{ $option['value'] ?? '' }}</span>
  75. </div>
  76. @endforeach
  77. </div>
  78. @endif
  79. </div>
  80. {{-- 参考答案 --}}
  81. <div class="p-3 bg-green-50 border border-green-200 rounded-md">
  82. <div class="flex items-start">
  83. <svg class="h-5 w-5 text-green-500 mr-2 flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
  84. <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
  85. </svg>
  86. <div>
  87. <p class="text-sm font-medium text-green-800">参考答案</p>
  88. @if(!empty($question['answer']))
  89. <p class="text-sm text-green-700 mt-1">{{ $question['answer'] }}</p>
  90. @else
  91. <p class="text-sm text-yellow-700 mt-1">⚠️ 未找到参考答案</p>
  92. @endif
  93. </div>
  94. </div>
  95. </div>
  96. </div>
  97. {{-- 右侧:评分操作区 --}}
  98. <div class="lg:col-span-1">
  99. <div class="border-l pl-6 h-full flex flex-col justify-center">
  100. @if($question['question_type'] === 'choice')
  101. {{-- 选择题评分 --}}
  102. <div class="space-y-4">
  103. <div class="text-sm font-medium text-gray-700">评分</div>
  104. <div class="flex flex-col space-y-2">
  105. <button
  106. type="button"
  107. wire:click="setChoiceAnswer({{ $index }}, true)"
  108. class="inline-flex items-center justify-center px-4 py-3 border rounded-md text-sm font-medium transition-colors
  109. {{ ($gradingData[$index]['is_correct'] ?? null) === true
  110. ? 'border-green-500 bg-green-500 text-white'
  111. : 'border-gray-300 bg-white text-gray-700 hover:bg-green-50 hover:border-green-300' }}">
  112. <svg class="h-4 w-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
  113. <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
  114. </svg>
  115. 正确 (✓)
  116. </button>
  117. <button
  118. type="button"
  119. wire:click="setChoiceAnswer({{ $index }}, false)"
  120. class="inline-flex items-center justify-center px-4 py-3 border rounded-md text-sm font-medium transition-colors
  121. {{ ($gradingData[$index]['is_correct'] ?? null) === false
  122. ? 'border-red-500 bg-red-500 text-white'
  123. : 'border-gray-300 bg-white text-gray-700 hover:bg-red-50 hover:border-red-300' }}">
  124. <svg class="h-4 w-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
  125. <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
  126. </svg>
  127. 错误 (✗)
  128. </button>
  129. </div>
  130. </div>
  131. @else
  132. {{-- 填空题/解答题评分 --}}
  133. <div class="space-y-4">
  134. <div class="text-sm font-medium text-gray-700">评分</div>
  135. <div class="space-y-3">
  136. <div>
  137. <label class="block text-xs text-gray-600 mb-1">得分</label>
  138. <div class="flex items-center space-x-2">
  139. <input
  140. type="number"
  141. wire:model="gradingData.{{ $index }}.score"
  142. wire:change="$refresh"
  143. placeholder="0"
  144. min="0"
  145. max="{{ $question['score'] ?? 0 }}"
  146. step="0.5"
  147. class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm">
  148. </div>
  149. <div class="text-xs text-gray-500 mt-1">满分:{{ $question['score'] ?? 0 }} 分</div>
  150. </div>
  151. </div>
  152. </div>
  153. @endif
  154. </div>
  155. </div>
  156. </div>
  157. </div>
  158. @endforeach
  159. </div>
  160. {{-- 提交按钮 --}}
  161. <div class="mt-6 flex justify-end space-x-3">
  162. <button type="button" wire:click="resetGrading" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 hover:bg-gray-50 transition-colors">
  163. 重置评分
  164. </button>
  165. <button type="submit" wire:click="submitGrading" class="px-6 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed">
  166. 提交评分
  167. </button>
  168. </div>
  169. @else
  170. <div class="text-center py-12">
  171. <svg class="mx-auto h-12 w-12 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
  172. <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
  173. </svg>
  174. <p class="mt-4 text-sm text-gray-600">暂无题目数据</p>
  175. </div>
  176. @endif
  177. </div>
  178. </div>