From 285a7c193147c844e7e27b71e74980d065f33e13 Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期四, 16 四月 2026 14:45:07 +0800
Subject: [PATCH] fix: 报工时可补料、退料

---
 src/views/productionManagement/workOrderManagement/index.vue |  305 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 304 insertions(+), 1 deletions(-)

diff --git a/src/views/productionManagement/workOrderManagement/index.vue b/src/views/productionManagement/workOrderManagement/index.vue
index 6def04c..9ffbd3f 100644
--- a/src/views/productionManagement/workOrderManagement/index.vue
+++ b/src/views/productionManagement/workOrderManagement/index.vue
@@ -163,6 +163,147 @@
         </span>
       </template>
     </el-dialog>
+
+    <el-dialog v-model="materialDialogVisible"
+               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="閫�鏂欐暟閲�"
+                         prop="returnQty"
+                         min-width="100" />
+        <el-table-column label="瀹為檯鏁伴噺"
+                         prop="actualQty"
+                         min-width="100" />
+        <el-table-column label="鎿嶄綔"
+                         align="center"
+                         fixed="right"
+                         width="220">
+          <template #default="{ row }">
+            <el-button type="primary"
+                       link
+                       @click="openSupplementDialog(row)">琛ユ枡</el-button>
+            <el-button type="warning"
+                       link
+                       @click="openReturnDialog(row)">閫�鏂�</el-button>
+            <el-button type="info"
+                       link
+                       @click="openSupplementRecordDialog(row)">琛ユ枡璁板綍</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </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%;" />
+        </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>
+      </el-form>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button type="primary"
+                     :loading="supplementSubmitting"
+                     @click="handleSubmitSupplement">纭畾</el-button>
+          <el-button @click="supplementDialogVisible = false">鍙栨秷</el-button>
+        </span>
+      </template>
+    </FormDialog>
+
+    <FormDialog v-model="returnDialogVisible"
+                title="閫�鏂�"
+                width="500px"
+                @confirm="handleSubmitReturn">
+      <el-form ref="returnFormRef"
+               :model="returnForm"
+               :rules="returnRules"
+               label-width="120px">
+        <el-form-item label="閫�鏂欐暟閲�"
+                      prop="returnQty">
+          <el-input-number v-model="returnForm.returnQty"
+                           :min="0.001"
+                           :precision="3"
+                           :step="1"
+                           style="width: 100%;" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button type="primary"
+                     :loading="returnSubmitting"
+                     @click="handleSubmitReturn">纭畾</el-button>
+          <el-button @click="returnDialogVisible = 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-table>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="supplementRecordDialogVisible = false">鍏抽棴</el-button>
+        </span>
+      </template>
+    </el-dialog>
     
     <FilesDia ref="workOrderFilesRef" />
   </div>
@@ -176,11 +317,16 @@
     productWorkOrderPage,
     addProductMain,
     downProductWorkOrder,
+    listWorkOrderMaterialLedger,
+    addWorkOrderMaterialSupplement,
+    addWorkOrderMaterialReturn,
+    listWorkOrderMaterialSupplementRecord,
   } from "@/api/productionManagement/workOrder.js";
   import { getUserProfile, userListNoPageByTenantId } from "@/api/system/user.js";
   import QRCode from "qrcode";
   import { getCurrentInstance, reactive, toRefs } from "vue";
   import FilesDia from "./components/filesDia.vue";
+  import FormDialog from "@/components/Dialog/FormDialog.vue";
   const { proxy } = getCurrentInstance();
 
   const tableColumn = ref([
@@ -255,7 +401,7 @@
     },
     {
       label: "鎿嶄綔",
-      width: "200",
+      width: "260",
       align: "center",
       dataType: "action",
       fixed: "right",
@@ -278,6 +424,12 @@
             showReportDialog(row);
           },
           disabled: row => row.planQuantity <= 0,
+        },
+        {
+          name: "鐗╂枡",
+          clickFun: row => {
+            openMaterialDialog(row);
+          },
         },
       ],
     },
@@ -340,6 +492,13 @@
     quantity: [{ required: true, validator: validateQuantity, trigger: "blur" }],
     scrapQty: [{ validator: validateScrapQty, trigger: "blur" }],
   };
+  const supplementRules = {
+    supplementQty: [{ required: true, message: "璇疯緭鍏ヨˉ鏂欐暟閲�", trigger: "blur" }],
+    supplementReason: [{ required: true, message: "璇疯緭鍏ヨˉ鏂欏師鍥�", trigger: "blur" }],
+  };
+  const returnRules = {
+    returnQty: [{ required: true, message: "璇疯緭鍏ラ��鏂欐暟閲�", trigger: "blur" }],
+  };
 
   // 澶勭悊鏈鐢熶骇鏁伴噺杈撳叆锛岄檺鍒跺繀椤诲ぇ浜庣瓑浜�1
   const handleQuantityInput = value => {
@@ -396,6 +555,27 @@
   };
   
   const currentReportRowData = ref(null);
+  const materialDialogVisible = ref(false);
+  const materialTableLoading = ref(false);
+  const materialTableData = ref([]);
+  const currentMaterialRow = ref(null);
+  const currentMaterialOrderRow = ref(null);
+  const supplementDialogVisible = ref(false);
+  const supplementSubmitting = ref(false);
+  const supplementFormRef = ref(null);
+  const supplementForm = reactive({
+    supplementQty: null,
+    supplementReason: "",
+  });
+  const returnDialogVisible = ref(false);
+  const returnSubmitting = ref(false);
+  const returnFormRef = ref(null);
+  const returnForm = reactive({
+    returnQty: null,
+  });
+  const supplementRecordDialogVisible = ref(false);
+  const supplementRecordLoading = ref(false);
+  const supplementRecordTableData = ref([]);
   const page = reactive({
     current: 1,
     size: 100,
@@ -547,6 +727,129 @@
     reportDialogVisible.value = true;
   };
 
+  const openMaterialDialog = async row => {
+    currentMaterialOrderRow.value = row;
+    materialDialogVisible.value = true;
+    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);
+      proxy.$modal.msgError("鑾峰彇鐗╂枡鍙拌处澶辫触");
+    } finally {
+      materialTableLoading.value = false;
+    }
+  };
+
+  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) return;
+      if (!currentMaterialRow.value?.id) {
+        proxy.$modal.msgWarning("缂哄皯鐗╂枡鏄庣粏ID");
+        return;
+      }
+      supplementSubmitting.value = true;
+      try {
+        await addWorkOrderMaterialSupplement({
+          materialLedgerId: currentMaterialRow.value.id,
+          supplementQty: Number(supplementForm.supplementQty),
+          supplementReason: supplementForm.supplementReason,
+          workOrderId: currentMaterialOrderRow.value?.id,
+        });
+        proxy.$modal.msgSuccess("琛ユ枡鎴愬姛");
+        supplementDialogVisible.value = false;
+        await openMaterialDialog(currentMaterialOrderRow.value);
+      } catch (e) {
+        console.error("琛ユ枡澶辫触", e);
+        proxy.$modal.msgError("琛ユ枡澶辫触");
+      } finally {
+        supplementSubmitting.value = false;
+      }
+    });
+  };
+
+  const openReturnDialog = row => {
+    currentMaterialRow.value = row;
+    returnForm.returnQty = null;
+    returnDialogVisible.value = true;
+    nextTick(() => {
+      returnFormRef.value?.clearValidate();
+    });
+  };
+
+  const handleSubmitReturn = () => {
+    returnFormRef.value?.validate(async valid => {
+      if (!valid) return;
+      if (!currentMaterialRow.value?.id) {
+        proxy.$modal.msgWarning("缂哄皯鐗╂枡鏄庣粏ID");
+        return;
+      }
+      const returnQty = Number(returnForm.returnQty);
+      const minQty =
+        Number(currentMaterialRow.value.pickQty || 0) +
+        Number(currentMaterialRow.value.supplementQty || 0);
+      if (returnQty < minQty) {
+        proxy.$modal.msgWarning(`閫�鏂欐暟閲忎笉鑳戒綆浜庨鐢ㄦ暟閲�+琛ユ枡鏁伴噺锛�${minQty}锛塦);
+        return;
+      }
+      returnSubmitting.value = true;
+      try {
+        await addWorkOrderMaterialReturn({
+          materialLedgerId: currentMaterialRow.value.id,
+          returnQty,
+          workOrderId: currentMaterialOrderRow.value?.id,
+        });
+        proxy.$modal.msgSuccess("閫�鏂欐垚鍔�");
+        returnDialogVisible.value = false;
+        await openMaterialDialog(currentMaterialOrderRow.value);
+      } catch (e) {
+        console.error("閫�鏂欏け璐�", e);
+        proxy.$modal.msgError("閫�鏂欏け璐�");
+      } finally {
+        returnSubmitting.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);
+      proxy.$modal.msgError("鑾峰彇琛ユ枡璁板綍澶辫触");
+    } finally {
+      supplementRecordLoading.value = false;
+    }
+  };
+
   const handleReport = () => {
     reportFormRef.value?.validate(valid => {
       if (!valid) {

--
Gitblit v1.9.3