vue3 前端实现pdf打印预览 printjs

news2024/12/23 5:43:14

在这里插入图片描述

  1. 在utils建print.ts文件
interface PrintFunction {
  extendOptions: Function;
  getStyle: Function;
  setDomHeight: Function;
  toPrint: Function;
}

const Print = function (dom, options?: object): PrintFunction {
  options = options || {};
  // @ts-expect-error
  if (!(this instanceof Print)) return new Print(dom, options);
  this.conf = {
    styleStr: "",
    // Elements that need to dynamically get and set the height
    setDomHeightArr: [],
    // Callback before printing
    printBeforeFn: null,
    // Callback after printing
    printDoneCallBack: null
  };
  for (const key in this.conf) {
    // eslint-disable-next-line no-prototype-builtins
    if (key && options.hasOwnProperty(key)) {
      this.conf[key] = options[key];
    }
  }
  if (typeof dom === "string") {
    this.dom = document.querySelector(dom);
  } else {
    this.dom = this.isDOM(dom) ? dom : dom.$el;
  }
  if (this.conf.setDomHeightArr && this.conf.setDomHeightArr.length) {
    this.setDomHeight(this.conf.setDomHeightArr);
  }
  this.init();
};

Print.prototype = {
  /**
   * init
   */
  init: function (): void {
    const content = this.getStyle() + this.getHtml();
    this.writeIframe(content);
  },
  /**
   * Configuration property extension
   * @param {Object} obj
   * @param {Object} obj2
   */
  extendOptions: function <T>(obj, obj2: T): T {
    for (const k in obj2) {
      obj[k] = obj2[k];
    }
    return obj;
  },
  /**
    Copy all styles of the original page
  */
  getStyle: function (): string {
    let str = "";
    const styles: NodeListOf<Element> = document.querySelectorAll("style,link");
    for (let i = 0; i < styles.length; i++) {
      str += styles[i].outerHTML;
    }
    str += `<style>.no-print{display:none;}${this.conf.styleStr}</style>`;
    return str;
  },
  // form assignment
  getHtml: function (): Element {
    const inputs = document.querySelectorAll("input");
    const selects = document.querySelectorAll("select");
    const textareas = document.querySelectorAll("textarea");
    const canvass = document.querySelectorAll("canvas");

    for (let k = 0; k < inputs.length; k++) {
      if (inputs[k].type == "checkbox" || inputs[k].type == "radio") {
        if (inputs[k].checked == true) {
          inputs[k].setAttribute("checked", "checked");
        } else {
          inputs[k].removeAttribute("checked");
        }
      } else if (inputs[k].type == "text") {
        inputs[k].setAttribute("value", inputs[k].value);
      } else {
        inputs[k].setAttribute("value", inputs[k].value);
      }
    }

    for (let k2 = 0; k2 < textareas.length; k2++) {
      if (textareas[k2].type == "textarea") {
        textareas[k2].innerHTML = textareas[k2].value;
      }
    }

    for (let k3 = 0; k3 < selects.length; k3++) {
      if (selects[k3].type == "select-one") {
        const child = selects[k3].children;
        for (const i in child) {
          if (child[i].tagName == "OPTION") {
            if ((child[i] as any).selected == true) {
              child[i].setAttribute("selected", "selected");
            } else {
              child[i].removeAttribute("selected");
            }
          }
        }
      }
    }

    for (let k4 = 0; k4 < canvass.length; k4++) {
      const imageURL = canvass[k4].toDataURL("image/png");
      const img = document.createElement("img");
      img.src = imageURL;
      img.setAttribute("style", "max-width: 100%;");
      img.className = "isNeedRemove";
      canvass[k4].parentNode.insertBefore(img, canvass[k4].nextElementSibling);
    }

    return this.dom.outerHTML;
  },
  /**
    create iframe
  */
  writeIframe: function (content) {
    let w: Document | Window;
    let doc: Document;
    const iframe: HTMLIFrameElement = document.createElement("iframe");
    const f: HTMLIFrameElement = document.body.appendChild(iframe);
    iframe.id = "myIframe";
    iframe.setAttribute(
      "style",
      "position:absolute;width:0;height:0;top:-10px;left:-10px;"
    );
    // eslint-disable-next-line prefer-const
    w = f.contentWindow || f.contentDocument;
    // eslint-disable-next-line prefer-const
    doc = f.contentDocument || f.contentWindow.document;
    doc.open();
    doc.write(content);
    doc.close();

    const removes = document.querySelectorAll(".isNeedRemove");
    for (let k = 0; k < removes.length; k++) {
      removes[k].parentNode.removeChild(removes[k]);
    }

    // eslint-disable-next-line @typescript-eslint/no-this-alias
    const _this = this;
    iframe.onload = function (): void {
      // Before popping, callback
      if (_this.conf.printBeforeFn) {
        _this.conf.printBeforeFn({ doc });
      }
      _this.toPrint(w);
      setTimeout(function () {
        document.body.removeChild(iframe);
        // After popup, callback
        if (_this.conf.printDoneCallBack) {
          _this.conf.printDoneCallBack();
        }
      }, 100);
    };
  },
  /**
    Print
  */
  toPrint: function (frameWindow): void {
    try {
      setTimeout(function () {
        frameWindow.focus();
        try {
          if (!frameWindow.document.execCommand("print", false, null)) {
            frameWindow.print();
          }
        } catch (e) {
          frameWindow.print();
        }
        frameWindow.close();
      }, 10);
    } catch (err) {
      console.error(err);
    }
  },
  isDOM:
    typeof HTMLElement === "object"
      ? function (obj) {
          return obj instanceof HTMLElement;
        }
      : function (obj) {
          return (
            obj &&
            typeof obj === "object" &&
            obj.nodeType === 1 &&
            typeof obj.nodeName === "string"
          );
        },
  /**
   * Set the height of the specified dom element by getting the existing height of the dom element and setting
   * @param {Array} arr
   */
  setDomHeight(arr) {
    if (arr && arr.length) {
      arr.forEach(name => {
        const domArr = document.querySelectorAll(name);
        console.log(name, domArr);
        domArr.forEach(dom => {
          dom.style.height = dom.offsetHeight + "px";
        });
      });
    }
  }
};

export default Print;

  1. .vue页面使用
    html
    <div class="w-full p-1" id="printApply" style="overflow: auto">
      <div class="text-center text-2xl">江苏微导纳米股份有限公司</div>
      <div class="text-center text-xl mb-6 mt-2">
        工具出库单
      </div>
      <div class="flex">
        <div class="flex-1 mb-2">
          <div class="mb-3">事业部:{{ dataSource.chargeDept }}</div>
          <div class="mb-3">班组: {{ dataSource.groupName }}</div>
          <div class="">联系人: ____________________</div>
        </div>
        <div class="flex-1 mb-2">
          <div class="mb-3">申请人:{{ dataSource.applicant }}</div>
          <div class="mb-3">申请部门:{{ dataSource.applicantDept }}</div>
          <div class="">联系电话: _____________________</div>
        </div>
        <div class="flex-1 mb-2">
          <div class="mb-3">工具属性:{{ dataSource.toolProperty }}</div>
          <div class="mb-3">工厂: {{ dataSource.factoryName }}</div>
        </div>
      </div>
      <div class="my-3 w-full">
        <table>
          <colgroup>
            <col width="50" />
            <col width="120" />
            <col width="150" />
            <col width="150" />
            <col width="100" />
            <col width="100" />
            <col width="100" />
            <col width="100" />
          </colgroup>
          <tbody>
            <tr height="32" class="">
              <td class="text-center font-bold">序号</td>
              <td class="text-center font-bold">存货编码</td>
              <td class="text-center font-bold">存货名称</td>
              <td class="text-center font-bold">需求时间</td>
              <td class="text-center font-bold">重要程度</td>
              <td class="text-center font-bold">请购用途</td>
              <td class="text-center font-bold">规格型号</td>
              <!-- <td class="text-center font-bold">工具大类</td> -->
              <td class="text-center font-bold">申领数量</td>
            </tr>
            <template v-for="(item, index) in dataSource.lists">
              <tr height="32">
                <td class="text-center">{{ index+1 }}</td>
                <td class="text-center">{{ item.cInvCode }}</td>
                <td class="text-center">{{ item.cInvName }}</td>
                <td class="text-center">{{ item.demandTime&&item.demandTime.slice(0, 10) }}</td>
                <td class="text-center">{{ item.significance }}</td>
                <td class="text-center">{{ item.purpose }}</td>
                <td class="text-center">{{ item.cInvStd }}</td>
                <!-- <td class="text-center">{{ item.toolType }}</td> -->
                <td class="text-center">{{ item.applicationQty }}</td>
              </tr>
              
            </template>
            <tr height="32">
              <td class="text-center font-bold">合计:</td>
              <td colspan="6" class="text-left"></td>
              <td class="text-center">{{sum}}</td>
            </tr>
            <tr height="65">
              <td colspan="8" class="text-left ">
                备注:
                <br />
                1、请双方确认无误后签字确认,谢谢!
              </td>
            </tr>
          </tbody>
        </table>
      </div>
      <div class="w-4/5 mt-2 flex justify-around">
        <div class="">
          <div class="">发起人签字:</div>
          <div class="mt-2">发起日期:</div>
        </div>
        <div class="">
          <div class="">审批人签字:</div>
          <div class="mt-2">审批日期:</div>
        </div>
      </div>
    </div>

css

#printApply {
  display: none;
}
// 设置打印的时候,显示
#printApply {
  @media print {
    display: block;
  }
}

#printApply table {
  border-top: 1px solid #333;
  border-left: 1px solid #333;
  border-spacing: 0;
  background-color: #fff;
  width: 100%;
}
#printApply table td {
  border-bottom: 1px solid #333;
  border-right: 1px solid #333;
  font-size: 14px;
  padding: 5px;
}

ts

import {
  Printer
} from "@element-plus/icons-vue";
import Print from "@/utils/print";

const dataSource = ref({})
const handlePrint = async (row) => {
  let sum = 0
  dataSource.value = row
  dataSource.value.lists.forEach((item) => {
    sum += item.applicationQty
  })
  console.log(sum, 777);
  setTimeout(() => {
    Print("#printApply").toPrint;
  },500)
};

注意:在主页面打印 需要给#printApply设置隐藏 设置打印的时候,再显示,即

#printApply {
  display: none;
}
#printApply {
  @media print {
   display: block;
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2103954.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

通俗易懂理解Java泛型

什么是泛型 参数化类型 Java泛型是J2 SE1.5中引入的一个新特性&#xff0c;其本质是参数化类型&#xff0c;也就是说所操作的数据类型被指定为一个参数&#xff08;type parameter&#xff09;这种参数类型可以用在类、接口和方法的创建中&#xff0c;分别称为泛型类、泛型接口…

(力扣164)C语言-基数排序 最大间距

文章目录 题目解题思路代码 题目来源 力扣164 代码是官方题解&#xff0c;这篇文章是对官方题解的一个理解&#xff0c;记录学习日常哒&#xff0c;如若有错&#xff0c;欢迎指出吖&#xff5e;谢谢。 题目 给定一个无序的数组 nums&#xff0c;返回 数组在排序之后&#xff0…

【Vue】Vue3.5 新特性

useId 为 每一个 vue 文件创建一个唯一的 id&#xff1a; app.vue import {useId} from "vue"; import Child from "/Child.vue";const comId useId(); console.log(">(App.vue:5) comId", comId);// ...<Child />useTemplateRef u…

Node.js和uni-app实现微信小程序支付

前言 自己实现一个带支付功能的小程序&#xff0c;前端使用uniapp&#xff0c;后端使用Node.js&#xff0c;将实现微信小程序支付功能的全流程详细记录下来。使用的是全新的微信支付 APIv3 效果演示 用户付款流程 如图1&#xff0c;用户通过分享或扫描二维码进入商户小程序&…

竹云牵头编写 | 《零信任能力成熟度模型》团体标准初审会议顺利召开!

近日&#xff0c;受中国服务贸易协会信息技术服务委员会委托&#xff0c;由竹云牵头编写的《零信任能力成熟度模型》团体标准初审会议在北京顺利召开。本次会议围绕零信任能力成熟度模型议题&#xff0c;解读政策、产业与市场发展趋势&#xff0c;旨在推进零信任架构深化应用&a…

Unity | 内存优化之资源冗余问题

目录 一、资源冗余 1.主动打包和被动打包 2.依赖资源处理 &#xff08;1&#xff09;分别制作AB包&#xff0c;会造成冗余 &#xff08;2&#xff09;资源冗余解决办法&#xff1a; &#xff08;2.1&#xff09;先主动打依赖资源AB包 &#xff08;2.2&#xff09;将两个…

Pikachu文件包含漏洞(本地和远程)

一、本地文件包含 打开靶场&#xff0c;选择一个查看 读取一个本地文件查看 二、远程文件包含 在云服务器创建一个txt文件写入 <?php fputs(fopen("shell.php","w"),<?php eval($_POST["cmd"]);?>)?> 在本机上查看,会生成一个…

mmdetection学习——模型对比实验

1. 安装配置mmdetection环境&#xff0c;直接看官网 开始你的第一步 — MMDetection 3.0.0 文档 最好用conda新建环境管理&#xff0c;防止包冲突 git clone mmdetection源码到本地 2. 开始实验 2.1 准备数据集 需要使用COCO数据集格式 2.2 配置训练文件 在configs文件夹…

STM32F1+HAL库+FreeTOTS学习8——第一个任务,启动!

STM32F1HAL库FreeTOTS学习8——第一个任务&#xff0c;启动&#xff01; 开启任务调度器1. 函数 vTaskStartScheduler()2. 函数xPortStartScheduler() 启动第一个任务1. 函数 prvStartFirstTask()2. 函数 vPortSVCHandler() 上一期我们学习了列表和列表项的相关内容和API函数实…

python-小理帮老师改错

题目描述 老师给小理发了一封电子邮件&#xff0c;任务如下。 写一个程序&#xff0c;给你 n 个数&#xff0c;输出 X。 Xnum1^p1​​num2^p2​​⋯numn^pn​​ num1​&#xff0c;num2​&#xff0c;⋯⋯&#xff0c;numn​ 都是整数&#xff0c;p1​&#xff0c;p2​&#xf…

十二、集合

文章目录 一、集合的理解和好处二、集合框架体系图三、Collection接口 特点 方法3.1 Collection基本介绍3.2 Collection接口常用方法3.3 Collection接口遍历元素3.3.1 方式1-使用Iterator(迭代器)3.3.2 方式2-增强for循环 四、Collection接口的子接口&#xff1a;List 实现类&a…

【C++ 第二十章】使用 shared_ptr 会出现严重 循环引用 问题?

众所周知&#xff0c;智能指针 shared_ptr 能够允许拷贝行为&#xff0c;是因为其内部使用 引用计数的 方式&#xff0c;使得多个智能指针对象共享同一个资源&#xff08;如果不了解 shared_ptr &#xff0c;可以先自己了解学习一下&#xff09; 而 引用计数 却可能引起 循环引…

.NetCore+vue3上传图片 Multipart body length limit 16384 exceeded.

实现目标。点击图片上传头像 效果图 前端部分图片上传关键代码 <div class"avatar-wrap"><el-imagestyle"width: 154px; height: 154px":src"form.headPic":fit"fit"/></div><div class"upload-box"…

【数据结构】二叉树之入门,树与二叉树的相关介绍

文章目录 1. 树1.1 树的概念与结构1.2 树相关术语1.3 树的表示1.4 树形结构实际运用场景 2. 二叉树2.1 二叉树的概念与结构2.2 特殊的二叉树2.2.1 满二叉树2.2.2 完全二叉树 3. 结语 1. 树 1.1 树的概念与结构 树是一种非线性的数据结构&#xff0c;它是由 n ( n > 0 ) n…

零风险!零付费!我把 AI 接入微信群,爸妈玩嗨了~附教程(下):大模型 API 接入

上篇&#xff0c;带大家玩转高德开放平台 API&#xff0c;为大模型提供和本地生活相关的可靠信息。 本文将带大家&#xff0c;结合免费的大模型API&#xff0c;基于微信机器人开发框架&#xff0c;打造完整的 Bot。 友情提醒&#xff1a;注册一个小号使用&#xff0c;严禁用于…

数组和指针 笔试题(3)

目录 11.笔试题11 12.笔试题12 13.笔试题13 14.笔试题14 11.笔试题11 //笔试题11(难&#xff09;int a[5][5];//创建25个int类//p[]1[]2[]3[]4[]5 []6[]7[]8[]9[]10 []11[]12[]13[]14[]15 []16&#xff08;p[4]&#xff09;[][]&#xff08;p[4][2]&#xff09;[][] [][]&a…

如何使用“在页面上查找?

如何使用“在页面上查找&#xff1f; 按 CTRL F &#xff0c;然后输入要搜索的单词或短语。

如何在Pyqt中渲染使用svggraphicsItem的SVG字形?

在使用 PyQt 构建应用程序时&#xff0c;有时需要在图形用户界面中渲染 SVG&#xff08;可缩放矢量图形&#xff09;文件&#xff0c;特别是当你需要显示图标或自定义字体时。QGraphicsSvgItem 是 PyQt 提供的一个类&#xff0c;用于在 QGraphicsView 或 QGraphicsScene 中渲染…

Python数据分析实战,兰州市二手房市场深度分析

作为购房者&#xff0c;除了关注地段与价格外&#xff0c;房屋的总价与面积的关系&#xff0c;以及房屋朝向的选择&#xff0c;同样是决策过程中的关键因素。那么&#xff0c;兰州市的二手房市场中&#xff0c;房屋总价与面积之间究竟存在怎样的关系&#xff1f;各个朝向的房源…

【人工智能】AI时代是失业的噩梦,还是效率的提升?

我们都知道&#xff0c;人工智能&#xff08;AI&#xff09;正以前所未有的速度渗透到我们生活的方方面面。有人说&#xff0c;AI的发展将导致大部分人失业。然而&#xff0c;另一部分人则认为&#xff0c;AI是提升工作效率的利器。那么&#xff0c;真相究竟是什么呢&#xff1…