基于Vue.js和PDF-Lib的条形码生成与批量打印方案

引言

在现代Web应用中,条形码生成与打印是许多业务场景(如库存管理、物流跟踪、零售收银等)中不可或缺的功能。本文将详细介绍如何使用Vue.js结合pdf-lib和jsbarcode库,实现一个完整的条形码生成与批量打印解决方案。

技术栈概述

1. 前端框架:Vue.js 3

我们选择Vue.js 3作为前端框架,利用其组合式API(<script setup>)带来的简洁性和高效性。Vue 3的响应式系统让我们能够轻松管理条形码数据的状态变化。

2. 核心功能库

  • pdf-lib: 一个强大的JavaScript库,用于创建、修改PDF文档
  • jsbarcode: 轻量级的条形码生成库,支持多种条形码格式
  • fontkit: PDF字体处理工具,配合pdf-lib使用

实现步骤详解

1. 项目初始化与依赖安装

首先创建一个Vue 3项目(如果尚未创建):

bash 复制代码
npm init vue@latest barcode-generator
cd barcode-generator
npm install pdf-lib jsbarcode @pdf-lib/fontkit

2. 组件结构与模板

我们的核心组件(barCode.vue)包含以下UI元素:

html 复制代码
<template>
  <div>
    <el-input v-model="msg"></el-input>
    <el-button @click="downloadPDF">生成PDF条码</el-button>
    <el-button @click="printBatch">批量打印</el-button>
    
    <!-- 隐藏的画布用于生成条码 -->
    <canvas id="barcodeCanvas" style="display: none"></canvas>
  </div>
</template>

<el-input><el-button>是Element Plus组件(也可替换为其他UI库),分别用于:

  • 输入条形码内容
  • 触发单个PDF生成
  • 触发批量打印

隐藏的<canvas>元素用于临时渲染条形码图像。

3. 脚本实现

3.1 导入与初始化
typescript 复制代码
import { ref } from "vue";
import { PDFDocument, rgb } from "pdf-lib";
import JsBarcode from "jsbarcode";
import fontkit from "@pdf-lib/fontkit";

const msg = ref("3-250622-00001"); // 默认条形码内容

我们使用Vue的ref创建响应式数据,存储条形码内容。

3.2 单个PDF生成逻辑

downloadPDF函数是核心功能,步骤如下:

  1. 生成条形码图像
typescript 复制代码
const canvas = document.getElementById("barcodeCanvas") as HTMLCanvasElement;
JsBarcode(canvas, msg.value, { 
  format: "CODE128", 
  height: 60 
});

JsBarcode配置说明:

  • format: "CODE128": 使用CODE128格式(广泛用于物流、仓储)
  • height: 60: 设置条形码高度
  1. 创建PDF文档
typescript 复制代码
const pdfDoc = await PDFDocument.create();
pdfDoc.registerFontkit(fontkit);
  1. 加载中文字体
typescript 复制代码
const fontUrl = "/fonts/SIMHEI.TTF"; // 本地路径
const fontBytes = await fetch(fontUrl).then((res) => res.arrayBuffer());
const customFont = await pdfDoc.embedFont(fontBytes, { subset: true });

字体处理注意事项:

  • 确保SIMHEI.TTF文件放置在public/fonts目录
  • subset: true只嵌入使用的字符,减小PDF体积
  1. 添加页面与内容
typescript 复制代码
const page = pdfDoc.addPage([300, 200]); // 页面尺寸: 300x200 points
const barcodeImage = await pdfDoc.embedPng(canvas.toDataURL("image/png"));
page.drawImage(barcodeImage, { 
  x: 50, 
  y: 60, 
  width: 200, 
  height: 80 
});

// 添加中文文本
page.drawText("测试字体", {
  x: 50,
  y: 140,
  size: 14,
  font: customFont,
  color: rgb(0, 0, 0),
});

页面布局要点:

  • 坐标系统原点在左下角
  • 单位是PDF points(1 point = 1/72 inch)
  1. 下载PDF
typescript 复制代码
const pdfBytes = await pdfDoc.save();
const blob = new Blob([pdfBytes], { type: "application/pdf" });
const link = document.createElement("a");
link.href = URL.createObjectURL(blob);
link.download = "产品条码.pdf";
link.click();
3.3 批量打印实现
typescript 复制代码
const printBatch = async () => {
  for (let i = 0; i < 5; i++) {
    await downloadPDF();
    if (i < 4) {
      await new Promise((resolve) => setTimeout(resolve, 200)); // 每次间隔 200ms
    }
  }
};

批量打印注意事项:

  • 添加延迟避免浏览器安全限制
  • 可扩展为动态数量(如从输入框获取)

4. 错误处理

typescript 复制代码
try {
  // ...主要逻辑
} catch (error) {
  console.error("生成失败:", error);
  reject("生成失败,请检查控制台");
}

良好的错误处理有助于:

  • 开发时快速定位问题
  • 生产环境提供友好提示

高级功能扩展

1. 动态内容生成

可以扩展为根据API数据动态生成条形码:

typescript 复制代码
const generateFromAPI = async () => {
  const products = await fetchProducts(); // 假设的API调用
  products.forEach(product => {
    msg.value = product.barcode;
    downloadPDF();
  });
};

2. 打印样式自定义

通过修改PDF生成参数,实现多样化样式:

typescript 复制代码
// 添加页眉页脚
page.drawText(new Date().toLocaleDateString(), {
  x: 10,
  y: 10,
  size: 10,
  font: customFont
});

// 添加公司LOGO
const logoBytes = await fetch('/logo.png').then(res => res.arrayBuffer());
const logoImage = await pdfDoc.embedPng(logoBytes);
page.drawImage(logoImage, {
  x: 10,
  y: 160,
  width: 50,
  height: 30
});

3. 批量打印优化

针对大批量打印场景的优化方案:

  1. 合并多条形码到单个PDF
typescript 复制代码
const pdfDoc = await PDFDocument.create();
// ...初始化

for (const barcode of barcodes) {
  const page = pdfDoc.addPage([300, 200]);
  // 生成并添加每个条形码
}
// 最后统一下载
  1. 使用Web Worker避免UI阻塞
typescript 复制代码
// worker.js
self.onmessage = async (e) => {
  const { barcodes } = e.data;
  // 生成PDF逻辑
  self.postMessage({ pdfBytes });
};

// 组件中
const worker = new Worker('worker.js');
worker.postMessage({ barcodes });
worker.onmessage = (e) => {
  // 处理生成的PDF
};

性能优化建议

  1. 字体加载优化

    • 预加载常用字体
    • 使用CDN加速字体加载
  2. PDF生成优化

    • 复用PDFDocument实例
    • 启用PDF压缩
  3. 内存管理

    • 及时释放Blob URL
    typescript 复制代码
    URL.revokeObjectURL(link.href);

常见问题解决方案

  1. 字体加载失败

    • 检查字体文件路径
    • 确保服务器配置正确的MIME类型
    • 提供备选字体方案
  2. 条形码扫描识别率低

    • 调整JsBarcode参数:

      javascript 复制代码
      JsBarcode(canvas, msg.value, {
        format: "CODE128",
        height: 60,
        width: 2,    // 条宽
        margin: 10,  // 边距
        displayValue: true // 显示文本
      });
  3. 批量打印速度慢

    • 增加延迟间隔
    • 采用合并PDF方案
    • 使用打印API替代下载

安全考虑

  1. 输入验证

    typescript 复制代码
    if (!/^[\w-]+$/.test(msg.value)) {
      throw new Error("无效的条形码格式");
    }
  2. PDF安全

    • 设置PDF密码保护
    • 添加水印防止未授权使用

测试策略

  1. 单元测试

    • 验证条形码生成逻辑
    • 测试PDF文档结构
  2. 集成测试

    • 完整流程测试(输入→生成→下载)
    • 批量打印压力测试
  3. 视觉回归测试

    • 确保条形码可扫描
    • 验证PDF布局一致性

部署方案

  1. 静态资源部署

    • 确保字体文件正确打包
    • 配置CDN缓存策略
  2. Docker化部署

    dockerfile 复制代码
    FROM nginx:alpine
    COPY dist /usr/share/nginx/html
    COPY public/fonts /usr/share/nginx/html/fonts

结论

本文详细介绍了基于Vue.js的条形码生成与打印解决方案。通过结合pdf-lib和jsbarcode,我们实现了一个功能完整、可扩展的条形码管理系统。关键点包括:

  1. 条形码图像生成与PDF嵌入
  2. 中文字体处理与渲染
  3. 批量打印与性能优化
  4. 完整的错误处理机制

这套方案可轻松集成到各类管理系统中,满足企业级条形码处理需求。通过进一步的定制开发,可以支持更复杂的业务场景,如多规格标签打印、数据库集成等。

相关推荐
ℋᙚᵐⁱᒻᵉ鲸落1 小时前
移动端滑动手势冲突:overflow: auto导致外层横向滑动失效
前端·javascript·css·vue.js·html
默_笙2 小时前
🎃 前端学了 Next.js,后端该学啥?NestJS 就是 Node 版的蜜雪冰城
前端·javascript
前端snow3 小时前
ai agent --- 实现 openclaw 定时间效果
前端
码云之上4 小时前
换模型之后,Chatbot 为什么要自己做 compact?
前端·agent·前端工程化
星栈4 小时前
自定义 UI-UX-Pro-Max 的 CSV 知识库,把 AI 生成的后台拉回行业该有的样子
前端·agent·weui
研☆香4 小时前
简单的图片上传 删除 预览
前端
ITresearchGuest4 小时前
我用 AI 一小时写了一个世界杯数据可视化平台|前端 VibeCoding 初体验
前端·人工智能·信息可视化
慧一居士6 小时前
Vite项目中使用Less步骤,详细使用示例
前端·css
花间相见6 小时前
【LangChain组件03】—— LangChain Agents 执行与状态:工作流程与状态管理实战
java·前端·langchain
kyriewen6 小时前
面试官让我用 AI 重构一个 8 年陈的 React 组件——他说他不看代码,只看我会不会拆
前端·javascript·面试