From 10ae883d6368fb8fc3f95620f610c3aaf6c6a3cd Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期二, 14 七月 2026 13:50:35 +0800
Subject: [PATCH] PDA扫码调试

---
 src/pages/inspectionUpload/upload.vue                |   33 -
 src/pages/works.vue                                  |  231 +++++++-----
 src/pages/equipmentManagement/upkeep/add.vue         |  147 +++++---
 src/components/pda-scan/pda-scan.vue                 |  226 ++++++++++++-
 src/pages/equipmentManagement/repair/add.vue         |  144 +++++---
 src/components/pda-media-upload/pda-media-upload.vue |    3 
 src/components/ScanWaitMask.vue                      |  220 ++++++++++++
 7 files changed, 734 insertions(+), 270 deletions(-)

diff --git a/src/components/ScanWaitMask.vue b/src/components/ScanWaitMask.vue
new file mode 100644
index 0000000..7407fb2
--- /dev/null
+++ b/src/components/ScanWaitMask.vue
@@ -0,0 +1,220 @@
+<template>
+  <view v-if="show" class="swm-mask" @touchmove.stop.prevent @tap.stop>
+    <view class="swm-card" @tap.stop>
+      <view class="swm-figure">
+        <view v-if="status === 'waiting'" class="swm-scan-box">
+          <view class="swm-scan-line" />
+          <view class="swm-scan-corner tl" />
+          <view class="swm-scan-corner tr" />
+          <view class="swm-scan-corner bl" />
+          <view class="swm-scan-corner br" />
+        </view>
+        <view v-else-if="status === 'done'" class="swm-check">
+          <view class="swm-check-mark" />
+        </view>
+        <view v-else class="swm-warn">
+          <view class="swm-warn-bar" />
+          <view class="swm-warn-dot" />
+        </view>
+      </view>
+      <view class="swm-title">{{ titleText }}</view>
+      <view class="swm-sub">{{ subText }}</view>
+    </view>
+  </view>
+</template>
+
+<script setup>
+  import { computed } from "vue";
+
+  const props = defineProps({
+    show: { type: Boolean, default: false },
+    status: { type: String, default: "waiting" },
+    title: { type: String, default: "" },
+    subTitle: { type: String, default: "" },
+  });
+
+  const titleText = computed(() => {
+    if (props.title) return props.title;
+    if (props.status === "done") return "鎵爜瀹屾垚";
+    if (props.status === "timeout") return "鎵爜瓒呮椂";
+    return "绛夊緟鎵爜";
+  });
+
+  const subText = computed(() => {
+    if (props.subTitle) return props.subTitle;
+    if (props.status === "done") return "姝e湪澶勭悊鎵爜缁撴灉";
+    if (props.status === "timeout") return "鏈敹鍒版壂鐮佹暟鎹紝璇烽噸璇�";
+    return "璇峰鍑嗕簩缁寸爜/鏉$爜杩涜鎵弿";
+  });
+</script>
+
+<style scoped lang="scss">
+  .swm-mask {
+    position: fixed;
+    left: 0;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    z-index: 9999;
+    background: rgba(0, 0, 0, 0.5);
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+
+  .swm-card {
+    width: 620rpx;
+    padding: 36rpx 32rpx 30rpx;
+    background: #ffffff;
+    border-radius: 24rpx;
+    box-shadow: 0 16rpx 44rpx rgba(0, 0, 0, 0.22);
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+  }
+
+  .swm-figure {
+    width: 260rpx;
+    height: 260rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-bottom: 18rpx;
+  }
+
+  .swm-title {
+    font-size: 34rpx;
+    font-weight: 700;
+    color: rgba(0, 0, 0, 0.88);
+    margin-bottom: 10rpx;
+  }
+
+  .swm-sub {
+    font-size: 26rpx;
+    color: rgba(0, 0, 0, 0.55);
+    text-align: center;
+    line-height: 38rpx;
+  }
+
+  .swm-scan-box {
+    width: 220rpx;
+    height: 220rpx;
+    border-radius: 22rpx;
+    background: rgba(25, 137, 250, 0.06);
+    position: relative;
+    overflow: hidden;
+  }
+
+  .swm-scan-line {
+    position: absolute;
+    left: 14rpx;
+    right: 14rpx;
+    height: 6rpx;
+    top: 18rpx;
+    border-radius: 6rpx;
+    background: linear-gradient(90deg, rgba(25, 137, 250, 0), #1989fa, rgba(25, 137, 250, 0));
+    animation: swmScan 1.2s linear infinite;
+  }
+
+  .swm-scan-corner {
+    position: absolute;
+    width: 34rpx;
+    height: 34rpx;
+    border-color: #1989fa;
+    border-style: solid;
+  }
+
+  .swm-scan-corner.tl {
+    left: 0;
+    top: 0;
+    border-width: 6rpx 0 0 6rpx;
+    border-top-left-radius: 20rpx;
+  }
+
+  .swm-scan-corner.tr {
+    right: 0;
+    top: 0;
+    border-width: 6rpx 6rpx 0 0;
+    border-top-right-radius: 20rpx;
+  }
+
+  .swm-scan-corner.bl {
+    left: 0;
+    bottom: 0;
+    border-width: 0 0 6rpx 6rpx;
+    border-bottom-left-radius: 20rpx;
+  }
+
+  .swm-scan-corner.br {
+    right: 0;
+    bottom: 0;
+    border-width: 0 6rpx 6rpx 0;
+    border-bottom-right-radius: 20rpx;
+  }
+
+  @keyframes swmScan {
+    0% {
+      transform: translateY(0);
+      opacity: 0.9;
+    }
+    90% {
+      opacity: 0.95;
+    }
+    100% {
+      transform: translateY(180rpx);
+      opacity: 0.55;
+    }
+  }
+
+  .swm-check {
+    width: 180rpx;
+    height: 180rpx;
+    border-radius: 90rpx;
+    background: rgba(18, 185, 129, 0.12);
+    border: 6rpx solid rgba(18, 185, 129, 0.85);
+    position: relative;
+  }
+
+  .swm-check-mark {
+    position: absolute;
+    left: 58rpx;
+    top: 72rpx;
+    width: 56rpx;
+    height: 30rpx;
+    border-left: 10rpx solid rgba(18, 185, 129, 0.95);
+    border-bottom: 10rpx solid rgba(18, 185, 129, 0.95);
+    transform: rotate(-45deg);
+  }
+
+  .swm-warn {
+    width: 180rpx;
+    height: 180rpx;
+    border-radius: 90rpx;
+    background: rgba(245, 158, 11, 0.12);
+    border: 6rpx solid rgba(245, 158, 11, 0.9);
+    position: relative;
+  }
+
+  .swm-warn-bar {
+    position: absolute;
+    left: 50%;
+    top: 44rpx;
+    width: 10rpx;
+    height: 72rpx;
+    border-radius: 10rpx;
+    transform: translateX(-50%);
+    background: rgba(245, 158, 11, 0.95);
+  }
+
+  .swm-warn-dot {
+    position: absolute;
+    left: 50%;
+    bottom: 42rpx;
+    width: 14rpx;
+    height: 14rpx;
+    border-radius: 14rpx;
+    transform: translateX(-50%);
+    background: rgba(245, 158, 11, 0.95);
+  }
+</style>
+
diff --git a/src/components/pda-media-upload/pda-media-upload.vue b/src/components/pda-media-upload/pda-media-upload.vue
index c9fd8e5..f645485 100644
--- a/src/components/pda-media-upload/pda-media-upload.vue
+++ b/src/components/pda-media-upload/pda-media-upload.vue
@@ -93,11 +93,9 @@
   const uploading = ref(false);
   const uploadProgress = ref(0);
 
-  // 鐩戝惉涓婁紶鐘舵�侊紝鍙戝嚭浜嬩欢
   const watchUploading = val => {
     emit("uploading", val);
   };
-  // 鐩戝惉杩涘害锛屽彂鍑轰簨浠�
   const watchProgress = val => {
     emit("progress", val);
   };
@@ -393,4 +391,3 @@
     font-size: 13px;
   }
 </style>
-
diff --git a/src/components/pda-scan/pda-scan.vue b/src/components/pda-scan/pda-scan.vue
index 341200f..de3f9bf 100644
--- a/src/components/pda-scan/pda-scan.vue
+++ b/src/components/pda-scan/pda-scan.vue
@@ -18,9 +18,17 @@
       extraKey: { type: String, default: "" },
       debounceMs: { type: Number, default: 150 },
     },
+    data() {
+      return {
+        _ensureTimer: null,
+        _ensureTries: 0,
+      };
+    },
     mounted() {
-      this.init();
-      if (this.active) this.start();
+      this.ensureStarted();
+    },
+    onHide() {
+      this.stop();
     },
     beforeUnmount() {
       this.stop();
@@ -28,14 +36,45 @@
     watch: {
       active(val) {
         if (val) {
-          this.init();
-          this.start();
+          this.ensureStarted();
         } else {
           this.stop();
         }
       },
     },
     methods: {
+      ensureStarted() {
+        if (!this.active) return;
+        this._ensureTries = 0;
+        if (this._ensureTimer) {
+          clearInterval(this._ensureTimer);
+          this._ensureTimer = null;
+        }
+
+        const tick = () => {
+          if (!this.active) return;
+          if (isRegistered) return;
+          this.init();
+          this.start();
+          this._ensureTries += 1;
+          if (isRegistered) {
+            if (this._ensureTimer) {
+              clearInterval(this._ensureTimer);
+              this._ensureTimer = null;
+            }
+          } else if (this._ensureTries >= 50) {
+            if (this._ensureTimer) {
+              clearInterval(this._ensureTimer);
+              this._ensureTimer = null;
+            }
+          }
+        };
+
+        tick();
+        if (!isRegistered) {
+          this._ensureTimer = setInterval(tick, 200);
+        }
+      },
       canUseAndroidBroadcast() {
         try {
           if (typeof plus === "undefined") return false;
@@ -47,22 +86,22 @@
         }
       },
       resolveBroadcastConfig(sys) {
+        try {
+          const brand = String(sys?.brand || "").toUpperCase();
+          const model = String(sys?.model || "").toUpperCase();
+          if (
+            brand.includes("DROI") ||
+            model.includes("MV-IDP5204") ||
+            model.includes("IDP")
+          ) {
+            return { action: "com.service.scanner.data", extraKey: "ScanCode" };
+          }
+        } catch (e) {}
         if (this.action && this.extraKey) {
           return { action: this.action, extraKey: this.extraKey };
         }
 
-        const brand = String(sys?.brand || "").toUpperCase();
-        const model = String(sys?.model || "").toUpperCase();
-
-        if (
-          brand.includes("DROI") ||
-          model.includes("MV-IDP5204") ||
-          model.includes("IDP")
-        ) {
-          return { action: "com.service.scanner.data", extraKey: "ScanCode" };
-        }
-
-        return { action: "", extraKey: "" };
+        return { action: "com.service.scanner.data", extraKey: "ScanCode" };
       },
       init() {
         if (!this.canUseAndroidBroadcast()) return;
@@ -86,14 +125,157 @@
           "android.content.IntentFilter"
         );
         intentFilter = new IntentFilter();
-        intentFilter.addAction(action);
+        const pickActions = v => {
+          const list = [];
+          if (v) {
+            String(v)
+              .split(/[,\s]+/)
+              .map(s => s.trim())
+              .filter(Boolean)
+              .forEach(a => list.push(a));
+          }
+          [
+            "com.service.scanner.data",
+            "com.scanner.broadcast",
+            "com.android.scanner.broadcast",
+            "com.seuic.scanner.data",
+            "com.android.scanner.receiver",
+            "com.android.scanner.result",
+            "com.rfid.SCAN",
+            "com.honeywell.decode.intent.action",
+            "com.symbol.datawedge.data",
+            "com.symbol.datawedge.api.RESULT_ACTION",
+            "com.datalogic.decodewedge.decode_action",
+            "android.intent.ACTION_DECODE_DATA",
+            "android.intent.action.SCANRESULT",
+            "android.intent.action.DECODE_DATA",
+            "scan.rcv.message",
+          ].forEach(a => {
+            if (!list.includes(a)) list.push(a);
+          });
+          return list;
+        };
+
+        const actions = pickActions(action);
+        actions.forEach(a => intentFilter.addAction(a));
+
+        const pickExtraKeys = key => {
+          const list = [];
+          if (key) {
+            String(key)
+              .split(/[,\s]+/)
+              .map(s => s.trim())
+              .filter(Boolean)
+              .forEach(k => list.push(k));
+          }
+          [
+            "ScanCode",
+            "scanCode",
+            "barcode",
+            "barCode",
+            "data",
+            "DATA",
+            "code",
+            "CODE",
+            "result",
+            "RESULT",
+            "scannerdata",
+            "decode_data",
+            "SCAN_RESULT",
+            "data_string",
+            "com.symbol.datawedge.data_string",
+            "com.symbol.datawedge.label_type",
+          ].forEach(k => {
+            if (!list.includes(k)) list.push(k);
+          });
+          return list;
+        };
+
+        const extraKeys = pickExtraKeys(extraKey);
 
         receiver = plus.android.implements(
           "io.dcloud.feature.internal.reflect.BroadcastReceiver",
           {
             onReceive(context, intent) {
               plus.android.importClass(intent);
-              const code = intent.getStringExtra(extraKey);
+              let code = "";
+              for (let i = 0; i < extraKeys.length; i++) {
+                const k = extraKeys[i];
+                try {
+                  const v = intent.getStringExtra(k);
+                  if (v) {
+                    code = v;
+                    break;
+                  }
+                } catch (e) {}
+                try {
+                  const bytes = intent.getByteArrayExtra(k);
+                  if (bytes && bytes.length) {
+                    const JString = plus.android.importClass("java.lang.String");
+                    code = new JString(bytes);
+                    if (code) break;
+                  }
+                } catch (e) {}
+              }
+              if (!code) {
+                try {
+                  const ds = intent.getDataString();
+                  if (ds) code = ds;
+                } catch (e) {}
+              }
+              if (!code) {
+                try {
+                  const extras = intent.getExtras();
+                  if (extras) {
+                    plus.android.importClass(extras);
+                    const keySet = extras.keySet();
+                    if (keySet) {
+                      plus.android.importClass(keySet);
+                      const it = keySet.iterator();
+                      if (it) {
+                        plus.android.importClass(it);
+                        while (it.hasNext()) {
+                          const k = it.next();
+                          const ks = String(k);
+                          let v = "";
+                          try {
+                            v = extras.getString(ks);
+                          } catch (e) {}
+                          if (!v) {
+                            try {
+                              const any = extras.get(ks);
+                              if (any != null) v = String(any);
+                            } catch (e) {}
+                          }
+                          const text = (v == null ? "" : String(v))
+                            .replace(/\n/g, "")
+                            .trim();
+                          if (
+                            text &&
+                            text.length >= 3 &&
+                            text.length <= 300 &&
+                            /[0-9A-Za-z]/.test(text) &&
+                            !text.includes("android.") &&
+                            !text.includes("com.")
+                          ) {
+                            code = text;
+                            break;
+                          }
+                          if (
+                            !code &&
+                            text &&
+                            text.length >= 3 &&
+                            text.length <= 300 &&
+                            /[0-9A-Za-z]/.test(text)
+                          ) {
+                            code = text;
+                          }
+                        }
+                      }
+                    }
+                  }
+                } catch (e) {}
+              }
               _this.emitCode(code);
             },
           }
@@ -106,9 +288,15 @@
         try {
           mainActivity.registerReceiver(receiver, intentFilter);
           isRegistered = true;
-        } catch (e) {}
+        } catch (e) {
+          isRegistered = false;
+        }
       },
       stop() {
+        if (this._ensureTimer) {
+          clearInterval(this._ensureTimer);
+          this._ensureTimer = null;
+        }
         if (!this.canUseAndroidBroadcast()) return;
         if (!mainActivity || !receiver) return;
         if (!isRegistered) return;
diff --git a/src/pages/equipmentManagement/repair/add.vue b/src/pages/equipmentManagement/repair/add.vue
index 4e15bf3..8f31e6c 100644
--- a/src/pages/equipmentManagement/repair/add.vue
+++ b/src/pages/equipmentManagement/repair/add.vue
@@ -129,8 +129,8 @@
                         @confirm="onDateConfirm"
                         @cancel="showDate = false"
                         mode="date" />
-    <PdaScan :active="pdaScanActive"
-             eventName="scan_repair_device" />
+    <ScanWaitMask :show="scanMaskShow" :status="scanMaskStatus" />
+    <PdaScan />
   </view>
 </template>
 
@@ -139,6 +139,7 @@
   import { onShow, onLoad } from "@dcloudio/uni-app";
   import PageHeader from "@/components/PageHeader.vue";
   import CommonUpload from "@/components/CommonUpload.vue";
+  import ScanWaitMask from "@/components/ScanWaitMask.vue";
   import PdaScan from "@/components/pda-scan/pda-scan.vue";
   import { getDeviceLedger } from "@/api/equipmentManagement/ledger";
   import {
@@ -188,8 +189,50 @@
   // 鎵爜鐩稿叧鐘舵��
   const isScanning = ref(false);
   const scanTimer = ref(null);
-  const pdaScanActive = ref(false);
-  const pdaScanTimer = ref(null);
+  const pendingDeviceScan = ref(false);
+  let pendingDeviceScanTimer = null;
+  const scanMaskShow = ref(false);
+  const scanMaskStatus = ref("waiting");
+  const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
+
+  const canUsePdaBroadcast = () => {
+    try {
+      if (typeof plus === "undefined") return false;
+      if (plus?.os?.name !== "Android") return false;
+      if (!plus?.android) return false;
+
+      const sys = uni.getSystemInfoSync?.() || {};
+      const brand = String(sys?.brand || "").toUpperCase();
+      const model = String(sys?.model || "").toUpperCase();
+
+      return (
+        brand.includes("DROI") ||
+        model.includes("MV-IDP5204") ||
+        model.includes("IDP")
+      );
+    } catch (e) {
+      return false;
+    }
+  };
+
+  onShow(() => {
+    uni.$off("scan");
+    uni.$on("scan", data => {
+      console.log("onscan");
+      console.log("鎵爜缁撴灉锛�", data.code);
+      if (!pendingDeviceScan.value) return;
+      pendingDeviceScan.value = false;
+      scanMaskStatus.value = "done";
+      if (pendingDeviceScanTimer) {
+        clearTimeout(pendingDeviceScanTimer);
+        pendingDeviceScanTimer = null;
+      }
+      delay(350).then(() => {
+        scanMaskShow.value = false;
+        handleScanResult(data.code);
+      });
+    });
+  });
 
   // 琛ㄥ崟楠岃瘉瑙勫垯
   const formRules = {
@@ -296,62 +339,47 @@
 
   // 鎵弿浜岀淮鐮佸姛鑳�
   const startScan = () => {
-    if (isScanning.value) {
-      showToast("姝e湪鎵弿涓紝璇风◢鍊�...");
-      return;
+    pendingDeviceScan.value = true;
+    scanMaskStatus.value = "waiting";
+    scanMaskShow.value = true;
+    if (pendingDeviceScanTimer) {
+      clearTimeout(pendingDeviceScanTimer);
+      pendingDeviceScanTimer = null;
     }
-
-    const canUsePdaBroadcast = () => {
-      try {
-        if (typeof plus === "undefined") return false;
-        if (plus?.os?.name !== "Android") return false;
-        if (!plus?.android) return false;
-
-        const sys = uni.getSystemInfoSync?.() || {};
-        const brand = String(sys?.brand || "").toUpperCase();
-        const model = String(sys?.model || "").toUpperCase();
-
-        return (
-          brand.includes("DROI") ||
-          model.includes("MV-IDP5204") ||
-          model.includes("IDP")
-        );
-      } catch (e) {
-        return false;
-      }
-    };
-
-    if (canUsePdaBroadcast()) {
-      if (pdaScanTimer.value) {
-        clearTimeout(pdaScanTimer.value);
-        pdaScanTimer.value = null;
-      }
-      uni.$off("scan_repair_device");
-      uni.$on("scan_repair_device", data => {
-        pdaScanActive.value = false;
-        uni.$off("scan_repair_device");
-        if (pdaScanTimer.value) {
-          clearTimeout(pdaScanTimer.value);
-          pdaScanTimer.value = null;
-        }
-        handleScanResult(data?.code);
+    pendingDeviceScanTimer = setTimeout(() => {
+      pendingDeviceScan.value = false;
+      pendingDeviceScanTimer = null;
+      scanMaskStatus.value = "timeout";
+      delay(900).then(() => {
+        scanMaskShow.value = false;
       });
-      pdaScanActive.value = true;
-      uni.showToast({ title: "璇蜂娇鐢≒DA鎵爜", icon: "none" });
-      pdaScanTimer.value = setTimeout(() => {
-        pdaScanActive.value = false;
-        uni.$off("scan_repair_device");
-        pdaScanTimer.value = null;
-      }, 20000);
-      return;
-    }
+    }, 20000);
 
+    if (canUsePdaBroadcast()) return;
     uni.scanCode({
       scanType: ["qrCode", "barCode"],
       success: res => {
-        handleScanResult(res.result);
+        pendingDeviceScan.value = false;
+        scanMaskStatus.value = "done";
+        if (pendingDeviceScanTimer) {
+          clearTimeout(pendingDeviceScanTimer);
+          pendingDeviceScanTimer = null;
+        }
+        delay(350).then(() => {
+          scanMaskShow.value = false;
+          handleScanResult(res.result);
+        });
       },
       fail: err => {
+        pendingDeviceScan.value = false;
+        scanMaskStatus.value = "timeout";
+        delay(900).then(() => {
+          scanMaskShow.value = false;
+        });
+        if (pendingDeviceScanTimer) {
+          clearTimeout(pendingDeviceScanTimer);
+          pendingDeviceScanTimer = null;
+        }
         console.error("鎵爜澶辫触:", err);
         showToast("鎵爜澶辫触锛岃閲嶈瘯");
       },
@@ -423,10 +451,6 @@
     showDate.value = false;
   };
 
-  onShow(() => {
-    // 椤甸潰鏄剧ず鏃堕�昏緫
-  });
-
   onMounted(() => {
     // 椤甸潰鍔犺浇鏃惰幏鍙栬澶囧垪琛�
     loadDeviceName();
@@ -437,10 +461,12 @@
     if (scanTimer.value) {
       clearTimeout(scanTimer.value);
     }
-    if (pdaScanTimer.value) {
-      clearTimeout(pdaScanTimer.value);
+    if (pendingDeviceScanTimer) {
+      clearTimeout(pendingDeviceScanTimer);
+      pendingDeviceScanTimer = null;
     }
-    uni.$off("scan_repair_device");
+    scanMaskShow.value = false;
+    uni.$off("scan");
   });
 
   // 鎻愪氦琛ㄥ崟
diff --git a/src/pages/equipmentManagement/upkeep/add.vue b/src/pages/equipmentManagement/upkeep/add.vue
index 457b265..a42b362 100644
--- a/src/pages/equipmentManagement/upkeep/add.vue
+++ b/src/pages/equipmentManagement/upkeep/add.vue
@@ -85,8 +85,9 @@
                         @confirm="onDateConfirm"
                         @cancel="showDate = false"
                         mode="date" />
-    <PdaScan :active="pdaScanActive"
-             eventName="scan_upkeep_device" />
+    <ScanWaitMask :show="scanMaskShow"
+                  :status="scanMaskStatus" />
+    <PdaScan />
   </view>
 </template>
 
@@ -95,6 +96,7 @@
   import { onShow } from "@dcloudio/uni-app";
   import PageHeader from "@/components/PageHeader.vue";
   import CommonUpload from "@/components/CommonUpload.vue";
+  import ScanWaitMask from "@/components/ScanWaitMask.vue";
   import PdaScan from "@/components/pda-scan/pda-scan.vue";
   import { getDeviceLedger } from "@/api/equipmentManagement/ledger";
   import {
@@ -143,8 +145,51 @@
   // 鎵爜鐩稿叧鐘舵��
   const isScanning = ref(false);
   const scanTimer = ref(null);
-  const pdaScanActive = ref(false);
-  const pdaScanTimer = ref(null);
+  const pendingDeviceScan = ref(false);
+  let pendingDeviceScanTimer = null;
+  const scanMaskShow = ref(false);
+  const scanMaskStatus = ref("waiting");
+  const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
+
+  const canUsePdaBroadcast = () => {
+    try {
+      if (typeof plus === "undefined") return false;
+      if (plus?.os?.name !== "Android") return false;
+      if (!plus?.android) return false;
+
+      const sys = uni.getSystemInfoSync?.() || {};
+      const brand = String(sys?.brand || "").toUpperCase();
+      const model = String(sys?.model || "").toUpperCase();
+
+      return (
+        brand.includes("DROI") ||
+        model.includes("MV-IDP5204") ||
+        model.includes("IDP")
+      );
+    } catch (e) {
+      return false;
+    }
+  };
+
+  onShow(() => {
+    uni.$off("scan");
+    uni.$on("scan", data => {
+      console.log("onscan");
+      console.log("鎵爜缁撴灉锛�", data.code);
+      if (!pendingDeviceScan.value) return;
+      pendingDeviceScan.value = false;
+      scanMaskStatus.value = "done";
+      if (pendingDeviceScanTimer) {
+        clearTimeout(pendingDeviceScanTimer);
+        pendingDeviceScanTimer = null;
+      }
+      delay(350).then(() => {
+        scanMaskShow.value = false;
+        processScanResult(data.code);
+      });
+    });
+    getPageParams();
+  });
 
   // 琛ㄥ崟楠岃瘉瑙勫垯
   const formRules = {
@@ -210,62 +255,47 @@
 
   // 鎵弿浜岀淮鐮佸姛鑳�
   const startScan = () => {
-    if (isScanning.value) {
-      showToast("姝e湪鎵弿涓紝璇风◢鍊�...");
-      return;
+    pendingDeviceScan.value = true;
+    scanMaskStatus.value = "waiting";
+    scanMaskShow.value = true;
+    if (pendingDeviceScanTimer) {
+      clearTimeout(pendingDeviceScanTimer);
+      pendingDeviceScanTimer = null;
     }
-
-    const canUsePdaBroadcast = () => {
-      try {
-        if (typeof plus === "undefined") return false;
-        if (plus?.os?.name !== "Android") return false;
-        if (!plus?.android) return false;
-
-        const sys = uni.getSystemInfoSync?.() || {};
-        const brand = String(sys?.brand || "").toUpperCase();
-        const model = String(sys?.model || "").toUpperCase();
-
-        return (
-          brand.includes("DROI") ||
-          model.includes("MV-IDP5204") ||
-          model.includes("IDP")
-        );
-      } catch (e) {
-        return false;
-      }
-    };
-
-    if (canUsePdaBroadcast()) {
-      if (pdaScanTimer.value) {
-        clearTimeout(pdaScanTimer.value);
-        pdaScanTimer.value = null;
-      }
-      uni.$off("scan_upkeep_device");
-      uni.$on("scan_upkeep_device", data => {
-        pdaScanActive.value = false;
-        uni.$off("scan_upkeep_device");
-        if (pdaScanTimer.value) {
-          clearTimeout(pdaScanTimer.value);
-          pdaScanTimer.value = null;
-        }
-        handleScanResult(data?.code);
+    pendingDeviceScanTimer = setTimeout(() => {
+      pendingDeviceScan.value = false;
+      pendingDeviceScanTimer = null;
+      scanMaskStatus.value = "timeout";
+      delay(900).then(() => {
+        scanMaskShow.value = false;
       });
-      pdaScanActive.value = true;
-      uni.showToast({ title: "璇蜂娇鐢≒DA鎵爜", icon: "none" });
-      pdaScanTimer.value = setTimeout(() => {
-        pdaScanActive.value = false;
-        uni.$off("scan_upkeep_device");
-        pdaScanTimer.value = null;
-      }, 20000);
-      return;
-    }
+    }, 20000);
 
+    if (canUsePdaBroadcast()) return;
     uni.scanCode({
       scanType: ["qrCode", "barCode"],
       success: res => {
-        handleScanResult(res.result);
+        pendingDeviceScan.value = false;
+        scanMaskStatus.value = "done";
+        if (pendingDeviceScanTimer) {
+          clearTimeout(pendingDeviceScanTimer);
+          pendingDeviceScanTimer = null;
+        }
+        delay(350).then(() => {
+          scanMaskShow.value = false;
+          handleScanResult(res.result);
+        });
       },
       fail: err => {
+        pendingDeviceScan.value = false;
+        scanMaskStatus.value = "timeout";
+        delay(900).then(() => {
+          scanMaskShow.value = false;
+        });
+        if (pendingDeviceScanTimer) {
+          clearTimeout(pendingDeviceScanTimer);
+          pendingDeviceScanTimer = null;
+        }
         console.error("鎵爜澶辫触:", err);
         showToast("鎵爜澶辫触锛岃閲嶈瘯");
       },
@@ -342,11 +372,6 @@
     showDate.value = false;
   };
 
-  onShow(() => {
-    // 椤甸潰鏄剧ず鏃惰幏鍙栧弬鏁�
-    getPageParams();
-  });
-
   onMounted(() => {
     // 椤甸潰鍔犺浇鏃惰幏鍙栬澶囧垪琛ㄥ拰鍙傛暟
     loadDeviceName();
@@ -358,10 +383,12 @@
     if (scanTimer.value) {
       clearTimeout(scanTimer.value);
     }
-    if (pdaScanTimer.value) {
-      clearTimeout(pdaScanTimer.value);
+    if (pendingDeviceScanTimer) {
+      clearTimeout(pendingDeviceScanTimer);
+      pendingDeviceScanTimer = null;
     }
-    uni.$off("scan_upkeep_device");
+    scanMaskShow.value = false;
+    uni.$off("scan");
   });
 
   // 鎻愪氦琛ㄥ崟
diff --git a/src/pages/inspectionUpload/upload.vue b/src/pages/inspectionUpload/upload.vue
index 785601e..8bceb63 100644
--- a/src/pages/inspectionUpload/upload.vue
+++ b/src/pages/inspectionUpload/upload.vue
@@ -65,12 +65,9 @@
         <PdaMediaUpload v-model="beforeModelValue"
                         :action="uploadFileUrl"
                         :limit="uploadConfig.limit"
-                        :fileSize="uploadConfig.fileSize"
+                        :uploadType="10"
                         :formData="{ type: 10 }"
-                        :allowCamera="true"
-                        :allowVideo="true"
                         @update:modelValue="handleFilesUpdate"
-                        @choose-media="handleChooseMedia"
                         @uploading="uploading = $event"
                         @progress="uploadProgress = $event" />
         <!-- 缁熻淇℃伅 -->
@@ -107,7 +104,7 @@
 
 <script setup>
   import { ref, computed, onMounted } from "vue";
-  import { onLoad, onShow, onHide } from "@dcloudio/uni-app";
+  import { onLoad } from "@dcloudio/uni-app";
   import PageHeader from "@/components/PageHeader.vue";
   import PdaMediaUpload from "@/components/pda-media-upload/pda-media-upload.vue";
   import { uploadInspectionTask } from "@/api/inspectionManagement";
@@ -526,40 +523,14 @@
       },
     });
 
-    // 鐩戝惉涓婁紶杩涘害
     uploadTask.onProgressUpdate(res => {
       uploadProgress.value = res.progress;
     });
   };
 
-  // 鐩戝惉鏂囦欢鍒楄〃鍙樺寲锛堢粍浠跺唴閮ㄥ鐞嗗垹闄わ紝鐖剁粍浠跺彧鍚屾锛�
   const handleFilesUpdate = files => {
     beforeModelValue.value = files;
   };
-
-  // 鐩戝惉缁勪欢鐨� choose-media 浜嬩欢锛堢敤浜庡吋瀹规棫閫昏緫锛屾垨鑰呭湪杩欓噷娣诲姞鑷畾涔夋搷浣滐級
-  const handleChooseMedia = type => {
-    // 鍙互鍦ㄨ繖閲屾坊鍔犺嚜瀹氫箟鐨勫墠缃搷浣�
-    console.log("鐢ㄦ埛閫夋嫨涓婁紶绫诲瀷:", type);
-  };
-
-  // PDA 鎵爜鐩戝惉锛堝彲閫夛細濡傛灉闇�瑕侀�氳繃鎵爜娣诲姞鏌愪釜鏍囩鎴栦俊鎭紝鍦ㄨ繖閲屽鐞嗭級
-  const handlePdaScan = data => {
-    console.log("PDA 鎵爜缁撴灉:", data);
-    uni.showToast({
-      title: `鎵爜缁撴灉: ${data.code}`,
-      icon: "none",
-    });
-  };
-
-  onShow(() => {
-    // 椤甸潰鏄剧ず鏃讹紝鐩戝惉 PDA 鎵爜锛堝鏋滄湁闇�瑕佺殑璇濓級
-    uni.$on("scan_inspection", handlePdaScan);
-  });
-
-  onHide(() => {
-    uni.$off("scan_inspection");
-  });
 </script>
 
 <style scoped>
diff --git a/src/pages/works.vue b/src/pages/works.vue
index d3c5d17..7a53a4f 100644
--- a/src/pages/works.vue
+++ b/src/pages/works.vue
@@ -299,17 +299,20 @@
         </up-grid>
       </view>
     </view>
-    <PdaScan :active="pdaScanActive"
-             eventName="scan_work_report" />
+    <ScanWaitMask :show="scanMaskShow"
+                  :status="scanMaskStatus" />
+    <PdaScan />
     <DownloadProgressMask />
   </view>
 </template>
 
 <script setup>
   import { ref, onMounted, nextTick, reactive, computed } from "vue";
+  import { onShow } from "@dcloudio/uni-app";
   import { userLoginFacotryList } from "@/api/login";
   import { getProductWorkOrderById } from "@/api/productionManagement/productionReporting";
   import DownloadProgressMask from "@/components/DownloadProgressMask.vue";
+  import ScanWaitMask from "@/components/ScanWaitMask.vue";
   import PdaScan from "@/components/pda-scan/pda-scan.vue";
   import modal from "@/plugins/modal";
   import useUserStore from "@/store/modules/user";
@@ -318,8 +321,11 @@
   const show = ref(false);
   const factoryList = ref([]);
   const factoryListTem = ref([]);
-  const pdaScanActive = ref(false);
+  const pendingWorkReportScan = ref(false);
   let scanWorkReportTimer = null;
+  const scanMaskShow = ref(false);
+  const scanMaskStatus = ref("waiting");
+  const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
   const iconStyle = {
     fontSize: "1.125rem",
     color: "#2979ff",
@@ -1076,124 +1082,153 @@
         factoryList.value = [];
       });
   }
-  const getcode = async () => {
-    const canUsePdaBroadcast = () => {
+
+  const canUsePdaBroadcast = () => {
+    try {
+      if (typeof plus === "undefined") return false;
+      if (plus?.os?.name !== "Android") return false;
+      if (!plus?.android) return false;
+
+      const sys = uni.getSystemInfoSync?.() || {};
+      const brand = String(sys?.brand || "").toUpperCase();
+      const model = String(sys?.model || "").toUpperCase();
+
+      return (
+        brand.includes("DROI") ||
+        model.includes("MV-IDP5204") ||
+        model.includes("IDP")
+      );
+    } catch (e) {
+      return false;
+    }
+  };
+
+  const handleWorkReportScan = async scanResultRaw => {
+    const scanResult = scanResultRaw == null ? "" : String(scanResultRaw);
+    let orderRow = "";
+
+    const isNumericId = /^\d+$/.test(scanResult.trim());
+
+    if (isNumericId) {
+      const workOrderId = scanResult.trim();
+      modal.loading("姝e湪鑾峰彇宸ュ崟淇℃伅...");
       try {
-        if (typeof plus === "undefined") return false;
-        if (plus?.os?.name !== "Android") return false;
-        if (!plus?.android) return false;
+        const workRes = await getProductWorkOrderById({ id: workOrderId });
+        modal.closeLoading();
 
-        const sys = uni.getSystemInfoSync?.() || {};
-        const brand = String(sys?.brand || "").toUpperCase();
-        const model = String(sys?.model || "").toUpperCase();
+        console.log("宸ュ崟鏌ヨ缁撴灉:", workRes);
 
-        return (
-          brand.includes("DROI") ||
-          model.includes("MV-IDP5204") ||
-          model.includes("IDP")
-        );
-      } catch (e) {
-        return false;
-      }
-    };
+        if (workRes.code === 200 && workRes.data) {
+          const workData = workRes.data;
+          console.log("宸ュ崟鏁版嵁:", workData);
 
-    const handleWorkReportScan = async scanResultRaw => {
-      const scanResult = scanResultRaw == null ? "" : String(scanResultRaw);
-      let orderRow = "";
-
-      const isNumericId = /^\d+$/.test(scanResult.trim());
-
-      if (isNumericId) {
-        const workOrderId = scanResult.trim();
-        modal.loading("姝e湪鑾峰彇宸ュ崟淇℃伅...");
-        try {
-          const workRes = await getProductWorkOrderById({ id: workOrderId });
-          modal.closeLoading();
-
-          console.log("宸ュ崟鏌ヨ缁撴灉:", workRes);
-
-          if (workRes.code === 200 && workRes.data) {
-            const workData = workRes.data;
-            console.log("宸ュ崟鏁版嵁:", workData);
-
-            if (workData.endOrder === true) {
-              modal.msgError("璇ヨ鍗曞凡缁撴潫锛屾棤娉曟姤宸�");
-              return;
-            }
-
-            orderRow = JSON.stringify(workData);
-
-            console.log("鏋勯�犵殑orderRow:", orderRow);
-          } else {
-            modal.msgError("鏈壘鍒板搴旂殑宸ュ崟淇℃伅");
+          if (workData.endOrder === true) {
+            modal.msgError("璇ヨ鍗曞凡缁撴潫锛屾棤娉曟姤宸�");
             return;
           }
-        } catch (error) {
-          modal.closeLoading();
-          console.error("鑾峰彇宸ュ崟淇℃伅澶辫触:", error);
-          modal.msgError("鑾峰彇宸ュ崟淇℃伅澶辫触: " + (error.message || "鏈煡閿欒"));
-          return;
-        }
-      } else {
-        try {
-          const orderRowStart = scanResult.indexOf("orderRow={");
-          if (orderRowStart !== -1) {
-            const jsonPart = scanResult.substring(orderRowStart + 9);
-            orderRow = jsonPart;
-          } else {
-            orderRow = scanResult;
-          }
-        } catch (e) {
-          console.error(e, "瑙f瀽澶辫触====????=====");
-          orderRow = "";
-        }
 
-        try {
-          JSON.parse(orderRow);
-        } catch (error) {
-          modal.msgError("璁㈠崟瑙f瀽澶辫触锛岃妫�鏌ヤ簩缁寸爜鏍煎紡");
+          orderRow = JSON.stringify(workData);
+
+          console.log("鏋勯�犵殑orderRow:", orderRow);
+        } else {
+          modal.msgError("鏈壘鍒板搴旂殑宸ュ崟淇℃伅");
           return;
         }
+      } catch (error) {
+        modal.closeLoading();
+        console.error("鑾峰彇宸ュ崟淇℃伅澶辫触:", error);
+        modal.msgError("鑾峰彇宸ュ崟淇℃伅澶辫触: " + (error.message || "鏈煡閿欒"));
+        return;
+      }
+    } else {
+      try {
+        const orderRowStart = scanResult.indexOf("orderRow={");
+        if (orderRowStart !== -1) {
+          const jsonPart = scanResult.substring(orderRowStart + 9);
+          orderRow = jsonPart;
+        } else {
+          orderRow = scanResult;
+        }
+      } catch (e) {
+        console.error(e, "瑙f瀽澶辫触====????=====");
+        orderRow = "";
       }
 
-      uni.navigateTo({
-        url: `/pages/productionManagement/productionReport/index?orderRow=${orderRow}`,
-      });
-    };
+      try {
+        JSON.parse(orderRow);
+      } catch (error) {
+        modal.msgError("璁㈠崟瑙f瀽澶辫触锛岃妫�鏌ヤ簩缁寸爜鏍煎紡");
+        return;
+      }
+    }
 
-    if (canUsePdaBroadcast()) {
+    uni.navigateTo({
+      url: `/pages/productionManagement/productionReport/index?orderRow=${orderRow}`,
+    });
+  };
+
+  onShow(() => {
+    uni.$off("scan");
+    uni.$on("scan", async data => {
+      console.log("onscan");
+      console.log("鎵爜缁撴灉锛�", data.code);
+      if (!pendingWorkReportScan.value) return;
+
+      pendingWorkReportScan.value = false;
+      scanMaskStatus.value = "done";
       if (scanWorkReportTimer) {
         clearTimeout(scanWorkReportTimer);
         scanWorkReportTimer = null;
       }
-      uni.$off("scan_work_report");
-      uni.$on("scan_work_report", async data => {
-        pdaScanActive.value = false;
-        uni.$off("scan_work_report");
+      await delay(350);
+      scanMaskShow.value = false;
+      await handleWorkReportScan(data?.code);
+    });
+  });
+
+  const getcode = async () => {
+    pendingWorkReportScan.value = true;
+    scanMaskStatus.value = "waiting";
+    scanMaskShow.value = true;
+
+    if (scanWorkReportTimer) {
+      clearTimeout(scanWorkReportTimer);
+      scanWorkReportTimer = null;
+    }
+
+    scanWorkReportTimer = setTimeout(() => {
+      pendingWorkReportScan.value = false;
+      scanWorkReportTimer = null;
+      scanMaskStatus.value = "timeout";
+      delay(900).then(() => {
+        scanMaskShow.value = false;
+      });
+    }, 20000);
+
+    if (canUsePdaBroadcast()) return;
+
+    uni.scanCode({
+      success: async res => {
+        pendingWorkReportScan.value = false;
+        scanMaskStatus.value = "done";
         if (scanWorkReportTimer) {
           clearTimeout(scanWorkReportTimer);
           scanWorkReportTimer = null;
         }
-        await handleWorkReportScan(data?.code);
-      });
-      pdaScanActive.value = true;
-      uni.showToast({
-        title: "璇蜂娇鐢≒DA鎵爜",
-        icon: "none",
-      });
-      scanWorkReportTimer = setTimeout(() => {
-        pdaScanActive.value = false;
-        uni.$off("scan_work_report");
-        scanWorkReportTimer = null;
-      }, 20000);
-      return;
-    }
-
-    uni.scanCode({
-      success: async res => {
+        await delay(350);
+        scanMaskShow.value = false;
         await handleWorkReportScan(res.result);
       },
       fail: err => {
+        pendingWorkReportScan.value = false;
+        scanMaskStatus.value = "timeout";
+        delay(900).then(() => {
+          scanMaskShow.value = false;
+        });
+        if (scanWorkReportTimer) {
+          clearTimeout(scanWorkReportTimer);
+          scanWorkReportTimer = null;
+        }
         uni.showToast({
           title: "鎵爜澶辫触",
           icon: "none",

--
Gitblit v1.9.3