You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ZXing-js无法扫描EAN-13条码 求可用示例代码

解决ZXing-js无法扫描EAN-13条码的问题(.NET 4.8 MVC)

问题诊断

你的代码中存在几个可能导致EAN-13扫描失败的问题:

  1. 使用的ZXing版本(0.18.6)较旧,对EAN-13的兼容性可能不足
  2. 设备选择逻辑错误:videoInputDevices是数组,直接取deviceId会导致未定义,应该选择具体设备(比如第一个摄像头)
  3. 格式配置的传递方式不符合新版本API要求
  4. 持续扫描未在成功后停止,可能干扰后续识别

修正后的可运行示例代码

@model Pocos.MCD_Stores

@{ 
    ViewBag.Title = "DoVisit";
}
<label id="recordCountLabel">Records Loaded: 0</label>
<br />
<h2>Do Visit</h2>

<!-- 扫描控制按钮 -->
<button id="startScanButton">启动扫描</button>
<button id="scanNowButton" style="display: none;">立即扫描</button>
<button id="resetButton">重置</button>
<br />
<!-- 扫描视频窗口 -->
<video id="barcode-scanner" width="600" height="400" style="border: 1px solid gray; display: block;"></video>
<br />
<!-- 扫描结果显示 -->
<label id="scannedBarcodeLabel">扫描条码: 无</label>
<br />
<label id="productDetailsLabel">产品详情: 无</label>
<br />
<!-- 产品下拉框 -->
<select id="productDropdown" style="width: 100%;">
    <option value="">选择产品</option>
</select>

<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
<!-- 升级到较新的ZXing版本 -->
<script src="https://cdn.jsdelivr.net/npm/@zxing/library@0.20.0/umd/index.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>

<script>
    let selectedDeviceId;
    let currentScanListener = null;
    // 初始化条码阅读器,指定仅支持EAN-13
    const codeReader = new ZXing.BrowserMultiFormatReader();
    // 配置阅读器优先识别EAN-13
    codeReader.setPossibleFormats([ZXing.BarcodeFormat.EAN_13]);
    console.log('ZXing条码阅读器已初始化');

    document.getElementById('startScanButton').addEventListener('click', () => {
        codeReader.listVideoInputDevices()
            .then(videoInputDevices => {
                // 处理多摄像头情况,默认选第一个可用摄像头
                if (videoInputDevices.length === 0) {
                    alert('未检测到摄像头设备');
                    return;
                }
                selectedDeviceId = videoInputDevices[0].deviceId;
                console.log('选择摄像头:', videoInputDevices[0].label);

                // 启动持续扫描,成功后自动停止
                currentScanListener = codeReader.decodeFromVideoDevice(selectedDeviceId, 'barcode-scanner', (result, err) => {
                    if (result) {
                        console.log('检测到条码:', result);
                        document.getElementById('scannedBarcodeLabel').innerText = `扫描条码: ${result.text}`;
                        handleScannedBarcode(result.text);
                        // 扫描成功后停止,避免重复触发
                        codeReader.reset();
                        document.getElementById('scanNowButton').style.display = 'none';
                    }
                    if (err && !(err instanceof ZXing.NotFoundException)) {
                        console.error('扫描错误:', err);
                    }
                });
                document.getElementById('scanNowButton').style.display = 'block';
            })
            .catch(err => console.error('获取摄像头列表失败:', err));
    });

    document.getElementById('scanNowButton').addEventListener('click', () => {
        if (!selectedDeviceId) {
            alert('请先启动扫描');
            return;
        }
        // 单次扫描模式
        codeReader.decodeOnceFromVideoDevice(selectedDeviceId, 'barcode-scanner')
            .then(result => {
                if (result) {
                    console.log('检测到条码:', result);
                    document.getElementById('scannedBarcodeLabel').innerText = `扫描条码: ${result.text}`;
                    handleScannedBarcode(result.text);
                }
            })
            .catch(err => {
                if (err && !(err instanceof ZXing.NotFoundException)) {
                    console.error('单次扫描错误:', err);
                } else {
                    alert('未检测到EAN-13条码,请调整位置重试');
                }
            });
    });

    document.getElementById('resetButton').addEventListener('click', () => {
        codeReader.reset();
        document.getElementById('scannedBarcodeLabel').innerText = '扫描条码: 无';
        document.getElementById('productDetailsLabel').innerText = '产品详情: 无';
        document.getElementById('scanNowButton').style.display = 'none';
        currentScanListener = null;
    });

    // 处理扫描到的条码逻辑(保留原有代码)
    function handleScannedBarcode(barcode) {
        const productDbRequest = indexedDB.open('ProductDatabase', 1);

        productDbRequest.onsuccess = (event) => {
            const db = event.target.result;
            const transaction = db.transaction('products', 'readonly');
            const objectStore = transaction.objectStore('products');
            const getRequest = objectStore.get(barcode);

            getRequest.onsuccess = (event) => {
                const product = event.target.result;
                if (product) {
                    document.getElementById('productDetailsLabel').innerText = `产品详情: ${JSON.stringify(product)}`;
                    storeScannedProduct(product.Sku);
                } else {
                    document.getElementById('productDetailsLabel').innerText = `产品详情: 未找到`;
                }
            };

            getRequest.onerror = (event) => {
                console.error('获取产品失败:', event.target.error);
            };
        };

        productDbRequest.onerror = (event) => {
            console.error('打开产品数据库失败:', event.target.error);
        };
    }

    function customMatcher(params, data) {
        if ($.trim(params.term) === '') {
            return data;
        }
        const term = params.term.toLowerCase();
        const text = data.text.toLowerCase();
        if (text.indexOf(term) > -1) {
            return data;
        }
        return null;
    }

    function storeScannedProduct(sku) {
        const scannedDbRequest = indexedDB.open('scannedProductDatabase', 1);

        scannedDbRequest.onsuccess = (event) => {
            const db = event.target.result;
            const transaction = db.transaction('skuCounts', 'readwrite');
            const objectStore = transaction.objectStore('skuCounts');
            const getRequest = objectStore.get(sku);

            getRequest.onsuccess = (event) => {
                const record = event.target.result;
                if (record) {
                    record.Count += 1;
                    objectStore.put(record);
                } else {
                    objectStore.put({ Sku: sku, Count: 1 });
                }
            };

            getRequest.onerror = (event) => {
                console.error('获取扫描记录失败:', event.target.error);
            };
        };

        scannedDbRequest.onerror = (event) => {
            console.error('打开扫描记录数据库失败:', event.target.error);
        };
    }

    document.addEventListener('DOMContentLoaded', (event) => {
        initScannedProductDB()
            .then(db => {
                console.log('扫描记录数据库已就绪');
                const recordCount = localStorage.getItem('recordCount');
                if (recordCount) {
                    document.getElementById('recordCountLabel').innerText = `已加载记录数: ${recordCount}`;
                }
            })
            .catch(error => {
                console.error('初始化扫描记录数据库失败:', error);
            });

        fetchProductsFromIndexedDB().then(products => {
            products.sort((a, b) => {
                const descA = a.Desc !== "NULL" ? a.Desc.toLowerCase() : "";
                const descB = b.Desc !== "NULL" ? b.Desc.toLowerCase() : "";
                if (descA < descB) return -1;
                if (descA > descB) return 1;
                return 0;
            });

            const dropdown = $('#productDropdown');
            products.forEach(product => {
                const desc = product.Desc !== "NULL" ? product.Desc : "";
                const colour = product.Colour !== "NULL" ? product.Colour : "";
                const size = product.Size !== "NULL" ? product.Size : "";
                const option = new Option(`${desc} - ${colour} - ${size}`, product.Sku, false, false);
                dropdown.append(option);
            });
            dropdown.select2({
                placeholder: "选择产品",
                allowClear: true,
                matcher: customMatcher
            });
        }).catch(error => {
            console.error('获取产品列表失败:', error);
        });
    });

    function initScannedProductDB() {
        return new Promise((resolve, reject) => {
            const request = indexedDB.open('scannedProductDatabase', 1);

            request.onupgradeneeded = (event) => {
                const db = event.target.result;
                const objectStore = db.createObjectStore('skuCounts', { keyPath: 'Sku' });
                objectStore.createIndex('Sku', 'Sku', { unique: true });
                objectStore.createIndex('Count', 'Count', { unique: false });
            };

            request.onsuccess = (event) => {
                console.log('扫描记录数据库初始化成功');
                resolve(event.target.result);
            };

            request.onerror = (event) => {
                reject(event.target.error);
            };
        });
    }

    function fetchProductsFromIndexedDB() {
        return new Promise((resolve, reject) => {
            const request = indexedDB.open('ProductDatabase', 1);

            request.onsuccess = (event) => {
                const db = event.target.result;
                const transaction = db.transaction(['products'], 'readonly');
                const objectStore = transaction.objectStore('products');
                const products = [];

                objectStore.openCursor().onsuccess = (event) => {
                    const cursor = event.target.result;
                    if (cursor) {
                        products.push(cursor.value);
                        cursor.continue();
                    } else {
                        resolve(products);
                    }
                };

                objectStore.openCursor().onerror = (event) => {
                    reject(event.target.error);
                };
            };

            request.onerror = (event) => {
                reject(event.target.error);
            };
        });
    }
</script>

关键修改说明

  1. 升级ZXing版本:从0.18.6升级到0.20.0,修复了旧版本对EAN-13的识别兼容问题
  2. 正确设置格式:使用codeReader.setPossibleFormats([ZXing.BarcodeFormat.EAN_13])替代原API的格式参数传递,符合新版本要求
  3. 修复设备选择逻辑:处理多摄像头场景,默认选择第一个可用设备,避免deviceId未定义的错误
  4. 优化扫描行为:持续扫描成功后自动停止,避免重复触发识别;单次扫描失败时给出友好提示
  5. 添加错误处理:补充摄像头未检测到的提示,增强用户体验

额外调试建议

  • 确保EAN-13条码清晰,无模糊或反光
  • 调整摄像头与条码的距离(建议10-30cm),确保条码完整出现在视频窗口中
  • 在浏览器控制台查看是否有设备权限或视频流错误
  • 尝试切换前后摄像头,部分设备前置摄像头分辨率较低可能影响识别

内容的提问来源于stack exchange,提问作者Jim Tench

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 03:25:57