Bläddra i källkod

feat(pdf): apply type-specific terminal punctuation policy for choice and fill stems

yemeishu 3 veckor sedan
förälder
incheckning
754a6ac154

+ 28 - 4
app/Support/BlankPlaceholderRenderer.php

@@ -114,6 +114,33 @@ class BlankPlaceholderRenderer
         return self::DEFAULT_BLANK_SPAN;
     }
 
+    /**
+     * 统一句尾标点(仅处理句尾,不影响中间小数/表达式)
+     *
+     * $mode:
+     * - remove: 去掉句尾句号
+     * - dot:    句尾统一为英文实心点 "."
+     * - cn:     句尾统一为中文句号 "。"
+     */
+    public static function normalizeTerminalPunctuation(string $content, string $mode): string
+    {
+        $replacement = match ($mode) {
+            'remove' => '',
+            'dot' => '.',
+            'cn' => '。',
+            default => null,
+        };
+        if ($replacement === null) {
+            return $content;
+        }
+
+        // 先处理数学片段尾点(如 "$.$" / "$。$" / "$.$")。
+        $content = preg_replace('/\$\s*[\..。]\s*\$(?=\s*(?:(?:<\/[^>]+>|<[^>]+\/>)\s*)*$)/u', $replacement, $content);
+
+        // 再处理普通句尾点。
+        return preg_replace('/[\..。](?=\s*(?:(?:<\/[^>]+>|<[^>]+\/>)\s*)*$)/u', $replacement, $content);
+    }
+
     private static function normalizeChineseTerminalPeriod(string $content): string
     {
         // 仅在存在中文语境时,把句末英文句号统一为中文句号。
@@ -121,9 +148,6 @@ class BlankPlaceholderRenderer
             return $content;
         }
 
-        // 先处理数学片段尾点(如 "$.$" / "$.$")。
-        $content = preg_replace('/\$\s*[\..]\s*\$(?=\s*(?:<\/[^>]+>\s*)*$)/u', '。', $content);
-
-        return preg_replace('/[\..](?=\s*(?:<\/[^>]+>\s*)*$)/u', '。', $content);
+        return self::normalizeTerminalPunctuation($content, 'cn');
     }
 }

+ 2 - 1
app/Support/GradingStyleQuestionStem.php

@@ -122,7 +122,8 @@ class GradingStyleQuestionStem
      */
     private static function applyBlankPlaceholdersLikeGrading(string $stemLine): string
     {
-        [$renderedStem] = BlankPlaceholderRenderer::replaceToBlankSpan($stemLine, null, true);
+        [$renderedStem] = BlankPlaceholderRenderer::replaceToBlankSpan($stemLine, null, true, false);
+        $renderedStem = BlankPlaceholderRenderer::normalizeTerminalPunctuation($renderedStem, 'remove');
 
         return $renderedStem;
     }

+ 6 - 2
resources/views/components/exam/paper-body.blade.php

@@ -150,7 +150,9 @@
                 }
             }
             // 选择题只做占位符归一,不再兜底追加下划线,避免出现“( )+下划线”重复。
-            [$renderedStem] = \App\Support\BlankPlaceholderRenderer::replaceToBlankSpan($stemLine, null, true);
+            [$renderedStem] = \App\Support\BlankPlaceholderRenderer::replaceToBlankSpan($stemLine, null, true, false);
+            // 选择题:句尾不保留句号。
+            $renderedStem = \App\Support\BlankPlaceholderRenderer::normalizeTerminalPunctuation($renderedStem, 'remove');
             $renderedStem = $mathProcessed ? $renderedStem : \App\Services\MathFormulaProcessor::processFormulas($renderedStem);
         @endphp
         <div class="question">
@@ -284,11 +286,13 @@
             // 【修复】使用question_number字段作为显示序号,确保全局序号一致性
             $questionNumber = $q->question_number ?? (count($choiceQuestions) + $index + 1);
             $blankSpan = \App\Support\BlankPlaceholderRenderer::defaultBlankSpan();
-            [$renderedContent, $hasPlaceholders] = \App\Support\BlankPlaceholderRenderer::replaceToBlankSpan((string) $q->content, $blankSpan, false);
+            [$renderedContent, $hasPlaceholders] = \App\Support\BlankPlaceholderRenderer::replaceToBlankSpan((string) $q->content, $blankSpan, false, false);
             // 填空题保留兜底:题干无任何占位时,在末尾补一个标准空位。
             if (!$hasPlaceholders) {
                 $renderedContent .= ' ' . $blankSpan;
             }
+            // 填空题:句尾统一为实心小圆点(英文句点)。
+            $renderedContent = \App\Support\BlankPlaceholderRenderer::normalizeTerminalPunctuation($renderedContent, 'dot');
             $renderedContent = $mathProcessed ? $renderedContent : \App\Services\MathFormulaProcessor::processFormulas($renderedContent);
         @endphp
         <div class="question">