From 36c0f9a3a0ef29f3a4095cff4abfa39c35f44e07 Mon Sep 17 00:00:00 2001 From: xuan <1359774872@qq.com> Date: Tue, 23 Jun 2026 17:08:17 +0800 Subject: [PATCH] =?UTF-8?q?feat(scan):=20=E6=B7=BB=E5=8A=A0=E6=89=8B?= =?UTF-8?q?=E6=9C=BA=E6=89=AB=E7=A0=81=E5=8A=9F=E8=83=BD=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 FabricOutScanBar 组件中添加手机扫码图标和事件处理 - 更新工作台页面的扫码逻辑以支持手机扫码回退 - 在销售拣货详情页添加手机扫码按钮和处理方法 - 重构扫码设置页面以支持扫码方式选择 - 添加手机扫码配置和判断逻辑到扫码配置模块 - 扩展扫码混入模块以支持手机扫码模式和设备检测 - 在多个业务页面中集成手机扫码功能和界面元素 - 更新扫码配置存储和读取逻辑以兼容新配置结构 --- src/common/scanConfig.js | 25 +++- src/common/scanMixin.js | 117 +++++++++++++++++- .../storefabric/FabricOutScanBar.vue | 14 +++ src/pages/saleship/salepickscandetail.vue | 18 ++- .../storefabric/storeFabricBusinessOutAdd.vue | 12 +- .../storeFabricBusinessOutEdit.vue | 2 + .../storeFabricBusinessOutMixin.js | 13 +- .../storegoods/storeGoodsBusinessCheckAdd.vue | 20 +-- .../storeGoodsBusinessCheckDetail.vue | 22 ++-- .../storeGoodsBusinessStationMoveOnly.vue | 14 ++- src/pages/sys/user/scan-settings.vue | 112 ++++++++++------- src/pages/sys/workbench/index.vue | 11 +- 12 files changed, 277 insertions(+), 103 deletions(-) diff --git a/src/common/scanConfig.js b/src/common/scanConfig.js index c082c74..1a3d4da 100644 --- a/src/common/scanConfig.js +++ b/src/common/scanConfig.js @@ -2,8 +2,20 @@ export const STORAGE_KEY = 'pda_scan_config'; export const DICTIONARY_TYPE_SCANNER = 10046; +export const PHONE_SCAN_BRAND = 'phone'; + +export const PHONE_SCAN_CONFIG = { + brand: PHONE_SCAN_BRAND, + name: '手机扫码', + isPhoneScan: true, +}; + const NO_SETUP_HINT_KEY = 'pda_scan_config_hint_shown'; +export function isPhoneScanConfig(config) { + return !!(config && (config.isPhoneScan || config.brand === PHONE_SCAN_BRAND)); +} + function enrichFromBuiltinConfig(config, builtinConfigs = []) { if (!config || !builtinConfigs.length) { return config; @@ -30,8 +42,15 @@ function enrichFromBuiltinConfig(config, builtinConfigs = []) { export function normalizeConfig(raw, builtinConfigs = []) { if (!raw || typeof raw !== 'object') return null; + const brand = String(raw.brand || raw.id || raw.dictionary_detail_id || raw.name || ''); + const isPhoneScan = raw.isPhoneScan === true || brand === PHONE_SCAN_BRAND; + + if (isPhoneScan) { + return { ...PHONE_SCAN_CONFIG }; + } + const config = enrichFromBuiltinConfig({ - brand: String(raw.brand || raw.id || raw.dictionary_detail_id || raw.name || ''), + brand, name: raw.name || '', action: raw.action || raw.code || '', dataKey: raw.dataKey || raw.data_key || raw.remark || '', @@ -51,10 +70,10 @@ export function mapDictionaryToScannerConfig(raw, builtinConfigs = []) { return normalizeConfig(raw, builtinConfigs); } -export function getScanConfig() { +export function getScanConfig(builtinConfigs = []) { try { const data = uni.getStorageSync(STORAGE_KEY); - return normalizeConfig(data); + return normalizeConfig(data, builtinConfigs); } catch (e) { console.log('读取扫码枪配置失败', e); return null; diff --git a/src/common/scanMixin.js b/src/common/scanMixin.js index fab48a0..f104a7e 100644 --- a/src/common/scanMixin.js +++ b/src/common/scanMixin.js @@ -3,10 +3,16 @@ import { getScanConfig, hasShownNoConfigHint, + isPhoneScanConfig, markNoConfigHintShown, normalizeConfig, + PHONE_SCAN_CONFIG, } from '@/common/scanConfig.js'; +const PDA_DEVICE_KEYWORDS = [ + 'newland', 'nls', 'sunmi', 'urovo', 'zebra', 'honeywell', 'idata', 'seuic', +]; + export default { data() { return { @@ -14,6 +20,8 @@ export default { isPageActive: false, registeredBrands: [], remoteScannerConfigs: [], + usePhoneScanFallback: false, + _scanCallback: null, } }, @@ -40,9 +48,43 @@ export default { dataKey: 'data', needSetup: false }, + { ...PHONE_SCAN_CONFIG }, ]; }, + getPhoneScanConfig() { + return { ...PHONE_SCAN_CONFIG }; + }, + + isPdaDevice() { + // #ifdef APP-PLUS + try { + const Build = plus.android.importClass('android.os.Build'); + const manufacturer = String(Build.MANUFACTURER || '').toLowerCase(); + const model = String(Build.MODEL || '').toLowerCase(); + return PDA_DEVICE_KEYWORDS.some((keyword) => { + return manufacturer.includes(keyword) || model.includes(keyword); + }); + } catch (error) { + console.log('检测设备类型失败', error); + return false; + } + // #endif + return false; + }, + + 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) { @@ -52,23 +94,77 @@ export default { 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(); + return getScanConfig(this.getScannerConfigs()); }, getDefaultScanConfig() { - const configs = this.getAllScannerConfigs(); + 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) { + if (activeConfig && !isPhoneScanConfig(activeConfig)) { return this.registerScanBroadcastByConfig(activeConfig, scanCallback); } @@ -101,21 +197,34 @@ export default { 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); + 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) { diff --git a/src/components/storefabric/FabricOutScanBar.vue b/src/components/storefabric/FabricOutScanBar.vue index 9d80a9d..e346bbf 100644 --- a/src/components/storefabric/FabricOutScanBar.vue +++ b/src/components/storefabric/FabricOutScanBar.vue @@ -10,6 +10,14 @@ @input="$emit('input', $event.detail.value)" @confirm="$emit('scan')" /> +