From f24a21a41c908285bbcacc59e1356d0713cba151 Mon Sep 17 00:00:00 2001 From: geht <2947093423@qq.com> Date: Mon, 20 Jul 2026 17:31:54 +0800 Subject: [PATCH] =?UTF-8?q?app=E7=AB=AF=E6=96=B0=E5=A2=9E=E5=8E=9F?= =?UTF-8?q?=E6=9D=90=E6=96=99=E9=80=81=E6=A3=80=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- JeecgUniapp-master/.hbuilderx/launch.json | 16 + .../docs/DT50扫描识别-广播参数与接入说明.md | 136 ++++++++ JeecgUniapp-master/env/.env.development | 6 +- JeecgUniapp-master/pages.config.ts | 2 +- JeecgUniapp-master/src/common/work.ts | 36 +- .../HelpTipBubble/HelpTipBubble.vue | 91 +++++ .../src/components/components.d.ts | 1 + JeecgUniapp-master/src/manifest.json | 6 +- JeecgUniapp-master/src/pages.json | 41 ++- JeecgUniapp-master/src/pages/index/index.vue | 20 +- JeecgUniapp-master/src/pages/login/login.vue | 74 +++- .../rawMaterialInspect/inspectResult.vue | 245 ++++++++++++++ .../rawMaterialInspect/rawMaterialInspect.vue | 289 ++++++++++++++++ .../src/pages/scanIdentify/scanIdentify.vue | 318 ++++++++++++++++++ .../src/service/xslmes/rawMaterialInspect.ts | 68 ++++ JeecgUniapp-master/src/static/logo/xslmes.png | Bin 0 -> 20618 bytes JeecgUniapp-master/src/types/uni-pages.d.ts | 3 + JeecgUniapp-master/src/utils/dt50Scan.ts | 291 ++++++++++++++++ .../jeecg-module-xslmes/doc/代码修改日志 | 10 + ...MesXslRawMaterialInspectAppController.java | 95 ++++++ ...MesXslRawMaterialInspectRecordService.java | 12 + ...slRawMaterialInspectRecordServiceImpl.java | 65 ++++ .../vo/MesXslRawMaterialInspectAppScanVo.java | 30 ++ qhmes.code-workspace | 3 +- 24 files changed, 1806 insertions(+), 52 deletions(-) create mode 100644 JeecgUniapp-master/.hbuilderx/launch.json create mode 100644 JeecgUniapp-master/docs/DT50扫描识别-广播参数与接入说明.md create mode 100644 JeecgUniapp-master/src/components/HelpTipBubble/HelpTipBubble.vue create mode 100644 JeecgUniapp-master/src/pages/rawMaterialInspect/inspectResult.vue create mode 100644 JeecgUniapp-master/src/pages/rawMaterialInspect/rawMaterialInspect.vue create mode 100644 JeecgUniapp-master/src/pages/scanIdentify/scanIdentify.vue create mode 100644 JeecgUniapp-master/src/service/xslmes/rawMaterialInspect.ts create mode 100644 JeecgUniapp-master/src/static/logo/xslmes.png create mode 100644 JeecgUniapp-master/src/utils/dt50Scan.ts create mode 100644 jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslRawMaterialInspectAppController.java create mode 100644 jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslRawMaterialInspectAppScanVo.java diff --git a/JeecgUniapp-master/.hbuilderx/launch.json b/JeecgUniapp-master/.hbuilderx/launch.json new file mode 100644 index 00000000..5e2090f2 --- /dev/null +++ b/JeecgUniapp-master/.hbuilderx/launch.json @@ -0,0 +1,16 @@ +{ + "version" : "1.0", + "configurations" : [ + { + "playground" : "standard", + "type" : "uni-app:app-android" + }, + { + "app-plus" : + { + "launchtype" : "local" + }, + "type" : "uniCloud" + } + ] +} diff --git a/JeecgUniapp-master/docs/DT50扫描识别-广播参数与接入说明.md b/JeecgUniapp-master/docs/DT50扫描识别-广播参数与接入说明.md new file mode 100644 index 00000000..3e6aeecc --- /dev/null +++ b/JeecgUniapp-master/docs/DT50扫描识别-广播参数与接入说明.md @@ -0,0 +1,136 @@ +# DT50 扫描识别 —— 广播参数与接入说明 + +> 面向 APP「协作」页「扫描识别」功能。 +> 设备:优博讯 UROVO **DT50**(Android 11)。 +> 参数来源:**设备实测 adb logcat 抓真实扫码** + **优博讯官方 ScanManager 文档** + **DCloud UniApp 官方示例** 三方交叉验证。 +> 记录日期:2026-07-20。 + +--- + +## 一、核心参数(最重要) + +| 项目 | 值 | 说明 | +|---|---|---| +| 输出方式 | **Intent / 广播** | 设备当前**已是此模式**,无需在设置页切换 | +| 广播 Action | `android.intent.ACTION_DECODE_DATA` | 实测 + 官方一致 | +| 条码文本(String) | `barcode_string` | 官方常量 `BARCODE_STRING_TAG`,**首选** | +| 原始字节(byte[]) | `barcode` | 官方常量 `DECODE_DATA_TAG`,兜底用 | +| 长度(int) | `length` | 官方常量 `BARCODE_LENGTH_TAG` | +| 码制(int/String) | `barcodeType` | 官方常量 `BARCODE_TYPE_TAG`,实测读出 `Code128` | +| 扫描键 keycode | `523` | KEYCODE_SCAN(机身侧键) | + +## 二、设备侧验证结论 + +- **硬件**:成像头正常,成功解出 Code128 条码 ✅ +- **触发**:侧键 keycode = 523,按下发 `ACTION_KEYCODE_SCAN_PRESSED` +- **广播**:成功解码时实测发出 `android.intent.ACTION_DECODE_DATA (has extras)` 并被接收 ✅ +- **模式**:当前即广播输出(非键盘输出),**直接 registerReceiver 即可** +- **无需**:原生 `.aar` 插件 / 自定义基座 / USB 驱动 / 完整 AndroidStudio 套壳;标准基座即可 + +相关系统组件(备查): +- 扫描设置 App:`com.ubx.barcodescanner.tool` +- 扫描服务:`com.ubx.uscanner` +- DataWedge 式配置:`com.ubx.datawedge` + +## 三、UniApp 监听代码(标准基座,无需插件) + +```js +let scanReceiver = null; + +/** 开始监听 DT50 扫描广播 */ +function startScanListener(onBarcode) { + const main = plus.android.runtimeMainActivity(); + const IntentFilter = plus.android.importClass('android.content.IntentFilter'); + const filter = new IntentFilter(); + filter.addAction('android.intent.ACTION_DECODE_DATA'); // DT50 广播 Action + + scanReceiver = plus.android.implements('io.dcloud.feature.internal.reflect.BroadcastReceiver', { + onReceive: function (context, intent) { + plus.android.importClass(intent); + // 首选直接取字符串 + let code = intent.getStringExtra('barcode_string'); + // 兜底:部分场景用字节数组 + if (!code) { + const bytes = intent.getByteArrayExtra('barcode'); + if (bytes) code = plus.android.newObject('java.lang.String', bytes); + } + const type = intent.getStringExtra('barcodeType'); // 码制,可选 + if (code) onBarcode(code, type); + } + }); + main.registerReceiver(scanReceiver, filter); +} + +/** 停止监听(务必在页面卸载时调用,避免重复注册 / 内存泄漏) */ +function stopScanListener() { + if (scanReceiver) { + plus.android.runtimeMainActivity().unregisterReceiver(scanReceiver); + scanReceiver = null; + } +} +``` + +页面接入: + +```js +onLoad() { + startScanListener((code, type) => { + this.barcode = code; + // TODO: 调 MES 后端接口 / 查料 + }); +}, +onUnload() { + stopScanListener(); +} +``` + +> 注意:仅 App(plus 环境)下可用,H5/小程序无 `plus`,接入时需做平台判断(`#ifdef APP-PLUS`)。 + +## 四、故障排查 + +| 现象 | 原因 / 处理 | +|---|---| +| 收不到广播 | 确认扫描设置里输出为「Intent/广播」而非「键盘/输入法」;确认 Action 拼写 | +| 扫描后文本框被输入内容 | 键盘输出模式也开了,去扫描设置关掉键盘输出 | +| `barcode_string` 为空 | 用兜底的 `barcode`(byte[]) 转 String | +| 一直解码失败(红光有但不出码) | 距离 15~20cm,红光完整压住条码,拿稳 1~2 秒;避免手机屏幕反光码 | + +## 五、参考 + +- 优博讯官方 ScanManager 文档:https://en.urovo.com/developer/android/device/ScanManager.html +- DCloud UniApp 监听优博讯扫码广播(含示例):https://ask.dcloud.net.cn/article/36468 + +## 六、本仓库接入位置(2026-07-20) + +| 项 | 位置 | +|---|---| +| 菜单入口 | `src/common/work.ts` → 其他服务「合同」后「扫描识别」 | +| 页面 | `src/pages/scanIdentify/scanIdentify.vue` | +| 广播工具 | `src/utils/dt50Scan.ts` | +| 行为 | 仅广播展示条码/码制/时间,不调后端、不弹输入法 | +| 生命周期 | `onShow` 注册 / `onHide`+`onUnload` 注销;同码防抖 | + +## 七、键盘输出 vs 广播输出 + +| | 键盘输出(Keyboard / 楔入) | 广播输出(Intent / Broadcast) | +|---|---|---| +| 原理 | 把条码当成「敲键盘」打进当前焦点输入框 | 系统发广播,App 用 `registerReceiver` 收 | +| App 是否要抢焦点 | 要,通常还会弹出软键盘 | **不需要**输入框焦点 | +| 适合场景 | 记事本、任意输入框快速验证 | 业务页稳定取码、拿码制等扩展字段 | +| 本页策略 | 已关闭楔入,避免弹输入法 | **本页只走广播** | + +设备设置建议:扫描设置 → 关闭「键盘输出」,开启「Intent/广播输出」。 +本页进入时会主动 `hideKeyboard`,不自动聚焦任何输入框。 + +## 附:参数是如何抓到的(可复现) + +```bash +# adb 路径(本机 Android SDK) +ADB="C:/Users/hp/AppData/Local/Android/Sdk/platform-tools/adb.exe" + +$ADB devices -l # 确认 DT50 已连(USB 调试) +$ADB logcat -c # 清空日志缓冲 +$ADB shell "timeout 40 logcat -v threadtime '*:V'" > scan.log # 抓 40s +# 抓取期间用 DT50 侧键扫几次条码,然后: +grep -E "ACTION_DECODE_DATA|barcodeType|DECODER" scan.log +``` diff --git a/JeecgUniapp-master/env/.env.development b/JeecgUniapp-master/env/.env.development index 734633fc..1a35d730 100644 --- a/JeecgUniapp-master/env/.env.development +++ b/JeecgUniapp-master/env/.env.development @@ -2,7 +2,7 @@ NODE_ENV = 'development' # 是否去除console 和 debugger VITE_DELETE_CONSOLE = false -# 是否开启sourcemap -VITE_SHOW_SOURCEMAP = true +# 是否开启sourcemap(App 真机编译易 OOM,开发期先关闭) +VITE_SHOW_SOURCEMAP = false -VITE_SERVER_BASEURL = 'http://localhost:8080/jeecg-boot' +VITE_SERVER_BASEURL = 'http://192.168.1.3:8888/jeecg-boot' diff --git a/JeecgUniapp-master/pages.config.ts b/JeecgUniapp-master/pages.config.ts index c109a168..0aff7102 100644 --- a/JeecgUniapp-master/pages.config.ts +++ b/JeecgUniapp-master/pages.config.ts @@ -36,7 +36,7 @@ export default defineUniPages({ iconPath: 'static/tabbar/tabbar-home-2.png', selectedIconPath: 'static/tabbar/tabbar-home.png', pagePath: 'pages/index/index', - text: '协作', + text: '生产', }, // { // iconPath: 'static/tabbar/tabbar-workHome-2.png', diff --git a/JeecgUniapp-master/src/common/work.ts b/JeecgUniapp-master/src/common/work.ts index 4b37f483..645b2c0b 100644 --- a/JeecgUniapp-master/src/common/work.ts +++ b/JeecgUniapp-master/src/common/work.ts @@ -1,5 +1,5 @@ /** - * 常用服务 + * 基础服务(原常用服务) * useful server */ @@ -108,36 +108,28 @@ export const us = { } /** - * other server 其他服务 + * 生产服务(原其他服务) + * 首页「更多」按钮仍按 type=other 追加,勿删空数组 */ export const os = { data: [ + //update-begin---author:xsl ---date:20260720 for:【APP首页】生产服务菜单调整----------- { - title: '新闻中心', - icon: icon_prefix + 'xinwen.png', - description: '新闻中心', - routeIndex: 'news', + title: '原材料送检', + icon: icon_prefix + 'renwu.png', + description: '扫码送检与录入检验结果', useCount: 10000, - }, - { - title: '会议', - icon: icon_prefix + 'huiyi.png', - description: '会议', - useCount: 10000, - routeIndex: 'meeting', + routeIndex: 'rawMaterialInspect', enabled: true, }, { - title: '任务中心', - icon: icon_prefix + 'renwu.png', - description: '任务中心', - useCount: 10000, - }, - { - title: '合同', - icon: icon_prefix + 'hetong.png', - description: '合同', + title: '扫描识别', + icon: icon_prefix + 'wendang.png', + description: '手持机扫描头识别条码', useCount: 10000, + routeIndex: 'scanIdentify', + enabled: true, }, + //update-end---author:xsl ---date:20260720 for:【APP首页】生产服务菜单调整----------- ], } diff --git a/JeecgUniapp-master/src/components/HelpTipBubble/HelpTipBubble.vue b/JeecgUniapp-master/src/components/HelpTipBubble/HelpTipBubble.vue new file mode 100644 index 00000000..0db8515f --- /dev/null +++ b/JeecgUniapp-master/src/components/HelpTipBubble/HelpTipBubble.vue @@ -0,0 +1,91 @@ + + + + + diff --git a/JeecgUniapp-master/src/components/components.d.ts b/JeecgUniapp-master/src/components/components.d.ts index c2538692..718d9dcb 100644 --- a/JeecgUniapp-master/src/components/components.d.ts +++ b/JeecgUniapp-master/src/components/components.d.ts @@ -5,6 +5,7 @@ Breadcrumb: typeof import('./Breadcrumb/Breadcrumb.vue')['default'] CategorySelect: typeof import('./CategorySelect/CategorySelect.vue')['default'] DateTime: typeof import('./DateTime/DateTime.vue')['default'] Grid: typeof import('./Grid/Grid.vue')['default'] +HelpTipBubble: typeof import('./HelpTipBubble/HelpTipBubble.vue')['default'] ImgPreview: typeof import('./ImgPreview/ImgPreview.vue')['default'] LFile: typeof import('./LFile/LFile.vue')['default'] PageLayout: typeof import('./PageLayout/PageLayout.vue')['default'] diff --git a/JeecgUniapp-master/src/manifest.json b/JeecgUniapp-master/src/manifest.json index 5f6b1883..244deba7 100644 --- a/JeecgUniapp-master/src/manifest.json +++ b/JeecgUniapp-master/src/manifest.json @@ -130,8 +130,8 @@ "sdkConfigs": { "maps": { "amap": { - "key": "???", - "securityJsCode": "???", + "key": "20854e7d231ee339bfa3b277c840070c", + "securityJsCode": "7a542edee4a82e56ed88fef8ef42b5a5", "serviceHost": "" } } @@ -142,4 +142,4 @@ "bundleName": "uniapp.demo.test" } } -} +} \ No newline at end of file diff --git a/JeecgUniapp-master/src/pages.json b/JeecgUniapp-master/src/pages.json index 896f1b7e..af27f64f 100644 --- a/JeecgUniapp-master/src/pages.json +++ b/JeecgUniapp-master/src/pages.json @@ -33,7 +33,7 @@ "iconPath": "static/tabbar/tabbar-home-2.png", "selectedIconPath": "static/tabbar/tabbar-home.png", "pagePath": "pages/index/index", - "text": "协作" + "text": "生产" }, { "iconPath": "static/tabbar/tabbar-user-2.png", @@ -197,6 +197,45 @@ } } }, + { + "path": "pages/rawMaterialInspect/inspectResult", + "type": "page", + "layout": "default", + "style": { + "navigationBarTitleText": "录入检验结果", + "navigationStyle": "custom", + "disableScroll": true, + "app-plus": { + "bounce": "none" + } + } + }, + { + "path": "pages/rawMaterialInspect/rawMaterialInspect", + "type": "page", + "layout": "default", + "style": { + "navigationBarTitleText": "原材料送检", + "navigationStyle": "custom", + "disableScroll": true, + "app-plus": { + "bounce": "none" + } + } + }, + { + "path": "pages/scanIdentify/scanIdentify", + "type": "page", + "layout": "default", + "style": { + "navigationBarTitleText": "扫描识别", + "navigationStyle": "custom", + "disableScroll": true, + "app-plus": { + "bounce": "none" + } + } + }, { "path": "pages/user/people", "type": "page", diff --git a/JeecgUniapp-master/src/pages/index/index.vue b/JeecgUniapp-master/src/pages/index/index.vue index 0766c509..5ac42e0f 100644 --- a/JeecgUniapp-master/src/pages/index/index.vue +++ b/JeecgUniapp-master/src/pages/index/index.vue @@ -28,22 +28,22 @@ - + - - - - - - - - - + + + + + + + + + diff --git a/JeecgUniapp-master/src/pages/login/login.vue b/JeecgUniapp-master/src/pages/login/login.vue index 71a3a9ad..51c9d113 100644 --- a/JeecgUniapp-master/src/pages/login/login.vue +++ b/JeecgUniapp-master/src/pages/login/login.vue @@ -14,9 +14,12 @@