Quellcode durchsuchen

fix: 继续修复pdf题目丢失问题

过卫栋 vor 5 Tagen
Ursprung
Commit
c99eace18a
1 geänderte Dateien mit 38 neuen und 12 gelöschten Zeilen
  1. 38 12
      app/Http/Controllers/ExamPdfController.php

+ 38 - 12
app/Http/Controllers/ExamPdfController.php

@@ -190,11 +190,14 @@ class ExamPdfController extends Controller
     {
         $options = [];
 
+        // 【修复】先移除SVG内容,避免误匹配SVG注释中的 BD:DC、A:B 等内容
+        $contentWithoutSvg = preg_replace('/<svg[^>]*>.*?<\/svg>/is', '[SVG_PLACEHOLDER]', $content);
+
         // 1. 尝试匹配多种格式的选项:A. / A、/ A: / A.(中文句点)/ A.(无空格)
-        // 支持格式:A.-1 / A. -1 / A、-1 / A:-1
-        $pattern = '/([A-D])[\.、:.:]\s*(.+?)(?=\s*[A-D][\.、:.:]|$)/su';
+        // 【修复】选项标记必须在行首或空白后,避免误匹配 SVG 注释中的 BD:DC 等内容
+        $pattern = '/(?:^|\s)([A-D])[\.、:.:]\s*(.+?)(?=(?:^|\s)[A-D][\.、:.:]|$)/su';
 
-        if (preg_match_all($pattern, $content, $matches, PREG_SET_ORDER)) {
+        if (preg_match_all($pattern, $contentWithoutSvg, $matches, PREG_SET_ORDER)) {
             foreach ($matches as $match) {
                 $optionText = trim($match[2]);
                 // 移除末尾的换行和空白
@@ -210,9 +213,10 @@ class ExamPdfController extends Controller
 
         // 2. 如果上面没提取到,尝试按换行分割
         if (empty($options)) {
-            $lines = preg_split('/[\r\n]+/', $content);
+            $lines = preg_split('/[\r\n]+/', $contentWithoutSvg);
             foreach ($lines as $line) {
                 $line = trim($line);
+                // 【修复】行首匹配选项标记
                 if (preg_match('/^([A-D])[\.、:.:]\s*(.+)$/u', $line, $match)) {
                     $optionText = trim($match[2]);
                     if (!empty($optionText)) {
@@ -236,8 +240,11 @@ class ExamPdfController extends Controller
      */
     private function separateStemAndOptions(string $content): array
     {
-        // 检测是否有选项(支持多种格式)
-        $hasOptions = preg_match('/[A-D][\.、:.:]/u', $content);
+        // 【修复】先移除SVG内容,避免误匹配SVG注释中的 BD:DC、A:B 等内容
+        $contentWithoutSvg = preg_replace('/<svg[^>]*>.*?<\/svg>/is', '[SVG_PLACEHOLDER]', $content);
+
+        // 【修复】检测是否有选项时,要求选项标记在行首或空白后
+        $hasOptions = preg_match('/(?:^|\s)[A-D][\.、:.:]/u', $contentWithoutSvg);
 
         if (!$hasOptions) {
             return [$content, []];
@@ -248,17 +255,36 @@ class ExamPdfController extends Controller
 
         // 如果提取到选项,分离题干
         if (!empty($options)) {
-            // 找到第一个选项的位置,之前的内容是题干
-            if (preg_match('/^(.+?)(?=[A-D][\.、:.:])/su', $content, $match)) {
+            // 【修复】找到第一个选项的位置,要求选项标记在行首或空白后
+            if (preg_match('/^(.+?)(?=(?:^|\s)[A-D][\.、:.:])/su', $contentWithoutSvg, $match)) {
                 $stem = trim($match[1]);
+                // 如果题干中有SVG占位符,从原始内容中提取对应部分
+                if (strpos($stem, '[SVG_PLACEHOLDER]') !== false) {
+                    // 找到原始内容中对应位置的题干
+                    $stemLength = mb_strlen(str_replace('[SVG_PLACEHOLDER]', '', $stem));
+                    // 使用更精确的方法:找到第一个有效选项标记的位置
+                    foreach (['A.', 'A、', 'A:', 'A.', 'A:'] as $marker) {
+                        // 只匹配在空白后的选项标记
+                        if (preg_match('/\s' . preg_quote($marker, '/') . '/', $content, $m, PREG_OFFSET_CAPTURE)) {
+                            $pos = $m[0][1];
+                            if ($pos > 0) {
+                                $stem = trim(mb_substr($content, 0, $pos));
+                                break;
+                            }
+                        }
+                    }
+                }
             } else {
                 // 如果正则失败,尝试按位置分割
                 $stem = $content;
                 foreach (['A.', 'A、', 'A:', 'A.', 'A:'] as $marker) {
-                    $pos = mb_strpos($content, $marker);
-                    if ($pos !== false && $pos > 0) {
-                        $stem = trim(mb_substr($content, 0, $pos));
-                        break;
+                    // 【修复】只匹配在空白后的选项标记
+                    if (preg_match('/\s' . preg_quote($marker, '/') . '/', $content, $m, PREG_OFFSET_CAPTURE)) {
+                        $pos = $m[0][1];
+                        if ($pos > 0) {
+                            $stem = trim(mb_substr($content, 0, $pos));
+                            break;
+                        }
                     }
                 }
             }