// common/scanMixin.js // 多厂商PDA扫码器兼容方案 - 策略模式 + 配置表驱动 import { BUILTIN_SCANNER_CONFIGS, getScanConfig, hasShownNoConfigHint, isPdaDevice as detectPdaDevice, isPhoneScanConfig, markNoConfigHintShown, normalizeConfig, PHONE_SCAN_CONFIG, } from '@/common/scanConfig.js'; export default { data() { return { scanReceivers: [], isPageActive: false, registeredBrands: [], remoteScannerConfigs: [], usePhoneScanFallback: false, _scanCallback: null, } }, methods: { getScannerConfigs() { return BUILTIN_SCANNER_CONFIGS; }, getPhoneScanConfig() { return { ...PHONE_SCAN_CONFIG }; }, isPdaDevice() { return detectPdaDevice(); }, shouldUsePhoneScan() { const builtinConfigs = this.getScannerConfigs(); const activeConfig = getScanConfig(builtinConfigs); if (activeConfig && isPhoneScanConfig(activeConfig)) { return true; } if (!activeConfig && !this.isPdaDevice()) { return true; } return false; }, getAllScannerConfigs() { const builtinConfigs = this.getScannerConfigs(); if (!this.remoteScannerConfigs.length) { return builtinConfigs; } const configMap = new Map(); builtinConfigs.forEach((item) => configMap.set(item.brand, item)); this.remoteScannerConfigs.forEach((item) => configMap.set(item.brand, item)); if (!configMap.has(PHONE_SCAN_CONFIG.brand)) { configMap.set(PHONE_SCAN_CONFIG.brand, { ...PHONE_SCAN_CONFIG }); } return Array.from(configMap.values()); }, getActiveScanConfig() { return getScanConfig(this.getScannerConfigs()); }, getDefaultScanConfig() { const configs = this.getAllScannerConfigs().filter((item) => !isPhoneScanConfig(item)); return configs.length ? configs[0] : null; }, openPhoneScan(options = {}) { const callback = options.callback || this._scanCallback; // #ifdef APP-PLUS || MP-WEIXIN uni.scanCode({ scanType: options.scanType || ['qrCode', 'barCode'], success: (res) => { this.handleScanResult(res.result, callback); }, fail: (err) => { console.error('手机扫码失败:', err); if (options.fail) { options.fail(err); return; } uni.showToast({ title: '扫码失败', icon: 'none', }); }, }); return; // #endif // #ifdef H5 uni.showToast({ title: 'H5环境不支持扫码功能', icon: 'none', }); // #endif }, triggerScan() { if (this.usePhoneScanFallback) { this.openPhoneScan(); } }, registerScanBroadcast(scanCallback) { this._scanCallback = scanCallback; // #ifndef APP-PLUS this.usePhoneScanFallback = true; return true; // #endif // #ifdef APP-PLUS if (this.shouldUsePhoneScan()) { this.usePhoneScanFallback = true; console.log('使用手机扫码模式'); return true; } this.usePhoneScanFallback = false; const activeConfig = this.getActiveScanConfig(); if (activeConfig && !isPhoneScanConfig(activeConfig)) { return this.registerScanBroadcastByConfig(activeConfig, scanCallback); } if (!hasShownNoConfigHint()) { markNoConfigHintShown(); uni.showToast({ title: '请先在「我的-扫描设置」配置扫码枪', icon: 'none', duration: 2500, }); } const defaultConfig = this.getDefaultScanConfig(); if (!defaultConfig) { console.error('未找到默认可用的扫码枪配置'); return false; } return this.registerScanBroadcastByConfig(defaultConfig, scanCallback); // #endif }, registerScanBroadcastByBrand(brand, scanCallback) { // #ifdef APP-PLUS const configs = this.getAllScannerConfigs(); const config = configs.find(c => c.brand === brand); if (!config) { console.error(`未找到厂商配置: ${brand}`); return false; } if (isPhoneScanConfig(config)) { this._scanCallback = scanCallback; this.usePhoneScanFallback = true; return true; } return this.registerScanBroadcastByConfig(config, scanCallback); // #endif }, registerScanBroadcastByConfig(config, scanCallback) { // #ifdef APP-PLUS const normalizedConfig = normalizeConfig(config, this.getScannerConfigs()); if (!normalizedConfig) { console.error('扫码枪配置无效'); return false; } if (isPhoneScanConfig(normalizedConfig)) { this._scanCallback = scanCallback; this.usePhoneScanFallback = true; return true; } try { this.registerSingleBroadcast(normalizedConfig, scanCallback); this.registeredBrands.push(normalizedConfig.brand); this.usePhoneScanFallback = false; console.log(`${normalizedConfig.name}扫码广播注册成功`); return true; } catch (error) { console.error(`${normalizedConfig.name}扫码广播注册失败:`, error); return false; } // #endif }, registerSingleBroadcast(config, scanCallback) { const main = plus.android.runtimeMainActivity(); if (config.needSetup && config.setupAction) { try { const Intent = plus.android.importClass('android.content.Intent'); const setupIntent = new Intent(config.setupAction); Object.keys(config.setupParams || {}).forEach(key => { setupIntent.putExtra(key, config.setupParams[key]); }); main.sendBroadcast(setupIntent); console.log(`${config.name}扫码配置完成`); } catch (error) { console.error(`${config.name}扫码配置失败:`, error); } } const IntentFilter = plus.android.importClass('android.content.IntentFilter'); const filter = new IntentFilter(); filter.addAction(config.action); const self = this; const receiver = plus.android.implements( 'io.dcloud.feature.internal.reflect.BroadcastReceiver', { onReceive: (context, intent) => { console.log(`${config.name}扫码广播接收,isPageActive:`, self.isPageActive); if (!self.isPageActive) return; try { // 广播回调里的 intent 需要按实例导入,否则 getStringExtra 不可用 plus.android.importClass(intent); const scanResult = intent.getStringExtra(config.dataKey); console.log(`${config.name}扫码结果:`, scanResult); if (scanResult) { self.handleScanResult(scanResult, scanCallback); } } catch (error) { console.error(`处理${config.name}广播数据出错:`, error); } } } ); main.registerReceiver(receiver, filter); this.scanReceivers.push({ brand: config.brand, receiver: receiver }); }, handleScanResult(scanResult, scanCallback) { try { let cleanCode = scanResult.replace(/\s+/g, '').replace(/[\r\n]/g, ''); console.log("扫码结果:", cleanCode); if (scanCallback) { scanCallback(cleanCode); } } catch (error) { console.error("处理扫码结果时出错:", error); } }, unregisterScanBroadcast() { // #ifdef APP-PLUS if (this.scanReceivers.length === 0) return; try { const main = plus.android.runtimeMainActivity(); this.scanReceivers.forEach(item => { try { main.unregisterReceiver(item.receiver); console.log(`${item.brand}扫码广播注销成功`); } catch (err) { console.error(`${item.brand}扫码广播注销失败:`, err); } }); this.scanReceivers = []; this.registeredBrands = []; console.log('所有扫码广播注销完成'); } catch (err) { console.error('注销扫码广播失败:', err); } // #endif }, handleGoodsScan(scanCode, successCallback, errorCallback) { const trimmedCode = scanCode ? scanCode.toString().trim() : ""; if (!trimmedCode) { this.playError && this.playError(); errorCallback && errorCallback("无效的二维码!"); return; } if (this.processScanCode) { this.processScanCode(trimmedCode, successCallback, errorCallback); } else { successCallback && successCallback(trimmedCode); } } }, onShow() { this.isPageActive = true; console.log('页面显示,设置 isPageActive 为 true'); }, onHide() { this.isPageActive = false; }, onUnload() { this.isPageActive = false; this.unregisterScanBroadcast(); } }