vue3 打印实现自定义分页、页眉、页脚

<template>
  <div class="main_container publicBg">
    <vxe-button @click="handlePrint">直接打印</vxe-button>
    <div ref="printContentRef">
      <!-- 多个实现分页 -->
      <div class="print-page">
        <div class="print-header">
          <div class="company-name">测试测试测试测试测试测试测试测试</div>
          <div class="report-title">检验报告</div>
        </div>

        <div class="report-date">报告日期: {{ getNowDate() }}</div>

        <table class="report-table">
          <template v-for="v in 8" :key="v">
            <tr>
              <td>测试测试测试测试</td>
              <td>测试测试测试测试</td>
              <td>测试测试测试测试</td>
              <td>测试测试测试测试</td>
              <td>测试测试测试测试</td>
              <td>测试测试测试测试</td>
              <td>测试测试测试测试</td>
              <td rowspan="8" v-if="v === 1">注:报表中的检测结果下面注有检测依据的是本结果执行的检测标准,其他结果均执行检测依据栏中的检测标准.</td>
            </tr>
          </template>
        </table>

        <table class="report-table noTopBor" style="margin-top:0;">
          <colgroup>
            <col style="width:12.5%">
            <col style="width:12.5%">
            <col style="width:12.5%">
            <col style="width:12.5%">
            <col style="width:12.5%">
            <col style="width:12.5%">
            <col style="width:12.5%">
            <col style="width:12.5%">
          </colgroup>
          <tr>
            <td style="font-weight:bold;">检测项目</td>
            <td style="font-weight:bold;" colspan="6">检测结果</td>
            <td style="font-weight:bold;">检测依据</td>
          </tr>
        </table>

        <table class="report-table noTopBor" style="margin-top:0;">
          <template v-for="v in 11" :key="v">
            <tr>
              <td>测试测试测试测试</td>
              <td>测试测试测试测试</td>
              <td>测试测试测试测试</td>
              <td>测试测试测试测试</td>
              <td>测试测试测试测试</td>
              <td>测试测试测试测试</td>
              <td>测试测试测试测试</td>
              <td>测试测试测试测试</td>
            </tr>
          </template>
        </table>

        <!-- 调整页脚位置 -->
        <div class="print-footer">
          <div>编制</div>
          <div>校验</div>
          <div>批准</div>
          <div>第1页共1页</div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { getNowDate } from '@/utils/index.js'

const printContentRef = ref(null)

// 自定义打印函数
const handlePrint = () => {
  const content = printContentRef.value
  if (!content) return

  // 创建一个隐藏的iframe用于打印
  const printIframe = document.createElement('iframe')
  printIframe.style.position = 'absolute'
  printIframe.style.width = '0'
  printIframe.style.height = '0'
  printIframe.style.left = '-9999px'
  document.body.appendChild(printIframe)

  // 构建打印页面的HTML
  const printHTML = `
    <!DOCTYPE html>
    <html>
    <head>
      <title>检验报告</title>
      <style>
        @page {
          size: A4 landscape; /* 横向 */
          margin: 10mm;
        }
        body {
          margin: 0;
          font-family: Arial, sans-serif;
        }
        .print-page {
          width: 100%;
          height: calc(210mm - 20mm); /* 减去上下边距 */
          box-sizing: border-box;
          position: relative;
          page-break-after: always;
          padding-bottom: 60px; /* 为页脚留出空间 */
        }
        .print-header {
          width: 100%;
          text-align: center;
        }
        .company-name {
          font-size: 20px;
          font-weight: bold;
        }
        .report-title {
          font-size: 30px;
          letter-spacing: 30px;
          // padding-top: 20px;
          font-weight: bold;
        }
        .report-date {
          position: absolute;
          left: 0;
          top: 80px;
          font-size: 14px;
        }
        .report-table {
          width: 100%;
          margin-top: 30px;
          border-collapse: collapse;
          table-layout: fixed;
        }
        .report-table td {
          padding: 5px 2px;
          text-align: center;
          border: 0.5px solid #9d9a9a;
          font-size: 12px;
          color: #202123;
        }
        .report-table col {
          width: 12.5%;
        }
        .noTopBor {
          margin-top: 0 !important;
        }
        .noTopBor td {
          border-top: none;
        }
        .print-footer {
          width: 100%;
          display: flex;
          justify-content: space-between;
          position: absolute;
          bottom: 0;
          left: 0;
          padding: 10px 0;
          border-top: 1px solid #eee;
          background-color: #fff;
        }
        .print-footer div {
          width: 25%;
          text-align: center;
        }
      </style>
    </head>
    <body>
      ${content.innerHTML}
    </body>
    </html>
  `

  // 写入iframe并直接打印
  const frameDoc = printIframe.contentWindow.document
  frameDoc.open()
  frameDoc.write(printHTML)
  frameDoc.close()

  // 等待iframe加载完成后打印
  printIframe.onload = () => {
    try {
      printIframe.contentWindow.focus()
      printIframe.contentWindow.print()
      setTimeout(() => {
        document.body.removeChild(printIframe)
      }, 1000)
    } catch (error) {
      console.error('打印失败:', error)
      document.body.removeChild(printIframe)
    }
  }
}
</script>

<style scoped>
.print-page {
  width: 100%;
  height: calc(210mm - 20mm);
  box-sizing: border-box;
  position: relative;
  page-break-after: always;
  padding-bottom: 60px;
}

.print-header {
  width: 100%;
  text-align: center;
}

.company-name {
  font-size: 20px;
  font-weight: bold;
}

.report-title {
  font-size: 30px;
  letter-spacing: 30px;
  /* padding-top: 20px; */
  font-weight: bold;
}

.report-date {
  position: absolute;
  left: 0;
  top: 80px;
  font-size: 14px;
}

.report-table {
  width: 100%;
  margin-top: 30px;
  border-collapse: collapse;
  table-layout: fixed;
}

.report-table td {
  width: 12.5%;
  padding: 5px 2px;
  text-align: center;
  border: 0.5px solid #9d9a9a;
  font-size: 12px;
  color: #202123;
}

.print-footer {
  width: 100%;
  display: flex;
  justify-content: space-between;
  position: absolute;
  bottom: 0;
  left: 0;
  padding: 10px 0;
  border-top: 1px solid #eee;
  background-color: #fff;
}

.print-footer div {
  width: 25%;
  text-align: center;
}

.noTopBor td {
  border-top: none;
}

</style>

posted @ 2025-03-27 13:38  小万子呀  阅读(511)  评论(0)    收藏  举报