vue中实现打印

news2024/9/20 18:37:39

一、VUE 集成 LODOP插件打印

VUE 集成LODOP插件打印

Lodop、C-Lodop使用说明及样例

C-Lodop插件官网:功能演示 - Lodop和C-Lodop官网主站

参考文章:VUE 集成 LODOP插件打印_廷贺的博客-CSDN博客

二、winodw.print() 打印 

print() 方法用于打印当前窗口的内容。调用 print() 方法会产生一个打印预览弹框,让用户可以设置打印请求。最简单的打印就是直接调用window.print(),当然用 document.querySelector('print') 也可以达到同样的效果。默认打印页面中body里的所有内容。

1.简单使用

参考文章连接1:vue、js 打印 window.print()方法_gu_eu的博客-CSDN博客_js afterprint

参考文章连接2:window.print()局部打印三种方式 - 硅谷工具人 - 博客园

参考文章连接3:vue,打印案例 window.print() 的完美实现_kaiking_g的博客-CSDN博客_// 打印类属性、方法定义 /* eslint-disable */

2.本人创建组件模板使用案例

2.1 创建 print.js 文件

// 打印类属性、方法定义
/* eslint-disable */
const Print = function (dom, options) {
    options = options || {}
    if (!(this instanceof Print)) return new Print(dom, options);
    this.conf = {
        isAllStyle:false, // 是否加载当前页面所有样式
        styleStr:'',    // 设置样式字符串
        setDomHeightArr: [], // 需要动态获取并设置高度的 元素
        echartDomArr: [], // echart dom
        printBeforeFn: null, // 打印前回调
        printDoneCallBack: null // 打印后回调
    }
    for (const key in this.conf) {
        if (key && options.hasOwnProperty(key)) {
            this.conf[key] = options[key]
        }
    }
    // debugger
    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: function () {
        var content = this.getStyle() + this.getHtml();
        this.writeIframe(content);
    },
    /**
     * 配置属性扩展
     * @param {Object} obj
     * @param {Object} obj2
     */
    extendOptions: function (obj, obj2) {
        for (var k in obj2) {
            obj[k] = obj2[k];
        }
        return obj;
    },
    /**
     复制原网页所有的样式
     */
    getStyle: function () {
        var str = ""
        if(this.conf.isAllStyle){
            let styles = document.querySelectorAll('style,link');
            for (var i = 0; i < styles.length; i++) {
                str += styles[i].outerHTML;
            }
        }
        str += `<style>.no-print{display:none;}${this.conf.styleStr}</style>`;
        return str;
    },
    // 表单赋值
    getHtml: function () {
        var inputs = document.querySelectorAll('input');
        var textareas = document.querySelectorAll('textarea');
        var selects = document.querySelectorAll('select');
        // debugger
        for (var 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 (var k2 = 0; k2 < textareas.length; k2++) {
            if (textareas[k2].type == 'textarea') {
                textareas[k2].innerHTML = textareas[k2].value
            }
        }

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

        return this.dom.outerHTML;
    },
    /**
     创建iframe
     */
    writeIframe: function (content) {
        // 方法二:
        var w, doc, iframe = document.createElement('iframe'),
            f = document.body.appendChild(iframe);
        iframe.id = "myIframe";
        iframe.setAttribute('style', 'position:absolute;width:0;height:0;top:-10px;left:-10px;');
        w = f.contentWindow || f.contentDocument;
        doc = f.contentDocument || f.contentWindow.document;
        doc.open();
        doc.write(content);
        doc.close();
        var _this = this
        iframe.onload = function () {
            // 弹出前,回调
            if (_this.conf.printBeforeFn) {
                _this.conf.printBeforeFn({ doc })
            }

            _this.drawEchartImg(doc).then(() => {
                _this.toPrint(w);
                setTimeout(function () {
                    document.body.removeChild(iframe)
                    // 弹出后,回调
                    if (_this.conf.printDoneCallBack) {
                        _this.conf.printDoneCallBack()
                    }
                }, 100)
            })
        }
    },
    /**
     * 项目用到echarts,需要获取图片,来打印
     * @param {Object} doc iframe window
     */
    drawEchartImg(doc) {
        return new Promise((resolve, reject) => {
            if (this.conf.echartDomArr && this.conf.echartDomArr.length > 0) {
                this.conf.echartDomArr.forEach(e => {
                    const dom = doc.querySelector('#' + e.$el.id)
                    const img = new Image()
                    const w = dom.offsetWidth + 'px'
                    const H = dom.offsetHeight + 'px'

                    img.style.width = w
                    img.style.height = H
                    img.src = e.imgSrc
                    dom.innerHTML = ''
                    dom.appendChild(img)
                })
            }
            resolve()
        })
    },
    /**
     打印
     */
    toPrint: function (frameWindow) {
        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.log('err', 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';
        },
    /**
     * 设置指定dom元素高度,通过获取该dom元素现有高度,并设置
     * @param {Array} arr
     */
    setDomHeight(arr) {
        if (arr && arr.length) {
            arr.forEach(name => {
                const domArr = document.querySelectorAll(name);
                // debugger
                domArr.forEach(dom => {
                    dom.style.height = dom.offsetHeight + 'px';
                })
            })
        }
    }
};
const MyPlugin = {}
MyPlugin.install = function (Vue, options) {
    // 4. 添加实例方法
    Vue.prototype.$print = Print
};
export default MyPlugin

2.2 在 main.js 文件中引入,全局使用

import print from '@/utils/print'
Vue.use(print)

2.3 创建请假组件模板 LeavePrintView.vue

<template>
  <div id="print-html" ref="PrintView">
    <table style="height: 358px; width: 95%; margin-left: auto; margin-right: auto;border-collapse: collapse;" border="1px" cellpadding="0" cellspacing="0" bordercolor ="#000000"  bordercolordark ="#000000">
      <caption style="padding: 13px 0; font-size: 22px; font-weight: inherit;">请假条</caption>
      <tbody>
      <tr style=" text-align: center;">
        <th width="10%" style="text-align: center; vertical-align: middle;word-wrap:break-word;">申请人</th>
        <td width="15%" style="text-align: center; vertical-align: middle;">{{infoForm&&infoForm.createUserName?infoForm.createUserName:''}}</td>
        <th width="10%" style="text-align: center; vertical-align: middle;">所属部门</th>
        <td width="15%" style="text-align: center; vertical-align: middle;">{{infoForm&&infoForm.userDeptName?infoForm.userDeptName:''}}</td>
        <th width="10%" style="text-align: center; vertical-align: middle;">请假时长</th>
        <td width="15%" style="text-align: center; vertical-align: middle;">{{infoForm&&infoForm.timelen?infoForm.timelen:''}}&nbsp;小时</td>
        <th width="10%" style="text-align: center; vertical-align: middle;">请假类型</th>
        <td width="15%" style="text-align: center; vertical-align: middle;">{{infoForm&&infoForm.leaveTypeLabel?infoForm.leaveTypeLabel:''}}</td>
      </tr>
      <tr style="">
        <th style="text-align: center; vertical-align: middle;">请假事由</th>
        <td style="text-align: center; vertical-align: middle;word-wrap:break-word;" colspan="7">{{infoForm&&infoForm.content?infoForm.content:''}}</td>
      </tr>
      <tr >
        <th style="text-align: center; vertical-align: middle;">申请时间</th>
        <td style="text-align: center; vertical-align: middle;">{{infoForm&&infoForm.createTime?momentObj(infoForm.createTime).format('YYYY-MM-DD'):''}}</td>
        <th style="text-align: center; vertical-align: middle;">开始时间</th>
        <td style="text-align: center; vertical-align: middle;" colspan="2">{{infoForm&&infoForm.startTime?infoForm.startTime:''}}</td>
        <th style="text-align: center; vertical-align: middle;">结束时间</th>
        <td style="text-align: center; vertical-align: middle;" colspan="2">{{infoForm&&infoForm.endTime?infoForm.endTime:''}}</td>
      </tr>
      <tr >
        <th style="text-align: center; vertical-align: middle;">审批</th>
        <td style="text-align: center; vertical-align: middle;word-wrap:break-word;" colspan="3">
          <span  v-for="item in this.checkUserIds" :key="item.id">
            {{item.name}}
          </span>
        </td>
        <th style="text-align: center; vertical-align: middle;">抄送</th>
        <td style="text-align: center; vertical-align: middle;word-wrap:break-word;" colspan="3">
          <span  v-for="item in this.copyUserIds" :key="item.id">
            {{item.name}}
          </span>
        </td>
      </tr>
      <tr >
        <th style="text-align: center; vertical-align: middle;">备注</th>
        <td style="text-align: center; vertical-align: middle;word-wrap:break-word;" colspan="7"></td>
      </tr>
      </tbody>
    </table>
  </div>
</template>
<script>
import moment from "moment"; // 日期格式化工具
import {mapState} from "vuex";

export default {
  name: 'PrintView',
  props: {
    //父组件传递 姓名字段
    name: {
      type: String,
      default: ''
    },
    //父组件传递 部门字段
    deptName: {
      type: String,
      default: ''
    },
    //父组件传递 时长字段
    duration: {
      type: String,
      default: ''
    },
    //父组件传递对象参数
    infoForm: {
      type: Object,
      default () {
        return {}
      }
    },
  },
  data() {
    return {
      momentObj: null,
      checkUserIds:null,
      copyUserIds:null
    }
  },
  created() {
    this.momentObj=moment
  },
  watch: {},
  computed: {
    ...mapState(['allUserlist']), // 获取用户数据
  },
    /**以下所有方法采用同步调用,防止打印时数据丢失**/
  methods: {
    /** 数据进行封装,页面进行回显 **/
    async getCheckUser(checkUserId,copyUserId){
      this.checkUserIds=await this.filterCheckedusers(checkUserId);
      this.copyUserIds= await this.filterCheckedusers(copyUserId);
    },
    /* 审批人 刷选 暴力方法,没做去重直接是清空在复制*/
    async filterCheckedusers(checkedIds) {
      checkedIds = checkedIds ? checkedIds.split(',') : []
      const checkedusers = []
      if(Array.isArray(checkedIds)) {
        checkedIds.forEach(item => {
          checkedusers.push(this.allUserlist.filter(i => (Boolean(item) && i.id === item))[0] )
        })
      } else if(checkedIds) {
        checkedusers.push(this.allUserlist.filter(i => i.id === checkedIds)[0])
      }
      return checkedusers.filter(item => item !== undefined)
    },
  },
}
</script>

2.4 使用组件模板

<div style="position: absolute;right: 26%; top: 3%;z-index: 100;"  >
                    <el-button type="info" size="small" @click="printHandle">
                      <i class="el-icon-printer" style="font-size:60%">打印</i>
                    </el-button>
                    <!-- 打印 -->
                    <print-view ref="PrintView" id="PrintView" style="display: none" :infoForm="infoForm"/>
                  </div>



<script>
// 引用组件
import PrintView from "@/components/print/LeavePrintView";

export default {
        name: 'approval-detail',
        data() {
            return {
              infoForm: {
                    checkUserId:'',
                    copyUserId:''},
            }
        },
        components: {PrintView },
        methods: {
            async printHandle(){
                // 调用子组件方法-进行数据封装
                await this.$refs.PrintView.getCheckUser(this.infoForm.checkUserId,this.infoForm.copyUserId)
                // 调用工具类中的打印方法,进行打印
                this.$print(this.$refs.PrintView.$el, {'styleStr': '#PrintView{display:block !important;}'})
          },
        
        },

}


</script>

 

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

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

相关文章

vs2015软件打包及常见问题解决方法

一、如程序文件是64位&#xff0c;而项目设置32位&#xff0c;打包项目编译时遇到如下问题 解决办法&#xff1a;选择打包程序项目的属性窗口设置TargetPlatform属性为对应的值&#xff0c;本项目的文件是64位的所以设置打包生成的程序为64位的&#xff0c;如下&#xff1a; …

【可解释性机器学习】排列重要性(Permutation Importance)及案例分析详解

Permutaion Importance&#xff1a;排列重要性引言工作原理代码示例排列重要性结果解读模型检验特征选择补充分析Partial Dependency PlotSharpley ValueLIME总结参考资料当训练得到一个模型之后&#xff0c;除了对模型的预测感兴趣之外&#xff0c;我们往往还想知道模型中哪些…

DDOS渗透与攻防(三)之socktress攻击

系列文章 DDOS渗透与攻防(一)之拒绝服务攻击概念介绍 DDOS渗透与攻防(二)之SYN-Flood攻击 socktress攻击 攻击协议原理介绍说明-socktress 2008年有Jack C.Louis发现&#xff0c;针对TCP服务的拒绝服务攻击&#xff1a; 消耗被攻击目标系统资源&#xff0c;与攻击目标建立…

xml配置JedisUtil

一.背景 习惯了Bean注解方式往sping容器中注入对象&#xff0c;现使用xml方式注入Bean对象总结下&#xff0c;顺便用帮女朋友解决的Jedis问题当做案例来总结。 二.配置JedisPool 从源码来看&#xff0c;JedisPool的构造函数有N多种 我们使用如下的构造函数来实例化JedisPool…

docker部署Nginx和Tomcat

文章目录 前言 目录 文章目录 前言 一、docker部署Nginx 二、docker部署Tomcat 总结 一、docker部署Nginx 下载镜像&#xff1a;docker pull nginx 后台运行镜像 -d 后台运行 --name"nginx01" 给容器命名 -p 宿主机端口:容器内部端口 docker run -d --name"…

2.SpringAop的jdkcglib动态代理xml注解实现切面

1.Spring 的 AOP 简介 1.1 什么是 AOP AOP 为 Aspect Oriented Programming 的缩写&#xff0c;意思为面向切面编程&#xff0c;是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。 AOP 是 OOP 的延续&#xff0c;是软件开发中的一个热点&#xff0c;也是…

Linux常用命令——rsync命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) rsync 远程数据同步工具 补充说明 rsync命令是一个远程数据同步工具&#xff0c;可通过LAN/WAN快速同步多台主机间的文件。rsync使用所谓的“rsync算法”来使本地和远程两个主机之间的文件达到同步&#xff0c…

ARMv8 AArch64异常处理机制概览

1 处理机制概述 相对于ARMv7中的异常向量表&#xff08;Exception Vector Table&#xff09;&#xff0c;ARMv8异常处理机制更为复杂&#xff0c;涉及处理器的异常等级&#xff08;Exception Levels, ELn&#xff09;、运行状态&#xff08;Execution States&#xff09;和安全…

汉字乱码状态下的编码转换将导致的问题

实验工具notepad编辑器实验过程步骤1&#xff1a;打开notepad&#xff0c;新建一个文本文件&#xff0c;在其中输入一段汉字文本&#xff0c;查看当前编码格式&#xff0c;如下&#xff1a;分析&#xff1a;由上图可见&#xff0c;从右下角可知当前文件是以UTF-8解码显示的&…

微信小程序——页面事件,.启用下拉刷新监听页面的下拉刷新事件,上拉触底事件,停止下拉刷新的效果

一.页面事件1.什么是下拉刷新下拉刷新是移动端的专有名词&#xff0c;指的是通过手指在屏幕上的下拉滑动操作&#xff0c;从而重新加载页面数据的行为。2.启用下拉刷新启用下拉刷新有两种方式&#xff1a;a.全局开启下拉刷新在 app.json 的window 节点中&#xff0c;将 enableP…

python 蓝桥杯 矩阵拼接

问题描述已知 3 个矩形的大小依次是 a_{1} \times b_{1}, a_{2} \times b_{2}a1b1,a2b2 和 a_{3} \times b_{3}a3b3 。用这 3 个矩形能拼 出的所有多边形中, 边数最少可以是多少?例如用 3 \times 232 的矩形&#xff08;用 A 表示)、 4 \times 141 的矩形 (用 BB 表示) 和 2 \…

法律常识(一)婚姻法全文

目录 参考 第一章 总 则 第二章 结 婚 第三章 家庭关系 第四章 离 婚 第五章 救助措施与法律责任 第六章 附 则 参考 中华人民共和国婚姻法http://www.gqb.gov.cn/node2/node3/node5/node9/node101/userobject7ai1290.html 《图解中华人民共和国婚姻法》 &#xff…

[架构之路-92]:《软件架构设计:程序员向架构师转型必备》-2-解析软件架构的概念

前言&#xff1a;什么是软件架构&#xff1f;不同的人&#xff0c;有不同的答案。因为架构无处不再&#xff0c;架构又有不同层面。很多人都给架构定义&#xff0c;不同的人&#xff0c;对架构有不同的理解&#xff0c;很难统一。本文是按照作者个人的理解&#xff0c;来展现一…

React是不是MVVM架构吗?

首先说结论&#xff1a;不是 一、MVVM Model-View-ViewModel&#xff1a;一句话概括MVVM&#xff0c;操作数据&#xff0c;就是操作视图&#xff0c;就是操作DOM。开发者只需要完成包含申明绑定的视图模板&#xff0c;编写ViewModel中业务数据变更逻辑&#xff0c;View层则完…

Lua 协同程序(coroutine)

Lua 协同程序(coroutine) 参考文章&#xff1a; 菜鸟教程 https://zhuanlan.zhihu.com/p/480357405 https://zhuanlan.zhihu.com/p/76249973 Lua 协同程序(coroutine)与线程比较类似&#xff1a;拥有独立的堆栈&#xff0c;独立的局部变量&#xff0c;独立的指令指针&#xff0…

贪心算法(例题详细解说)

日升时奋斗&#xff0c;日落时自省 目录 1、选择排序 2、分割平衡字符串 3、买卖股票的最佳时机 II 4、跳跃游戏 5、钱币找零 6、多机调度问题 7、活动选择 8、无重复区间 贪心思想&#xff1a;顾名思义 贪 是该算法的一大特点&#xff0c;如何贪&#xff1f;&#x…

2023-01-28 clickhouse-聚合函数的源码再梳理

笔者在源码笔记1之中分析过ClickHouse的聚合函数的实现&#xff0c;但是对于各个接口函数的实际如何共同工作的源码&#xff0c;回头看并没有那么明晰&#xff0c;主要原因是没有结合Aggregator的类来一起分析聚合函数的是如果工作起来的。所以决定重新再完成一篇聚合函数的源码…

梦熊杯-十二月月赛-白银组题解-A.自由

A. Problem A.自由&#xff08;freedom.cpp&#xff09; 内存限制&#xff1a;256 MiB 时间限制&#xff1a;1000 ms 标准输入输出 题目类型&#xff1a;传统 评测方式&#xff1a;文本比较 题目描述: 「蒙德」是「自由」的国度。 巴巴托斯认为&#xff0c;如果一个数的…

ch1_2 计算机的基本组成

计算机的基本组成 1. 冯 诺依曼计算机的特点 计算机由五大部件组成指令和数据 以同等地位 存于存储器&#xff0c; 可按地址寻访。指令和数据用二进制 表示指令由操作码 和 地址码 组成&#xff1b;存储程序&#xff1b;以运算器 为中心&#xff1b; 2. 硬件框图 存储器&am…

【Java集合】HashSet源码分析

目录 一、Set简介 二、HashSet简介 2.1 简介 2.2 HashSet继承关系 三、源码分析 3.1 成员属性 3.2 构造方法 3.3 添加元素 3.3.1 add()方法 3.3.2 addAll()方法 3.4 删除元素 3.4.1 remove()方法 3.4.2 removeAll()方法 3.5 查询元素 3.5.1 contains()方法 3.5.2 containsAll方…