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

温问问 2024-08-29 13:03:01 阅读 89

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

开发工具:VS CODE

界面开发:Vue3+TypeScript+ElementPlus

打印组件:Print-JS

前端打印入口图:

标签页面:

打印界面:

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

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

  标签模板代码:

<code><template>

<div class="LabelPrint-List">code>

<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" width="50%" >code>

<template #header>

<div style="color: #fff">code>

<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Edit/> </el-icon>code>

<span>标签打印界面</span>

</div>

</template>

<el-row :gutter="10">code>

<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb10">code>

<div v-for="item in state.Datas">code>

<el-card class="box-card" style="width:100mm; height: 90mm;display: block;" >code>

<div :id='item.id?.toString()'>code>

<!-- print-js -->

<div class="labelHeadBody">code>

<div class="labelHeadBodyLeftHead">code>

<img class="labelHeadBodyLeftHeadimage" src="/image/点金log.png" fit="fill" />code>

</div>

<div class="labelHeadBodyRightHead">code>

<table class="tableHead">code>

<tr>

<td class="labelHeadBodyRightHeadTd">某某有限公司</td>code>

</tr>

<tr>

<td class="labelHeadBodyRightHeadTd">物料标识卡</td>code>

</tr>

</table>

</div>

</div>

<div class="labelBody">code>

<table>

<tbody>

<tr><td class="lableBodytdleft">P/N:</td><td class="lableBodytdright">{ { item.produceNo }}</td></tr>code>

<tr><td class="lableBodytdleft">数量:</td><td class="lableBodytdright">{ { item.quantity }}</td></tr>code>

<tr><td class="lableBodytdleft">规格:</td><td class="lableBodytdright lableBodytdrightfont">{ { item.platingSpecs }}</td></tr>code>

<tr><td class="lableBodytdleft">供应商:</td><td class="lableBodytdright">东莞点金</td></tr>code>

<tr><td class="lableBodytdleft">生产日期:</td><td class="lableBodytdright">{ {moment(String(item.createTime)).format('YYYY/MM/DD')}}</td></tr>code>

<tr><td class="lableBodytdleft">批次单号:</td><td class="lableBodytdright">{ { item.lot }}</td></tr>code>

<tr><td class="lableBodytdleft">单重:</td><td class="lableBodytdright">{ { item.singleWeight }}</td></tr>code>

<tr><td class="lableBodytdleft">总重:</td><td class="lableBodytdright">{ { item.sumWeight }}</td></tr>code>

<tr><td class="lableBodytdleft">标识人:</td><td class="lableBodytdright"></td></tr>code>

</tbody>

</table>

</div>

</div>

</el-card>

</div>

</el-col>

</el-row>

<template #footer>

<span class="dialog-footer">code>

<el-button @click="cancel">取 消</el-button>code>

<el-button style="background-color:red;color:white" @click="print">打 印</el-button>code>

</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>code>

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">code>

<div :style="createQrcode(scope.row.eqNo)" ></div>code>

<!-- <el-image :scr="createQrcode1(scope.row.eqNo)" style="width: 60px;height: 60px;"></el-image> -->code>

</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=""; code>

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`;

}



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。