vue 打印、自定义打印、页面打印、隐藏页眉页脚

news2024/11/18 21:37:48

        花了一天时间搞了个打印功能,现则将整体实现过程进行整理分享。先来看看效果图:

1、页面展示为:

2、重组页面打印格式为:这里重组页面的原因是客户要求为一行两列打印 !内容过于多的行则独占一行显示完整。

 整体实现:

在你的项目的components目录下创建如下目录及文件:

 将以下代码粘贴到这个print.js文件中:

// 打印类属性、方法定义
/* eslint-disable */
const Print = function (dom, options) {
    if (!(this instanceof Print)) return new Print(dom, options);

    this.options = this.extend({
        'noPrint': '.no-print'
    }, options);

    if ((typeof dom) === "string") {
        this.dom = document.querySelector(dom);
    } else {
        this.isDOM(dom)
        this.dom = this.isDOM(dom) ? dom : dom.$el;
    }

    this.init();
};
Print.prototype = {
    init: function () {
        var content = this.getStyle() + this.getHtml();
        this.writeIframe(content);
    },
    extend: function (obj, obj2) {
        for (var k in obj2) {
            obj[k] = obj2[k];
        }
        return obj;
    },

    getStyle: function () {
        var str = "",
            styles = document.querySelectorAll('style,link');
        for (var i = 0; i < styles.length; i++) {
            str += styles[i].outerHTML;
        }
        str += "<style>" + (this.options.noPrint ? this.options.noPrint : '.no-print') + "{display:none;}</style>";
        // str += "<style>html,body,div{height: auto!important;font-size:14px}</style>";
        return str;
    },

    getHtml: function () {
        var inputs = document.querySelectorAll('input');
        var textareas = document.querySelectorAll('textarea');
        var selects = document.querySelectorAll('select');

        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;
    },

    writeIframe: function (content) {
        var w, doc, iframe = document.createElement('iframe'),
            f = document.body.appendChild(iframe);
        iframe.id = "myIframe";
        //iframe.style = "position:absolute;width:0;height:0;top:-10px;left:-10px;";
        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 () {
            _this.toPrint(w);
            setTimeout(function () {
                document.body.removeChild(iframe)
            }, 100)
        }
    },

    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';
        }
};
const MyPlugin = {}
MyPlugin.install = function (Vue, options) {
    // 4. 添加实例方法
    Vue.prototype.$print = Print
}
export default MyPlugin

 在views目录下创建重组页面,即要实现的打印页面。目录及页面文件如下:

粘贴以下代码进入index.vue组件中:注意阅读并分析这里面的实现,预留功能为一行N列实现,栅格布局计算!

<template>
    <el-dialog :title="title" :visible.sync="visible" width="148mm" :before-close="handleClose" center append-to-body>
        <div class="w-100 h-100">
            <div class="w-100" ref="print">
                <div class="header-view w-100">
                    <div class="title-view w-100 single-line">{{ printData.title }}</div>
                </div>
                <div class="w-100 body-view">
                    <div class="print-section" v-for="(item, tindex) in printData.data" :key="item">
                        <div class="section-view">{{ item.title }}</div>
                        <el-row class="row-view bd-right" v-for="(a, aindex) in item.child" :key="a"
                            :class="{ 'bd-top': aindex == 0 }">
                            <el-col :span="rowSpan" v-for="(p, index) in a.child" class="col-view flex-row"
                                :class="{ 'bd-left': index == 0 }">
                                <div class="main-lb cell-view"
                                    :class="[index > 0 ? 'bd-left' : '', `lb_${tindex}_${aindex}_${index}`]">{{ p.label
                                        | textFilter
                                    }}
                                </div>
                                <div class="value-lb cell-view"
                                    :class="[p.singLine ? 'value-pre' : '', `vlb_${tindex}_${aindex}_${index}`]">{{
                                        p.value
                                    }}</div>
                            </el-col>
                        </el-row>
                        <el-row class="row-view bd-right">
                            <el-col :span="12" class="col-view flex-row bd-left">
                                <div class="main-lb cell-view">备注</div>
                                <div class="value-lb cell-view" style="height: 50px;"></div>
                            </el-col>
                        </el-row>
                    </div>
                </div>
            </div>
        </div>
        <div slot="footer" class="w-100 flex-row no-print" style="height: 44px;">
            <el-button class="el-icon-printer" type="primary" @click="handlePrint">打印</el-button>
        </div>
    </el-dialog>
</template>
<script>

export default
    {
        name: 'pagePrinter',
        components: {},
        data() {
            return {
                visible: false,
                inMobile: false,
                printData: {
                    'title': '',
                    'titleClass': null,
                    'subTitle': '',
                    'subTitleClass': null,
                    'data': []
                },
                rowSpan: 12
            }
        },
        props:
        {
            title: {
                type: String,
                default: () => null
            },
            //是否随机项目
            printMap: {
                type: Object,
                default: () => {
                    return {
                        'title': '',
                        'titleClass': null,
                        'subTitle': '',
                        'subTitleClass': null,
                        'data': []
                    }
                }
            },
        },
        watch: {
            printMap: {
                deep: true,
                handler(val) {
                    if (val) {
                        this.updatePrintData()
                    }
                }
            },
        },
        created() {

        },
        filters: {
            textFilter(val) {
                let v = val.replace(/:/g, '');
                return v
            }
        },
        methods: {
            handleClose() {
                this.visible = false;
                this.$emit('update:visible', false)
                this.$emit('close', {})
            },
            updatePrintData() {
                this.inMobile = this.isMobile()
                let m = {
                    'title': this.printMap.title,
                    'titleClass': this.printMap.titleClass,
                    'subTitle': this.printMap.subTitle,
                    'subTitleClass': this.printMap.subTitleClass,
                    'data': this.printMap.data
                }
                let dataList = []
                let col = 24 / this.rowSpan
                this.printMap.data.forEach(e => {
                    let ae = {
                        title: e.title,
                        child: []
                    }
                    let list = []
                    e.child?.forEach((c, cdex) => {
                        c.span = this.rowSpan
                        list.push(c)
                        if (list.length % col == 0 || cdex == e.child.length - 1 || c.singLine) {
                            if (c.singLine) {
                                list.forEach(n => {
                                    n.singLine = true
                                    let cx = {
                                        child: [n]
                                    }
                                    ae.child.push(cx)
                                })
                            }
                            else {
                                let cx = {
                                    child: list
                                }
                                ae.child.push(cx)
                            }
                            list = []
                        }
                    });
                    dataList.push(ae)
                });
                m.data = dataList
                this.printData = m
                this.visible = true
                this.$nextTick(() => {
                    dataList.forEach((a, aindex) => {
                        a.child.forEach((b, bindex) => {
                            let maxHeight = 0
                            b.child.forEach((c, cindex) => {
                                let csName = `.lb_${aindex}_${bindex}_${cindex}`
                                let atarget = document.querySelector(csName)
                                let aht = atarget.offsetHeight

                                let bsName = `.vlb_${aindex}_${bindex}_${cindex}`
                                let btarget = document.querySelector(bsName)
                                let bht = btarget.offsetHeight
                                maxHeight = Math.max(maxHeight, Math.max(aht, bht))

                                atarget.style.height = maxHeight + 'px';
                                btarget.style.height = maxHeight + 'px';
                            });

                            b.child.forEach((c, cindex) => {
                                let csName = `.lb_${aindex}_${bindex}_${cindex}`
                                let atarget = document.querySelector(csName)

                                let bsName = `.vlb_${aindex}_${bindex}_${cindex}`
                                let btarget = document.querySelector(bsName)

                                atarget.style.height = maxHeight + 'px';
                                btarget.style.height = maxHeight + 'px';
                            });
                        });
                    })
                })
            },
            handlePrint() {
                this.$print(this.$refs.print);
            },
        }
    }
</script>

<style lang="scss" scoped>
.header-view {
    width: 100%;
    padding: 10px 0px;

    //border-bottom: 1px solid #ccc;
}

.section-view {
    font-size: 12px;
    text-align: left;
    color: #333;
    margin-left: 10px;
    padding-bottom: 5px;
}

.title-view {
    font-size: 18px;
    text-align: center;
    color: black;
}

.cnt-view {
    height: calc(100% - 44px);
}

.body-view {
    height: calc(100% - 64px);
}

.bd-left {
    border-left: 1px solid #ccc;
}

.bd-right {
    border-right: 1px solid #ccc;
}

.bd-top {
    border-top: 1px solid #ccc;
}

.row-view {
    border-bottom: 1px solid #ccc;
}

.flex-row {
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
}

.cell-view {
    //min-height: 38px;
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
    align-items: center;
}

.main-lb {
    font-size: 10px;
    color: #444;
    width: 40%;
    font-weight: 500;
    padding-left: 5px;
    //border-right: 1px solid #ccc;
}

.value-lb {
    font-size: 11px;
    color: black;
    width: 60%;
    border-left: 1px solid #ccc;
    white-space: pre-line;
    word-break: break-all;
    padding: 4px 10px;
}

.value-pre {
    white-space: pre;
}

::v-deep {
    .el-dialog {
        width: 100%;
        //height: 100%;
    }

    .el-dialog__body {
        height: 100%;
        padding: 10px 20px;
    }

    .el-dialog--center {
        margin-top: 30px !important;
        margin-bottom: 30px !important;
    }

    .el-divider--horizontal {
        margin: 0;
    }

    .is-horizontal {
        height: 0px;
        display: none;
    }

    .el-scrollbar__wrap {
        overflow-x: hidden;
    }
}

//隐藏页眉页脚
@media print {
    body {
        margin: 0;
        padding: 0;
    }

    @page {
        margin: 0 10px;
    }

    header,
    footer {
        display: none;
    }
}
</style>

隐藏页眉页脚: 

//隐藏页眉页脚
@media print {
    body {
        margin: 0;
        padding: 0;
    }

    @page {
        margin: 0 10px;
    }

    header,
    footer {
        display: none;
    }
}

 在使用打印功能的父组件页面中引入上述子组件;

 

组装数据格式为,传到打印页面,最终打印页面会计算布局,根据一行显示多少列来遍历child进行布局后显示打印页面。

singLine意即为是否独占一行打印显示,封装数据后传入组件内部会根据预设来布局显示完成打印预览及打印功能。

[
    {
        "title": "起搏器工作情况:",
        "child": [
            {
                "label": "植入型号:",
                "value": "MDT-SEDRL1",
                "singLine": false
            },
            {
                "label": "随访时间",
                "value": "2024-05-23 11:26:41",
                "singLine": false
            },
            {
                "label": "模式",
                "value": "DDDR",
                "singLine": false
            },
            {
                "label": "基础频率:",
                "value": "60(bpm)",
                "singLine": false
            },
            {
                "label": "最大跟踪频率:",
                "value": "130(bpm)",
                "singLine": false
            },
            {
                "label": "更多频率:",
                "value": "否",
                "singLine": false
            },
            {
                "label": "心房阈值:",
                "value": "0.5(V)",
                "singLine": false
            },
            {
                "label": "心房脉宽:",
                "value": "0.4(ms)",
                "singLine": false
            },
            {
                "label": "心房输出电压:",
                "value": "1.5(V)",
                "singLine": false
            },
            {
                "label": "心房电极阻抗",
                "value": "738(Ω)",
                "singLine": false
            },
            {
                "label": "心房感知:",
                "value": ">2.8(mV)",
                "singLine": false
            },
            {
                "label": "心房起搏比例:",
                "value": "74.8(%)",
                "singLine": false
            },
            {
                "label": "右室阈值:",
                "value": "0.625(V)",
                "singLine": false
            },
            {
                "label": "右室脉宽:",
                "value": "0.4(ms)",
                "singLine": false
            },
            {
                "label": "右室输出电压:",
                "value": "2.0(V)",
                "singLine": false
            },
            {
                "label": "右室电极阻抗:",
                "value": "385(Ω)",
                "singLine": false
            },
            {
                "label": "右室感知:",
                "value": "5.6-8.0(mV)",
                "singLine": false
            },
            {
                "label": "右室起搏比例:",
                "value": "2.5(%)",
                "singLine": false
            },
            {
                "label": "PAV间期:",
                "value": "150/120-320/290(ms)",
                "singLine": false
            },
            {
                "label": "起搏器预计使用年限:",
                "value": "10",
                "singLine": false
            },
            {
                "label": "电池电压:",
                "value": "2.79(V)",
                "singLine": false
            },
            {
                "label": "磁铁频率:",
                "value": "100",
                "singLine": false
            },
            {
                "label": "电池阻抗:",
                "value": "181(Ω)",
                "singLine": false
            },
            {
                "label": "ICD/CRTD选项:",
                "value": "否",
                "singLine": false
            },
            {
                "label": "CRT选项",
                "value": "否",
                "singLine": false
            },
            {
                "label": "是否有心律失常:",
                "value": "是",
                "singLine": false
            },
            {
                "label": "何种心律失常:",
                "value": "室性心动过速、房性心动过速",
                "singLine": false
            },
            {
                "label": "心律失常信息:",
                "value": "2023-04-18  VHR A/V:116/180bpm  1  3S  /;\\n2023-06-30  AHR  A/V:191/128bpm  1  14min54s  /;\\n",
                "singLine": true
            },
            {
                "label": "是否放电:",
                "value": "否",
                "singLine": false
            },
            {
                "label": "其他情况登记:",
                "value": "2 VHR 3S 2023.4.18;2024.1.17 \\n86 AHR 37S-1h13min36s  2023.6.26-2023.7.6 ",
                "singLine": false
            }
        ]
    }
]

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

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

相关文章

isscc2024 short course2 Performance Compute Environment

这部分分为4部分&#xff1a; 概览&#xff1a;LLMs和生成式AI 探讨大语言模型&#xff08;LLMs&#xff09;和生成式AI的整体环境&#xff0c;及其对硬件加速器设计的影响。 高性能AI加速器的特定考虑因素 广泛的模型和使用案例支持&#xff1a;需要设计能支持多种模型和应…

python中的线程并行

文章目录 1. 单线程2. 线程池ThreadPoolExecutor 1. 单线程 现在有1154张图片需要顺时针旋转后保存到本地&#xff0c;一般使用循环1154次处理&#xff0c;具体代码如下所示&#xff0c;img_paths中存储1154个图片路径&#xff0c;该代码段耗时约用97ms。 t1time.time() for …

SpringCloud系列(30)--准备使用Hystrix的前期工作,创建服务消费者模块

前言&#xff1a;在上一章节中我们创建了服务提供者模块&#xff0c;而本节内容则是创建服务消费者模块。 1、创建一个服务提供者模块&#xff0c;命名为cloud-consumer-feign-hystrix-order80 (1)在父工程下新建模块 (2)选择模块的项目类型为Maven并选择模块要使用的JDK版本 …

面向Prompt编程

Prompt 就像和一个人对话&#xff0c;你说一句&#xff0c;ta 回一句&#xff0c;你再说一句&#xff0c;ta 再回一句…… Prompt 就是你发给大模型的指令&#xff0c;比如「讲个笑话」、「用 Python 编个贪吃蛇游戏」、「给男/女朋友写封情书」等 貌似简单&#xff0c;但意义…

vue项目实战 - 如果高效的实现防抖和节流

在Vue项目中&#xff0c;处理高频事件的优化至关重要&#xff0c;直接影响用户体验和应用性能。防抖&#xff08;Debounce&#xff09;和节流&#xff08;Throttle&#xff09;是两种常用且有效的方法&#xff0c;可以控制事件触发频率&#xff0c;减少不必要的资源消耗。如何在…

labview_开放协议

一、开放协议 二、硬件设置 英格索兰硬件设置&#xff1a; 三、配套测试软件 四、Labview代码

科技赋能,打破视障人士的沟通壁垒

在探索如何增强盲人群体的社会参与度与幸福感的旅程中&#xff0c;盲人社交能力提升策略成为了不容忽视的一环。随着科技的不断进步&#xff0c;像“蝙蝠避障”这样的辅助软件&#xff0c;不仅在日常出行中为盲人提供了实时避障和拍照识别的便利&#xff0c;也在无形中为他们拓…

SQL面试题练习 —— 波峰波谷

来源&#xff1a;字节今日头条 目录 1 题目2 建表语句3 题解 1 题目 有如下数据&#xff0c;记录每天每只股票的收盘价格&#xff0c;请查出每只股票的波峰和波谷的日期和价格&#xff1b; 波峰定义&#xff1a;股票价格高于前一天和后一天价格时为波峰 波谷定义&#xff1a;股…

FPGA状态机设计详解

一.什么是状态机&#xff1f; 想象一下你正在玩一个电子游戏&#xff0c;角色有多种状态&#xff0c;比如“行走”、“跳跃”、“攻击”等。每当你按下不同的按键或者满足某些条件时&#xff0c;角色的状态就会改变&#xff0c;并执行与该状态对应的动作。这就是状态机的一个简…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-23.3,4,5,6 讲 I2C驱动-读取AP3216C传感器​

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

计算机SCI期刊,IF=8+,专业性强,潜力新刊!

一、期刊名称 Journal of Big data 二、期刊简介概况 期刊类型&#xff1a;SCI 学科领域&#xff1a;计算机科学 影响因子&#xff1a;8.1 中科院分区&#xff1a;2区 出版方式&#xff1a;开放出版 版面费&#xff1a;$1990 三、期刊征稿范围 《大数据杂志》发表了关于…

HLS视频加密,让您的视频内容更安全!

背景介绍 HLS视频加密是一种基于HTTP Live Streaming&#xff08;HLS&#xff09;协议的加密技术。它的核心思想是将视频切片进行加密处理&#xff0c;在客户端播放时需要先获取解密密钥才能正常偶发。通过这种方式&#xff0c;HLS加密可以有效防止未经授权的第三方窃取视频内…

刷题篇--数据结构--链表

一.环形链表Ⅰ . - 力扣&#xff08;LeetCode&#xff09; 这道题可以利用快慢指针的方法来解决&#xff0c;即定义一个快指针f他的速度是一次走两步&#xff0c;慢指针s他的速度是一次走一步&#xff0c;这时我们假设链表有环&#xff0c;环的入口点为N&#xff0c;当两个指…

27寸2K显示器 - HKC G27H2

HKC G27H2是一款面向电竞市场的高性能显示器&#xff0c;以其2K分辨率和180Hz的刷新率作为主要卖点&#xff0c;旨在为玩家提供流畅而清晰的视觉体验。配备HDR 400技术和95% DCI-P3色域覆盖&#xff0c;这款显示器还支持升降旋转支架&#xff0c;为用户提供了高度的人体工程学适…

同旺科技 FLUKE ADPT 隔离版发布 ---- 说明书

所需设备&#xff1a; 1、FLUKE ADPT 隔离版 内附链接&#xff1b; 应用于&#xff1a;福禄克Fluke 12E / 15BMax / 17B Max / 101 / 106 / 107 应用于&#xff1a;福禄克Fluke 15B / 17B / 18B

酷开科技大屏营销,多元需求唤醒“客厅经济”

随着科技的发展和消费者习惯的变化&#xff0c;OTT大屏营销正逐渐成为客厅经济的新风向。OTT不仅改变了人们获取信息和娱乐的方式&#xff0c;也为品牌营销提供了新的机遇和挑战&#xff0c;OTT大屏营销已经成为客厅经济的重要组成部分。酷开科技通过其自主研发的智能电视操作系…

戴尔(Dell)服务器运行状况监控

戴尔&#xff08;Dell&#xff09;服务器因其加速的性能、增强的自动化和简化的管理而受到全球许多组织的青睐&#xff0c;许多组织将其业务关键应用程序和功能放在戴尔&#xff08;Dell&#xff09;服务器中&#xff0c;因此&#xff0c;有效的戴尔&#xff08;Dell&#xff0…

Jeecg | 完成配置后,如何启动整个项目?

前端启动步骤&#xff1a; 1. 以管理员身份打开控制台&#xff0c;切换到前端项目目录。 2. 输入 pnpm install 3. 输入 pnpm dev 4. 等待前端成功运行。 可以看到此时前端已经成功启动。 后端启动步骤&#xff1a; 1. 启动 mysql 服务器。 管理员身份打开控制台&#…

基于51单片机的多功能万年历温度计—可显示农历

基于51单片机的万年历温度计 &#xff08;仿真&#xff0b;程序&#xff0b;原理图&#xff0b;设计报告&#xff09; 功能介绍 具体功能&#xff1a; 本设计基于STC89C52&#xff08;与AT89S52、AT89C52通用&#xff0c;可任选&#xff09;单片机以及DS1302时钟芯片、DS18B…

Spring6 对 集成MyBatis 开发运用(附有详细的操作步骤)

详细实现操作步骤 具体实现内容&#xff1a;我们运用 Spring6 和 MyBatis 实现一个转账操作(该转账操作&#xff0c;进行一个事务上的控制&#xff0c;运用 MyBatis 执行 SQL 语句)。 第一步&#xff1a;准备数据库表 使用t_act表&#xff08;账户表&#xff09; 连接数据库的…