news 2026/4/27 17:54:27

Vue3 + Element Plus 项目里,我是这样用hiprint搞定复杂表格打印的(附完整代码)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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 rel="stylesheet" href="/plugins/hiprint/css/hiprint.css"> <link rel="stylesheet" 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-model="selectedFields"> <el-checkbox v-for="field in availableFields" :key="field.prop" :label="field.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 @click="showDesigner">设计模板</el-button> <el-button @click="print">打印当前</el-button> <div id="hiprint-designer" v-show="designMode"></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的分页和表头重复功能大大改善了打印效果。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/27 17:53:26

开源聊天历史管理工具:AI对话数据存储、检索与向量搜索实践

1. 项目概述&#xff1a;一个开源聊天历史管理工具最近在折腾本地大模型应用的时候&#xff0c;我发现了一个挺普遍但又容易被忽视的问题&#xff1a;聊天历史的管理。无论是用LangChain、LlamaIndex这类框架&#xff0c;还是自己写个简单的对话应用&#xff0c;聊天的记录怎么…

作者头像 李华
网站建设 2026/4/27 17:52:20

解密OpenHand机械手:从实验室原型到工业级抓取系统的实战演进

解密OpenHand机械手&#xff1a;从实验室原型到工业级抓取系统的实战演进 【免费下载链接】openhand-hardware CAD files for the OpenHand hand designs 项目地址: https://gitcode.com/gh_mirrors/op/openhand-hardware 面对机器人抓取任务中的自适应挑战&#xff0c;…

作者头像 李华
网站建设 2026/4/27 17:48:54

高性能渲染Corona 11.2 for C4D全流程下载与安装指南

如你所知&#xff0c;Chaos Corona‌是一款物理真实感3D渲染引擎‌&#xff0c;主要用于建筑可视化、影视动画、产品设计等领域。它以 ‌易用性、高渲染质量和高效性‌ 为核心优势&#xff0c;支持3ds Max‌和Cinema 4D‌等主流三维软件作为插件使用。 目前比较常用的版本为Co…

作者头像 李华
网站建设 2026/4/27 17:48:00

AI代码治理平台Packmind:统一团队规范,提升AI编码助手效能

1. 项目概述&#xff1a;一个为AI编码助手打造的“工程剧本” 如果你和我一样&#xff0c;每天都在和GitHub Copilot、Claude Code、Cursor这些AI编码助手打交道&#xff0c;那你肯定也经历过这种“甜蜜的烦恼”&#xff1a;助手很聪明&#xff0c;但写出来的代码总感觉“味儿…

作者头像 李华
网站建设 2026/4/27 17:46:58

羲语言解数学题之一

网友提出一个数学题&#xff0c;原起是一个智力题&#xff0c;原题是这样的&#xff1a;真假金币&#xff0d;有十袋金币&#xff0c;每一枚金币重10&#xff27;。其中有一袋金币是假金币&#xff0c;每枚重量仅9&#xff27;。有一把电子秤&#xff0c;怎样称一次就知道哪袋金…

作者头像 李华