uniapp(vue3) H5页面连接打印机并打印

一、找到对应厂商打印机的驱动并在windows上面安装。查看是否安装完成可以在:控制面板->查看设备和打印机,找到对应打印机驱动是否安装完成

二、打印机USB连接电脑

三、运行代码调用浏览器打印,主要使用的是window.print()功能。下面使用的是基于ifream的,这样可以控制到具体打印范围,全屏打印可以考虑不用。(原理应该就是打印机打印PDF)

四、打印样式不全或者其他,可以考虑设置打印格式 或者 代码样式调整

五、demo 代码

(1) 核心代码

(2) 完整代码

复制代码
<template>
    <div class="mainContent" @click="emits('close')">
        <div class="printContent">
            <iframe style="width: 100%;height: 100%" :src="ticketUrl" ref="ticketIframe" @load="onIframeLoad"></iframe>
            <div class="btnPrint" @click="printReceipt">打印</div>
        </div>
    </div>
</template>

<script setup>
import {forDate} from "@/utlis/uni_api";
import {ref, onMounted, getCurrentInstance, toRefs} from 'vue';

let {proxy} = getCurrentInstance();
let emits = defineEmits(["print", "close"])
let props = defineProps(["data"])
const ticketIframe = ref(null);
const ticketUrl = '../static/print.html';
let {data} = toRefs(props)
let merOrderList = {}
let originalPrice = ""
let sendTxt = ""
let goodsDetails = ""

// 确保iframe加载完成
onMounted(async () => {
    await proxy.$nextTick();
    ticketIframe.value.contentWindow.focus();

    merOrderList = data.value.merOrderList

    let proList = data.value.goodList
    for (let i = 0; i < proList.length; i++) {
        let goodsName = proList[i].goodsName
        let goodsNum = proList[i].goodsNum
        let realPrice = proList[i].realPrice
        let spec = proList[i].goodsSpecification
        //商品信息
        goodsDetails += goodsName + "[" + spec + "]" + "&nbsp;X&nbsp;" + goodsNum + "&nbsp;&nbsp;&nbsp;&nbsp;¥" + realPrice + "</br>"
    }
    //原价
    originalPrice = merOrderList.price + merOrderList.discountsPrice
    //配送时间
    sendTxt = data.value.isIm ? "立即配送" : data.value.predictTime
});

function onIframeLoad() {
    console.log("data = ", data.value)
    let printerName = uni.getStorageSync("printerName")
    let iframe = ticketIframe.value
    let iframeDocument = iframe.contentWindow ? iframe.contentWindow.document : iframe.contentDocument;
    // 对于跨域限制不适用的情况,可以直接操作DOM
    if (iframeDocument) {
        if (printerName == "XP58C" || printerName == "POS58") {
            iframeDocument.body.innerHTML = ticketXP58C()
        }
    }
}

function ticketXP58C() {
    return `
            <img style="width: 160px;height: 70px;margin: 0 0 30px 20px;" src="../static/image/public/print_logo.png">
            <div style="font-size: 20px;font-weight: bold;margin-bottom: 20px;">#${data.value.dayNum}&nbsp;&nbsp;&nbsp;*外卖狮配送*</div>
            <div style="font-size: 10px;margin-bottom: 4px;">-----------------------------------------------</div>
            <div style="display: flex;justify-content: space-between;font-size: 11px;margin-bottom: 4px;">
                <div>送达时间:</div>
                <div>${sendTxt}</div>
            </div>
            <div style="display: flex;justify-content: space-between;font-size: 11px;margin-bottom: 4px;">
                <span>下单时间:</span>
                <span>${forDate(merOrderList.createTime)}</span>
            </div>
            <div style="display: flex;justify-content: space-between;font-size: 11px;margin-bottom: 4px;">
                <div>订单编号:</div>
                <div>${merOrderList.orderSn}</div>
            </div>
            <div style="font-size: 10px;margin-bottom: 4px;">-----------------------------------------------</div>
            <div style="display: flex;font-size: 18px;font-weight:bold;margin-bottom: 4px;">
                <span>备注:</span>
                <span>${data.value.remark ? data.value.remark : "无"}</span>
            </div>
            <div style="font-size: 12px;margin-bottom: 4px;">*************************************</div>
            <div style="font-size: 11px;margin-bottom: 4px;">---------------------餐品------------------</div>
            <div style="font-size: 11px;margin-bottom: 4px;">${goodsDetails}</div>
            <div style="font-size: 11px;margin-bottom: 4px;">---------------------其他------------------</div>
            <div style="display: flex;justify-content: space-between;font-size: 11px;margin-bottom: 4px;">
                <span>打包费:</span>
                <span>¥${merOrderList.packPrice}</span>
            </div>
            <div style="display: flex;justify-content: space-between;font-size: 11px;margin-bottom: 4px;">
                <span>配送费:</span>
                <span>¥${merOrderList.distributionPrice}</span>
            </div>
            <div style="display: flex;justify-content: space-between;font-size: 11px;margin-bottom: 4px;">
                <span>优惠价格:</span>
                <span>-¥${merOrderList.discountsPrice}</span>
            </div>
            <div style="font-size: 12px;margin-bottom: 4px;">*************************************</div>
            <div style="display: flex;justify-content: space-between;font-size: 11px;margin-bottom: 4px;">
                ${merOrderList.payType == "alipay" ? "支付宝支付" : "微信支付"}
            </div>
            <div style="display: flex;justify-content: space-between;font-size: 11px;margin-bottom: 4px;">
                原价:¥${originalPrice}
            </div>
            <div style="display: flex;justify-content: right;font-size: 18px;font-weight: bold;margin-bottom: 4px;">
               实付:¥${merOrderList.price}
            </div>
            <div style="font-size: 10px;margin-bottom: 30px;">------------------------------------------------</div>
            <div style="display: flex;font-size: 18px;font-weight: bold;margin-bottom: 20px;">
                ${data.value.name} ${data.value.phone.substr(0, 3) + "****" + data.value.phone.substr(data.value.phone.length - 4, data.value.phone.length)}
            </div>
            <div style="font-size: 12px;margin-bottom: 60px;">*************************************</div>
            <div style="font-size: 1px;">-</div>
        `
    //地址
    // < div style = "display: flex;font-size: 18px;font-weight: bold;margin-bottom: 15px;" >
    // ${merOrderList.address}
    // < /div>
}

function printReceipt() {
    emits("close")
    ticketIframe.value.contentWindow.print(); // 调用iframe内部的window.print()
    proxy.$refs.ticketIframe.contentWindow.location.reload(true);
}
</script>

<style scoped>
.mainContent {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    min-height: 100vh;
    background-color: rgba(0, 0, 0, 0.5);
    z-index: 999999;
    display: flex;
    align-items: center;
    justify-content: center;
}

.printContent {
    width: 70%;
    height: 50vh;
    background-color: #FFFFFF;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    align-items: center;
    border-radius: 10rpx;
    padding: 20rpx;
}

.btnPrint {
    width: 50%;
    margin: 80rpx auto 20rpx;
    font-size: 26rpx;
    color: #FFFFFF;
    background-color: #FF0000;
    text-align: center;
    padding: 10rpx 0;
    border-radius: 10rpx;
}

iframe {
    border: none;
}
</style>
相关推荐
程序员猫哥_8 小时前
HTML 生成网页工具推荐:从手写代码到 AI 自动生成网页的进化路径
前端·人工智能·html
龙飞058 小时前
Systemd -systemctl - journalctl 速查表:服务管理 + 日志排障
linux·运维·前端·chrome·systemctl·journalctl
2501_915106328 小时前
使用 Sniffmaster TCP 抓包和 Wireshark 网络分析
网络协议·tcp/ip·ios·小程序·uni-app·wireshark·iphone
我爱加班、、8 小时前
Websocket能携带token过去后端吗
前端·后端·websocket
AAA阿giao8 小时前
从零拆解一个 React + TypeScript 的 TodoList:模块化、数据流与工程实践
前端·react.js·ui·typescript·前端框架
杨超越luckly8 小时前
HTML应用指南:利用GET请求获取中国500强企业名单,揭秘企业增长、分化与转型的新常态
前端·数据库·html·可视化·中国500强
hedley(●'◡'●)9 小时前
基于cesium和vue的大疆司空模仿程序
前端·javascript·vue.js·python·typescript·无人机
qq5_8115175159 小时前
web城乡居民基本医疗信息管理系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】
前端·vue.js·spring boot
百思可瑞教育9 小时前
构建自己的Vue UI组件库:从设计到发布
前端·javascript·vue.js·ui·百思可瑞教育·北京百思教育
百锦再9 小时前
Vue高阶知识:利用 defineModel 特性开发搜索组件组合
前端·vue.js·学习·flutter·typescript·前端框架