Kaynağa Gözat

Merge branch 'codex/ye-answer-detail-page'

yemeishu 1 hafta önce
ebeveyn
işleme
82533f5096

+ 2 - 2
app/Support/GradingMarkBoxCounter.php

@@ -25,7 +25,8 @@ class GradingMarkBoxCounter
         $parts = preg_split('/(?=步骤\s*\d+|第\s*\d+\s*步)/u', $text, -1, PREG_SPLIT_NO_EMPTY) ?: [];
         $count = 0;
         foreach ($parts as $part) {
-            if (trim((string) $part) !== '') {
+            $stepText = trim((string) $part);
+            if ($stepText !== '' && preg_match('/^(步骤\s*\d+|第\s*\d+\s*步)/u', $stepText)) {
                 $count++;
             }
         }
@@ -33,4 +34,3 @@ class GradingMarkBoxCounter
         return max(1, $count);
     }
 }
-

+ 7 - 3
resources/views/components/exam/paper-body.blade.php

@@ -474,13 +474,17 @@
 
                                     if (count($allSteps) > 0) {
                                         $processed = '';
-                                        // 为每个步骤添加方框(包括第一个)
+                                        // 与判题卡计数规则一致:仅显式步骤前加方框;前置引导语不加方框
                                         for ($i = 0; $i < count($allSteps); $i++) {
                                             $stepText = trim($allSteps[$i]);
                                             if (!empty($stepText)) {
-                                                // 为每个步骤添加方框和换行(第一个步骤前面不加<br>)
                                                 $prefix = ($i > 0) ? '<br>' : '';
-                                                $processed .= $prefix . '<span class="solution-step"><span class="step-box">' . $renderBoxes(1) . '</span><span class="step-label">' . $stepText . '</span></span>';
+                                                $isStep = preg_match('/^(步骤\s*\d+|第\s*\d+\s*步)/u', $stepText);
+                                                if ($isStep) {
+                                                    $processed .= $prefix . '<span class="solution-step"><span class="step-box">' . $renderBoxes(1) . '</span><span class="step-label">' . $stepText . '</span></span>';
+                                                } else {
+                                                    $processed .= $prefix . '<span class="step-label">' . $stepText . '</span>';
+                                                }
                                             }
                                         }
                                         $sectionContent = $processed;

+ 45 - 0
resources/views/pdf/partials/answer-detail-page.blade.php

@@ -74,6 +74,46 @@
         return ltrim($text, '<br>');
     };
 
+    $renderAnswerSolutionWithStepBoxes = function (string $solutionHtml): string {
+        $solution = trim($solutionHtml);
+        if ($solution === '' || $solution === '(无详解)') {
+            return $solutionHtml;
+        }
+
+        // 去掉分步得分等分值标记,与判卷页一致
+        $solution = preg_replace('/(\s*\d+\s*分\s*)/u', '', $solution) ?? $solution;
+
+        // 与判卷页一致:优先识别“步骤X / 第X步”
+        if (preg_match('/(步骤\s*\d+|第\s*\d+\s*步)/u', $solution)) {
+            $parts = preg_split('/(?=步骤\s*\d+|第\s*\d+\s*步)/u', $solution, -1, PREG_SPLIT_NO_EMPTY) ?: [];
+            $processed = '';
+            foreach ($parts as $index => $part) {
+                $stepText = trim((string) $part);
+                if ($stepText === '') {
+                    continue;
+                }
+                $prefix = $index > 0 ? '<br>' : '';
+                $isStep = preg_match('/^(步骤\s*\d+|第\s*\d+\s*步)/u', $stepText);
+                if ($isStep) {
+                    $processed .= $prefix
+                        . '<span class="solution-step"><span class="step-box"><span class="detail-grade-box"></span></span><span class="step-label">'
+                        . $stepText
+                        . '</span></span>';
+                } else {
+                    // 与判卷页保持一致:步骤前引导语不加方框
+                    $processed .= $prefix . '<span class="step-label">' . $stepText . '</span>';
+                }
+            }
+
+            return $processed !== '' ? $processed : $solution;
+        }
+
+        // 无步骤关键词:与判卷页一致,在解析开头加一个判分框
+        return '<span class="solution-step"><span class="step-box"><span class="detail-grade-box"></span></span><span class="step-label">'
+            . $solution
+            . '</span></span>';
+    };
+
 @endphp
 
 <div class="answer-detail-page">
@@ -92,6 +132,8 @@
         @foreach($allQuestions as $q)
             @php
                 $no = (int) ($q->question_number ?? 0);
+                $questionType = strtolower((string) ($q->question_type ?? ''));
+                $isAnswerType = $questionType === 'answer';
                 $rawAnswer = trim((string) ($q->answer ?? ''));
                 $rawSolution = $normalizeDetailHtml($q->solution ?? '');
                 $isSeeSolutionAnswer = (bool) preg_match('/^见\s*解析[。\.]?$|^详见解析/u', $rawAnswer);
@@ -102,6 +144,9 @@
                 $renderSolution = $rawSolution !== ''
                     ? \App\Services\MathFormulaProcessor::processFormulas($formatDetailForReadability($rawSolution))
                     : '(无详解)';
+                if ($isAnswerType) {
+                    $renderSolution = $renderAnswerSolutionWithStepBoxes($renderSolution);
+                }
             @endphp
             <div class="answer-detail-item">
                 <div class="entry-line">

+ 27 - 0
resources/views/pdf/partials/answer-detail-styles.blade.php

@@ -153,6 +153,16 @@
     margin-right: 2px;
 }
 
+.answer-detail-item .detail-grade-box {
+    display: inline-block;
+    width: 11px;
+    height: 11px;
+    border: 1px solid #333;
+    box-sizing: border-box;
+    background: #fff;
+    vertical-align: middle;
+}
+
 .answer-detail-item .entry-line {
     display: block;
     font-weight: 400;
@@ -251,3 +261,20 @@
 .answer-detail-item .solution-only br {
     line-height: 1.4;
 }
+
+.answer-detail-item .solution-step {
+    display: inline-block;
+    margin: 2px 0;
+}
+
+.answer-detail-item .step-box {
+    display: inline-flex;
+    align-items: center;
+    margin-right: 6px;
+    vertical-align: middle;
+}
+
+.answer-detail-item .step-label {
+    display: inline;
+    vertical-align: middle;
+}