Selaa lähdekoodia

fix: pdf丢题问题

过卫栋 5 päivää sitten
vanhempi
commit
95ca7afd30
2 muutettua tiedostoa jossa 47 lisäystä ja 15 poistoa
  1. 33 15
      app/Services/ExamPdfExportService.php
  2. 14 0
      config/pdf.php

+ 33 - 15
app/Services/ExamPdfExportService.php

@@ -1022,14 +1022,19 @@ class ExamPdfExportService
         $utf8Html = $this->ensureUtf8Html($html);
         $written = file_put_contents($tmpHtml, $utf8Html);
 
-        Log::warning('ExamPdfExportService: [调试] HTML文件已创建', [
+        Log::debug('ExamPdfExportService: HTML文件已创建', [
             'path' => $tmpHtml,
             'html_length' => strlen($utf8Html),
             'written_bytes' => $written,
-            'file_exists' => file_exists($tmpHtml),
-            'file_size' => file_exists($tmpHtml) ? filesize($tmpHtml) : 0,
         ]);
 
+        // 【调试】如果启用了HTML保存调试,复制HTML到storage用于分析
+        if (config('pdf.debug_save_html', false)) {
+            $debugPath = storage_path('app/debug_pdf_' . date('YmdHis') . '.html');
+            @copy($tmpHtml, $debugPath);
+            Log::warning('ExamPdfExportService: [DEBUG] HTML副本已保存', ['path' => $debugPath]);
+        }
+
         // 仅使用Chrome渲染
         $chromePdf = $this->renderWithChrome($tmpHtml);
         @unlink($tmpHtml);
@@ -1870,6 +1875,7 @@ class ExamPdfExportService
         foreach ($paperQuestions as $pq) {
             $questionsData[] = [
                 'id' => $pq->question_bank_id,
+                'question_number' => $pq->question_number, // 传递原始题号,确保渲染时序号正确
                 'kp_code' => $pq->knowledge_point,
                 'question_type' => $pq->question_type ?? 'answer',
                 'stem' => $pq->question_text ?? '题目内容缺失',
@@ -1916,6 +1922,17 @@ class ExamPdfExportService
             $classified[$type][] = (object) $q;
         }
 
+        // 【调试】记录题目分类情况
+        Log::debug('buildQuestionsData: 题目分类结果', [
+            'total_questions' => count($questionsData),
+            'choice_count' => count($classified['choice']),
+            'fill_count' => count($classified['fill']),
+            'answer_count' => count($classified['answer']),
+            'choice_numbers' => array_map(fn($q) => $q->question_number ?? 'N/A', $classified['choice']),
+            'fill_numbers' => array_map(fn($q) => $q->question_number ?? 'N/A', $classified['fill']),
+            'answer_numbers' => array_map(fn($q) => $q->question_number ?? 'N/A', $classified['answer']),
+        ]);
+
         return $classified;
     }
 
@@ -1996,14 +2013,23 @@ class ExamPdfExportService
 
     /**
      * 判断题目类型
+     * 【修复】优先使用 question_type 字段,避免选择题因含有()被误判为填空题
      */
     private function determineQuestionType(array $question): string
     {
+        // 1. 【优先】根据已有类型字段判断(最可靠的来源)
+        if (!empty($question['question_type'])) {
+            $type = strtolower(trim($question['question_type']));
+            if (in_array($type, ['choice', '选择题'])) return 'choice';
+            if (in_array($type, ['fill', '填空题'])) return 'fill';
+            if (in_array($type, ['answer', '解答题'])) return 'answer';
+        }
+
+        // 2. 如果没有明确类型,则根据题干内容推断
         $stem = $question['stem'] ?? $question['content'] ?? '';
-        $tags = $question['tags'] ?? '';
 
-        // 根据题干内容判断选择题
         if (is_string($stem)) {
+            // 检查是否有选项模式 A. B. C. D.
             $hasOptionA = preg_match('/\bA\s*[\.\、\:]/', $stem) || preg_match('/\(A\)/', $stem) || preg_match('/^A[\.\s]/', $stem);
             $hasOptionB = preg_match('/\bB\s*[\.\、\:]/', $stem) || preg_match('/\(B\)/', $stem) || preg_match('/^B[\.\s]/', $stem);
             $hasOptionC = preg_match('/\bC\s*[\.\、\:]/', $stem) || preg_match('/\(C\)/', $stem) || preg_match('/^C[\.\s]/', $stem);
@@ -2014,21 +2040,13 @@ class ExamPdfExportService
                 return 'choice';
             }
 
-            // 检查是否有填空标记
+            // 检查是否有填空标记(但要排除选择题的括号)
             if (preg_match('/(\s*)|\(\s*\)/', $stem)) {
                 return 'fill';
             }
         }
 
-        // 根据已有类型字段判断
-        if (!empty($question['question_type'])) {
-            $type = strtolower(trim($question['question_type']));
-            if (in_array($type, ['choice', '选择题'])) return 'choice';
-            if (in_array($type, ['fill', '填空题'])) return 'fill';
-            if (in_array($type, ['answer', '解答题'])) return 'answer';
-        }
-
-        // 默认返回解答题
+        // 3. 默认返回解答题
         return 'answer';
     }
 

+ 14 - 0
config/pdf.php

@@ -0,0 +1,14 @@
+<?php
+
+return [
+    /*
+    |--------------------------------------------------------------------------
+    | PDF调试设置
+    |--------------------------------------------------------------------------
+    |
+    | 启用此选项会在生成PDF时保存HTML副本到storage/app目录
+    | 用于调试PDF渲染问题
+    |
+    */
+    'debug_save_html' => env('PDF_DEBUG_SAVE_HTML', false),
+];