Browse Source

feat: 把pdf里的空白页去掉

过卫栋 4 days ago
parent
commit
2d6eb180d0
1 changed files with 86 additions and 21 deletions
  1. 86 21
      app/Services/ExamPdfExportService.php

+ 86 - 21
app/Services/ExamPdfExportService.php

@@ -1457,48 +1457,113 @@ class ExamPdfExportService
     }
 
     /**
-     * 【新增】构建统一的HTML文档(保留原始结构
-     * 保留第一个HTML的完整head和样式,只在body之间插入分页符
+     * 【优化重构】构建统一的HTML文档(容器结构 + 消除空白页
+     * 使用容器结构替代空的 page-break div,避免中间出现空白页
      */
     private function buildUnifiedHtmlWithOriginalStructure(string $examHead, string $examBody, string $gradingBody): string
     {
-        // 保留原始head内容,添加分页符样式
+        // 清洗内容:移除可能存在的分页符,避免双重分页
+        $examBody = $this->stripPageBreakElements($examBody);
+        $gradingBody = $this->stripPageBreakElements($gradingBody);
+
+        // 构建优化的HTML结构,使用容器控制分页
         $headContent = $examHead . '
     <style>
-        /* 分页符样式 - 插入到原始样式之后 */
-        .page-break {
-            page-break-before: always;
-            page-break-after: always;
+        /* 容器基础样式 - 保持现有页面边距 */
+        .exam-part,
+        .grading-part {
+            width: 100%;
+            margin: 0;
+            padding: 0;
+        }
+
+        /* 核心分页控制:只在 grading-part 上设置 */
+        .grading-part {
+            /* CSS3 新标准 */
             break-before: page;
-            break-after: page;
+            /* 兼容旧版 WebKit */
+            page-break-before: always;
+            /* 确保顶部没有额外边距 */
+            margin-top: 0;
+            padding-top: 0;
         }
 
-        /* 确保分页符在打印时生效 */
-        @media print {
-            .page-break {
-                page-break-before: always;
-            }
+        /* 防止试卷部分末尾分页 */
+        .exam-part {
+            /* 确保试卷内容连续 */
+            break-after: auto;
+            page-break-after: auto;
+        }
+
+        /* 避免在关键元素中间分页 */
+        .exam-part h1, .exam-part h2,
+        .grading-part h1, .grading-part h2 {
+            break-after: avoid;
+            page-break-after: avoid;
+        }
+
+        .exam-part table, .exam-part .question-item,
+        .grading-part table, .grading-part .answer-item {
+            break-inside: avoid;
+            page-break-inside: avoid;
+        }
+
+        /* 防止孤儿行 */
+        .exam-part p, .exam-part li,
+        .grading-part p, .grading-part li {
+            orphans: 2;
+            widows: 2;
+        }
+
+        /* 数学公式优化 */
+        .katex {
+            break-inside: avoid;
+            page-break-inside: avoid;
         }
     </style>';
 
         return '<!DOCTYPE html>
 <html lang="zh-CN">
 <head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>试卷与判卷合并</title>
 ' . $headContent . '
 </head>
 <body>
-    <!-- 第一部分:试卷(不含答案) -->
-    ' . $examBody . '
-
-    <!-- 分页符:第二部分从这里开始 -->
-    <div class="page-break"></div>
-
-    <!-- 第二部分:判卷(含答案与解析) -->
-    ' . $gradingBody . '
+    <!-- 试卷部分 - 连续显示 -->
+    <div class="exam-part">
+' . $examBody . '
+    </div>
+
+    <!-- 判卷部分 - 强制新页面开始(不使用空的 page-break div) -->
+    <div class="grading-part">
+' . $gradingBody . '
+    </div>
 </body>
 </html>';
     }
 
+    /**
+     * 【新增】清洗HTML内容中的分页符元素
+     * 移除可能存在的 page-break 元素,避免双重分页导致空白页
+     */
+    private function stripPageBreakElements(string $content): string
+    {
+        // 只移除空的 page-break div 元素(通常是 <div class="page-break"></div>)
+        // 使用更精确的正则,只匹配空内容或纯空白内容的 div
+        $patterns = [
+            '/<div[^>]*class="[^"]*page-break[^"]*"[^>]*>\s*<\/div>/si',
+            '/<div[^>]*style="[^"]*page-break[^"]*"[^>]*>\s*<\/div>/si',
+        ];
+
+        foreach ($patterns as $pattern) {
+            $content = preg_replace($pattern, '', $content);
+        }
+
+        return $content;
+    }
+
     /**
      * 【新增】获取PDF通用样式
      */