ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

前端打印利器hiprint:Vue项目可视化打印模板设计与实现

前端打印利器hiprint:Vue项目可视化打印模板设计与实现 简介这是一套专为Vue开发者设计的跨版本打印解决方案面向Web应用开发中需实现报表定制、票据打印与可视化排版的中高级前端工程师。资源提供hiprint在Vue2/Vue3环境下的完整集成能力覆盖打印设计、可视化设计器、元素拖拽编辑、多数据源报表生成等核心场景显著降低发票、工单、证书等业务文档的开发门槛。压缩包共77个文件3.8MB含26个JS逻辑模块、12个Vue组件、15张PNG/SVG图标与工具图示、4个CSS样式文件及字体/HTML/配置类资源结构清晰便于按功能模块快速定位与二次开发。已有5137人学习下载内含可直接运行的demo示例、多套预设模板template1–3.png、微信/支付宝支付凭证样例图及WebStorm集成图标等实用资产开箱即用支持快速嵌入现有Vue项目并完成专业级打印定制。1. 项目概述hiprint一个被低估的前端打印利器如果你在前端开发中尤其是使用Vue2或Vue3构建管理后台、ERP、报表系统时被复杂的打印需求折磨过——比如要动态生成带表格、条形码、图片的送货单或者让用户能自己拖拽调整打印模板——那么你很可能需要hiprint。这不是一个简单的“点击打印”按钮库而是一个完整的、从前端可视化设计到后端数据填充、最终驱动打印机输出的解决方案。它把传统需要依赖后端报表引擎如JasperReports、FastReport或复杂CSS排版才能实现的打印功能完全搬到了浏览器里。简单来说有了hiprint你的Vue项目就能获得一个类似“Word文档设计器”的打印模板设计能力用户或管理员可以自由设计票据、标签、合同等任何打印样式开发者只需关注数据绑定。我最初接触它是因为一个仓储物流项目客户需要随时调整货架标签的尺寸和内容。传统方式每改一次都要后端重新开发模板耗时耗力。引入hiprint后实施顾问自己就能在系统前台完成标签模板的调整效率提升立竿见影。它的核心价值在于“可视化”和“解耦”将打印样式与业务代码分离将设计权交给更贴近业务的人。2. 核心架构与设计思路拆解2.1 为什么是hiprint对比传统打印方案在hiprint出现之前前端处理复杂打印无非几种路径CSS打印样式通过media print编写样式简单但难以应对复杂布局、分页控制、精确到毫米的定位且无法预览真实效果。调用浏览器打印APIwindow.print()功能原始无法定制页眉页脚样式控制弱。后端生成PDF后端使用iText、PDFlib等库生成PDF返给前端打印。功能强大但前后端交互频繁无法实时预览调整模板需要重新部署。纯Canvas绘制灵活度高但开发成本巨大相当于自己实现一个绘图引擎。hiprint的思路独树一帜它定义了一套JSON Schema来描述打印模板。这个JSON模板定义了纸张大小、方向、边距以及模板上所有元素文本、表格、条形码、图片、竖排文字等的类型、位置、样式和数据绑定规则。前端渲染器根据这个JSON在Canvas上精确绘制出预览图打印时再将数据和模板结合通过一个隐藏的iframe调用浏览器打印。这样模板的设计、存储、渲染、打印完全在前端完成。方案选型考量开发效率hiprint提供可视化设计器节省从零开发设计器的数月时间。灵活性模板即JSON可存数据库、可版本管理、可动态下发。用户体验所见即所得的预览和设计无需刷新页面。技术栈契合度专为Vue生态设计以Vue组件形式集成无缝融入项目。2.2 hiprint的核心模块与工作流hiprint的架构可以清晰地分为几个模块理解它们有助于后续的开发和调试hiprint核心渲染库这是一个无UI的纯逻辑库。它的职责是解析我们定义的打印模板JSON并根据另一份数据JSON将两者结合在指定的DOM容器通常是一个div内渲染出打印预览画面。这个预览不是简单的HTML而是基于Canvas的精确定位绘制确保了与最终打印效果的一致性。vue-plugin-hiprint设计器插件这是一个Vue组件。它封装了核心库并提供了一个可交互的UI界面——即我们看到的可视化设计器。设计器左侧是元素工具栏中间是画布右侧是属性面板。用户在这里拖拽、配置最终生成的就是那份核心的打印模板JSON。打印执行器当预览无误后调用hiprint提供的打印方法。其内部原理是将渲染好的内容可能是Canvas转成的图片或生成的HTML放入一个隐藏的iframe中然后调用iframe.contentWindow.print()来触发浏览器的原生打印对话框。这种方式能最大程度保证打印样式不丢失。整个工作流如下[可视化设计器] - 生成 - [打印模板JSON] - 存储到数据库/文件 [业务数据] [打印模板JSON] - [hiprint核心库渲染] - [前端预览] 用户确认 - [调用打印执行器] - [浏览器打印对话框] - [物理打印]3. 环境搭建与基础集成3.1 在Vue2与Vue3中的安装与引入hiprint对Vue2和Vue3都提供了良好支持但引入方式因版本而异。首先需要通过npm或yarn安装核心包。对于Vue2项目npm install vue-plugin-hiprint --save # 或 yarn add vue-plugin-hiprint在main.js中全局引入并注册插件import Vue from vue; import App from ./App.vue; import hiprint from vue-plugin-hiprint; Vue.use(hiprint); // 可选初始化一些默认配置如自定义条形码类型 hiprint.init({ // 配置项... }); new Vue({ render: h h(App), }).$mount(#app);对于Vue3项目Vue3的插件注册方式不同需要查看vue-plugin-hiprint的官方文档确认其是否提供了Vue3专用的版本或注册方法。通常如果插件支持Vue3会提供一个createHiprint之类的函数。npm install vue-plugin-hiprintnext --save // 假设有next版本支持Vue3在main.js中import { createApp } from vue; import App from ./App.vue; import hiprint from vue-plugin-hiprint; const app createApp(App); app.use(hiprint); // 如果插件支持Vue3的use语法 // 或者 app.config.globalProperties.$hiprint hiprint; // 另一种方式 app.mount(#app);注意务必确认你安装的vue-plugin-hiprint版本与你的Vue版本兼容。一个常见的坑是在Vue3项目中直接安装默认版本可能导致运行时错误因为内部可能使用了Vue2的API。如果找不到官方Vue3支持可能需要寻找社区分支或考虑其他方案。3.2 设计器与预览器的组件化使用安装完成后你可以在任何Vue组件中使用设计器和预览器。设计器组件用于创建和编辑模板。template div h2打印模板设计器/h2 !-- 设计器组件ref用于获取组件实例以调用其方法 -- vue-plugin-hiprint-design refdesigner :optiondesignerOption saveonTemplateSave / button clickgetTemplateJson保存模板JSON/button /div /template script export default { name: PrintDesigner, data() { return { designerOption: { // 设计器配置如是否显示标尺、网格等 showGrid: true, gridSize: 10 } }; }, methods: { onTemplateSave(templateJson) { // 接收到设计器保存的模板JSON console.log(模板JSON:, templateJson); // 通常这里调用API将templateJson保存到服务器 // this.saveToServer(templateJson); }, getTemplateJson() { // 通过ref主动获取当前模板的JSON const json this.$refs.designer.getJson(); console.log(当前模板JSON:, json); } } }; /script预览/打印组件用于加载模板并填充数据预览。template div h2打印预览/h2 !-- 预览容器hiprint会将内容渲染到此div中 -- div refpreviewContainer stylewidth: 210mm; margin: 0 auto; background: white;/div button clickdoPrint执行打印/button /div /template script import { hiprint } from vue-plugin-hiprint; export default { name: PrintPreview, props: { templateJson: { // 从父组件或API获取的模板JSON type: Object, required: true }, printData: { // 需要打印的业务数据 type: Object, required: true } }, mounted() { this.renderPreview(); }, watch: { // 当模板或数据变化时重新渲染预览 templateJson: { handler: renderPreview, deep: true }, printData: { handler: renderPreview, deep: true } }, methods: { renderPreview() { if (!this.templateJson || !this.$refs.previewContainer) return; // 清空容器 this.$refs.previewContainer.innerHTML ; // 1. 根据模板JSON创建一个打印模板对象 const template new hiprint.PrintTemplate({ template: this.templateJson, }); // 2. 将模板和数据渲染到预览容器 template.print(this.printData, this.$refs.previewContainer); // 保存template实例供打印时使用 this.currentTemplate template; }, doPrint() { if (this.currentTemplate) { // 直接调用打印会弹出浏览器打印对话框 this.currentTemplate.print(this.printData); } } } }; /script4. 可视化设计器深度使用指南4.1 设计器界面与基本操作设计器启动后界面通常分为三栏左侧元素面板分类罗列了所有可拖拽的元素如“基础元素”文本、线条、矩形、“表格元素”普通表格、交叉表格、“条形码元素”支持Code128、QR码等、“图片元素”等。中间画布区域模拟实际纸张如A4、A5、自定义尺寸你从这里拖入的元素位置就是最终打印的位置。支持缩放、标尺、网格对齐。右侧属性面板当选中画布上的某个元素时这里会显示该元素的所有可配置属性如宽度、高度、坐标、字体、颜色、数据字段名等。实操要点纸张设置首先在画布空白处点击在右侧属性面板设置纸张类型、宽度、高度、方向纵向/横向以及页边距。这是所有元素定位的基准。拖拽与定位从左侧拖拽元素到画布通过鼠标拖动调整位置或直接在属性面板输入精确的x、y坐标单位通常是mm或px取决于配置。元素层级与组合后添加的元素会覆盖在先前的元素之上。可以通过右键菜单调整层级上移一层、下移一层、置于顶层、置于底层。对于经常一起使用的元素如“单价”标签和其后面的横线可以右键“组合”方便整体移动。对齐与分布多选元素后可以利用顶部工具栏或右键菜单中的对齐工具左对齐、居中对齐、右对齐、等间距分布快速排版让界面更整齐。4.2 高级元素配置与数据绑定这是hiprint的灵魂所在。每个元素都必须正确配置数据绑定才能实现动态内容打印。文本元素绑定 在文本元素的属性面板找到“标题”或“内容”属性。你可以直接输入静态文本如“收货单”。但更关键的是“字段名”或“数据键”属性。绑定简单字段假设你的数据是{ customerName: ‘张三’ orderNo: ‘SO20231001’ }。你可以拖入两个文本元素一个的字段名设为customerName另一个设为orderNo。预览时这些文本元素就会自动显示“张三”和“SO20231001”。格式化显示hiprint支持在字段名中使用简单的函数或过滤器。例如字段名可以配置为‘totalPrice | toFixed:2’假设你的数据是{ totalPrice: 123.456 }那么打印时会显示“123.46”。这需要你在初始化hiprint时注册对应的格式化函数。表格元素绑定 表格是打印中最复杂的部分。hiprint的表格元素需要绑定一个数组类型的数据。设计表头拖入一个“表格”元素后首先双击表格进入行编辑模式。第一行通常是表头你可以在每个单元格里输入静态文本如“商品名称”、“数量”、“单价”。绑定表格数据在表格元素的属性面板找到“数据源”或“dataset”属性填入你数据中对应数组的字段名例如items。绑定单元格数据在表头下面的数据行通常是第二行的单元格中不再输入静态文本而是输入数据项对象的属性名。假设你的items数组每一项是{ productName: ‘铅笔’ qty: 100 price: 0.5 }那么就在对应单元格的字段名里分别填入productName、qty、price。合计行在表格底部添加一行在“数量”列下方的单元格字段名可以写为‘qty | sum’hiprint会自动计算该列所有数据行的总和。同样需要预先注册sum这个聚合函数。图片与条形码图片图片元素的字段名应绑定到一个图片URL的字段上。数据可以是完整的http://链接也可以是后端返回的Base64字符串。hiprint会自动加载并渲染。条形码/二维码条形码元素通常有一个“条码内容”或“value”属性将其绑定到数据中的对应字段即可如snCode。你可以在属性面板选择条码类型Code128, EAN13, QR Code等和大小。实操心得在设计复杂表格时务必先准备好一份结构清晰的模拟数据。边绑数据边调整表格列宽和行高效率更高。另外表格的样式边框、字体可以在属性面板中统一设置也可以单独设置某个单元格优先级为单元格 行 表格。5. 核心功能实现与自定义扩展5.1 实现“合并某一列所有单元格”等高阶需求网络热词中提到了“hiprint合并某一列所有单元格”这是一个典型的高级需求。例如在送货单中可能有一个“备注”列需要跨所有行合并成一个单元格。hiprint的标准表格元素可能不直接提供跨行合并的UI配置。实现这种效果通常有两种思路思路一使用“自定义元素”功能推荐hiprint允许开发者注册自定义元素。我们可以创建一个“合并单元格”的自定义元素。注册自定义元素在应用初始化时调用hiprint的API注册一个新元素类型。hiprint.registerElementType(‘mergedCell’ function(options, data) { // options是元素的配置data是当前行的数据 // 这个函数需要返回一个包含html和style的对象 // 为了实现合并我们需要计算这个元素应该占据多少行 // 这通常需要访问到整个表格的数据集而不仅仅是当前行数据 // 因此更常见的做法是在表格渲染的回调中处理 });使用渲染后回调更实用的方法是在渲染整个模板后通过JavaScript操作生成的DOM来实现合并。hiprint的打印模板在预览时最终会生成HTML结构。我们可以监听渲染完成事件然后用jQuery或原生JS操作DOM。// 在渲染预览后执行 setTimeout(() { const table document.querySelector(‘#previewContainer .hiprint-table’); // 找到需要合并的列例如第5列 const rows table.rows; let mergeStartRow 1; // 从第2行开始索引1假设第1行是表头 let mergeContent rows[mergeStartRow].cells[4].innerText; // 获取内容 for (let i mergeStartRow 1; i rows.length; i) { // 清空后续行该列的内容并设置rowspan rows[mergeStartRow].cells[4].rowSpan (rows[mergeStartRow].cells[4].rowSpan || 1) 1; rows[i].cells[4].style.display ‘none’; // 或者直接移除单元格 } rows[mergeStartRow].cells[4].innerText mergeContent; // 设置合并后的内容 }, 100); // 稍作延迟确保DOM渲染完毕注意直接操作DOM的方式虽然灵活但依赖于hiprint内部生成的HTML结构如果库版本更新导致结构变化代码可能需要调整。务必做好注释和版本控制。思路二设计时规避如果合并逻辑是固定的如“备注”列永远合并可以在设计模板时就不使用标准表格。而是将表格拆分为两部分第一部分用标准表格打印商品明细行不需要备注列。第二部分在表格下方单独放置一个大的“多行文本”元素来显示备注内容。 这种方式更简单稳定但失去了表格的自动行高扩展等特性。5.2 自定义打印样式与CSS注入虽然hiprint主要用Canvas和内部样式渲染但它也支持注入自定义CSS来影响最终打印输出的样式。const template new hiprint.PrintTemplate({ template: templateJson, setting: { // 自定义CSS style: media print { .hiprint-element-text { font-family: ‘SimSun’, serif !important; /* 打印时强制使用宋体 */ } .hiprint-table td { border-color: #333 !important; } } /* 非打印时的预览样式 */ .hiprint-preview { box-shadow: 0 0 10px rgba(0,0,0,0.1); } } });这对于统一字体、调整边框颜色等全局样式微调非常有用。但要注意其优先级可能低于元素内联样式且不是所有属性都能被覆盖。5.3 注册自定义函数过滤器如前所述在字段绑定中使用‘price | toFixed:2’这样的语法需要先注册toFixed函数。// 在初始化hiprint时或任何模板渲染前 hiprint.init({ providers: [ { // 定义一个提供者可以包含多个函数 name: ‘common’, functions: { toFixed: function(value, decimals) { if (value null) return ‘’; return Number(value).toFixed(decimals || 2); }, sum: function(columnName, dataset) { // dataset是当前表格绑定的整个数组 if (!Array.isArray(dataset)) return 0; return dataset.reduce((sum, item) sum (Number(item[columnName]) || 0) 0); } } } ] });在模板JSON中绑定字段时就可以写‘price | toFixed:2’或‘qty | sum’后者通常在表格合计行使用且需要能访问到dataset具体语法需参考官方文档。6. 与Vue2/Vue3特性的深度结合6.1 在Vue2中的响应式集成在Vue2中我们可以利用计算属性(computed)和侦听器(watch)来优雅地管理模板JSON和打印数据。template div button clickloadTemplate加载模板/button button clickloadData加载数据/button div refpreviewContainer/div /div /template script import { hiprint } from ‘vue-plugin-hiprint’; export default { data() { return { currentTemplate: null, templateJson: null, // 从API加载的模板JSON printData: {}, // 从API加载的业务数据 // 我们可以根据业务数据动态计算一些打印字段 computedPrintFields: {} }; }, computed: { // 计算属性将原始数据与计算字段合并形成最终的打印数据源 finalPrintData() { return { …this.printData, …this.computedPrintFields }; } }, watch: { // 深度监听模板或数据变化自动重新渲染预览 templateJson: { handler: function(newVal) { if (newVal) { this.renderPreview(); } }, deep: true }, finalPrintData: { handler: function() { if (this.currentTemplate this.$refs.previewContainer) { // 仅更新数据重新渲染 this.currentTemplate.update(this.finalPrintData, this.$refs.previewContainer); } }, deep: true } }, methods: { async loadTemplate() { const resp await this.$http.get(‘/api/print-template/1’); this.templateJson resp.data; }, async loadData() { const resp await this.$http.get(‘/api/order/123’); this.printData resp.data; // 基于业务数据计算一些额外字段 this.computedPrintFields { grandTotal: this.printData.items.reduce((sum, item) sum item.qty * item.price, 0), formattedDate: new Date().toLocaleDateString(‘zh-CN’) }; }, renderPreview() { if (!this.templateJson || !this.$refs.previewContainer) return; this.$refs.previewContainer.innerHTML ‘’; this.currentTemplate new hiprint.PrintTemplate({ template: this.templateJson, }); this.currentTemplate.print(this.finalPrintData, this.$refs.previewContainer); } } }; /script这种模式将数据准备、计算和渲染分离符合Vue2的响应式哲学代码清晰易维护。6.2 在Vue3中的Composition API集成Vue3的Composition API提供了更灵活的代码组织方式。我们可以将hiprint的核心功能封装成一个可复用的Composable函数。template div button clickloadAndRender加载并渲染/button div refpreviewContainer/div /div /template script setup import { ref, computed, watch, onMounted, onUnmounted } from ‘vue’; import { hiprint } from ‘vue-plugin-hiprint’; // 假设已正确安装Vue3版本 // 1. 定义响应式数据 const previewContainer ref(null); const templateJson ref(null); const apiData ref({ id: 123 items: [] }); const currentTemplate ref(null); // 2. 使用计算属性处理打印数据 const finalPrintData computed(() { const data apiData.value; if (!data.items) return data; const total data.items.reduce((sum, item) sum (item.qty || 0) * (item.price || 0), 0); return { …data, _computed: { // 将计算字段放在一个独立对象里避免污染原数据 grandTotal: total.toFixed(2), itemCount: data.items.length } }; }); // 3. 渲染函数 const renderPreview () { if (!templateJson.value || !previewContainer.value) return; previewContainer.value.innerHTML ‘’; currentTemplate.value new hiprint.PrintTemplate({ template: templateJson.value, }); currentTemplate.value.print(finalPrintData.value, previewContainer.value); }; // 4. 监听数据变化自动更新预览使用watchEffect watch([() templateJson.value, () finalPrintData.value], () { if (currentTemplate.value previewContainer.value) { // 使用update方法进行高效更新而非重新创建整个模板 currentTemplate.value.update(finalPrintData.value, previewContainer.value); } }, { deep: true }); // 5. 模拟加载数据 const loadAndRender async () { // 模拟API调用 const [templateResp, dataResp] await Promise.all([ fetch(‘/api/template/1’).then(r r.json()), fetch(‘/api/order/123’).then(r r.json()) ]); templateJson.value templateResp; apiData.value dataResp; // 首次渲染 if (!currentTemplate.value) { renderPreview(); } }; // 6. 生命周期 onMounted(() { // 可以初始化一些默认模板 }); onUnmounted(() { // 清理资源防止内存泄漏 if (currentTemplate.value) { currentTemplate.value.destroy(); } }); /script使用script setup和Composition API逻辑关注点更加集中响应式数据流也一目了然。将打印功能抽象成自定义Hook如useHiprint的潜力也更大。7. 常见问题排查与性能优化7.1 典型问题与解决方案速查表问题现象可能原因排查步骤与解决方案设计器无法加载白屏或报错1. 插件未正确注册或版本不兼容。2. 依赖的静态资源如JS、CSS路径错误或未加载。1. 检查浏览器控制台F12的报错信息。2. 确认vue-plugin-hiprint版本与Vue版本匹配。3. 如果是CDN引入检查资源URL是否可达。拖拽元素到画布无反应1. 画布未正确初始化或尺寸为0。2. 元素拖拽区域被其他DOM元素遮挡。1. 确保设计器组件已成功挂载到DOM中。2. 检查设计器容器的CSS确保其有明确的宽度和高度且position不为static。预览内容空白1. 模板JSON格式错误或为空。2. 打印数据与模板字段名不匹配。3. 预览容器DOM未找到或已被销毁。1. 打印templateJson和printData到控制台检查数据结构。2. 确认字段名大小写完全一致。3. 在mounted或onMounted生命周期后再执行渲染。打印对话框弹出但内容缺失或样式错乱1. 浏览器打印样式media print覆盖了hiprint的样式。2. 使用了不支持的CSS属性。3. 图片或字体未加载完成。1. 检查应用全局CSS中是否有强力的media print样式尝试暂时禁用。2. 尽量使用hiprint元素自带的样式属性进行设置。3. 对于图片确保URL可访问或使用Base64内嵌。表格数据过多渲染卡顿或内存溢出1. 一次性渲染数据量过大如超过1000行。2. 表格内嵌了过多复杂元素或图片。1.分页打印在模板中设置好分页利用hiprint的自动分页功能。2.数据分片业务上考虑分批打印或后端进行分页处理。3.简化模板减少不必要的装饰性元素。条形码/二维码渲染不出来1. 数据字段值为空或格式不正确。2. 选择的条码类型与数据不匹配如EAN13需要13位数字。3. 条码渲染库加载失败。1. 检查绑定字段的数据值。2. 查阅条码规范确保数据符合所选类型要求。3. 查看网络请求确认条码生成所需的JS库是否成功加载。保存的模板JSON再次加载后样式不对1. 模板JSON在传输或存储过程中被意外修改。2. hiprint版本升级导致模板格式不兼容。1. 对比前后两次生成的JSON字符串使用JSON比对工具。2. 将模板JSON进行版本化管理升级hiprint时注意测试旧模板兼容性。7.2 性能优化与最佳实践模板管理版本化模板JSON应保存在后端数据库并带有版本号。这样在升级hiprint库或修改模板格式时可以平滑迁移。分类与复用建立模板分类如“销售单据”、“物流标签”对于公共部分如公司Logo、页眉页脚可以设计成子模板或片段通过引用的方式复用减少重复设计。数据准备预处理尽量在后端或Vue的计算属性中将数据预处理成打印模板最需要的格式避免在模板中使用复杂的函数计算。图片优化打印模板中的图片特别是Logo建议使用SVG矢量格式或经过压缩的WebP/PNG格式。如果使用Base64注意字符串长度过长的Base64字符串会显著增大模板JSON和数据体积。渲染优化延迟渲染如果页面有多个打印预览区域不要一次性全部渲染。可以使用v-if或Intersection Observer API实现懒加载当用户滚动到附近时再渲染。销毁实例在Vue组件的beforeUnmount或onUnmounted生命周期中主动调用template.destroy()方法清理内部事件监听器和DOM引用防止内存泄漏。打印体验静默打印对于高频、固定的打印任务如仓库连续打单可以研究浏览器的“静默打印”特性但这通常需要浏览器特定配置或插件支持且用户体验需谨慎权衡。批量打印如果需要连续打印多份不同数据的单据可以循环调用template.print(data)但注意处理浏览器打印队列的弹窗阻塞问题。一种折中方案是生成一个包含所有页面的PDF这可能需要后端配合或使用html2canvasjspdf库在前端合成然后一次性打印这个PDF。8. 项目实战构建一个简单的订单打印模块让我们串联以上所有知识在一个假设的Vue3订单管理后台中实现一个完整的打印功能模块。需求用户可以在订单详情页点击“打印送货单”按钮弹出一个模态框。模态框内左侧是设计好的打印模板预览右侧可以调整一些参数如打印份数点击“打印”按钮调用系统打印机。步骤实现组件结构OrderDetail.vue └── PrintOrderModal.vue (模态框组件) ├── PrintTemplateDesigner.vue (设计器组件可选) ├── PrintPreview.vue (预览组件) └── PrintConfigPanel.vue (配置面板)PrintOrderModal.vue 核心代码片段template el-dialog title“打印送货单” v-model“visible” width“90%” div class“print-modal-container” div class“preview-area” PrintPreview :template-id“defaultTemplateId” :order-data“currentOrder” ref“previewRef” / /div div class“config-area” PrintConfigPanel config-change“handleConfigChange” / el-button type“primary” click“handlePrint”打印/el-button el-button click“handlePrintPreview”打印预览(PDF)/el-button /div /div /el-dialog /template script setup import { ref } from ‘vue’; import PrintPreview from ‘./PrintPreview.vue’; import PrintConfigPanel from ‘./PrintConfigPanel.vue’; const props defineProps({ orderData: Object }); const visible ref(false); const previewRef ref(null); const defaultTemplateId ‘delivery_note_v1’; // 从配置或用户偏好中读取 const printConfig ref({ copies: 1 printer: ‘default’ }); const handleConfigChange (config) { printConfig.value config; // 可以基于配置重新渲染预览例如改变打印份数在模板上的显示 }; const handlePrint () { if (previewRef.value previewRef.value.getTemplate()) { // 调用预览组件暴露的打印方法 previewRef.value.printDirectly(printConfig.value.copies); } }; const handlePrintPreview async () { // 生成PDF预览这里可能需要集成html2canvas和jspdf // const pdfBlob await previewRef.value.exportToPdf(); // window.open(URL.createObjectURL(pdfBlob)); }; defineExpose({ open: () visible.value true }); /scriptPrintPreview.vue 核心增强script setup import { ref, onMounted, watch } from ‘vue’; import { hiprint } from ‘vue-plugin-hiprint’; import { getPrintTemplateById } from ‘/api/print’; const props defineProps({ templateId: String, orderData: Object }); const previewContainer ref(null); const currentTemplate ref(null); const templateJson ref(null); const loadTemplate async () { const resp await getPrintTemplateById(props.templateId); templateJson.value resp.data; }; const render () { if (!templateJson.value || !previewContainer.value) return; previewContainer.value.innerHTML ‘’; currentTemplate.value new hiprint.PrintTemplate({ template: templateJson.value, setting: { pageWidth: ‘210mm’, pageHeight: ‘297mm’, } }); currentTemplate.value.print(props.orderData, previewContainer.value); }; const printDirectly (copies 1) { if (!currentTemplate.value) return; // hiprint可能不支持直接设置份数份数通常在浏览器打印对话框中设置 // 这里可以循环调用但会弹出多次对话框 for (let i 0; i copies; i) { // 注意简单的循环会连续弹出多个打印对话框体验不好。 // 对于多份打印更好的方式是生成一个包含多页的PDF或让打印机驱动处理份数。 setTimeout(() currentTemplate.value.print(props.orderData), i * 300); } }; const getTemplate () currentTemplate.value; onMounted(loadTemplate); watch(() props.templateId, loadTemplate); watch(() props.orderData, () { if (currentTemplate.value previewContainer.value) { currentTemplate.value.update(props.orderData, previewContainer.value); } }, { deep: true }); defineExpose({ printDirectly, getTemplate }); /script这个实战案例展示了如何将hiprint嵌入到一个真实的业务场景中并考虑了组件化、状态管理和用户体验。关键在于将打印功能模块化并通过清晰的接口props/events/expose与父组件通信。最后关于网络热词中提到的其他Vue2/Vue3问题如“vue2 watch handle”、“vue3 computed”、“defineemits vue3”等它们都是Vue框架本身的核心概念。在集成hiprint时熟练运用这些特性如用watch监听数据变化触发重新渲染用computed处理打印数据用defineEmits向上传递打印完成事件能让你的代码更加健壮和优雅。hiprint本身是一个功能强大的工具但将其威力完全发挥出来离不开你对Vue框架本身的深入理解和灵活运用。本文还有配套的精品资源点击获取
返回列表