exam-grading.blade.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. @php
  2. $grading = true;
  3. // 提取15位paper_id数字部分作为学案编号
  4. $rawPaperId = $paper->paper_id ?? 'unknown';
  5. preg_match('/paper_(\d{15})/', $rawPaperId, $matches);
  6. $gradingCode = $matches[1] ?? preg_replace('/[^0-9]/', '', $rawPaperId);
  7. $studentName = $student['name'] ?? ($paper->student_id ?? '________');
  8. // 生成时间(格式:2026年01月30日 15:04:05)
  9. $generateDateTime = now()->format('Y年m月d日 H:i:s');
  10. @endphp
  11. <!DOCTYPE html>
  12. <html lang="zh-CN">
  13. <head>
  14. <meta charset="UTF-8">
  15. <title>{{ $paper->paper_name ?? '判卷预览' }}</title>
  16. <link rel="stylesheet" href="/css/katex/katex.min.css">
  17. <style>
  18. @page {
  19. size: A4;
  20. margin: 2.2cm 2cm 2.3cm 2cm;
  21. @top-left {
  22. content: "知了数学·{{ $generateDateTime }}";
  23. font-size: 13px;
  24. color: #666;
  25. }
  26. @top-center {
  27. content: "{{ $studentName }}";
  28. font-size: 13px;
  29. color: #666;
  30. }
  31. @top-right {
  32. content: "{{ $gradingCode }}";
  33. font-size: 13px;
  34. color: #666;
  35. }
  36. @bottom-left {
  37. content: "{{ $gradingCode }}";
  38. font-size: 13px;
  39. color: #666;
  40. }
  41. @bottom-right {
  42. content: counter(page) "/" counter(pages);
  43. font-size: 13px;
  44. color: #666;
  45. }
  46. }
  47. :root {
  48. --question-gap: 6px;
  49. }
  50. body {
  51. font-family: "SimSun", "Songti SC", serif;
  52. line-height: 1.65;
  53. color: #000;
  54. background: #fff;
  55. font-size: 14px;
  56. }
  57. .page {
  58. max-width: 720px;
  59. margin: 0 auto;
  60. padding: 0 12px;
  61. }
  62. .header { text-align: center; margin-bottom: 1.5rem; border-bottom: 2px solid #000; padding-bottom: 1rem; }
  63. /* 大题标题:不与后面内容分开 */
  64. .section-title {
  65. font-size: 16px;
  66. font-weight: bold;
  67. margin-top: 16px;
  68. margin-bottom: 10px;
  69. page-break-after: avoid;
  70. break-after: avoid;
  71. }
  72. /* 题目整体:不分页 */
  73. .question {
  74. margin-bottom: 14px;
  75. page-break-inside: avoid;
  76. break-inside: avoid;
  77. -webkit-column-break-inside: avoid;
  78. }
  79. /* 题目网格:不分页 */
  80. .question-grid {
  81. display: grid;
  82. grid-template-columns: auto 1fr;
  83. column-gap: 4px;
  84. row-gap: 6px;
  85. align-items: flex-start;
  86. page-break-inside: avoid;
  87. break-inside: avoid;
  88. }
  89. .question-lead {
  90. display: flex;
  91. gap: 4px;
  92. align-items: flex-start;
  93. font-weight: 600;
  94. font-size: 14px;
  95. line-height: 1.6;
  96. margin-top: 2px;
  97. }
  98. .question-lead.spacer { visibility: hidden; }
  99. .question-number { white-space: nowrap; margin-right: 2px; }
  100. .grading-boxes { gap: 4px; flex-wrap: wrap; align-items: center; }
  101. .grading-boxes span { vertical-align: middle; }
  102. /* 题目内容:防止孤行 */
  103. .question-main {
  104. font-size: 14px;
  105. line-height: 1.65;
  106. font-family: inherit;
  107. display: block;
  108. orphans: 3;
  109. widows: 3;
  110. }
  111. .question-score { margin-right: 6px; font-weight: 600; }
  112. .question-stem {
  113. display: inline-block;
  114. font-size: 14px;
  115. font-family: inherit;
  116. orphans: 3;
  117. widows: 3;
  118. }
  119. /* 选项容器:不分页 */
  120. .options {
  121. display: grid;
  122. row-gap: 8px;
  123. margin-top: 8px;
  124. page-break-inside: avoid;
  125. break-inside: avoid;
  126. }
  127. .options-grid-4 {
  128. display: grid;
  129. grid-template-columns: repeat(4, 1fr);
  130. gap: 8px 12px;
  131. page-break-inside: avoid;
  132. break-inside: avoid;
  133. }
  134. .options-grid-2 {
  135. display: grid;
  136. grid-template-columns: 1fr 1fr;
  137. gap: 8px 20px;
  138. page-break-inside: avoid;
  139. break-inside: avoid;
  140. }
  141. .options-grid-1 {
  142. display: grid;
  143. grid-template-columns: 1fr;
  144. gap: 8px;
  145. page-break-inside: avoid;
  146. break-inside: avoid;
  147. }
  148. /* 单个选项:不分页 */
  149. .option {
  150. display: flex;
  151. align-items: flex-start;
  152. font-size: 14px;
  153. line-height: 1.6;
  154. page-break-inside: avoid;
  155. break-inside: avoid;
  156. }
  157. .option strong { margin-right: 4px; }
  158. .option-compact { font-size: 14px; line-height: 1.6; }
  159. /* 答案区域:不分页 */
  160. .answer-area {
  161. position: relative;
  162. margin-top: 4px;
  163. page-break-inside: avoid;
  164. break-inside: avoid;
  165. }
  166. .answer-area.boxy {
  167. min-height: 150px;
  168. border: 1.5px solid #444;
  169. border-radius: 6px;
  170. padding: 14px;
  171. }
  172. .answer-label {
  173. position: absolute;
  174. top: -10px;
  175. left: 10px;
  176. font-size: 10px;
  177. background: #fff;
  178. padding: 0 4px;
  179. color: #555;
  180. letter-spacing: 1px;
  181. }
  182. /* 答案元信息:不分页 */
  183. .answer-meta {
  184. font-size: 12px;
  185. color: #2f2f2f;
  186. line-height: 1.75;
  187. margin-top: 4px;
  188. page-break-inside: avoid;
  189. break-inside: avoid;
  190. }
  191. .answer-line + .answer-line { margin-top: 4px; }
  192. .solution-step {
  193. align-items: center;
  194. gap: 6px;
  195. }
  196. .step-box { display: inline-block; }
  197. .step-label { white-space: nowrap; }
  198. .solution-heading { font-weight: 700; }
  199. .solution-content { display: inline-block; line-height: 1.75; }
  200. /* 解析区域:不分页 */
  201. .solution-section {
  202. margin-top: 8px;
  203. padding: 6px 8px;
  204. page-break-inside: avoid;
  205. break-inside: avoid;
  206. }
  207. .solution-section strong {
  208. font-size: 13px;
  209. }
  210. .solution-parsed {
  211. margin-top: 6px;
  212. line-height: 1.8;
  213. }
  214. svg, .math-render svg {
  215. max-width: 100%;
  216. height: auto;
  217. display: block;
  218. /* 确保SVG中的文字和图形元素正确对齐 */
  219. shape-rendering: geometricPrecision;
  220. text-rendering: geometricPrecision;
  221. }
  222. /* 优化SVG中文字标签的显示 */
  223. svg text {
  224. font-family: "SimSun", "Times New Roman", serif !important;
  225. font-size: 12px;
  226. font-weight: bold;
  227. dominant-baseline: middle;
  228. text-anchor: middle;
  229. alignment-baseline: central;
  230. /* 确保文字在点的正中央 */
  231. paint-order: stroke fill;
  232. stroke: none;
  233. fill: #000;
  234. }
  235. /* SVG中点标签的精确对齐 */
  236. svg text.label-point {
  237. font-size: 14px;
  238. font-weight: bold;
  239. dx: 0;
  240. dy: 0;
  241. }
  242. /* 确保SVG中的圆形和线条正确渲染 */
  243. svg circle, svg line, svg polygon, svg polyline {
  244. shape-rendering: geometricPrecision;
  245. }
  246. /* PDF图片容器:防止图片跨页分割 - 增强版 */
  247. .pdf-figure {
  248. break-inside: avoid;
  249. page-break-inside: avoid;
  250. -webkit-column-break-inside: avoid;
  251. break-before: avoid;
  252. break-after: avoid;
  253. page-break-before: avoid;
  254. page-break-after: avoid;
  255. margin: 8px 0;
  256. display: block;
  257. /* 确保图片不会在页面底部被截断 */
  258. min-height: 30px;
  259. /* 限制单张图片最大高度,防止过大图片跨页 */
  260. max-height: 180mm;
  261. }
  262. .pdf-figure img {
  263. max-width: 100%;
  264. height: auto;
  265. display: block;
  266. margin: 0 auto;
  267. object-fit: contain;
  268. box-sizing: border-box;
  269. }
  270. /* 题干中的图片样式(向后兼容) */
  271. .question-stem img,
  272. .question-main img,
  273. .question-content img {
  274. display: block;
  275. max-width: 100%;
  276. height: auto;
  277. margin: 12px auto;
  278. box-sizing: border-box;
  279. }
  280. /* 选项中的图片样式 - 防止超出容器 */
  281. .option img {
  282. max-width: 100%;
  283. height: auto;
  284. vertical-align: middle;
  285. }
  286. </style>
  287. </head>
  288. <body style="page-break-before: always;">
  289. <div class="page">
  290. <div class="header">
  291. <div style="font-size:22px;font-weight:bold;">判卷专用</div>
  292. <div style="font-size:18px;">{{ $gradingCode }}</div>
  293. <div style="display:flex;justify-content:space-between;font-size:14px;margin-top:8px;">
  294. <span>老师:{{ $teacher['name'] ?? '________' }}</span>
  295. <span>年级:@formatGrade($student['grade'] ?? '________')</span>
  296. <span>姓名:{{ $student['name'] ?? '________' }}</span>
  297. <span>得分:________</span>
  298. </div>
  299. <div style="font-size:13px;margin-top:10px;color:#333;text-align:left;">提示:请根据答案和解析进行批改,在回答正确的 □ 前划 / ,在回答错误的 □ 前打 X 或置空</div>
  300. </div>
  301. @include('components.exam.paper-body', ['questions' => $questions, 'grading' => true])
  302. </div>
  303. <!-- KaTeX -->
  304. <script src="/js/katex.min.js"></script>
  305. <script src="/js/auto-render.min.js"></script>
  306. <script>
  307. document.addEventListener('DOMContentLoaded', function() {
  308. try {
  309. renderMathInElement(document.body, {
  310. delimiters: [
  311. {left: '$$', right: '$$', display: true},
  312. {left: '$', right: '$', display: false},
  313. {left: '\\(', right: '\\)', display: false},
  314. {left: '\\[', right: '\\]', display: true}
  315. ],
  316. throwOnError: false,
  317. strict: false,
  318. trust: true
  319. });
  320. } catch(e) {}
  321. });
  322. </script>
  323. </body>
  324. </html>