二维码打印

需求:制作一个带有车辆信息的二维码,链接打印机可打印

前提准备:下载 qrcodejs2-fix 依赖

html 复制代码
<!-- 二维码弹层 -->
<!-- eslint-disable vue/html-self-closing -->
<template>
  <el-dialog :title="title" width="40%" top="1%" v-model="dialogVisible" :close-on-click-modal="false" @close="handleClickCancel">
    <!-- 打印按钮 -->
    <div class="print-btn-wrap">
      <el-button type="primary" v-print="printConfig">打印二维码</el-button>
    </div>

    <!-- 打印区域 + 二维码内容 -->
    <div v-if="dialogVisible" ref="printWrapRef" class="print_body">
      <div id="printContent" class="qr_code_box">
        <img src="../../../../assets/images/logo.png" alt="logo" />
        <div style="width: 162px; height: 162px; overflow: hidden; flex: none">
          <div class="qr_code" ref="qrCodeRef"></div>
        </div>
        <div class="info-wrap">
          <div class="mess">
            <span class="mess_title">车辆编号:</span>
            <span class="mess_content">{{ listData.vehicleId }}</span>
          </div>
          <div class="mess">
            <span class="mess_title">VIN号:</span>
            <span class="mess_content">{{ listData.vin }}</span>
          </div>
        </div>
      </div>
    </div>
  </el-dialog>
</template>
javascript 复制代码
<script setup>
import QRCode from 'qrcodejs2-fix'
import { ref, nextTick } from 'vue'
import { vPrint } from 'vue-print-next'

// 弹窗状态
const dialogVisible = ref(false)
// 数据源
const listData = ref({})
// DOM 引用
const qrCodeRef = ref(null)
const printWrapRef = ref(null)
// 弹窗标题
const title = ref('二维码标签打印')

// 打开弹窗 & 生成二维码, data是接收的展示数据信息
const openDialog = (data) => {
  listData.value = data?.[0] || {}
  dialogVisible.value = true

  nextTick(() => {
    createQrCode()
  })
}

// 生成二维码
const createQrCode = () => {
  const el = qrCodeRef.value
  const codeText = listData.value.vin
  if (!el || !codeText) return

  // 清空旧二维码
  el.innerHTML = ''

  const qrSize = 160
  new QRCode(el, {
    text: codeText,
    width: qrSize,
    height: qrSize,
    colorDark: '#000',
    colorLight: '#fff',
    correctLevel: QRCode.CorrectLevel.H
  })
}

// 关闭弹窗回调
const handleClickCancel = () => {
  dialogVisible.value = false
}

// ========== 重点修改:正方形标签打印机 打印配置 ==========
const printConfig = {
  el: '#printContent',
  preview: false,
  previewTitle: '二维码标签预览',
  noPrintSelector: '.no-print',
  // 移除A4,使用**自定义纸张**,适配正方形标签机
  paperSize: false,
  orientation: 'portrait',
  popTitle: '车辆二维码标签',
  // 关闭浏览器默认页眉页脚
  pageStyle: '@page { margin: 0; size: auto; }',
  openCallback() {
    console.log('打印窗口已打开')
  },
  closeCallback() {
    console.log('打印窗口关闭')
  }
}

// 对外暴露方法
defineExpose({
  openDialog
})
</script>
css 复制代码
<style lang="scss" scoped>
::v-deep .el-dialog__body {
  overflow: auto;
  height: 65vh;
}

/* 打印按钮定位 */
.print-btn-wrap {
  position: absolute;
  top: 42px;
  right: 22px;
  z-index: 10;
}

.print_body {
  padding: 20px 0;
  display: flex;
  justify-content: center;
  overflow-y: auto;
}

/* 标签容器:固定正方形尺寸,和你的标签纸物理尺寸一致 */
.qr_code_box {
  width: 320px;
  height: 320px;
  border: 1px solid #eee;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  padding: 16px;
  background: #fff;
}

.qr_code_box img {
  width: 170px;
  height: 60px;
  margin-bottom: 12px;
  object-fit: contain;
}

.qr_code {
  width: 100%;
}

/* 信息区域整体样式 */
.info-wrap {
  padding: 0 10px;
}

/* 单行信息样式 */
.mess {
  display: flex;
  align-items: center;
  line-height: 1.6;
  font-size: 14px;
  margin: 4px 0;

  .mess_title {
    flex-shrink: 0;
    font-weight: 500;
    color: #333;
    width: 80px;
  }

  .mess_content {
    flex: 1;
    color: #666;
    word-break: break-all;
  }
}

/* ========== 重点修改:打印样式 适配正方形标签机 ========== */
@media print {
  /* 全局重置,清除浏览器默认边距、缩放 */
  html,
  body {
    margin: 0 !important;
    padding: 0 !important;
    width: 100% !important;
    height: 100% !important;
    zoom: 1 !important;
  }

  /* 核心标签容器:强制正方形、无边框、无内边距(按需微调padding) */
  .qr_code_box {
    width: 320px !important;
    height: 320px !important;
    border: none !important;
    margin: 20px auto !important;
    box-shadow: none !important;
  }

  /* 隐藏页面多余元素 */
  .print-btn-wrap,
  .el-dialog__header,
  .el-dialog__footer {
    display: none !important;
  }
}
</style>
相关推荐
智商不够_熬夜来凑2 小时前
【Radio & Checkbox】
前端·javascript·vue.js
xiaofeichaichai2 小时前
Diff 算法
前端·javascript
wgc2k2 小时前
Nest.js 基础-8-Hello,NestJS
开发语言·javascript·ecmascript
Larcher2 小时前
从 0 到 1:用 Bun + axios 快速搭建 LLM API 客户端
前端·javascript
子午2 小时前
基于DeepSeek的酒店客房管理系统~Python+DeepSeek智能问答+Vue3+Web网站系统
开发语言·前端·python
bkspiderx2 小时前
Boa Web服务器HTTPS支持的源码改造方案
服务器·前端·https·web服务器·boa·https支持
贺今宵2 小时前
Vue 3 + Capacitor 使用jeep-sqlite,web端使用本地sqlite数据库
前端·数据库·vue.js·sqlite·web
taocarts_bidfans2 小时前
Google Indexing API 外贸独立站主动推送收录实战开发
前端·独立站·外贸独立站·taoify
lichenyang4532 小时前
鸿蒙 Stage 模型到底是什么?一篇讲清 Ability、EntryAbility 和入口文件为什么这么设计
前端