From 664bba7725ee0dcdcb29bb218a81f78f3f7aefc4 Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期五, 24 四月 2026 14:09:28 +0800
Subject: [PATCH] 修改

---
 src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue |  517 ++++++++++++++++++++++++++++++---------------------------
 1 files changed, 273 insertions(+), 244 deletions(-)

diff --git a/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue b/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue
index 9e1a852..6b040d6 100644
--- a/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue
+++ b/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue
@@ -1,298 +1,327 @@
 <template>
   <div>
-    <el-dialog v-model="dialogVisible" title="棰嗘枡鍙拌处" width="1200px" @close="handleClose">
+    <el-dialog v-model="dialogVisible"
+               title="棰嗘枡鍙拌处"
+               width="1200px"
+               @close="handleClose">
       <div class="material-toolbar">
-        <el-button type="primary" @click="handleAddMaterialRow">鏂板</el-button>
+        <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">
+      <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 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">
+        <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)">
+            <el-button v-else
+                       type="primary"
+                       link
+                       @click="openMaterialProductSelect(row)">
               {{ row.materialName || "閫夋嫨鍘熸枡" }}
             </el-button>
           </template>
         </el-table-column>
-        <el-table-column label="鍘熸枡鍨嬪彿" min-width="180">
+        <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>
-            <el-input-number
-              v-else
-              v-model="row.requiredQty"
-              :min="0"
-              :precision="3"
-              :step="1"
-              controls-position="right"
-              style="width: 100%;"
-              @change="val => handleRequiredQtyChange(row, val)"
-            />
+            <el-input-number v-else
+                             v-model="row.requiredQty"
+                             :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">
+        <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"
-              :min="0"
-              :precision="3"
-              :step="1"
-              controls-position="right"
-              style="width: 100%;"
-            />
+            <el-input-number v-model="row.pickQty"
+                             :min="0"
+                             :precision="3"
+                             :step="1"
+                             controls-position="right"
+                             style="width: 100%;" />
           </template>
         </el-table-column>
-        <el-table-column label="鎿嶄綔" width="90" fixed="right">
+        <el-table-column label="鎿嶄綔"
+                         width="90"
+                         fixed="right">
           <template #default="{ $index, row }">
-            <el-button v-if="row.bom !== true" type="danger" link @click="handleDeleteMaterialRow($index)">鍒犻櫎</el-button>
+            <el-button v-if="row.bom !== true"
+                       type="danger"
+                       link
+                       @click="handleDeleteMaterialRow($index)">鍒犻櫎</el-button>
           </template>
         </el-table-column>
       </el-table>
       <template #footer>
         <span class="dialog-footer">
-          <el-button type="primary" :loading="materialSaving" @click="handleMaterialSave">淇濆瓨</el-button>
+          <el-button type="primary"
+                     :loading="materialSaving"
+                     @click="handleMaterialSave">淇濆瓨</el-button>
           <el-button @click="dialogVisible = false">鍙栨秷</el-button>
         </span>
       </template>
     </el-dialog>
-
-    <ProductSelectDialog
-      v-model="materialProductDialogVisible"
-      @confirm="handleMaterialProductConfirm"
-      single
-      request-url="/stockInventory/rawMaterials"
-    />
+    <ProductSelectDialog v-model="materialProductDialogVisible"
+                         @confirm="handleMaterialProductConfirm"
+                         single />
+    <!-- request-url="/stockInventory/rawMaterials" -->
   </div>
 </template>
 
 <script setup>
-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,
-  saveMaterialPickingLedger,
-} from "@/api/productionManagement/productionOrder.js";
+  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,
+    saveMaterialPickingLedger,
+  } from "@/api/productionManagement/productionOrder.js";
 
-const props = defineProps({
-  modelValue: { type: Boolean, default: false },
-  orderRow: { type: Object, default: null },
-});
-const emit = defineEmits(["update:modelValue", "saved"]);
-
-const dialogVisible = computed({
-  get: () => props.modelValue,
-  set: val => emit("update:modelValue", val),
-});
-
-const materialProductDialogVisible = ref(false);
-const materialTableLoading = ref(false);
-const materialSaving = ref(false);
-const materialTableData = ref([]);
-const processOptions = ref([]);
-const currentMaterialSelectRowIndex = ref(-1);
-let materialTempId = 0;
-
-const createMaterialRow = (row = {}) => ({
-  tempId: row.id || `temp_${++materialTempId}`,
-  id: row.id,
-  processId: row.processId,
-  productProcessId: row.productProcessId || row.processId,
-  processName: row.processName || "",
-  bom: row.bom === true,
-  materialModelId: row.materialModelId,
-  materialName: row.materialName || "",
-  materialModel: row.materialModel || "",
-  requiredQty: Number(row.requiredQty ?? 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,
-      });
-    }
+  const props = defineProps({
+    modelValue: { type: Boolean, default: false },
+    orderRow: { type: Object, default: null },
   });
-  processOptions.value = Array.from(processMap.values());
-};
+  const emit = defineEmits(["update:modelValue", "saved"]);
 
-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 detailList = Array.isArray(detailRes?.data)
-      ? detailRes.data
-      : detailRes?.data?.records || [];
-    if (detailList.length > 0) {
-      materialTableData.value = detailList.map(item => createMaterialRow(item));
+  const dialogVisible = computed({
+    get: () => props.modelValue,
+    set: val => emit("update:modelValue", val),
+  });
+
+  const materialProductDialogVisible = ref(false);
+  const materialTableLoading = ref(false);
+  const materialSaving = ref(false);
+  const materialTableData = ref([]);
+  const processOptions = ref([]);
+  const currentMaterialSelectRowIndex = ref(-1);
+  let materialTempId = 0;
+
+  const createMaterialRow = (row = {}) => ({
+    tempId: row.id || `temp_${++materialTempId}`,
+    id: row.id,
+    processId: row.processId,
+    productProcessId: row.productProcessId || row.processId,
+    processName: row.processName || "",
+    bom: row.bom === true,
+    materialModelId: row.materialModelId,
+    materialName: row.materialName || "",
+    materialModel: row.materialModel || "",
+    requiredQty: Number(row.requiredQty ?? 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 detailList = Array.isArray(detailRes?.data)
+        ? detailRes.data
+        : detailRes?.data?.records || [];
+      if (detailList.length > 0) {
+        materialTableData.value = detailList.map(item => createMaterialRow(item));
+        return;
+      }
+      const ledgerRes = await listMaterialPickingLedger({
+        orderId: props.orderRow.id,
+      });
+      const ledgerList = Array.isArray(ledgerRes?.data)
+        ? ledgerRes.data
+        : ledgerRes?.data?.records || [];
+      materialTableData.value = ledgerList.map(item => createMaterialRow(item));
+    } finally {
+      materialTableLoading.value = false;
+    }
+  };
+
+  watch(
+    () => dialogVisible.value,
+    visible => {
+      if (visible) {
+        loadMaterialData();
+      }
+    }
+  );
+
+  const handleClose = () => {
+    materialTableData.value = [];
+    currentMaterialSelectRowIndex.value = -1;
+  };
+
+  const handleAddMaterialRow = () => {
+    materialTableData.value.push(createMaterialRow());
+  };
+
+  const handleDeleteMaterialRow = index => {
+    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;
+  };
+
+  const handleMaterialProductConfirm = products => {
+    if (!products || products.length === 0) return;
+    const index = currentMaterialSelectRowIndex.value;
+    if (index < 0 || !materialTableData.value[index]) return;
+    const product = products[0];
+    const row = materialTableData.value[index];
+    row.materialModelId =
+      product.materialModelId || product.modelId || product.id;
+    row.materialName =
+      product.materialName || product.productName || product.name || "";
+    row.materialModel = product.materialModel || product.model || "";
+    row.unit = product.unit || product.measureUnit || "";
+    currentMaterialSelectRowIndex.value = -1;
+    materialProductDialogVisible.value = false;
+  };
+
+  const validateMaterialRows = () => {
+    if (materialTableData.value.length === 0) {
+      return { valid: false, message: "璇峰厛鏂板棰嗘枡鏁版嵁" };
+    }
+    const invalidNewRow = materialTableData.value.find(
+      item => item.bom !== true && (!item.processName || !item.materialName)
+    );
+    if (invalidNewRow) {
+      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
+    );
+    if (invalidRow) {
+      return { valid: false, message: "璇峰畬鍠勫伐搴忋�佸師鏂欏拰鏁伴噺鍚庡啀淇濆瓨" };
+    }
+    return { valid: true, message: "" };
+  };
+
+  const handleMaterialSave = async () => {
+    if (!props.orderRow?.id) return;
+    const validateResult = validateMaterialRows();
+    if (!validateResult.valid) {
+      ElMessage.warning(validateResult.message);
       return;
     }
-    const ledgerRes = await listMaterialPickingLedger({ orderId: props.orderRow.id });
-    const ledgerList = Array.isArray(ledgerRes?.data)
-      ? ledgerRes.data
-      : ledgerRes?.data?.records || [];
-    materialTableData.value = ledgerList.map(item => createMaterialRow(item));
-  } finally {
-    materialTableLoading.value = false;
-  }
-};
-
-watch(
-  () => dialogVisible.value,
-  visible => {
-    if (visible) {
-      loadMaterialData();
+    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,
+        })),
+      });
+      emit("saved");
+      dialogVisible.value = false;
+    } finally {
+      materialSaving.value = false;
     }
-  }
-);
-
-const handleClose = () => {
-  materialTableData.value = [];
-  currentMaterialSelectRowIndex.value = -1;
-};
-
-const handleAddMaterialRow = () => {
-  materialTableData.value.push(createMaterialRow());
-};
-
-const handleDeleteMaterialRow = index => {
-  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;
-};
-
-const handleMaterialProductConfirm = products => {
-  if (!products || products.length === 0) return;
-  const index = currentMaterialSelectRowIndex.value;
-  if (index < 0 || !materialTableData.value[index]) return;
-  const product = products[0];
-  const row = materialTableData.value[index];
-  row.materialModelId = product.materialModelId || product.modelId || product.id;
-  row.materialName = product.materialName || product.productName || product.name || "";
-  row.materialModel = product.materialModel || product.model || "";
-  row.unit = product.unit || product.measureUnit || "";
-  currentMaterialSelectRowIndex.value = -1;
-  materialProductDialogVisible.value = false;
-};
-
-const validateMaterialRows = () => {
-  if (materialTableData.value.length === 0) {
-    return { valid: false, message: "璇峰厛鏂板棰嗘枡鏁版嵁" };
-  }
-  const invalidNewRow = materialTableData.value.find(
-    item => item.bom !== true && (!item.processName || !item.materialName)
-  );
-  if (invalidNewRow) {
-    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
-  );
-  if (invalidRow) {
-    return { valid: false, message: "璇峰畬鍠勫伐搴忋�佸師鏂欏拰鏁伴噺鍚庡啀淇濆瓨" };
-  }
-  return { valid: true, message: "" };
-};
-
-const handleMaterialSave = async () => {
-  if (!props.orderRow?.id) return;
-  const validateResult = validateMaterialRows();
-  if (!validateResult.valid) {
-    ElMessage.warning(validateResult.message);
-    return;
-  }
-  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,
-      })),
-    });
-    emit("saved");
-    dialogVisible.value = false;
-  } finally {
-    materialSaving.value = false;
-  }
-};
+  };
 </script>
 
 <style scoped lang="scss">
-.material-toolbar {
-  margin-bottom: 12px;
-  text-align: right;
-}
+  .material-toolbar {
+    margin-bottom: 12px;
+    text-align: right;
+  }
 </style>

--
Gitblit v1.9.3