From a563ea879ef5fb6897e76d2df661e465dce2ab9b Mon Sep 17 00:00:00 2001
From: huminmin <mac@MacBook-Pro.local>
Date: 星期一, 01 六月 2026 15:02:27 +0800
Subject: [PATCH] Merge branch 'dev_新疆_大罗素马铃薯new' of http://114.132.189.42:9002/r/product-inventory-management into dev_新疆_大罗素马铃薯new

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

diff --git a/src/views/productionManagement/workOrderManagement/components/MaterialDialog.vue b/src/views/productionManagement/workOrderManagement/components/MaterialDialog.vue
new file mode 100644
index 0000000..45944b5
--- /dev/null
+++ b/src/views/productionManagement/workOrderManagement/components/MaterialDialog.vue
@@ -0,0 +1,320 @@
+<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">
+          <template #default="{ row }">
+            <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">
+          <template #default="{ row }">
+            <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 @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%;" />
+        </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>
+    <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>
+  </div>
+</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";
+
+  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 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;
+    }
+    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