Vue3+TypeScript+printjs实现标签批量打印功能的完整过程

 更新时间:2024年09月03日 09:50:45   作者:温问问  
最近在做vue项目时使用到了print-js打印,这里给大家分享下,这篇文章主要给大家介绍了关于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`;
}

总结 

到此这篇关于Vue3+TypeScript+printjs实现标签批量打印功能的文章就介绍到这了,更多相关Vue3+TypeScript+printjs标签批量打印内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue+element-ui动态生成多级表头的方法

    vue+element-ui动态生成多级表头的方法

    今天小编就为大家分享一篇vue+element-ui动态生成多级表头的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-08-08
  • vue动态删除从数据库倒入列表的某一条方法

    vue动态删除从数据库倒入列表的某一条方法

    今天小编就为大家分享一篇vue动态删除从数据库倒入列表的某一条方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-09-09
  • 分享一个精简的vue.js 图片lazyload插件实例

    分享一个精简的vue.js 图片lazyload插件实例

    本篇文章主要介绍了分享一个精简的vue.js 图片lazyload插件实例。非常具有实用价值,需要的朋友可以参考下。
    2017-03-03
  • 基于express中路由规则及获取请求参数的方法

    基于express中路由规则及获取请求参数的方法

    下面小编就为大家分享一篇基于express中路由规则及获取请求参数的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-03-03
  • 解决vue中使用Axios调用接口时出现的ie数据处理问题

    解决vue中使用Axios调用接口时出现的ie数据处理问题

    今天小编就为大家分享一篇解决vue中使用Axios调用接口时出现的ie数据处理问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-08-08
  • vue 目录树的展开与关闭的实现

    vue 目录树的展开与关闭的实现

    Vue作为一款流行的前端框架,提供了一种数据驱动的方式来实现目录树,本文主要介绍了vue 目录树的展开与关闭的实现,具有一定的参考价值,感兴趣的可以了解一下
    2023-11-11
  • Vue封装--如何将数字转换成万

    Vue封装--如何将数字转换成万

    这篇文章主要介绍了Vue封装--将数字转换成万的实现方法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • Vue解析带html标签的字符串为dom的实例

    Vue解析带html标签的字符串为dom的实例

    今天小编就为大家分享一篇Vue解析带html标签的字符串为dom的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-11-11
  • nuxt框架中对vuex进行模块化设置的实现方法

    nuxt框架中对vuex进行模块化设置的实现方法

    这篇文章主要介绍了nuxt框架中对vuex进行模块化设置的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • 基于Vue实现Excel解析与导出功能详解

    基于Vue实现Excel解析与导出功能详解

    导入导出excel这是前端做管理系统最常用的功能了,下面这篇文章主要给大家介绍了基于Vue实现Excel解析与导出功能的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2021-08-08

最新评论