grading-scan-sheet.blade.php 3.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. @php
  2. // 判题卡项目:保留题号与题目对应方框数(用于OCR锚点+判卷标记)
  3. $scanSheetItems = [];
  4. $countBlanks = function ($text) {
  5. $text = (string)$text;
  6. // 与判卷正文保持一致:下划线、中文空括号、英文空括号
  7. $count = 0;
  8. $count += preg_match_all('/_{2,}/u', $text, $m);
  9. $count += preg_match_all('/(\s*)/u', $text, $m);
  10. $count += preg_match_all('/\(\s*\)/', $text, $m);
  11. return max(1, $count);
  12. };
  13. $countSteps = function ($text) {
  14. $text = (string)$text;
  15. // 与判卷正文保持一致:支持“步骤1”与“第1步”两种写法
  16. $count = preg_match_all('/(步骤\s*\d+|第\s*\d+\s*步)/u', $text, $m);
  17. return max(1, $count);
  18. };
  19. foreach (($questions['choice'] ?? []) as $q) {
  20. $scanSheetItems[] = ['no' => (int)($q->question_number ?? 0), 'box_count' => 1];
  21. }
  22. foreach (($questions['fill'] ?? []) as $q) {
  23. $scanSheetItems[] = ['no' => (int)($q->question_number ?? 0), 'box_count' => $countBlanks($q->content ?? '')];
  24. }
  25. foreach (($questions['answer'] ?? []) as $q) {
  26. $scanSheetItems[] = ['no' => (int)($q->question_number ?? 0), 'box_count' => $countSteps($q->solution ?? '')];
  27. }
  28. usort($scanSheetItems, function ($a, $b) {
  29. return ($a['no'] <=> $b['no']);
  30. });
  31. // 每页容量不是上限20,而是保证至少可容纳20题,并尽量提高单页承载
  32. $scanSheetPerPage = 24;
  33. $scanSheetPages = array_chunk($scanSheetItems, $scanSheetPerPage);
  34. @endphp
  35. @foreach($scanSheetPages as $pageIndex => $scanSheetPageItems)
  36. <div class="page scan-sheet-page" style="page-break-before: always; break-before: page; width:100%; max-width:100%; margin:0 auto; padding:0 8px; box-sizing:border-box;">
  37. <div class="scan-sheet-header" style="text-align:center;margin-bottom:1.5rem;border-bottom:2px solid #000;padding-bottom:1rem;">
  38. <div style="font-size:22px;font-weight:bold;">判题卡</div>
  39. <div style="display:flex;justify-content:space-between;font-size:14px;margin-top:8px;">
  40. <span>老师:{{ $teacher['name'] ?? '________' }}</span>
  41. <span>年级:@formatGrade($student['grade'] ?? '________')</span>
  42. <span>姓名:{{ $student['name'] ?? '________' }}</span>
  43. <span>得分:________</span>
  44. </div>
  45. </div>
  46. <div class="scan-sheet-hint" style="font-size:13px;color:#444;margin-bottom:10px;line-height:1.5;">提示:请根据答案和解析进行批改,在回答正确的 □ 前划 / ,在回答错误的 □ 前打 X 或置空</div>
  47. <div class="scan-sheet-list" style="display:grid;grid-template-columns:minmax(0,1fr);gap:4px;width:100%;box-sizing:border-box;">
  48. @foreach($scanSheetPageItems as $scanItem)
  49. <div class="scan-sheet-item" style="border:1px solid #b5b5b5;border-radius:4px;padding:4px 8px;min-height:28px;display:grid;grid-template-columns:auto 1fr;align-items:center;column-gap:8px;font-size:13px;line-height:1.2;page-break-inside:avoid;break-inside:avoid;width:100%;box-sizing:border-box;">
  50. <span class="scan-sheet-no" style="font-weight:700;text-align:center;min-width:58px;">题目 {{ $scanItem['no'] > 0 ? $scanItem['no'] : ($pageIndex * $scanSheetPerPage + $loop->iteration) }}.</span>
  51. <span class="scan-sheet-marks" style="display:flex;align-items:center;gap:4px 6px;justify-content:flex-start;flex-wrap:wrap;max-width:100%;">
  52. @for($i = 0; $i < max(1, (int)($scanItem['box_count'] ?? 1)); $i++)
  53. <span class="scan-grade-box" style="width:17px;height:17px;border:1px solid #333;display:inline-block;vertical-align:middle;box-sizing:border-box;"></span>
  54. @endfor
  55. </span>
  56. </div>
  57. @endforeach
  58. </div>
  59. </div>
  60. @endforeach