/** * RFID扫描管理器 * 用于在扫码时自动启动RFID扫描 * 全局单例,应用启动时自动初始化,应用退出时才清理 */ import idataRFID from '@/common/idata-rfid.js'; class RFIDScanner { constructor() { this.isInitialized = false; this.isInitializing = false; // 正在初始化标志 this.isScanning = false; this.powerStatus = 'disconnected'; this.scanCallback = null; this.currentInputRef = null; // 当前输入框的引用(用于自动填入) this.moduleTypeIndex = 0; // 当前尝试的模块类型索引:0=UM, 1=SLR, 2=GX this.moduleTypes = [0, 1, 2]; // 模块类型列表 this.moduleTypeNames = ['UM模块', 'SLR模块', 'GX模块']; this.initRetryCount = 0; this.maxRetryCount = 3; // 每种模块类型最多尝试3次 this.autoStopTimer = null; // 自动停止定时器 this.autoStopDelay = 30000; // 30秒后自动停止扫描(延长,避免频繁停止) this.powerCheckTimer = null; // 上电检查定时器 this.currentPageInstance = null; // 当前页面实例(用于自动填入) this.globalScanMode = false; // 全局扫描模式(不依赖输入框焦点) this.scanDebounceTimer = null; // 防抖定时器 this.scanDebounceDelay = 300; // 防抖延迟300ms } /** * 初始化RFID模块(应用启动时调用,全局只初始化一次) */ init() { if (this.isInitialized) { console.log('[RFIDScanner] 模块已初始化,跳过'); return; } if (this.isInitializing) { console.log('[RFIDScanner] 正在初始化中,跳过'); return; } this.isInitializing = true; console.log('[RFIDScanner] ========== 开始初始化RFID模块 =========='); // 监听上电事件 idataRFID.onPowerEvent((e) => { console.log('[RFIDScanner] POWEREvent:', JSON.stringify(e)); if (e && e.status === 'connected') { this.powerStatus = 'connected'; this.isInitialized = true; this.isInitializing = false; console.log('[RFIDScanner] ✓✓✓ 模块已上电成功!'); // 清除重试定时器 if (this.powerCheckTimer) { clearTimeout(this.powerCheckTimer); this.powerCheckTimer = null; } } else { this.powerStatus = 'disconnected'; console.log('[RFIDScanner] ✗ 模块未上电:', e ? e.msg : '未知错误'); } }); // 监听扫描事件 idataRFID.onScanEvent((e) => { console.log('[RFIDScanner] ========== 扫描到标签 =========='); console.log('[RFIDScanner] EPC:', e ? e.epc : 'undefined'); console.log('[RFIDScanner] TID:', e ? e.tid : 'undefined'); // 调用回调函数(回调函数中会更新输入框) if (this.scanCallback) { this.scanCallback(e); } // 全局扫描模式:自动填入当前焦点输入框 if (this.globalScanMode && e && e.epc) { this.fillCurrentInput(e.epc); } }); // 开始尝试初始化 this.tryInitModule(); } /** * 尝试初始化模块(自动尝试不同模块类型) */ tryInitModule() { if (this.isInitialized) { return; } const moduleType = this.moduleTypes[this.moduleTypeIndex]; console.log(`[RFIDScanner] 尝试初始化 ${this.moduleTypeNames[this.moduleTypeIndex]} (类型${moduleType})...`); idataRFID.initUHF(moduleType, (ret) => { console.log(`[RFIDScanner] initUHF(${moduleType}) result:`, ret); // 等待上电结果(最多等待3秒) this.powerCheckTimer = setTimeout(() => { if (!this.isInitialized && this.powerStatus !== 'connected') { console.log(`[RFIDScanner] ${this.moduleTypeNames[this.moduleTypeIndex]} 初始化超时,尝试下一个模块类型`); this.initRetryCount++; if (this.initRetryCount >= this.maxRetryCount) { // 当前模块类型尝试次数用完,切换到下一个 this.moduleTypeIndex = (this.moduleTypeIndex + 1) % this.moduleTypes.length; this.initRetryCount = 0; console.log(`[RFIDScanner] 切换到 ${this.moduleTypeNames[this.moduleTypeIndex]}`); } // 延迟后重试 setTimeout(() => { if (!this.isInitialized) { this.tryInitModule(); } }, 2000); } }, 3000); }); } /** * 开始扫描(在扫码输入框获得焦点时调用,或扫码按键触发) * @param {Object} inputRef - 输入框引用对象,用于自动填入扫描结果 {epc: ''} * @param {Function} callback - 扫描到标签时的回调函数(可选) */ startScan(inputRef = null, callback = null) { // 防抖处理,避免快速点击 if (this.scanDebounceTimer) { clearTimeout(this.scanDebounceTimer); } this.scanDebounceTimer = setTimeout(() => { this._doStartScan(inputRef, callback); }, this.scanDebounceDelay); } /** * 实际执行开始扫描 */ _doStartScan(inputRef = null, callback = null) { console.log('[RFIDScanner] ========== 开始扫描 =========='); console.log('[RFIDScanner] 当前状态 - isScanning:', this.isScanning, 'powerStatus:', this.powerStatus); // 如果未初始化,先初始化(确保模块已上电) if (!this.isInitialized && !this.isInitializing) { console.log('[RFIDScanner] 模块未初始化,开始初始化...'); this.init(); } // 如果已经在扫描,直接返回 if (this.isScanning) { console.log('[RFIDScanner] 已在扫描中,跳过'); return; } // 设置扫描回调和输入框引用 this.scanCallback = callback; this.currentInputRef = inputRef; // 如果不是全局扫描模式,设置当前页面实例 if (!this.globalScanMode && typeof getCurrentPages === 'function') { const pages = getCurrentPages(); if (pages.length > 0) { this.currentPageInstance = pages[pages.length - 1].$vm; } } // 检查上电状态 if (this.powerStatus !== 'connected') { console.log('[RFIDScanner] ⚠ RFID正在上电,请稍候...'); idataRFID.showToast('RFID正在上电,请稍候...', 1); // 等待上电完成后再开始扫描 const checkPowerAndStart = () => { if (this.powerStatus === 'connected' && !this.isScanning) { console.log('[RFIDScanner] 模块已上电,开始扫描...'); this.doStartScan(); } else if (!this.isScanning) { console.log('[RFIDScanner] 等待模块上电...'); // 如果未上电,等待1秒后重试(最多等待10秒) setTimeout(() => { if (!this.isScanning && this.powerStatus !== 'connected') { checkPowerAndStart(); } }, 1000); } }; setTimeout(() => { checkPowerAndStart(); }, 500); return; } // 如果已上电,直接开始扫描 this.doStartScan(); } /** * 执行开始扫描操作 */ doStartScan() { // 如果已经在扫描,不重复调用 if (this.isScanning) { console.log('[RFIDScanner] 已在扫描中,跳过'); return; } console.log('[RFIDScanner] 模块已上电,开始扫描...'); idataRFID.startOrStopRFID((ret) => { console.log('[RFIDScanner] startOrStopRFID result:', JSON.stringify(ret)); if (ret && ret.code === 'success') { if (ret.msg === 'start') { // 成功启动 this.isScanning = true; console.log('[RFIDScanner] ✓ RFID扫描已启动'); idataRFID.showToast('RFID扫描已启动', 1); // 设置自动停止定时器(30秒后自动停止,避免频繁停止) if (this.autoStopTimer) { clearTimeout(this.autoStopTimer); } this.autoStopTimer = setTimeout(() => { console.log('[RFIDScanner] 自动停止扫描(超时)'); this.stopScan(); }, this.autoStopDelay); } else if (ret.msg === 'stop') { // 如果返回stop,说明当前状态是启动的,调用后变成了停止 // 这种情况不应该发生,但需要处理 console.log('[RFIDScanner] ⚠ 扫描状态异常,收到stop消息'); this.isScanning = false; } else { console.log('[RFIDScanner] ⚠ 未知的扫描状态:', ret.msg); } } else { console.log('[RFIDScanner] ⚠ 启动扫描失败:', ret ? ret.msg : '未知错误'); idataRFID.showToast('启动扫描失败', 1); } }); } /** * 停止扫描(在扫码输入框失去焦点或输入完成时调用) * 注意:只停止扫描,不下电,保持模块上电状态 */ stopScan() { // 防抖处理 if (this.scanDebounceTimer) { clearTimeout(this.scanDebounceTimer); this.scanDebounceTimer = null; } if (!this.isScanning) { console.log('[RFIDScanner] 当前未在扫描,跳过停止操作'); return; } console.log('[RFIDScanner] ========== 停止扫描 =========='); // 清除自动停止定时器 if (this.autoStopTimer) { clearTimeout(this.autoStopTimer); this.autoStopTimer = null; } // 先设置状态为false,避免重复调用 this.isScanning = false; idataRFID.startOrStopRFID((ret) => { console.log('[RFIDScanner] stop scan result:', JSON.stringify(ret)); if (ret && ret.code === 'success') { if (ret.msg === 'stop') { console.log('[RFIDScanner] ✓ RFID扫描已停止(模块保持上电状态)'); } else if (ret.msg === 'start') { // 如果返回start,说明当前状态是停止的,调用后变成了启动 // 这种情况不应该发生,但需要处理 console.log('[RFIDScanner] ⚠ 扫描状态异常,收到start消息,重新设置为停止'); this.isScanning = true; // 立即再次停止 setTimeout(() => { this.stopScan(); }, 100); } } }); // 清除回调和输入框引用(但不清除globalScanMode,因为可能还需要继续扫描) this.scanCallback = null; this.currentInputRef = null; } /** * 获取上电状态 */ getPowerStatus() { return this.powerStatus; } /** * 获取扫描状态 */ getScanningStatus() { return this.isScanning; } /** * 全局扫描模式:为当前焦点输入框启动扫描(扫码按键触发) */ startScanForCurrentInput() { console.log('[RFIDScanner] ========== 全局扫描模式启动 =========='); // 如果正在扫描,先停止 if (this.isScanning) { console.log('[RFIDScanner] 当前正在扫描,先停止'); this.stopScan(); // 等待停止完成后再启动 setTimeout(() => { this._startScanForCurrentInput(); }, 500); return; } this._startScanForCurrentInput(); } /** * 实际执行全局扫描 */ _startScanForCurrentInput() { // 确保设置了当前页面实例 if (typeof getCurrentPages === 'function') { const pages = getCurrentPages(); if (pages.length > 0) { this.currentPageInstance = pages[pages.length - 1].$vm; console.log('[RFIDScanner] 已设置当前页面实例:', pages[pages.length - 1].route); } } this.globalScanMode = true; this.startScan(null, (tagData) => { if (tagData && tagData.epc) { console.log('[RFIDScanner] 扫描到标签,自动填入当前输入框:', tagData.epc); this.fillCurrentInput(tagData.epc); // 扫描成功后停止(延迟一下,确保填入完成) setTimeout(() => { this.stopScan(); }, 500); } }); } /** * 自动填入当前焦点输入框 */ fillCurrentInput(epc) { try { console.log('[RFIDScanner] ========== 尝试自动填入EPC:', epc); // 优先使用保存的页面实例 let vm = null; if (this.currentPageInstance) { vm = this.currentPageInstance; console.log('[RFIDScanner] 使用保存的页面实例'); } else if (typeof getCurrentPages === 'function') { // 如果保存的实例没有找到,尝试从getCurrentPages获取 const pages = getCurrentPages(); if (pages.length > 0) { const currentPage = pages[pages.length - 1]; console.log('[RFIDScanner] 当前页面:', currentPage.route); if (currentPage && currentPage.$vm) { vm = currentPage.$vm; // 更新保存的实例 this.currentPageInstance = vm; } } } if (!vm) { console.log('[RFIDScanner] 未找到页面实例,无法自动填入'); return; } // 检查常见的输入框变量名(按优先级) // 优先查找可能有焦点的输入框 const inputFields = ['barcode', 'matnr', 'locNo', 'orderNo', 'sourceSite', 'targetSite']; let filled = false; for (let field of inputFields) { if (vm[field] !== undefined) { console.log(`[RFIDScanner] 找到输入框变量 ${field},当前值:`, vm[field]); vm[field] = epc; console.log(`[RFIDScanner] ✓✓✓ 已自动填入EPC到 ${field}:`, epc); idataRFID.showToast('已自动填入', 1); filled = true; break; // 只填入第一个找到的 } } if (!filled) { console.log('[RFIDScanner] 未找到输入框变量,无法自动填入'); console.log('[RFIDScanner] 页面实例data:', Object.keys(vm.$data || {})); } } catch (error) { console.error('[RFIDScanner] 自动填入失败:', error); } } /** * 单标签读无过滤(在输入框获得焦点时调用) * @param {String} fieldName - 要填入的字段名(如 'barcode', 'matnr' 等) * @param {Function} callback - 读取成功后的回调函数(可选) */ readSingleTagWithoutFilter(fieldName = null, callback = null) { console.log('[RFIDScanner] ========== 单标签读无过滤 =========='); console.log('[RFIDScanner] 字段名:', fieldName); // 如果未初始化,先初始化(确保模块已上电) if (!this.isInitialized && !this.isInitializing) { console.log('[RFIDScanner] 模块未初始化,开始初始化...'); this.init(); } // 检查上电状态 if (this.powerStatus !== 'connected') { console.log('[RFIDScanner] ⚠ RFID正在上电,请稍候...'); idataRFID.showToast('RFID正在上电,请稍候...', 1); // 等待上电完成后再读取 const checkPowerAndRead = () => { if (this.powerStatus === 'connected') { console.log('[RFIDScanner] 模块已上电,开始单标签读取...'); this._doReadSingleTag(fieldName, callback); } else { console.log('[RFIDScanner] 等待模块上电...'); setTimeout(() => { if (this.powerStatus !== 'connected') { checkPowerAndRead(); } }, 1000); } }; setTimeout(() => { checkPowerAndRead(); }, 500); return; } // 如果已上电,直接读取 this._doReadSingleTag(fieldName, callback); } /** * 执行单标签读取操作 */ _doReadSingleTag(fieldName = null, callback = null) { // 确保设置了当前页面实例 if (typeof getCurrentPages === 'function') { const pages = getCurrentPages(); if (pages.length > 0) { this.currentPageInstance = pages[pages.length - 1].$vm; } } // 调用单标签读无过滤 // readBank: 1->EPC, startBlock: 2, len: 6, pwd: "00000000" idataRFID.readTagWithoutFilter(1, 2, 6, "00000000", (ret) => { console.log('[RFIDScanner] readTagWithoutFilter result:', JSON.stringify(ret)); if (ret && ret.code === 'success' && ret.data) { const epc = ret.data.trim(); console.log('[RFIDScanner] ✓✓✓ 成功读取到标签 EPC:', epc); // 如果有回调函数,先调用回调 if (callback && typeof callback === 'function') { callback({ epc: epc, tid: '' }); } // 如果指定了字段名,自动填入 if (fieldName) { this.fillFieldByName(fieldName, epc); } else { // 如果没有指定字段名,自动填入当前焦点输入框 this.fillCurrentInput(epc); } idataRFID.showToast('读取成功', 1); } else { console.log('[RFIDScanner] ✗ 读取失败:', ret ? ret.msg : '未知错误'); if (ret && ret.code === 'fail') { idataRFID.showToast('读取失败: ' + (ret.msg || '未知错误'), 1); } } }); } /** * 根据字段名填入值 */ fillFieldByName(fieldName, value) { try { console.log(`[RFIDScanner] 尝试填入字段 ${fieldName}:`, value); // 优先使用保存的页面实例 let vm = null; if (this.currentPageInstance) { vm = this.currentPageInstance; } else if (typeof getCurrentPages === 'function') { const pages = getCurrentPages(); if (pages.length > 0 && pages[pages.length - 1].$vm) { vm = pages[pages.length - 1].$vm; this.currentPageInstance = vm; } } if (!vm) { console.log('[RFIDScanner] 未找到页面实例,无法填入'); return; } if (vm[fieldName] !== undefined) { vm[fieldName] = value; console.log(`[RFIDScanner] ✓✓✓ 已填入字段 ${fieldName}:`, value); idataRFID.showToast('已自动填入', 1); } else { console.log(`[RFIDScanner] 字段 ${fieldName} 不存在`); } } catch (error) { console.error('[RFIDScanner] 填入字段失败:', error); } } /** * 设置当前页面实例(页面onShow时调用) */ setCurrentPageInstance(pageInstance) { this.currentPageInstance = pageInstance; } /** * 清理资源(应用退出时调用,全局只调用一次) */ cleanup() { console.log('[RFIDScanner] ========== 清理RFID资源(应用退出) =========='); this.stopScan(); idataRFID.closeUHF(); idataRFID.removeEventListeners(); this.isInitialized = false; this.isInitializing = false; this.isScanning = false; this.powerStatus = 'disconnected'; this.scanCallback = null; this.currentInputRef = null; if (this.powerCheckTimer) { clearTimeout(this.powerCheckTimer); this.powerCheckTimer = null; } console.log('[RFIDScanner] ✓ RFID资源已清理'); } } // 创建单例实例 const rfidScanner = new RFIDScanner(); export default rfidScanner;