gaoluyang
2026-04-25 4e62fd388119141405e33ecc28cad2638617603f
src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue
@@ -5,59 +5,61 @@
        <el-button type="primary" @click="handleAddMaterialRow">新增</el-button>
      </div>
      <el-table v-loading="materialTableLoading" :data="materialTableData" border row-key="tempId">
        <el-table-column label="工序名称" min-width="180">
          <template #default="{ row }">
            <span v-if="row.bom === true">{{ row.processName || "-" }}</span>
            <el-select
              v-else
              v-model="row.processName"
              placeholder="请选择工序"
              clearable
              filterable
              style="width: 100%;"
              @change="val => handleProcessNameChange(row, val)"
            >
              <el-option v-for="item in processOptions" :key="item.id" :label="item.name" :value="item.name" />
            </el-select>
          </template>
        </el-table-column>
        <el-table-column label="原料名称" min-width="160">
          <template #default="{ row }">
            <span v-if="row.bom === true">{{ row.materialName || "-" }}</span>
            <el-button v-else type="primary" link @click="openMaterialProductSelect(row)">
              {{ row.materialName || "选择原料" }}
            </el-button>
          </template>
        <el-table-column label="原料名称" min-width="160" prop="materialName">
        </el-table-column>
        <el-table-column label="原料型号" min-width="180">
          <template #default="{ row }">
            {{ row.materialModel || "-" }}
          </template>
        </el-table-column>
        <el-table-column label="需求数量" min-width="120">
        <el-table-column label="原纸需要量" min-width="120">
          <template #default="{ row }">
            <span v-if="row.bom === true">{{ row.requiredQty ?? "-" }}</span>
            {{ row.basePaperQty ?? "-" }}
          </template>
        </el-table-column>
        <el-table-column label="纸箱需要量" min-width="120">
          <template #default="{ row }">
            {{ row.cartonQty ?? "-" }}
          </template>
        </el-table-column>
        <el-table-column label="塑料袋数量" min-width="120">
          <template #default="{ row }">
            {{ row.plasticBagQty ?? "-" }}
          </template>
        </el-table-column>
<!--        <el-table-column label="计量单位" width="120">-->
<!--          <template #default="{ row }">-->
<!--            {{ row.unit || "-" }}-->
<!--          </template>-->
<!--        </el-table-column>-->
        <el-table-column label="原纸领用数量" min-width="120">
          <template #default="{ row }">
            <el-input-number
              v-else
              v-model="row.requiredQty"
              v-model="row.basePaperPickQty"
              :min="0"
              :precision="3"
              :step="1"
              controls-position="right"
              style="width: 100%;"
              @change="val => handleRequiredQtyChange(row, val)"
            />
          </template>
        </el-table-column>
        <el-table-column label="计量单位" width="120">
          <template #default="{ row }">
            {{ row.unit || "-" }}
          </template>
        </el-table-column>
        <el-table-column label="领用数量" min-width="120">
        <el-table-column label="纸箱领用数量" min-width="120">
          <template #default="{ row }">
            <el-input-number
              v-model="row.pickQty"
              v-model="row.cartonPickQty"
              :min="0"
              :precision="3"
              :step="1"
              controls-position="right"
              style="width: 100%;"
            />
          </template>
        </el-table-column>
        <el-table-column label="塑料袋领用数量" min-width="120">
          <template #default="{ row }">
            <el-input-number
              v-model="row.plasticBagPickQty"
              :min="0"
              :precision="3"
              :step="1"
@@ -84,7 +86,6 @@
      v-model="materialProductDialogVisible"
      @confirm="handleMaterialProductConfirm"
      single
      request-url="/stockInventory/rawMaterials"
    />
  </div>
</template>
@@ -93,7 +94,6 @@
import { computed, ref, watch } from "vue";
import { ElMessage } from "element-plus";
import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
import { findProductProcessRouteItemList } from "@/api/productionManagement/productProcessRoute.js";
import {
  listMaterialPickingDetail,
  listMaterialPickingLedger,
@@ -115,7 +115,6 @@
const materialTableLoading = ref(false);
const materialSaving = ref(false);
const materialTableData = ref([]);
const processOptions = ref([]);
const currentMaterialSelectRowIndex = ref(-1);
let materialTempId = 0;
@@ -129,38 +128,21 @@
  materialModelId: row.materialModelId,
  materialName: row.materialName || "",
  materialModel: row.materialModel || "",
  requiredQty: Number(row.requiredQty ?? 0),
  basePaperQty: Number(row.basePaperQty ?? row.requiredQty ?? 0),
  cartonQty: Number(row.cartonQty ?? 0),
  plasticBagQty: Number(row.plasticBagQty ?? 0),
  basePaperPickQty: Number(row.basePaperPickQty ?? row.pickQty ?? 0),
  cartonPickQty: Number(row.cartonPickQty ?? 0),
  plasticBagPickQty: Number(row.plasticBagPickQty ?? 0),
  unit: row.unit || "",
  pickQty: Number(row.pickQty ?? row.requiredQty ?? 0),
});
const getProcessOptions = async () => {
  if (!props.orderRow?.id) return;
  const res = await findProductProcessRouteItemList({ orderId: props.orderRow.id });
  const routeList = Array.isArray(res?.data) ? res.data : res?.data?.records || [];
  const processMap = new Map();
  routeList.forEach(item => {
    const processId = item.processId;
    const processName = item.processName;
    if (!processId || !processName) return;
    const key = `${processId}_${processName}`;
    if (!processMap.has(key)) {
      processMap.set(key, {
        id: processId,
        name: processName,
      });
    }
  });
  processOptions.value = Array.from(processMap.values());
};
const loadMaterialData = async () => {
  if (!props.orderRow?.id) return;
  materialTableLoading.value = true;
  materialTableData.value = [];
  await getProcessOptions();
  try {
    const detailRes = await listMaterialPickingDetail({ orderId: props.orderRow.id });
    const detailRes = await listMaterialPickingDetail({ productOrderId: props.orderRow.id });
    const detailList = Array.isArray(detailRes?.data)
      ? detailRes.data
      : detailRes?.data?.records || [];
@@ -200,19 +182,6 @@
  materialTableData.value.splice(index, 1);
};
const handleProcessNameChange = (row, processName) => {
  const process = processOptions.value.find(item => item.name === processName);
  row.productProcessId = process?.id;
};
const handleRequiredQtyChange = (row, val) => {
  const required = Number(val ?? 0);
  row.requiredQty = required;
  if (!row.pickQty || Number(row.pickQty) === 0) {
    row.pickQty = required;
  }
};
const openMaterialProductSelect = row => {
  currentMaterialSelectRowIndex.value = materialTableData.value.findIndex(item => item.tempId === row.tempId);
  materialProductDialogVisible.value = true;
@@ -237,22 +206,23 @@
    return { valid: false, message: "请先新增领料数据" };
  }
  const invalidNewRow = materialTableData.value.find(
    item => item.bom !== true && (!item.processName || !item.materialName)
    item => item.bom !== true && !item.materialName
  );
  if (invalidNewRow) {
    return { valid: false, message: "新增行的工序名称和原料名称为必填项" };
    return { valid: false, message: "新增行的原料名称为必填项" };
  }
  const invalidRow = materialTableData.value.find(
    item =>
      !item.processName ||
      !item.materialName ||
      item.requiredQty === null ||
      item.requiredQty === undefined ||
      item.pickQty === null ||
      item.pickQty === undefined
      item.basePaperPickQty === null ||
      item.basePaperPickQty === undefined ||
      item.cartonPickQty === null ||
      item.cartonPickQty === undefined ||
      item.plasticBagPickQty === null ||
      item.plasticBagPickQty === undefined
  );
  if (invalidRow) {
    return { valid: false, message: "请完善工序、原料和数量后再保存" };
    return { valid: false, message: "请完善领用数量后再保存" };
  }
  return { valid: true, message: "" };
};
@@ -266,22 +236,7 @@
  }
  materialSaving.value = true;
  try {
    await saveMaterialPickingLedger({
      orderId: props.orderRow.id,
      items: materialTableData.value.map(item => ({
        id: item.id,
        processId: item.processName,
        productProcessId: item.productProcessId,
        processName: item.processName,
        bom: item.bom === true,
        materialModelId: item.materialModelId,
        materialName: item.materialName,
        materialModel: item.materialModel,
        requiredQty: item.requiredQty,
        unit: item.unit,
        pickQty: item.pickQty,
      })),
    });
    await saveMaterialPickingLedger(materialTableData.value[0]);
    emit("saved");
    dialogVisible.value = false;
  } finally {