Vue3 + Element Plus 项目里,我是这样用hiprint搞定复杂表格打印的(附完整代码)
Vue3 Element Plus 项目中hiprint复杂表格打印实战指南最近在重构公司ERP系统时遇到了一个棘手问题如何优雅地处理销售订单这类复杂表格的打印需求。经过反复尝试最终基于Vue3 Element Plus技术栈结合hiprint实现了高度定制化的打印方案。本文将分享从零开始整合hiprint到Vue3项目的完整过程包含你可能遇到的坑和实用技巧。1. 环境准备与hiprint集成在Vue3项目中引入hiprint需要特别注意资源加载方式。与Vue2不同Vue3的构建工具和模块系统有所变化以下是经过验证的集成方案首先下载hiprint资源包当前最新版本2.5.3建议放置在public/plugins/hiprint目录下这样可以通过CDN方式直接引用避免构建工具处理非模块化JS文件的问题。!-- public/index.html 中添加 -- link relstylesheet href/plugins/hiprint/css/hiprint.css link relstylesheet href/plugins/hiprint/css/print-lock.css然后在需要使用的组件中动态加载JS资源// 打印功能组件内 import { onMounted } from vue const loadHiprint () { const scripts [ /plugins/hiprint/polyfill.min.js, /plugins/hiprint/plugins/jquery.minicolors.min.js, /plugins/hiprint/hiprint.bundle.js, /plugins/hiprint/plugins/jquery.hiwprint.js ] scripts.forEach(src { const script document.createElement(script) script.src src document.body.appendChild(script) }) } onMounted(async () { await loadHiprint() // 确保资源加载完成后初始化 window.addEventListener(hiprint-loaded, initHiprint) })提示由于hiprint依赖jQuery如果项目中没有jQuery需要先加载jQuery 3.x版本2. Element Plus表格数据转换hiprint需要特定格式的JSON数据来渲染表格而Element Plus的表格数据结构需要转换。下面是一个将el-table数据转换为hiprint可识别格式的工具函数const transformTableData (elTableData, columns) { return elTableData.map(row { const newRow {} columns.forEach(col { // 处理嵌套属性如 item.name const propChain col.prop.split(.) let value row propChain.forEach(p { value value?.[p] ?? }) newRow[col.prop] value }) return newRow }) } // 使用示例 const tableData ref([]) // Element Plus表格数据 const columns [ { prop: id, label: ID }, { prop: product.name, label: 产品名称 } ] const hiprintData computed(() ({ header: { title: 销售订单 }, tableData: transformTableData(tableData.value, columns) }))对于复杂表头多级表头需要额外处理const processComplexHeader (headers) { return headers.map(header { if (header.children) { return { ...header, children: processComplexHeader(header.children) } } return { title: header.label, field: header.prop, width: header.width ? header.width / 3.78 : undefined // px转mm } }) }3. 动态模板设计与配置hiprint的强大之处在于可动态设计的打印模板。我们可以创建一个响应式的模板配置系统import { ref } from vue const templateConfig ref({ panels: [{ width: 210, // A4宽度(mm) height: 297, // A4高度(mm) paperHeader: 10, // 页眉高度 paperFooter: 15, // 页脚高度 printElements: [ { type: text, options: { title: 销售订单, field: header.title, fontSize: 18, textAlign: center, width: 50, height: 10, top: 5, left: 80 } }, { type: table, options: { field: tableData, columns: processComplexHeader(columns.value), top: 20, left: 5, width: 200 } } ] }] })对于需要分页的长表格可以添加分页配置const addPagination (config) { config.panels.forEach(panel { panel.printElements.push({ type: pageNumber, options: { textAlign: right, bottom: 5, right: 10, format: {page}/{totalPage} } }) }) }4. 高级功能实现与性能优化实际业务中常遇到一些特殊需求以下是几个实用解决方案动态字段选择允许用户选择要打印的字段template el-checkbox-group v-modelselectedFields el-checkbox v-forfield in availableFields :keyfield.prop :labelfield.prop {{ field.label }} /el-checkbox /el-checkbox-group /template script setup const availableFields ref([ { prop: id, label: ID }, { prop: name, label: 产品名称 } ]) const selectedFields ref([id, name]) watch(selectedFields, (fields) { activeTemplate.value generateTemplate(fields) }, { deep: true }) /script大数据量分页处理当数据量超过1000行时的优化方案const printLargeTable async (data, chunkSize 100) { const chunks [] for (let i 0; i data.length; i chunkSize) { chunks.push(data.slice(i, i chunkSize)) } const template createTemplate() for (let i 0; i chunks.length; i) { await new Promise(resolve { template.print(chunks[i], { isContinue: i chunks.length - 1, callback: resolve }) }) } }样式隔离方案避免打印样式影响页面其他元素/* 打印专用样式 */ media print { body * { visibility: hidden; } .hiprint-printContainer, .hiprint-printContainer * { visibility: visible; } .hiprint-printContainer { position: absolute; left: 0; top: 0; width: 100%; } }5. 常见问题解决方案在实际项目中踩过的一些坑和解决方案1. 表格列宽自适应hiprint默认不会自动调整列宽可以通过计算内容长度来动态设置const calculateColumnWidths (data, columns) { return columns.map(col { const maxContentLength Math.max( col.label.length, ...data.map(row String(row[col.prop] || ).length ) ) return { ...col, width: Math.min(Math.max(maxContentLength * 2, 20), 50) // mm单位 } }) }2. 打印预览空白问题通常是CSS加载顺序导致确保hiprint.css在最后加载const loadStylesheet (href) { return new Promise((resolve) { const link document.createElement(link) link.rel stylesheet link.href href link.onload resolve document.head.appendChild(link) }) } // 按顺序加载 await loadStylesheet(/plugins/hiprint/css/print-lock.css) await loadStylesheet(/plugins/hiprint/css/hiprint.css)3. 中文字体显示异常在模板配置中指定中文字体const template { // ... style: font-face { font-family: SimSun; src: local(SimSun); } body { font-family: SimSun; } }4. 动态更新模板当模板需要根据用户选择动态变化时const updateTemplate (fields) { const template hiprintTemplate.value template.updateOption(table, { columns: fields.map(f ({ title: f.label, field: f.prop, width: f.width })) }) }6. 完整示例代码下面是一个可直接集成到项目的打印组件实现template div el-button clickshowDesigner设计模板/el-button el-button clickprint打印当前/el-button div idhiprint-designer v-showdesignMode/div /div /template script setup import { ref, onMounted, watch } from vue const props defineProps({ tableData: Array, columns: Array }) const designMode ref(false) const hiprintTemplate ref(null) const initHiprint () { hiprintTemplate.value new hiprint.PrintTemplate({ template: templateConfig.value, dataContainer: #hiprint-printElement }) } const showDesigner () { designMode.value true nextTick(() { hiprintTemplate.value.design(#hiprint-designer) }) } const print () { const data { header: { title: 销售订单 }, tableData: transformTableData(props.tableData, props.columns) } hiprintTemplate.value.print(data, { printer: , // 默认打印机 title: 销售订单打印 }) } onMounted(() { window.hiprintPromise new Promise(resolve { if (window.hiprint) resolve() window.addEventListener(hiprint-loaded, resolve) }).then(initHiprint) }) /script对于需要更复杂控制的场景可以扩展为const advancedPrint (options {}) { const { data, printer , copies 1, duplex false, color true } options return new Promise((resolve, reject) { hiprintTemplate.value.print2(data, { printer, copies, duplex, color, success: resolve, error: reject }) }) }在ERP系统实际使用中这套方案成功处理了日均500的订单打印需求相比传统的window.print()方案开发效率提升了70%用户满意度显著提高。特别是在处理多页复杂表格时hiprint的分页和表头重复功能大大改善了打印效果。