From eee1310bc134b2bb7c8a406750cb64e9fe226ac2 Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期二, 29 九月 2026 11:25:29 +0800
Subject: [PATCH] chore: 薪火智能配置文件

---
 src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue |  129 ++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 126 insertions(+), 3 deletions(-)

diff --git a/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue b/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue
index 739facb..d066899 100644
--- a/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue
+++ b/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue
@@ -6,12 +6,23 @@
                @close="handleClose">
       <div class="material-toolbar">
         <el-button type="primary"
+                   plain
+                   @click="handleAddPurchase">鏂板閲囪喘</el-button>
+        <el-button type="primary"
                    @click="handleAddMaterialRow">鏂板</el-button>
       </div>
       <el-table v-loading="materialTableLoading"
                 :data="materialTableData"
                 border
+                @selection-change="handleMaterialSelectionChange"
                 row-key="tempId">
+        <el-table-column align="center"
+                         type="selection"
+                         width="55" />
+        <el-table-column align="center"
+                         type="index"
+                         label="搴忓彿"
+                         width="60" />
         <el-table-column label="宸ュ簭鍚嶇О"
                          min-width="100">
           <template #default="{ row }">
@@ -56,11 +67,13 @@
                        multiple
                        collapse-tags
                        collapse-tags-indicator
+                       clearable
                        placeholder="璇烽�夋嫨鎵瑰彿"
-                       style="width: 100%;">
+                       style="width: 100%;"
+                       @change="val => handleBatchNoChange(row, val)">
               <el-option v-for="item in row.batchNoList"
                          :key="item"
-                         :label="item"
+                         :label="getBatchOptionLabel(row, item)"
                          :value="item" />
             </el-select>
           </template>
@@ -80,13 +93,20 @@
                              @change="val => handleRequiredQtyChange(row, val)" />
           </template>
         </el-table-column>
+        <el-table-column label="搴撳瓨浣欓噺"
+                         min-width="90">
+          <template #default="{ row }">
+            <span v-if="row.stockQty === null">-</span>
+            <span v-else>{{ stripTrailingZeros(row.stockQty) }}</span>
+          </template>
+        </el-table-column>
         <el-table-column label="宸查鏁伴噺"
                          min-width="90">
           <template #default="{ row }">
             {{ stripTrailingZeros(row.pickedQty) ?? 0 }}
           </template>
         </el-table-column>
-        <el-table-column label="鍓╀綑鍙"
+        <el-table-column label="鍓╀綑闇�棰�"
                          min-width="90">
           <template #default="{ row }">
             <span :class="{ 'remaining-empty': Number(row.remainingQty) <= 0 }">
@@ -136,6 +156,8 @@
     <ProductSelectDialog v-model="materialProductDialogVisible"
                          @confirm="handleMaterialProductConfirm"
                          single />
+    <PurchaseLedgerAddDialog ref="purchaseLedgerAddDialogRef"
+                             v-model="purchaseLedgerDialogVisible" />
     <!-- request-url="/stockInventory/rawMaterials" -->
   </div>
 </template>
@@ -144,7 +166,9 @@
   import { computed, ref, watch } from "vue";
   import { ElMessage } from "element-plus";
   import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
+  import PurchaseLedgerAddDialog from "./PurchaseLedgerAddDialog.vue";
   import { findProductProcessRouteItemList } from "@/api/productionManagement/productProcessRoute.js";
+  import { getStockInventoryByModelId } from "@/api/inventoryManagement/stockInventory.js";
   import {
     listMaterialPickingDetail,
     listMaterialPickingBom,
@@ -166,6 +190,9 @@
   const materialTableLoading = ref(false);
   const materialSaving = ref(false);
   const materialTableData = ref([]);
+  const selectedMaterialRows = ref([]);
+  const purchaseLedgerDialogVisible = ref(false);
+  const purchaseLedgerAddDialogRef = ref(null);
 
   const isSaveDisabled = computed(() => {
     if (materialTableLoading.value) return true;
@@ -222,10 +249,16 @@
       returnedQty,
       remainingQty,
       pickQty: 0,
+      stockQty: null,
       batchNo: [],
       batchNoList,
+      batchQtyMap: {},
     };
   };
+
+  // 鎵瑰彿閫夐」灞曠ず涓衡�滄壒鍙凤紙搴撳瓨鏁伴噺锛夆��
+  const getBatchOptionLabel = (row, batchNo) =>
+    `${batchNo}锛�${stripTrailingZeros(row.batchQtyMap?.[batchNo] ?? 0)}锛塦;
 
   const getProcessOptions = async () => {
     if (!props.orderRow?.id) return;
@@ -349,6 +382,10 @@
           })
         );
       });
+      // 鍏堟煡鍑哄簱瀛樹綑閲忓啀鍏ヨ〃锛屼繚璇侀娆℃墦寮�鍗冲睍绀猴紙rows 灏氭湭杞负鍝嶅簲寮忎唬鐞嗭紝
+      // 鍏ヨ〃鍚庡啀鏀瑰師濮嬪璞′笉浼氳Е鍙戣鍥炬洿鏂帮級
+      await loadStockQtyForRows(rows);
+      // 鎵撳紑棰嗘枡鍙拌处涓嶉粯璁ら�変腑鎵瑰彿锛氬彧鏈夋墜鍔ㄩ�夋嫨浜嗘壒鍙风殑琛屾墠浼氶鏂�
       materialTableData.value = rows;
     } finally {
       materialTableLoading.value = false;
@@ -366,11 +403,84 @@
 
   const handleClose = () => {
     materialTableData.value = [];
+    selectedMaterialRows.value = [];
     currentMaterialSelectRowIndex.value = -1;
+  };
+
+  // 鎸夊瀷鍙锋眹鎬绘墍鏈夋壒娆$殑鍘熸枡鍙敤搴撳瓨浣欓噺锛屽苟璁板綍姣忎釜鎵瑰彿瀵瑰簲鐨勫簱瀛樻暟閲�
+  const loadStockQtyForRows = async rows => {
+    const modelIds = [
+      ...new Set(rows.map(row => row.materialModelId).filter(Boolean)),
+    ];
+    const stockMap = new Map();
+    const batchQtyMap = new Map();
+    await Promise.all(
+      modelIds.map(async modelId => {
+        try {
+          const res = await getStockInventoryByModelId(modelId);
+          const list = Array.isArray(res?.data)
+            ? res.data
+            : res?.data?.records || res?.data?.rows || [];
+          const perBatch = {};
+          const total = list.reduce((sum, item) => {
+            const qty = toNumber(item?.qualitity ?? item?.quantity);
+            if (item?.batchNo) {
+              perBatch[item.batchNo] = roundQuantity(
+                toNumber(perBatch[item.batchNo]) + qty
+              );
+            }
+            return sum + qty;
+          }, 0);
+          stockMap.set(modelId, roundQuantity(total));
+          batchQtyMap.set(modelId, perBatch);
+        } catch (e) {
+          stockMap.set(modelId, 0);
+          batchQtyMap.set(modelId, {});
+        }
+      })
+    );
+    rows.forEach(row => {
+      if (!row.materialModelId) {
+        row.stockQty = null;
+        row.batchQtyMap = {};
+        return;
+      }
+      row.stockQty = stockMap.has(row.materialModelId)
+        ? stockMap.get(row.materialModelId)
+        : 0;
+      row.batchQtyMap = batchQtyMap.get(row.materialModelId) || {};
+    });
   };
 
   const handleAddMaterialRow = () => {
     materialTableData.value.push(createMaterialRow());
+  };
+
+  const handleMaterialSelectionChange = selection => {
+    selectedMaterialRows.value = selection;
+  };
+
+  const handleAddPurchase = () => {
+    if (selectedMaterialRows.value.length === 0) {
+      ElMessage.warning("璇烽�夋嫨闇�瑕佹柊澧為噰璐殑鍘熸枡琛�");
+      return;
+    }
+    const rowsWithModel = selectedMaterialRows.value.filter(
+      row => row.materialModelId
+    );
+    if (rowsWithModel.length === 0) {
+      ElMessage.warning("鎵�閫夎缂哄皯鍘熸枡鍨嬪彿锛岃鍏堥�夋嫨鍘熸枡鍚庡啀鏂板閲囪喘");
+      return;
+    }
+    const productRows = rowsWithModel.map(row => ({
+      productModelId: row.materialModelId,
+      productCategory: row.materialName,
+      specificationModel: row.materialModel,
+      unit: row.unit,
+      quantity: row.demandedQuantity,
+      isChecked: false,
+    }));
+    purchaseLedgerAddDialogRef.value?.open(productRows);
   };
 
   const handleDeleteMaterialRow = index => {
@@ -382,6 +492,17 @@
       item => item.name === operationName
     );
     row.technologyOperationId = process?.technologyOperationId;
+  };
+
+  // 閫夋嫨鎵瑰彿鍗宠〃绀烘湰琛屾湰娆¢鏂欙細鑷姩甯﹀嚭鍓╀綑闇�棰嗘暟閲忥紱娓呯┖鎵瑰彿琛ㄧず鏈涓嶉鏂�
+  const handleBatchNoChange = (row, batchNo) => {
+    if (!Array.isArray(batchNo) || batchNo.length === 0) {
+      row.pickQty = 0;
+      return;
+    }
+    if (toNumber(row.pickQty) <= 0) {
+      row.pickQty = roundQuantity(row.remainingQty);
+    }
   };
 
   const handleRequiredQtyChange = (row, val) => {
@@ -414,8 +535,10 @@
     row.unit = product.unit || product.measureUnit || "";
     row.batchNoList = Array.isArray(product.batchNoList) ? product.batchNoList : [];
     row.batchNo = [];
+    row.pickQty = 0;
     currentMaterialSelectRowIndex.value = -1;
     materialProductDialogVisible.value = false;
+    loadStockQtyForRows([row]);
   };
 
   const validateMaterialRows = () => {

--
Gitblit v1.9.3