- A+
vue-plugin-hiprint的学习与应用
? 生命不息,写作不止
? 继续踏上学习之路,学之分享笔记
? 总有一天我也能像各位大佬一样
? 一个有梦有戏的人 @怒放吧德德
?分享学习心得,欢迎指正,大家一起学习成长!
生命不息,写作不止,养成良好的学习精神!
简介
本文介绍对vue-plugin-hiprint部分重要代码的解析,这是一个很好的开源插件,能够自己自定义打印模板,通过后端传来的数据进行渲染打印,官方也提供了许多的api供开发者使用。界面采用了antdesign。实现了免预览的直接打印。
github:https://github.com/CcSimple/vue-plugin-hiprint
print.io官网:http://hiprint.io/demo
引入插件:
jsbarcode:
npm install jsbarcode --save
socket.io:
npm install socket.io
jspdf:
npm install jspdf --save
代码简单介绍
面板
分别是:拖拽组件、画布、属性栏
<a-row :gutter="[8,0]"> <a-col :span="4"> <a-card style="height: 100vh"> <a-row> <a-col :span="24" class="rect-printElement-types hiprintEpContainer"> </a-col> </a-row> </a-card> </a-col> <a-col :span="14"> <a-card class="card-design"> <div id="hiprint-printTemplate" class="hiprint-printTemplate"></div> </a-card> </a-col> <a-col :span="6" class="params_setting_container"> <a-card> <a-row class="hinnn-layout-sider"> <div id="PrintElementOptionSetting"></div> </a-row> </a-card> </a-col> </a-row>
初始化
在挂载中调用初始化
mounted() { this.init() this.otherPaper() },
其中初始化方法:
init() { // 左边设计模板的选择 this.modeList = providers.map((e) => { return {type: e.type, name: e.name, value: e.value} }) this.changeMode() }, changeMode() { // 数据渲染 let {mode} = this let provider = providers[mode] console.log("provider", provider) hiprint.init({ providers: [provider.f] }); $('.hiprintEpContainer').empty() hiprint.PrintElementTypeManager.build('.hiprintEpContainer', provider.value); $('#hiprint-printTemplate').empty() let templates = this.$ls.get('KEY_TEMPLATES', {}) // 从本地获取数据 console.log("getTemplates", templates) let template = templates[provider.value] ? templates[provider.value] : {} hiprintTemplate = new hiprint.PrintTemplate({ template: template, // panels: [{...}] dataMode: 1, // 1:getJson 其他:getJsonTid 默认1 history: true, // 是否需要 撤销重做功能 onDataChanged: (type, json) => { console.log(type); // 新增、移动、删除、修改(参数调整)、大小、旋转 console.log(json); // 返回 template // 更新模板 hiprintTemplate.update(json) // console.log(hiprintTemplate.historyList) }, settingContainer: '#PrintElementOptionSetting', paginationContainer: '.hiprint-printPagination' }); hiprintTemplate.design('#hiprint-printTemplate'); console.log('hiprintTemplate', hiprintTemplate); // 获取当前放大比例, 当zoom时传true 才会有 this.scaleValue = hiprintTemplate.editingPanel.scale || 1; },
设置纸张大小
otherPaper() { let value = {} value.width = this.paperWidth value.height = this.paperHeight this.paperPopVisible = false this.setPaper('other', value) }, /** * 设置纸张大小 * @param type [A3, A4, A5, B3, B4, B5, other] * @param value {width,height} mm */ setPaper(type, value) { try { if (Object.keys(this.paperTypes).includes(type)) { this.curPaper = {type: type, width: value.width, height: value.height} hiprintTemplate.setPaper(value.width, value.height) } else { this.curPaper = {type: 'other', width: value.width, height: value.height} hiprintTemplate.setPaper(value.width, value.height) } } catch (error) { this.$message.error(`操作失败: ${error}`) } },
通过生命周期activated来解决切换模板的时候还能拖拽,并且不会被清除
activated() { // 重新再实例化, 处理切换demo, 无法拖拽问题 if (this.deactivated) { this.changeMode(); this.deactivated = false; } }, deactivated() { this.deactivated = true; },
预览
封装的预览vue界面
将模板和数据用HTML的方法转化赋值 $('#preview_content_custom').html(hiprintTemplate.getHtml(printData))
<template> <a-modal :visible="visible" :maskClosable="false" @cancel="hideModal" :width="width+'mm'"> <a-spin :spinning="spinning" style="min-height: 100px"> <div id="preview_content_custom"></div> </a-spin> <template slot="title"> <a-space> <div style="margin-right: 20px">打印预览</div> <a-button :loading="waitShowPrinter" type="primary" icon="printer" @click.stop="print">打印</a-button> <a-button type="primary" icon="printer" @click.stop="toPdf">pdf</a-button> </a-space> </template> <template slot="footer"> <a-button key="close" type="info" @click="hideModal"> 关闭 </a-button> </template> </a-modal> </template> <script> export default { name: "printPreview", props: {}, data() { return { visible: false, spinning: true, waitShowPrinter: false, // 纸张宽 mm width: 0, // 模板 hiprintTemplate: {}, // 数据 printData: {} } }, computed: {}, watch: {}, created() { }, mounted() { }, methods: { hideModal() { this.visible = false }, show(hiprintTemplate, printData, width = '210') { this.visible = true this.spinning = true this.width = width this.hiprintTemplate = hiprintTemplate this.printData = printData setTimeout(() => { // eslint-disable-next-line no-undef $('#preview_content_custom').html(hiprintTemplate.getHtml(printData)) this.spinning = false }, 500) }, print() { this.waitShowPrinter = true this.hiprintTemplate.print(this.printData, {}, { callback: () => { this.waitShowPrinter = false } }) }, toPdf() { this.hiprintTemplate.toPdf(this.printData, '打印预览pdf'); }, } } </script> <style lang="less" scoped> /deep/ .ant-modal-body { padding: 0px; } /deep/ .ant-modal-content { margin-bottom: 24px; } </style>
直接打印
直接打印需要安装桌面插件,window.hiwebSocket.opened是为了判断socketIo是否打开,hiprintTemplate中的print2是直接打印,print是会显示预览的打印。直接打印在printIo底层会自动去连接客户端,以及传输数据。
print() { if (window.hiwebSocket.opened) { const printerList = hiprintTemplate.getPrinterList(); console.log(printerList) // 打印机列表数据 console.log('printData', printData) // 数据源 hiprintTemplate.print2(printData, {printer: '', title: 'hiprint测试直接打印'}); return } this.$message.error('客户端未连接,无法直接打印') },
批量打印
批量打印就是采用队列打印的方式,通过TaskRunner 任务进程管理,在通过for循环收集数据去打印。
batPrint() { // 批量打印 if (window.hiwebSocket.opened) { const printerList = hiprintTemplate.getPrinterList(); console.log(printerList) // 打印机列表 this.tasksPrint() return } this.$message.error('客户端未连接,无法直接打印') }, tasksPrint() { // 队列打印 const runner = new TaskRunner(); runner.setConcurrency(1); // 同时执行数量 const task = [] let that = this const tasksKey = `open${Date.now()}`; for (let i = 0; i < testDatas.table.length; i++) { // 循环数据 // done -> 任务完成回调 let key = `task${i}`; task.push(done => { let printData = { testChinese: testDatas.table[i].testChinese, testEnglish: testDatas.table[i].testEnglish } // 动态数据 console.log('printData', printData) that.realPrint(runner, done, key, i, printData, tasksKey) }) } runner.addMultiple(task) this.openNotification(runner, tasksKey) }, realPrint(runner, done, key, i, printData, tasksKey) { let that = this that.$notification.info({ key: key, placement: 'topRight', duration: 2.5, message: `正在准备打印第 ${i} 张`, description: '队列运行中...', }); let template = that.$ls.get('KEY_TEMPLATES', {}) // 外層還有個模板名包裹 let hiprintTemplate = new hiprint.PrintTemplate({ template: template.aProviderModule, }); hiprintTemplate.print2(printData, {printer: '', title: key}); hiprintTemplate.on('printSuccess', function () { let info = runner.tasks.list.length > 1 ? '准备打印下一张' : '已完成打印' that.$notification.success({ key: key, placement: 'topRight', message: key + ' 打印成功', description: info, }); done() if (!runner.isBusy()) { that.$notification.close(tasksKey) } }) hiprintTemplate.on('printError', function () { that.$notification.close(key) done() that.$message.error('打印失败,已加入重试队列中') runner.add(that.realPrint(runner, done, key, i, printData)) }) }, openNotification(runner, tasksKey) { let that = this; that.$notification.open({ key: tasksKey, message: '队列运行中...', duration: 0, placement: 'topLeft', description: '点击关闭所有任务', btn: h => { return h( 'a-button', { props: { type: 'danger', size: 'small', }, on: { click: () => { that.$notification.close(tasksKey); // 详情请查阅文档 runner.removeAll(); that.$message.info('已移除所有任务'); }, }, }, '关闭任务', ); }, }); }
保存JSON数据
只要调用apihiprintTemplate.getJson()
saveJson() { if (hiprintTemplate) { const jsonOut = JSON.stringify(hiprintTemplate.getJson() || {}) console.log(jsonOut) } },
自定义组件
封装js中,使用addPrintElementTypes方法添加自定义的组件,可以查看print.io官方文档来配置参数。通过控制台输入window.HIPRINT_CONFIG可以查看配置参数名。
new hiprint.PrintElementTypeGroup("自定义表格1", [ { tid: 'aProviderModule.customText1', title: '表格标题', customText: '自定义文本', custom: true, width: 120, type: 'text', options: { height: 31.5, hideTitle: true, field: 'testEnglish', fontSize: 20.25, color: '#000000', backgroundColor: '#ffffff', textAlign: 'center', textContentVerticalAlign: 'middle', lineAlign: 'center', borderLeft: 'solid', borderTop: 'solid', borderRight: 'solid', borderBottom: 'solid' } }, { tid: 'aProviderModule.customText2', title: '表格内容', customText: '自定义文本', custom: true, width: 120, type: 'text', options: { hideTitle: true, field: 'testChinese', height: 31.5, fontSize: 20.25, color: '#000000', backgroundColor: '#ffffff', textAlign: 'center', textContentVerticalAlign: 'middle', lineAlign: 'center', borderLeft: 'solid', borderTop: 'solid', borderRight: 'solid', borderBottom: 'solid' } }, ]),
?创作不易,如有错误请指正,感谢观看!记得点个赞哦!?