当前位置: 首页 > news >正文

Vue3+TypeScript+printjs 实现标签批量打印功能

前言:临时性需求没怎么接触过前端,代码实现有问题及优化点希望大佬可以留言告知一下

开发工具:VS CODE

界面开发:Vue3+TypeScript+ElementPlus

打印组件:Print-JS

前端打印入口图:

标签页面:

打印界面:

实现功能:前端点击"打印标签"弹出打印界面进行打印作业

实现过程:主界面点击"打印标签"调用el-dialog弹窗(预览和直接打印都居于弹窗实现)

  标签模板代码:

<template><div class="LabelPrint-List"><el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" width="50%" ><template #header><div style="color: #fff"><el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Edit/> </el-icon><span>标签打印界面</span></div></template><el-row :gutter="10"><el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb10"><div v-for="item in state.Datas"><el-card class="box-card" style="width:100mm; height: 90mm;display: block;" ><div :id='item.id?.toString()'><!-- print-js --><div class="labelHeadBody"><div class="labelHeadBodyLeftHead"><img class="labelHeadBodyLeftHeadimage"  src="/image/点金log.png" fit="fill" /></div><div class="labelHeadBodyRightHead"><table class="tableHead"><tr><td class="labelHeadBodyRightHeadTd">某某有限公司</td></tr><tr><td class="labelHeadBodyRightHeadTd">物料标识卡</td></tr></table></div></div><div class="labelBody"><table><tbody><tr><td class="lableBodytdleft">P/N:</td><td class="lableBodytdright">{{ item.produceNo }}</td></tr><tr><td class="lableBodytdleft">数量:</td><td class="lableBodytdright">{{ item.quantity }}</td></tr><tr><td class="lableBodytdleft">规格:</td><td class="lableBodytdright lableBodytdrightfont">{{ item.platingSpecs }}</td></tr><tr><td class="lableBodytdleft">供应商:</td><td class="lableBodytdright">东莞点金</td></tr><tr><td class="lableBodytdleft">生产日期:</td><td class="lableBodytdright">{{moment(String(item.createTime)).format('YYYY/MM/DD')}}</td></tr><tr><td class="lableBodytdleft">批次单号:</td><td class="lableBodytdright">{{ item.lot }}</td></tr><tr><td class="lableBodytdleft">单重:</td><td class="lableBodytdright">{{ item.singleWeight }}</td></tr><tr><td class="lableBodytdleft">总重:</td><td class="lableBodytdright">{{ item.sumWeight }}</td></tr><tr><td class="lableBodytdleft">标识人:</td><td class="lableBodytdright"></td></tr></tbody></table></div></div></el-card></div></el-col></el-row><template #footer><span class="dialog-footer"><el-button @click="cancel">取 消</el-button><el-button style="background-color:red;color:white" @click="print">打 印</el-button></span></template> </el-dialog></div>
</template>

Typescript代码:

printrow 方法中使用nextTick是当el-dialog弹窗DOM加载完成后在调用PrintJS获取需要打印的区域,这个直接打印过程其实会先弹窗然后DOM加载完成后直接调用浏览器打印界面,后面把弹出关闭,如果不加载el-dialog可以通过动态加载html内容来实现直接打印,我这里图方便就用该方法实现了。

printJS({printable:区域id,type:打印类型(pdf\image\html等),style:打印内容的CSS样式})

注意:style参数值按打印区域的HTMLCSS样式构建,调用printJS设置scanStyles:false不会自动加载HTML的CSS样式需要重新给Style参数赋值所以增加了一个printStyle函数,scanStyles默认值是true(会导致打印界面的内容奇奇怪怪,还没去了解详细原因哈哈哈哈)

<script lang="ts" setup>
import { ref,reactive,nextTick } from 'vue';
import { TbProduceOrderNoInfo } from '/@/api-services';
import printJS from 'print-js';
import moment from 'moment';
const props=defineProps({title:String
})const state=reactive({isShowDialog:false,Datas:[] as Array<TbProduceOrderNoInfo>,
})const emits = defineEmits(['handleQuery']);
const closeDialog=()=>{emits('handleQuery');state.isShowDialog=false;
}const cancel=()=>{state.isShowDialog=false;closeDialog();
}//预览+打印
const openDialog=async(row:any)=>{state.Datas=JSON.parse(JSON.stringify(row));state.isShowDialog=true;
}const print=()=>{for(var i=0;i<state.Datas.length;i++){printJS({printable:`${state.Datas[i].id}`,type:"html",style:printStyle(),scanStyles:false})}
}//直接打印不预览
const printrow=async(row:any)=>{state.Datas=JSON.parse(JSON.stringify(row));state.isShowDialog=true;//主界面form DOM加载完成nextTick(()=>{//弹窗加载完成nextTick(()=>{printJS({printable:`${state.Datas[0].id}`,type:"html",style:printStyle(),scanStyles:false})state.isShowDialog=false;})})
}//打印界面的CSS样式
const printStyle=()=>{return `
.labelHeadBody{display: flex;justify-content:space-between;margin: 0; font-size: 16px;width: 100%; height:45px
}
.labelHeadBodyLeftHead{width: 30px;
}
.labelHeadBodyRightHead{width: 250px; height: 70px;display: flex;justify-content: center;
}
.lableBodytdrightfont{font-size:10px
}
.labelHeadBodyRightHeadTd{padding: 0;font-size: 14px;font-weight: bold;text-align: center;vertical-align: middle;
}
.labelBody{margin-left: 5px;margin-right: 5px;
}
.lableBodytdleft{width: 30%;font-weight: bold;vertical-align: bottom;}.lableBodytdright{width: 70%; border-bottom: 1px solid;
}
.labelHeadBodyLeftHeadimage{width: 70px; height: 40px
}
.tableHead{height: 20px;
}`;
}//预览、直接打印
defineExpose({openDialog,printrow})
</script>

标签前端样式代码:

<style>
.labelHeadBody{display: flex;justify-content:space-between;margin: 0; font-size: 16px;width: 100%;
}
.labelHeadBodyLeftHead{width: 30px;
}
.labelHeadBodyRightHead{width: 250px; height: 70px;display: flex;justify-content: center;
}.labelHeadBodyRightHeadTd{padding: 0;font-size: 14px;font-weight: bold;text-align: center;vertical-align: middle;
}
.labelBody{margin-top: 10px;margin-left: 5px;margin-right: 5px;
}
.lableBodytdleft{width: 30%;font-weight: bold;vertical-align: bottom;}
.lableBodytdright{width: 75%; border-bottom: 1px solid;
}
.labelHeadBodyLeftHeadimage{width: 80px; height: 55px
}
.tableHead{height: 20px;
}
</style>

最后,如果需要带二维码的同学可以添加qrcode组件,以下是简单的实现(el-image、img标签中图片不显示的问题还没解决,迂回操作直接把生成的二维码图片设置成控件背景来处理,囧.........):

<template #default="scope"><div :style="createQrcode(scope.row.eqNo)" ></div><!-- <el-image :scr="createQrcode1(scope.row.eqNo)" style="width: 60px;height: 60px;"></el-image> -->
</template>import QRCode from 'qrcode'//将生成的二维码设置成div的Style,不知道为嘛el-image绑定base64image图片不显示
const createQrcode=(text:string)=>{if(text==""||text==undefined||text==null) return "";let url1:any;url1="";  QRCode.toDataURL(text,(err,url)=>{if(err){console.error(err);}else{url1=url;}})return `background-image: url(${url1});background-position: center center;background-size: contain;background-repeat: no-repeat;;width:100%;height:60px`;
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Spingboot请求tcp 方式
  • 写一个图片裁剪的js,JavaScript图片裁剪插件PlusCropper
  • 【数值计算方法】数值积分微分-python实现-p2
  • volatile 关键字的两层语义
  • jEasyUI 扩展编辑器
  • 读零信任网络:在不可信网络中构建安全系统06授权
  • springboot的表现层/控制层controller开发
  • 设计模式的类别
  • 【计算机网络】三次握手、四次挥手
  • go selenium 使用总结
  • dbm和w的换算公式
  • FPGA开发——状态机的使用
  • 如何在C语言中实现求解超级丑数
  • 10年仓库管理经验:“管、存、发、盘”一文搞定!
  • 计网面试题
  • Android开源项目规范总结
  • CSS进阶篇--用CSS开启硬件加速来提高网站性能
  • flask接收请求并推入栈
  • JavaScript HTML DOM
  • js学习笔记
  • js正则,这点儿就够用了
  • Laravel Mix运行时关于es2015报错解决方案
  • Mocha测试初探
  • OpenStack安装流程(juno版)- 添加网络服务(neutron)- controller节点
  • PAT A1092
  • Rancher如何对接Ceph-RBD块存储
  • 阿里云前端周刊 - 第 26 期
  • 得到一个数组中任意X个元素的所有组合 即C(n,m)
  • 服务器之间,相同帐号,实现免密钥登录
  • 回顾2016
  • 记一次和乔布斯合作最难忘的经历
  • 开年巨制!千人千面回放技术让你“看到”Flutter用户侧问题
  • 前端性能优化--懒加载和预加载
  • 浅析微信支付:申请退款、退款回调接口、查询退款
  • 区块链共识机制优缺点对比都是什么
  • 手机app有了短信验证码还有没必要有图片验证码?
  • 通过来模仿稀土掘金个人页面的布局来学习使用CoordinatorLayout
  • 再次简单明了总结flex布局,一看就懂...
  • mysql面试题分组并合并列
  • #Datawhale X 李宏毅苹果书 AI夏令营#3.13.2局部极小值与鞍点批量和动量
  • #我与Java虚拟机的故事#连载10: 如何在阿里、腾讯、百度、及字节跳动等公司面试中脱颖而出...
  • (~_~)
  • (1)Hilt的基本概念和使用
  • (14)Hive调优——合并小文件
  • (1综述)从零开始的嵌入式图像图像处理(PI+QT+OpenCV)实战演练
  • (保姆级教程)Mysql中索引、触发器、存储过程、存储函数的概念、作用,以及如何使用索引、存储过程,代码操作演示
  • (二)Eureka服务搭建,服务注册,服务发现
  • (二)pulsar安装在独立的docker中,python测试
  • (附源码)计算机毕业设计ssm基于Internet快递柜管理系统
  • (附源码)计算机毕业设计SSM疫情下的学生出入管理系统
  • (数据结构)顺序表的定义
  • (转)Android学习系列(31)--App自动化之使用Ant编译项目多渠道打包
  • (转载)微软数据挖掘算法:Microsoft 时序算法(5)
  • .bat批处理出现中文乱码的情况
  • .gitignore文件使用