From 6e763136fdf4469143ebbae0b717eb8e9b0ca954 Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期一, 03 十一月 2025 17:32:35 +0800
Subject: [PATCH] fix: 完成巡查

---
 src/pages/routingInspection/upload.vue             |  158 ++++++-
 src/pages/routingInspection/index.vue              |  107 ++--
 src/pages/routingInspection/product_card/index.vue |   55 --
 src/utils/request.ts                               |    3 
 src/api/routingInspection/routingInspection.ts     |    8 
 src/pages/routingInspection/detail/indexJX.vue     |  239 ++++++++--
 src/pages/routingInspection/list/index.vue         |  212 +++++----
 src/composables/useScanCode.ts                     |  249 +++++++++++
 src/App.vue                                        |   59 ++
 src/pages/routingInspection/detail/indexLS.vue     |  199 ++++++--
 10 files changed, 966 insertions(+), 323 deletions(-)

diff --git a/src/App.vue b/src/App.vue
index 220abd9..e1a44ed 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,22 +1,81 @@
 <script setup lang="ts">
 import { onLaunch, onShow, onHide } from "@dcloudio/uni-app";
 import { useThemeStore } from "@/store";
+import { ref } from "vue";
 
 // 涓婚鍒濆鍖�
 const themeStore = useThemeStore();
+
+// 鍏ㄥ眬鎵爜骞挎挱鎺ユ敹鍣�
+let main: any = null;
+let receiver: any = null;
+let filter: any = null;
+
+// 鍒濆鍖栨壂鐮佸箍鎾帴鏀�
+const initGlobalScan = () => {
+  // #ifdef APP-PLUS
+  try {
+    main = plus.android.runtimeMainActivity();
+    const IntentFilter = plus.android.importClass("android.content.IntentFilter");
+    filter = new IntentFilter();
+    filter.addAction("com.dwexample.ACTION");
+    
+    receiver = plus.android.implements("io.dcloud.feature.internal.reflect.BroadcastReceiver", {
+      onReceive: (context: any, intent: any) => {
+        console.log("馃攳 [鍏ㄥ眬Scan] onReceive 瑙﹀彂:", context, intent);
+        plus.android.importClass(intent);
+        const scanResult = intent.getStringExtra("com.motorolasolutions.emdk.datawedge.data_string");
+        console.log("馃攳 [鍏ㄥ眬Scan] 鎵弿缁撴灉:", scanResult);
+        
+        // 鍙戦�佸埌鎵�鏈夊彲鑳界殑浜嬩欢
+        const eventNames = ["scan", "scanIndex", "scanJX", "scanLS"];
+        eventNames.forEach((eventName) => {
+          uni.$emit(eventName, { code: scanResult });
+          console.log(`馃攳 [鍏ㄥ眬Scan] 宸插彂閫� ${eventName} 浜嬩欢`);
+        });
+      },
+    });
+    
+    // 娉ㄥ唽骞挎挱鎺ユ敹鍣�
+    main.registerReceiver(receiver, filter);
+    console.log("馃攳 [鍏ㄥ眬Scan] 鍏ㄥ眬鎵爜骞挎挱鎺ユ敹鍣ㄥ凡鍚姩");
+  } catch (error) {
+    console.error("馃攳 [鍏ㄥ眬Scan] 鍒濆鍖栧け璐�:", error);
+  }
+  // #endif
+};
+
+// 鍋滄鎵爜骞挎挱鎺ユ敹
+const stopGlobalScan = () => {
+  // #ifdef APP-PLUS
+  try {
+    if (main && receiver) {
+      main.unregisterReceiver(receiver);
+      console.log("馃攳 [鍏ㄥ眬Scan] 鍏ㄥ眬鎵爜骞挎挱鎺ユ敹鍣ㄥ凡鍋滄");
+    }
+  } catch (error) {
+    console.error("馃攳 [鍏ㄥ眬Scan] 鍋滄澶辫触:", error);
+  }
+  // #endif
+};
 
 onLaunch(() => {
   console.log("App Launch");
   // 鍒濆鍖栦富棰�
   themeStore.initTheme();
+  // 鍒濆鍖栧叏灞�鎵爜骞挎挱鎺ユ敹鍣�
+  initGlobalScan();
 });
 
 onShow(() => {
   console.log("App Show");
+  // 搴旂敤鏄剧ず鏃堕噸鏂板惎鍔ㄥ箍鎾帴鏀跺櫒
+  initGlobalScan();
 });
 
 onHide(() => {
   console.log("App Hide");
+  // 搴旂敤闅愯棌鏃朵笉鍋滄骞挎挱锛堜繚鎸佸悗鍙版帴鏀讹級
 });
 </script>
 
diff --git a/src/api/routingInspection/routingInspection.ts b/src/api/routingInspection/routingInspection.ts
index 440808e..1e2488a 100644
--- a/src/api/routingInspection/routingInspection.ts
+++ b/src/api/routingInspection/routingInspection.ts
@@ -50,6 +50,14 @@
       data: data,
     });
   },
+
+  // 楠岃瘉浜岀淮鐮�
+  assertScanQR(params: { deviceUid: string }) {
+    return request<BaseResult<any>>({
+      url: "/wireInspection/assertScanQR?deviceUid=" + params.deviceUid,
+      method: "GET",
+    });
+  },
 };
 
 export default RoutingInspectionApi;
diff --git a/src/composables/useScanCode.ts b/src/composables/useScanCode.ts
new file mode 100644
index 0000000..ade564f
--- /dev/null
+++ b/src/composables/useScanCode.ts
@@ -0,0 +1,249 @@
+import { ref, computed, onUnmounted } from "vue";
+import { onShow, onHide } from "@dcloudio/uni-app";
+import RoutingInspectionApi from "@/api/routingInspection/routingInspection";
+
+/**
+ * 鎵爜鏁版嵁鎺ュ彛
+ */
+interface ScanCodeData {
+  uid?: string;
+  deviceModel?: string;
+  [key: string]: any;
+}
+
+// 鍏ㄥ眬鐩戝惉鍣ㄧ姸鎬佹槧灏勶紙纭繚姣忎釜浜嬩欢鍚嶅彧鏈変竴涓洃鍚櫒锛�
+const globalListeners = new Map<string, boolean>();
+
+// 娣诲姞涓�涓叏灞�鐨勬崟鑾锋墍鏈夋壂鐮佷簨浠剁殑鐩戝惉鍣紙鐢ㄤ簬璋冭瘯锛�
+let debugListenerInitialized = false;
+
+const initDebugListener = () => {
+  if (debugListenerInitialized) return;
+  
+  // 鐩戝惉鎵�鏈夊彲鑳界殑鎵爜浜嬩欢
+  const eventNames = ["scan", "scanIndex", "scanJX", "scanLS"];
+  eventNames.forEach((eventName) => {
+    uni.$on(eventName, (data: any) => {
+      console.log(`馃攳 [鍏ㄥ眬璋冭瘯] 鎹曡幏鍒� ${eventName} 浜嬩欢:`, data);
+    });
+  });
+  
+  debugListenerInitialized = true;
+  console.log("馃攳 [鍏ㄥ眬璋冭瘯] 璋冭瘯鐩戝惉鍣ㄥ凡鍒濆鍖�");
+};
+
+/**
+ * 鎵爜绠$悊 Composable
+ * 缁熶竴绠$悊鎵爜浜嬩欢鐩戝惉銆佺紦瀛樺瓨鍌ㄥ拰鏁版嵁璇诲彇
+ * 鍏ㄥ眬鐩戝惉鍣紝涓嶉殢椤甸潰鍒囨崲鑰屽叧闂�
+ * @param eventName 鐩戝惉鐨勪簨浠跺悕绉帮紝榛樿涓� "scan"
+ */
+export function useScanCode(eventName: string = "scan") {
+  // 褰撳墠鎵爜鐨勮澶� UID
+  const deviceUid = ref<string>("");
+  // 褰撳墠鎵爜鐨勬満鍙板瀷鍙�
+  const deviceModel = ref<string>("");
+  // 瀹屾暣鐨勬壂鐮佹暟鎹�
+  const scanData = ref<ScanCodeData>({});
+  // 淇濆瓨浜嬩欢鍚嶇О
+  const currentEventName = eventName;
+
+  /**
+   * 浠庢湰鍦扮紦瀛樺姞杞芥壂鐮佹暟鎹�
+   */
+  const loadFromCache = () => {
+    try {
+      const cachedData = uni.getStorageSync("scanCodeData");
+      if (cachedData) {
+        scanData.value = cachedData;
+        deviceUid.value = cachedData.uid || "";
+        deviceModel.value = cachedData.deviceModel || "";
+        console.log("[useScanCode] 浠庣紦瀛樺姞杞芥壂鐮佹暟鎹�:", cachedData);
+        return cachedData;
+      }
+    } catch (error) {
+      console.error("[useScanCode] 璇诲彇缂撳瓨澶辫触:", error);
+    }
+    return null;
+  };
+
+  /**
+   * 淇濆瓨鎵爜鏁版嵁鍒扮紦瀛�
+   */
+  const saveToCache = (data: ScanCodeData) => {
+    try {
+      uni.setStorageSync("scanCodeData", data);
+      console.log("[useScanCode] 宸蹭繚瀛樺埌缂撳瓨:", data);
+      return true;
+    } catch (error) {
+      console.error("[useScanCode] 淇濆瓨缂撳瓨澶辫触:", error);
+      return false;
+    }
+  };
+
+  /**
+   * 娓呯┖鎵爜鏁版嵁鍜岀紦瀛�
+   */
+  const clearScanData = () => {
+    try {
+      uni.removeStorageSync("scanCodeData");
+      deviceUid.value = "";
+      deviceModel.value = "";
+      scanData.value = {};
+      console.log("[useScanCode] 宸叉竻绌烘壂鐮佹暟鎹�");
+    } catch (error) {
+      console.error("[useScanCode] 娓呯┖缂撳瓨澶辫触:", error);
+    }
+  };
+
+  /**
+   * 楠岃瘉浜岀淮鐮侊紙浠呰皟鐢ㄦ帴鍙o紝涓嶅鐞嗚繑鍥炵粨鏋滐級
+   */
+  const validateQRCode = async (uid: string): Promise<void> => {
+    try {
+      console.log("[useScanCode] 璋冪敤楠岃瘉浜岀淮鐮佹帴鍙�, deviceUid:", uid);
+      await RoutingInspectionApi.assertScanQR({ deviceUid: uid });
+      console.log("[useScanCode] 楠岃瘉鎺ュ彛璋冪敤瀹屾垚");
+    } catch (error: any) {
+      console.error("[useScanCode] 楠岃瘉鎺ュ彛璋冪敤寮傚父:", error);
+      // 鍗充娇寮傚父涔熶笉褰卞搷鍚庣画娴佺▼
+    }
+  };
+
+  /**
+   * 澶勭悊鎵爜浜嬩欢
+   */
+  const handleScanEvent = async (params: any) => {
+    console.log(`========== [useScanCode][${currentEventName}] 鏀跺埌鎵爜浜嬩欢 ==========`);
+    console.log(`[useScanCode][${currentEventName}] 鎺ユ敹鍙傛暟:`, params);
+    console.log(`[useScanCode][${currentEventName}] 瑙﹀彂鏃堕棿:`, new Date().toLocaleTimeString());
+
+    try {
+      if (!params?.code) {
+        console.warn("[useScanCode] 鎵爜鍐呭涓虹┖");
+        return;
+      }
+
+      let codeObj: ScanCodeData = {};
+      try {
+        codeObj = JSON.parse(params.code);
+        console.log("[useScanCode] 瑙f瀽鍚庣殑瀵硅薄:", codeObj);
+      } catch (err) {
+        console.error("[useScanCode] JSON 瑙f瀽澶辫触:", err);
+        console.log("[useScanCode] 鍘熷瀛楃涓�:", params.code);
+        // 濡傛灉涓嶆槸 JSON锛屽皾璇曚綔涓烘櫘閫氬瓧绗︿覆澶勭悊
+        codeObj = { code: params.code };
+      }
+
+      // 妫�鏌ユ槸鍚︽湁蹇呰鐨勫瓧娈碉紙uid 鎴� deviceModel锛�
+      if (!codeObj.uid && !codeObj.deviceModel) {
+        console.warn("[useScanCode] 鎵爜鏁版嵁缂哄皯 uid 鍜� deviceModel锛屼笉淇濆瓨缂撳瓨");
+        uni.showToast({
+          title: "鎵爜鏁版嵁鏃犳晥",
+          icon: "none",
+        });
+        return;
+      }
+
+      // 鏇存柊鏈湴鐘舵��
+      scanData.value = codeObj;
+      deviceUid.value = codeObj.uid || "";
+      deviceModel.value = codeObj.deviceModel || "";
+
+      // 淇濆瓨鍒扮紦瀛�
+      saveToCache(codeObj);
+
+      // 濡傛灉鏈� uid锛岃皟鐢ㄩ獙璇佹帴鍙o紙涓嶇瓑寰呯粨鏋滐級
+      if (codeObj.uid) {
+        validateQRCode(codeObj.uid);
+      }
+
+      // 鏄剧ず鎴愬姛鎻愮ず
+      uni.showToast({
+        title: "鎵爜鎴愬姛",
+        icon: "success",
+      });
+
+      console.log("[useScanCode] 鎵爜鏁版嵁宸叉洿鏂�:", {
+        uid: deviceUid.value,
+        deviceModel: deviceModel.value,
+      });
+    } catch (error) {
+      console.error("[useScanCode] 澶勭悊鎵爜鏁版嵁寮傚父:", error);
+    }
+  };
+
+  /**
+   * 鍚敤鎵爜鐩戝惉锛堝叏灞�锛屾瘡娆¢兘閲嶆柊娉ㄥ唽浠ョ‘淇濇湁鏁堬級
+   */
+  const enableListener = () => {
+    // 鍏堢Щ闄ゅ彲鑳藉瓨鍦ㄧ殑鏃х洃鍚櫒
+    uni.$off(currentEventName, handleScanEvent);
+    // 娣诲姞鏂扮殑鐩戝惉鍣�
+    uni.$on(currentEventName, handleScanEvent);
+    // 鏍囪涓哄叏灞�宸插惎鐢�
+    globalListeners.set(currentEventName, true);
+    console.log(
+      `[useScanCode][${currentEventName}] 鉁� 鍏ㄥ眬鐩戝惉鍣ㄥ凡鍚敤/鍒锋柊锛堜笉浼氶殢椤甸潰鍒囨崲鍏抽棴锛塦
+    );
+  };
+
+  /**
+   * 绂佺敤鎵爜鐩戝惉锛堜粎鐢ㄤ簬搴旂敤閫�鍑烘椂娓呯悊锛屾甯搁〉闈㈠垏鎹笉璋冪敤锛�
+   */
+  const disableListener = () => {
+    if (!globalListeners.get(currentEventName)) {
+      console.log(`[useScanCode][${currentEventName}] 鐩戝惉鍣ㄦ湭鍚敤锛岃烦杩嘸);
+      return;
+    }
+
+    uni.$off(currentEventName, handleScanEvent);
+    globalListeners.delete(currentEventName);
+    console.log(`[useScanCode][${currentEventName}] 鉂� 鍏ㄥ眬鐩戝惉鍣ㄥ凡绂佺敤`);
+  };
+
+  /**
+   * 璁剧疆椤甸潰鐢熷懡鍛ㄦ湡閽╁瓙锛堝叏灞�鐩戝惉鍣ㄦā寮忥級
+   * 鐩戝惉鍣ㄥ叏灞�鍚敤涓�娆★紝涓嶉殢椤甸潰鍒囨崲鍏抽棴
+   * @param options 閰嶇疆閫夐」
+   */
+  const setupLifecycle = (
+    options: {
+      loadCacheOnShow?: boolean; // 鏄惁鍦� onShow 鏃跺姞杞界紦瀛�
+    } = {}
+  ) => {
+    const { loadCacheOnShow = true } = options;
+
+    // 鍙湪 onShow 鏃跺姞杞界紦瀛橈紝涓嶇鐢ㄧ洃鍚櫒
+    if (loadCacheOnShow) {
+      onShow(() => {
+        console.log(`[useScanCode][${currentEventName}] onShow 瑙﹀彂`);
+        loadFromCache();
+      });
+    }
+
+    // 娉ㄦ剰锛氫笉鍐嶅湪 onHide 鍜� onUnmounted 涓鐢ㄧ洃鍚櫒
+    // 鐩戝惉鍣ㄤ繚鎸佸叏灞�婵�娲荤姸鎬�
+  };
+
+  // 椤甸潰鍔犺浇鏃惰嚜鍔ㄤ粠缂撳瓨璇诲彇
+  loadFromCache();
+
+  return {
+    // 鐘舵��
+    deviceUid,
+    deviceModel,
+    scanData,
+    // 璁$畻灞炴��
+    hasScanned: computed(() => !!deviceUid.value),
+    displayText: computed(() => deviceModel.value || "鏈壂鐮�"),
+    // 鏂规硶
+    loadFromCache,
+    saveToCache,
+    clearScanData,
+    validateQRCode,
+    enableListener,
+    disableListener,
+    setupLifecycle,
+  };
+}
diff --git a/src/pages/routingInspection/detail/indexJX.vue b/src/pages/routingInspection/detail/indexJX.vue
index f82336a..27572e5 100644
--- a/src/pages/routingInspection/detail/indexJX.vue
+++ b/src/pages/routingInspection/detail/indexJX.vue
@@ -34,6 +34,9 @@
         淇濆瓨
       </wd-button>
       <view class="placeholder"></view>
+      <view class="scan-info">
+        <text class="scan-device-text">褰撳墠鎵爜鏈哄彴: {{ scannedDeviceModel || "鏈壂鐮�" }}</text>
+      </view>
       <view class="scan-wrapper" @click="openScan">
         <wd-icon name="scan" size="24px" color="#0D867F"></wd-icon>
       </view>
@@ -70,20 +73,20 @@
         <wd-form-item label="鐢熶骇闀垮害" prop="actuallyLength">
           {{ formatValue(recordData.fixedInfo?.actuallyLength, "m") }}
         </wd-form-item>
-        <wd-form-item label="寮犲姏璁剧疆" prop="twistTension">
-          {{ formatValue(recordData.fixedInfo?.twistTension, "N/m") }}
+        <wd-form-item label="寮犲姏璁剧疆" prop="tensionSetting">
+          {{ formatValue(recordData.fixedInfo?.tensionSetting, "N/m") }}
         </wd-form-item>
         <!-- 缁炲埗澶栧緞锛堝彲缂栬緫锛� -->
-        <wd-form-item label="缁炲埗澶栧緞" prop="twistDiameter" required>
+        <wd-form-item label="缁炲悎澶栧緞" prop="twistedOuterDiameter" required>
           <template v-if="isEdit">
             <wd-input
-              v-model="formData.twistDiameter"
-              placeholder="璇疯緭鍏ョ粸鍒跺寰勶紙mm锛�"
+              v-model="formData.twistedOuterDiameter"
+              placeholder="璇疯緭鍏ョ粸鍚堝寰勶紙mm锛�"
               type="number"
             />
           </template>
           <template v-else>
-            {{ formatValue(formData.twistDiameter, "mm") }}
+            {{ formatValue(formData.twistedOuterDiameter, "mm") }}
           </template>
         </wd-form-item>
       </wd-col>
@@ -205,7 +208,12 @@
         </wd-form-item>
         <wd-form-item label="鑺傝窛" prop="pitch" required>
           <template v-if="isEdit">
-            <wd-input v-model="item.pitch" placeholder="璇疯緭鍏ヨ妭璺濓紙mm锛�" type="number" />
+            <wd-input
+              v-model="item.pitch"
+              placeholder="璇疯緭鍏ヨ妭璺濓紙mm锛�"
+              type="number"
+              @input="updatePitchRatio(item)"
+            />
           </template>
           <template v-else>
             {{ formatValue(item.pitch, "mm") }}
@@ -225,17 +233,18 @@
       <wd-col :span="24">
         <wd-form-item label="浜у搧澶栬" prop="productAppearance" required>
           <template v-if="isEdit">
-            <wd-checkbox-group
-              v-model="formData.productAppearance"
-              inline
-              v-for="(opt, idx) in appearanceOptions"
-              :key="idx"
-              style="text-align: justify"
-            >
-              <wd-checkbox :modelValue="opt.value" style="width: 100px">
+            <view style="display: flex; flex-wrap: wrap; gap: 10px">
+              <wd-checkbox
+                v-for="(opt, idx) in appearanceOptions"
+                :key="idx"
+                :value="opt.value"
+                :modelValue="formData.productAppearance.includes(opt.value)"
+                @click="handleAppearanceClick(opt.value)"
+                style="width: 100px"
+              >
                 {{ opt.label }}
               </wd-checkbox>
-            </wd-checkbox-group>
+            </view>
           </template>
           <template v-else>
             {{ formatProductAppearance(formData.productAppearance) }}
@@ -308,18 +317,18 @@
         <img :src="previewImageUrl" alt="棰勮鍥剧墖" style="width: 100%; height: auto" />
       </div>
     </wd-popup>
-    <Scan ref="scanRef" emitName="scan" />
     <wd-toast />
   </view>
 </template>
 
 <script setup lang="ts">
-import { ref, reactive, computed } from "vue";
-import { onLoad } from "@dcloudio/uni-app";
+import { ref, reactive, computed, onUnmounted } from "vue";
+import { onLoad, onShow, onHide } from "@dcloudio/uni-app";
 import RoutingInspectionApi from "@/api/routingInspection/routingInspection";
-import Scan from "@/components/scan/index.vue";
 import { useToast } from "wot-design-uni";
 import AttachmentUpload from "../upload.vue";
+import { useUserStore } from "@/store/modules/user";
+import { useScanCode } from "@/composables/useScanCode";
 
 const paramsType = ref("");
 const paramsId = ref("");
@@ -328,15 +337,25 @@
 const previewImageUrl = ref("");
 const isEdit = ref(false);
 const tempFiles = ref<any[]>([]); // 涓存椂瀛樺偍鏂颁笂浼犵殑闄勪欢
-const deviceUid = ref("");
-const scanRef = ref();
 const toast = useToast();
 const attachmentRef = ref<any>(null);
 const detailData = reactive<any>({});
 const detailDataLoaded = ref(false);
 
+// 鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛淇℃伅
+const userStore = useUserStore();
+const userInfo: any = computed(() => userStore.userInfo);
+
+// 浣跨敤鎵爜绠$悊 composable锛堝叏灞�鐩戝惉鍣紝涓嶉殢椤甸潰鍒囨崲鍏抽棴锛�
+const {
+  deviceUid,
+  deviceModel: scannedDeviceModel,
+  loadFromCache,
+  enableListener,
+} = useScanCode("scanJX");
+
 const formData = reactive({
-  twistDiameter: "", // 缁炲埗澶栧緞
+  twistedOuterDiameter: "", // 缁炲埗澶栧緞
   structureFormula: "", // 鎴愬搧缁撴瀯
   structureItems: [], // 缁撴瀯鏍囧噯鍊煎拰瀹炴祴
   inspectTwist: [], // 缁炵嚎宸ヨ壓璐ㄩ噺鎺у埗
@@ -370,15 +389,19 @@
   const structureResult = recordData.value.structureInfo?.structureRecordResult || {};
   const inspectionResult = recordData.value.inspectionResult || {};
 
-  formData.twistDiameter = inspectionResult.twistDiameter || "";
+  formData.twistedOuterDiameter =
+    recordData.value.structureInfo.structureRecordResult.twistedOuterDiameter || "";
   formData.structureFormula = structureResult.inspectStructure?.structureFormula || "";
   formData.sampleComplete = inspectionResult.sampleComplete || "";
   formData.conclusion = structureResult.conclusion || "";
-  formData.productAppearance = Array.isArray(structureResult.productAppearance)
+
+  // 鍒濆鍖栦骇鍝佸瑙�
+  const appearance = Array.isArray(structureResult.productAppearance)
     ? structureResult.productAppearance
     : structureResult.productAppearance
-    ? [structureResult.productAppearance]
-    : [];
+      ? [structureResult.productAppearance]
+      : [];
+  formData.productAppearance = appearance;
 
   formData.structureItems = JSON.parse(
     JSON.stringify(structureResult.inspectStructure?.structureItems || [])
@@ -395,6 +418,13 @@
     const response = await RoutingInspectionApi.getStrandedInspectionStructureInfoById({ id });
     recordData.value = response.data;
     detailData.value = response.data.structureInfo;
+
+    // 濡傛灉璁板綍浜轰负绌猴紝榛樿璁剧疆涓哄綋鍓嶇櫥褰曠敤鎴�
+    if (recordData.value.structureInfo && !recordData.value.structureInfo.createUserName) {
+      recordData.value.structureInfo.createUserName =
+        userInfo.value?.nickName || userInfo.value?.userName || "";
+    }
+
     console.log("detailData.value", detailData.value);
     tempFiles.value = []; // 娓呯┖涓存椂鏂囦欢
     initFormData(); // 鏁版嵁杩斿洖鍚庡垵濮嬪寲琛ㄥ崟
@@ -434,7 +464,8 @@
 const saveList = async () => {
   // 1. 鍩虹瀛楁鏍¢獙
   if (!formData.structureFormula) return uni.showToast({ title: "鎴愬搧缁撴瀯涓哄繀濉」", icon: "none" });
-  if (!formData.twistDiameter) return uni.showToast({ title: "缁炲埗澶栧緞涓哄繀濉」", icon: "none" });
+  if (!formData.twistedOuterDiameter)
+    return uni.showToast({ title: "缁炲埗澶栧緞涓哄繀濉」", icon: "none" });
   if (!formData.productAppearance.length)
     return uni.showToast({ title: "浜у搧澶栬涓哄繀濉」", icon: "none" });
   if (!formData.conclusion) return uni.showToast({ title: "缁撹涓哄繀濉」", icon: "none" });
@@ -458,8 +489,15 @@
     if (!item.pitchRatio)
       return uni.showToast({ title: `${item.twistName}鑺傚緞姣斾负蹇呭~椤筦, icon: "none" });
   }
-  console.log("1111", deviceUid.value);
-  if (!deviceUid.value) return uni.showToast({ title: "璇锋壂鎻忎簩缁寸爜", icon: "none" });
+  // 楠岃瘉鎵爜鏁版嵁锛堜粠缂撳瓨鎴栨柊鎵爜鑾峰彇锛�
+  console.log("淇濆瓨鍓嶆鏌� deviceUid:", deviceUid.value);
+  if (!deviceUid.value) {
+    return uni.showToast({
+      title: "璇峰厛鎵弿璁惧浜岀淮鐮�",
+      icon: "none",
+      duration: 2000,
+    });
+  }
   const { newFiles } = attachmentRef.value.getSubmitFiles();
   console.log("newFiles", newFiles);
   const allFileIds = [...newFiles];
@@ -468,7 +506,7 @@
       deviceUid: deviceUid.value,
       id: paramsId.value,
       result: {
-        twistDiameter: formData.twistDiameter,
+        twistedOuterDiameter: formData.twistedOuterDiameter,
         structureFormula: formData.structureFormula,
         structureItems: formData.structureItems,
         inspectTwist: formData.inspectTwist,
@@ -483,9 +521,20 @@
     });
 
     if (res.code === 200) {
-      uni.showToast({ title: "淇濆瓨鎴愬姛", icon: "success" });
-      isEdit.value = false;
-      getDetailData(paramsId.value, paramsType.value);
+      // 璁剧疆鍒锋柊鏍囪锛屽憡璇夊垪琛ㄩ〉闇�瑕佸埛鏂�
+      uni.setStorageSync("needRefreshInspectionList", true);
+
+      uni.showToast({
+        title: "淇濆瓨鎴愬姛",
+        icon: "success",
+        duration: 1500,
+      });
+      // 寤惰繜杩斿洖鍒楄〃椤碉紝璁╃敤鎴风湅鍒版垚鍔熸彁绀�
+      setTimeout(() => {
+        uni.navigateBack({
+          delta: 1,
+        });
+      }, 1500);
     } else {
       uni.showModal({ title: res.msg || "淇濆瓨澶辫触", icon: "error" });
     }
@@ -507,11 +556,11 @@
     case 1:
       return "danger"; // 宸查┏鍥�
     case 2:
-      return "info"; // 寰呭鏍�
+      return "primary"; // 寰呭鏍�
     case 3:
       return "success"; // 閫氳繃
     default:
-      return "info";
+      return "default";
   }
 };
 
@@ -553,36 +602,90 @@
   });
 };
 
-const openScan = () => {
-  scanRef.value.triggerScan();
+// 璁$畻鑺傚緞姣�
+const calculatePitchRatio = (pitch: string, dia: string) => {
+  // 濡傛灉pitch鎴杁ia涓虹┖锛屽垯杩斿洖"-"
+  if (!pitch || !dia) return "-";
+
+  // 灏唒itch鍜宒ia杞崲涓烘诞鐐规暟
+  const pitchNum = parseFloat(pitch);
+  const diaNum = parseFloat(dia);
+
+  // 濡傛灉pitchNum鎴杁iaNum鏄疦aN锛屾垨鑰卍iaNum涓�0锛屽垯杩斿洖"-"
+  if (isNaN(pitchNum) || isNaN(diaNum) || diaNum === 0) return "-";
+
+  // 璁$畻pitchNum鍜宒iaNum鐨勬瘮鍊硷紝骞朵繚鐣欎袱浣嶅皬鏁�
+  return (pitchNum / diaNum).toFixed(2);
 };
-const getScanCode = (params: any) => {
-  console.log("瀹屾暣鍙傛暟锛�", params);
-  let codeObj = {};
-  try {
-    codeObj = JSON.parse(params.code);
-  } catch (err) {
-    console.error("JSON瑙f瀽澶辫触锛�", err);
-    toast.error("鎵爜鏁版嵁寮傚父");
-    return;
+
+// 鏇存柊鑺傚緞姣旓紙褰撹妭璺濆彉鍖栨椂鑷姩璁$畻锛�
+const updatePitchRatio = (item: any) => {
+  // 浣跨敤缁炲悎澶栧緞浣滀负鐩村緞鏉ヨ绠楄妭寰勬瘮
+  const dia = item.dia;
+  item.pitchRatio = calculatePitchRatio(item.pitch, dia);
+};
+
+// 澶勭悊浜у搧澶栬閫夋嫨鐨勪簰鏂ラ�昏緫
+const handleAppearanceClick = (value: string) => {
+  const currentValues = [...formData.productAppearance];
+  const isCurrentlyChecked = currentValues.includes(value);
+
+  let newSelection: string[] = [];
+
+  if (value === "鏃犲瑙傞棶棰�") {
+    if (isCurrentlyChecked) {
+      // 鍙栨秷閫変腑"鏃犲瑙傞棶棰�"
+      newSelection = [];
+    } else {
+      // 閫変腑"鏃犲瑙傞棶棰�"锛屾竻绌哄叾浠栭�夐」
+      newSelection = ["鏃犲瑙傞棶棰�"];
+    }
+  } else {
+    // 鐐瑰嚮鍏朵粬閫夐」
+    if (isCurrentlyChecked) {
+      // 鍙栨秷閫変腑璇ラ�夐」
+      newSelection = currentValues.filter((v) => v !== value);
+    } else {
+      // 閫変腑璇ラ�夐」锛岀Щ闄�"鏃犲瑙傞棶棰�"
+      const filteredValues = currentValues.filter((v) => v !== "鏃犲瑙傞棶棰�");
+      newSelection = [...filteredValues, value];
+    }
   }
-  deviceUid.value = codeObj?.uid;
-  toast.success("鎵爜鎴愬姛");
+
+  formData.productAppearance = newSelection;
 };
-// 纭繚鍏堢Щ闄ゅ啀娣诲姞鐩戝惉
-const setupScanListener = () => {
-  uni.$off("scan", getScanCode); // 鍏堢Щ闄ゆ棫鐨�
-  uni.$on("scan", getScanCode); // 鍐嶆坊鍔犳柊鐨�
+
+const openScan = () => {
+  console.log("indexJX - 鐐瑰嚮鎵爜鎸夐挳锛堝叏灞�鎵爜妯″紡锛屾棤闇�鎵嬪姩瑙﹀彂锛�");
+  // 鍏ㄥ眬鎵爜妯″紡涓嬶紝纭欢鎵爜浼氳嚜鍔ㄨЕ鍙戯紝鏃犻渶鎵嬪姩璋冪敤
+  uni.showToast({
+    title: "璇蜂娇鐢ㄦ壂鐮佹灙鎵弿",
+    icon: "none",
+  });
 };
-onUnmounted(() => {
-  // 寮�鍚箍鎾洃鍚簨浠�
-  uni.$off("scan", getScanCode);
-  console.log("绂诲紑1");
-});
-onMounted(() => {
-  // 寮�鍚箍鎾洃鍚簨浠�
-  setupScanListener();
-  console.log("鏄剧ず1");
+
+// 椤甸潰鏄剧ず鏃剁殑澶勭悊
+onShow(() => {
+  console.log("========== indexJX - onShow 瑙﹀彂 ==========");
+  // 閲嶆柊鍚敤鐩戝惉鍣紙纭繚鐩戝惉鍣ㄦ湁鏁堬級
+  enableListener();
+  // 鍔犺浇缂撳瓨锛堟洿鏂癠I鏄剧ず锛�
+  const cachedData = loadFromCache();
+
+  // 濡傛灉娌℃湁缂撳瓨鏁版嵁锛屾彁绀虹敤鎴烽渶瑕佹壂鐮�
+  if (!cachedData || !cachedData.uid) {
+    console.log("鈿狅笍 鏈娴嬪埌鎵爜缂撳瓨锛岀敤鎴烽渶瑕佹壂鎻忚澶囦簩缁寸爜");
+    // 鍦ㄧ紪杈戞ā寮忎笅鎵嶆彁绀�
+    if (isEdit.value) {
+      setTimeout(() => {
+        uni.showToast({
+          title: "璇锋壂鎻忚澶囦簩缁寸爜鍚庡啀淇濆瓨",
+          icon: "none",
+          duration: 2000,
+        });
+      }, 500);
+    }
+  }
 });
 </script>
 
@@ -612,6 +715,18 @@
   flex: 1;
 }
 
+.scan-info {
+  display: flex;
+  align-items: center;
+  margin-right: 10px;
+
+  .scan-device-text {
+    font-size: 14px;
+    color: #0d867f;
+    font-weight: 500;
+  }
+}
+
 .scan-wrapper {
   width: 38px;
   height: 38px;
diff --git a/src/pages/routingInspection/detail/indexLS.vue b/src/pages/routingInspection/detail/indexLS.vue
index f0f4a6b..31b72e3 100644
--- a/src/pages/routingInspection/detail/indexLS.vue
+++ b/src/pages/routingInspection/detail/indexLS.vue
@@ -34,6 +34,9 @@
         淇濆瓨
       </wd-button>
       <view class="placeholder"></view>
+      <view class="scan-info">
+        <text class="scan-device-text">褰撳墠鎵爜鏈哄彴: {{ scannedDeviceModel || "鏈壂鐮�" }}</text>
+      </view>
       <view class="scan-wrapper" @click="openScan">
         <wd-icon name="scan" size="24px" color="#0D867F"></wd-icon>
       </view>
@@ -126,17 +129,18 @@
 
         <wd-form-item label="澶栬" prop="appearance" required>
           <template v-if="isEdit">
-            <wd-checkbox-group
-              v-model="formData.appearance"
-              inline
-              v-for="(opt, idx) in appearanceOptions"
-              :key="idx"
-              style="text-align: justify"
-            >
-              <wd-checkbox :modelValue="opt.value" style="width: 100px">
+            <view style="display: flex; flex-wrap: wrap; gap: 10px">
+              <wd-checkbox
+                v-for="(opt, idx) in appearanceOptions"
+                :key="idx"
+                :value="opt.value"
+                :modelValue="formData.appearance?.includes(opt.value) || false"
+                @click="handleAppearanceClick(opt.value)"
+                style="width: 100px"
+              >
                 {{ opt.label }}
               </wd-checkbox>
-            </wd-checkbox-group>
+            </view>
           </template>
           <template v-else>
             {{ formatProductAppearance(formData.appearance) }}
@@ -293,18 +297,18 @@
         <img :src="previewImageUrl" alt="棰勮鍥剧墖" style="width: 100%; height: auto" />
       </div>
     </wd-popup>
-    <Scan ref="scanRef" emitName="scan" />
     <wd-toast />
   </view>
 </template>
 
 <script setup lang="ts">
-import { ref, reactive } from "vue";
-import { onLoad } from "@dcloudio/uni-app";
+import { ref, reactive, computed, onUnmounted } from "vue";
+import { onLoad, onShow, onHide } from "@dcloudio/uni-app";
 import RoutingInspectionApi from "@/api/routingInspection/routingInspection";
-import Scan from "@/components/scan/index.vue";
 import { useToast } from "wot-design-uni";
 import AttachmentUpload from "../upload.vue";
+import { useUserStore } from "@/store/modules/user";
+import { useScanCode } from "@/composables/useScanCode";
 
 // 鏍稿績鐘舵��
 const paramsId = ref("");
@@ -314,17 +318,27 @@
 const previewImageUrl = ref("");
 const isEdit = ref(false);
 const tempFiles = ref<any[]>([]);
-const deviceUid = ref("");
-const scanRef = ref();
 const toast = useToast();
 const attachmentRef = ref<any>(null);
+
+// 鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛淇℃伅
+const userStore = useUserStore();
+const userInfo: any = computed(() => userStore.userInfo);
+
+// 浣跨敤鎵爜绠$悊 composable锛堝叏灞�鐩戝惉鍣紝涓嶉殢椤甸潰鍒囨崲鍏抽棴锛�
+const {
+  deviceUid,
+  deviceModel: scannedDeviceModel,
+  loadFromCache,
+  enableListener,
+} = useScanCode("scanLS");
 
 // 琛ㄥ崟鏁版嵁
 const formData = reactive({
   dia: "",
   maxDia: "",
   minDia: "",
-  appearance: [],
+  appearance: [] as string[],
   windingTightness: "",
   arrangementNeatness: "",
   aluminumWireDistance: "",
@@ -360,11 +374,11 @@
     case 1:
       return "danger";
     case 2:
-      return "info";
+      return "primary";
     case 3:
       return "success";
     default:
-      return "info";
+      return "default";
   }
 };
 
@@ -385,7 +399,45 @@
 
 // 鏍煎紡鍖栧伐鍏�
 const formatProductAppearance = (productAppearance: string[]) => {
-  return !productAppearance.length ? "-" : productAppearance.join("銆�");
+  if (!productAppearance || !Array.isArray(productAppearance) || !productAppearance.length) {
+    return "-";
+  }
+  return productAppearance.join("銆�");
+};
+
+// 澶勭悊澶栬閫夋嫨鐨勪簰鏂ラ�昏緫
+const handleAppearanceClick = (value: string) => {
+  // 纭繚 appearance 鏄暟缁�
+  if (!Array.isArray(formData.appearance)) {
+    formData.appearance = [];
+  }
+
+  const currentValues = [...formData.appearance];
+  const isCurrentlyChecked = currentValues.includes(value);
+
+  let newSelection: string[] = [];
+
+  if (value === "鏃犲瑙傞棶棰�") {
+    if (isCurrentlyChecked) {
+      // 鍙栨秷閫変腑"鏃犲瑙傞棶棰�"
+      newSelection = [];
+    } else {
+      // 閫変腑"鏃犲瑙傞棶棰�"锛屾竻绌哄叾浠栭�夐」
+      newSelection = ["鏃犲瑙傞棶棰�"];
+    }
+  } else {
+    // 鐐瑰嚮鍏朵粬閫夐」
+    if (isCurrentlyChecked) {
+      // 鍙栨秷閫変腑璇ラ�夐」
+      newSelection = currentValues.filter((v) => v !== value);
+    } else {
+      // 閫変腑璇ラ�夐」锛岀Щ闄�"鏃犲瑙傞棶棰�"
+      const filteredValues = currentValues.filter((v) => v !== "鏃犲瑙傞棶棰�");
+      newSelection = [...filteredValues, value];
+    }
+  }
+
+  formData.appearance = newSelection;
 };
 
 const formatValue = (value: any, unit?: string) => {
@@ -409,7 +461,12 @@
   formData.dia = inspectionResult.dia || "";
   formData.maxDia = inspectionResult.maxDia || "";
   formData.minDia = inspectionResult.minDia || "";
-  formData.appearance = inspectionResult.appearance || [];
+  // 纭繚 appearance 鏄暟缁�
+  formData.appearance = Array.isArray(inspectionResult.appearance)
+    ? inspectionResult.appearance
+    : inspectionResult.appearance
+      ? [inspectionResult.appearance]
+      : [];
   formData.windingTightness = inspectionResult.windingTightness || "";
   formData.arrangementNeatness = inspectionResult.arrangementNeatness || "";
   formData.aluminumWireDistance = inspectionResult.aluminumWireDistance || "";
@@ -423,6 +480,13 @@
   try {
     const response = await RoutingInspectionApi.getDrawInspectInfoById({ id });
     detailData.value = response.data;
+
+    // 濡傛灉宸℃鍛樹负绌猴紝榛樿璁剧疆涓哄綋鍓嶇櫥褰曠敤鎴�
+    if (!detailData.value.processInspectionUserName) {
+      detailData.value.processInspectionUserName =
+        userInfo.value?.nickName || userInfo.value?.userName || "";
+    }
+
     tempFiles.value = [];
     initFormData();
   } catch (error) {
@@ -464,7 +528,16 @@
     return uni.showToast({ title: "鎴愬搧妯″悗鎺ュご鎯呭喌涓哄繀濉」", icon: "none" });
   if (!formData.conclusion) return uni.showToast({ title: "缁撹涓哄繀濉」", icon: "none" });
   if (!formData.isFully) return uni.showToast({ title: "閾濇潌鏍峰搧鏄惁榻愬叏涓哄繀濉」", icon: "none" });
-  if (!deviceUid.value) return uni.showToast({ title: "璇锋壂鎻忎簩缁寸爜", icon: "none" });
+
+  // 楠岃瘉鎵爜鏁版嵁锛堜粠缂撳瓨鎴栨柊鎵爜鑾峰彇锛�
+  console.log("淇濆瓨鍓嶆鏌� deviceUid:", deviceUid.value);
+  if (!deviceUid.value) {
+    return uni.showToast({
+      title: "璇峰厛鎵弿璁惧浜岀淮鐮�",
+      icon: "none",
+      duration: 2000,
+    });
+  }
   const { newFiles } = attachmentRef.value.getSubmitFiles();
   console.log("newFiles", newFiles);
   const allFileIds = [...newFiles];
@@ -488,9 +561,20 @@
       processInspectionAttachmentList: allFileIds,
     });
     if (res.code === 200) {
-      uni.showToast({ title: "淇濆瓨鎴愬姛", icon: "success" });
-      isEdit.value = false;
-      getDetailData(paramsId.value, paramsType.value);
+      // 璁剧疆鍒锋柊鏍囪锛屽憡璇夊垪琛ㄩ〉闇�瑕佸埛鏂�
+      uni.setStorageSync("needRefreshInspectionList", true);
+
+      uni.showToast({
+        title: "淇濆瓨鎴愬姛",
+        icon: "success",
+        duration: 1500,
+      });
+      // 寤惰繜杩斿洖鍒楄〃椤碉紝璁╃敤鎴风湅鍒版垚鍔熸彁绀�
+      setTimeout(() => {
+        uni.navigateBack({
+          delta: 1,
+        });
+      }, 1500);
     } else {
       uni.showModal({ title: res.msg || "淇濆瓨澶辫触", icon: "error" });
     }
@@ -505,33 +589,36 @@
 };
 
 const openScan = () => {
-  scanRef.value.triggerScan();
+  console.log("indexLS - 鐐瑰嚮鎵爜鎸夐挳锛堝叏灞�鎵爜妯″紡锛屾棤闇�鎵嬪姩瑙﹀彂锛�");
+  // 鍏ㄥ眬鎵爜妯″紡涓嬶紝纭欢鎵爜浼氳嚜鍔ㄨЕ鍙戯紝鏃犻渶鎵嬪姩璋冪敤
+  uni.showToast({
+    title: "璇蜂娇鐢ㄦ壂鐮佹灙鎵弿",
+    icon: "none",
+  });
 };
-const getScanCode = (params: any) => {
-  let codeObj = {};
-  try {
-    codeObj = JSON.parse(params.code);
-  } catch (err) {
-    toast.error("鎵爜鏁版嵁寮傚父");
-    return; // 瑙f瀽澶辫触鐩存帴杩斿洖锛岄伩鍏嶅悗缁敊璇�
+
+// 椤甸潰鏄剧ず鏃剁殑澶勭悊
+onShow(() => {
+  console.log("========== indexLS - onShow 瑙﹀彂 ==========");
+  // 閲嶆柊鍚敤鐩戝惉鍣紙纭繚鐩戝惉鍣ㄦ湁鏁堬級
+  enableListener();
+  // 鍔犺浇缂撳瓨锛堟洿鏂癠I鏄剧ず锛�
+  const cachedData = loadFromCache();
+
+  // 濡傛灉娌℃湁缂撳瓨鏁版嵁锛屾彁绀虹敤鎴烽渶瑕佹壂鐮�
+  if (!cachedData || !cachedData.uid) {
+    console.log("鈿狅笍 鏈娴嬪埌鎵爜缂撳瓨锛岀敤鎴烽渶瑕佹壂鎻忚澶囦簩缁寸爜");
+    // 鍦ㄧ紪杈戞ā寮忎笅鎵嶆彁绀�
+    if (isEdit.value) {
+      setTimeout(() => {
+        uni.showToast({
+          title: "璇锋壂鎻忚澶囦簩缁寸爜鍚庡啀淇濆瓨",
+          icon: "none",
+          duration: 2000,
+        });
+      }, 500);
+    }
   }
-  deviceUid.value = codeObj?.uid;
-  toast.success("鎵爜鎴愬姛");
-};
-// 纭繚鍏堢Щ闄ゅ啀娣诲姞鐩戝惉
-const setupScanListener = () => {
-  uni.$off("scan", getScanCode); // 鍏堢Щ闄ゆ棫鐨�
-  uni.$on("scan", getScanCode); // 鍐嶆坊鍔犳柊鐨�
-};
-onUnmounted(() => {
-  // 寮�鍚箍鎾洃鍚簨浠�
-  uni.$off("scan", getScanCode);
-  console.log("绂诲紑1");
-});
-onMounted(() => {
-  // 寮�鍚箍鎾洃鍚簨浠�
-  setupScanListener();
-  console.log("鏄剧ず1");
 });
 </script>
 
@@ -559,6 +646,18 @@
 
 .placeholder {
   flex: 1;
+}
+
+.scan-info {
+  display: flex;
+  align-items: center;
+  margin-right: 10px;
+
+  .scan-device-text {
+    font-size: 14px;
+    color: #0d867f;
+    font-weight: 500;
+  }
 }
 
 .scan-wrapper {
@@ -681,4 +780,4 @@
   align-items: flex-start; // 鍨傜洿鏂瑰悜椤堕儴瀵归綈锛堜笂绉诲叧閿級
   gap: 20rpx; // 閫夐」涔嬮棿鐨勯棿璺�
 }
-</style>
\ No newline at end of file
+</style>
diff --git a/src/pages/routingInspection/index.vue b/src/pages/routingInspection/index.vue
index 7979244..ddad4be 100644
--- a/src/pages/routingInspection/index.vue
+++ b/src/pages/routingInspection/index.vue
@@ -2,7 +2,14 @@
   <view>
     <wd-row>
       <wd-col :span="21">
-        <wd-search placeholder-left hide-cancel></wd-search>
+        <wd-search
+          v-model="searchKeyword"
+          placeholder="璇疯緭鍏ョ彮缁勫悕绉�"
+          placeholder-left
+          hide-cancel
+          @search="handleSearch"
+          @clear="handleClear"
+        ></wd-search>
       </wd-col>
       <wd-col :span="3">
         <view class="scan_box" @click="openScan">
@@ -17,64 +24,64 @@
         :title="`${item.deviceModel}锛堝緟妫�鏌�${item.pendingNum}鏉★級`"
         class="tab_bg"
       >
-        <ProductList :api="RoutingInspectionApi.getInspectListByPatrol" :ProList="item" />
+        <ProductList
+          :key="searchKey"
+          :api="RoutingInspectionApi.getInspectListByPatrol"
+          :ProList="{ ...item, teamName: searchKeyword }"
+        />
       </wd-tab>
     </wd-tabs>
-    <Scan ref="scanRef" emitName="scan" />
     <wd-toast />
   </view>
 </template>
 
 <script lang="ts" setup>
 import { ref, reactive, computed, onMounted, onUnmounted } from "vue";
+import { onShow, onHide } from "@dcloudio/uni-app";
 import ProductList from "./list/index.vue";
-import Scan from "@/components/scan/index.vue";
 import { useUserStore } from "@/store/modules/user";
 import reportApi from "@/api/work/report";
 import { useToast } from "wot-design-uni";
 import RoutingInspectionApi from "@/api/routingInspection/routingInspection";
+import { useScanCode } from "@/composables/useScanCode";
 
-const scanRef = ref();
 const userStore = useUserStore();
 const userInfo: any = computed(() => userStore.userInfo);
 const toast = useToast();
 const tab = ref<number>(0);
 const patrolList = ref<any[]>([]); // 宸℃璁惧鍒楄〃鏁版嵁
+const searchKeyword = ref<string>(""); // 鎼滅储鍏抽敭璇嶏紙鐝粍鍚嶇О锛�
+const searchKey = ref<number>(0); // 鐢ㄤ簬寮哄埗鍒锋柊鍒楄〃
+
+// 浣跨敤鎵爜绠$悊 composable锛堝叏灞�鐩戝惉鍣紝涓嶉殢椤甸潰鍒囨崲鍏抽棴锛�
+const { deviceUid, deviceModel, hasScanned, displayText, loadFromCache, enableListener } =
+  useScanCode("scanIndex");
 
 const handlePatrolData = (index: number, count: number) => {
   // 鍙互鍦ㄨ繖閲屾洿鏂扮壒瀹氬贰妫�璁惧鐨勫緟妫�鏌ユ暟閲�
   // 渚嬪锛歱atrolList.value[index].pendingNum = count;
 };
 
+// 澶勭悊鎼滅储
+const handleSearch = (value: string) => {
+  console.log("鎼滅储鐝粍:", value);
+  searchKey.value++; // 鏇存柊 key 寮哄埗鍒锋柊鍒楄〃
+};
+
+// 澶勭悊娓呯┖鎼滅储
+const handleClear = () => {
+  console.log("娓呯┖鎼滅储");
+  searchKeyword.value = "";
+  searchKey.value++; // 鏇存柊 key 寮哄埗鍒锋柊鍒楄〃
+};
+
 const openScan = () => {
-  scanRef.value.triggerScan();
-};
-
-const getScanCode = async () => {
-  const { code } = await reportApi.sendWorkTime({
-    userName: userInfo.value.userName,
+  console.log("index.vue - 鐐瑰嚮鎵爜鎸夐挳锛堝叏灞�鎵爜妯″紡锛屾棤闇�鎵嬪姩瑙﹀彂锛�");
+  // 鍏ㄥ眬鎵爜妯″紡涓嬶紝纭欢鎵爜浼氳嚜鍔ㄨЕ鍙戯紝鏃犻渶鎵嬪姩璋冪敤
+  uni.showToast({
+    title: "璇蜂娇鐢ㄦ壂鐮佹灙鎵弿",
+    icon: "none",
   });
-  if (code == 200) {
-    toast.success("鎵爜鎴愬姛");
-  }
-};
-
-// 鑾峰彇鐗瑰畾宸℃璁惧鐨勬暟鎹�
-const getPatrolData = (item: any) => {
-  return async (params: any) => {
-    // 杩欓噷鍙互鏍规嵁item涓殑淇℃伅璋冪敤鐩稿簲鐨勬帴鍙h幏鍙栬鎯�
-    // 杩斿洖鐨勬暟鎹牸寮忛渶瑕佷笌ProductList缁勪欢鏈熸湜鐨勬牸寮忎竴鑷�
-    return {
-      code: 200,
-      data: {
-        type: "宸℃",
-        data: {
-          total: 0,
-          records: [],
-        },
-      },
-    };
-  };
 };
 
 // 鑾峰彇宸℃璁惧鍒楄〃
@@ -89,24 +96,32 @@
   }
 };
 
-// 纭繚鍏堢Щ闄ゅ啀娣诲姞鐩戝惉
-const setupScanListener = () => {
-  uni.$off("scan", getScanCode); // 鍏堢Щ闄ゆ棫鐨�
-  uni.$on("scan", getScanCode); // 鍐嶆坊鍔犳柊鐨�
-};
-
 onMounted(() => {
-  // 寮�鍚箍鎾洃鍚簨浠�
-  setupScanListener();
-  console.log("鏄剧ず1");
   // 椤甸潰鍔犺浇鏃惰幏鍙栧贰妫�璁惧鍒楄〃
   loadPatrolList();
+  // 鍚敤鍏ㄥ眬鐩戝惉鍣�
+  enableListener();
+  console.log("index.vue - onMounted");
 });
 
-onUnmounted(() => {
-  // 寮�鍚箍鎾洃鍚簨浠�
-  uni.$off("scan", getScanCode);
-  console.log("绂诲紑1");
+onShow(() => {
+  console.log("========== index.vue - onShow 瑙﹀彂 ==========");
+  // 椤甸潰鏄剧ず鏃堕噸鏂板惎鐢ㄧ洃鍚櫒锛堢‘淇濈洃鍚櫒鏈夋晥锛�
+  enableListener();
+  // 鍔犺浇缂撳瓨锛堟洿鏂癠I鏄剧ず锛�
+  loadFromCache();
+
+  // 妫�鏌ユ槸鍚﹂渶瑕佸埛鏂板垪琛紙鍙湁鎻愪氦鎴愬姛鍚庢墠鍒锋柊锛�
+  const needRefresh = uni.getStorageSync("needRefreshInspectionList");
+  if (needRefresh) {
+    console.log("妫�娴嬪埌闇�瑕佸埛鏂板垪琛紝寮�濮嬪埛鏂�...");
+    // 閲嶆柊鍔犺浇宸℃璁惧鍒楄〃锛堝埛鏂板緟妫�鏌ユ暟閲忥級
+    loadPatrolList();
+    // 寮哄埗鍒锋柊 ProductList 缁勪欢
+    searchKey.value++;
+    // 娓呴櫎鍒锋柊鏍囪
+    uni.removeStorageSync("needRefreshInspectionList");
+  }
 });
 </script>
 
@@ -146,4 +161,4 @@
 .statistics_box {
   margin: 15px;
 }
-</style>
\ No newline at end of file
+</style>
diff --git a/src/pages/routingInspection/list/index.vue b/src/pages/routingInspection/list/index.vue
index 41b6c0e..43d1041 100644
--- a/src/pages/routingInspection/list/index.vue
+++ b/src/pages/routingInspection/list/index.vue
@@ -1,112 +1,130 @@
 <template>
-	<view class="card_box">
-		<z-paging ref="pagingRef" v-model="list" :fixed="false" :auto-show-back-to-top="true" @query="getList">
-			<ProductCard v-for="(item, index) in list" :key="index" :data="item" :map="map"
-				@click="toDetail(item.id, item.deviceType)" />
-		</z-paging>
-		<wd-toast />
-	</view>
+  <view class="card_box">
+    <z-paging
+      ref="pagingRef"
+      v-model="list"
+      :fixed="false"
+      :auto-show-back-to-top="true"
+      @query="getList"
+    >
+      <ProductCard
+        v-for="(item, index) in list"
+        :key="index"
+        :data="item"
+        :map="map"
+        @click="toDetail(item.id, item.deviceType)"
+      />
+    </z-paging>
+    <wd-toast />
+  </view>
 </template>
 
 <script setup lang="ts">
-	import ProductCard from "../product_card/index.vue";
-	import { useUserStore } from "@/store/modules/user";
-	import zPaging from "@/components/z-paging/z-paging.vue";
-	import { useToast } from "wot-design-uni";
+import ProductCard from "../product_card/index.vue";
+import { useUserStore } from "@/store/modules/user";
+import zPaging from "@/components/z-paging/z-paging.vue";
+import { useToast } from "wot-design-uni";
 
-	const toast = useToast();
-	const userStore = useUserStore();
-	const userInfo : any = computed(() => userStore.userInfo);
-	const pagingRef = ref();
+const toast = useToast();
+const userStore = useUserStore();
+const userInfo: any = computed(() => userStore.userInfo);
+const pagingRef = ref();
 const map = reactive({
-		deviceModel: "deviceModel",
-		model: "model",
-		firstNo: "firstNo",
-		recordDate: "recordDate",
-		workShift: "workShift",
-		teamName: "teamName",
-		poleModel: "poleModel",
-		poleNumber: "poleNumber",
-		outputNumber: "outputNumber",
-		inspectPerson: "inspectPerson",
-		status: "status",
-    rejectList: [
+  deviceModel: "deviceModel",
+  model: "model",
+  firstNo: "firstNo",
+  recordDate: "recordDate",
+  workShift: "workShift",
+  teamName: "teamName",
+  poleModel: "poleModel",
+  poleNumber: "poleNumber",
+  outputNumber: "outputNumber",
+  inspectPerson: "inspectPerson",
+  status: "status",
+  productType: "productType",
+  recordPosition: "recordPosition",
+  rejectList: [
+    {
+      rejectPerson: "rejectPerson",
+      rejectTime: "rejectTime",
+      rejectReason: {
+        reason: "reason",
+      },
+    },
+  ], // 鏀逛负瀵硅薄锛屽寘鍚墍闇�鐨勫祵濂楀睘鎬�
+});
+const props = defineProps({
+  api: {
+    type: Function,
+    default: () => {},
+  },
+  ProList: {
+    type: Object,
+    default: () => {},
+  },
+});
+
+const list = ref<any[]>([]);
+
+const toDetail = (id: number, deviceType: number) => {
+  console.log("鐐瑰嚮鍗$墖", id, deviceType);
+  if (deviceType == 1) {
+    // 缁炵嚎
+    uni.navigateTo({
+      url: `/pages/routingInspection/detail/indexJX?id=${id}&deviceType=${deviceType}`,
+    });
+  } else if (deviceType == 0) {
+    // 鎷変笣
+    uni.navigateTo({
+      url: `/pages/routingInspection/detail/indexLS?id=${id}&deviceType=${deviceType}`,
+    });
+  }
+};
+
+const getList = async (pageNo = 1, pageSize = 10) => {
+  const { code, data } = await props.api({
+    deviceModel: props.ProList.deviceModel,
+    status: "0",
+    deviceType: props.ProList.deviceType,
+    teamName: props.ProList.teamName || "", // 鐝粍鍚嶇О鎼滅储
+    current: pageNo,
+    size: pageSize,
+  });
+  if (code == 200) {
+    map.deviceModel = "deviceModel";
+    map.model = "model";
+    map.firstNo = "firstNo";
+    map.recordDate = "recordDate";
+    map.workShift = "workShift";
+    map.teamName = "teamName";
+    map.poleModel = "poleModel";
+    map.poleNumber = "poleNumber";
+    map.outputNumber = "outputNumber";
+    map.inspectPerson = "inspectPerson";
+    map.productType = "productType";
+    map.recordPosition = "recordPosition";
+    map.rejectList = [
       {
         rejectPerson: "rejectPerson",
         rejectTime: "rejectTime",
         rejectReason: {
-          reason: "reason"
+          reason: "reason",
         },
       },
-		], // 鏀逛负瀵硅薄锛屽寘鍚墍闇�鐨勫祵濂楀睘鎬�
-	});
-	const props = defineProps({
-		api: {
-			type: Function,
-			default: () => { },
-		},
-		ProList: {
-			type: Object,
-			default: () => { },
-		},
-	});
-
-	const list = ref<any[]>([]);
-
-const toDetail = (id: number, deviceType: number) => {
-	console.log('鐐瑰嚮鍗$墖', id, deviceType);
-	if (deviceType == 1) {
-			// 缁炵嚎
-			uni.navigateTo({
-				url: `/pages/routingInspection/detail/indexJX?id=${id}&deviceType=${deviceType}`,
-			});
-	} else if (deviceType == 0) {
-			// 鎷変笣
-			uni.navigateTo({
-				url: `/pages/routingInspection/detail/indexLS?id=${id}&deviceType=${deviceType}`,
-			});
-		}
-	};
-
-	const getList = async () => {
-		const { code, data } = await props.api({
-			deviceModel: props.ProList.deviceModel,
-			status: "0",
-			deviceType: props.ProList.deviceType,
-		});
-		if (code == 200) {
-      map.deviceModel = "deviceModel";
-			map.model = "model";
-			map.firstNo = "firstNo";
-			map.recordDate = "recordDate";
-			map.workShift = "workShift";
-			map.teamName = "teamName";
-			map.poleModel = "poleModel";
-			map.poleNumber = "poleNumber";
-			map.outputNumber = "outputNumber";
-      map.inspectPerson = "inspectPerson";
-      map.rejectList = [
-        {
-          rejectPerson: "rejectPerson",
-          rejectTime: "rejectTime",
-          rejectReason: {
-            reason: "reason"
-          },
-        },
-      ];
-			map.status = "status";
-			if (data.total == 0) {
-				pagingRef.value.complete(true);
-      } else {
-        console.log('data.records', data.records);
-				pagingRef.value.complete(data.records);
-			}
-		}
-	};
+    ];
+    map.status = "status";
+    if (data.total == 0) {
+      pagingRef.value.complete(true);
+    } else {
+      console.log("data.records", data.records);
+      pagingRef.value.complete(data.records);
+    }
+  }
+};
 </script>
 
 <style lang="scss" scoped>
-	.card_box {
-		height: calc(100vh - 120px);
-	}
-</style>
\ No newline at end of file
+.card_box {
+  height: calc(100vh - 120px);
+}
+</style>
diff --git a/src/pages/routingInspection/product_card/index.vue b/src/pages/routingInspection/product_card/index.vue
index 6266cd8..dd95bd5 100644
--- a/src/pages/routingInspection/product_card/index.vue
+++ b/src/pages/routingInspection/product_card/index.vue
@@ -2,25 +2,12 @@
   <wd-card class="card_bg" @click="handleCardClick">
     <template #title>
       <view class="flex justify-between w-full">
-        <text class="font-medium text-[#252525]">鏈哄彴: {{ data[map.deviceModel] }}</text>
+        <text class="font-medium text-[#252525]">璁板綍浣嶇疆: {{ data[map.recordPosition] }}</text>
         <wd-tag color="#0D867F" bg-color="#E7F4EC">
           <text class="text-xs">{{ data[map.model] }}</text>
         </wd-tag>
       </view>
     </template>
-    <wd-row class="my-2">
-      <wd-col :span="24">
-        <view class="flex">
-          <view class="icon_box">
-            <wd-icon name="folder" color="#0D867F"></wd-icon>
-          </view>
-          <text class="text-[#646874] mx-2">
-            棣栨鍗曞彿:
-            <text class="text-[#252525]">{{ data[map.firstNo] }}</text>
-          </text>
-        </view>
-      </wd-col>
-    </wd-row>
     <wd-row class="my-2">
       <wd-col :span="24">
         <view class="flex">
@@ -42,44 +29,22 @@
           </view>
           <text class="text-[#646874] mx-2">
             鐝粍:
-            <text class="text-[#252525]">{{ data[map.teamName] }}</text>
+            <text class="text-[#252525]">
+              {{ data[map.teamName]?.slice(-2) || data[map.teamName] }}
+            </text>
           </text>
         </view>
       </wd-col>
     </wd-row>
-    <wd-row class="my-2">
+    <wd-row class="my-2" v-if="data[map.productType]">
       <wd-col :span="24">
         <view class="flex">
           <view class="icon_box">
             <wd-icon name="folder" color="#0D867F"></wd-icon>
           </view>
           <text class="text-[#646874] mx-2">
-            棰嗙敤鏉嗗彿:
-            <text class="text-[#252525]">{{ data[map.poleNumber] }}</text>
-          </text>
-        </view>
-      </wd-col>
-    </wd-row>
-    <wd-col :span="12">
-      <view class="flex">
-        <view class="icon_box">
-          <wd-icon name="folder" color="#0D867F"></wd-icon>
-        </view>
-        <text class="text-[#646874] mx-2">
-          鏉嗗瀷鍙�:
-          <text class="text-[#252525]">{{ data[map.poleModel] }}</text>
-        </text>
-      </view>
-    </wd-col>
-    <wd-row class="my-2">
-      <wd-col :span="12">
-        <view class="flex">
-          <view class="icon_box">
-            <wd-icon name="folder" color="#0D867F"></wd-icon>
-          </view>
-          <text class="text-[#646874] mx-2">
-            鐢熶骇杞存暟:
-            <text class="text-[#252525]">{{ data[map.outputNumber] }}</text>
+            浜у搧绫诲埆:
+            <text class="text-[#252525]">{{ data[map.productType] }}</text>
           </text>
         </view>
       </wd-col>
@@ -216,7 +181,9 @@
 .page-class {
   :deep() {
     .custom-shadow {
-      box-shadow: 0 3px 1px -2px rgb(0 0 0 / 20%), 0 2px 2px 0 rgb(0 0 0 / 14%),
+      box-shadow:
+        0 3px 1px -2px rgb(0 0 0 / 20%),
+        0 2px 2px 0 rgb(0 0 0 / 14%),
         0 1px 5px 0 rgb(0 0 0 / 12%);
     }
   }
@@ -232,4 +199,4 @@
 .content {
   padding: 5px;
 }
-</style>
\ No newline at end of file
+</style>
diff --git a/src/pages/routingInspection/upload.vue b/src/pages/routingInspection/upload.vue
index 5b69b44..4e18c6b 100644
--- a/src/pages/routingInspection/upload.vue
+++ b/src/pages/routingInspection/upload.vue
@@ -18,20 +18,25 @@
     <view class="attachment-list">
       <wd-status-tip v-if="attachmentList.length === 0" image="content" tip="鏆傛棤闄勪欢" />
 
-      <view v-for="item in attachmentList" :key="item.id" class="attachment-card">
+      <view v-for="(item, index) in attachmentList" :key="item.id || index" class="attachment-card">
         <view class="media-wrapper" @click="previewAttachment(item)">
           <!-- 鍥剧墖棰勮 -->
           <template v-if="isImageType(item.url)">
             <image
-              v-if="!item.loadError"
               :src="getFullUrl(item.url)"
               mode="aspectFill"
               class="media-preview"
-              @error="onImageError(item)"
-              @load="onImageLoad(item)"
+              style="width: 100%; height: 100%"
+              @error="onImageError(item, index)"
+              @load="onImageLoad(item, index)"
+              :show-menu-by-longpress="true"
             />
+            <!-- 鍔犺浇涓伄缃� -->
+            <view v-if="item.loading" class="loading-mask">
+              <text class="loading-text">鍔犺浇涓�...</text>
+            </view>
             <!-- 鍥剧墖鍔犺浇澶辫触鏄剧ず榛樿鍥炬爣 -->
-            <view v-else class="file-icon-wrapper">
+            <view v-if="item.loadError" class="file-icon-wrapper error-overlay">
               <wd-icon name="picture" size="48px" color="#ccc" />
               <text class="file-name error-text">鍔犺浇澶辫触</text>
             </view>
@@ -40,15 +45,15 @@
           <!-- 瑙嗛棰勮 -->
           <template v-else-if="isVideoType(item.url)">
             <video
-              v-if="!item.loadError"
               :src="getFullUrl(item.url)"
               class="media-preview"
               :controls="false"
-              :show-center-play-btn="false"
-              @error="onVideoError(item)"
+              :show-center-play-btn="true"
+              @error="onVideoError(item, index)"
+              object-fit="cover"
             />
             <!-- 瑙嗛鍔犺浇澶辫触鏄剧ず榛樿鍥炬爣 -->
-            <view v-else class="file-icon-wrapper">
+            <view v-if="item.loadError" class="file-icon-wrapper error-overlay">
               <wd-icon name="video" size="48px" color="#ccc" />
               <text class="file-name error-text">鍔犺浇澶辫触</text>
             </view>
@@ -73,15 +78,17 @@
 </template>
 
 <script setup lang="ts">
-import { ref } from "vue";
+import { ref, computed, watch } from "vue";
 import { useToast } from "wot-design-uni";
 import AttachmentAPI from "@/api/product/attachment";
 
 // H5 浣跨敤 VITE_APP_BASE_API 浣滀负浠g悊璺緞锛屽叾浠栧钩鍙颁娇鐢� VITE_APP_API_URL 浣滀负璇锋眰璺緞
-let baseUrl = import.meta.env.VITE_APP_API_URL;
+let baseUrlValue = import.meta.env.VITE_APP_API_URL || "";
 // #ifdef H5
-baseUrl = import.meta.env.VITE_APP_BASE_API;
+baseUrlValue = import.meta.env.VITE_APP_BASE_API || "";
 // #endif
+
+const baseUrl = ref(baseUrlValue); // 浣跨敤ref浣垮叾鍦ㄦā鏉夸腑鍙闂�
 
 // 澶栭儴鍙傛暟
 const props = defineProps({
@@ -91,35 +98,100 @@
 });
 
 const toast = useToast();
-const attachmentList = ref<any[]>(props.detailData.files || []);
-const attachmentIds = ref<string[]>(props.detailData.attachmentId || []);
+
+// 鑾峰彇鍒濆鏁版嵁
+const getInitialData = () => {
+  // 澶勭悊涓嶅悓鐨勬暟鎹粨鏋�
+  let data = props.detailData;
+
+  // 濡傛灉鏄� ref 瀵硅薄锛岃幏鍙栧叾 value
+  if (data && typeof data === "object" && "value" in data) {
+    data = data.value;
+  }
+
+  // 濡傛灉鏄暟缁勶紝鐩存帴杩斿洖
+  if (Array.isArray(data)) {
+    return data.map((item) => ({
+      ...item,
+      loading: false,
+      loadError: false,
+    }));
+  }
+
+  // 濡傛灉鏈� files 灞炴��
+  if (data && data.files) {
+    const files = Array.isArray(data.files) ? data.files : [];
+    return files.map((item) => ({
+      ...item,
+      loading: false,
+      loadError: false,
+    }));
+  }
+
+  return [];
+};
+
+const attachmentList = ref<any[]>(getInitialData());
+const attachmentIds = ref<string[]>(attachmentList.value.map((item: any) => item.id) || []);
+
+// 鐩戝惉 props.detailData 鍙樺寲
+watch(
+  () => props.detailData,
+  (newVal) => {
+    const newData = getInitialData();
+    if (newData.length > 0) {
+      attachmentList.value = newData.map((item) => ({
+        ...item,
+        loading: false,
+        loadError: false,
+      }));
+      attachmentIds.value = newData.map((item: any) => item.id);
+    }
+  },
+  { deep: true, immediate: false }
+);
 
 // 鑾峰彇瀹屾暣鐨勫浘鐗�/瑙嗛 URL
 const getFullUrl = (url: string) => {
   if (!url) return "";
+
   // 濡傛灉宸茬粡鏄畬鏁寸殑 URL锛坔ttp 鎴� https 寮�澶达級锛岀洿鎺ヨ繑鍥�
   if (url.startsWith("http://") || url.startsWith("https://")) {
     return url;
   }
+
+  // 妫�鏌� baseUrl 鏄惁鏈夋晥
+  if (!baseUrl.value) {
+    console.error("鉂� baseUrl鏈厤缃紝url:", url);
+    return url;
+  }
+
   // 濡傛灉鏄浉瀵硅矾寰勶紝鎷兼帴鍩虹 URL
-  return `${baseUrl}${url.startsWith("/") ? "" : "/"}${url}`;
+  const separator = url.startsWith("/") || baseUrl.value.endsWith("/") ? "" : "/";
+  return `${baseUrl.value}${separator}${url}`;
 };
 
 // 鍥剧墖鍔犺浇鎴愬姛
-const onImageLoad = (item: any) => {
+const onImageLoad = (item: any, index: number) => {
+  item.loading = false;
   item.loadError = false;
+  attachmentList.value = [...attachmentList.value];
 };
 
 // 鍥剧墖鍔犺浇澶辫触
-const onImageError = (item: any) => {
-  console.error("鍥剧墖鍔犺浇澶辫触:", item.url);
+const onImageError = (item: any, index: number) => {
+  console.error(`鍥剧墖鍔犺浇澶辫触 [${index}]:`, item.url);
+  item.loading = false;
   item.loadError = true;
+  attachmentList.value = [...attachmentList.value];
 };
 
 // 瑙嗛鍔犺浇澶辫触
-const onVideoError = (item: any) => {
-  console.error("瑙嗛鍔犺浇澶辫触:", item.url);
+const onVideoError = (item: any, index: number) => {
+  console.error(`瑙嗛鍔犺浇澶辫触 [${index}]:`, item.url);
+  item.loading = false;
   item.loadError = true;
+  attachmentList.value = [...attachmentList.value];
 };
 
 // 鏂板闄勪欢
@@ -405,14 +477,23 @@
 
   .attachment-card {
     width: 100%;
-    aspect-ratio: 1;
+    position: relative;
+
+    // 浣跨敤 padding-top 瀹炵幇姝f柟褰紙鍏煎鎬ф洿濂斤級
+    &::before {
+      content: "";
+      display: block;
+      padding-top: 100%; // 楂樺害绛変簬瀹藉害
+    }
   }
 }
 
 .media-wrapper {
-  position: relative;
-  width: 100%;
-  height: 100%;
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
   border-radius: 8px;
   overflow: hidden;
   background: #f5f5f5;
@@ -421,6 +502,25 @@
     width: 100%;
     height: 100%;
     object-fit: cover;
+    display: block;
+  }
+
+  .loading-mask {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background: rgba(0, 0, 0, 0.3);
+    z-index: 5;
+
+    .loading-text {
+      font-size: 12px;
+      color: #fff;
+    }
   }
 
   .file-icon-wrapper {
@@ -448,6 +548,16 @@
         color: #ff4757;
       }
     }
+
+    &.error-overlay {
+      position: absolute;
+      top: 0;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      background: rgba(255, 255, 255, 0.9);
+      z-index: 5;
+    }
   }
 
   .delete-btn {
diff --git a/src/utils/request.ts b/src/utils/request.ts
index 8fa1c60..804150b 100644
--- a/src/utils/request.ts
+++ b/src/utils/request.ts
@@ -36,10 +36,12 @@
           uni.showToast({
             title: resData.msg || "涓氬姟澶勭悊澶辫触",
             icon: "none",
+            duration: 2000,
           });
           reject({
             message: resData.msg || "涓氬姟澶勭悊澶辫触",
             code: resData.code,
+            duration: 2000,
           });
         }
       },
@@ -53,6 +55,7 @@
         reject({
           message: "缃戠粶璇锋眰澶辫触",
           error,
+          duration: 2000,
         });
       },
     });

--
Gitblit v1.9.3