若依二维码生成、下载、打印
初学二维码使用的过程,网上总是只贴部分代码,翻看了太多才一点点试着成功,有点费脑子,特此记录以供学习借鉴
1、前言
建立数据表
CREATE TABLE `test_v` (
`v_id` int NOT NULL AUTO_INCREMENT COMMENT 'id',
`v_name` varchar(255) DEFAULT NULL COMMENT 'name',
`v_card` varchar(255) DEFAULT NULL COMMENT 'card',
PRIMARY KEY (`v_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
若生代码自动生成页面
2、二维码生成
分别使用vue-qr和qrcodejs2插件生成二维码
2.1 使用vue-qr生成二维码
2.1.1 vue-qr 插件下载、引用
下载插件
npm install vue-qr
引用插件
import VueQr from 'vue-qr';
export default{
components: { VueQr },
}
2.1.2 vue-qr 生成二维码
el-table中添加操作“生成二维码(VueQr)”按钮,代码如下:
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-info"
@click="handleGenetateVueQrCode(scope.row)"
>生成二维码(VueQr)</el-button>
</el-table-column>
添加变量VueQrCode,存储vue-qr二维码生成的相关参数,代码如下:
VueQrCode:{
// id
id:"VQid",
// 打开弹窗是否
ishow:false,
// 二维码实点颜色
dark: null,
// 二维码空白颜色
light: null,
// ref
ref:"VueQrCodeDlg",
// qrcode
QrCode:null,
// 存放生成的二维码url
CodeUrl:null,
// 嵌入二维码中心的logo图片地址
logoSrc:require('@/assets/logo/logo.png'),
width:256,
height:256,
text:null,
size:256 ,
logoScale:0.3,
margin:5,
Radius:0,
correctLevel:3,
},
添加el-dialog,当点击“生成二维码(VueQr)”按钮时,弹出对话框显示生成的二维码,并在二维码上下分别添加文字,代码如下:
<!-- 二维码弹窗 import VueQr from 'vue-qr'; -->
<el-dialog :title="title" :visible.sync="VueQrCode.ishow" width="500px" append-to-body>
<div style="margin-left:100px;">
<vue-qr
:id="VueQrCode.id"
:ref="VueQrCode.ref"
:logoSrc="VueQrCode.logoSrc"
:text="VueQrCode.text"
:size="VueQrCode.size"
:logoScale="VueQrCode.logoScale"
:callback="VueQrCodeCallback"
:margin="VueQrCode.margin"
:logoCornerRadius="VueQrCode.Radius"
:correctLevel="VueQrCode.correctLevel"
:color-dark="VueQrCode.dark"
:color-light="VueQrCode.light"
></vue-qr>
</div>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="VueQrdownloadCode">下 载</el-button>
<el-button @click="VueQrcancelDownload">取 消</el-button>
</div>
</el-dialog>
添加el-select,根据el-select内容(字典:sys_qr_type)选择生成普通二维码、带logo二维码、随机颜色二维码,代码如下:
export default
{
dicts: ['sys_qr_type'],
}
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-select
v-model="queryParams.barcodeType"
placeholder="请选择条码类型"
size="mini">
<el-option v-for="dict in dict.type.sys_qr_type"
:key="dict.value" :label="dict.label"
:value="dict.value"></el-option>
</el-select>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
生成二维码,代码如下:
// 生成二维码(vue-qr)
handleGenetateVueQrCode(row){
var type=this.queryParams.barcodeType;
switch (type) {
case '0':
// 普通二维码
this.QrJsCode.dark = 'black';
this.QrJsCode.light = 'white';
this.QrJsCode.logoSrc = '';
break
case '1':
// 带log二维码
this.QrJsCode.dark = 'black';
this.QrJsCode.light = 'white';
this.QrJsCode.logoSrc = this.logo;
break
case '2':
// 随机颜色二维码
this.QrJsCode.dark = this.getColor();
this.QrJsCode.light = this.getColor();
this.QrJsCode.logoSrc = '';
break
case '3':
// 随机颜色二维码
this.QrJsCode.dark = this.getColor();
this.QrJsCode.light = this.getColor();
this.QrJsCode.logoSrc = this.logo;
break
default:
// 普通二维码
this.QrJsCode.dark = 'black';
this.QrJsCode.light = 'white';
this.QrJsCode.logoSrc = '';
break
}
this.VueQrCode.ishow = true;
this.title = '二维码';
if(this.VueQrCode.QrCode!==null)
{
this.$refs.VueQrCodeDlg.innerHTML = ""; //清空二维码,避免生成多个二维码
}
this.VueQrCode.text=row.vId+row.vCard; // 生成二维码的内容
this.VueQrCode.dark=this.getColor();
this.VueQrCode.light=this.getColor();
},
// 生成随机颜色
getColor() {
var str = '#'
var arr = ['1', '2', '3', '4', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']
for (var i = 0; i < 6; i++) {
var num = parseInt(Math.random() * 16)
str += arr[num]
}
return str
},
// vue-qr 回调.如果有额外的需求,可以在回调函数里操作.如添加文字,原理是拿到生成的二维码后通过 canvas 对图片进行加工
VueQrCodeCallback (dataUrl) {
this.VueQrCode.CodeUrl = dataUrl // 可用于canvas画图制作分享海报
var text="进出准许证"
this.VueQrAddText(dataUrl,text);
},
// vue-qr二维码 添加文字
VueQrAddText(dUrl,text)
{
const img = new Image();
img.src = dUrl;
img.onload = () => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
// 设置轮廓颜色和宽度
ctx.strokeStyle = '#994AE7';
ctx.lineWidth = 3;
// 绘制文字轮廓
ctx.strokeText(text, canvas.width / 2 - ctx.measureText(text).width / 2, canvas.height / 1.6);
ctx.font = 'bold 10px'; // 设置字体大小和类型
ctx.fillStyle = 'white'; // 设置字体颜色
ctx.fillText(text, canvas.width / 2 - ctx.measureText(text).width / 2, canvas.height / 1.6); // 在图片中心添加文字
document.getElementById(this.VueQrCode.id).src = canvas.toDataURL('image/png');
};
},
效果图如下:
普通二维码效果图如下:
2.1.3 vue-qr 下载二维码
// 下载二维码
VueQrdownloadCode(){
// 方法2:
let name = new Date().getTime();
let a = document.createElement("a");
a.style.display = "none";
a.download = name;
a.href = this.VueQrCode.CodeUrl;
document.body.appendChild(a);
a.click();
a.remove();
},
// 取消
VueQrcancelDownload(){
this.VueQrCode.ishow = false;
this.$refs.VueQrCodeDlg.innerHTML = ""; //清空二维码,避免生成多个二维码
},
2.2 使用qrcodejs2生成二维码
2.2.1 qrcodejs2插件下载、引用
下载插件
npm install qrcodejs2
引用插件
import QRCode from 'qrcodejs2';
2.2.2 qrcodejs2 生成二维码
el-table中添加操作“生成二维码(QrJs)”
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-info"
@click="handleGenetateQrJsCode(scope.row)"
>生成二维码(QrJs)</el-button>
</template>
</el-table-column>
添加变量QrJsCode,存储qrcodejs2二维码生成的相关参数
// qrcodejs2二维码
QrJsCode:{
// id
id:"QrJsCodeId",
// ref
ref:"QrJsCodeDlg",
// 打开弹窗是否
ishow:false,
ishow2:false,
// 二维码内容
text:null,
// 嵌入二维码中心的logo图片地址
logoSrc:null,
// 二维码实点颜色
dark: null,
// 二维码空白颜色
light: null,
// qrcode
QrJs:null,
// 宽高
width:"256",
heigth:"256",
// logo图片宽高
lwidth:"60",
lheight:"60",
},
添加el-dialog,当点击“生成二维码(QrJs)”按钮时,弹出对话框显示生成的二维码,并在二维码上下分别添加文字
<!-- 二维码弹窗 import QRCode from 'qrcodejs2'; -->
<el-dialog :title="title" :visible.sync="QrJsCode.ishow" width="500px" append-to-body >
<p style="text-align: center; font-size: 2rem;">准许证</p>
<div style="margin-left:70px;">
<div class="QrJsCodeStyle" id="QrJsCodeId" :ref="QrJsCode.ref" :callback="QrJsCodeCallback" >
</div>
</div>
<p style="text-align: center; font-size: 2rem;">{{ this.QrJsCode.text }}</p>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="QrJsdownloadCode">下 载</el-button>
<el-button @click="QrJscancelDownload">取 消</el-button>
</div>
</el-dialog>
生成二维码,代码如下:
// 二维码logo
logo:require('@/assets/logo/logo.png'),
// 生成二维码(qrcodejs2)
handleGenetateQrJsCode(row){
var type=this.queryParams.barcodeType;
switch (type) {
case '0':
// 普通二维码
this.QrJsCode.dark = 'black';
this.QrJsCode.light = 'white';
this.QrJsCode.logoSrc = '';
break
case '1':
// 带log二维码
this.QrJsCode.dark = 'black';
this.QrJsCode.light = 'white';
this.QrJsCode.logoSrc = this.logo;
break
case '2':
// 随机颜色二维码
this.QrJsCode.dark = this.getColor();
this.QrJsCode.light = this.getColor();
this.QrJsCode.logoSrc = '';
break
case '3':
// 随机颜色二维码
this.QrJsCode.dark = this.getColor();
this.QrJsCode.light = this.getColor();
this.QrJsCode.logoSrc = this.logo;
break
default:
// 普通二维码
this.QrJsCode.dark = 'black';
this.QrJsCode.light = 'white';
this.QrJsCode.logoSrc = '';
break
}
this.QrJsCode.ishow = true;
this.title = '二维码';
// this.QrJsCode.dark=this.getColor();
// this.QrJsCode.light=this.getColor();
// this.QrJsCode.logoSrc=this.logo;
this.QrJsCode.text=row.vId+row.vCard;
if(this.QrJsCode.QrJs!==null)
{
this.$refs.QrJsCodeDlg.innerHTML = ""; //清空二维码,避免生成多个二维码
}
this.$nextTick(() => {
this.QrJsCode.QrJs = new QRCode(this.$refs.QrJsCodeDlg, {
text: this.QrJsCode.text, // 生成二维码的内容
//logoSrc:this.QrJsCode.logoSrc,// qrcodejs2没有logo
colorDark:this.QrJsCode.dark,
colorLight:this.QrJsCode.light,
width: this.QrJsCode.width,
height: this.QrJsCode.heigth,
correctLevel: QRCode.CorrectLevel.H, //二维码容错等级
});
});
if(this.QrJsCode.logoSrc)
{
this.addLogo();
}
var text="进出准许证"
this.QrJsAddText(this.QrJsCode.CodeUrl,text);
},
// qrcodejs2 添加logog
addLogo(){
// 加工要显示的图片
let logo = new Image();
logo.crossOrigin = 'Anonymous';
// 填入你本地log图片
logo.src = this.logo;
logo.onload = () => {
//获取页面上展示二维码的容器并清空
let container = document.getElementById('QrJsCodeId');
//将没有图片的二维码与照片合并在一起
// 获取二维码
let qrImg = this.QrJsCode.QrJs._el.getElementsByTagName('img')[0];
// 获取canvas
let canvas = this.QrJsCode.QrJs._el.getElementsByTagName('canvas')[0];
let ctx = canvas.getContext("2d");
// 写入log
ctx.drawImage(logo, this.QrJsCode.width * 0.5 - this.QrJsCode.lwidth*0.5, this.QrJsCode.width * 0.5 - this.QrJsCode.lheight*0.5, this.QrJsCode.lwidth, this.QrJsCode.lheight);
//将图片转化成链接地址
qrImg.src = canvas.toDataURL();
//将生成有图片的二维码追加到页面二维码容器中
container.appendChild(this.QrJsCode.QrJs._el);
}
},
效果图如下:
普通二维码效果图如下:
带logo二维码效果图如下:
随机颜色二维码效果图如下:
带logo+随机颜色二维码效果图如下:
2.2.3 qrcodejs2 下载二维码
// 下载二维码
QrJsdownloadCode(){
let that = this;
//获取二维码中格式为imag的元素
const nodeList = Array.prototype.slice.call(that.QrJsCode.QrJs._el.children)
const img = nodeList.find((item) => item.nodeName.toUpperCase() === 'IMG') // 选出图片类型
// 构建画布
let canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
canvas.getContext('2d').drawImage(img, 0, 0);
// 构造url
let url = canvas.toDataURL('image/png');
const a = document.createElement("a");
a.href = url;
a.download = `二维码.png`;
// 触发a链接点击事件,浏览器开始下载文件
a.click();
},
// 取消
QrJscancelDownload(){
this.QrJsCode.ishow = false;
this.$refs.QrJsCodeDlg.innerHTML = ""; //清空二维码,避免生成多个二维码
},
2.3 el-table中生成二维码
2.3.1 生成二维码
依然使用vue-qr插件,代码如下:
<el-table-column label="二维码" width="170" align="center">
<template slot-scope = "scope" >
<p>准许证</p>
<!-- 生成二维码 -->
<vue-qr
:ref="'ref'+scope.row.vId"
:size="80"
:margin="0"
:auto-color="true"
:dot-scale="1"
:text = "scope.row.vId+scope.row.vCard"/>
<p>{{scope.row.vId+'_'+scope.row.vName+'_'+scope.row.vCard}}</p>
</template>
</el-table-column>
添加打印插件
import print from 'print-js'; // 引入print JS库
data(){
// 打印的内容
printable:[],
}
添加“打印防伪码(VueQr)”按钮,代码如下:
<el-row :gutter="10" class="mb8">
<el-button
type="info"
plain
icon="el-icon-download"
size="mini"
@click="handlePrinter"
>打印防伪码(VueQr)</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
2.3.2 打印二维码
选择多行表格数据时,点击“打印防伪码”按钮,获取生成的二维码,并打印二维码,代码如下:
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.vId)
this.single = selection.length!==1
this.multiple = !selection.length
this.selectNum=selection.length;
// 获取生成之后的防伪码Src
this.printable=selection.map(item => this.$refs['ref'+item.vId].$el.src)
console.log(this.printable);
console.log(this.multipleSelection);
},
打印已生成的二维码,代码如下:
// 批量打印按钮点击事件
handlePrinter(){
console.log("print = ",this.printable);
printJS({
// 把勾选的img图片放入下面数组打印
printable:this.printable,
// 打印类型
type:'image',
// 二维码样式
imageStyle:'margin:0px; padding:0px; width:40%; height:40%; display: block;margin: 0 auto; padding-top:12%',
})
},
效果图如下:
以pdf格式保存二维码图片。
2.4 批量单独保存二维码图片
待续…
2.5 批量单独打印二维码图片
待续…
3、若依后端生成、下载、保存、打印二维码
待续…
4、总结
以上内容均学习、借鉴于CSDN博主,整理二维码使用过程,分享给大家。
全部代码:
a. 2.4节以前所有代码
上面粘贴的代码可能有遗漏,把所有代码全部粘贴在下面(可能有点乱)
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="name" prop="vName">
<el-input
v-model="queryParams.vName"
placeholder="请输入name"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="card" prop="vCard">
<el-input
v-model="queryParams.vCard"
placeholder="请输入card"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
<!-- <el-form-item label="条码类型" prop="barcodeType">
<el-select v-model="queryParams.barcodeType" placeholder="请选择条码类型">
<el-option v-for="dict in dict.type.sys_qr_type" :key="dict.value" :label="dict.label"
:value="dict.value"></el-option>
</el-select>
</el-form-item> -->
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['learn:vistor:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['learn:vistor:edit']"
>修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['learn:vistor:remove']"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
v-hasPermi="['learn:vistor:export']"
>导出</el-button>
</el-col>
<el-col :span="1.5">
<el-select
v-model="queryParams.barcodeType"
placeholder="请选择条码类型"
size="mini">
<el-option v-for="dict in dict.type.sys_qr_type"
:key="dict.value" :label="dict.label"
:value="dict.value"></el-option>
</el-select>
</el-col>
<el-col :span="1.5">
<el-button
type="info"
plain
icon="el-icon-download"
size="mini"
@click="handleBatchGenerationQrJs"
>生成二维码(QrJs)</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="info"
plain
icon="el-icon-download"
size="mini"
@click="handleBatchGenerationVueQr"
>生成二维码(VueQr)</el-button>
<el-button
type="info"
plain
icon="el-icon-download"
size="mini"
@click="handlePrinter"
>打印防伪码(VueQr)</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="vistorList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="id" align="center" prop="vId" />
<el-table-column label="name" align="center" prop="vName" />
<el-table-column label="card" align="center" prop="vCard" />
<el-table-column label="二维码" width="170" align="center">
<template slot-scope = "scope" >
<p>准许证</p>
<!-- 生成二维码 -->
<vue-qr
:ref="'ref'+scope.row.vId"
:size="80"
:margin="0"
:auto-color="true"
:dot-scale="1"
:text = "scope.row.vId+scope.row.vCard"/>
<p>{{scope.row.vId+'_'+scope.row.vName+'_'+scope.row.vCard}}</p>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['learn:vistor:edit']"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['learn:vistor:remove']"
>删除</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-info"
@click="handleGenetateQrJsCode(scope.row)"
>生成二维码(QrJs)</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-info"
@click="handleGenetateVueQrCode(scope.row)"
>生成二维码(VueQr)</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-info"
@click="handlePrinter(scope.row)"
>打印防伪码</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改vistor对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="name" prop="vName">
<el-input v-model="form.vName" placeholder="请输入name" />
</el-form-item>
<el-form-item label="card" prop="vCard">
<el-input v-model="form.vCard" placeholder="请输入card" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</el-dialog>
<!-- 二维码弹窗 import QRCode from 'qrcodejs2'; -->
<el-dialog :title="title" :visible.sync="QrJsCode.ishow" width="500px" append-to-body >
<p style="text-align: center; font-size: 2rem;">准许证</p>
<div style="margin-left:70px;">
<div class="QrJsCodeStyle" id="QrJsCodeId" :ref="QrJsCode.ref" :callback="QrJsCodeCallback" >
</div>
</div>
<p style="text-align: center; font-size: 2rem;">{{ this.QrJsCode.text }}</p>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="QrJsdownloadCode">下 载</el-button>
<el-button @click="QrJscancelDownload">取 消</el-button>
</div>
</el-dialog>
<!-- 二维码弹窗(批量) import QRCode from 'qrcodejs2'; -->
<!-- <el-dialog :title="title" :visible.sync="QrJsCode.ishow2" width="500px" append-to-body>
<div v-for="(item, index) in QrJsList" :key="item.id">
<div>
<div ref="QrJsCodeDlg2" :id="'codeImgbox' + index">111111</div>
<div>1111111</div>
</div>
</div>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="QrJsdownloadCode">下 载</el-button>
<el-button @click="QrJscancelDownload2">取 消</el-button>
</div>
</el-dialog> -->
<el-dialog :title="title" :visible.sync="QrJsCode.ishow2" width="500px" append-to-body>
<!-- <div v-for="(item, index) in QrJsDataList" :key="index"> -->
<div v-for="item in QrJsDataList" :key="item.vId">
<p style="text-align: center; font-size: 2rem;">准许证</p>
<div style="margin-left:70px;">
<div class="QrJsCodeStyle" id="QrJsCodeId2" ref="QrJsCodeDlg2">
</div>
</div>
<p style="text-align: center; font-size: 2rem;">{{ item }}</p>
</div>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="QrJsdownloadCode">下 载</el-button>
<el-button @click="QrJscancelDownload2">取 消</el-button>
<el-button @click="QrJscancelPrint2">打印</el-button>
</div>
</el-dialog>
<!-- 二维码弹窗 import VueQr from 'vue-qr'; -->
<el-dialog :title="title" :visible.sync="VueQrCode.ishow" width="500px" append-to-body>
<div style="margin-left:100px;">
<vue-qr
:id="VueQrCode.id"
:ref="VueQrCode.ref"
:logoSrc="VueQrCode.logoSrc"
:text="VueQrCode.text"
:size="VueQrCode.size"
:logoScale="VueQrCode.logoScale"
:callback="VueQrCodeCallback"
:margin="VueQrCode.margin"
:logoCornerRadius="VueQrCode.Radius"
:correctLevel="VueQrCode.correctLevel"
:color-dark="VueQrCode.dark"
:color-light="VueQrCode.light"
></vue-qr>
</div>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="VueQrdownloadCode">下 载</el-button>
<el-button @click="VueQrcancelDownload">取 消</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listVistor, getVistor, delVistor, addVistor, updateVistor } from "@/api/learn/vistor";
import QRCode from 'qrcodejs2'; // 2024.08.03 添加:二维码
// import QRCode from 'qrcode';
import VueQr from 'vue-qr'; // 2024.08.03 添加:二维码
// import VueQr from 'vue-qr/src/packages/vue-qr.vue';
import JSZip from 'jszip' // 2024.08.03 添加:zip压缩包
import print from 'print-js'; // 引入print JS库
export default
{
name: "Vistor",
// sys_qr_type:条形码类型;mes_barcode_formart:条形码格式
dicts: ['sys_qr_type', 'mes_barcode_formart'],
components: { VueQr },
// 父组件向子组件传递的值
props:['rowQrData'],
data() {
return {
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 2024.08.03 添加:选择个数
selectNum:0,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// vistor表格数据
vistorList: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
vName: null,
vCard: null,
// 条形码类型
barcodeType:null,
},
// 表单参数
form: {},
// 表单校验
rules: {
},
nameList:{},
zip:null,
// 存放生成的二维码url
qrCodeUrl: '',
// 二维码logo
logo:require('@/assets/logo/logo.png'),
//设置需要的数据
QrJsList:[],
QrJsDataList:[],
// qrcodejs2二维码
QrJsCode:{
// id
id:"QrJsCodeId",
// ref
ref:"QrJsCodeDlg",
// 打开弹窗是否
ishow:false,
ishow2:false,
// 二维码内容
text:null,
// 嵌入二维码中心的logo图片地址
logoSrc:null,
// 二维码实点颜色
dark: null,
// 二维码空白颜色
light: null,
// qrcode
QrJs:null,
// 宽高
width:"256",
heigth:"256",
// logo宽高
lwidth:"60",
lheight:"60",
},
VueQrCode:{
// id
id:"VQid",
// 打开弹窗是否
ishow:false,
// 二维码实点颜色
dark: null,
// 二维码空白颜色
light: null,
// ref
ref:"VueQrCodeDlg",
// qrcode
QrCode:null,
// 存放生成的二维码url
CodeUrl:null,
// 嵌入二维码中心的logo图片地址
logoSrc:require('@/assets/logo/logo.png'),
width:256,
height:256,
text:null,
size:256 ,
logoScale:0.3,
margin:5,
Radius:0,
correctLevel:3,
},
// 打印的内容
printable:[],
};
},
created() {
this.getList();
},
methods: {
/** 查询vistor列表 */
getList() {
this.loading = true;
listVistor(this.queryParams).then(response => {
this.vistorList = response.rows;
this.total = response.total;
this.loading = false;
});
},
// 取消按钮
cancel() {
this.open = false;
this.reset();
},
// 表单重置
reset() {
this.form = {
vId: null,
vName: null,
vCard: null
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.vId)
this.single = selection.length!==1
this.multiple = !selection.length
this.selectNum=selection.length;
// 获取id和card
this.QrJsDataList= selection.map(item => item.vId+item.vCard)
console.log("QrJsDataList = ",this.QrJsDataList);
// 获取生成之后的防伪码Src
this.printable=selection.map(item => this.$refs['ref'+item.vId].$el.src)
console.log(this.printable);
console.log(this.multipleSelection);
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加vistor";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const vId = row.vId || this.ids
getVistor(vId).then(response => {
this.form = response.data;
this.open = true;
this.title = "修改vistor";
});
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.vId != null) {
updateVistor(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addVistor(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const vIds = row.vId || this.ids;
this.$modal.confirm('是否确认删除vistor编号为"' + vIds + '"的数据项?').then(function() {
return delVistor(vIds);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
/** 导出按钮操作 */
handleExport() {
this.download('learn/vistor/export', {
...this.queryParams
}, `vistor_${new Date().getTime()}.xlsx`)
},
// 2024.08.03 添加:批量生成二维码
handleBatchGenerationQrJs()
{
//this.QrJsDataList = [];//设置需要的数据
this.QrJsCode.ishow2=true;
console.log("ishow2 = ",this.QrJsCode.ishow2);
this.bindQRCode(this.QrJsDataList); //组装完数据后调用生成二维码的方法
// const vIds = row.vId || this.ids;
// this.QrJsCode.text=vIds.vId+vIds.vCard;
},
bindQRCode(QrJsDataList){
var type=this.queryParams.barcodeType;
console.log("type = ",type);
switch (type) {
case '0':
console.log("case = 0");
// 普通二维码
this.QrJsCode.dark = 'black';
this.QrJsCode.light = 'white';
this.QrJsCode.logoSrc = '';
break
case '1':
console.log("case = 1");
// 带log二维码
this.QrJsCode.dark = 'black';
this.QrJsCode.light = 'white';
this.QrJsCode.logoSrc = this.logo;
break
case '2':
console.log("case = 2");
// 随机颜色二维码
this.QrJsCode.dark = this.getColor();
this.QrJsCode.light = this.getColor();
this.QrJsCode.logoSrc = '';
break
case '3':
console.log("case = 3");
// 随机颜色二维码
this.QrJsCode.dark = this.getColor();
this.QrJsCode.light = this.getColor();
this.QrJsCode.logoSrc = this.logo;
break
default:
console.log("case = default");
// 普通二维码
this.QrJsCode.dark = 'black';
this.QrJsCode.light = 'white';
this.QrJsCode.logoSrc = '';
break
}
console.log("dark = ",this.QrJsCode.dark);
console.log("light = ",this.QrJsCode.light);
console.log("logoSrc = ",this.QrJsCode.logoSrc);
console.log("len = ",this.QrJsDataList.length);
console.log("QrJsDataList = ",this.QrJsDataList);
this.$nextTick(() => {
this.QrJsDataList.forEach((item,index)=>{
console.log("index = ",index);
console.log("type = ",typeof index);
console.log("type = ",this.$refs.QrJsCodeDlg2[index]);
this.$refs.QrJsCodeDlg2[index].innerHTML="";
console.log("text = ",this.QrJsDataList[index]);
this.QrJsList[index] = new QRCode(this.$refs.QrJsCodeDlg2[index], {
// 生成二维码的内容
text:this.QrJsDataList[index],
//logoSrc:this.QrJsCode.logoSrc,// qrcodejs2没有logo
// colorDark:this.QrJsCode.dark,
// colorLight:this.QrJsCode.light,
render: 'table',
// width: this.QrJsCode.width,
// height: this.QrJsCode.heigth,
// correctLevel: QRCode.CorrectLevel.H, //二维码容错等级
})
//this.QrJsList=qj.$el.src
// var childs = document.getElementsByClassName('QrJsCodeId2')[index].childNodes;
// document.getElementsByClassName('QrJsCodeId2')[index].removeChild(childs[0]);
});
},this.QrJsDataList.length)
//初始化
// this.nameList = {}
// this.zip = null
// this.zip = new JSZip()
// // 获取外部容器.get-Element-By-Id,就是通过ID来设置/返回HTML标签的属性及调用其事件与方法。用这个方法基本上可以控制页面所有标签,条件很简单就是给每个标签分配一个ID号
// const divBox = document.getElementById('container');
// console.log("divBox = ",divBox);
// // 异步使用for循环顺序执行正常
// console.log("this.selectNum = ",this.selectNum);
// for (let i = 0; i < this.selectNum; i++) {
// //console.log("document.getElementById('input').value = ",document.getElementById('input').value);
// // 随机值
// const key = Math.random() * 100000000000000000
// // 制作一个div
// let div = document.createElement('div')
// // 将div放入外部容器
// divBox.appendChild(div)
// // 唯一id
// div.id = `id${i}`
// // style主要是为了使多个div重叠,且不出问题(ps:将单双数的二维码大小区分开)
// div.style = `width: 324px;height: ${i%2?200:350}px;background-color: white;position:absolute;z-index: -1`
// //创造一个二维码div
// let qrcodeDiv = document.createElement('div')
// qrcodeDiv.id = `qrcode${i}`
// div.appendChild(qrcodeDiv)
// qrcodeDiv.style = `margin-top: 8px;width: 324px;height:${i%2?150:300}px;display:flex;justify-content:center ;align-items:center ;`
// var qrcode = new QRCode(qrcodeDiv, {
// width: i%2?150:300,
// height: i%2?150:300
// });
// // 生成二维码
// qrcode.makeCode(key);
// // 创造一个key值div
// let keyDiv = document.createElement('div')
// div.appendChild(keyDiv)
// keyDiv.style = `margin-top: 8px;width: 324px;height:40px;text-align:center;font-size:14px;color:#1890ff`
// keyDiv.innerHTML = key
// // 把需要传的值做好
// const data = {
// id: `#id${i}`,
// name: `${key}.png`,
// over:i === (document.getElementById('input').value - 1)
// }
// // 执行多元下载方法
// transition(data);
// }
},
// 打印
QrJscancelPrint2(){
// console.log("print = ",this.QrJsList);
// printJS({
// // 把勾选的img图片放入下面数组打印
// printable:this.QrJsList,
// // 打印类型
// type:'image',
// // 二维码样式
// imageStyle:'margin:0px; padding:0px; width:40%; height:40%; display: block;margin: 0 auto; padding-top:12%',
// })
this.$print(this.$refs.QrJsCodeDlg2);
},
// 批量生成二维码
handleBatchGenerationVueQr(){
},
// 2024.08.03 添加:
transition(data) {
html2canvas($(data.id), {
onrendered: function(canvas) {
var dataUrl = canvas.toDataURL('image/png', 1.0);
var imgdata = dataUrl.split(',')
// 将base64位文件放入压缩包
setFile(data.name, imgdata[1], 1, data.name)
// 判断为最后一个打包下载
if (data.over) {
this.zip.generateAsync({
type: 'blob'
})
.then(function(content) {
saveAs(content, "二维码合集.zip")
})
}
//删除原来的div
document.getElementById(data.id.split('#')[1]).outerHTML = ''
}
})
},
// 2024.08.03 添加:文件名去重(压缩包内不能有重复名字的文件,不然会覆盖)
setFile(name, imgdata, i, oldName) {
if (this.nameList[name]) {
//名字重复则在后面加(数字)
var newName = oldName.split('.png')[0] + `(${i}).png`
console.log("setFile() - newName = ",newName);
var newI = i + 1
//递归执行
setFile(newName, imgdata, newI, oldName)
} else {
//名字不重复则名字加入名字除重列表
this.nameList[name] = true
this.zip.file(name, imgdata, {
base64: true
})
}
},
// 生成随机颜色
getColor() {
var str = '#'
var arr = ['1', '2', '3', '4', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']
for (var i = 0; i < 6; i++) {
var num = parseInt(Math.random() * 16)
str += arr[num]
}
return str
},
// 生成二维码(qrcodejs2)
handleGenetateQrJsCode(row){
var type=this.queryParams.barcodeType;
switch (type) {
case '0':
// 普通二维码
this.QrJsCode.dark = 'black';
this.QrJsCode.light = 'white';
this.QrJsCode.logoSrc = '';
break
case '1':
// 带log二维码
this.QrJsCode.dark = 'black';
this.QrJsCode.light = 'white';
this.QrJsCode.logoSrc = this.logo;
break
case '2':
// 随机颜色二维码
this.QrJsCode.dark = this.getColor();
this.QrJsCode.light = this.getColor();
this.QrJsCode.logoSrc = '';
break
case '3':
// 随机颜色二维码
this.QrJsCode.dark = this.getColor();
this.QrJsCode.light = this.getColor();
this.QrJsCode.logoSrc = this.logo;
break
default:
// 普通二维码
this.QrJsCode.dark = 'black';
this.QrJsCode.light = 'white';
this.QrJsCode.logoSrc = '';
break
}
this.QrJsCode.ishow = true;
this.title = '二维码';
// this.QrJsCode.dark=this.getColor();
// this.QrJsCode.light=this.getColor();
// this.QrJsCode.logoSrc=this.logo;
this.QrJsCode.text=row.vId+row.vCard;
if(this.QrJsCode.QrJs!==null)
{
this.$refs.QrJsCodeDlg.innerHTML = ""; //清空二维码,避免生成多个二维码
}
this.$nextTick(() => {
this.QrJsCode.QrJs = new QRCode(this.$refs.QrJsCodeDlg, {
text: this.QrJsCode.text, // 生成二维码的内容
//logoSrc:this.QrJsCode.logoSrc,// qrcodejs2没有logo
colorDark:this.QrJsCode.dark,
colorLight:this.QrJsCode.light,
width: this.QrJsCode.width,
height: this.QrJsCode.heigth,
correctLevel: QRCode.CorrectLevel.H, //二维码容错等级
});
});
if(this.QrJsCode.logoSrc)
{
this.addLogo();
}
var text="进出准许证"
this.QrJsAddText(this.QrJsCode.CodeUrl,text);
},
// qrcodejs2 添加logog
addLogo(){
// 加工要显示的图片
let logo = new Image();
logo.crossOrigin = 'Anonymous';
// 填入你本地log图片
logo.src = this.logo;
logo.onload = () => {
//获取页面上展示二维码的容器并清空
let container = document.getElementById('QrJsCodeId');
//将没有图片的二维码与照片合并在一起
// 获取二维码
let qrImg = this.QrJsCode.QrJs._el.getElementsByTagName('img')[0];
// 获取canvas
let canvas = this.QrJsCode.QrJs._el.getElementsByTagName('canvas')[0];
let ctx = canvas.getContext("2d");
// 写入log
ctx.drawImage(logo, this.QrJsCode.width * 0.5 - this.QrJsCode.lwidth*0.5, this.QrJsCode.width * 0.5 - this.QrJsCode.lheight*0.5, this.QrJsCode.lwidth, this.QrJsCode.lheight);
//将图片转化成链接地址
qrImg.src = canvas.toDataURL();
//将生成有图片的二维码追加到页面二维码容器中
container.appendChild(this.QrJsCode.QrJs._el);
}
},
// 重新生成二维码(qrcodejs2)
resetQrJsCode(){
this.QrJsCode.QrJs.clear();
this.QrJsCode.QrJs.makeCode(this.QrJsCode.text); // 加logo后无法刷新
},
// 回调函数
QrJsCodeCallback(dataUrl){
this.QrJsCode.CodeUrl = dataUrl // 可用于canvas画图制作分享海报
var text="进出准许证"
this.QrJsAddText(dataUrl,text);
},
// 添加文字
QrJsAddText(dUrl,text){
const img = new Image();
img.src = dUrl;
img.onload = () => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
// 设置轮廓颜色和宽度
ctx.strokeStyle = '#994AE7';
ctx.lineWidth = 3;
// 绘制文字轮廓
ctx.strokeText(text, canvas.width / 2 - ctx.measureText(text).width / 2, canvas.height / 1.6);
ctx.font = 'bold 10px'; // 设置字体大小和类型
ctx.fillStyle = 'white'; // 设置字体颜色
ctx.fillText(text, canvas.width / 2 - ctx.measureText(text).width / 2, canvas.height / 1.6); // 在图片中心添加文字
document.getElementById(this.QrJsCode.id).src = canvas.toDataURL('image/png');
};
},
// 生成二维码(vue-qr)
handleGenetateVueQrCode(row){
var type=this.queryParams.barcodeType;
this.rowQrData=row.vId+row.vCard;
switch (type) {
case '0':
// 普通二维码
this.QrJsCode.dark = 'black';
this.QrJsCode.light = 'white';
this.QrJsCode.logoSrc = '';
break
case '1':
// 带log二维码
this.QrJsCode.dark = 'black';
this.QrJsCode.light = 'white';
this.QrJsCode.logoSrc = this.logo;
break
case '2':
// 随机颜色二维码
this.QrJsCode.dark = this.getColor();
this.QrJsCode.light = this.getColor();
this.QrJsCode.logoSrc = '';
break
case '3':
// 随机颜色二维码
this.QrJsCode.dark = this.getColor();
this.QrJsCode.light = this.getColor();
this.QrJsCode.logoSrc = this.logo;
break
default:
// 普通二维码
this.QrJsCode.dark = 'black';
this.QrJsCode.light = 'white';
this.QrJsCode.logoSrc = '';
break
}
this.VueQrCode.ishow = true;
this.title = '二维码';
if(this.VueQrCode.QrCode!==null)
{
this.$refs.VueQrCodeDlg.innerHTML = ""; //清空二维码,避免生成多个二维码
}
this.VueQrCode.text=row.vId+row.vCard; // 替换为你要生成二维码的内容
this.VueQrCode.dark=this.getColor();
this.VueQrCode.light=this.getColor();
},
// 重新生成二维码(VueQr)
resetVueQrCode(){
this.VueQrCode.QrJs.clear();
this.VueQrCode.QrJs.makeCode(this.VueQrCode.text); // 加logo后无法刷新
},
// 下载二维码
QrJsdownloadCode(){
let that = this;
//获取二维码中格式为imag的元素
const nodeList = Array.prototype.slice.call(that.QrJsCode.QrJs._el.children)
const img = nodeList.find((item) => item.nodeName.toUpperCase() === 'IMG') // 选出图片类型
// 构建画布
let canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
canvas.getContext('2d').drawImage(img, 0, 0);
// 构造url
let url = canvas.toDataURL('image/png');
const a = document.createElement("a");
a.href = url;
a.download = `二维码.png`;
// 触发a链接点击事件,浏览器开始下载文件
a.click();
},
// 取消
QrJscancelDownload(){
this.QrJsCode.ishow = false;
this.$refs.QrJsCodeDlg.innerHTML = ""; //清空二维码,避免生成多个二维码
},
// 取消
QrJscancelDownload2(){
this.QrJsCode.ishow2 = false;
this.$refs.QrJsCodeDlg2.innerHTML = ""; //清空二维码,避免生成多个二维码
},
// 下载二维码
VueQrdownloadCode(){
// 方法2:
let name = new Date().getTime();
let a = document.createElement("a");
a.style.display = "none";
a.download = name;
a.href = this.VueQrCode.CodeUrl;
document.body.appendChild(a);
a.click();
a.remove();
},
// 取消
VueQrcancelDownload(){
this.VueQrCode.ishow = false;
this.$refs.VueQrCodeDlg.innerHTML = ""; //清空二维码,避免生成多个二维码
},
// vue-qr 回调.如果有额外的需求,可以在回调函数里操作.如添加文字,原理是拿到生成的二维码后通过 canvas 对图片进行加工
VueQrCodeCallback (dataUrl) {
this.VueQrCode.CodeUrl = dataUrl // 可用于canvas画图制作分享海报
var text="进出准许证"
this.VueQrAddText(dataUrl,text);
},
// vue-qr二维码 添加文字
VueQrAddText(dUrl,text)
{
const img = new Image();
img.src = dUrl;
img.onload = () => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
// 设置轮廓颜色和宽度
ctx.strokeStyle = '#994AE7';
ctx.lineWidth = 3;
// 绘制文字轮廓
ctx.strokeText(text, canvas.width / 2 - ctx.measureText(text).width / 2, canvas.height / 1.6);
ctx.font = 'bold 10px'; // 设置字体大小和类型
ctx.fillStyle = 'white'; // 设置字体颜色
ctx.fillText(text, canvas.width / 2 - ctx.measureText(text).width / 2, canvas.height / 1.6); // 在图片中心添加文字
document.getElementById(this.VueQrCode.id).src = canvas.toDataURL('image/png');
};
},
// 批量打印按钮点击事件
handlePrinter(){
console.log("print = ",this.printable);
printJS({
// 把勾选的img图片放入下面数组打印
printable:this.printable,
// 打印类型
type:'image',
// 二维码样式
imageStyle:'margin:0px; padding:0px; width:40%; height:40%; display: block;margin: 0 auto; padding-top:12%',
})
},
}
};
</script>
<style>
.QrJsCodeStyle{
/* box-sizing: border-box,元素的宽度和高度将会包括内容(content)、内边距(padding)和边框(border),但不包括外边距(margin)。这意味着,如果你给一个元素设置了宽度和高度,并且还给它添加了内边距和边框,元素的最终尺寸将不会增加,而是内容区域会根据设置的内边距和边框大小相应减小。 */
box-sizing: border-box;
width: 300px;
height: 300px;
/* 边框:border */
border: 5px solid #000000;
/* 内边距:padding */
padding: 4px;
/* 外边距:margin */
margin:10px;
/* border-radius 是CSS(层叠样式表)中的一个属性,它用于给HTML元素的边框创建圆角效果。 */
border-radius: 4px;
/* justify-content 是CSS(层叠样式表)中的一个属性,专门用于设置或检索弹性盒子(flexbox)元素在主轴(默认为水平方向,但可以通过设置 flex-direction 属性来改变)上的对齐方式。 */
justify-content: center;/* center:弹性项目在行中居中对齐。这意味着弹性项目会在容器的中心位置显示,两侧留有等量的空间。 */
/* align-items 是CSS(层叠样式表)中的一个属性,专门用于设置或检索弹性盒子(flexbox)容器内部所有项目(flex items)在交叉轴(cross axis)上的对齐方式。 */
align-items: center;
/* 为了方便观察效果,设置主轴为垂直方向 */
flex-direction: column;
/* 设置为flex容器 */
display: flex;
/* display: inline-block; */
}
</style>
b. 2.4节以前所有代码
待续…
错误问题
错误1:
logo:require(‘@/assets/logo/logo.png’)报错如下:
上述代码(学习测试)在联网的机子上,也报过错,但是网上查询改错后,修改了require写法,运行正常后以为是require写法有问题。但在脱网的机子上这样使用的时候却仍然一直报错。了解的同学麻烦解惑一下
解决方法:
// 在外部代码中引入Logo模块
import logo from '@/assets/logo/logo.png';
若依项目加载图片,require(‘@/src/assets/logo/logo.png’)报如下错误,如何解决?(语言-javascript)