|  |  | 
 |  |  | <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> | 
 |  |  |  | 
 
 |  |  | 
 |  |  |       data: data, | 
 |  |  |     }); | 
 |  |  |   }, | 
 |  |  |  | 
 |  |  |   // éªè¯äºç»´ç  | 
 |  |  |   assertScanQR(params: { deviceUid: string }) { | 
 |  |  |     return request<BaseResult<any>>({ | 
 |  |  |       url: "/wireInspection/assertScanQR?deviceUid=" + params.deviceUid, | 
 |  |  |       method: "GET", | 
 |  |  |     }); | 
 |  |  |   }, | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | export default RoutingInspectionApi; | 
 
| ¶Ô±ÈÐÂÎļþ | 
 |  |  | 
 |  |  | 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); | 
 |  |  |     } | 
 |  |  |   }; | 
 |  |  |  | 
 |  |  |   /** | 
 |  |  |    * éªè¯äºç»´ç ï¼ä»
è°ç¨æ¥å£ï¼ä¸å¤çè¿åç»æï¼ | 
 |  |  |    */ | 
 |  |  |   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] è§£æåç对象:", codeObj); | 
 |  |  |       } catch (err) { | 
 |  |  |         console.error("[useScanCode] JSON è§£æå¤±è´¥:", 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ï¼è°ç¨éªè¯æ¥å£ï¼ä¸çå¾
ç»æï¼ | 
 |  |  |       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, | 
 |  |  |   }; | 
 |  |  | } | 
 
 |  |  | 
 |  |  |         ä¿å | 
 |  |  |       </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> | 
 |  |  | 
 |  |  |         <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> | 
 |  |  | 
 |  |  |         </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") }} | 
 |  |  | 
 |  |  |       <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) }} | 
 |  |  | 
 |  |  |         <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(""); | 
 |  |  | 
 |  |  | 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: [], // ç»çº¿å·¥èºè´¨éæ§å¶ | 
 |  |  | 
 |  |  |   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 || []) | 
 |  |  | 
 |  |  |     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(); // æ°æ®è¿åååå§å表å | 
 |  |  | 
 |  |  | 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" }); | 
 |  |  | 
 |  |  |     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]; | 
 |  |  | 
 |  |  |       deviceUid: deviceUid.value, | 
 |  |  |       id: paramsId.value, | 
 |  |  |       result: { | 
 |  |  |         twistDiameter: formData.twistDiameter, | 
 |  |  |         twistedOuterDiameter: formData.twistedOuterDiameter, | 
 |  |  |         structureFormula: formData.structureFormula, | 
 |  |  |         structureItems: formData.structureItems, | 
 |  |  |         inspectTwist: formData.inspectTwist, | 
 |  |  | 
 |  |  |     }); | 
 |  |  |  | 
 |  |  |     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" }); | 
 |  |  |     } | 
 |  |  | 
 |  |  |     case 1: | 
 |  |  |       return "danger"; // å·²é©³å | 
 |  |  |     case 2: | 
 |  |  |       return "info"; // å¾
审核 | 
 |  |  |       return "primary"; // å¾
审核 | 
 |  |  |     case 3: | 
 |  |  |       return "success"; // éè¿ | 
 |  |  |     default: | 
 |  |  |       return "info"; | 
 |  |  |       return "default"; | 
 |  |  |   } | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | 
 |  |  |   }); | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | const openScan = () => { | 
 |  |  |   scanRef.value.triggerScan(); | 
 |  |  | // è®¡ç®è徿¯ | 
 |  |  | const calculatePitchRatio = (pitch: string, dia: string) => { | 
 |  |  |   // å¦æpitchædia为空ï¼åè¿å"-" | 
 |  |  |   if (!pitch || !dia) return "-"; | 
 |  |  |  | 
 |  |  |   // å°pitchådia转æ¢ä¸ºæµ®ç¹æ° | 
 |  |  |   const pitchNum = parseFloat(pitch); | 
 |  |  |   const diaNum = parseFloat(dia); | 
 |  |  |  | 
 |  |  |   // å¦æpitchNumædiaNumæ¯NaNï¼æè
diaNum为0ï¼åè¿å"-" | 
 |  |  |   if (isNaN(pitchNum) || isNaN(diaNum) || diaNum === 0) return "-"; | 
 |  |  |  | 
 |  |  |   // è®¡ç®pitchNumådiaNumçæ¯å¼ï¼å¹¶ä¿ç两ä½å°æ° | 
 |  |  |   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è§£æå¤±è´¥ï¼", 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(); | 
 |  |  |   // å è½½ç¼åï¼æ´æ°UIæ¾ç¤ºï¼ | 
 |  |  |   const cachedData = loadFromCache(); | 
 |  |  |  | 
 |  |  |   // å¦ææ²¡æç¼åæ°æ®ï¼æç¤ºç¨æ·éè¦æ«ç  | 
 |  |  |   if (!cachedData || !cachedData.uid) { | 
 |  |  |     console.log("â ï¸ æªæ£æµå°æ«ç ç¼åï¼ç¨æ·éè¦æ«æè®¾å¤äºç»´ç "); | 
 |  |  |     // å¨ç¼è¾æ¨¡å¼ä¸ææç¤º | 
 |  |  |     if (isEdit.value) { | 
 |  |  |       setTimeout(() => { | 
 |  |  |         uni.showToast({ | 
 |  |  |           title: "è¯·æ«æè®¾å¤äºç»´ç ååä¿å", | 
 |  |  |           icon: "none", | 
 |  |  |           duration: 2000, | 
 |  |  |         }); | 
 |  |  |       }, 500); | 
 |  |  |     } | 
 |  |  |   } | 
 |  |  | }); | 
 |  |  | </script> | 
 |  |  |  | 
 |  |  | 
 |  |  |   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; | 
 
 |  |  | 
 |  |  |         ä¿å | 
 |  |  |       </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> | 
 |  |  | 
 |  |  |  | 
 |  |  |         <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) }} | 
 |  |  | 
 |  |  |         <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(""); | 
 |  |  | 
 |  |  | 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: "", | 
 |  |  | 
 |  |  |     case 1: | 
 |  |  |       return "danger"; | 
 |  |  |     case 2: | 
 |  |  |       return "info"; | 
 |  |  |       return "primary"; | 
 |  |  |     case 3: | 
 |  |  |       return "success"; | 
 |  |  |     default: | 
 |  |  |       return "info"; | 
 |  |  |       return "default"; | 
 |  |  |   } | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | 
 |  |  |  | 
 |  |  | // æ ¼å¼åå·¥å
· | 
 |  |  | 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) => { | 
 |  |  | 
 |  |  |   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 || ""; | 
 |  |  | 
 |  |  |   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) { | 
 |  |  | 
 |  |  |     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]; | 
 |  |  | 
 |  |  |       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" }); | 
 |  |  |     } | 
 |  |  | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | 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; // è§£æå¤±è´¥ç´æ¥è¿åï¼é¿å
åç»é误 | 
 |  |  |  | 
 |  |  | // é¡µé¢æ¾ç¤ºæ¶çå¤ç | 
 |  |  | onShow(() => { | 
 |  |  |   console.log("========== indexLS - onShow è§¦å =========="); | 
 |  |  |   // éæ°å¯ç¨çå¬å¨ï¼ç¡®ä¿çå¬å¨ææï¼ | 
 |  |  |   enableListener(); | 
 |  |  |   // å è½½ç¼åï¼æ´æ°UIæ¾ç¤ºï¼ | 
 |  |  |   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> | 
 |  |  |  | 
 |  |  | 
 |  |  |  | 
 |  |  | .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 { | 
 |  |  | 
 |  |  |   align-items: flex-start; // åç´æ¹åé¡¶é¨å¯¹é½ï¼ä¸ç§»å
³é®ï¼ | 
 |  |  |   gap: 20rpx; // é项ä¹é´çé´è· | 
 |  |  | } | 
 |  |  | </style> | 
 |  |  | </style> | 
 
 |  |  | 
 |  |  |   <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"> | 
 |  |  | 
 |  |  |         :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) => { | 
 |  |  |   // å¯ä»¥å¨è¿éæ´æ°ç¹å®å·¡æ£è®¾å¤çå¾
æ£æ¥æ°é | 
 |  |  |   // ä¾å¦ï¼patrolList.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ä¸çä¿¡æ¯è°ç¨ç¸åºçæ¥å£è·å详æ
 | 
 |  |  |     // è¿åçæ°æ®æ ¼å¼éè¦ä¸ProductListç»ä»¶ææçæ ¼å¼ä¸è´ | 
 |  |  |     return { | 
 |  |  |       code: 200, | 
 |  |  |       data: { | 
 |  |  |         type: "å·¡æ£", | 
 |  |  |         data: { | 
 |  |  |           total: 0, | 
 |  |  |           records: [], | 
 |  |  |         }, | 
 |  |  |       }, | 
 |  |  |     }; | 
 |  |  |   }; | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | // è·åå·¡æ£è®¾å¤å表 | 
 |  |  | 
 |  |  |   } | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | // ç¡®ä¿å
ç§»é¤åæ·»å çå¬ | 
 |  |  | 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(); | 
 |  |  |   // å è½½ç¼åï¼æ´æ°UIæ¾ç¤ºï¼ | 
 |  |  |   loadFromCache(); | 
 |  |  |  | 
 |  |  |   // æ£æ¥æ¯å¦éè¦å·æ°å表ï¼åªææäº¤æååæå·æ°ï¼ | 
 |  |  |   const needRefresh = uni.getStorageSync("needRefreshInspectionList"); | 
 |  |  |   if (needRefresh) { | 
 |  |  |     console.log("æ£æµå°éè¦å·æ°å表ï¼å¼å§å·æ°..."); | 
 |  |  |     // éæ°å è½½å·¡æ£è®¾å¤å表ï¼å·æ°å¾
æ£æ¥æ°éï¼ | 
 |  |  |     loadPatrolList(); | 
 |  |  |     // å¼ºå¶å·æ° ProductList ç»ä»¶ | 
 |  |  |     searchKey.value++; | 
 |  |  |     // æ¸
é¤å·æ°æ è®° | 
 |  |  |     uni.removeStorageSync("needRefreshInspectionList"); | 
 |  |  |   } | 
 |  |  | }); | 
 |  |  | </script> | 
 |  |  |  | 
 |  |  | 
 |  |  | .statistics_box { | 
 |  |  |   margin: 15px; | 
 |  |  | } | 
 |  |  | </style> | 
 |  |  | </style> | 
 
 |  |  | 
 |  |  | <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> | 
 |  |  | .card_box { | 
 |  |  |   height: calc(100vh - 120px); | 
 |  |  | } | 
 |  |  | </style> | 
 
 |  |  | 
 |  |  |   <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"> | 
 |  |  | 
 |  |  |           </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> | 
 |  |  | 
 |  |  | .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%); | 
 |  |  |     } | 
 |  |  |   } | 
 |  |  | 
 |  |  | .content { | 
 |  |  |   padding: 5px; | 
 |  |  | } | 
 |  |  | </style> | 
 |  |  | </style> | 
 
 |  |  | 
 |  |  |     <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> | 
 |  |  | 
 |  |  |           <!-- è§é¢é¢è§ --> | 
 |  |  |           <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> | 
 |  |  | 
 |  |  | </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 ä½ä¸ºä»£çè·¯å¾ï¼å
¶ä»å¹³å°ä½¿ç¨ 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({ | 
 |  |  | 
 |  |  | }); | 
 |  |  |  | 
 |  |  | 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ï¼http æ 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]; | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | // æ°å¢éä»¶ | 
 |  |  | 
 |  |  |  | 
 |  |  |   .attachment-card { | 
 |  |  |     width: 100%; | 
 |  |  |     aspect-ratio: 1; | 
 |  |  |     position: relative; | 
 |  |  |  | 
 |  |  |     // ä½¿ç¨ padding-top å®ç°æ£æ¹å½¢ï¼å
¼å®¹æ§æ´å¥½ï¼ | 
 |  |  |     &::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; | 
 |  |  | 
 |  |  |     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 { | 
 |  |  | 
 |  |  |         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 { | 
 
 |  |  | 
 |  |  |           uni.showToast({ | 
 |  |  |             title: resData.msg || "ä¸å¡å¤ç失败", | 
 |  |  |             icon: "none", | 
 |  |  |             duration: 2000, | 
 |  |  |           }); | 
 |  |  |           reject({ | 
 |  |  |             message: resData.msg || "ä¸å¡å¤ç失败", | 
 |  |  |             code: resData.code, | 
 |  |  |             duration: 2000, | 
 |  |  |           }); | 
 |  |  |         } | 
 |  |  |       }, | 
 |  |  | 
 |  |  |         reject({ | 
 |  |  |           message: "ç½ç»è¯·æ±å¤±è´¥", | 
 |  |  |           error, | 
 |  |  |           duration: 2000, | 
 |  |  |         }); | 
 |  |  |       }, | 
 |  |  |     }); |