springBoot+vue二维码标签生成

页面效果:

1.maven配置


        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.10</version>
        </dependency>

        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>

        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>core</artifactId>
            <version>3.3.0</version>
        </dependency>
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>javase</artifactId>
            <version>3.3.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>fontbox</artifactId>
            <version>2.0.11</version>
        </dependency>
        <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>pdfbox</artifactId>
            <version>2.0.11</version>
        </dependency>

2.PDF生成

package com.beaver.util;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.beaver.common.utils.file.FileUtils;
import com.beaver.domain.vo.QRCodeParam;
import com.beaver.domain.vo.QRCodeRequest;
import com.beaver.domain.vo.QRCodeResponse;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;

import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfWriter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.*;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class QrCodeUtil {

    private static final Log log = LogFactory.getLog(QrCodeUtil.class);

    private static final QRCodeWriter QR_CODE_WRITER = new QRCodeWriter();

    public static final String QR_CODE_IMAGE_PATH = "code";

    // 设置默认参数,可以根据需要进行修改
    private static final int QRCOLOR = 0xFF000000; // 默认是黑色
    private static final int BGWHITE = 0xFFFFFFFF; // 背景颜色
    private static final int WIDTH = 80; // 二维码宽
    private static final int HEIGHT = 80; // 二维码高

    /**
     * 生成二维码字节数组.
     */
    public static byte[] generateQrCode(String text, String format, int width, int height) {
        try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
            BitMatrix bitMatrix = QR_CODE_WRITER.encode(text, BarcodeFormat.QR_CODE, width, height,hints);
            MatrixToImageWriter.writeToStream(bitMatrix, format, os);
            return os.toByteArray();
        } catch (WriterException e) {
            throw new RuntimeException(String.format("fail to generate qr code:text[%s]", text), e);
        } catch (IOException e) {
            throw new RuntimeException(String.format("fail to writeToStream when generating qr code: text[%s]", text), e);
        }
    }

    /**
     * 保存二维码图片到文件系统.
     */
    public static void generateQrCodeAndSave(String text, String format, int width, int height, String path) {
        try {
            BitMatrix bitMatrix = QR_CODE_WRITER.encode(text, BarcodeFormat.QR_CODE, width, height,hints);
            MatrixToImageWriter.writeToPath(bitMatrix, format, Paths.get(path));
        } catch (WriterException e) {
            throw new RuntimeException(String.format("fail to generate qr code:text[%s]", text), e);
        } catch (IOException e) {
            throw new RuntimeException(String.format("fail to writeToStream when generating qr code: text[%s]", text), e);
        }
    }

    /**
     * 用于设置QR二维码参数
     * com.google.zxing.EncodeHintType:编码提示类型,枚举类型
     * EncodeHintType.CHARACTER_SET:设置字符编码类型
     * EncodeHintType.ERROR_CORRECTION:设置误差校正
     * ErrorCorrectionLevel:误差校正等级,L = ~7% correction、M = ~15% correction、Q = ~25% correction、H = ~30% correction
     * 不设置时,默认为 L 等级,等级不一样,生成的图案不同,但扫描的结果是一样的
     * EncodeHintType.MARGIN:设置二维码边距,单位像素,值越小,二维码距离四周越近
     * */
    private static Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>() {
        private static final long serialVersionUID = 1L;
        {
            put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);// 设置QR二维码的纠错级别(H为最高级别)具体级别信息
            put(EncodeHintType.CHARACTER_SET, "utf-8");// 设置编码方式
            put(EncodeHintType.MARGIN, 0);
        }
    };


    public static  String convertEmpty(String str){
         if(str == null){
             return "";
         }
         return str;
    }


    public static QRCodeResponse drawPDFQRCode(QRCodeRequest qRCodeRequest) {
        QRCodeResponse qRCodeResponse = new QRCodeResponse();
        FileOutputStream fileOutputStream = null;
        try {
            String absolutePath = FileUtils.getAbsolutePath(new File(""));
            File stockPath = new File(absolutePath + "/" + QR_CODE_IMAGE_PATH);
            if (!stockPath.exists()) {
                stockPath.mkdirs();
                stockPath.setReadable(true);
                stockPath.setWritable(true);
            }
            String key =  IdWorker.getIdStr();
            String pdfPath =  QR_CODE_IMAGE_PATH + "/" + key+ ".pdf";
            File file = new File(absolutePath+"/"+pdfPath);
            fileOutputStream = new FileOutputStream(file);
            createPdfQr(qRCodeRequest, qRCodeRequest.getWidth(), qRCodeRequest.getHeight(), fileOutputStream);
            String imagePath = PdfUtil.PdfToImg(file, key);
            qRCodeResponse.setImagePath(imagePath);
            qRCodeResponse.setPdfPath(pdfPath);
        } catch (IOException | DocumentException e) {
            log.error("二维码写入IO流异常", e);
        } finally {
            try {
                if (null != fileOutputStream) {
                    fileOutputStream.flush();
                    fileOutputStream.close();
                }
            } catch (IOException ioe) {
                log.error("二维码关流异常", ioe);
            }
        }
        return qRCodeResponse;
    }



    private static void createPdfQr(QRCodeRequest qRCodeRequest, Float width, Float height, FileOutputStream out ) throws IOException, DocumentException {
        List<QRCodeParam> qrCodeParams = qRCodeRequest.getQrCodeParams();
        int paramSize = qrCodeParams.size();
        Rectangle tRectangle = new Rectangle(0, 0, height/0.3523F, width/0.3523F); // 页面大小
        Document doc = new Document(tRectangle);// 定义文档
        doc = new Document(tRectangle.rotate());// 横向打印
        PdfWriter writer = PdfWriter.getInstance(doc, out);// 书写器
        writer.setPdfVersion(PdfWriter.PDF_VERSION_1_2);
        // 3-综合属性:
        doc.setMargins(width*0.1F, width*0.1F, width*0.3F, width*0.1F);// 页边空白
        doc.open();// 打开文档

        float size = width*0.6F;
        byte[]  bytes = generateQrCode(qRCodeRequest.getContent(),"png",(int)(width*0.9F),(int)(width*0.9F));
        Image image = Image.getInstance(bytes);
        float asx = width * 2F;
        float asy = height * 0.4F;
        image.setAbsolutePosition(asx, asy);
        image.scaleAbsolute(size, size);
        for (QRCodeParam qrCodeParam : qrCodeParams) {
            doc.add(getParagraph(paramSize,height,qrCodeParam.getAttrName()+": " + convertEmpty(qrCodeParam.getAttrValue())));
        }
        doc.add(image);
        doc.newPage();
        doc.close();
    }

    private static Paragraph getParagraph( int paramSize,float height, String content) throws DocumentException, IOException {
        float scale  =  height-paramSize*2;
        BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
        Paragraph paragraph = new Paragraph(content,   new Font(bfChinese, scale*0.15F, Font.NORMAL));
        paragraph.setAlignment(0); //设置文字居中 0靠左   1,居中     2,靠右
        paragraph.setIndentationLeft(scale*0.2F); //设置左缩
        paragraph.setFirstLineIndent(scale*0.1F); //设置首行缩进
        paragraph.setLeading(scale*0.25F); //行间距
        return paragraph;
    }

}

package com.beaver.domain.vo;


import lombok.Data;

import java.util.List;

@Data
public class QRCodeRequest {

   private float width;

   private float height;

   private  List<QRCodeParam> qrCodeParams;

   public  String getContent(){
       StringBuffer sb = new StringBuffer();
       for (QRCodeParam qrCodeParam : qrCodeParams) {
           sb.append(qrCodeParam.getAttrValue()).append("$");
       }
       if(sb.length()>1){
           sb = sb.deleteCharAt(sb.length() -1);
       }
       return sb.toString();
   }
}
package com.beaver.domain.vo;

import lombok.Data;

@Data
public class QRCodeResponse {

    private String  pdfPath;

    private String  imagePath;

}

3.生成图片 

package com.beaver.util;

import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.beaver.common.config.ProjectConfig;
import com.beaver.common.utils.file.FileUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;

public class PdfUtil {


    /**
     * <p>Description:pdf文件转img文件 </p>
     */
    public static String PdfToImg(File pdfFile,String key) {
        PDDocument pdDocument;
        try {
            String imgPath =  QrCodeUtil.QR_CODE_IMAGE_PATH + "/" + key +".png";
            pdDocument = PDDocument.load(pdfFile);
            PDFRenderer renderer = new PDFRenderer(pdDocument);
            /* 第二位参数越大转换后越清晰,相对转换速度越慢 */
            BufferedImage image = renderer.renderImageWithDPI(0, 1000);
            BufferedImage bufferedImage = resizeBufferedImage(image, 500,450 , true);
            ImageIO.write(bufferedImage, "png", new File(FileUtils.getAbsolutePath(new File("")) + "/"+ imgPath));
            pdDocument.close();
            return imgPath;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 调整bufferedimage大小
     * @param source BufferedImage 原始image
     * @param targetW int  目标宽
     * @param targetH int  目标高
     * @param flag boolean 是否同比例调整
     * @return BufferedImage  返回新image
     */
    private static BufferedImage resizeBufferedImage(BufferedImage source, int targetW, int targetH, boolean flag) {
        int type = source.getType();
        BufferedImage target = null;
        double sx = (double) targetW / source.getWidth();
        double sy = (double) targetH / source.getHeight();
        if (flag && sx > sy) {
            sx = sy;
            targetW = (int) (sx * source.getWidth());
        } else if(flag && sx <= sy){
            sy = sx;
            targetH = (int) (sy * source.getHeight());
        }
        if (type == BufferedImage.TYPE_CUSTOM) { // handmade
            ColorModel cm = source.getColorModel();
            WritableRaster raster = cm.createCompatibleWritableRaster(targetW, targetH);
            boolean alphaPremultiplied = cm.isAlphaPremultiplied();
            target = new BufferedImage(cm, raster, alphaPremultiplied, null);
        } else {
            target = new BufferedImage(targetW, targetH, type);
        }
        Graphics2D g = target.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g.drawRenderedImage(source, AffineTransform.getScaleInstance(sx, sy));
        g.dispose();
        return target;
    }
}

3.页面

<template>
  <div class="app-container">
         <el-card class="param-card" >
           <div class="param-card-content">
           <el-row :gutter="10" class="mb8">
             <el-col :span="1.5">
               <el-button
                 type="primary"
                 plain
                 size="mini"
                 round
                 @click="showDynamicAttr"
               >新增动态属性</el-button>
             </el-col>
           </el-row>

            <el-form ref="form"  label-width="80px" style="margin-top: 40px">
              <div style="margin-left: 10%;display: inline-block;">
                <el-form-item  label="标签宽度"  >
                  <el-input style="width: 100%;" v-model="tagWidth" placeholder="请输入标签宽度" />
                </el-form-item>
              </div>
              <div style=" float: right;position: relative;margin-right: 15%">
                <el-form-item  label="标签高度"  >
                  <el-input style="width: 100%;" v-model="tagHeight" placeholder="请输入标签高度" />
                </el-form-item>
              </div>
              <el-divider></el-divider>
              <div  v-for="(item,index) in formData">
                <el-form-item  :label="item.attrName" :prop="item.attrCode" style="margin-left: 5%">
                  <el-input style="width: 90%;" v-model="item.attrValue" :placeholder="'请输入'+item.attrName" />
                  <el-button type="danger" icon="el-icon-delete" circle style="margin-left: 2%"  @click="deleteFlexAttr(index)"></el-button>
                </el-form-item>

              </div>
            </el-form>
             <div class="plus-attr-button">
               <el-button type="primary" @click="_generateQRCode">生成包装码</el-button>
             </div>
           </div>
         </el-card>

          <el-dialog title="动态新增属性" width="800px" :visible="showDynamic" @close="showDynamic = false">
            <div  v-for="(item,index) in dynamicAttrData">
                <div style="margin-top: 2%">
                  <el-input style="width: 30%;margin-left: 5%" v-model="item.attrName" placeholder="属性名称" />
                  <el-input style="width: 30%;margin-left: 5%" v-model="item.attrCode" placeholder="属性编码" />
                  <el-button type="primary" icon="el-icon-plus"  style="margin-left: 5%" circle @click="addDynamicAttr"></el-button>
                  <el-button type="danger" icon="el-icon-delete" circle style="margin-left: 2%"  @click="deleteDynamicAttr(index)"></el-button>
                </div>
            </div>
            <div class="plus-attr-button" >
              <el-button type="primary" @click="confirmDynamicAttr">确 定</el-button>
            </div>
          </el-dialog>

          <el-card class="qrcode-card">
            <div class="param-card-code">
                <el-card shadow="hover" class="image">
                    <el-image :src="imageUrl" >
                      <div slot="error" class="image-slot error">
                        <div>
                        </div>
                      </div>
                    </el-image>
                </el-card>
                <div class="print-button" >
                  <el-button type="primary" @click="printQRCode">打印包装码</el-button>
                </div>
            </div>
          </el-card>
  </div>
</template>

<script>

import { generateQRCode } from "@/api/business/tag";
import printJS from "print-js";

export default {
  name: "qrCode",
  data() {
    return {
        tagWidth: 110,
        tagHeight:90,
        formData: [
            {attrName:'物料编码',attrCode:'coding',attrValue:'1010010'},
            {attrName:'物料名称',attrCode:'name',attrValue:'CPU'},
            {attrName:'物料规格',attrCode:'mode',attrValue:'GH8989HJ'},
            {attrName:'批次',attrCode:'batch',attrValue:'20221205'},
            {attrName:'生产厂商',attrCode:'supplier',attrValue:'西安'},
            {attrName:'单位',attrCode:'unit',attrValue:'个'},
            {attrName:'单重',attrCode:'singleWeight',attrValue:'0.3'},
            {attrName:'数量',attrCode:'qty',attrValue:'50'}
        ],
        dynamicAttrData:[
            {attrName:'',attrCode:'',attrValue:''},
        ],
        showDynamic:false,
        imageUrl:'',
        printUrl:''
    };
  },
  created() {
  },
  methods: {
      showDynamicAttr(){
          this.showDynamic = true
      },
      addDynamicAttr(){
          this.dynamicAttrData.push({attrName:'',attrCode:'',attrValue:''});
      },
      deleteFlexAttr(index){
          if(this.formData.length >1){
              this.formData.splice(index, 1);
          }
      },
      deleteDynamicAttr(index){
          if(this.dynamicAttrData.length >1){
              this.dynamicAttrData.splice(index, 1);
          }
      },
      confirmDynamicAttr(){
          for(let item of this.dynamicAttrData){
             this.formData.push(item)
          }
          this.showDynamic = false
          this.dynamicAttrData = [];
          this.dynamicAttrData.push({attrName:'',attrCode:'',attrValue:''});
      },
      _generateQRCode(){
          let params = {};
          params.width = this.tagWidth;
          params.height = this.tagHeight;
          params.qrCodeParams = this.formData;
          generateQRCode(params).then(response => {
              this.imageUrl = process.env.VUE_APP_HOST+response.data.imagePath;
              this.printUrl = process.env.VUE_APP_HOST+response.data.pdfPath;
          });
      },
      printQRCode(){
          printJS({ printable: this.printUrl, type: 'pdf' })
      }
  }
};
</script>

<style lang ="scss">

  .param-card {
    width: 50%;
    display: inline-block;
    overflow: visible;
  }

  .param-card-content {
    height:999999px;
    overflow: visible;
  }

  .param-card-code {
    height:999999px;
    overflow: hidden;
  }

   .qrcode-card{
     width: 50%;
     position: relative;
     float: right;
  }

  .plus-attr-button{
    margin-left: 40%;
    margin-top: 5%;
  }

  .image{
    margin-top: 20%;
    margin-left: 20%;
    width: 500px;
    height: 450px;
  }

  .card-image{
    width: 100%;
    height: 100%;
  }

  .print-button{
    margin-left: 47%;
    margin-top: 5%;
  }

</style>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
生成二维码可以使用zxing库,而在Spring Boot中集成zxing可以使用springfox依赖。 1. 添加依赖 在pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>com.google.zxing</groupId> <artifactId>core</artifactId> <version>3.3.3</version> </dependency> <dependency> <groupId>com.google.zxing</groupId> <artifactId>javase</artifactId> <version>3.3.3</version> </dependency> ``` 2. 添加二维码生成接口 在Controller中添加以下接口: ```java @RestController @RequestMapping("/api") @Api(tags = "二维码生成接口") public class QRCodeController { @GetMapping("/qrcode/{content}") @ApiOperation(value = "生成二维码", notes = "根据传入的内容生成二维码") public void generateQRCode(@PathVariable String content, HttpServletResponse response) { try { BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, 200, 200); MatrixToImageWriter.writeToStream(bitMatrix, "png", response.getOutputStream()); } catch (Exception e) { e.printStackTrace(); } } } ``` 3. 访问接口 启动Spring Boot应用后,在浏览器中访问http://localhost:8080/swagger-ui.html,可以看到Swagger UI界面,找到“二维码生成接口”并点击“Try it out”,输入需要生成二维码的内容,点击“Execute”,就可以生成二维码了。 4. 在Vue中使用 在Vue组件中添加以下代码: ```html <template> <div> <button @click="generateQRCode">生成二维码</button> <img :src="qrcode" v-if="qrcode"> </div> </template> <script> export default { data () { return { qrcode: null } }, methods: { generateQRCode () { const content = 'https://www.baidu.com' // 需要生成二维码的内容 this.qrcode = `http://localhost:8080/api/qrcode/${encodeURIComponent(content)}` } } } </script> ``` 在按钮点击事件中,使用axios发送GET请求获取生成二维码图片地址,然后在img标签中显示即可。需要注意的是,需要使用encodeURIComponent对内容进行编码,以防止特殊字符造成问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值