✨ feat:
修改二维码生成逻辑,改为一次性二维码,存储更多信息
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
|
||||
import QRCode from 'qrcode';
|
||||
|
||||
/**
|
||||
* 通用js方法封装处理
|
||||
@@ -231,3 +231,117 @@ export function tansParams(params) {
|
||||
export function blobValidate(data) {
|
||||
return data.type !== 'application/json'
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存二维码为图片
|
||||
* @param {string} code 二维码内容
|
||||
* @param {string} text 下方文字
|
||||
* @param {number} index 索引,用于生成文件名
|
||||
* @param {Object} context Vue组件实例上下文(需要包含$message、barcodeWidth、barcodeHeight)
|
||||
*/
|
||||
export async function saveAsImage(code, text, index, context) {
|
||||
// 确保上下文存在
|
||||
if (!context) {
|
||||
console.error('缺少组件上下文,请传入Vue实例');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 检查QRCode库是否加载
|
||||
if (typeof QRCode === 'undefined') {
|
||||
throw new Error('QRCode库未加载,请确保已引入');
|
||||
}
|
||||
|
||||
// 创建临时canvas用于绘制二维码和文字
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
if (!ctx) {
|
||||
throw new Error('无法获取canvas上下文');
|
||||
}
|
||||
|
||||
// 从上下文获取尺寸参数,提供默认值
|
||||
const barcodeWidth = context.barcodeWidth || 200;
|
||||
const barcodeHeight = context.barcodeHeight || 200;
|
||||
const textHeight = 30; // 文字区域高度
|
||||
|
||||
canvas.width = barcodeWidth;
|
||||
canvas.height = barcodeHeight + textHeight;
|
||||
|
||||
// 绘制二维码
|
||||
const qrCanvas = document.createElement('canvas');
|
||||
qrCanvas.width = barcodeWidth;
|
||||
qrCanvas.height = barcodeHeight;
|
||||
|
||||
// 等待二维码绘制完成
|
||||
await new Promise((resolve, reject) => {
|
||||
QRCode.toCanvas(qrCanvas, code, {
|
||||
width: barcodeWidth,
|
||||
height: barcodeHeight,
|
||||
margin: 0,
|
||||
errorCorrectionLevel: 'M'
|
||||
}, (error) => {
|
||||
if (error) reject(error);
|
||||
else resolve();
|
||||
});
|
||||
});
|
||||
|
||||
// 将二维码绘制到主canvas
|
||||
ctx.drawImage(qrCanvas, 0, 0);
|
||||
|
||||
// 绘制文字(处理文字过长情况)
|
||||
ctx.fillStyle = '#000';
|
||||
ctx.font = '14px Arial, sans-serif';
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'top';
|
||||
|
||||
// 处理过长文字,最多显示2行
|
||||
const maxTextWidth = barcodeWidth - 20; // 预留边距
|
||||
let displayText = text;
|
||||
if (ctx.measureText(text).width > maxTextWidth) {
|
||||
// 尝试截断并添加省略号
|
||||
let i = text.length;
|
||||
while (ctx.measureText(text.substring(0, i)).width > maxTextWidth && i > 0) {
|
||||
i--;
|
||||
}
|
||||
displayText = text.substring(0, i) + '...';
|
||||
}
|
||||
ctx.fillText(displayText, barcodeWidth / 2, barcodeHeight + 5);
|
||||
|
||||
// 创建图片链接并下载
|
||||
canvas.toBlob(blob => {
|
||||
if (!blob) {
|
||||
throw new Error('无法生成图片blob对象');
|
||||
}
|
||||
|
||||
try {
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
|
||||
// 处理文件名特殊字符
|
||||
a.download = `二维码_${index + 1}.png`;
|
||||
a.href = url;
|
||||
|
||||
// 模拟点击下载
|
||||
document.body.appendChild(a);
|
||||
const event = new MouseEvent('click');
|
||||
a.dispatchEvent(event);
|
||||
|
||||
// 清理资源
|
||||
setTimeout(() => {
|
||||
document.body.removeChild(a);
|
||||
URL.revokeObjectURL(url);
|
||||
}, 100);
|
||||
|
||||
context.$message.success('图片保存成功');
|
||||
} catch (urlError) {
|
||||
console.error('创建下载链接失败:', urlError);
|
||||
context.$message.error('创建下载链接失败');
|
||||
}
|
||||
}, 'image/png'); // 明确指定MIME类型
|
||||
|
||||
} catch (error) {
|
||||
console.error('保存图片失败:', error);
|
||||
context.$message.error(`保存图片失败: ${error.message || '未知错误'}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user