gongchunyi
2026-09-20 7f58edd8ff6fdadbe7b1d15cf86ffe7b47dc4fe3
src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue
@@ -19,6 +19,10 @@
        <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 }">
@@ -63,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>
@@ -246,8 +252,13 @@
      stockQty: null,
      batchNo: [],
      batchNoList,
      batchQtyMap: {},
    };
  };
  // 批号选项展示为“批号(库存数量)”
  const getBatchOptionLabel = (row, batchNo) =>
    `${batchNo}(${stripTrailingZeros(row.batchQtyMap?.[batchNo] ?? 0)})`;
  const getProcessOptions = async () => {
    if (!props.orderRow?.id) return;
@@ -374,14 +385,7 @@
      // 先查出库存余量再入表,保证首次打开即展示(rows 尚未转为响应式代理,
      // 入表后再改原始对象不会触发视图更新)
      await loadStockQtyForRows(rows);
      // 打开领料台账默认:自动选中第一个可用批号,领用数量=需求数量
      rows.forEach(row => {
        const batchNoList = Array.isArray(row.batchNoList) ? row.batchNoList : [];
        if (batchNoList.length > 0) {
          row.batchNo = [batchNoList[0]];
          row.pickQty = toNumber(row.demandedQuantity);
        }
      });
      // 打开领料台账不默认选中批号:只有手动选择了批号的行才会领料
      materialTableData.value = rows;
    } finally {
      materialTableLoading.value = false;
@@ -403,12 +407,13 @@
    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 {
@@ -416,24 +421,34 @@
          const list = Array.isArray(res?.data)
            ? res.data
            : res?.data?.records || res?.data?.rows || [];
          const total = list.reduce(
            (sum, item) => sum + toNumber(item?.qualitity ?? item?.quantity),
            0
          );
          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) || {};
    });
  };
@@ -479,6 +494,17 @@
    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) => {
    const required = roundQuantity(val);
    row.demandedQuantity = required;
@@ -509,6 +535,7 @@
    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]);