From a81155c4a46848b6a54352dd169a7af308d7cad3 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期四, 20 八月 2026 11:41:00 +0800
Subject: [PATCH] 天津-阳光彩印 1.发货模块改造:部分发货 + 批量发货 + 解除完工限制

---
 src/views/salesManagement/salesLedger/index.vue |  241 +++++++++++++++++++++++++++++++++++++----------
 1 files changed, 187 insertions(+), 54 deletions(-)

diff --git a/src/views/salesManagement/salesLedger/index.vue b/src/views/salesManagement/salesLedger/index.vue
index 7bb01c6..d35f68f 100644
--- a/src/views/salesManagement/salesLedger/index.vue
+++ b/src/views/salesManagement/salesLedger/index.vue
@@ -57,6 +57,10 @@
           <el-button type="primary"
                      plain
                      @click="handlePrint">鎵撳嵃</el-button>
+          <el-button type="primary"
+                     plain
+                     :disabled="selectedRows.length === 0"
+                     @click="handleBatchShipping">鎵归噺鍙戣揣</el-button>
         </div>
       </div>
       <el-table :data="tableData"
@@ -872,16 +876,15 @@
                ref="deliveryFormRef">
         <el-row :gutter="30">
           <el-col :span="24">
-            <el-form-item label="鍙戣揣绫诲瀷锛�"
-                          prop="type">
-              <el-select v-model="deliveryForm.type"
-                         placeholder="璇烽�夋嫨鍙戣揣绫诲瀷"
-                         style="width: 100%">
-                <el-option label="璐ц溅"
-                           value="璐ц溅" />
-                <el-option label="蹇��"
-                           value="蹇��" />
-              </el-select>
+            <el-form-item label="鏈鍙戣揣鏁伴噺锛�"
+                          prop="quantity">
+              <el-input-number v-model="deliveryForm.quantity"
+                               :min="0.01"
+                               :max="Number(deliveryForm.unshippedQuantity)"
+                               :precision="2"
+                               placeholder="璇疯緭鍏ユ湰娆″彂璐ф暟閲�"
+                               style="width: 100%" />
+              <span style="margin-left: 8px; color: #909399;">鍓╀綑鍙彂锛歿{ deliveryForm.unshippedQuantity }}</span>
             </el-form-item>
           </el-col>
         </el-row>
@@ -894,6 +897,39 @@
         </div>
       </template>
     </el-dialog>
+    <!-- 鎵归噺鍙戣揣寮规 -->
+    <el-dialog v-model="batchShippingOpen"
+               title="鎵归噺鍙戣揣"
+               width="60%"
+               @close="closeBatchShipping">
+      <el-table :data="batchShippingRows"
+                border>
+        <el-table-column label="浜у搧澶х被"
+                         prop="productCategory" />
+        <el-table-column label="瑙勬牸鍨嬪彿"
+                         prop="specificationModel" />
+        <el-table-column label="璁㈠崟鏁伴噺"
+                         prop="quantity" />
+        <el-table-column label="鍓╀綑鍙彂"
+                         prop="unshippedQuantity" />
+        <el-table-column label="鏈鍙戣揣鏁伴噺">
+          <template #default="scope">
+            <el-input-number v-model="scope.row.shipQuantity"
+                             :min="0.01"
+                             :max="Number(scope.row.unshippedQuantity)"
+                             :precision="2"
+                             size="small" />
+          </template>
+        </el-table-column>
+      </el-table>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary"
+                     @click="submitBatchShipping">纭鍙戣揣</el-button>
+          <el-button @click="closeBatchShipping">鍙栨秷</el-button>
+        </div>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
@@ -901,7 +937,7 @@
   import { getToken } from "@/utils/auth";
   import pagination from "@/components/PIMTable/Pagination.vue";
   import { onMounted, ref, getCurrentInstance } from "vue";
-  import { addShippingInfo } from "@/api/salesManagement/deliveryLedger.js";
+  import { addShippingInfo, batchAdd } from "@/api/salesManagement/deliveryLedger.js";
   import { ElMessageBox, ElMessage } from "element-plus";
   import { UploadFilled, Download } from "@element-plus/icons-vue";
   import useUserStore from "@/store/modules/user";
@@ -1052,13 +1088,23 @@
   const currentDeliveryRow = ref(null);
   const deliveryFormData = reactive({
     deliveryForm: {
-      type: "璐ц溅", // 璐ц溅, 蹇��
+      salesLedgerProductId: null,
+      salesLedgerId: null,
+      quantity: null, // 鏈鍙戣揣鏁伴噺
+      unshippedQuantity: 0, // 鍓╀綑鍙彂鏁伴噺锛堟墦寮�寮圭獥鏃惰祴鍊硷級
+      type: "閮ㄥ垎鍙戣揣",
+      approveUserIds: [],
+      tempFileIds: [],
     },
     deliveryRules: {
-      type: [{ required: true, message: "璇烽�夋嫨鍙戣揣绫诲瀷", trigger: "change" }],
+      quantity: [{ required: true, message: "璇疯緭鍏ユ湰娆″彂璐ф暟閲�", trigger: "blur" }],
     },
   });
   const { deliveryForm, deliveryRules } = toRefs(deliveryFormData);
+
+  // 鎵归噺鍙戣揣鐩稿叧
+  const batchShippingOpen = ref(false);
+  const batchShippingRows = ref([]);
 
   // 瀵煎叆鐩稿叧
   const importUploadRef = ref(null);
@@ -2516,20 +2562,23 @@
    * @param row 琛屾暟鎹�
    */
   const canShip = row => {
-    if (!row || !row.hasStockInventory) {
+    if (!row) {
       return false;
     }
-
-    // 鑾峰彇鍙戣揣鐘舵��
-    const shippingStatus = row.shippingStatus;
 
     // 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屼笉鑳藉啀娆″彂璐�
     if (row.shippingDate || row.shippingCarNumber) {
       return false;
     }
 
+    // 浠呴渶瀛樺湪鍓╀綑鍙彂鏁伴噺锛堜笉鍐嶈姹傛湁搴撳瓨璁板綍/宸插畬宸ワ級
+    const qty = Number(row.unshippedQuantity);
+    if (!qty || qty <= 0) {
+      return false;
+    }
+
     // 鍙戣揣鐘舵�佸繀椤绘槸"寰呭彂璐�"鎴�"瀹℃牳鎷掔粷"
-    const statusStr = shippingStatus ? String(shippingStatus).trim() : "";
+    const statusStr = row.shippingStatus ? String(row.shippingStatus).trim() : "";
     return statusStr === "寰呭彂璐�" || statusStr === "瀹℃牳鎷掔粷";
   };
 
@@ -2581,55 +2630,70 @@
     // 妫�鏌ユ槸鍚﹀彲浠ュ彂璐�
     if (!canShip(row)) {
       proxy.$modal.msgWarning(
-        "鍙湁鍦ㄤ骇鍝佹湁搴撳瓨鏁伴噺锛屽彂璐х姸鎬佹槸寰呭彂璐ф垨瀹℃牳鎷掔粷鐨勬椂鍊欐墠鍙互鍙戣揣"
+        "鍙湁瀛樺湪鍓╀綑鍙彂鏁伴噺涓斿彂璐х姸鎬佷负寰呭彂璐ф垨瀹℃牳鎷掔粷鐨勬椂鍊欐墠鍙互鍙戣揣"
       );
       return;
     }
 
     currentDeliveryRow.value = row;
     deliveryForm.value = {
-      type: "璐ц溅",
+      salesLedgerProductId: row.id,
+      salesLedgerId: row.salesLedgerId,
+      quantity: row.unshippedQuantity, // 榛樿鍙栧墿浣欏彲鍙戞暟閲�
+      unshippedQuantity: row.unshippedQuantity,
+      type: "閮ㄥ垎鍙戣揣",
+      approveUserIds: [],
+      tempFileIds: [],
     };
     deliveryFormVisible.value = true;
   };
 
   // 鎻愪氦鍙戣揣琛ㄥ崟
   const submitDelivery = () => {
-    proxy.$refs["deliveryFormRef"].validate(valid => {
-      if (valid) {
-        // 淇濆瓨褰撳墠灞曞紑鐨勮ID锛屼互渚垮彂璐у悗閲嶆柊鍔犺浇瀛愯〃鏍兼暟鎹�
-        const currentExpandedKeys = [...expandedRowKeys.value];
-        const salesLedgerId = currentDeliveryRow.value.salesLedgerId;
-        addShippingInfo({
-          salesLedgerId: salesLedgerId,
-          salesLedgerProductId: currentDeliveryRow.value.id,
-          type: deliveryForm.value.type,
-        }).then(() => {
-          proxy.$modal.msgSuccess("鍙戣揣鎴愬姛");
-          closeDeliveryDia();
-          // 鍒锋柊涓昏〃鏁版嵁
-          getList().then(() => {
-            // 濡傛灉涔嬪墠鏈夊睍寮�鐨勮锛岄噸鏂板姞杞借繖浜涜鐨勫瓙琛ㄦ牸鏁版嵁
-            if (currentExpandedKeys.length > 0) {
-              // 浣跨敤 Promise.all 骞惰鍔犺浇鎵�鏈夊睍寮�琛岀殑瀛愯〃鏍兼暟鎹�
-              const loadPromises = currentExpandedKeys.map(ledgerId => {
-                return productList({ salesLedgerId: ledgerId, type: 1 }).then(
-                  res => {
-                    const index = tableData.value.findIndex(
-                      item => item.id === ledgerId
-                    );
-                    if (index > -1) {
-                      tableData.value[index].children = res.data;
-                    }
+    const qty = Number(deliveryForm.value.quantity);
+    if (!qty || qty <= 0) {
+      proxy.$modal.msgError("鏈鍙戣揣鏁伴噺蹇呴』澶т簬 0");
+      return;
+    }
+    if (qty > Number(deliveryForm.value.unshippedQuantity)) {
+      proxy.$modal.msgError("鏈鍙戣揣鏁伴噺涓嶈兘瓒呰繃鍓╀綑鍙彂鏁伴噺");
+      return;
+    }
+    // 淇濆瓨褰撳墠灞曞紑鐨勮ID锛屼互渚垮彂璐у悗閲嶆柊鍔犺浇瀛愯〃鏍兼暟鎹�
+    const currentExpandedKeys = [...expandedRowKeys.value];
+    addShippingInfo({
+      salesLedgerId: deliveryForm.value.salesLedgerId,
+      salesLedgerProductId: deliveryForm.value.salesLedgerProductId,
+      quantity: qty,
+      type: deliveryForm.value.type,
+      approveUserIds: deliveryForm.value.approveUserIds,
+      tempFileIds: deliveryForm.value.tempFileIds,
+    }).then(res => {
+      if (res.code === 200) {
+        proxy.$modal.msgSuccess("鍙戣揣鎴愬姛锛屽凡鍙戣捣瀹℃壒");
+        closeDeliveryDia();
+        // 鍒锋柊涓昏〃鏁版嵁
+        getList().then(() => {
+          // 濡傛灉涔嬪墠鏈夊睍寮�鐨勮锛岄噸鏂板姞杞借繖浜涜鐨勫瓙琛ㄦ牸鏁版嵁
+          if (currentExpandedKeys.length > 0) {
+            // 浣跨敤 Promise.all 骞惰鍔犺浇鎵�鏈夊睍寮�琛岀殑瀛愯〃鏍兼暟鎹�
+            const loadPromises = currentExpandedKeys.map(ledgerId => {
+              return productList({ salesLedgerId: ledgerId, type: 1 }).then(
+                res => {
+                  const index = tableData.value.findIndex(
+                    item => item.id === ledgerId
+                  );
+                  if (index > -1) {
+                    tableData.value[index].children = res.data;
                   }
-                );
-              });
-              Promise.all(loadPromises).then(() => {
-                // 鎭㈠灞曞紑鐘舵��
-                expandedRowKeys.value = currentExpandedKeys;
-              });
-            }
-          });
+                }
+              );
+            });
+            Promise.all(loadPromises).then(() => {
+              // 鎭㈠灞曞紑鐘舵��
+              expandedRowKeys.value = currentExpandedKeys;
+            });
+          }
         });
       }
     });
@@ -2641,6 +2705,75 @@
     deliveryFormVisible.value = false;
     currentDeliveryRow.value = null;
   };
+
+  // 鎵归噺鍙戣揣锛氭牎楠屽悓涓�瀹㈡埛鍚庢媺鍙栧彲鍙戜骇鍝佽
+  const handleBatchShipping = async () => {
+    if (!selectedRows.value.length) {
+      proxy.$modal.msgWarning("璇峰厛鍕鹃�夎鍙戣揣鐨勮鍗�");
+      return;
+    }
+    // 鍚屼竴瀹㈡埛鏍¢獙锛堝悗绔篃浼氭牎楠岋級
+    const customerNames = [
+      ...new Set(selectedRows.value.map(l => l.customerName)),
+    ];
+    if (customerNames.length > 1) {
+      proxy.$modal.msgError("鎵归噺鍙戣揣浠呮敮鎸佸悓涓�瀹㈡埛鐨勫鏉¤鍗�");
+      return;
+    }
+    // 鎷夊彇鍚勮鍗曠殑浜у搧鏄庣粏锛屾敹闆嗗墿浣欏彲鍙戞暟閲� > 0 鐨勮
+    batchShippingRows.value = [];
+    for (const ledger of selectedRows.value) {
+      const res = await productList({ salesLedgerId: ledger.id, type: 1 });
+      const rows = (res.data || []).filter(r => Number(r.unshippedQuantity) > 0);
+      rows.forEach(r => {
+        r.salesLedgerId = ledger.id;
+        r.shipQuantity = r.unshippedQuantity; // 榛樿鏈鍙戣揣鏁伴噺 = 鍓╀綑鍙彂
+      });
+      batchShippingRows.value = batchShippingRows.value.concat(rows);
+    }
+    if (!batchShippingRows.value.length) {
+      proxy.$modal.msgWarning("鎵�閫夎鍗曟棤鍓╀綑鍙彂璐т骇鍝�");
+      return;
+    }
+    batchShippingOpen.value = true;
+  };
+
+  // 鎵归噺鎻愪氦鍙戣揣
+  const submitBatchShipping = () => {
+    // 閫愯鏍¢獙鏁伴噺
+    for (const row of batchShippingRows.value) {
+      const qty = Number(row.shipQuantity);
+      if (!qty || qty <= 0) {
+        proxy.$modal.msgError("瀛樺湪鏈鍙戣揣鏁伴噺涓虹┖鎴栦负 0 鐨勮");
+        return;
+      }
+      if (qty > Number(row.unshippedQuantity)) {
+        proxy.$modal.msgError("瀛樺湪瓒呰繃鍓╀綑鍙彂鏁伴噺鐨勮");
+        return;
+      }
+    }
+    const reqs = batchShippingRows.value.map(r => ({
+      salesLedgerId: r.salesLedgerId,
+      salesLedgerProductId: r.id,
+      quantity: r.shipQuantity,
+      type: "鎵归噺鍙戣揣",
+      approveUserIds: [],
+    }));
+    batchAdd(reqs).then(res => {
+      if (res.code === 200) {
+        proxy.$modal.msgSuccess("鎵归噺鍙戣揣鎴愬姛锛屽凡鍙戣捣瀹℃壒");
+        batchShippingOpen.value = false;
+        getList();
+      }
+    });
+  };
+
+  // 鍏抽棴鎵归噺鍙戣揣寮规
+  const closeBatchShipping = () => {
+    batchShippingOpen.value = false;
+    batchShippingRows.value = [];
+  };
+
   const currentFactoryName = ref("");
   const getCurrentFactoryName = async () => {
     let res = await userStore.getInfo();

--
Gitblit v1.9.3