feat(utils): 添加二维码处理逻辑
This commit is contained in:
2
public/wasm/README.txt
Normal file
2
public/wasm/README.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
zxing_full.wasm
|
||||
zxing-wasm v2.0.1
|
BIN
public/wasm/zxing_full.wasm
Normal file
BIN
public/wasm/zxing_full.wasm
Normal file
Binary file not shown.
252
src/assets/js/qr-code.js
Normal file
252
src/assets/js/qr-code.js
Normal file
@@ -0,0 +1,252 @@
|
||||
import {
|
||||
prepareZXingModule,
|
||||
readBarcodes,
|
||||
writeBarcode,
|
||||
} from 'zxing-wasm/full';
|
||||
|
||||
/**
|
||||
* @desc 二维码读取配置选项
|
||||
* @type { import('zxing-wasm').ReaderOptions }
|
||||
*/
|
||||
const readerOptions = {
|
||||
formats: ['QRCode'],
|
||||
maxNumberOfSymbols: 8,
|
||||
textMode: 'Plain',
|
||||
tryDownscale: true,
|
||||
tryHarder: true,
|
||||
tryInvert: true,
|
||||
tryRotate: true,
|
||||
};
|
||||
|
||||
/**
|
||||
* @desc 二维码生成配置选项
|
||||
* @type { import('zxing-wasm').WriterOptions }
|
||||
*/
|
||||
const writerOptions = {
|
||||
ecLevel: '',
|
||||
format: 'QRCode',
|
||||
scale: 1,
|
||||
};
|
||||
|
||||
// 配置 wasm 文件路径
|
||||
prepareZXingModule({
|
||||
overrides: {
|
||||
locateFile: (path, prefix) => {
|
||||
if (path.endsWith('.wasm')) {
|
||||
return `./wasm/${path}`;
|
||||
} else {
|
||||
return (prefix + path);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* @description 转换 Blob 为 DataURL
|
||||
* @param {Blob} blob
|
||||
* @param {Callback} callback
|
||||
*/
|
||||
export function blobToDataURL(blob, callback) {
|
||||
|
||||
/** @typedef {(data: { error: boolean, result: string }) => void} Callback */
|
||||
|
||||
let reader = new FileReader();
|
||||
|
||||
reader.onerror = function () {
|
||||
callback({
|
||||
error: true,
|
||||
result: reader.result,
|
||||
});
|
||||
};
|
||||
|
||||
reader.onload = function () {
|
||||
callback({
|
||||
error: false,
|
||||
result: reader.result,
|
||||
});
|
||||
};
|
||||
|
||||
reader.readAsDataURL(blob);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 将 SVG 字符串渲染到 Canvas
|
||||
* @param {object} options
|
||||
* @param {HTMLCanvasElement} options.canvas
|
||||
* @param {string} options.svgString
|
||||
* @param {number} options.drawLeft
|
||||
* @param {number} options.drawTop
|
||||
* @param {number} options.drawWidth
|
||||
* @param {number} options.drawHeight
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
function renderSvgToCanvas(options) {
|
||||
|
||||
let {
|
||||
canvas, svgString,
|
||||
drawLeft = 0, drawTop = 0,
|
||||
drawWidth = 0, drawHeight = 0,
|
||||
} = options;
|
||||
|
||||
return new Promise((resolve) => {
|
||||
|
||||
let svgBlob = new Blob([svgString], {
|
||||
type: 'image/svg+xml;charset=utf-8',
|
||||
});
|
||||
let svgUrl = URL.createObjectURL(svgBlob);
|
||||
let image = new Image();
|
||||
|
||||
image.onerror = () => {
|
||||
console.error('加载 SVG 失败');
|
||||
URL.revokeObjectURL(svgUrl);
|
||||
resolve(false);
|
||||
};
|
||||
|
||||
image.onload = () => {
|
||||
let ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(image, drawLeft, drawTop, drawWidth, drawHeight);
|
||||
URL.revokeObjectURL(svgUrl);
|
||||
resolve(true);
|
||||
};
|
||||
|
||||
image.src = svgUrl;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 解析二维码图片
|
||||
* @param {Blob} image 图片二进制
|
||||
*/
|
||||
export function readQrCodeImage(image) {
|
||||
|
||||
/**
|
||||
* @desc 返回结果
|
||||
* @type {{ error: string; image: string; textList: string[]; }}
|
||||
*/
|
||||
let returns = {
|
||||
error: '',
|
||||
image: '',
|
||||
textList: [],
|
||||
};
|
||||
|
||||
/** 读取图片,转换为 DataURL */
|
||||
let fileReader = new FileReader();
|
||||
|
||||
return new Promise((resolve) => {
|
||||
|
||||
// 处理读取异常
|
||||
fileReader.onerror = function () {
|
||||
console.error('解析二维码失败:读取图片失败');
|
||||
returns.error = '读取图片失败';
|
||||
resolve('');
|
||||
};
|
||||
|
||||
// 处理读取完成
|
||||
fileReader.onload = function () {
|
||||
resolve(fileReader.result);
|
||||
};
|
||||
|
||||
// 开始读取
|
||||
fileReader.readAsDataURL(image);
|
||||
|
||||
}).then((dataURL) => {
|
||||
if (dataURL) {
|
||||
returns.image = dataURL;
|
||||
return readBarcodes(image, readerOptions);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}).then((resultList) => {
|
||||
|
||||
let textList = returns.textList;
|
||||
|
||||
if (resultList.length === 0) {
|
||||
console.warn('解析二维码失败:未识别到内容');
|
||||
return returns;
|
||||
} else {
|
||||
console.debug('解析二维码成功:', resultList);
|
||||
}
|
||||
|
||||
for (let i = 0; i < resultList.length; i++) {
|
||||
|
||||
let item = resultList[i];
|
||||
|
||||
textList.push(item.text);
|
||||
|
||||
}
|
||||
|
||||
return returns;
|
||||
|
||||
}).catch((error) => {
|
||||
console.error('解析二维码失败:');
|
||||
console.error(error);
|
||||
returns.error = String(error);
|
||||
return returns;
|
||||
});;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 生成二维码图片
|
||||
* @param {object} options
|
||||
* @param {string} options.content
|
||||
* @param {number} options.width
|
||||
* @param {number} options.height
|
||||
* @returns 二维码图片 DataURL
|
||||
*/
|
||||
export function writeQrCodeImage(options = {}) {
|
||||
|
||||
let { content = '', width = 256, height = 256 } = options;
|
||||
|
||||
let canvas = document.createElement('canvas');
|
||||
let ctx = canvas.getContext('2d');
|
||||
|
||||
// 更新画布大小
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
|
||||
// 设置背景颜色
|
||||
ctx.fillStyle = '#FFFFFF';
|
||||
ctx.fillRect(0, 0, width, height);
|
||||
|
||||
return writeBarcode(content, writerOptions).then((result) => {
|
||||
|
||||
console.debug('生成二维码', result);
|
||||
|
||||
if (result.error) {
|
||||
console.error(`生成二维码失败:${result.error}`);
|
||||
return '';
|
||||
} else {
|
||||
return result.svg;
|
||||
}
|
||||
|
||||
}).then((svgString) => {
|
||||
if (svgString) {
|
||||
return renderSvgToCanvas({
|
||||
canvas: canvas,
|
||||
svgString: svgString,
|
||||
drawLeft: 0,
|
||||
drawTop: 0,
|
||||
drawWidth: width,
|
||||
drawHeight: height,
|
||||
});
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}).then((success) => {
|
||||
|
||||
if (success) {
|
||||
return canvas.toDataURL('image/png');
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
|
||||
}).catch((error) => {
|
||||
console.error('生成二维码失败:');
|
||||
console.error(error);
|
||||
return '';
|
||||
});
|
||||
|
||||
}
|
Reference in New Issue
Block a user