一、 vue页面生成二维码
<template>
<div class="app-container">
//在页面放着二维码的div
<div id="qrcode" ref="qrcode" align="middle">
</div>
</div>
</template>
methods: {
//生成二维码
qrcodeScan() {
this.$refs.qrcode.innerHTML = "";//将div中的内容先清空,否知第二次打开页面会有2个二维码
let qrcode = new QRCode(this.$refs.qrcode, {
width: 200, // 二维码宽度
height: 200, // 二维码高度
text: "https://blog.csdn.net/qq_33007465?spm=1019.2139.3001.5343",//二维码内容
});
qrcode._el.title='';//鼠标放在二维码上不显示文本内容
},
}
};
二、 vue项目的列表页面,每条数据后添加按钮,点击按钮弹窗展示二维码。
<!--查看二维码-->
<el-dialog :title="qrcodetitle" :visible.sync="qrcodeopen" width="400px" append-to-body>
<div id="qrcode" ref="qrcode" align="middle">
</div>
</el-dialog>
- 在return里面定义弹出层标题和是否展示弹出层
return {
active: 1,
// 弹出层标题
qrcodetitle: "",
// 二维码弹出层
qrcodeopen: false
}
- 点击按钮事件中将二维码弹出层赋值为true,打开弹出层,给弹出层的关闭按钮添加点击事件,将二维码弹出层赋值false。
methods: {
//查看二维码按钮
handleCode(row){
const id = row.id || this.ids;//商家id
const name = row.name;//商家名称
this.qrcodeopen = true;//弹出层打开
this.qrcodetitle = name + "收款二维码";//弹出层标题
this.$nextTick (function () {//调用生成二维码方法
this.qrcodeScan(id);
})
},
//生成二维码
qrcodeScan (id){
this.$refs.qrcode.innerHTML = "";//先将div内容清空,否知每次打开会多增加一个二维码
let qrcode = new QRCode(this.$refs.qrcode, {
width: 200, // 二维码宽度
height: 200, // 二维码高度
text: "https://blog.csdn.net/qq_33007465?spm=1019.2139.3001.5343",//二维码内容
});
qrcode._el.title='';//鼠标放在二维码上不显示文本内容
},
}
三、 controller层生成二维码保存到服务器上并存入数据中。
- controller层代码。
package com.ruoyi.merchant.utils;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import sun.misc.BASE64Encoder;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
public class QrCoder {
/**
* 图片的宽度
*/
private static final int IMAGE_WIDTH = 350;
/**
* 图片的高度(需按实际内容高度进行调整)
*/
private static final int IMAGE_HEIGHT = 420;
/**
* 二维码的宽度
*/
private static final int QR_CODE_WIDTH = 200;
/**
* 二维码的宽度
*/
private static final int QR_CODE_HEIGHT = 200;
private static final String FORMAT_NAME = "JPG";
/**
* @param imgLogo logo图片
* @param title 头部标题
* @param text 二维码内容
* @param content 二维码上方文字内容
* @param footer 底部文字
*/
public static BufferedImage createQrCode(String imgLogo, String title, String text, String content, String footer) {
// 头部文字区域高度
int titleHeight = 50;
// 创建主模板图片
BufferedImage image = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB);
Graphics2D main = image.createGraphics();
main.setColor(new Color(89, 146, 235)); //蓝色
main.fillRect(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
// 动态高度
int height = 0;
//***********************页面头部 文字****************
Graphics2D titleRight = image.createGraphics();
// 设置字体颜色 black黑 white白
titleRight.setColor(Color.black);
// 设置字体
Font titleFont = new Font("宋体", Font.BOLD, 25);
titleRight.setFont(titleFont);
titleRight.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
// 居中 x开始的位置:(图片宽度-字体大小*字的个数)/2
int x = (IMAGE_WIDTH - (titleFont.getSize() * title.length())) / 2;
titleRight.drawString(title, x, (titleHeight) / 2 + 10);
height += titleHeight;
//***************插入二维码图片***********************************************
Graphics codePic = image.getGraphics();
BufferedImage codeImg;
QrConfig config = new QrConfig();
config.setWidth(QR_CODE_WIDTH);
config.setHeight(QR_CODE_HEIGHT);
if (StrUtil.isNotBlank(imgLogo)) {
config.setImg(imgLogo);
}
codeImg = QrCodeUtil.generate(text, config);
// 绘制二维码
codePic.drawImage(codeImg, (IMAGE_WIDTH - QR_CODE_WIDTH) / 2, height, QR_CODE_WIDTH, QR_CODE_HEIGHT, null);
codePic.dispose();
//**********************中间文字部分*********
Graphics2D centerWord = image.createGraphics();
// 设置字体颜色,先设置颜色,再填充内容
centerWord.setColor(Color.white);
// 设置字体
Font wordFont = new Font("宋体", Font.BOLD, 20);
centerWord.setFont(wordFont);
centerWord.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
String[] info = content.split("-");
for (String s : info) {
// x开始的位置:(图片宽度-字体大小*字的个数)/2
int strWidth = centerWord.getFontMetrics().stringWidth(s);
// 总长度减去文字长度的一半 (居中显示)
int startX = (IMAGE_WIDTH - strWidth) / 2;
height += 30;
centerWord.drawString(s, startX, height);
}
//**********************底部公司名字*********
Graphics2D typeLeft = image.createGraphics();
// 设置字体颜色
typeLeft.setColor(Color.black);
// 设置字体
Font footerFont = new Font("宋体", Font.PLAIN, 10);
typeLeft.setFont(footerFont);
typeLeft.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
// x开始的位置:(图片宽度-字体大小*字的个数)/2
int startX = (IMAGE_WIDTH - (footerFont.getSize() * footer.length())) / 2;
height += QR_CODE_HEIGHT;
typeLeft.drawString(footer, startX, height);
//***************插入标志图片***********************************************
// Graphics signPic = image.getGraphics();
// BufferedImage signImg = null;
// try {
// signImg = ImageIO.read(new java.io.File(imgSign));
// } catch (Exception e) {
// }
//
// if (signImg != null) {
// signPic.drawImage(signImg, 0, 130, QR_CODE_WIDTH, QR_CODE_HEIGHT, null);
// signPic.dispose();
// }
// 返回image方便后续处理是生成图片还是生成base64字符串
return image;
}
// 生成图片文件
public static void createImage(BufferedImage image, String fileLocation) {
if (image != null) {
try {
ImageIO.write(image, "png", new File(fileLocation));
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 获取图片base64数据
public static String base64ImageString(BufferedImage image) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();//io流
ImageIO.write(image, FORMAT_NAME, bos);//写入流中
byte[] bytes = bos.toByteArray();//转换成字节
BASE64Encoder encoder = new BASE64Encoder();
String jpgBase64 = encoder.encodeBuffer(bytes).trim();//转换成base64串
jpgBase64 = jpgBase64.replaceAll("\n", "").replaceAll("\r", "");//删除 \r\n
return "data:image/jpg;base64," + jpgBase64;
}
//content是二维码上方的文字描述,通过 - 进行换行,默认是文字描述在上二维码在下,如果实现二维码在上文字在上,我使用----多个换行实现的。
//text是二维码的文本内容
//createImage方法中填写本地路径或者项目部署到服务器上的路径
//jar包部署的需要在nginx配置文件中配置图片的查看地址,tomcat的war包部署,需要在tomcat中配置静态文件查看地址
public static void main(String[] args) {
String content = "- - - - - - - -山东老字号菜品展览会-煎饼食品部-统一收款二维码- -";
String text = "填写二维码的内容";
BufferedImage bufferedImage = createQrCode(null, "", text, content, "测试数据");
createImage(bufferedImage, "/data/项目路径/项目的图片路径/test.png");
String url = "项目的域名+图片路径+图片名称.png";//将url存入对应数据中
}
}
- vue层代码
<!--查看二维码-->
<el-dialog :title="qrcodetitle" :visible.sync="qrcodeopen" width="400px" append-to-body>
<img :src="bookImg" style="width:350px;height:420px">
</el-dialog>
//查看二维码按钮
handleCode(row){
const id = row.id || this.ids;//商家id
const name = row.name;//商家名称
selectCode(id ).then(response => {
this.qrcodeopen = true;
this.qrcodetitle = name+ "收款二维码";
this.bookImg = response.msg;
})
},
四、将数据库的所有二维码图片放到文件夹中压缩成压缩包下载到本地
- controller代码
/**
* 批量下载二维码
*/
@PreAuthorize("@ss.hasPermi('xxxx:xxxx:download')")//权限
@GetMapping("/downloadCode")
public AjaxResult downloadCode()
{
return xxService.downloadCode();
}
- service层代码
public AjaxResult downloadCode() {
List<QrCode> list = xxMapper.downloadCode();//获取数据库中所有二维码图片地址
Long startTs = System.currentTimeMillis(); // 当前时间戳
String path = "/data/项目路径/图片存放路径/"+startTs.toString();
//在桌面新建文件夹(项目在本地启动时,可以在本地新建文件夹直接将图片写入文件夹)
File deleteFile = new File(path);
String mkDirectoryPath = path;
//删除文件夹
/* String[] cmd = new String[]{"/bin/sh", "-c", "rm -rf " + mkDirectoryPath};
try {
Process process = Runtime.getRuntime().exec(cmd);
} catch (IOException e) {
e.printStackTrace();
}*/
mkDirectory(mkDirectoryPath);
try {
for (int i = 0; i < list.size(); i++) {
QrCode qrCode = list.get(i);
String str = qrCode.getCodeUrl();//图片的地址
String name = qrCode.getBrandName();//图片的名称
URL url = new URL(str);
InputStream inputStream = null;
inputStream = url.openStream();
byte[] bytes = IOUtils.toByteArray(inputStream);
//获取用户本地桌面地址(在本地启动是可以使用)
//FileSystemView fsv = FileSystemView.getFileSystemView();
//File com = fsv.getHomeDirectory();
//将图片下载到文件夹中
File imageFile = new File(path+"/" + name + ".png");
//创建输出流
FileOutputStream outStream = new FileOutputStream(imageFile);
//写入数据
outStream.write(bytes);
//关闭输出流
outStream.close();
}
CompressedFileUtil.compressedFile(path, "/data/项目路径/图片路径/zip");
} catch (Exception e) {
return AjaxResult.error();
}
//将文件夹压缩之后的压缩包放到服务器项目路径下,把url地址传给前端vue
String codeUrl = "域名/项目路径/图片路径/zip/"+startTs.toString()+".zip";
return AjaxResult.success(codeUrl);
}
- vue前端
queryCode(){
this.$refs["codeform"].validate(valid => {
if (valid) {
this.$confirm('是否确认批量下载二维码?', "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
downloadCode(codeExhiId).then(response => {//调用下载二维码方法
console.log(response.msg);//返回的压缩包的url地址
window.location.href = response.msg;//直接打开url会把任务交给浏览器,浏览器自动下载
this.downloadQrCode = false;//关闭弹窗
});
});
}
})
},