详解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>
相关文章:
详解window.print(),实现长列表打印分页
相信大家平时做项目时,打印需求很常见,但想把打印做好,还是要花点时间的。特别是长列表要分页的情况。 我们知道浏览原生 API window.print() 可以用于印当前窗口(window.document)视图内容。调用此方法会产生一个打印…...
使用Chatgpt编写的PHP数据库pdo操作类(增删改查)
摘要 将PDO封装成PHP类进行调用有很多好处,包括: 1、封装性和抽象性: 通过将PDO封装到一个类中,您可以将数据库操作逻辑与应用程序的其他部分分离开来,提高了代码的组织性和可维护性。这样,您只需在一个地…...
蓝桥杯2023年第十四届省赛真题-异或和之和--题解
目录 蓝桥杯2023年第十四届省赛真题-异或和之和 题目描述 输入格式 输出格式 样例输入 样例输出 【代码实现】 大家觉得写得可以的话,可以加入QQ群907575059. 蓝桥杯2023年第十四届省赛真题-异或和之和 时间限制: 3s 内存限制: 320MB 提交: 241 解决: 66 …...
Linux 常用命令学习笔记
Linux 常用命令学习笔记 文件操作 ls:列出当前目录下的文件和文件夹。 ls -l:以长格式显示文件和文件夹的详细信息。ls -a:显示所有文件,包括隐藏文件。 cd [目录]:切换到指定目录。pwd:显示当前工作目录…...
支撑电动汽车规模化,特来电智能化升级群充产品
9月26日,中国领先的充电网生态运营商特来电重磅发布智能群充4.0产品,标志着特来电群充产品体系进一步升级,充电行业迎来更高质量、更高性能的设备与系统,充电网基础设施将更好地支撑大规模电动汽车的发展。 群充技术路线引领充电…...
本次CTF·泰山杯网络安全的基础知识部分
简记23年九月参加的泰山杯网络安全的部分基础知识的题目,随时补充 1. 国密算法哪个属于公钥? SM2 a. 国产密码算法(国密算法)是指国家密码局认定的国产商用密码算法,目前主要使用公开的SM2、SM3、SM4三类算法&#x…...
通信协议:Uart的Verilog实现(下)
4、UART接收器 UART接收器负责接收串行比特流,去除起始位和停止位,并以并行格式将数据保存到与主机数据总线相连的寄存器里。接收器无法获得发送时钟,因此尽管数据以标准比特率到达,但数据未必与接收主机内的时钟同步。同步问题可…...
嵌入式MCU都有什么高级用法?
嵌入式MCU都有什么高级用法? 您举的几个例子,确实是MCU外设的一些高端玩法。只是不知道您是否想过,既然这些机制是被 人设计出来的,那它就是种标准用法。从微控制器的发展历程来看,许多硬件机制都是有了实际 需求后才…...
热启动和冷启动是什么,区别
app冷启动: 当应用启动时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用, 这个启动方式就叫做冷启动(后台不存在该应用进程)。冷启动因为系统会重新创建一个新的进程分配给它ÿ…...
每日一题 494目标和(0-1背包)(灵神笔记)
0-1背包模版 有n个物品,它们有各自的体积和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和? 当前操作?枚举第i个物品选还是不选,不选容量不变,选容量减少 子问题ÿ…...
软件测试工作步骤详情
软件测试步骤按照研发阶段一般分为5个部分:单元测试、集成测试、确认测试、系统测试、验收测试,下面将不同阶段需要的一些工作内容做一下梳理希望可以帮助到大家。 一、单元测试的内容:(白盒为主,黑盒为辅)…...
java项目之列车票务信息管理系统(ssm源码+文档)
项目简介 列车票务信息管理系统实现了以下功能: 管理员:个人中心、用户管理、车票信息管理、购票指南管理、管理员管理、论坛管理、我的收藏管理、系统管理、订单管理。前台首页:首页、车票信息、购票指南、我的收藏管理、论坛信息、我的、…...
【Pytorch笔记】3.数学运算
深度之眼官方账号 - 01-03-mp4-张量操作与线性回归 torch.add() 功能:逐元素计算inputalphaother。 torch.add(input,alpha1,other,outNone)input:tensor; alpha:other的系数,是个实数; other࿱…...
MeterSphere 监控方案
前言:在部署MeterSphere之后,很多时候需要看下MeterSphere服务的监控信息,虽然有监控告警脚本,但还不是太直观,所以就结合 PrometheusExporterGrafana 部署一套完整的MeterSphere监控方案。 首先我们先罗列一下需要监控…...
elementui-plus+ts+axios使用el-upload组件自定义上传
1.前言: 使用element ui有很多便捷之处,但是由于是封装的组件和自己写还是有些许的不一样,这里主要解决几个问题。 1. 如何获取子组件实例 2. 如何自定义上传方法 2.两个问题: ⛺️ 获取子组件实例 实际上vue一般通过ref获取子组…...
【STM32单片机】u8g2智能风扇设计
文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用STM32F103C8T6单片机控制器,使用按键、IIC OLED模块、DS18B20温度传感器、直流电机、红外遥控等。 主要功能: 初始化后进入温度显示界面,系统初始状态为手动…...
Java中的IO流的缓冲流
不爱生姜不吃醋⭐️ 如果本文有什么错误的话欢迎在评论区中指正 与其明天开始,不如现在行动! 文章目录 🌴IO流体系结构🌴缓冲流1.提高效率的原理2.缓冲流的类型3.字符缓冲流两个特有方法 🌴总结 🌴IO流体系…...
7、SpringBoot_高级配置
一、配置高级 1.临时属性设置 1.1引出问题 如果目标电脑上8080端口已经使用,再次使用该端口会出现端口占用问题 解决方式 重新更换配置文件修改端口打包通过临时属性配置新端口更换配置文件 1.2添加临时属性配置 通过临时属性修改8080端口 java -jar 项目.jar…...
cocos2dx查看版本号的方法
打开文件:项目根目录\frameworks\cocos2d-x\docs\RELEASE_NOTES.md 知道引擎版本号的意义: 1.面试中经常被问到(面试官想知道你会不会查版本号,你会查也不一定会去看,如果你去看了说明你是一个有心人,或者想深入研究下…...
某高校的毕设
最近通过某个平台接的单子,最后Kali做的测试没有公开可以私聊给教程。 下面是规划与配置 1.vlan方面:推荐一个vlan下的所有主机为一个子网网段 连接电脑和http客户端的接口配置为access接口 交换机与交换机或路由器连接的接口配置为trunk接口---也可以…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...
