打印和导出pdf

安装

cnpm install vue3-print-nb
cnpm install html2canvas
cnpm install jspdf

代码

  <div class="print-preview">
    <div class="flex f-end exportBtn">
      <a-button v-print="print">打印</a-button>
      <a-button class="ml-10" @click="exportToPDF('printFrom')">导出PDF</a-button>
    </div>
    <div class="print-container">
      <div id="printFrom">
        <h3 class="title">员工入职登记表</h3>
        <div class="flex f-between">
          <a-form-item label="公司">{{ formModel.rosterFromDetailResp?.companyStr }}</a-form-item>
          <a-form-item label="部门">{{ formModel.rosterFromDetailResp?.departmentStr }}</a-form-item>
          <a-form-item label="岗位">{{ formModel.rosterFromDetailResp?.positionStr }}</a-form-item>
          <a-form-item label="入职日期">{{ formModel.rosterFromDetailResp?.joinWorkDate }}</a-form-item>
        </div>
 </div>
 </div>
 </div>
import { ref, reactive, toRefs, onMounted } from 'vue'
import print from 'vue3-print-nb'
import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
const print = ref({
  id: 'printFrom',//这里的id就是上面我们的打印区域id,实现指哪打哪
  // popTitle: '', // 打印配置页上方的标题
  extraHead: '', // 最上方的头部文字,附加在head标签上的额外标签,使用逗号分割
  preview: false, // 是否启动预览模式,默认是false
  previewTitle: '', // 打印预览的标题
  previewPrintBtnLabel: '', // 打印预览的标题下方的按钮文本,点击可进入打印
  zIndex: 20002, // 预览窗口的z-index,默认是20002,最好比默认值更高
})
const exportToPDF = async (elementId) => {
  const element = document.getElementById(elementId);

  // 使用 html2canvas 将 DOM 转换为 canvas 图像
  const canvas = await html2Canvas(element, {
    scale: 2,
    logging: true, // 开启日志以便调试
    ignoreElements: (el) => el.style.display === 'none' // 忽略隐藏元素
  });
  const imgData = canvas.toDataURL('image/jpeg', 0.7); // 使用 JPEG 格式

  // 获取 canvas 的宽度和高度(单位:像素)
  const imgWidth = canvas.width;
  const imgHeight = canvas.height;

  // 定义转换比例因子(从像素到毫米)
  const ratio = 25.4 / 96; // 1 英寸 = 25.4 mm, 默认屏幕分辨率为 96 dpi

  // 计算页面尺寸(单位:毫米)
  const pdfWidth = imgWidth * ratio;
  const pdfHeight = imgHeight * ratio;

  // 创建一个新的 jsPDF 实例,动态设置页面大小
  const orientation = pdfWidth > pdfHeight ? 'l' : 'p'; // 根据宽高比选择方向
  const pdf = new JsPDF({
    orientation,
    unit: 'mm',
    format: [pdfWidth, pdfHeight]
  });

  // 添加白色背景,避免阴影
  pdf.setFillColor(255, 255, 255);
  pdf.rect(0, 0, pdf.internal.pageSize.getWidth(), pdf.internal.pageSize.getHeight(), 'F');

  // 添加图像到 PDF 文档
  // 添加图像到 PDF 文档时,确保宽度和高度与 PDF 页面完全匹配
  pdf.addImage(imgData, 'PNG', 0, 0, pdf.internal.pageSize.getWidth(), pdf.internal.pageSize.getHeight());

  // 保存 PDF 文件
  pdf.save('员工入职登记表.pdf');
}

<style scoped lang="less">
.print-preview {
  padding: 10px 0;
  position: relative;

  .exportBtn {
    position: sticky;
    top: 10px;
    margin-right: 40px;
  }
}

.print-container {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
}


#printFrom {
  text-align: center;
  padding: 20px;
  background-color: #fff;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
  page-break-inside: avoid;

  th,
  td {
    font-size: 14px;
    font-weight: normal;
    min-width: 100px;
    max-width: 156px;
    white-space: wrap;
    text-align: center;
    padding: 0 4px;
    height: 27px;
  }
}

/* 定义单选按钮组的基本样式 */
.radio-group {
  display: flex;
  align-items: center;
}

/* 隐藏原始的单选按钮 */
input[type="radio"] {
  display: none;
}

/* 定义标签的基础样式 */
label {
  position: relative;
  padding-left: 25px;
  margin-right: 20px;
  font-size: 14px;
  cursor: pointer;
  transition: all 0.3s ease;
}

/* 创建空心圆圈作为未选中的状态 */
label::before {
  content: "";
  display: inline-block;
  width: 16px;
  height: 16px;
  margin-right: 8px;
  position: absolute;
  left: 0;
  top: 0;
  background-color: white;
  border: 1px solid #ccc;
  border-radius: 50%;
  transition: all 0.3s ease;
}

/* 创建实心圆圈作为选中的状态 */
input[type="radio"]:checked+label::after {
  content: "";
  display: block;
  width: 10px;
  height: 10px;
  position: absolute;
  left: 3px;
  top: 3px;
  background-color: #3498db;
  border-radius: 50%;
  transition: all 0.3s ease;
}

@media print {
  .title {
    text-align: center;
  }

  #printFrom {
    box-shadow: none;

    th,
    td {
      min-width: 100px;
      max-width: 156px;
      white-space: wrap;
    }

  }

  input[type="radio"]:checked+label::after {
    content: "";
    display: block;
    width: 10px;
    height: 10px;
    position: absolute;
    left: 3px;
    top: 3px;
    background-color: #3498db;
    border-radius: 50%;
    transition: all 0.3s ease;
    -webkit-print-color-adjust: exact !important; //强调背景颜色
    color-adjust: exact !important; //强调背景颜色
  }



}

.ant-form-item {
  margin-bottom: 0px !important;
}
</style>

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容