封装打印组件
Vue打印组件封装-每页签名表格实现
#tech / dev / frame
#type / howto
#status / growing
封装打印组件
背景说明
现在打印内容有 正文 + 签名表格(应该每页都完整显示)
当前使用将 正文+表格都放在一起,使用 html2CanvasPrint 将 DOM 渲染为一个画布 然后调用浏览器打印方式来打印,会自动翻页(正文内容较多时,表格分割并且不是每页都有)
现在的打印实现逻辑: 点击按钮,跳转到 printDetail 页面并携带参数(用于获取数据),然后渲染页面
所以我只需要 提取 function 获取数据、 function 获取签名表、 function 渲染数据表格、 function 渲染签名表格、 function 渲染 分页PDF、const printCss、
目标:
- 签名表格不跨页拆分。
- 确保每页都有完整的签名区域。
- 先在页面底部放签名表(重复显示内容),剩余空间来渲染 其余内容
解决方案选项:
- 基于 DOM 的打印 + CSS 分页控制(推荐)
- 停止转换为画布,直接打印 DOM。
- 使用支持 CSS 的打印库:
- 为签名表格容器添加
page-break-inside: avoid; break-inside: avoid-page。 - 调整内容结构,使每页包含 “主表格片段” 和签名区块。
- 为签名表格容器添加
- 优点:通过 CSS 实现更精细控制;可实现每页重复签名区域。
- 缺点:需手动将
archiveList分页拆分。
- 手动分页 + 每页独立容器(可靠)
- 按每页行数拆分
archiveList(例如每页 15 行,可根据布局调整)。 - 为每页渲染:
- 页眉
- 包含当前页数据的子表格
- 签名表格(
appendix-1和appendix-2) - 备注框(可选是否每页显示)
- 为每个页面容器添加
page-break-after: always;及page-break-inside: avoidCSS。 - 可确保签名表格不拆分且每页均显示。
- 优点:结果可预测;布局一致性强。
- 缺点:需一定开发工作量;每页行数需根据 A4 尺寸调整。
- 画布切片(若坚持使用 html2canvas 的备选方案)
- 按当前 DPI 计算 A4 页面对应的画布高度,将长画布切片为多张图片,确保签名区块不被切割。
- 需计算签名区块的 Y 轴位置并调整切片边界。
- 优点:保持图片打印模式。
- 缺点:逻辑复杂;对动态内容适应性差;需测量 DOM 以对齐切片位置。
优选方案:2) 手动分页 + 直接 DOM 打印 + 分页控制 CSS
vue-print-next 是否适用?
- 概述:
vue-print-next库专注于打印特定 DOM 元素,提供钩子函数、样式注入和配置项,依赖原生打印或 iframe 实现,而非画布。 - 适用性:
- 支持直接打印 DOM 内容,可识别 CSS 分页符(
page-break-inside、break-inside、page-break-after)。 - 可将每页内容封装为独立元素,确保签名表格不拆分。
- 可通过在每个页面容器中渲染页眉 / 页脚类区块,实现每页重复显示。
- 支持直接打印 DOM 内容,可识别 CSS 分页符(
- 限制:
- 浏览器对 “运行时页眉 / 页脚” 的支持不一致。仅通过 CSS 无法实现签名区域自动作为每页页脚重复显示,需在 DOM 中为每页单独渲染签名表格。
vue-print-next不支持自动分页 —— 需手动拆分archiveList。
- 结论:适用。若实现手动分页并配置正确 CSS,vue-print-next 可实现基于 DOM 的打印,确保每页签名区域完整无拆分。
实现
Q1
打印界面不能翻页,只显示第一页
使用如下代码解决了
<style>
/* 强制覆盖全局的 html/body 样式,确保打印时可以滚动/分页 */
@media print {
html, body, #app {
height: auto !important;
overflow: visible !important;
display: block !important;
}
}
</style>
Q2
预览界面不能翻页,只显示第一页
Q3
页面样式需要调整,
- 让 签字表 始终位于最下方
- 调整布局样式,减小内容大小,让表格能显示完整,且多显示几行,使用 pagedjs
Q4
我发现一个大问题,就是我使用提一个文件,但是在其他新项目中写的demo 就能正确显示多页,而放在这个项目就只有一页。这说明应该是某一个 全局样式 影响了 vueprintnext 的样式行为,请你找到这个问题发生处
之前一页

现在

想法
我觉得可以直接生成一个统一的 打印并且包含固定部分(签名表)的 组件 和 composables 文件
应该是直接封装 composables 文件,里面需要几个功能:
- 获取重复内容(签名表)
- 获取选择内容的数据
- 根据选择的内容来生成 表格、html
- 使用 pagedjs 来优化样式
- 把最终获取到的完整内容加上 el 传入 vueprinternext 来渲染
直接在 原本打开预览界面的 按钮 替换为 vueprinternext 按钮,使用它自带的 preview dialog。
以函数式编程的方式来实现,也便于测试