// 注册 Vant 组件 Vue.use(vant.NavBar); Vue.use(vant.Steps); Vue.use(vant.Step); Vue.use(vant.Tabs); Vue.use(vant.Tab); Vue.use(vant.List); Vue.use(vant.Icon); Vue.use(vant.Toast); Vue.use(vant.Dialog); var app = new Vue({ el: "#app", data: { // 盘点单信息 inventoryInfo: { id: null, checkVouchId: null, name: '', documentNo: '', inventoryStartDate: '', inventoryEndDate: '' }, // 当前激活的Tab activeTab: 0, // 待盘明细相关 allPendingList: [], // 所有待盘数据(cfCheckVouchsResponses) displayedPendingList: [], // 当前显示的待盘数据 pendingPage: 0, // 当前页 pendingLoading: false, // 是否正在加载 pendingFinished: false, // 是否加载完毕 pendingTotal: 0, // 待盘总数 // 已盘相关 allCheckedList: [], // 所有已盘数据 displayedCheckedList: [], // 当前显示的已盘数据 checkedPage: 0, // 当前页 checkedLoading: false, // 是否正在加载 checkedFinished: false, // 是否加载完毕 checkedTotal: 0, // 已盘总数 // 每页显示数量 pageSize: 10, // IndexDB 数据库实例 checkVouchDb: null, // RFID 扫描状态 isScanning: false, // === 扫描优化相关 === // EPC扫描缓冲区(用于批量处理) scanBuffer: [], // 批量处理定时器 batchProcessTimer: null, // 批量处理间隔(毫秒) batchProcessInterval: 500, // UI更新定时器 uiUpdateTimer: null, // UI更新间隔(毫秒) uiUpdateInterval: 1000, // 待盘数据Map索引(key: epc, value: item) pendingMap: {}, // 已盘数据Map索引(key: checkVouchsId, value: true) checkedMap: {}, // 待更新UI标记 needsUIUpdate: false, // 新增已盘数量(用于实时显示) newCheckedCount: 0, }, methods: { /** * 返回上一页 */ goBack: function () { history.go(-1); }, /** * 去同步页面 - 确保数据已保存 */ goToSync: function () { var _self = this; // 停止扫描 if (_self.isScanning) { _self.stopRfidScan(); } // 确保最新数据已保存 _self.saveToUploadQueue(); // 显示提示并跳转 if (_self.allCheckedList && _self.allCheckedList.length > 0) { vant.Toast.success('已盘数据已保存,即将跳转到同步页面'); } else { vant.Toast('当前没有已盘数据'); } setTimeout(function () { window.location.href = './DataSync.html'; }, 800); }, /** * 初始化盘点单信息并加载待盘数据 */ initInventoryInfo: function () { var _self = this; // 从localStorage获取选中的盘点单 var selectedInventory = localStorage.getItem('selectedInventory'); if (!selectedInventory) { vant.Toast.fail('请先选择盘点单'); setTimeout(function () { _self.goBack(); }, 1500); return; } var inventory = JSON.parse(selectedInventory); _self.inventoryInfo = { id: inventory.id, checkVouchId: inventory.checkVouchId, name: inventory.name, documentNo: inventory.documentNo, inventoryStartDate: inventory.inventoryStartDate || '', inventoryEndDate: inventory.inventoryEndDate || '' }; // 从 IndexDB 加载完整的盘点单数据 if (_self.checkVouchDb) { _self.checkVouchDb.get('checkVouchList', inventory.checkVouchId, function (data) { if (data && data.cfCheckVouchsResponses) { // 根据 checkVouchDate 区分已盘数据和待盘数据 var pendingList = []; var checkedList = []; data.cfCheckVouchsResponses.forEach(function (item) { var itemData = { id: item.checkVouchsId, checkVouchsId: item.checkVouchsId, assetName: item.inventoryName, no: item.inventoryNo, epc: item.inventoryEpc, positionId: item.positionId, positionName: item.positionName, positionNo: item.positionNo, warehouseId: item.warehouseId, warehouseName: item.warehouseName, warehouseNo: item.warehouseNo, inventoryId: item.inventoryId }; // 根据 checkVouchDate 判断是已盘还是待盘 if (item.checkVouchDate) { // 有 checkVouchDate,是已盘数据 itemData.checkTime = item.checkVouchDate; itemData.userName = item.userName || ''; checkedList.push(itemData); // 构建已盘Map索引 _self.checkedMap[item.checkVouchsId] = true; } else { // 没有 checkVouchDate,是待盘数据 pendingList.push(itemData); // 构建待盘Map索引 if (itemData.epc) { _self.pendingMap[itemData.epc] = itemData; } } }); _self.allPendingList = pendingList; _self.allCheckedList = checkedList; _self.pendingTotal = pendingList.length; _self.checkedTotal = checkedList.length; console.log('数据加载完成 - 待盘:', pendingList.length, '条,已盘:', checkedList.length, '条'); } // 加载本地新盘的数据(如果有的话,需要与服务器已盘数据合并) _self.loadLocalCheckedData(inventory.checkVouchId); }, function (error) { console.error('加载盘点单数据失败:', error); }); } }, /** * 加载本地新盘的数据(如果有的话,需要与服务器已盘数据合并) */ loadLocalCheckedData: function (checkVouchId) { var _self = this; _self.checkVouchDb.get('uploadQueue', checkVouchId, function (uploadData) { if (uploadData && uploadData.cfCheckVouchsRequests && uploadData.cfCheckVouchsRequests.length > 0) { console.log('发现本地新盘数据:', uploadData.cfCheckVouchsRequests.length, '条(需要与服务器已盘数据合并)'); // 将本地新盘数据与服务器已盘数据合并 // 使用 checkVouchsId 去重 var existingIds = {}; _self.allCheckedList.forEach(function (item) { existingIds[item.checkVouchsId] = true; }); // 添加本地新盘的数据(不在服务器已盘列表中的) uploadData.cfCheckVouchsRequests.forEach(function (item) { if (!existingIds[item.checkVouchsId]) { // 从待盘列表中查找完整信息 var foundPending = null; for (var i = 0; i < _self.allPendingList.length; i++) { if (_self.allPendingList[i].checkVouchsId === item.checkVouchsId) { foundPending = _self.allPendingList[i]; break; } } var checkedItem = { id: item.checkVouchsId, checkVouchsId: item.checkVouchsId, checkTime: item.checkVouchTime }; // 补充完整信息 if (foundPending) { checkedItem.assetName = foundPending.assetName; checkedItem.no = foundPending.no; checkedItem.epc = foundPending.epc; checkedItem.positionId = foundPending.positionId; checkedItem.positionName = foundPending.positionName; checkedItem.inventoryId = foundPending.inventoryId; } // 添加到已盘列表 _self.allCheckedList.push(checkedItem); // 构建已盘Map索引 _self.checkedMap[item.checkVouchsId] = true; existingIds[item.checkVouchsId] = true; } }); _self.checkedTotal = _self.allCheckedList.length; console.log('合并后的已盘数据总数:', _self.checkedTotal, '条'); } else { console.log('没有本地新盘数据'); } }, function (error) { console.log('加载本地新盘数据失败(可能是首次盘点):', error); }); }, /** * 处理 RFID 扫描到的 EPC * @param {String} epc - 扫描到的 EPC */ addEpc: function (epc) { var _self = this; // 将EPC添加到缓冲区 _self.scanBuffer.push(epc); // 如果定时器未启动,启动批量处理定时器 if (!_self.batchProcessTimer) { _self.batchProcessTimer = setInterval(function () { _self.processScanBuffer(); }, _self.batchProcessInterval); } }, /** * 批量处理扫描缓冲区中的EPC数据 */ processScanBuffer: function () { var _self = this; // 如果缓冲区为空,直接返回 if (_self.scanBuffer.length === 0) { return; } var processStartTime = Date.now(); var batchSize = _self.scanBuffer.length; console.log('开始批量处理 ' + batchSize + ' 条扫描数据'); // 临时存储本次批量处理的新增已盘项 var newCheckedItems = []; var duplicateCount = 0; var notFoundCount = 0; // 批量处理缓冲区中的所有EPC for (var i = 0; i < batchSize; i++) { var epc = _self.scanBuffer[i]; // 使用Map快速查找待盘数据 var foundItem = _self.pendingMap[epc]; if (foundItem) { // 使用Map快速检查是否已经盘点过 if (!_self.checkedMap[foundItem.checkVouchsId]) { // 添加到已盘列表 var checkedItem = { id: foundItem.checkVouchsId, checkVouchsId: foundItem.checkVouchsId, assetName: foundItem.assetName, no: foundItem.no, epc: foundItem.epc, checkTime: _self.formatDateTime(new Date()), positionId: foundItem.positionId, positionName: foundItem.positionName, inventoryId: foundItem.inventoryId }; // 添加到已盘列表 _self.allCheckedList.push(checkedItem); // 更新已盘Map索引 _self.checkedMap[foundItem.checkVouchsId] = true; // 添加到本次批量新增列表 newCheckedItems.push(checkedItem); } else { duplicateCount++; } } else { notFoundCount++; } } // 清空缓冲区 _self.scanBuffer = []; // 更新已盘总数 _self.checkedTotal = _self.allCheckedList.length; _self.newCheckedCount += newCheckedItems.length; var processEndTime = Date.now(); console.log('批量处理完成: 新增 ' + newCheckedItems.length + ' 条, 重复 ' + duplicateCount + ' 条, 未找到 ' + notFoundCount + ' 条, 耗时 ' + (processEndTime - processStartTime) + 'ms'); // 标记需要更新UI if (newCheckedItems.length > 0) { _self.needsUIUpdate = true; _self.scheduleUIUpdate(); // 实时保存已盘数据到 IndexDB _self.saveToUploadQueue(); } }, /** * 实时保存已盘数据到 IndexDB 的 uploadQueue * 注意:新盘数据会与服务器已盘数据合并,不会覆盖服务器数据 */ saveToUploadQueue: function () { var _self = this; // 如果没有数据库实例或没有已盘数据,不保存 if (!_self.checkVouchDb || !_self.allCheckedList || _self.allCheckedList.length === 0) { return; } // 构建上传数据结构(allCheckedList已经包含了服务器已盘数据和新盘数据) var uploadData = { checkVouchId: _self.inventoryInfo.checkVouchId, cfCheckVouchsRequests: _self.allCheckedList.map(function (item) { return { checkVouchsId: item.checkVouchsId, checkVouchTime: item.checkTime }; }) }; // 保存到 IndexDB 的上传队列(使用 put 会覆盖同一 checkVouchId 的旧数据) _self.checkVouchDb.put('uploadQueue', uploadData, function () { console.log('已盘数据已实时保存到上传队列,数量: ' + _self.allCheckedList.length); }, function (error) { console.error('保存已盘数据失败:', error); }); }, /** * 安排UI更新(节流) */ scheduleUIUpdate: function () { var _self = this; // 如果已经有UI更新定时器,不重复创建 if (_self.uiUpdateTimer) { return; } // 设置UI更新定时器 _self.uiUpdateTimer = setTimeout(function () { _self.performUIUpdate(); _self.uiUpdateTimer = null; }, _self.uiUpdateInterval); }, /** * 执行UI更新 */ performUIUpdate: function () { var _self = this; if (!_self.needsUIUpdate) { return; } // 只有当前在已盘tab时才更新显示列表 if (_self.activeTab === 1) { _self.refreshCheckedList(); } _self.needsUIUpdate = false; console.log('UI更新完成,当前已盘总数: ' + _self.checkedTotal); }, /** * 格式化日期时间 */ formatDateTime: function (date) { var year = date.getFullYear(); var month = String(date.getMonth() + 1).padStart(2, '0'); var day = String(date.getDate()).padStart(2, '0'); var hours = String(date.getHours()).padStart(2, '0'); var minutes = String(date.getMinutes()).padStart(2, '0'); var seconds = String(date.getSeconds()).padStart(2, '0'); return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds; }, /** * Tab切换 */ onTabChange: function (name) { var _self = this; console.log('切换到Tab:', name); // 如果切换到已盘tab if (name === 1) { // 如果有待更新的数据,立即更新UI if (_self.needsUIUpdate) { // 取消定时器,立即更新 if (_self.uiUpdateTimer) { clearTimeout(_self.uiUpdateTimer); _self.uiUpdateTimer = null; } _self.performUIUpdate(); } else if (_self.displayedCheckedList.length < _self.allCheckedList.length) { // 检查是否有新数据需要刷新 _self.refreshCheckedList(); } } }, /** * 刷新已盘列表(重新加载所有数据) */ refreshCheckedList: function () { var _self = this; // 重置分页 _self.checkedPage = 0; _self.displayedCheckedList = []; _self.checkedFinished = false; // 触发加载 _self.checkedLoading = true; _self.onLoadChecked(); }, /** * 加载待盘数据 */ onLoadPending: function () { var _self = this; // 模拟加载延迟 setTimeout(function () { var startIndex = _self.pendingPage * _self.pageSize; var endIndex = startIndex + _self.pageSize; // 获取当前页的数据 var pageData = _self.allPendingList.slice(startIndex, endIndex); if (pageData.length > 0) { // 追加到显示列表 _self.displayedPendingList = _self.displayedPendingList.concat(pageData); _self.pendingPage++; _self.pendingLoading = false; // 判断是否加载完毕 if (_self.displayedPendingList.length >= _self.allPendingList.length) { _self.pendingFinished = true; } } else { // 没有更多数据了 _self.pendingFinished = true; _self.pendingLoading = false; } }, 300); }, /** * 加载已盘数据 */ onLoadChecked: function () { var _self = this; // 模拟加载延迟 setTimeout(function () { var startIndex = _self.checkedPage * _self.pageSize; var endIndex = startIndex + _self.pageSize; // 获取当前页的数据(倒序显示,最新的在前面) var reversedList = _self.allCheckedList.slice().reverse(); var pageData = reversedList.slice(startIndex, endIndex); if (pageData.length > 0) { // 追加到显示列表 _self.displayedCheckedList = _self.displayedCheckedList.concat(pageData); _self.checkedPage++; _self.checkedLoading = false; // 判断是否加载完毕 if (_self.displayedCheckedList.length >= _self.allCheckedList.length) { _self.checkedFinished = true; } } else { // 没有更多数据了 _self.checkedFinished = true; _self.checkedLoading = false; } }, 300); }, /** * 重置待盘分页 */ resetPendingPagination: function () { var _self = this; _self.pendingPage = 0; _self.displayedPendingList = []; _self.pendingFinished = false; _self.pendingLoading = true; }, /** * 重置已盘分页 */ resetCheckedPagination: function () { var _self = this; _self.checkedPage = 0; _self.displayedCheckedList = []; _self.checkedFinished = false; _self.checkedLoading = false; // 不自动触发加载,等待van-list组件触发 }, /** * 启动 RFID 扫描 */ startRfidScan: function () { var _self = this; if (!plugin || !plugin.rfidMiddleware) { console.error('RFID 插件未加载'); return; } // 重置计数器和缓冲区 _self.newCheckedCount = 0; _self.scanBuffer = []; _self.isScanning = true; plugin.rfidMiddleware.start(); plugin.rfidMiddleware.readEvent = function (epc) { _self.addEpc(epc); return "success"; }; console.log('RFID 扫描已启动'); }, /** * 停止 RFID 扫描 */ stopRfidScan: function () { var _self = this; if (!plugin || !plugin.rfidMiddleware) { return; } _self.isScanning = false; plugin.rfidMiddleware.stop(); plugin.rfidMiddleware.stopInventory(); // 清理批量处理定时器 if (_self.batchProcessTimer) { clearInterval(_self.batchProcessTimer); _self.batchProcessTimer = null; } // 处理剩余缓冲区数据 if (_self.scanBuffer.length > 0) { console.log('处理剩余缓冲区数据: ' + _self.scanBuffer.length + ' 条'); _self.processScanBuffer(); } // 清理UI更新定时器 if (_self.uiUpdateTimer) { clearTimeout(_self.uiUpdateTimer); _self.uiUpdateTimer = null; } // 如果有待更新的UI,立即更新 if (_self.needsUIUpdate) { _self.performUIUpdate(); } console.log('RFID 扫描已停止,总计扫描: ' + _self.newCheckedCount + ' 条新数据'); }, /** * 清理所有定时器 */ cleanupTimers: function () { var _self = this; if (_self.batchProcessTimer) { clearInterval(_self.batchProcessTimer); _self.batchProcessTimer = null; } if (_self.uiUpdateTimer) { clearTimeout(_self.uiUpdateTimer); _self.uiUpdateTimer = null; } }, /** * 获取扫描统计信息 */ getScanStats: function () { var _self = this; return { pendingTotal: _self.pendingTotal, checkedTotal: _self.checkedTotal, newCheckedCount: _self.newCheckedCount, bufferSize: _self.scanBuffer.length, scanProgress: _self.pendingTotal > 0 ? ((_self.checkedTotal / _self.pendingTotal) * 100).toFixed(2) : '0.00' }; }, /** * 保存盘点数据到 IndexDB(兼容旧版调用,实际调用 saveToUploadQueue) * @param {Function} callback - 保存成功后的回调 */ saveInventoryData: function (callback) { var _self = this; // 调用实时保存方法 _self.saveToUploadQueue(); // 执行回调 if (callback) { callback(); } }, /** * 初始化 */ init: function () { var _self = this; // 初始化 IndexDB 数据库 var objectStoreDefines = [ { name: 'checkVouchList', defineOption: { keyPath: 'checkVouchId' }, indexDefineList: null }, { name: 'uploadQueue', defineOption: { keyPath: 'checkVouchId' }, indexDefineList: null } ]; _self.checkVouchDb = new IndexDbFactory('checkVouchDB', objectStoreDefines, 1); _self.checkVouchDb.open(function () { console.log('盘点数据库初始化成功'); // 数据库初始化成功后,初始化盘点单信息 _self.initInventoryInfo(); // 启动 RFID 扫描 _self.startRfidScan(); }, function () { console.error('盘点数据库初始化失败'); vant.Dialog.alert({ title: '错误', message: '数据库初始化失败,请先进行数据同步。', theme: 'round-button', }); }); } }, created: function () { console.log('AssetInventoryCheck Vue实例创建完成'); }, mounted: function () { var _self = this; _self.init(); console.log('AssetInventoryCheck页面加载完成'); // 隐藏页面加载指示器 setTimeout(function() { var loadingElement = document.getElementById('pageLoading'); if (loadingElement) { loadingElement.style.display = 'none'; } }, 100); }, beforeDestroy: function () { var _self = this; // 停止 RFID 扫描(会自动清理定时器) _self.stopRfidScan(); // 保存盘点数据 _self.saveInventoryData(); }, destroyed: function () { var _self = this; // 确保停止 RFID 扫描 _self.stopRfidScan(); // 清理所有定时器 _self.cleanupTimers(); } });