- 在 FabricOutScanBar 组件中添加手机扫码图标和事件处理 - 更新工作台页面的扫码逻辑以支持手机扫码回退 - 在销售拣货详情页添加手机扫码按钮和处理方法 - 重构扫码设置页面以支持扫码方式选择 - 添加手机扫码配置和判断逻辑到扫码配置模块 - 扩展扫码混入模块以支持手机扫码模式和设备检测 - 在多个业务页面中集成手机扫码功能和界面元素 - 更新扫码配置存储和读取逻辑以兼容新配置结构
363 lines
10 KiB
JavaScript
363 lines
10 KiB
JavaScript
// common/scanMixin.js
|
|
// 多厂商PDA扫码器兼容方案 - 策略模式 + 配置表驱动
|
|
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 {
|
|
scanReceivers: [],
|
|
isPageActive: false,
|
|
registeredBrands: [],
|
|
remoteScannerConfigs: [],
|
|
usePhoneScanFallback: false,
|
|
_scanCallback: null,
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
getScannerConfigs() {
|
|
return [
|
|
{
|
|
brand: 'newland',
|
|
name: '东集',
|
|
action: 'com.android.server.scannerservice.broadcast',
|
|
dataKey: 'scannerdata',
|
|
needSetup: true,
|
|
setupAction: 'com.android.scanner.service_settings',
|
|
setupParams: {
|
|
action_barcode_broadcast: 'com.android.server.scannerservice.broadcast',
|
|
key_barcode_broadcast: 'scannerdata',
|
|
endchar: 'ENTER'
|
|
}
|
|
},
|
|
{
|
|
brand: 'sunmi',
|
|
name: '商米',
|
|
action: 'com.sunmi.scanner.ACTION_DATA_CODE_RECEIVED',
|
|
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) {
|
|
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 {
|
|
plus.android.importClass('android.content.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();
|
|
}
|
|
}
|