From 1378fc4cd7abc24ed3a982e09437c2c8a74e9f2f Mon Sep 17 00:00:00 2001
From: 647556386 <647556386@qq.com>
Date: 星期二, 27 一月 2026 19:06:32 +0800
Subject: [PATCH] 代码优化

---
 项目代码/WIDESEA_WMSClient/src/extension/outbound/extend/NoStockOut.vue |  389 ++++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 284 insertions(+), 105 deletions(-)

diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/outbound/extend/NoStockOut.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/outbound/extend/NoStockOut.vue"
index 7e80215..bb63598 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/outbound/extend/NoStockOut.vue"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/outbound/extend/NoStockOut.vue"
@@ -8,6 +8,14 @@
       title="铏氭嫙鍑哄叆搴�"
       class="custom-vol-box"
     >
+      <!-- 鎻愪氦閬僵灞傦細瑕嗙洊鏁翠釜寮圭獥鍐呭鍖哄煙 -->
+      <div class="submit-mask" v-show="submitLoading">
+        <div class="mask-content">
+          <el-loading-spinner class="loading-icon" />
+          <span class="loading-text">姝e湪鎻愪氦鍑哄簱锛岃绋嶅��...</span>
+        </div>
+      </div>
+
       <div>
         <!-- 鍗曟嵁杈撳叆鍖哄煙锛堟敮鎸佹壂鐮侊級 -->
         <el-form 
@@ -23,13 +31,13 @@
               clearable
               style="width: 220px; margin-right: 10px;"
               @input="handleOutboundInput"
-              @keyup.enter="(e) => {
-                e.stopPropagation(); // 闃绘浜嬩欢鍐掓场
-                e.preventDefault(); // 闃绘榛樿琛屼负
-                focusBarcodeInputDirectly();
-              }"
+              @keyup.enter="validateOutboundOrder"
               ref="outboundInputRef"
+              :disabled="loading || submitLoading || isOutboundVerified"
             ></el-input>
+            <!-- 鏂板锛氶獙璇佺姸鎬佹彁绀� -->
+            <span v-if="isOutboundVerified" class="verified-tag">鉁� 宸查獙璇�</span>
+            <span v-else-if="loading" class="loading-tag">鉁� 楠岃瘉涓�...</span>
           </el-form-item>
           <el-form-item label="閲囪喘鍗曟嵁:" name="purchaseOrderNo">
             <el-input
@@ -40,6 +48,7 @@
               @input="handlePurchaseInput"
               readonly
               ref="purchaseInputRef"
+              :disabled="submitLoading"
             ></el-input>
           </el-form-item>
         </el-form>
@@ -56,7 +65,6 @@
             label="鎵弿鏉$爜:"
             style="width: 80%"
             name="barcode"
-            :rules="[{ required: true, message: '璇锋壂鎻忔垨杈撳叆鏉$爜', trigger: 'blur' }]"
           >
             <el-input
               ref="barcodeInputRef"
@@ -65,7 +73,7 @@
               @keydown.enter="debouncedHandleScan" 
               autofocus
               class="custom-input"
-              :disabled="!orderForm.outboundOrderNo || loading"
+              :disabled="!isOutboundVerified || loading || submitLoading"
             ></el-input>
           </el-form-item>
           <el-form-item>
@@ -74,14 +82,14 @@
               size="small" 
               @click="handleScan" 
               class="custom-button"
-              :disabled="!orderForm.outboundOrderNo || loading"
+              :disabled="!isOutboundVerified || loading || submitLoading"
             >
               <Search /> 纭鎵弿
             </el-button>
           </el-form-item>
         </el-form>
 
-        <!-- 涓嬫柟鏄剧ず妗� -->
+        <!-- 涓嬫柟鏄剧ず妗嗭紙鐩存帴娓叉煋鍚庣杩斿洖鐨勬暟缁勶級 -->
         <div class="scan-list">
           <el-card shadow="hover" style="margin-bottom: 10px; border: none;" class="custom-card">
             <div class="card-header">
@@ -90,19 +98,49 @@
             <div class="card-body">
               <el-scrollbar height="400px" class="custom-scrollbar">
                 <transition-group name="barcode-item-transition">
-                  <div class="barcode-item" v-for="(item, index) in scannedBarcodes" :key="item.barcode" :data-index="index">
-                    <span class="barcode-text">{{ index + 1 }}. {{ item.barcode }}</span>
+                  <div class="barcode-item" v-for="(item, index) in scannedBarcodes" :key="`${item.barcode}-${index}`" :data-index="index">
+                    <div class="barcode-detail">
+                      <div class="detail-row">
+                        <span class="label">鏉$爜锛�</span>
+                        <span class="value">{{ item.barcode || '-' }}</span>
+                      </div>
+                      <div class="detail-row">
+                        <span class="label">鐗╂枡缂栫爜锛�</span>
+                        <span class="value">{{ item.materielCode || '-' }}</span>
+                      </div>
+                      <div class="detail-row">
+                        <span class="label">鐗╂枡鍚嶇О锛�</span>
+                        <span class="value">{{ item.materielName || '-' }}</span>
+                      </div>
+                      <div class="detail-row">
+                        <span class="label">鎵规鍙凤細</span>
+                        <span class="value">{{ item.batchNo || '-' }}</span>
+                      </div>
+                      <div class="detail-row">
+                        <span class="label">鏉$爜鏁伴噺锛�</span>
+                        <span class="value">{{ item.orderQuantity || item.quantity || 0 }}</span>
+                      </div>
+                      <div class="detail-row">
+                        <span class="label">渚涘簲鍟嗙紪鐮侊細</span>
+                        <span class="value">{{ item.supplyCode || '-' }}</span>
+                      </div>
+                      <div class="detail-row">
+                        <span class="label">閲囪喘鍗曞彿锛�</span>
+                        <span class="value">{{ item.purchaseOrderNo || '-' }}</span>
+                      </div>
+                    </div>
                     <el-button
                       class="delete-btn"
                       @click="removeItem(index, item.barcode)"
                       icon="Delete"
                       circle
-                      :disabled="loading"
+                      :disabled="loading || submitLoading"
                     ></el-button>
                   </div>
                 </transition-group>
                 <div class="empty-tip" v-if="scannedBarcodes.length === 0">
-                  <span>鏆傛棤鎵弿璁板綍锛岃鍏堣緭鍏ュ嚭搴撳崟鎹悗鎵弿鏉$爜</span>
+                  <span v-if="isOutboundVerified">鏆傛棤鎵弿璁板綍锛岃鎵弿鏉$爜</span>
+                  <span v-else>璇峰厛杈撳叆骞堕獙璇佹湁鏁堢殑鍑哄簱鍗曟嵁鍙�</span>
                 </div>
               </el-scrollbar>
             </div>
@@ -116,7 +154,7 @@
             type="primary" 
             size="small" 
             @click="submit" 
-            :disabled="scannedBarcodes.length === 0 || !orderForm.outboundOrderNo || !orderForm.purchaseOrderNo || loading" 
+            :disabled="scannedBarcodes.length === 0 || !isOutboundVerified || loading || submitLoading" 
             class="submit-btn"
           >
             <Check /> 鎻愪氦鍑哄簱
@@ -130,7 +168,7 @@
               showDetailBox = false;
             }" 
             class="cancel-btn" 
-            :disabled="loading"
+            :disabled="loading || submitLoading"
           >
             鍙栨秷
           </el-button>
@@ -141,7 +179,7 @@
 </template>
 
 <script setup>
-import { ref, reactive, onMounted, nextTick, watch } from 'vue';
+import { ref, reactive, onMounted, nextTick } from 'vue';
 import { ElMessage } from 'element-plus';
 import { Search, Check } from '@element-plus/icons-vue';
 
@@ -159,8 +197,10 @@
 });
 const scannedBarcodes = ref([]);
 const loading = ref(false);
-// 鏂板锛氬瓨鍌ㄩ娆℃壂鎻忕殑閲囪喘鍗曞彿锛堢敤浜庝竴鑷存�ф牎楠岋級
-const firstPurchaseOrderNo = ref(null);
+// 鏂板锛氭彁浜や笓灞瀕oading鐘舵�侊紝鎺у埗閬僵灞傛樉绀�
+const submitLoading = ref(false);
+// 鏍稿績鏂板锛氬嚭搴撳崟楠岃瘉鐘舵�佹爣璇�
+const isOutboundVerified = ref(false);
 
 // 妯℃澘寮曠敤
 const formRef = ref(null);
@@ -175,15 +215,7 @@
   });
 });
 
-// 鐩戝惉鎵弿鍒楄〃锛岃嫢涓虹┖鍒欓噸缃娆¢噰璐崟鍙�
-watch(scannedBarcodes, (newVal) => {
-  if (newVal.length === 0) {
-    firstPurchaseOrderNo.value = null;
-    orderForm.purchaseOrderNo = ""; // 鍚屾娓呯┖閲囪喘鍗曡緭鍏ユ
-  }
-}, { deep: true });
-
-// 绠�鍗曢槻鎶栧嚱鏁帮紙鏃犻渶渚濊禆lodash锛�
+// 绠�鍗曢槻鎶栧嚱鏁�
 const debounce = (fn, delay = 100) => {
   let timer = null;
   return (...args) => {
@@ -201,151 +233,216 @@
   formData.barcode = "";
   orderForm.outboundOrderNo = "";
   orderForm.purchaseOrderNo = "";
-  // 閲嶇疆棣栨閲囪喘鍗曞彿
-  firstPurchaseOrderNo.value = null;
+  submitLoading.value = false; // 鎵撳紑寮圭獥鏃堕噸缃彁浜oading
+  isOutboundVerified.value = false; // 鎵撳紑寮圭獥鏃堕噸缃嚭搴撳崟楠岃瘉鐘舵��
   nextTick(() => {
-    outboundInputRef.value?.focus();
+    outboundInputRef.value?.focus(); // 鎵撳紑寮圭獥浠嶈仛鐒﹀嚭搴撳崟杈撳叆妗�
   });
 };
 
-// 鍑哄簱鍗曡緭鍏ュ鐞嗭紙鎵爜鎴栨墜鍔ㄨ緭鍏ワ級
-const handleOutboundInput = (value) => {
-  if (value && value.trim()) {
-    // 鍑哄簱鍗曞彿鏍煎紡楠岃瘉閫昏緫锛堟寜闇�淇濈暀锛�
+/**
+ * 楠岃瘉鍑哄簱鍗曟嵁鍙风殑鏈夋晥鎬�
+ * 鏍稿績淇敼锛氶獙璇佹垚鍔熷悗鏍囪isOutboundVerified涓簍rue锛屽け璐ュ垯閲嶇疆涓篺alse
+ */
+const validateOutboundOrder = async () => {
+  const outboundOrderNo = orderForm.outboundOrderNo.trim();
+  if (!outboundOrderNo) {
+    ElMessage.warning("璇疯緭鍏ュ嚭搴撳崟鎹彿");
+    return;
+  }
+
+  try {
+    loading.value = true;
+    const res = await http.post(
+      `/api/OutboundPicking/GetAvailablePickingOrders?outOrder=`+ outboundOrderNo,
+      "楠岃瘉鍑哄簱鍗曟嵁鍙蜂腑..."
+    );
+
+    if (res.status !== true) {
+      // 楠岃瘉澶辫触锛氭竻绌鸿緭鍏ユ锛屾彁绀洪敊璇紝閲嶇疆楠岃瘉鐘舵�侊紝鑱氱劍鍥炲嚭搴撳崟杈撳叆妗�
+      orderForm.outboundOrderNo = "";
+      isOutboundVerified.value = false;
+      ElMessage.error(res.message || "鍑哄簱鍗曟嵁鍙烽獙璇佸け璐ワ紝璇锋鏌ュ崟鎹彿鏄惁姝g‘");
+      nextTick(() => {
+        outboundInputRef.value?.focus(); // 澶辫触鑱氱劍鍑哄簱鍗曡緭鍏ユ
+      });
+      return;
+    }
+
+    // 楠岃瘉鎴愬姛锛氭爣璁伴獙璇佺姸鎬佷负true锛屾彁绀虹敤鎴凤紝鑱氱劍鏉$爜鎵弿妗�
+    isOutboundVerified.value = true;
+    ElMessage.success("鍑哄簱鍗曟嵁鍙烽獙璇侀�氳繃");
+    nextTick(() => {
+      barcodeInputRef.value?.focus(); // 鎴愬姛鐩存帴璺宠浆鍒版潯鐮佹壂鎻忔
+    });
+  } catch (error) {
+    // 鎺ュ彛寮傚父锛氭竻绌鸿緭鍏ユ锛屾彁绀洪敊璇紝閲嶇疆楠岃瘉鐘舵�侊紝鑱氱劍鍥炲嚭搴撳崟杈撳叆妗�
+    orderForm.outboundOrderNo = "";
+    isOutboundVerified.value = false;
+    ElMessage.error(`鍑哄簱鍗曟嵁鍙烽獙璇佸紓甯革細${error.message || "缃戠粶閿欒锛岃閲嶈瘯"}`);
+    nextTick(() => {
+      outboundInputRef.value?.focus(); // 寮傚父鑱氱劍鍑哄簱鍗曡緭鍏ユ
+    });
+  } finally {
+    loading.value = false;
   }
 };
 
-// 閲囪喘鍗曡緭鍏ュ鐞嗭紙鎵爜鎴栨墜鍔ㄨ緭鍏ワ級
+// 鍑哄簱鍗曡緭鍏ュ鐞�
+const handleOutboundInput = (value) => {
+  // 鏍稿績淇敼锛氳緭鍏ユ椂鑷姩閲嶇疆楠岃瘉鐘舵�侊紙闃叉鎵嬪姩淇敼宸查獙璇佺殑鍑哄簱鍗曞彿锛�
+  if (value && value.trim()) {
+    isOutboundVerified.value = false;
+  }
+};
+
+// 閲囪喘鍗曡緭鍏ュ鐞�
 const handlePurchaseInput = (value) => {
   if (value && value.trim()) {
-    // 閲囪喘鍗曞彿鏍煎紡楠岃瘉閫昏緫锛堟寜闇�淇濈暀锛�
+    // 鍙繚鐣欓噰璐崟鍙锋牸寮忛獙璇侀�昏緫
   }
 };
 
-// 鐩存帴璺宠浆鍒版潯鐮佽緭鍏ユ锛堟棤闇�鍏堝~閲囪喘鍗曪級
+// 鑱氱劍鏉$爜杈撳叆妗嗭紙澶嶇敤鍑芥暟锛�
 const focusBarcodeInputDirectly = () => {
-  if (orderForm.outboundOrderNo.trim()) {
+  if (isOutboundVerified.value) {
     barcodeInputRef.value?.focus();
   } else {
-    ElMessage.warning("璇峰厛杈撳叆鏈夋晥鐨勫嚭搴撳崟鎹彿");
+    ElMessage.warning("璇峰厛杈撳叆骞堕獙璇佹湁鏁堢殑鍑哄簱鍗曟嵁鍙�");
+    nextTick(() => {
+      outboundInputRef.value?.focus();
+    });
   }
 };
 
 /**
- * 鏍规嵁鏉$爜鏌ヨ閲囪喘鍗曟帴鍙o紙瀹屽叏瀵归綈绀轰緥璇锋眰鏍煎紡锛�
- * @param {string} barcode 鏉$爜
- * @returns {Promise<string>} 閲囪喘鍗曞彿
+ * 鏍规嵁鏉$爜鏌ヨ閲囪喘鍗曞彿
  */
 const getPurchaseOrderByBarcode = async (barcode) => {
-  // 瀹屽叏鎸夌収绀轰緥鏍煎紡锛歶rl鎷兼帴鍙傛暟 + 绗簩涓弬鏁颁紶鎻愮ず鏂囨湰
-  const res = await http.post(`/api/OutboundPicking/GetPurchaseOrderByBarcode?barCode=${encodeURIComponent(barcode)}`, "鏌ヨ閲囪喘鍗曚腑...");
+  const res = await http.post(`/api/OutboundPicking/GetPurchaseOrderByBarcode?barCode=${encodeURIComponent(barcode)}`, "鏌ヨ閲囪喘鍗曞彿涓�...");
 
   if (res.status !== true) {
-    throw new Error(res.message || "鏌ヨ閲囪喘鍗曞け璐�");
+    throw new Error(res.message || "鏌ヨ閲囪喘鍗曞彿澶辫触");
   }
-  if (!res.data?.purchaseOrderNo) {
-    throw new Error("鏈煡璇㈠埌璇ユ潯鐮佸搴旂殑閲囪喘鍗�");
+
+  let purchaseOrderNo = '';
+  if (Array.isArray(res.data) && res.data.length > 0) {
+    purchaseOrderNo = res.data[0].purchaseOrderNo || res.data[0].orderId;
+  } else {
+    purchaseOrderNo = res.data?.purchaseOrderNo || res.data?.orderId;
   }
-  return res.data.purchaseOrderNo;
+
+  return purchaseOrderNo;
 };
 
 // 鎵弿鏉$爜鏍稿績閫昏緫
 const handleScan = async () => {
+  // 鏍稿績鏂板锛氬墠缃牎楠岋紝纭繚鍑哄簱鍗曞凡楠岃瘉
+  if (!isOutboundVerified.value) {
+    ElMessage.warning("璇峰厛楠岃瘉鏈夋晥鐨勫嚭搴撳崟鎹彿鍚庡啀鎵弿鏉$爜");
+    nextTick(() => {
+      outboundInputRef.value?.focus();
+    });
+    return;
+  }
+
   if (!formRef.value) return;
-  // 楠岃瘉鏉$爜蹇呭~
   await formRef.value.validateField('barcode');
 
   const barcode = formData.barcode.trim();
   const outboundOrderNo = orderForm.outboundOrderNo.trim();
 
-  // 妫�鏌ユ潯鐮佹槸鍚﹀凡鎵弿
-  if (scannedBarcodes.value.some(item => item.barcode === barcode)) {
-    ElMessage.warning(`鏉$爜 ${barcode} 宸叉壂鎻忚繃锛岃鍕块噸澶嶆壂鎻廯);
+  // 鏉$爜鍘婚噸
+  const isDuplicate = scannedBarcodes.value.some(item => item.barcode === barcode);
+  if (isDuplicate) {
+    ElMessage.warning(`鏉$爜銆�${barcode}銆戝凡瀛樺湪锛屾棤闇�閲嶅鎵弿`);
     formData.barcode = "";
-    nextTick(() => barcodeInputRef.value?.focus());
+    nextTick(() => barcodeInputRef.value?.focus()); // 鍘婚噸鍚庝粛鑱氱劍鏉$爜妗�
     return;
   }
 
   try {
     loading.value = true;
 
-    // 姝ラ1锛氫粎浼犳潯鐮佹煡璇㈤噰璐崟锛堜娇鐢ㄧず渚嬫牸寮忕殑璇锋眰锛�
+    // 姝ラ1锛氭煡璇㈤噰璐崟鍙�
     const purchaseOrderNo = await getPurchaseOrderByBarcode(barcode);
-
-    // 鏍稿績鏍¢獙锛氶噰璐崟涓�鑷存�ф鏌�
-    if (firstPurchaseOrderNo.value) {
-      // 闈為娆℃壂鎻忥紝鏍¢獙閲囪喘鍗曞彿鏄惁涓�鑷�
-      if (purchaseOrderNo !== firstPurchaseOrderNo.value) {
-        throw new Error(`褰撳墠鏉$爜瀵瑰簲鐨勯噰璐崟銆�${purchaseOrderNo}銆戜笌棣栨鎵弿鐨勯噰璐崟銆�${firstPurchaseOrderNo.value}銆戜笉涓�鑷达紝绂佹鎵弿锛乣);
-      }
+    if (purchaseOrderNo) {
+      orderForm.purchaseOrderNo = purchaseOrderNo;
     } else {
-      // 棣栨鎵弿锛岃褰曢噰璐崟鍙�
-      firstPurchaseOrderNo.value = purchaseOrderNo;
+      ElMessage.info("鏈煡璇㈠埌璇ユ潯鐮佸搴旂殑閲囪喘鍗曞彿锛岀户缁獙璇佹潯鐮佹湁鏁堟��");
+      formData.barcode = "";
+      nextTick(() => barcodeInputRef.value?.focus());
     }
 
-    // 璧嬪�奸噰璐崟鍒拌緭鍏ユ
-    orderForm.purchaseOrderNo = purchaseOrderNo;
-    ElMessage.success(`鎴愬姛鏌ヨ鍒伴噰璐崟锛�${purchaseOrderNo}`);
-
-    // 姝ラ2锛氳皟鐢ㄥ師鏈夋潯鐮侀獙璇佹帴鍙o紙濡傞渶瀵归綈鏍煎紡鍙悓姝ヤ慨鏀癸紝姝ゅ淇濈暀鍘熸湁鏍煎紡锛�
+    // 姝ラ2锛氶獙璇佹潯鐮佸苟鑾峰彇鐗╂枡淇℃伅
     const validateRes = await http.post("/api/OutboundPicking/BarcodeValidate", {
       outOder: outboundOrderNo,
-      inOder: purchaseOrderNo,
+      inOder: purchaseOrderNo || orderForm.purchaseOrderNo,
       barCode: barcode
     });
 
     if (validateRes.status === true) {
-      scannedBarcodes.value.push({ barcode });
-      ElMessage.success("鎵弿鎴愬姛");
-      formData.barcode = "";
+      if (!Array.isArray(validateRes.data) || validateRes.data.length === 0) {
+        ElMessage.warning("璇ユ潯鐮侀獙璇佹垚鍔燂紝浣嗘湭杩斿洖鐗╂枡淇℃伅");
+        formData.barcode = "";
+        nextTick(() => barcodeInputRef.value?.focus());
+      } else {
+        const newItems = validateRes.data.map(item => ({
+          barcode: item.barcode || '',
+          materielCode: item.materielCode || '',
+          materielName: item.materielName || '',
+          batchNo: item.batchNo || '',
+          orderQuantity: item.orderQuantity || item.quantity || 0,
+          supplyCode: item.supplyCode || '',
+          purchaseOrderNo: purchaseOrderNo || ''
+        }));
+        scannedBarcodes.value.push(...newItems);
+        ElMessage.success(`鎵弿鎴愬姛锛屾柊澧� ${newItems.length} 鏉$墿鏂欎俊鎭紝绱 ${scannedBarcodes.value.length} 鏉);
+        formData.barcode = "";
+      }
     } else {
       ElMessage.error("鎵弿澶辫触锛�" + (validateRes.message || '鏉$爜楠岃瘉澶辫触'));
+      formData.barcode = "";
+      nextTick(() => barcodeInputRef.value?.focus());
     }
   } catch (error) {
-    // 鎹曡幏閲囪喘鍗曚笉涓�鑷寸瓑閿欒骞舵彁绀�
     ElMessage.error(error.message);
-    // 娓呯┖褰撳墠杈撳叆妗嗭紝鑱氱劍鏉$爜杈撳叆妗�
     formData.barcode = "";
     nextTick(() => barcodeInputRef.value?.focus());
   } finally {
     loading.value = false;
-    // 寮哄埗鑱氱劍鏉$爜杈撳叆妗嗭紝閬垮厤鐒︾偣璺冲埌寮圭獥澶�
+    // 鎵弿瀹屾垚鍚庡缁堣仛鐒︽潯鐮佽緭鍏ユ锛堟柟渚胯繛缁壂鎻忥級
     nextTick(() => {
-      if (barcodeInputRef.value) {
-        barcodeInputRef.value.focus();
-        // 娓呯┖杈撳叆妗嗛�変腑鐘舵�侊紙鎵爜鏋彲鑳芥畫鐣欓�変腑锛�
-        if (barcodeInputRef.value.input) {
-          barcodeInputRef.value.input.select = () => {};
-        }
+      barcodeInputRef.value?.focus();
+      if (barcodeInputRef.value?.input) {
+        barcodeInputRef.value.input.select = () => {};
       }
     });
   }
 };
 
-// 甯﹂槻鎶栧拰浜嬩欢鎷︽埅鐨勬壂鎻忓鐞嗭紙閫傞厤鎵爜鏋級
+// 甯﹂槻鎶栫殑鎵弿澶勭悊
 const debouncedHandleScan = debounce(async (e) => {
-  // 闃绘浜嬩欢鍐掓场鍜岄粯璁よ涓�
   e.stopPropagation();
   e.preventDefault();
   await handleScan();
 }, 100);
 
-// 绉婚櫎鍗曟潯鎵弿璁板綍
+// 绉婚櫎鍗曟潯璁板綍
 const removeItem = async (index, barcode) => {
   try {
     loading.value = true;
+    const currentItem = scannedBarcodes.value[index];
     const res = await http.post("/api/OutboundPicking/DeleteBarcode", {
       outOder: orderForm.outboundOrderNo,
-      inOder: orderForm.purchaseOrderNo,
+      inOder: currentItem?.purchaseOrderNo || orderForm.purchaseOrderNo,
       barCode: barcode
     });
 
     if (res.status === true) {
       scannedBarcodes.value.splice(index, 1);
       ElMessage.success("鍒犻櫎鎴愬姛");
-      // 鑻ュ垹闄ゅ悗鏃犳潯鐮侊紝鑷姩閲嶇疆棣栨閲囪喘鍗曞彿鍜岄噰璐崟杈撳叆妗�
       if (scannedBarcodes.value.length === 0) {
-        firstPurchaseOrderNo.value = null;
         orderForm.purchaseOrderNo = "";
       }
     } else {
@@ -355,38 +452,56 @@
     ElMessage.error("鍒犻櫎鏉$爜寮傚父锛�" + error.message);
   } finally {
     loading.value = false;
+    // 鍒犻櫎鍚庝粛鑱氱劍鏉$爜杈撳叆妗�
+    nextTick(() => barcodeInputRef.value?.focus());
   }
 };
 
 // 鎻愪氦鍑哄簱
 const submit = async () => {
+  // 鏍稿績鏂板锛氬墠缃牎楠屽嚭搴撳崟楠岃瘉鐘舵��
+  if (!isOutboundVerified.value) {
+    ElMessage.warning("鍑哄簱鍗曟嵁鍙锋湭楠岃瘉锛屾棤娉曟彁浜�");
+    nextTick(() => {
+      outboundInputRef.value?.focus();
+    });
+    return;
+  }
+
   if (scannedBarcodes.value.length === 0) {
     ElMessage.warning("璇峰厛鎵弿鑷冲皯涓�鏉℃潯鐮�");
+    nextTick(() => barcodeInputRef.value?.focus());
     return;
   }
 
   const barcodes = scannedBarcodes.value.map(item => item.barcode);
+  const purchaseOrderNos = [...new Set(scannedBarcodes.value.map(item => item.purchaseOrderNo).filter(Boolean))];
 
   try {
-    loading.value = true;
+    // 寮�鍚彁浜oading锛屾樉绀洪伄缃╁眰
+    submitLoading.value = true;
     const res = await http.post("/api/OutboundPicking/NoStockOutSubmit", {
       OutOderSubmit: orderForm.outboundOrderNo,
-      InOderSubmit: orderForm.purchaseOrderNo,
+      InOderSubmit: purchaseOrderNos.join(',') || '',
       BarCodeSubmit: barcodes
     });
 
     if (res.status === true) {
       ElMessage.success("鍑哄簱鎻愪氦鎴愬姛");
       showDetailBox.value = false;
-      // 鎻愪氦鎴愬姛鍚庨噸缃姸鎬�
-      firstPurchaseOrderNo.value = null;
       scannedBarcodes.value = [];
+      orderForm.purchaseOrderNo = "";
+      isOutboundVerified.value = false; // 鎻愪氦鎴愬姛鍚庨噸缃獙璇佺姸鎬�
     } else {
       ElMessage.error("鍑哄簱鎻愪氦澶辫触锛�" + (res.message || '鎻愪氦澶辫触'));
+      nextTick(() => barcodeInputRef.value?.focus());
     }
   } catch (error) {
     ElMessage.error("鍑哄簱鎻愪氦寮傚父锛�" + error.message);
+    nextTick(() => barcodeInputRef.value?.focus());
   } finally {
+    // 鍏抽棴鎻愪氦loading锛岄殣钘忛伄缃╁眰
+    submitLoading.value = false;
     loading.value = false;
   }
 };
@@ -398,7 +513,7 @@
 </script>
 
 <style scoped>
-/* 鍏抽敭锛氬畾涔夊垪琛ㄩ」鐨勮繃娓″姩鐢� */
+/*杩囨浮鍔ㄧ敾 */
 .barcode-item-transition-enter-active,
 .barcode-item-transition-leave-active {
   transition: all 0.3s ease;
@@ -411,9 +526,54 @@
   opacity: 0;
   transform: translateX(30px);
 }
-/* 纭繚鍒犻櫎鏃跺叾浠栧厓绱犲钩婊戜笂绉� */
 .barcode-item-transition-move {
   transition: transform 1s ease;
+}
+
+/* 鏂板锛氭彁浜ら伄缃╁眰鏍峰紡 */
+.submit-mask {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background-color: rgba(255, 255, 255, 0.85);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  z-index: 100;
+  border-radius: inherit;
+}
+.mask-content {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  gap: 12px;
+  color: #409eff;
+  font-size: 15px;
+}
+.loading-icon {
+  font-size: 24px;
+  animation: el-loading-circle 1.5s linear infinite;
+}
+
+/* 鏂板锛氶獙璇佺姸鎬佹爣绛炬牱寮� */
+.verified-tag {
+  color: #67c23a;
+  font-size: 12px;
+  margin-left: 8px;
+  font-weight: 500;
+}
+.loading-tag {
+  color: #409eff;
+  font-size: 12px;
+  margin-left: 8px;
+  font-weight: 500;
+  animation: spin 1s linear infinite;
+}
+@keyframes spin {
+  0% { transform: rotate(0deg); }
+  100% { transform: rotate(360deg); }
 }
 
 .scan-list {
@@ -447,7 +607,6 @@
   padding: 0;
 }
 
-/* 鑷畾涔夋粴鍔ㄦ潯 */
 .custom-scrollbar :deep(.el-scrollbar__thumb) {
   background: rgba(0, 0, 0, 0.2);
   border-radius: 4px;
@@ -464,26 +623,47 @@
 .barcode-item {
   display: flex;
   justify-content: space-between;
-  align-items: center;
-  padding: 10px 15px;
+  align-items: flex-start;
+  padding: 15px;
   border-bottom: 1px solid #f7f7f7;
   transition: background-color 0.2s ease;
 }
 .barcode-item:hover {
   background-color: #fafafa;
 }
-/* 涓哄鏁拌娣诲姞杞诲井鐨勮儗鏅壊锛屽寮哄彲璇绘�� */
 .barcode-item:nth-child(odd) {
   background-color: #f9f9f9;
 }
-.barcode-text {
+.barcode-detail {
   flex: 1;
+  display: grid;
+  grid-template-columns: repeat(4, 1fr);
+  gap: 8px 15px;
   font-size: 14px;
-  color: #666;
-  transition: color 0.2s;
 }
-.barcode-item:hover .barcode-text {
-  color: #409eff;
+@media (max-width: 1200px) {
+  .barcode-detail {
+    grid-template-columns: repeat(3, 1fr);
+  }
+}
+@media (max-width: 992px) {
+  .barcode-detail {
+    grid-template-columns: repeat(2, 1fr);
+  }
+}
+.detail-row {
+  display: flex;
+  align-items: center;
+}
+.label {
+  color: #999;
+  margin-right: 5px;
+  white-space: nowrap;
+}
+.value {
+  color: #666;
+  flex: 1;
+  word-break: break-all;
 }
 
 .delete-btn {
@@ -491,6 +671,8 @@
   font-size: 16px;
   transition: all 0.2s;
   opacity: 0.7;
+  margin-left: 10px;
+  flex-shrink: 0;
 }
 .barcode-item:hover .delete-btn {
   opacity: 1;
@@ -516,7 +698,6 @@
   color: #dcdfe6;
 }
 
-/* 鑷畾涔夎緭鍏ユ */
 .custom-input :deep(.el-input__inner) {
   border-radius: 6px;
   border-color: #e4e7ed;
@@ -529,7 +710,6 @@
   box-shadow: 0 0 0 3px rgba(64, 158, 255, 0.1);
 }
 
-/* 鑷畾涔夋寜閽� */
 .custom-button {
   border-radius: 6px;
   height: 36px;
@@ -568,7 +748,6 @@
 </style>
 
 <style>
-/* 鍏ㄥ眬鏍峰紡閮ㄥ垎淇濇寔涓嶅彉 */
 .text-button:hover {
   background-color: #f0f9eb !important;
 }

--
Gitblit v1.9.3