From b7e3bc6bbe2f6464f4f92e457212fac7ea61758d Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期二, 28 四月 2026 11:04:33 +0800
Subject: [PATCH] 领料功能

---
 src/views/productionManagement/workOrderManagement/components/MaterialDialog.vue |  502 ++++++++++++++++++++++++++++++-------------------------
 1 files changed, 272 insertions(+), 230 deletions(-)

diff --git a/src/views/productionManagement/workOrderManagement/components/MaterialDialog.vue b/src/views/productionManagement/workOrderManagement/components/MaterialDialog.vue
index 575d888..45944b5 100644
--- a/src/views/productionManagement/workOrderManagement/components/MaterialDialog.vue
+++ b/src/views/productionManagement/workOrderManagement/components/MaterialDialog.vue
@@ -1,86 +1,119 @@
 <template>
   <div>
-    <el-dialog
-      v-model="dialogVisible"
-      title="鐗╂枡"
-      width="1200px"
-      @close="handleCloseMaterialDialog"
-    >
-      <el-table v-loading="materialTableLoading" :data="materialTableData" border row-key="id">
-        <el-table-column label="宸ュ簭鍚嶇О" prop="processName" min-width="140" />
-        <el-table-column label="鍘熸枡鍚嶇О" prop="materialName" min-width="140" />
-        <el-table-column label="鍘熸枡鍨嬪彿" prop="materialModel" min-width="140" />
-        <el-table-column label="璁¢噺鍗曚綅" prop="unit" min-width="100" />
-        <el-table-column label="绾胯竟浠撴暟閲�" prop="pickQty" min-width="100" />
-        <el-table-column label="琛ユ枡鏁伴噺" prop="supplementQty" min-width="100" />
-        <el-table-column label="瀹為檯鏁伴噺" min-width="140">
+    <el-dialog v-model="dialogVisible"
+               title="鐗╂枡"
+               width="1200px"
+               @close="handleCloseMaterialDialog">
+      <el-table v-loading="materialTableLoading"
+                :data="materialTableData"
+                border
+                row-key="id">
+        <el-table-column label="宸ュ簭鍚嶇О"
+                         prop="processName"
+                         min-width="140" />
+        <el-table-column label="鍘熸枡鍚嶇О"
+                         prop="materialName"
+                         min-width="140" />
+        <el-table-column label="鍘熸枡鍨嬪彿"
+                         prop="materialModel"
+                         min-width="140" />
+        <el-table-column label="璁¢噺鍗曚綅"
+                         prop="unit"
+                         min-width="100" />
+        <el-table-column label="绾胯竟浠撴暟閲�"
+                         prop="pickQty"
+                         min-width="100" />
+        <el-table-column label="琛ユ枡鏁伴噺"
+                         prop="supplementQty"
+                         min-width="100" />
+        <el-table-column label="瀹為檯鏁伴噺"
+                         min-width="140">
           <template #default="{ row }">
-            <el-input-number
-              v-model="row.actualQty"
-              :min="0"
-              :precision="3"
-              :step="1"
-              controls-position="right"
-              style="width: 100%;"
-            />
+            <el-input-number v-model="row.actualQty"
+                             :min="0"
+                             :precision="3"
+                             :step="1"
+                             controls-position="right"
+                             style="width: 100%;" />
           </template>
         </el-table-column>
-        <el-table-column label="鎿嶄綔" align="center" fixed="right" width="180">
+        <el-table-column label="鎿嶄綔"
+                         align="center"
+                         fixed="right"
+                         width="180">
           <template #default="{ row }">
-            <el-button type="primary" link @click="openSupplementDialog(row)">琛ユ枡</el-button>
-            <el-button type="info" link @click="openSupplementRecordDialog(row)">琛ユ枡璁板綍</el-button>
+            <el-button type="primary"
+                       link
+                       @click="openSupplementDialog(row)">琛ユ枡</el-button>
+            <el-button type="info"
+                       link
+                       @click="openSupplementRecordDialog(row)">琛ユ枡璁板綍</el-button>
           </template>
         </el-table-column>
       </el-table>
       <template #footer>
         <span class="dialog-footer">
-          <el-button type="primary" :loading="pickSubmitting" @click="handleSubmitPick">棰嗙敤</el-button>
+          <el-button type="primary"
+                     :loading="pickSubmitting"
+                     @click="handleSubmitPick">棰嗙敤</el-button>
           <el-button @click="dialogVisible = false">鍙栨秷</el-button>
         </span>
       </template>
     </el-dialog>
-
-    <FormDialog
-      v-model="supplementDialogVisible"
-      title="琛ユ枡"
-      width="500px"
-      @confirm="handleSubmitSupplement"
-    >
-      <el-form ref="supplementFormRef" :model="supplementForm" :rules="supplementRules" label-width="100px">
-        <el-form-item label="琛ユ枡鏁伴噺" prop="supplementQty">
-          <el-input-number
-            v-model="supplementForm.supplementQty"
-            :min="0.001"
-            :precision="3"
-            :step="1"
-            style="width: 100%;"
-          />
+    <FormDialog v-model="supplementDialogVisible"
+                title="琛ユ枡"
+                width="500px"
+                @confirm="handleSubmitSupplement">
+      <el-form ref="supplementFormRef"
+               :model="supplementForm"
+               :rules="supplementRules"
+               label-width="100px">
+        <el-form-item label="琛ユ枡鏁伴噺"
+                      prop="supplementQty">
+          <el-input-number v-model="supplementForm.supplementQty"
+                           :min="0.001"
+                           :precision="3"
+                           :step="1"
+                           style="width: 100%;" />
         </el-form-item>
-        <el-form-item label="琛ユ枡鍘熷洜" prop="supplementReason">
-          <el-input
-            v-model="supplementForm.supplementReason"
-            type="textarea"
-            :rows="3"
-            maxlength="200"
-            show-word-limit
-            placeholder="璇疯緭鍏ヨˉ鏂欏師鍥�"
-          />
+        <el-form-item label="琛ユ枡鍘熷洜"
+                      prop="supplementReason">
+          <el-input v-model="supplementForm.supplementReason"
+                    type="textarea"
+                    :rows="3"
+                    maxlength="200"
+                    show-word-limit
+                    placeholder="璇疯緭鍏ヨˉ鏂欏師鍥�" />
         </el-form-item>
       </el-form>
       <template #footer>
         <span class="dialog-footer">
-          <el-button type="primary" :loading="supplementSubmitting" @click="handleSubmitSupplement">纭畾</el-button>
+          <el-button type="primary"
+                     :loading="supplementSubmitting"
+                     @click="handleSubmitSupplement">纭畾</el-button>
           <el-button @click="supplementDialogVisible = false">鍙栨秷</el-button>
         </span>
       </template>
     </FormDialog>
-
-    <el-dialog v-model="supplementRecordDialogVisible" title="琛ユ枡璁板綍" width="900px">
-      <el-table v-loading="supplementRecordLoading" :data="supplementRecordTableData" border row-key="id">
-        <el-table-column label="琛ユ枡鏁伴噺" prop="supplementQty" min-width="100" />
-        <el-table-column label="琛ユ枡鍘熷洜" prop="supplementReason" min-width="200" />
-        <el-table-column label="琛ユ枡浜�" prop="supplementUserName" min-width="120" />
-        <el-table-column label="琛ユ枡鏃ユ湡" prop="supplementTime" min-width="160" />
+    <el-dialog v-model="supplementRecordDialogVisible"
+               title="琛ユ枡璁板綍"
+               width="900px">
+      <el-table v-loading="supplementRecordLoading"
+                :data="supplementRecordTableData"
+                border
+                row-key="id">
+        <el-table-column label="琛ユ枡鏁伴噺"
+                         prop="supplementQty"
+                         min-width="100" />
+        <el-table-column label="琛ユ枡鍘熷洜"
+                         prop="supplementReason"
+                         min-width="200" />
+        <el-table-column label="琛ユ枡浜�"
+                         prop="supplementUserName"
+                         min-width="120" />
+        <el-table-column label="琛ユ枡鏃ユ湡"
+                         prop="supplementTime"
+                         min-width="160" />
       </el-table>
       <template #footer>
         <span class="dialog-footer">
@@ -92,187 +125,196 @@
 </template>
 
 <script setup>
-import { computed, nextTick, reactive, ref, watch } from "vue";
-import { ElMessage } from "element-plus";
-import FormDialog from "@/components/Dialog/FormDialog.vue";
-import {
-  listWorkOrderMaterialLedger,
-  addWorkOrderMaterialSupplement,
-  listWorkOrderMaterialSupplementRecord,
-  pickWorkOrderMaterial,
-} from "@/api/productionManagement/workOrder.js";
+  import { computed, nextTick, reactive, ref, watch } from "vue";
+  import { ElMessage } from "element-plus";
+  import FormDialog from "@/components/Dialog/FormDialog.vue";
+  import {
+    listWorkOrderMaterialLedger,
+    addWorkOrderMaterialSupplement,
+    listWorkOrderMaterialSupplementRecord,
+    pickWorkOrderMaterial,
+  } from "@/api/productionManagement/workOrder.js";
 
-const props = defineProps({
-  modelValue: {
-    type: Boolean,
-    default: false,
-  },
-  rowData: {
-    type: Object,
-    default: () => null,
-  },
-});
-
-const emit = defineEmits(["update:modelValue", "refresh"]);
-
-const dialogVisible = computed({
-  get: () => props.modelValue,
-  set: val => emit("update:modelValue", val),
-});
-
-const materialTableLoading = ref(false);
-const materialTableData = ref([]);
-const currentMaterialRow = ref(null);
-const currentMaterialOrderRow = ref(null);
-const pickSubmitting = ref(false);
-
-const supplementDialogVisible = ref(false);
-const supplementSubmitting = ref(false);
-const supplementFormRef = ref(null);
-const supplementForm = reactive({
-  supplementQty: null,
-  supplementReason: "",
-});
-
-const supplementRecordDialogVisible = ref(false);
-const supplementRecordLoading = ref(false);
-const supplementRecordTableData = ref([]);
-
-const supplementRules = {
-  supplementQty: [{ required: true, message: "璇疯緭鍏ヨˉ鏂欐暟閲�", trigger: "blur" }],
-  supplementReason: [{ required: true, message: "璇疯緭鍏ヨˉ鏂欏師鍥�", trigger: "blur" }],
-};
-const loadMaterialTable = async row => {
-  if (!row?.id) return;
-  currentMaterialOrderRow.value = row;
-  materialTableLoading.value = true;
-  materialTableData.value = [];
-  try {
-    const res = await listWorkOrderMaterialLedger({
-      workOrderId: row.id,
-      processId: row.processId,
-      productProcessRouteItemId: row.productProcessRouteItemId,
-    });
-    materialTableData.value = res.data || [];
-  } catch (e) {
-    console.error("鑾峰彇鐗╂枡鍙拌处澶辫触", e);
-    ElMessage.error("鑾峰彇鐗╂枡鍙拌处澶辫触");
-  } finally {
-    materialTableLoading.value = false;
-  }
-};
-
-watch(
-  () => props.modelValue,
-  visible => {
-    if (visible && props.rowData) {
-      loadMaterialTable(props.rowData);
-    }
-  }
-);
-
-const handleCloseMaterialDialog = () => {
-  materialTableData.value = [];
-  currentMaterialRow.value = null;
-  currentMaterialOrderRow.value = null;
-};
-
-const openSupplementDialog = row => {
-  currentMaterialRow.value = row;
-  supplementForm.supplementQty = null;
-  supplementForm.supplementReason = "";
-  supplementDialogVisible.value = true;
-  nextTick(() => {
-    supplementFormRef.value?.clearValidate();
+  const props = defineProps({
+    modelValue: {
+      type: Boolean,
+      default: false,
+    },
+    rowData: {
+      type: Object,
+      default: () => null,
+    },
   });
-};
 
-const handleSubmitSupplement = () => {
-  supplementFormRef.value?.validate(async valid => {
-    if (!valid || !currentMaterialRow.value?.id) {
-      ElMessage.warning("缂哄皯鐗╂枡鏄庣粏ID");
+  const emit = defineEmits(["update:modelValue", "refresh"]);
+
+  const dialogVisible = computed({
+    get: () => props.modelValue,
+    set: val => emit("update:modelValue", val),
+  });
+
+  const materialTableLoading = ref(false);
+  const materialTableData = ref([]);
+  const currentMaterialRow = ref(null);
+  const currentMaterialOrderRow = ref(null);
+  const pickSubmitting = ref(false);
+
+  const supplementDialogVisible = ref(false);
+  const supplementSubmitting = ref(false);
+  const supplementFormRef = ref(null);
+  const supplementForm = reactive({
+    supplementQty: null,
+    supplementReason: "",
+  });
+
+  const supplementRecordDialogVisible = ref(false);
+  const supplementRecordLoading = ref(false);
+  const supplementRecordTableData = ref([]);
+
+  const supplementRules = {
+    supplementQty: [
+      { required: true, message: "璇疯緭鍏ヨˉ鏂欐暟閲�", trigger: "blur" },
+    ],
+    supplementReason: [
+      { required: true, message: "璇疯緭鍏ヨˉ鏂欏師鍥�", trigger: "blur" },
+    ],
+  };
+  const loadMaterialTable = async row => {
+    if (!row?.id) return;
+    currentMaterialOrderRow.value = row;
+    materialTableLoading.value = true;
+    materialTableData.value = [];
+    try {
+      const res = await listWorkOrderMaterialLedger({
+        workOrderId: row.id,
+        processId: row.processId,
+        productProcessRouteItemId: row.productProcessRouteItemId,
+      });
+      materialTableData.value = res.data || [];
+    } catch (e) {
+      console.error("鑾峰彇鐗╂枡鍙拌处澶辫触", e);
+      ElMessage.error("鑾峰彇鐗╂枡鍙拌处澶辫触");
+    } finally {
+      materialTableLoading.value = false;
+    }
+  };
+
+  watch(
+    () => props.modelValue,
+    visible => {
+      if (visible && props.rowData) {
+        loadMaterialTable(props.rowData);
+      }
+    }
+  );
+
+  const handleCloseMaterialDialog = () => {
+    materialTableData.value = [];
+    currentMaterialRow.value = null;
+    currentMaterialOrderRow.value = null;
+  };
+
+  const openSupplementDialog = row => {
+    currentMaterialRow.value = row;
+    supplementForm.supplementQty = null;
+    supplementForm.supplementReason = "";
+    supplementDialogVisible.value = true;
+    nextTick(() => {
+      supplementFormRef.value?.clearValidate();
+    });
+  };
+
+  const handleSubmitSupplement = () => {
+    supplementFormRef.value?.validate(async valid => {
+      if (!valid || !currentMaterialRow.value?.id) {
+        ElMessage.warning("缂哄皯鐗╂枡鏄庣粏ID");
+        return;
+      }
+      supplementSubmitting.value = true;
+      try {
+        await addWorkOrderMaterialSupplement({
+          materialLedgerId: currentMaterialRow.value.id,
+          supplementQty: Number(supplementForm.supplementQty),
+          supplementReason: supplementForm.supplementReason,
+          workOrderId: currentMaterialOrderRow.value?.id,
+        });
+        supplementDialogVisible.value = false;
+        await loadMaterialTable(currentMaterialOrderRow.value);
+        ElMessage.success("琛ユ枡鎴愬姛");
+        emit("refresh");
+      } catch (e) {
+        console.error("琛ユ枡澶辫触", e);
+        ElMessage.error("琛ユ枡澶辫触");
+      } finally {
+        supplementSubmitting.value = false;
+      }
+    });
+  };
+
+  const openSupplementRecordDialog = async row => {
+    supplementRecordDialogVisible.value = true;
+    supplementRecordLoading.value = true;
+    supplementRecordTableData.value = [];
+    try {
+      const res = await listWorkOrderMaterialSupplementRecord({
+        materialLedgerId: row.id,
+      });
+      supplementRecordTableData.value = res.data || [];
+    } catch (e) {
+      console.error("鑾峰彇琛ユ枡璁板綍澶辫触", e);
+      ElMessage.error("鑾峰彇琛ユ枡璁板綍澶辫触");
+    } finally {
+      supplementRecordLoading.value = false;
+    }
+  };
+
+  const validatePickRows = () => {
+    if (materialTableData.value.length === 0) {
+      return { valid: false, message: "鏆傛棤鍙鐢ㄧ墿鏂�" };
+    }
+    const invalidRow = materialTableData.value.find(
+      item =>
+        item.actualQty === null ||
+        item.actualQty === undefined ||
+        item.actualQty === ""
+    );
+    if (invalidRow) {
+      return { valid: false, message: "璇峰~鍐欏疄闄呮暟閲忓悗鍐嶉鐢�" };
+    }
+    const exceedRow = materialTableData.value.find(item => {
+      const maxQty = Number(item.pickQty || 0) + Number(item.supplementQty || 0);
+      return Number(item.actualQty || 0) > maxQty;
+    });
+    if (exceedRow) {
+      return { valid: false, message: "瀹為檯鏁伴噺涓嶈兘澶т簬棰嗙敤鏁伴噺+琛ユ枡鏁伴噺" };
+    }
+    return { valid: true, message: "" };
+  };
+
+  const handleSubmitPick = async () => {
+    if (!currentMaterialOrderRow.value?.id) return;
+    const validateResult = validatePickRows();
+    if (!validateResult.valid) {
+      ElMessage.warning(validateResult.message);
       return;
     }
-    supplementSubmitting.value = true;
+    pickSubmitting.value = true;
     try {
-      await addWorkOrderMaterialSupplement({
-        materialLedgerId: currentMaterialRow.value.id,
-        supplementQty: Number(supplementForm.supplementQty),
-        supplementReason: supplementForm.supplementReason,
-        workOrderId: currentMaterialOrderRow.value?.id,
+      await pickWorkOrderMaterial({
+        workOrderId: currentMaterialOrderRow.value.id,
+        items: materialTableData.value.map(item => ({
+          materialLedgerId: item.id,
+          actualQty: Number(item.actualQty || 0),
+        })),
       });
-      supplementDialogVisible.value = false;
+      ElMessage.success("棰嗙敤鎴愬姛");
       await loadMaterialTable(currentMaterialOrderRow.value);
-      ElMessage.success("琛ユ枡鎴愬姛");
       emit("refresh");
     } catch (e) {
-      console.error("琛ユ枡澶辫触", e);
-      ElMessage.error("琛ユ枡澶辫触");
+      console.error("棰嗙敤澶辫触", e);
+      ElMessage.error("棰嗙敤澶辫触");
     } finally {
-      supplementSubmitting.value = false;
+      pickSubmitting.value = false;
     }
-  });
-};
-
-const openSupplementRecordDialog = async row => {
-  supplementRecordDialogVisible.value = true;
-  supplementRecordLoading.value = true;
-  supplementRecordTableData.value = [];
-  try {
-    const res = await listWorkOrderMaterialSupplementRecord({
-      materialLedgerId: row.id,
-    });
-    supplementRecordTableData.value = res.data || [];
-  } catch (e) {
-    console.error("鑾峰彇琛ユ枡璁板綍澶辫触", e);
-    ElMessage.error("鑾峰彇琛ユ枡璁板綍澶辫触");
-  } finally {
-    supplementRecordLoading.value = false;
-  }
-};
-
-const validatePickRows = () => {
-  if (materialTableData.value.length === 0) {
-    return { valid: false, message: "鏆傛棤鍙鐢ㄧ墿鏂�" };
-  }
-  const invalidRow = materialTableData.value.find(item => item.actualQty === null || item.actualQty === undefined || item.actualQty === "");
-  if (invalidRow) {
-    return { valid: false, message: "璇峰~鍐欏疄闄呮暟閲忓悗鍐嶉鐢�" };
-  }
-  const exceedRow = materialTableData.value.find(item => {
-    const maxQty = Number(item.pickQty || 0) + Number(item.supplementQty || 0);
-    return Number(item.actualQty || 0) > maxQty;
-  });
-  if (exceedRow) {
-    return { valid: false, message: "瀹為檯鏁伴噺涓嶈兘澶т簬棰嗙敤鏁伴噺+琛ユ枡鏁伴噺" };
-  }
-  return { valid: true, message: "" };
-};
-
-const handleSubmitPick = async () => {
-  if (!currentMaterialOrderRow.value?.id) return;
-  const validateResult = validatePickRows();
-  if (!validateResult.valid) {
-    ElMessage.warning(validateResult.message);
-    return;
-  }
-  pickSubmitting.value = true;
-  try {
-    await pickWorkOrderMaterial({
-      workOrderId: currentMaterialOrderRow.value.id,
-      items: materialTableData.value.map(item => ({
-        materialLedgerId: item.id,
-        actualQty: Number(item.actualQty || 0),
-      })),
-    });
-    ElMessage.success("棰嗙敤鎴愬姛");
-    await loadMaterialTable(currentMaterialOrderRow.value);
-    emit("refresh");
-  } catch (e) {
-    console.error("棰嗙敤澶辫触", e);
-    ElMessage.error("棰嗙敤澶辫触");
-  } finally {
-    pickSubmitting.value = false;
-  }
-};
+  };
 </script>

--
Gitblit v1.9.3