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 @@
+
+
+
+ ?
+
+
+
+ {{ text }}
+
+
+
+
+
+
+
+
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 @@
-
-
- {{ compTitle || 'JEECG BOOT' }}
+
+ 启航密炼
+ 智能制造MES手持端
+
+
+
@@ -69,7 +72,7 @@
-
+
{{ loading ? '登录...' : '登录' }}
@@ -80,6 +83,11 @@
+
+
@@ -361,20 +369,64 @@ if (isLocalConfig === false) {
.page-container {
padding: 0 20upx;
padding-top: 100upx;
+ padding-bottom: calc(24upx + env(safe-area-inset-bottom));
position: relative;
font-size: 15px;
color: var(--UI-FG-0);
- .logo {
- width: 200upx;
- height: 150px;
+ min-height: 100vh;
+ box-sizing: border-box;
+ display: flex;
+ flex-direction: column;
+ .brand {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ flex-shrink: 0;
}
- .title {
- font-size: 58upx;
+ .brand-title {
+ font-size: 52upx;
+ font-weight: 700;
+ color: #1a1a1a;
+ letter-spacing: 6upx;
+ line-height: 1.3;
+ }
+ .brand-subtitle {
+ margin-top: 12upx;
+ font-size: 28upx;
+ color: #666;
+ letter-spacing: 2upx;
+ line-height: 1.4;
+ }
+ .form-wrap {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ min-height: 0;
+ }
+ .footer {
+ flex-shrink: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 12upx;
+ padding-top: 24upx;
+ padding-bottom: 12upx;
+ }
+ .footer-logo {
+ width: 48upx;
+ height: 48upx;
+ border-radius: 8upx;
+ }
+ .footer-text {
+ font-size: 22upx;
+ color: #888;
+ letter-spacing: 1upx;
}
.enter-area {
- padding-top: 75px;
+ padding-top: 24px;
width: 87%;
- margin: 0 auto 60upx;
+ margin: 0 auto 40upx;
.box {
display: flex;
align-items: center;
diff --git a/JeecgUniapp-master/src/pages/rawMaterialInspect/inspectResult.vue b/JeecgUniapp-master/src/pages/rawMaterialInspect/inspectResult.vue
new file mode 100644
index 00000000..684cd1e4
--- /dev/null
+++ b/JeecgUniapp-master/src/pages/rawMaterialInspect/inspectResult.vue
@@ -0,0 +1,245 @@
+
+{
+ layout: 'default',
+ style: {
+ navigationBarTitleText: '录入检验结果',
+ navigationStyle: 'custom',
+ disableScroll: true,
+ 'app-plus': {
+ bounce: 'none',
+ },
+ },
+}
+
+
+
+
+
+
+
+
+
+
+ 条码{{ record.barcode || '-' }}
+ 批次{{ record.batchNo || '-' }}
+ 物料{{ record.materialName || '-' }}
+ 送检时间{{ record.inspectTime || '-' }}
+
+
+
+ 加载中…
+ 暂无检验明细
+
+ {{ idx + 1 }}. {{ line.inspectItemName || '检验项' }}
+ 容差:{{ formatRange(line) }}
+ 状态:{{ passText(line.passFlag) }}
+
+ 检验值
+ onValueInput(line, e)"
+ />
+
+
+ 检验值
+ {{ line.inspectValue ?? '-' }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/JeecgUniapp-master/src/pages/rawMaterialInspect/rawMaterialInspect.vue b/JeecgUniapp-master/src/pages/rawMaterialInspect/rawMaterialInspect.vue
new file mode 100644
index 00000000..7dabb673
--- /dev/null
+++ b/JeecgUniapp-master/src/pages/rawMaterialInspect/rawMaterialInspect.vue
@@ -0,0 +1,289 @@
+
+{
+ layout: 'default',
+ style: {
+ navigationBarTitleText: '原材料送检',
+ navigationStyle: 'custom',
+ disableScroll: true,
+ 'app-plus': {
+ bounce: 'none',
+ },
+ },
+}
+
+
+
+
+
+
+
+
+
+
+
+ 查询
+
+
+
+ 暂无待送检数据,请扫码或查询
+
+
+ {{ item.barcode }}
+ 移除
+
+ 批次{{ item.batchNo || '-' }}
+ 入场日期{{ formatDate(item.entryDate) }}
+ 物料名称{{ item.materialName || '-' }}
+ 供应商{{ item.supplierName || '-' }}
+ 厂家物料{{ item.manufacturerMaterialName || '-' }}
+ 保质期{{ item.shelfLife || '-' }}
+ 库区{{ item.warehouseArea || '-' }}
+ 卸货人{{ item.unloadOperator || '-' }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/JeecgUniapp-master/src/pages/scanIdentify/scanIdentify.vue b/JeecgUniapp-master/src/pages/scanIdentify/scanIdentify.vue
new file mode 100644
index 00000000..3ee67a10
--- /dev/null
+++ b/JeecgUniapp-master/src/pages/scanIdentify/scanIdentify.vue
@@ -0,0 +1,318 @@
+
+{
+ layout: 'default',
+ style: {
+ navigationBarTitleText: '扫描识别',
+ navigationStyle: 'custom',
+ disableScroll: true,
+ 'app-plus': {
+ bounce: 'none',
+ },
+ },
+}
+
+
+
+
+
+
+ {{ isAppEnv ? '请按下侧键扫描条码' : '请在 DT50 手持机 App 中使用' }}
+
+ {{
+ isAppEnv
+ ? '本页使用广播接收扫码结果,不会自动弹出输入法。请在设备扫描设置中开启 Intent/广播输出。'
+ : 'H5 无法调用扫描头'
+ }}
+
+
+
+
+ 最近一次识别
+ {{ latestCode || '等待扫描…' }}
+
+ 来源:{{ latestSource }}
+ 码制:{{ latestType }}
+ 时间:{{ latestTime }}
+
+
+
+
+ 扫描记录
+ 清空
+
+
+ 暂无记录
+
+ {{ history.length - index }}
+
+ {{ item.code }}
+
+ {{ item.source }}
+ {{ item.type }}
+ {{ item.time }}
+
+
+
+
+
+
+ 调试日志
+ 清空
+
+
+ {{ line }}
+
+
+
+
+
+
+
+
diff --git a/JeecgUniapp-master/src/service/xslmes/rawMaterialInspect.ts b/JeecgUniapp-master/src/service/xslmes/rawMaterialInspect.ts
new file mode 100644
index 00000000..8bb7cbf3
--- /dev/null
+++ b/JeecgUniapp-master/src/service/xslmes/rawMaterialInspect.ts
@@ -0,0 +1,68 @@
+import { http } from '@/utils/http'
+
+const BASE = '/xslmes/app/rawMaterialInspect'
+
+/** 原材料卡片(展示字段) */
+export interface RawMaterialCard {
+ id: string
+ barcode?: string
+ batchNo?: string
+ entryDate?: string
+ materialName?: string
+ supplierName?: string
+ manufacturerMaterialName?: string
+ shelfLife?: string
+ warehouseArea?: string
+ unloadOperator?: string
+ testResult?: string
+}
+
+export interface InspectScanResult {
+ card: RawMaterialCard
+ /** sendInspect | enterResult | finished */
+ action: string
+ hasPendingInspect?: boolean
+ pendingRecordId?: string
+}
+
+export interface InspectRecordLine {
+ id: string
+ recordId?: string
+ inspectItemName?: string
+ allowMin?: number | null
+ includeMinFlag?: number
+ allowMax?: number | null
+ includeMaxFlag?: number
+ inspectValue?: number | string | null
+ passFlag?: string
+ sortNo?: number
+}
+
+export interface InspectRecord {
+ id: string
+ barcode?: string
+ batchNo?: string
+ materialName?: string
+ inspectStatus?: string
+ inspectTime?: string
+}
+
+/** 按条码查询卡片及送检状态 */
+export const queryByBarcode = (barcode: string) =>
+ http.get(`${BASE}/queryByBarcode`, { barcode })
+
+/** 按条码送检 */
+export const createByBarcode = (barcode: string) =>
+ http.post(`${BASE}/createByBarcode`, { barcode })
+
+/** 加载检验明细 */
+export const prepareResultEntry = (id: string) =>
+ http.post(`${BASE}/prepareResultEntry`, { id })
+
+/** 保存检验结果 */
+export const saveInspectResult = (id: string, lineList: Array<{ id: string; inspectValue: number | string }>) =>
+ http.post(`${BASE}/saveInspectResult`, { id, lineList })
+
+/** 查询送检记录主表 */
+export const queryRecordById = (id: string) =>
+ http.get(`${BASE}/queryRecordById`, { id })
diff --git a/JeecgUniapp-master/src/static/logo/xslmes.png b/JeecgUniapp-master/src/static/logo/xslmes.png
new file mode 100644
index 00000000..fbcbade1
Binary files /dev/null and b/JeecgUniapp-master/src/static/logo/xslmes.png differ
diff --git a/JeecgUniapp-master/src/types/uni-pages.d.ts b/JeecgUniapp-master/src/types/uni-pages.d.ts
index 34924c2b..e533b730 100644
--- a/JeecgUniapp-master/src/types/uni-pages.d.ts
+++ b/JeecgUniapp-master/src/types/uni-pages.d.ts
@@ -17,6 +17,9 @@ interface NavigateToOptions {
"/pages/login/loginOauth2" |
"/pages/message/message" |
"/pages/more/more" |
+ "/pages/rawMaterialInspect/inspectResult" |
+ "/pages/rawMaterialInspect/rawMaterialInspect" |
+ "/pages/scanIdentify/scanIdentify" |
"/pages/user/people" |
"/pages/workHome/workHome" |
"/pages-home/home/home" |
diff --git a/JeecgUniapp-master/src/utils/dt50Scan.ts b/JeecgUniapp-master/src/utils/dt50Scan.ts
new file mode 100644
index 00000000..dad25ebb
--- /dev/null
+++ b/JeecgUniapp-master/src/utils/dt50Scan.ts
@@ -0,0 +1,291 @@
+/**
+ * 优博讯 DT50 扫描头广播监听
+ * 参数见 docs/DT50扫描识别-广播参数与接入说明.md
+ *
+ * 说明:设备常同时开启「广播 + 键盘」双通道,需优先广播并合并去重,
+ * 否则键盘缓冲会把同一条码拼成两遍(如 6942…28286942…2828)。
+ */
+
+export type Dt50ScanCallback = (code: string, type?: string, source?: string) => void
+export type Dt50LogCallback = (msg: string) => void
+
+const SCAN_ACTIONS = ['android.intent.ACTION_DECODE_DATA']
+
+const CODE_KEYS = ['barcode_string', 'scannerdata', 'data', 'barcode']
+const TYPE_KEYS = ['codetype', 'barcodeType', 'codeType', 'type']
+
+/** 同码防抖窗口(广播+键盘几乎同时到达) */
+const DEBOUNCE_MS = 1200
+/** 广播成功后,忽略键盘楔入的时间窗 */
+const IGNORE_KEYBOARD_AFTER_BROADCAST_MS = 1500
+
+let scanReceiver: any = null
+let listening = false
+let registering = false
+let lastCode = ''
+let lastTime = 0
+let lastBroadcastTime = 0
+let broadcastConfirmed = false
+let activeCallback: Dt50ScanCallback | null = null
+let logCallback: Dt50LogCallback | null = null
+
+function log(msg: string) {
+ const line = `[dt50Scan] ${msg}`
+ console.log(line)
+ try {
+ logCallback && logCallback(line)
+ } catch (_e) {
+ // ignore
+ }
+}
+
+function hasPlusAndroid() {
+ return typeof plus !== 'undefined' && !!(plus as any).android
+}
+
+function toJsString(val: any): string {
+ if (val == null || val === undefined) return ''
+ if (typeof val === 'string') return val.trim()
+ try {
+ if (typeof val === 'object' && typeof val.toString === 'function') {
+ const s = val.toString()
+ if (s && s !== '[object Object]') return String(s).trim()
+ }
+ } catch (_e) {
+ // ignore
+ }
+ try {
+ return String(plus.android.invoke(val, 'toString') || '').trim()
+ } catch (_e) {
+ return String(val).trim()
+ }
+}
+
+function bytesToString(bytes: any): string {
+ if (!bytes) return ''
+ try {
+ const JString = plus.android.importClass('java.lang.String') as any
+ return toJsString(new JString(bytes, 'UTF-8'))
+ } catch (_e) {
+ try {
+ return toJsString(plus.android.newObject('java.lang.String', bytes))
+ } catch (_e2) {
+ return ''
+ }
+ }
+}
+
+/** 拆开「同一条码粘成两遍」的情况 */
+export function normalizeScanCode(raw: string): string {
+ const s = String(raw || '')
+ .replace(/[\r\n\t]+/g, '')
+ .trim()
+ if (!s) return ''
+ // 整串 = A+A
+ if (s.length >= 6 && s.length % 2 === 0) {
+ const half = s.length / 2
+ const a = s.slice(0, half)
+ const b = s.slice(half)
+ if (a && a === b) {
+ log(`检测到粘连双码,已拆半: ${s} -> ${a}`)
+ return a
+ }
+ }
+ return s
+}
+
+function dumpAllExtras(intent: any): string {
+ const found: string[] = []
+ const allKeys = Array.from(new Set([...CODE_KEYS, ...TYPE_KEYS, 'length']))
+ for (const key of allKeys) {
+ try {
+ const s = intent.getStringExtra(key)
+ if (s != null) found.push(`${key}(str)=${toJsString(s)}`)
+ } catch (_e) {
+ // ignore
+ }
+ try {
+ const bytes = intent.getByteArrayExtra(key)
+ if (bytes) found.push(`${key}(bytes)=${bytesToString(bytes)}`)
+ } catch (_e) {
+ // ignore
+ }
+ try {
+ const n = intent.getIntExtra(key, -999999)
+ if (n !== -999999) found.push(`${key}(int)=${n}`)
+ } catch (_e) {
+ // ignore
+ }
+ }
+ return found.length ? found.join(' | ') : '(无可用 extra)'
+}
+
+function parseBarcode(intent: any): string {
+ for (const key of CODE_KEYS) {
+ try {
+ const s = toJsString(intent.getStringExtra(key))
+ if (s) return normalizeScanCode(s)
+ } catch (_e) {
+ // ignore
+ }
+ }
+ try {
+ const bytes = intent.getByteArrayExtra('barcode')
+ const s = bytesToString(bytes)
+ if (s) return normalizeScanCode(s)
+ } catch (_e) {
+ // ignore
+ }
+ return ''
+}
+
+function parseType(intent: any): string {
+ for (const key of TYPE_KEYS) {
+ try {
+ const s = toJsString(intent.getStringExtra(key))
+ if (s) return s
+ } catch (_e) {
+ // ignore
+ }
+ }
+ return ''
+}
+
+function emitBarcode(code: string, type: string, source: string) {
+ const normalized = normalizeScanCode(code)
+ if (!normalized) return
+
+ const now = Date.now()
+
+ // 广播已出结果时,短时间内的键盘结果一律丢弃(避免粘连/重复)
+ if (source === 'keyboard') {
+ if (broadcastConfirmed && now - lastBroadcastTime < IGNORE_KEYBOARD_AFTER_BROADCAST_MS) {
+ log(`忽略键盘重复(广播优先) code=${normalized}`)
+ return
+ }
+ if (broadcastConfirmed) {
+ log(`忽略键盘(本页已确认广播可用) code=${normalized}`)
+ return
+ }
+ }
+
+ if (normalized === lastCode && now - lastTime < DEBOUNCE_MS) {
+ log(`防抖忽略重复码 source=${source} code=${normalized}`)
+ return
+ }
+
+ lastCode = normalized
+ lastTime = now
+ if (source === 'broadcast') {
+ lastBroadcastTime = now
+ broadcastConfirmed = true
+ }
+
+ log(`识别成功 source=${source} code=${normalized} type=${type || '-'}`)
+ const cb = activeCallback
+ if (!cb) {
+ log('警告:无页面回调,条码未展示')
+ return
+ }
+ setTimeout(() => {
+ try {
+ cb(normalized, type || undefined, source)
+ } catch (e) {
+ log(`回调异常: ${e}`)
+ }
+ }, 0)
+}
+
+function doReceive(_context: any, intent: any) {
+ log('>>> onReceive 触发(说明广播已进入 App)')
+ try {
+ plus.android.importClass(intent)
+ const action = toJsString(intent.getAction())
+ log(`action=${action}`)
+ log(`extras=${dumpAllExtras(intent)}`)
+ const code = parseBarcode(intent)
+ if (!code) {
+ log('广播已收到,但未能解析出条码文本')
+ return
+ }
+ emitBarcode(code, parseType(intent), 'broadcast')
+ } catch (e) {
+ log(`onReceive 异常: ${e}`)
+ }
+}
+
+function registerNow(onBarcode: Dt50ScanCallback) {
+ activeCallback = onBarcode
+ if (listening && scanReceiver) {
+ log('已在监听中,仅更新回调')
+ return
+ }
+ if (registering) {
+ log('正在注册中,跳过重复注册')
+ return
+ }
+ registering = true
+
+ const main = plus.android.runtimeMainActivity()
+ const IntentFilter = plus.android.importClass('android.content.IntentFilter') as any
+ const filter = new IntentFilter()
+ SCAN_ACTIONS.forEach((action) => filter.addAction(action))
+
+ scanReceiver = plus.android.implements('io.dcloud.feature.internal.reflect.BroadcastReceiver', {
+ onReceive: doReceive,
+ })
+
+ try {
+ main.registerReceiver(scanReceiver, filter)
+ listening = true
+ log(`已注册广播监听 actions=${SCAN_ACTIONS.join(',')}`)
+ } catch (e) {
+ scanReceiver = null
+ listening = false
+ log(`registerReceiver 失败: ${e}`)
+ } finally {
+ registering = false
+ }
+}
+
+export function setDt50ScanLogger(cb: Dt50LogCallback | null) {
+ logCallback = cb
+}
+
+/** 本页是否已确认广播可用(用于关闭键盘楔入) */
+export function isDt50BroadcastConfirmed() {
+ return broadcastConfirmed
+}
+
+export function reportDt50ScanCode(code: string, source = 'keyboard') {
+ emitBarcode(String(code || ''), '', source)
+}
+
+export function startDt50ScanListener(onBarcode: Dt50ScanCallback) {
+ if (!hasPlusAndroid()) {
+ log('当前环境无 plus.android,无法监听扫描头广播')
+ return
+ }
+ registerNow(onBarcode)
+}
+
+export function stopDt50ScanListener() {
+ activeCallback = null
+ broadcastConfirmed = false
+ lastBroadcastTime = 0
+ if (!hasPlusAndroid() || !scanReceiver) {
+ listening = false
+ registering = false
+ scanReceiver = null
+ return
+ }
+ try {
+ plus.android.runtimeMainActivity().unregisterReceiver(scanReceiver)
+ log('已取消广播监听')
+ } catch (e) {
+ log(`unregisterReceiver 失败: ${e}`)
+ }
+ scanReceiver = null
+ listening = false
+ registering = false
+}
diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/doc/代码修改日志 b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/doc/代码修改日志
index 4576c58f..07b7171a 100644
--- a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/doc/代码修改日志
+++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/doc/代码修改日志
@@ -1247,3 +1247,13 @@ jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/
jeecgboot-vue3/src/views/xslmes/mesXslDryingProcessSwitch/MesXslDryingProcessSwitchPage.vue
jeecgboot-vue3/src/views/xslmes/mesXslDryingProcessSwitch/MesXslDryingProcessSwitch.api.ts
-- author:jiangxh---date:20260708--for: 【MES】烘胶流程开启(总开关+二次确认,不校验烘胶房日期) ---
+
+-- author:xsl---date:20260720--for: APPԭͼ졿ֳֶ˰ѯ/ͼ/¼ӿҳ ---
+jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslRawMaterialInspectAppScanVo.java
+jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslRawMaterialInspectAppController.java
+jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslRawMaterialInspectRecordService.java
+jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslRawMaterialInspectRecordServiceImpl.java
+JeecgUniapp-master/src/service/xslmes/rawMaterialInspect.ts
+JeecgUniapp-master/src/pages/rawMaterialInspect/rawMaterialInspect.vue
+JeecgUniapp-master/src/pages/rawMaterialInspect/inspectResult.vue
+JeecgUniapp-master/src/common/work.ts
diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslRawMaterialInspectAppController.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslRawMaterialInspectAppController.java
new file mode 100644
index 00000000..4aa22056
--- /dev/null
+++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslRawMaterialInspectAppController.java
@@ -0,0 +1,95 @@
+package org.jeecg.modules.xslmes.controller;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.lang3.StringUtils;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.aspect.annotation.AutoLog;
+import org.jeecg.modules.xslmes.entity.MesXslRawMaterialInspectRecord;
+import org.jeecg.modules.xslmes.entity.MesXslRawMaterialInspectRecordLine;
+import org.jeecg.modules.xslmes.service.IMesXslRawMaterialInspectRecordService;
+import org.jeecg.modules.xslmes.vo.MesXslRawMaterialInspectAppScanVo;
+import org.jeecg.modules.xslmes.vo.MesXslRawMaterialInspectRecordPage;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * APP 原材料送检接口(手持端)
+ * 判重规则与 PC 一致:存在 inspect_status=0 的送检记录视为已送检。
+ */
+@Tag(name = "APP-原材料送检")
+@RestController
+@RequestMapping("/xslmes/app/rawMaterialInspect")
+public class MesXslRawMaterialInspectAppController {
+
+ @Autowired private IMesXslRawMaterialInspectRecordService inspectRecordService;
+
+ //update-begin---author:xsl ---date:20260720 for:【APP原材料送检】扫码查询-----------
+ @AutoLog(value = "APP原材料送检-按条码查询")
+ @Operation(summary = "按条码查询卡片及送检状态")
+ @GetMapping("/queryByBarcode")
+ public Result queryByBarcode(
+ @RequestParam(name = "barcode") String barcode) {
+ if (StringUtils.isBlank(barcode)) {
+ return Result.error("条码不能为空");
+ }
+ return Result.OK(inspectRecordService.queryByBarcodeForApp(barcode.trim()));
+ }
+ //update-end---author:xsl ---date:20260720 for:【APP原材料送检】扫码查询-----------
+
+ //update-begin---author:xsl ---date:20260720 for:【APP原材料送检】按条码送检-----------
+ @AutoLog(value = "APP原材料送检-按条码送检")
+ @Operation(summary = "按条码送检")
+ @PostMapping("/createByBarcode")
+ public Result createByBarcode(@RequestBody Map body) {
+ String barcode = body.get("barcode") == null ? "" : body.get("barcode").toString();
+ if (StringUtils.isBlank(barcode)) {
+ return Result.error("条码不能为空");
+ }
+ MesXslRawMaterialInspectRecord record = inspectRecordService.createByBarcode(barcode.trim());
+ return Result.OK("送检成功", record);
+ }
+ //update-end---author:xsl ---date:20260720 for:【APP原材料送检】按条码送检-----------
+
+ //update-begin---author:xsl ---date:20260720 for:【APP原材料送检】录入检验结果-----------
+ @AutoLog(value = "APP原材料送检-加载检验明细")
+ @Operation(summary = "录入检验结果前加载明细")
+ @PostMapping("/prepareResultEntry")
+ public Result> prepareResultEntry(
+ @RequestBody Map body) {
+ String id = body.get("id") == null ? "" : body.get("id").toString();
+ if (StringUtils.isBlank(id)) {
+ return Result.error("id不能为空");
+ }
+ return Result.OK(inspectRecordService.prepareResultEntryLines(id.trim()));
+ }
+
+ @AutoLog(value = "APP原材料送检-保存检验结果")
+ @Operation(summary = "保存检验结果")
+ @PostMapping("/saveInspectResult")
+ public Result saveInspectResult(@RequestBody MesXslRawMaterialInspectRecordPage page) {
+ if (StringUtils.isBlank(page.getId())) {
+ return Result.error("id不能为空");
+ }
+ inspectRecordService.saveInspectResult(page.getId(), page.getLineList());
+ return Result.OK("保存成功");
+ }
+
+ @Operation(summary = "按送检记录ID查询主表")
+ @GetMapping("/queryRecordById")
+ public Result queryRecordById(@RequestParam(name = "id") String id) {
+ MesXslRawMaterialInspectRecord db = inspectRecordService.getById(id);
+ if (db == null) {
+ return Result.error("未找到对应数据");
+ }
+ return Result.OK(db);
+ }
+ //update-end---author:xsl ---date:20260720 for:【APP原材料送检】录入检验结果-----------
+}
diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslRawMaterialInspectRecordService.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslRawMaterialInspectRecordService.java
index fb16ed7b..ee91714c 100644
--- a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslRawMaterialInspectRecordService.java
+++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslRawMaterialInspectRecordService.java
@@ -23,4 +23,16 @@ public interface IMesXslRawMaterialInspectRecordService
Integer includeMinFlag,
BigDecimal allowMax,
Integer includeMaxFlag);
+
+ //update-begin---author:xsl ---date:20260720 for:【APP原材料送检】按条码查询/送检-----------
+ /**
+ * APP:按条码查询卡片及送检状态(是否已有待检送检记录)
+ */
+ org.jeecg.modules.xslmes.vo.MesXslRawMaterialInspectAppScanVo queryByBarcodeForApp(String barcode);
+
+ /**
+ * APP:按条码发起送检
+ */
+ MesXslRawMaterialInspectRecord createByBarcode(String barcode);
+ //update-end---author:xsl ---date:20260720 for:【APP原材料送检】按条码查询/送检-----------
}
diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslRawMaterialInspectRecordServiceImpl.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslRawMaterialInspectRecordServiceImpl.java
index d1db6d68..76f243ec 100644
--- a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslRawMaterialInspectRecordServiceImpl.java
+++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslRawMaterialInspectRecordServiceImpl.java
@@ -324,4 +324,69 @@ public class MesXslRawMaterialInspectRecordServiceImpl
private String normalize(String value) {
return StringUtils.trimToEmpty(value);
}
+
+ //update-begin---author:xsl ---date:20260720 for:【APP原材料送检】按条码查询/送检-----------
+ @Override
+ public org.jeecg.modules.xslmes.vo.MesXslRawMaterialInspectAppScanVo queryByBarcodeForApp(String barcode) {
+ String code = normalize(barcode);
+ if (StringUtils.isBlank(code)) {
+ throw new JeecgBootException("条码不能为空");
+ }
+ MesXslRawMaterialCard card =
+ rawMaterialCardService
+ .lambdaQuery()
+ .eq(MesXslRawMaterialCard::getBarcode, code)
+ .last("LIMIT 1")
+ .one();
+ if (card == null) {
+ throw new JeecgBootException("未找到条码对应的原材料卡片");
+ }
+ MesXslRawMaterialInspectRecord pending =
+ this.lambdaQuery()
+ .eq(MesXslRawMaterialInspectRecord::getRawMaterialCardId, card.getId())
+ .eq(MesXslRawMaterialInspectRecord::getInspectStatus, STATUS_PENDING)
+ .orderByDesc(MesXslRawMaterialInspectRecord::getInspectTime)
+ .last("LIMIT 1")
+ .one();
+
+ org.jeecg.modules.xslmes.vo.MesXslRawMaterialInspectAppScanVo vo =
+ new org.jeecg.modules.xslmes.vo.MesXslRawMaterialInspectAppScanVo();
+ vo.setCard(card);
+ if (pending != null) {
+ // 已有待检送检记录 → 视为已送检,进入录入检验结果
+ vo.setHasPendingInspect(true);
+ vo.setPendingRecordId(pending.getId());
+ vo.setAction("enterResult");
+ return vo;
+ }
+ vo.setHasPendingInspect(false);
+ String cardTestResult = normalize(card.getTestResult());
+ if (StringUtils.isBlank(cardTestResult) || CARD_TEST_RESULT_UNTESTED.equals(cardTestResult)) {
+ vo.setAction("sendInspect");
+ } else {
+ // 已合格/不合格且无待检记录
+ vo.setAction("finished");
+ }
+ return vo;
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public MesXslRawMaterialInspectRecord createByBarcode(String barcode) {
+ String code = normalize(barcode);
+ if (StringUtils.isBlank(code)) {
+ throw new JeecgBootException("条码不能为空");
+ }
+ MesXslRawMaterialCard card =
+ rawMaterialCardService
+ .lambdaQuery()
+ .eq(MesXslRawMaterialCard::getBarcode, code)
+ .last("LIMIT 1")
+ .one();
+ if (card == null) {
+ throw new JeecgBootException("未找到条码对应的原材料卡片");
+ }
+ return createByRawMaterialCardId(card.getId());
+ }
+ //update-end---author:xsl ---date:20260720 for:【APP原材料送检】按条码查询/送检-----------
}
diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslRawMaterialInspectAppScanVo.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslRawMaterialInspectAppScanVo.java
new file mode 100644
index 00000000..dc9f4110
--- /dev/null
+++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslRawMaterialInspectAppScanVo.java
@@ -0,0 +1,30 @@
+package org.jeecg.modules.xslmes.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import java.io.Serializable;
+import lombok.Data;
+import org.jeecg.modules.xslmes.entity.MesXslRawMaterialCard;
+
+/**
+ * APP 原材料送检扫码查询结果
+ */
+@Data
+@Schema(description = "APP原材料送检扫码结果")
+public class MesXslRawMaterialInspectAppScanVo implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @Schema(description = "原材料卡片")
+ private MesXslRawMaterialCard card;
+
+ /**
+ * sendInspect=可送检;enterResult=已送检待录入;finished=已完成检验
+ */
+ @Schema(description = "下一步动作:sendInspect/enterResult/finished")
+ private String action;
+
+ @Schema(description = "是否存在待检送检记录")
+ private Boolean hasPendingInspect;
+
+ @Schema(description = "待检送检记录ID(action=enterResult 时有值)")
+ private String pendingRecordId;
+}
diff --git a/qhmes.code-workspace b/qhmes.code-workspace
index ab2f0bda..1b450c5b 100644
--- a/qhmes.code-workspace
+++ b/qhmes.code-workspace
@@ -17,7 +17,8 @@
"name": "打印调节器"
},
{
- "path": "JeecgUniapp-master"
+ "path": "JeecgUniapp-master",
+ "name": "APP端"
}
],
"settings": {