qrcode error: code length overflow. (1596>1056) qrcode.js二维码长度溢出

qrcode.js二维码长度溢出

报错如下:

qrcode error: code length overflow. (1596>1056)

网上有很多方法,让改代码的,让使用一个修改过的库的。
其实都不用。

使用时候修改一下传入参数就行:correctLevel : 3
不用默认的QRCode.CorrectLevel.H
另外注意,宽高要改大一点,比如300,400,因为如果信息过多,小的图是显示不下的。

width: 300,
height: 300,
correctLevel: 3, //QRCode.CorrectLevel.H

github库

https://github.com/davidshimjs/qrcodejs/

<template> <view class="content"> <view class="main-content"> <view class="text-area"> <text class="title">{{title}}</text> </view> <!-- 二维码组件 --> <tki-qrcode v-if="qrCodeVisible" ref="qrcode" :val="qrContent" :size="200" /> <view class="operation-buttons"> <button @click="openSQL">打开数据库</button> <button @click="createTable1">创建商品表</button> <button @click="createTable2">创建账单表</button> <button @click="selectTableData">查询表数据</button> <button @click="showInsertDialog">新增商品数据</button> <button @click="showCreateBillDialog">生成账单</button> <button @click="sendToDevice">发送二维码</button> </view> <!-- 显示查询结果 --> <view class="result-list" v-if="listData.length > 0"> <view class="result-item" v-for="(item, index) in listData" :key="index"> <text>{{item.id}}. {{item.name}}</text> <text>售价: ¥{{ (item.price || 0).toFixed(2) }}</text> <text>进价: ¥{{ (item.purchaseprice || 0).toFixed(2) }}</text> <text>状态: {{item.status || '无'}}</text> <text>条码: {{item.barcode || '无'}}</text> <view class="item-actions"> <button @click="updateTableData(item)" size="mini">修改</button> <button @click="confirmDelete(item.id)" size="mini" type="warn">删除</button> </view> </view> </view> </view> </view> </template> <script> import { DB } from '@/db/database.js'; import tkiQrcode from '@/components/tki-qrcode/tki-qrcode.vue'; export default { components: { tkiQrcode }, data() { return { title: '欢迎光临', db: null, listData: [], isInserting: false, inputProduct: { name: '', price: '', purchaseprice: '', status: '在售', barcode: '' }, statusList: ['在售', '缺货', '下架'], qrCodeVisible: false, qrContent: '', currentBill: null }; }, onLoad() { this.openSQL().then(() => { return DB.selectTableData("products").then(res => { console.log('当前表数据:', res); }).catch(err => { console.warn('表可能不存在:', err); this.showToast('表不存在,请先创建表'); }); }); }, methods: { resetDatabase() { DB.dropTable("products").then(() => { this.showToast("表已删除"); this.createTable1(); }); }, openSQL() { if (!DB.isOpen()) { DB.openSqlite() .then(() => { console.log("数据库已打开"); this.showToast("数据库已打开"); }) .catch((error) => { console.error("数据库开启失败", error); this.showToast("数据库开启失败"); }); } }, createTable1() { if (DB.isOpen()) { const sql = ` "id" INTEGER PRIMARY KEY AUTOINCREMENT, "name" TEXT NOT NULL, "price" REAL DEFAULT 0, "purchaseprice" REAL DEFAULT 0, "status" TEXT DEFAULT '在售', "barcode" TEXT `; DB.createTable("products", sql) .then(() => { console.log("创建表成功"); this.showToast("商品表创建成功"); }) .catch((error) => { console.error("创建表失败详情:", error); this.showToast(`创建表失败: ${error.message}`); }); } else { this.showToast("数据库未打开"); } }, createTable2() { if (DB.isOpen()) { const billsSql = ` "id" INTEGER PRIMARY KEY AUTOINCREMENT, "total" REAL DEFAULT 0, "items" TEXT NOT NULL, "timestamp" TEXT NOT NULL `; DB.createTable("bills", billsSql) .then(() => { console.log("账单表创建成功"); this.showToast("账单表创建成功"); }) .catch((error) => { console.error("创建账单表失败详情:", error); this.showToast(`创建账单表失败: ${error.message}`); }); } else { this.showToast("数据库未打开"); } }, showCreateBillDialog() { uni.showModal({ title: '生成账单', content: '', editable: true, placeholderText: '格式:总金额,商品明细', success: (res) => { if (res.confirm && res.content) { this.parseAndCreateBill(res.content).then(bill => { this.currentBill = bill; this.generateQRCode(bill); }); } } }); }, generateQRCode(bill) { this.qrContent = `账单号:${new Date(bill.timestamp).getTime()}\n金额:${bill.total.toFixed(2)}\n商品:${bill.items}`; this.qrCodeVisible = true; this.$nextTick(() => { this.$refs.qrcode._makeCode(); uni.showModal({ title: '二维码已生成', content: `金额: ${bill.total.toFixed(2)}`, showCancel: false }); }); }, parseAndCreateBill(inputStr) { const parts = inputStr.split(',').map(part => part.trim()); if (parts.length < 2) { this.showToast('请输入完整信息:总金额,商品明细'); return Promise.reject('输入不完整'); } const bill = { total: parseFloat(parts[0]), items: parts[1], timestamp: new Date().toISOString() }; if (isNaN(bill.total)) { this.showToast('请输入有效的总金额'); return Promise.reject('无效金额'); } const values = [ bill.total, `'${bill.items.replace(/'/g, "''")}'`, `'${bill.timestamp}'` ].join(','); const columns = "total,items,timestamp"; return DB.insertTableData("bills", values, columns) .then(() => { this.showToast("账单生成成功"); return bill; }) .catch(err => { console.error("账单生成失败:", err); this.showToast(`账单生成失败: ${err.message || err}`); throw err; }); }, async sendToDevice() { try { // 检查二维码内容 if (!this.qrContent) { uni.showToast({ title: '请先生成二维码', icon: 'none' }); return; } // 检查运行环境 if (typeof navigator === 'undefined' || !navigator.serial) { // 非浏览器环境或浏览器不支持Web Serial API if (uni.getSystemInfoSync().platform === 'android') { // Android平台使用原生插件 await this.sendViaNativePlugin(); } else { uni.showToast({ title: '当前环境不支持串口通信,请使用Chrome/Edge浏览器或Android APP', icon: 'none', duration: 3000 }); } return; } // 请求串口访问权限 const port = await navigator.serial.requestPort(); await port.open({ baudRate: 9600 }); // 波特率需与STM32一致 // 将二维码转换为适合OLED显示的格式 const qrCodeData = await this.prepareQrCodeForOled(); // 发送数据 const writer = port.writable.getWriter(); // 发送起始标志 await writer.write(new TextEncoder().encode('@QRCODE_START@\r\n')); // 分块发送数据(避免缓冲区溢出) const chunkSize = 64; // 根据STM32缓冲区大小调整 for (let i = 0; i < qrCodeData.length; i += chunkSize) { const chunk = qrCodeData.slice(i, i + chunkSize); await writer.write(new TextEncoder().encode(chunk)); await new Promise(resolve => setTimeout(resolve, 10)); // 添加小延迟 } // 发送结束标志 await writer.write(new TextEncoder().encode('@QRCODE_END@\r\n')); writer.releaseLock(); uni.showToast({ title: '二维码已发送到设备', icon: 'success' }); } catch (err) { console.error('发送失败:', err); uni.showToast({ title: `发送失败: ${err.message}`, icon: 'none' }); } }, // 准备OLED格式的二维码数据 async prepareQrCodeForOled() { // 获取二维码的像素数据(使用tki-qrcode组件) const qrCodeCanvas = await this.$refs.qrcode._getQrcodeCanvas(); const ctx = qrCodeCanvas.getContext('2d'); const imageData = ctx.getImageData(0, 0, qrCodeCanvas.width, qrCodeCanvas.height); // 转换为单色位图格式(1位/像素) const width = qrCodeCanvas.width; const height = qrCodeCanvas.height; const bytesPerRow = Math.ceil(width / 8); const oledData = new Uint8Array(bytesPerRow * height); for (let y = 0; y < height; y++) { for (let x = 0; x < width; x++) { const index = (y * width + x) * 4; const r = imageData.data[index]; const g = imageData.data[index + 1]; const b = imageData.data[index + 2]; // 简单亮度计算 const brightness = (r + g + b) / 3; const isBlack = brightness < 128; // 阈值可调整 if (isBlack) { const byteIndex = Math.floor(x / 8) + y * bytesPerRow; const bitIndex = 7 - (x % 8); oledData[byteIndex] |= (1 << bitIndex); } } } // 转换为16进制字符串便于传输 return Array.from(oledData).map(b => b.toString(16).padStart(2, '0')).join(''); }, insertTableData() { if (DB.isOpen()) { const testData = [ { name: '矿泉水', price: 2.00, purchaseprice: 1.50, status: '在售', barcode: '1234567890123' }, { name: '面包', price: 5.00, purchaseprice: 3.50, status: '在售', barcode: '9876543210987' } ]; testData.forEach(item => { const sql = `'${item.name.replace(/'/g, "''")}', ${item.price}, ${item.purchaseprice}, '${item.status.replace(/'/g, "''")}', '${item.barcode.replace(/'/g, "''")}'`; const condition = "'name', 'price', 'purchaseprice', 'status', 'barcode'"; DB.insertTableData("products", sql, condition) .then(() => { console.log("新增数据成功"); this.showToast("新增数据成功"); this.selectTableData(); }) .catch((error) => { console.error("新增数据失败", error); this.showToast("新增数据失败: " + error.message); }); }); this.showToast("测试数据已添加"); } else { this.showToast("数据库未打开"); } }, showInsertDialog() { uni.showModal({ title: '新增商品', content: '', editable: true, placeholderText: '格式:名称,价格,进价,状态,条码', success: (res) => { if (res.confirm && res.content) { this.parseAndInsert(res.content); } } }); }, parseAndInsert(inputStr) { // 分割输入字符串 const parts = inputStr.split(',').map(part => part.trim()); if (parts.length < 5) { this.showToast('请输入完整信息:名称,价格,进价,状态,条码'); return; } // 构造商品对象 const product = { name: parts[0], price: parseFloat(parts[1]), purchaseprice: parseFloat(parts[2]), status: parts[3], barcode: parts[4] }; // 验证数据 if (!product.name) { this.showToast('商品名称不能为空'); return; } if (isNaN(product.price)) { this.showToast('请输入有效的价格'); return; } if (isNaN(product.purchaseprice)) { this.showToast('请输入有效的进价'); return; } // 处理单引号转义 const escapeStr = str => str.replace(/'/g, "''"); // 构建SQL参数 const values = [ `'${escapeStr(product.name)}'`, product.price, product.purchaseprice, `'${escapeStr(product.status)}'`, product.barcode ? `'${escapeStr(product.barcode)}'` : 'NULL' ].join(','); const columns = "name,price,purchaseprice,status,barcode"; // 插入数据 DB.insertTableData("products", values, columns) .then(() => { this.showToast("商品添加成功"); this.selectTableData(); // 刷新列表 }) .catch(err => { console.error("添加失败:", err); this.showToast(`添加失败: ${err.message || err}`); }); }, selectTableData() { if (DB.isOpen()) { DB.selectTableData("products") .then((res) => { console.log("查询结果", res); this.listData = res; }) .catch((error) => { console.error("查询失败", error); this.showToast("查询失败"); }); } else { this.showToast("数据库未打开"); } }, updateTableData(item) { // 第一步:输入新名称 uni.showModal({ title: '修改商品名称', content: item.name, editable: true, placeholderText: '请输入新名称', success: (nameRes) => { if (nameRes.confirm && nameRes.content) { // 第二步:输入新价格 uni.showModal({ title: '修改商品价格', content: String(item.price), editable: true, placeholderText: '请输入新价格', success: (priceRes) => { if (priceRes.confirm && priceRes.content) { // 第三步:输入新进价 uni.showModal({ title: '修改商品进价', content: String(item.purchaseprice), editable: true, placeholderText: '请输入新进价', success: (purchasepriceRes) => { if (purchasepriceRes.confirm && purchasepriceRes.content) { // 第四步:输入新状态 uni.showModal({ title: '修改商品状态', content: item.status, editable: true, placeholderText: '请输入新状态', success: (statusRes) => { if (statusRes.confirm && statusRes.content) { // 第五步:输入新条形码 uni.showModal({ title: '修改商品条形码', content: item.barcode, editable: true, placeholderText: '请输入新条形码', success: (barcodeRes) => { if (barcodeRes.confirm && barcodeRes.content) { const newName = nameRes.content; const newPrice = parseFloat(priceRes.content) || item.price; const newPurchaseprice = parseFloat(purchasepriceRes.content) || item.purchaseprice; const newStatus = statusRes.content; const newBarcode = barcodeRes.content; const data = ` name = '${newName}', price = ${newPrice}, purchaseprice = ${newPurchaseprice}, status = '${newStatus}', barcode = '${newBarcode}' `; DB.updateTableData("products", data, "id", item.id) .then(() => { this.showToast("修改成功"); this.selectTableData(); }) .catch((error) => { this.showToast("修改失败"); }); } } }); } } }); } } }); } } }); } } }); }, confirmDelete(id) { uni.showModal({ title: '确认删除', content: '确定要删除这个商品吗?', success: (res) => { if (res.confirm) { this.deleteTableData(id); } } }); }, deleteTableData(id) { if (DB.isOpen()) { DB.deleteTableData("products", "id", id) .then(() => { this.showToast("删除成功"); this.selectTableData(); }) .catch((error) => { this.showToast("删除失败"); }); } }, showToast(message) { uni.showToast({ title: message, icon: "none", duration: 2000 }); } } }; </script> <style lang="scss" scoped> .content { display: flex; flex-direction: column; align-items: center; justify-content: flex-start; padding-top: 100rpx; } .main-content { display: flex; flex-direction: column; align-items: center; width: 100%; } .text-area { display: flex; justify-content: center; margin-bottom: 30rpx; .title { font-size: 80rpx; color: #3c3c3e; } } .operation-buttons { margin-top: 100rpx; display: flex; flex-wrap: wrap; justify-content: center; gap: 10rpx; width: 100%; button { background-color: #ffd778; color: white; border: none; padding: 20rpx 30rpx; border-radius: 80rpx; font-size: 32rpx; min-width: 200rpx; width: 100%; } } .result-list { margin-top: 40rpx; width: 90%; border: 1rpx solid #eee; padding: 20rpx; border-radius: 8rpx; .result-item { padding: 15rpx 0; border-bottom: 1rpx solid #f0f0f0; font-size: 28rpx; &:last-child { border-bottom: none; } } } .item-actions { display: flex; justify-content: flex-end; margin-top: 10rpx; button { margin-right: 10rpx; padding: 0 20rpx; font-size: 24rpx; height: 50rpx; line-height: 50rpx; } } </style>
05-23
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值