From a8d694d5d987892afee5a1bb8f6c01d612e6b2a3 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期四, 14 五月 2026 11:23:23 +0800
Subject: [PATCH] 浪潮 1.入库管理、出库管理添加库位相关字段和逻辑

---
 src/views/inventoryManagement/dispatchLog/Record.vue       |  169 ++++++++++++++++++++-------
 src/views/inventoryManagement/stockManagement/New.vue      |   65 ++++++++--
 src/components/PIMTable/PIMTable.vue                       |   59 +++++++++
 src/views/inventoryManagement/stockManagement/Record.vue   |    1 
 src/views/inventoryManagement/receiptManagement/Record.vue |   65 +++++-----
 5 files changed, 271 insertions(+), 88 deletions(-)

diff --git a/src/components/PIMTable/PIMTable.vue b/src/components/PIMTable/PIMTable.vue
index f99b1eb..e256832 100644
--- a/src/components/PIMTable/PIMTable.vue
+++ b/src/components/PIMTable/PIMTable.vue
@@ -14,6 +14,10 @@
             :expand-row-keys="expandRowKeys"
             :show-summary="isShowSummary"
             :summary-method="summaryMethod"
+            :default-expand-all="defaultExpandAll"
+            :tree-props="treeProps"
+            :lazy="lazy"
+            :load="load"
             @row-click="rowClick"
             @current-change="currentChange"
             @selection-change="handleSelectionChange"
@@ -316,6 +320,22 @@
       type: [String, Object],
       default: () => ({ width: "100%" }),
     },
+    defaultExpandAll: {
+      type: Boolean,
+      default: false,
+    },
+    treeProps: {
+      type: Object,
+      default: () => ({ children: "children", hasChildren: "hasChildren" }),
+    },
+    lazy: {
+      type: Boolean,
+      default: false,
+    },
+    load: {
+      type: Function,
+      default: null,
+    },
   });
 
   const mergedHeaderCellStyle = computed(() => ({
@@ -326,6 +346,7 @@
   }));
 
   // Data
+  const multipleTable = ref(null);
   const uploadRefs = ref([]);
   const currentFiles = ref({});
   const uploadKeys = ref({});
@@ -499,6 +520,44 @@
   const handleSelectionChange = newSelection => {
     emit("selection-change", newSelection);
   };
+
+  // 灞曞紑/鎶樺彔鏍戝舰鑺傜偣
+  const toggleRowExpansion = (row, expanded) => {
+    multipleTable.value?.toggleRowExpansion(row, expanded);
+  };
+
+  // 灞曞紑鎵�鏈夋爲褰㈣妭鐐�
+  const expandAll = () => {
+    const expandRows = (rows) => {
+      rows?.forEach(row => {
+        if (row[props.treeProps.children]?.length > 0) {
+          multipleTable.value?.toggleRowExpansion(row, true);
+          expandRows(row[props.treeProps.children]);
+        }
+      });
+    };
+    expandRows(props.tableData);
+  };
+
+  // 鎶樺彔鎵�鏈夋爲褰㈣妭鐐�
+  const collapseAll = () => {
+    const collapseRows = (rows) => {
+      rows?.forEach(row => {
+        if (row[props.treeProps.children]?.length > 0) {
+          collapseRows(row[props.treeProps.children]);
+          multipleTable.value?.toggleRowExpansion(row, false);
+        }
+      });
+    };
+    collapseRows(props.tableData);
+  };
+
+  defineExpose({
+    toggleRowExpansion,
+    expandAll,
+    collapseAll,
+    multipleTable
+  });
 </script>
 
 <style scoped lang="scss">
diff --git a/src/views/inventoryManagement/dispatchLog/Record.vue b/src/views/inventoryManagement/dispatchLog/Record.vue
index 724f561..7ba8dfd 100644
--- a/src/views/inventoryManagement/dispatchLog/Record.vue
+++ b/src/views/inventoryManagement/dispatchLog/Record.vue
@@ -68,6 +68,7 @@
           show-overflow-tooltip
         />
         <el-table-column label="瑙勬牸鍨嬪彿" prop="model" show-overflow-tooltip />
+        <el-table-column label="搴撲綅" prop="warehouseName" show-overflow-tooltip />
         <el-table-column label="鎵瑰彿" prop="batchNo" show-overflow-tooltip />
         <el-table-column label="鍗曚綅" prop="unit" show-overflow-tooltip />
         <el-table-column
@@ -148,48 +149,26 @@
                       prop="unit">
           <el-input v-model="formState.unit" disabled />
         </el-form-item>
-        <el-form-item label="搴撳瓨绫诲瀷"
-                      prop="type"
+        <el-form-item label="浠撳簱"
+                      prop="warehouseId"
                       :rules="[
                         {
                           required: true,
-                          message: '璇烽�夋嫨搴撳瓨绫诲瀷',
+                          message: '璇烽�夋嫨浠撳簱',
                           trigger: 'change',
                         }
                       ]">
-          <el-select v-model="formState.type"
-                     placeholder="璇烽�夋嫨搴撳瓨绫诲瀷"
-                     :disabled="isEdit">
-            <el-option label="鍚堟牸搴撳瓨"
-                       value="qualified" />
-            <el-option label="涓嶅悎鏍煎簱瀛�"
-                       value="unqualified" />
+          <el-select v-model="formState.warehouseId"
+                     placeholder="璇烽�夋嫨浠撳簱"
+                     clearable
+                     :disabled="isEdit || !formState.productId"
+                     @change="handleWarehouseChange"
+                     style="width: 100%">
+            <el-option v-for="warehouse in warehouseList"
+                       :key="warehouse.id"
+                       :label="warehouse.name"
+                       :value="warehouse.id" />
           </el-select>
-        </el-form-item>
-        <el-form-item label="鍑哄簱鏁伴噺"
-                      prop="qualitity"
-                      :rules="[
-                        {
-                          required: true,
-                          message: '璇疯緭鍏ュ嚭搴撴暟閲�',
-                          trigger: 'blur',
-                        },
-                        {
-                          validator: (rule, value, callback) => {
-                            if (formState.maxStock > 0 && value > formState.maxStock) {
-                              callback('鍑哄簱鏁伴噺涓嶈兘瓒呰繃褰撳墠鎵瑰彿搴撳瓨 ' + formState.maxStock);
-                            } else {
-                              callback();
-                            }
-                          },
-                          trigger: 'blur',
-                        }
-                      ]">
-          <el-input-number v-model="formState.qualitity"
-                           :step="1"
-                           :min="1"
-                           :max="formState.maxStock > 0 ? formState.maxStock : undefined"
-                           style="width: 100%" />
         </el-form-item>
         <el-form-item label="鎵瑰彿"
                       prop="batchNo"
@@ -217,6 +196,31 @@
                       prop="currentStock">
           <el-input v-model="batchNoStockMap[formState.batchNo]" disabled />
         </el-form-item>
+        <el-form-item label="鍑哄簱鏁伴噺"
+                      prop="qualitity"
+                      :rules="[
+                        {
+                          required: true,
+                          message: '璇疯緭鍏ュ嚭搴撴暟閲�',
+                          trigger: 'blur',
+                        },
+                        {
+                          validator: (rule, value, callback) => {
+                            if (formState.maxStock > 0 && value > formState.maxStock) {
+                              callback('鍑哄簱鏁伴噺涓嶈兘瓒呰繃褰撳墠鎵瑰彿搴撳瓨 ' + formState.maxStock);
+                            } else {
+                              callback();
+                            }
+                          },
+                          trigger: 'blur',
+                        }
+                      ]">
+          <el-input-number v-model="formState.qualitity"
+                           :step="1"
+                           :min="1"
+                           :max="formState.maxStock > 0 ? formState.maxStock : undefined"
+                           style="width: 100%" />
+        </el-form-item>
         <el-form-item v-if="isEdit"
                       label="鏉ユ簮"
                       prop="recordType">
@@ -227,6 +231,24 @@
                        :key="item.value"
                        :label="item.label"
                        :value="item.value" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="搴撳瓨绫诲瀷"
+                      prop="type"
+                      :rules="[
+                        {
+                          required: true,
+                          message: '璇烽�夋嫨搴撳瓨绫诲瀷',
+                          trigger: 'change',
+                        }
+                      ]">
+          <el-select v-model="formState.type"
+                     placeholder="璇烽�夋嫨搴撳瓨绫诲瀷"
+                     :disabled="isEdit">
+            <el-option label="鍚堟牸搴撳瓨"
+                       value="qualified" />
+            <el-option label="涓嶅悎鏍煎簱瀛�"
+                       value="unqualified" />
           </el-select>
         </el-form-item>
         <el-form-item label="澶囨敞"
@@ -270,6 +292,7 @@
 } from "@/api/basicData/enum.js";
 import { addStockOutRecordOnly } from "@/api/inventoryManagement/stockInventory.js";
 import { addUnqualifiedStockOutRecordOnly } from "@/api/inventoryManagement/stockUninventory.js";
+import { getWarehouseList } from "@/api/inventoryManagement/warehouse.js";
 
 const userStore = useUserStore();
 const { proxy } = getCurrentInstance();
@@ -282,6 +305,10 @@
 const batchNoList = ref([]);
 // 鎵瑰彿搴撳瓨鏄犲皠
 const batchNoStockMap = ref({});
+// 浠撳簱鍒楄〃
+const warehouseList = ref([]);
+// 鍘熷batchNoMaps鏁版嵁
+const rawBatchNoMaps = ref({});
 const page = reactive({
   current: 1,
   size: 100,
@@ -330,6 +357,7 @@
   productName: "",
   productModelName: "",
   unit: "",
+  warehouseId: null, // 浠撳簱ID
   type: undefined,
   qualitity: 0,
   batchNo: null,
@@ -476,6 +504,7 @@
     productName: "",
     productModelName: "",
     unit: "",
+    warehouseId: null,
     type: undefined,
     qualitity: 0,
     batchNo: null,
@@ -483,14 +512,29 @@
     remark: "",
     maxStock: 0,
   };
+  warehouseList.value = [];
   batchNoList.value = [];
   batchNoStockMap.value = {};
+  rawBatchNoMaps.value = {};
 };
 
 // 鍏抽棴瀵硅瘽妗�
 const closeDialog = () => {
   dialogVisible.value = false;
   resetForm();
+};
+
+// 鍔犺浇浠撳簱鍒楄〃
+const loadWarehouseList = async () => {
+  try {
+    const res = await getWarehouseList();
+    if (res.code === 200) {
+      return res.data || [];
+    }
+  } catch (error) {
+    console.error('鍔犺浇浠撳簱鍒楄〃澶辫触', error);
+  }
+  return [];
 };
 
 // 浜у搧閫夋嫨澶勭悊
@@ -502,23 +546,60 @@
     formState.value.productModelName = product.model;
     formState.value.productModelId = product.id;
     formState.value.unit = product.unit;
-    // 浠巄atchNoMaps鑾峰彇鎵瑰彿鍒楄〃鍜屽簱瀛�
-    if (product.batchNoMaps && Object.keys(product.batchNoMaps).length > 0) {
-      batchNoList.value = Object.keys(product.batchNoMaps);
-      batchNoStockMap.value = product.batchNoMaps;
-    } else {
-      batchNoList.value = [];
-      batchNoStockMap.value = {};
-    }
-    // 娓呯┖宸查�夋嫨鐨勬壒鍙峰拰鏈�澶у簱瀛�
+    // 瑙f瀽batchNoMaps鏁版嵁锛屾牸寮忎负锛歿 浠撳簱ID: [{鎵瑰彿: 搴撳瓨}, {鎵瑰彿: 搴撳瓨}] }
+    warehouseList.value = [];
+    batchNoList.value = [];
+    batchNoStockMap.value = {};
+    rawBatchNoMaps.value = {};
+    formState.value.warehouseId = null;
     formState.value.batchNo = null;
     formState.value.maxStock = 0;
+
+    if (product.batchNoMaps && Object.keys(product.batchNoMaps).length > 0) {
+      rawBatchNoMaps.value = product.batchNoMaps;
+      // 鑾峰彇鎵�鏈変粨搴撲俊鎭敤浜庡弽鏄惧悕绉�
+      const allWarehouses = await loadWarehouseList();
+      const warehouseMap = {};
+      allWarehouses.forEach(w => {
+        warehouseMap[w.id] = w.warehouseName || w.name || w.warehouseCode || `浠撳簱${w.id}`;
+      });
+      // 鏋勫缓浠撳簱鍒楄〃
+      warehouseList.value = Object.keys(product.batchNoMaps).map(warehouseId => ({
+        id: warehouseId,
+        name: warehouseMap[warehouseId] || `浠撳簱${warehouseId}`
+      }));
+    }
     showProductSelect.value = false;
     // 瑙﹀彂琛ㄥ崟楠岃瘉鏇存柊
     proxy.$refs["formRef"]?.validateField("productModelId");
   }
 };
 
+// 浠撳簱閫夋嫨鍙樺寲澶勭悊
+const handleWarehouseChange = (warehouseId) => {
+  batchNoList.value = [];
+  batchNoStockMap.value = {};
+  formState.value.batchNo = null;
+  formState.value.maxStock = 0;
+
+  if (warehouseId && rawBatchNoMaps.value[warehouseId]) {
+    // 瑙f瀽璇ヤ粨搴撲笅鐨勬壒鍙锋暟鎹紝鏍煎紡涓猴細[{鎵瑰彿: 搴撳瓨}, {鎵瑰彿: 搴撳瓨}]
+    const batchArray = rawBatchNoMaps.value[warehouseId];
+    const batchMap = {};
+    const batches = [];
+
+    batchArray.forEach(item => {
+      const batchNo = Object.keys(item)[0];
+      const stock = item[batchNo];
+      batches.push(batchNo);
+      batchMap[batchNo] = stock;
+    });
+
+    batchNoList.value = batches;
+    batchNoStockMap.value = batchMap;
+  }
+};
+
 // 鎵瑰彿閫夋嫨鍙樺寲澶勭悊
 const handleBatchNoChange = (batchNo) => {
   if (batchNo && batchNoStockMap.value[batchNo]) {
diff --git a/src/views/inventoryManagement/receiptManagement/Record.vue b/src/views/inventoryManagement/receiptManagement/Record.vue
index 8e51b13..929b2a0 100644
--- a/src/views/inventoryManagement/receiptManagement/Record.vue
+++ b/src/views/inventoryManagement/receiptManagement/Record.vue
@@ -70,6 +70,9 @@
         <el-table-column label="瑙勬牸鍨嬪彿"
                          prop="model"
                          show-overflow-tooltip/>
+        <el-table-column label="搴撲綅"
+                         prop="warehouseName"
+                         show-overflow-tooltip/>
         <el-table-column label="鎵瑰彿"
                          prop="batchNo"
                          show-overflow-tooltip/>
@@ -149,37 +152,6 @@
                       prop="unit">
           <el-input v-model="formState.unit" disabled />
         </el-form-item>
-        <el-form-item label="搴撳瓨绫诲瀷"
-                      prop="type"
-                      :rules="[
-                        {
-                          required: true,
-                          message: '璇烽�夋嫨搴撳瓨绫诲瀷',
-                          trigger: 'change',
-                        }
-                      ]">
-          <el-select v-model="formState.type"
-                     placeholder="璇烽�夋嫨搴撳瓨绫诲瀷"
-                     :disabled="isEdit">
-            <el-option label="鍚堟牸搴撳瓨"
-                       value="qualified" />
-            <el-option label="涓嶅悎鏍煎簱瀛�"
-                       value="unqualified" />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="搴撳瓨鏁伴噺"
-                      prop="qualitity">
-          <el-input-number v-model="formState.qualitity"
-                           :step="1"
-                           :min="1"
-                           style="width: 100%" />
-        </el-form-item>
-        <el-form-item label="鎵瑰彿"
-                      prop="batchNo">
-          <el-input v-model="formState.batchNo"
-                    placeholder="璇疯緭鍏ユ壒鍙�"
-                    :disabled="isEdit" />
-        </el-form-item>
         <el-form-item label="搴撲綅"
                       prop="warehouseId"
                       :rules="[
@@ -198,6 +170,19 @@
                        :label="warehouse.warehouseName + ' - ' + warehouse.location"
                        :value="warehouse.id" />
           </el-select>
+        </el-form-item>
+        <el-form-item label="鎵瑰彿"
+                      prop="batchNo">
+          <el-input v-model="formState.batchNo"
+                    placeholder="璇疯緭鍏ユ壒鍙�"
+                    :disabled="isEdit" />
+        </el-form-item>
+        <el-form-item label="搴撳瓨鏁伴噺"
+                      prop="qualitity">
+          <el-input-number v-model="formState.qualitity"
+                           :step="1"
+                           :min="1"
+                           style="width: 100%" />
         </el-form-item>
         <el-form-item v-if="isEdit"
                       label="鏉ユ簮"
@@ -220,6 +205,24 @@
                            :max="formState.qualitity"
                            style="width: 100%" />
         </el-form-item>
+        <el-form-item label="搴撳瓨绫诲瀷"
+                      prop="type"
+                      :rules="[
+                        {
+                          required: true,
+                          message: '璇烽�夋嫨搴撳瓨绫诲瀷',
+                          trigger: 'change',
+                        }
+                      ]">
+          <el-select v-model="formState.type"
+                     placeholder="璇烽�夋嫨搴撳瓨绫诲瀷"
+                     :disabled="isEdit">
+            <el-option label="鍚堟牸搴撳瓨"
+                       value="qualified" />
+            <el-option label="涓嶅悎鏍煎簱瀛�"
+                       value="unqualified" />
+          </el-select>
+        </el-form-item>
         <el-form-item label="澶囨敞"
                       prop="remark">
           <el-input v-model="formState.remark"
diff --git a/src/views/inventoryManagement/stockManagement/New.vue b/src/views/inventoryManagement/stockManagement/New.vue
index 2addb95..5a22acd 100644
--- a/src/views/inventoryManagement/stockManagement/New.vue
+++ b/src/views/inventoryManagement/stockManagement/New.vue
@@ -32,6 +32,37 @@
           <el-input v-model="formState.unit"
                     disabled />
         </el-form-item>
+        <el-form-item label="搴撲綅"
+                      prop="warehouseId"
+                      :rules="[
+                {
+                required: true,
+                message: '璇烽�夋嫨搴撲綅',
+                trigger: 'change',
+              }
+            ]">
+          <el-select v-model="formState.warehouseId"
+                     placeholder="璇烽�夋嫨搴撲綅"
+                     clearable
+                     style="width: 100%">
+            <el-option v-for="warehouse in warehouseList"
+                       :key="warehouse.id"
+                       :label="warehouse.warehouseName + ' - ' + warehouse.location"
+                       :value="warehouse.id" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鎵瑰彿"
+                      prop="batchNo">
+          <el-input v-model="formState.batchNo"
+                    placeholder="璇疯緭鍏ユ壒鍙�" />
+        </el-form-item>
+        <el-form-item label="搴撳瓨鏁伴噺"
+                      prop="qualitity">
+          <el-input-number v-model="formState.qualitity"
+                           :step="1"
+                           :min="1"
+                           style="width: 100%" />
+        </el-form-item>
         <el-form-item label="搴撳瓨绫诲瀷"
                       prop="type"
                       :rules="[
@@ -48,18 +79,6 @@
             <el-option label="涓嶅悎鏍煎簱瀛�"
                        value="unqualified" />
           </el-select>
-        </el-form-item>
-        <el-form-item label="搴撳瓨鏁伴噺"
-                      prop="qualitity">
-          <el-input-number v-model="formState.qualitity"
-                           :step="1"
-                           :min="1"
-                           style="width: 100%" />
-        </el-form-item>
-        <el-form-item label="鎵瑰彿"
-                      prop="batchNo">
-          <el-input v-model="formState.batchNo"
-                    placeholder="璇疯緭鍏ユ壒鍙�" />
         </el-form-item>
         <el-form-item v-if="formState.type === 'qualified'"
                       label="搴撳瓨棰勮鏁伴噺"
@@ -93,10 +112,11 @@
 </template>
 
 <script setup>
-  import { ref, computed, watch, getCurrentInstance } from "vue";
+  import { ref, computed, watch, getCurrentInstance, onMounted } from "vue";
   import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
   import { addStockInRecordOnly } from "@/api/inventoryManagement/stockInventory.js";
   import { createStockUnInventory } from "@/api/inventoryManagement/stockUninventory.js";
+  import { getWarehouseList } from "@/api/inventoryManagement/warehouse.js";
 
   const props = defineProps({
     visible: {
@@ -119,12 +139,16 @@
     productName: "",
     productModelName: "",
     unit: "",
+    warehouseId: undefined,
     type: undefined,
     qualitity: 0,
     batchNo: null,
     warnNum: 0,
     remark: "",
   });
+
+  // 浠撳簱鍒楄〃
+  const warehouseList = ref([]);
 
   const isShow = computed({
     get() {
@@ -136,6 +160,15 @@
   });
 
   const showProductSelectDialog = ref(false);
+
+  // 鑾峰彇浠撳簱鍒楄〃
+  const fetchWarehouseList = () => {
+    getWarehouseList({ status: true }).then(res => {
+      warehouseList.value = res.data || [];
+    }).catch(() => {
+      proxy.$modal.msgError("鑾峰彇浠撳簱鍒楄〃澶辫触");
+    });
+  };
 
   // 鎵瑰彿涓虹┖鏃惰浆涓� null
   watch(
@@ -157,6 +190,7 @@
       productName: "",
       productModelName: "",
       unit: "",
+      warehouseId: undefined,
       type: undefined,
       qualitity: 0,
       batchNo: null,
@@ -215,6 +249,11 @@
     });
   };
 
+  // 缁勪欢鎸傝浇鏃跺姞杞戒粨搴撳垪琛�
+  onMounted(() => {
+    fetchWarehouseList();
+  });
+
   defineExpose({
     closeModal,
     handleSubmit,
diff --git a/src/views/inventoryManagement/stockManagement/Record.vue b/src/views/inventoryManagement/stockManagement/Record.vue
index 0e16cca..cfa19ea 100644
--- a/src/views/inventoryManagement/stockManagement/Record.vue
+++ b/src/views/inventoryManagement/stockManagement/Record.vue
@@ -26,6 +26,7 @@
         <el-table-column label="浜у搧澶х被" prop="productName" show-overflow-tooltip />
         <el-table-column label="瑙勬牸鍨嬪彿" prop="model" show-overflow-tooltip />
         <el-table-column label="鍗曚綅" prop="unit" show-overflow-tooltip />
+        <el-table-column label="搴撲綅" prop="warehouseName" show-overflow-tooltip />
         <el-table-column label="鎵瑰彿" prop="batchNo" show-overflow-tooltip />
         <el-table-column label="鍚堟牸搴撳瓨鏁伴噺" prop="qualifiedQuantity" show-overflow-tooltip />
         <el-table-column label="涓嶅悎鏍煎簱瀛樻暟閲�" prop="unQualifiedQuantity" show-overflow-tooltip />

--
Gitblit v1.9.3