From bfa9cabc4fe74da05c3d1eb5148929551c4d87c2 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期四, 28 五月 2026 09:13:01 +0800
Subject: [PATCH] 中兴实强new 1.生产订单领料时如果库存不足可以提交采购申请单 2.采购申请单通知点击跳转是根据合同号直接进行查询

---
 src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue |  123 ++++++++++++++++++++++++++++++++++------
 1 files changed, 104 insertions(+), 19 deletions(-)

diff --git a/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue b/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue
index 210dbba..85fbe35 100644
--- a/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue
+++ b/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue
@@ -2,7 +2,7 @@
   <div>
     <el-dialog v-model="dialogVisible"
                title="棰嗘枡鍙拌处"
-               width="1200px"
+               width="1400px"
                @close="handleClose">
       <div class="material-toolbar">
         <el-button type="primary"
@@ -65,10 +65,18 @@
             </el-select>
           </template>
         </el-table-column>
+        <el-table-column label="搴撳瓨鏁伴噺"
+                         min-width="120">
+          <template #default="{ row }">
+            <span :class="{ 'text-danger': isStockInsufficient(row) }">
+              {{ row.stockQuantity ?? '-' }}
+            </span>
+          </template>
+        </el-table-column>
         <el-table-column label="闇�姹傛暟閲�"
                          min-width="120">
           <template #default="{ row }">
-            <span v-if="row.bom === true">{{ row.demandedQuantity ?? "-" }}</span>
+            <span v-if="row.bom === true" :class="{ 'text-danger': isStockInsufficient(row) }">{{ row.demandedQuantity ?? "-" }}</span>
             <el-input-number v-else
                              v-model="row.demandedQuantity"
                              :min="0"
@@ -76,6 +84,7 @@
                              :step="1"
                              controls-position="right"
                              style="width: 100%;"
+                             :class="{ 'is-stock-insufficient': isStockInsufficient(row) }"
                              @change="val => handleRequiredQtyChange(row, val)" />
           </template>
         </el-table-column>
@@ -109,8 +118,12 @@
       </el-table>
       <template #footer>
         <span class="dialog-footer">
+          <el-button v-if="hasInsufficientStock"
+                     type="warning"
+                     @click="openPurchaseRequestDialog">閲囪喘鐢宠</el-button>
           <el-button type="primary"
                      :loading="materialSaving"
+                     :disabled="isSaveDisabled"
                      @click="handleMaterialSave">淇濆瓨</el-button>
           <el-button @click="dialogVisible = false">鍙栨秷</el-button>
         </span>
@@ -119,6 +132,10 @@
     <ProductSelectDialog v-model="materialProductDialogVisible"
                          @confirm="handleMaterialProductConfirm"
                          single />
+    <PurchaseRequestDialog v-model="purchaseRequestDialogVisible"
+                           :insufficient-items="insufficientStockItems"
+                           :order-row="props.orderRow"
+                           @saved="handlePurchaseRequestSaved" />
     <!-- request-url="/stockInventory/rawMaterials" -->
   </div>
 </template>
@@ -127,18 +144,18 @@
   import { computed, ref, watch } from "vue";
   import { ElMessage } from "element-plus";
   import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
+  import PurchaseRequestDialog from "./PurchaseRequestDialog.vue";
   import {
     findProductProcessRouteItemList,
     listMain,
   } from "@/api/productionManagement/productProcessRoute.js";
   import {
-    listMaterialPickingDetail,
     listMaterialPickingBom,
-    listMaterialPickingLedger,
     saveMaterialPickingLedger,
     updateMaterialPickingLedger,
   } from "@/api/productionManagement/productionOrder.js";
   import { queryList2 } from "@/api/productionManagement/productStructure.js";
+
 
   const props = defineProps({
     modelValue: { type: Boolean, default: false },
@@ -155,6 +172,51 @@
   const materialTableLoading = ref(false);
   const materialSaving = ref(false);
   const materialTableData = ref([]);
+  const purchaseRequestDialogVisible = ref(false);
+
+  const isSaveDisabled = computed(() => {
+    if (materialTableData.value.length === 0) return true;
+    return !materialTableData.value.some(row => {
+      // 妫�鏌ユ槸鍚︽湁浠讳綍鐢ㄦ埛杈撳叆鍐呭
+      const hasBatch = Array.isArray(row.batchNo) && row.batchNo.length > 0;
+      const hasPickQty =
+        row.pickQty !== null && row.pickQty !== undefined && row.pickQty !== 0;
+
+      if (row.bom) {
+        // 瀵逛簬鏉ヨ嚜BOM鐨勮锛岃緭鍏ユ鍙湁鈥滄壒鍙封�濆拰鈥滈鐢ㄦ暟閲忊��
+        return hasBatch || hasPickQty;
+      } else {
+        // 瀵逛簬鏂板琛岋紝杈撳叆妗嗗寘鎷�滃伐搴忊�濄�佲�滃師鏂欌�濄�佲�滈渶姹傛暟閲忊�濄�佲�滄壒鍙封�濆拰鈥滈鐢ㄦ暟閲忊��
+        const hasOperation = !!row.operationName;
+        const hasMaterial = !!row.materialName;
+        const hasDemanded =
+          row.demandedQuantity !== null &&
+          row.demandedQuantity !== undefined &&
+          row.demandedQuantity !== 0;
+        return (
+          hasBatch || hasPickQty || hasOperation || hasMaterial || hasDemanded
+        );
+      }
+    });
+  });
+
+  // 鍒ゆ柇搴撳瓨鏄惁涓嶈冻
+  const isStockInsufficient = (row) => {
+    const stockQuantity = Number(row.stockQuantity ?? 0);
+    const demandedQty = Number(row.demandedQuantity ?? 0);
+    return demandedQty > 0 && stockQuantity > 0 && demandedQty > stockQuantity;
+  };
+
+  // 搴撳瓨涓嶈冻鐨勮
+  const insufficientStockItems = computed(() => {
+    return materialTableData.value.filter(row => isStockInsufficient(row));
+  });
+
+  // 鏄惁鏈夊簱瀛樹笉瓒�
+  const hasInsufficientStock = computed(() => {
+    return insufficientStockItems.value.length > 0;
+  });
+
   const processOptions = ref([]);
   const currentMaterialSelectRowIndex = ref(-1);
   let materialTempId = 0;
@@ -178,6 +240,7 @@
         : row.batchNo
       : [],
     batchNoList: row.batchNoList || [],
+    stockQuantity: row.stockQuantity ?? row.stockQty ?? null,
   });
 
   const getProcessOptions = async () => {
@@ -211,22 +274,14 @@
     materialTableData.value = [];
     await getProcessOptions();
     try {
-      const detailRes = await listMaterialPickingDetail(props.orderRow.id);
-      const detailList = Array.isArray(detailRes?.data)
-        ? detailRes.data
-        : detailRes?.data?.records || [];
-      if (detailList.length > 0) {
-        isDetail.value = true;
-        materialTableData.value = detailList.map(item => createMaterialRow(item));
-        return;
-      } else {
+      // 鐩存帴璋冪敤listMaterialPickingBom鎺ュ彛鑾峰彇搴撳瓨鏁伴噺
+      const bomRes = await listMaterialPickingBom(props.orderRow.id);
+      const bomList = Array.isArray(bomRes?.data)
+        ? bomRes.data
+        : bomRes?.data?.records || [];
+      if (bomList.length > 0) {
         isDetail.value = false;
-        const bomRes = await listMaterialPickingBom(props.orderRow.id);
-        const bomList = Array.isArray(bomRes?.data)
-          ? bomRes.data
-          : bomRes?.data?.records || [];
         materialTableData.value = bomList.map(item => createMaterialRow(item));
-        return;
       }
     } finally {
       materialTableLoading.value = false;
@@ -277,7 +332,7 @@
     materialProductDialogVisible.value = true;
   };
 
-  const handleMaterialProductConfirm = products => {
+  const handleMaterialProductConfirm = async (products) => {
     console.log(products, "products");
 
     if (!products || products.length === 0) return;
@@ -312,12 +367,20 @@
         !item.materialName ||
         (Number(item.pickQty) > 0 &&
           (!item.batchNo || item.batchNo.length === 0)) ||
+        (item.batchNo && item.batchNo.length > 0 && Number(item.pickQty) <= 0) ||
         item.demandedQuantity === null ||
         item.demandedQuantity === undefined ||
         item.pickQty === null ||
         item.pickQty === undefined
     );
     if (invalidRow) {
+      if (
+        invalidRow.batchNo &&
+        invalidRow.batchNo.length > 0 &&
+        Number(invalidRow.pickQty) <= 0
+      ) {
+        return { valid: false, message: "閫夋嫨浜嗘壒鍙锋椂锛岄鐢ㄦ暟閲忓繀椤诲ぇ浜庨浂" };
+      }
       return { valid: false, message: "璇峰畬鍠勫伐搴忋�佸師鏂欍�佹壒鍙峰拰鏁伴噺鍚庡啀淇濆瓨" };
     }
     return { valid: true, message: "" };
@@ -381,6 +444,17 @@
       materialSaving.value = false;
     }
   };
+
+  // 鎵撳紑閲囪喘鐢宠瀵硅瘽妗�
+  const openPurchaseRequestDialog = () => {
+    purchaseRequestDialogVisible.value = true;
+  };
+
+  // 閲囪喘鐢宠淇濆瓨鍥炶皟
+  const handlePurchaseRequestSaved = () => {
+    // 閲囪喘鐢宠淇濆瓨鎴愬姛鍚庡埛鏂版暟鎹�
+    loadMaterialData();
+  };
 </script>
 
 <style scoped lang="scss">
@@ -388,4 +462,15 @@
     margin-bottom: 12px;
     text-align: right;
   }
+
+  .text-danger {
+    color: #f56c6c;
+    font-weight: bold;
+  }
+
+  :deep(.is-stock-insufficient) {
+    .el-input__wrapper {
+      box-shadow: 0 0 0 1px #f56c6c inset;
+    }
+  }
 </style>

--
Gitblit v1.9.3