gaoluyang
2026-05-14 a8d694d5d987892afee5a1bb8f6c01d612e6b2a3
浪潮
1.入库管理、出库管理添加库位相关字段和逻辑
已修改5个文件
359 ■■■■ 文件已修改
src/components/PIMTable/PIMTable.vue 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/dispatchLog/Record.vue 169 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/receiptManagement/Record.vue 65 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/stockManagement/New.vue 65 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/stockManagement/Record.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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">
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;
    // 从batchNoMaps获取批号列表和库存
    if (product.batchNoMaps && Object.keys(product.batchNoMaps).length > 0) {
      batchNoList.value = Object.keys(product.batchNoMaps);
      batchNoStockMap.value = product.batchNoMaps;
    } else {
      batchNoList.value = [];
      batchNoStockMap.value = {};
    }
    // 清空已选择的批号和最大库存
    // 解析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]) {
    // 解析该仓库下的批号数据,格式为:[{批号: 库存}, {批号: 库存}]
    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]) {
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"
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,
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 />