详解window.print(),实现长列表打印分页

相信大家平时做项目时,打印需求很常见,但想把打印做好,还是要花点时间的。特别是长列表要分页的情况。

我们知道浏览原生 API `window.print()` 可以用于印当前窗口(window.document)视图内容。调用此方法会产生一个打印预览弹框,用户可以根据具体设置来得到打印结果。

一、window的打印事件

默认情况下,调用 window.print() 会对整个 document.body 进行打印,当需要打印指定容器内容时,可以这样做:

1、先获取指定容器中的内容,将body的内容替换掉,调用了打印方法后,再把原来的body恢复。

<body><div id="container1"><p>这是第一个段落</p></div><div id="container2"><p>这是第二个段落</p></div><input type="button" value="打印此页面" onclick="printPage()" /><script>const printPage= () => {let newstr = document.getElementById("container1").innerHTML;let oldstr = document.body.innerHTML;document.body.innerHTML = newstr;window.print();document.body.innerHTML = oldstr;</script>
</body>

2、监听打印前、后事件实现区域打印

window.onbeforeprint()、window.onafterprint()

<body><div id="container"><p>这是一个段落</p><h1 id="title">这是一个标题</h1></div><input type="button" value="打印此页面" onclick="printPage()" /><script>const printPage= () => {window.print();}// 打印前事件window.onbeforeprint = function() {// 隐藏不需要打印的元素document.getElementById('title').style.display = 'none';}// 打印完成后window.onafterprint = function() {// 放开隐藏的元素document.getElementById('title').style.display = 'block';}</script>
</body>

二、打印样式

 我们页面的样式和打印页面时的样式是两个不同的样式,打印时会默认携带页面的样式,同时呢我们也可以修改页面打印时的样式。修改打印样式的方法:

1、使用内联media属性

<style media="print">.container{width:800px;}
</style>

2、使用媒体查询

<style>@media print {h1{color: #333;background: #ccc;}}
</style>

3、引入打印样式表 

 例如:print.css

@media print {@page {size: auto;margin: 20px 30px;}#mainBody{margin-top:0 !important;margin-bottom:0 !important;}
}

 用link引入

<link rel="stylesheet" type="text/css" href="./css/print.css" media="print" />

注意:

1、如果是前后不分离的项目,在样式中用到`@`时可能会报错:"上下文中未定义@media或@page",这时候我们可以用`<link>`的方式引入。

2、修改打印样式时必须确保打印机样式实际上确实覆盖了主样式表。可以使用!important。

3、@page属性可以控制打印页面的边距大小和页眉页脚

@media print {@page {size: auto; // {size:A4}、{size: 800px 1200px}、{size:portrait}竖向打印、{size:landscape}横向打印margin: 20px 30px; // 边距,可去除页眉页脚}// 覆盖页面原有样式#container{margin-top:0 !important;margin-bottom:0 !important;}
}

4、-webkit-print-color-adjust:是一个在浏览器中强制打印背景颜色和字体颜色的css属性,当打印出来的某些元素的背景颜色没有被显示时,可以使用-webkit-print-color-adjust:exact

5、当需要自定义打印分页时机时,可通过如下方式将指定 DOM 设为分割点。

@media print {h1 {page-break-before: always; //在指定元素前面添加分页符}#title {page-break-after: always;//在指定元素后面添加分页符}
}

了解更多:page-break-after - CSS:层叠样式表 | MDN

 三、长列表打印

打印长列表时会要求自动分页,但添加了分页符效果可能并不理想。最常见的就是表格行被从中间截断,那要怎么解决呢?

其实我们只要控制打印的行数就可以了。我们需要知道打印元素的高度和表格行的高度,算出一页纸可以打印多少行,超出的部分放到下一页打印。(一页放多少行没必要计算,根据打印元素的高度估算下就可以了。)

示例:

<style>body {font-family: "微软雅黑",Verdana,SimHei,"Microsoft JhengHei",Tahoma;line-height: 1.5;background-color: #ffffff;margin: 0;}// 打印容器#mainBody {margin: 20px 20px 0 20px;}table {border: 1px solid #000;border-collapse: collapse;width: 100%;}table td {border: 1px solid #000;height: 30px;text-align: center;}table th {border: 1px solid #000;height: 30px;text-align: center;}.printContainer {margin: 0 auto;// 打印内容宽高width: 1052px;height: 1480px;position: relative;}.printTitle {font-size: 22px;font-weight: bold;text-align: center;}.printnav {display: flex;justify-content: space-between;}.signature_footer {position: absolute;width: 100%;bottom: -20px;display: flex;justify-content: space-around;font-size: 20px;}
</style>
<body><div id="mainBody"></div>
</body><script>$(document).ready(function () {getList()})//获取地址栏参数function getUrlParam(name) {var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); //构造一个含有目标参数的正则表达式对象var r = window.location.search.substr(1).match(reg);  //匹配目标参数if (r != null) return unescape(r[2]); return null; //返回参数值}// 将列表数据分页,array要分页的数据,subNum是每页多少条(根据纸张大小估算一页能展示多少条)function groupArray(array, subNum) {let index = 0let newArray = []while (index < array.length) {newArray.push(array.slice(index, (index += subNum)))}return newArray}// 获取数据源,页面添加元素function getList() {var params = {PatientID: getUrlParam('PatientID'),BedNo: getUrlParam('BedNo'),xdStartDate: getUrlParam('StartDate'),xdEndDate: getUrlParam('EndDate')}$.get('/IndexPrintList', params, function (res) {// 先清空上一次的数据$('#mainBody').empty()// 分页的数据,返回的数组长度即页数var arr = groupArray(res.alist, 14)if (arr.length) {for (let i = 0; i < arr.length; i++) {// 创建打印元素$('#mainBody').append(`<div class="printContainer"><div class="printTitle">${res.hospitalName}</div><div style="text-align:center;font-weight:bold;font-size:20px;margin:20px 0;">定点血糖记录表</div><div class="printnav" style="margin: 10px 0; font-size:14px;"><div>患者ID: ${res.patientModel.no}</div><div>姓名:${res.patientModel.name}</div><div>性别: ${res.patientModel.sex == 0 ? "男" : "女"}</div><div>病区:${res.patientModel.Bed.WardModel.wardName}</div><div>床号:${res.patientModel.Bed.innerOrder}</div><div>测量次数:${res.allNum}</div></div><div class="printContent"><table><thead><tr><th colspan="2">日期\监测点</th>${res.SortList.map(column => {return `<th>${column.name}</th>`}).join("")}</tr></thead><tbody>${arr[i].map(row => {return `<tr><td rowspan="3" style="width:90px">${row.measureTime}</td><td>血糖值(mmol/L)</td>${res.MeasurePointList.map(point => {if (row.dict[point.id]) {return `<td style="color:${row.dict[point.id].color}"> 		    																		 ${row.dict[point.id].Value}</td>`} else {return `<td></td>`}}).join("")}</tr><tr><td>操作者</td>${res.MeasurePointList.map(point => {if (row.dict[point.id]) {return `<td>${row.dict[point.id].AccountName}</td>`} else {return `<td></td>`}}).join("")}</tr><tr><td>测量时间</td>${res.MeasurePointList.map(point => {if (row.dict[point.id]) {return `<td>08:00</td>`} else {return `<td></td>`}}).join("")}</tr>`}).join("")}</tbody></table></div><div class="signature_footer"><div>医生手签:</div><div style="margin-right:30px;">质控护士手签:</div></div></div>`)}}window.print();})}</script>

代码解释:

1、首先给打印元素设置宽和高,高度根据需要或实际情况设置。(可根据A4纸大小来定)

2、通过接口拿到长列表数据,然后用`groupArray`方法计算需要打印几页。(groupArray函数返回一个二维数据,二维数组的长度就是页数,二维数组的每一项就是每页的数据)

3、根据这个二维数组循环创建要打印的元素。(类`.printContainer`是要打印的整体内容,即一页纸的内容,arr[i]就是每页的表格数据)

4、示例中每页都加了标题和签名,表格有合并单元格。

5、简单表格如下:

<table><thead><tr><th>检测日期</th><th>检测值</th><th>操作护士</th></tr></thead><tbody>${arr[i].map(item=>{return `<tr><td>${item.MeasureDateStr}</td><td>${item.value}</td><td>${item.AccountName}</td></tr>`}).join("")}</tbody>
</table>

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

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

相关文章

ExcelServer EXCEL服务器使用- 用户、角色权限配置

Excel文件服务器搭建 搭建Excel服务器 1、登录 默认 用户名 Admin 密码 3 2、角色管理 添加修改角色 角色配置在 系统管理->角色.fexm文件夹下 可以像修改excel文件一样 修改角色 3、用户管理 添加修改用户 用户的修改在 系统管理->用户.fexm 可以像excel一样编辑用户…

Ubuntu下载

参考文档&#xff1a; 镜像文件&#xff1a;VMware下安装ubuntu 16.04&#xff08;全步骤&#xff09;_vmwaubuntu-16.04.4-desktop-amd64.iso_ST0new的博客-CSDN博客 vmware tools使用安装&#xff1a;VMware——VMware Tools的介绍及安装方法_William.csj的博客-CSDN博客 …

链式二叉树的实现及遍历(C语言版)

目录 1 基本概念 1.1 树的概念 1.2 二叉树的链式表示 1.2.1 "左孩子右兄弟"表示法 1.2.2 "左右子树"表示法 1.2.3 手动构建一棵树 2 树的遍历 2.1 前序遍历/先序遍历 2.2 中序遍历 2.3 后序遍历 2.4 层序遍历 2.4.1 算法思想 ​编辑 2.4.2 带头…

MongoDB基础详解

一、MongoDB概述 MongoDB 是一个基于 分布式文件存储 的开源 NoSQL 数据库系统&#xff0c;由 C 编写的。MongoDB 提供了 面向文档 的存储方式&#xff0c;操作起来比较简单和容易&#xff0c;支持“无模式”的数据建模&#xff0c;可以存储比较复杂的数据类型&#xff0c;是一…

图像采集 deep OCR

按照芯片类型可以分为CCD相机、CMOS相机 按照传感器的结构特性可以分为线阵相机、面阵相机 按照扫描方式可以分为隔行扫描相机、逐行扫描相机 按照分辨率大小可以分为普通分辨率相机、高分辨率相机按照输出信号方式可以分为模拟相机、数字相机 按照输出色彩可以分为单色(黑白)相…

【Linux学习】02Linux基础命令

Linux&#xff08;B站黑马&#xff09;学习笔记 01Linux初识与安装 02Linux基础命令 文章目录 Linux&#xff08;B站黑马&#xff09;学习笔记前言02Linux基础命令Linux的目录结构Linux命令入门ls命令 目录切换相关命令(cd/pwd)cd命令pwd命令 相对路径、绝对路径和特殊路径符创…

自我介绍+项目

自我介绍 1.自我介绍2.快手实习难点&#xff1a;上锁函数 防抖函数结合亮点&#xff1a;技术选型 Uber实习auth0 原理 1.自我介绍 &#xff08;乖巧&#xff0c;听话的声音&#xff09; 好的&#xff0c;面试官你好。我是一名前端开发工程师&#xff0c;叫李小菲&#xff0c;…

Seata流程源码梳理下篇-TC

我们上篇简单梳理了下TM、RM的一些流程&#xff08;离现在过得挺久的了&#xff0c;这篇我们这篇来梳理下TC的内容。 TC (Transaction Coordinator) - 事务协调者 维护全局和分支事务的状态&#xff0c;驱动全局事务提交或回滚。 TM (Transaction Manager) - 事务管理器 定…

Flask-[实现websocket]-(2): flask-socketio文档学习

一、简单项目的构建 flask_websocket |---static |---js |---jquery-3.7.0.min.js |---socket.io_4.3.1.js |---templates |---home |---group_chat.html |---index.html |---app.py 1.1、python环境 python3.9.0 1.2、依赖包 Flask2.1.0 eventlet0.33.3 #使用这个性能会…

将本地项目上传至Github详解

目录 1 前言2 本地代码上传2.1 命令行方法2.2 图形界面法2.3 结果 1 前言 GitHub是一个面向开源及私有软件项目的托管平台&#xff0c;因为只支持Git作为唯一的版本库格式进行托管&#xff0c;故名GitHub 。开发者常常将github作为代码管理平台&#xff0c;方便代码存储、版本…

基于SpringBoot的的师生健康信息管理系统

目录 前言 一、技术栈 二、系统功能介绍 管理员功能模块 学生功能模块 教师功能模块 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着移动应用技术的发展&#xff0c;越来越多的用户借助于移动手机、电脑完成生活中的事务&#xff0c;许多的传统行业也…

超级详细 SQL 优化大全

1、MySQL的基本架构 1&#xff09;MySQL的基础架构图 左边的client可以看成是客户端&#xff0c;客户端有很多&#xff0c;像我们经常你使用的CMD黑窗口&#xff0c;像我们经常用于学习的WorkBench&#xff0c;像企业经常使用的Navicat工具&#xff0c;它们都是一个客户端。右…

北工大汇编题——分支程序设计

题目要求 信息检素程序设计&#xff1a;在数据区&#xff0c;有9个不同的信息&#xff0c;编号 0-8&#xff0c;每个信息包括20 个字符。从键盘接收 0-8 之间的一个编号&#xff0c;然后再屏幕上显示出相应编号的信息内容&#xff0c;按“q”键退出 完整代码 DATAS SEGMENTn0…

Day 03 python学习笔记

位运算 基于二进制的运算&#xff08;计算机的底层基于位运算&#xff09; 计算机最小单位&#xff1a;bit (比特/位/二进制) 1byte&#xff08;字节&#xff09; 8bit &#xff08; 0000 0000&#xff09; &&#xff1a;与 &#xff08;全真为真&#xff0c;一假则…

项目开发过程中遇到了什么困难?

1.需求最初是什么样的&#xff1f; 2.如何挖掘的需求&#xff0c;挖掘后真实的需求是什么样的&#xff1f; 3.我们做了那些调查&#xff1f; 4.我们给出了那些方案&#xff0c;优缺点是什么&#xff1f; 5.根据实际情况&#xff0c;老板的期望&#xff0c;最终我们选择的什…

linux ansible(三)

ansible 配置详解 3.1 ansible 安装方式 ansible安装常用两种方式&#xff0c;yum安装和pip程序安装 3.1.1 使用 pip&#xff08;python的包管理模块&#xff09;安装 需要安装一个python-pip包&#xff0c;安装完成以后&#xff0c;则直接使用pip命令来安装我们的ansible包 …

Leetcode 01-算法入门与数组-③数组排序

LeetCode 01-算法入门与数组-③数组排序 一. 冒泡排序 1. 冒泡排序算法思想 冒泡排序&#xff08;Bubble Sort&#xff09;基本思想&#xff1a; 经过多次迭代&#xff0c;通过相邻元素之间的比较与交换&#xff0c;使值较小的元素逐步从后面移到前面&#xff0c;值较大的元素…

SAP PO运维(一):系统概览异常处理

打开SAP PIPO Netweaver Administration界面,系统概览下显示异常: 参考SAP note: 2577844 - AS Java Monitoring and Logging parametrization best practice service/protectedwebmethods = SDEFAULT -GetVersionInfo -GetAccessPointList -ListLogFiles -ReadLogFile -Para…

为什么选择Spring Cloud

Spring Cloud与Netflix Netflix是一家做视频网站的公司&#xff0c;之所以要说一下这个公司是因为Spring Cloud在发展之初&#xff0c;Netflix做了很大的贡献。包括服务注册中心Eureka、服务调用Ribbon、Feign&#xff0c;服务容错限流Hystrix、服务网关Zuul等众多组件都是Net…

在PyTorch里面利用transformers的Trainer微调预训练大模型

背景 transformers提供了非常便捷的api来进行大模型的微调&#xff0c;下面就讲一讲利用Trainer来微调大模型的步骤 第一步&#xff1a;加载预训练的大模型 from transformers import AutoModelForSequenceClassificationmodel AutoModelForSequenceClassification.from_pr…