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/productionOrder/components/MaterialDetailDialog.vue |  284 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 284 insertions(+), 0 deletions(-)

diff --git a/src/views/productionManagement/productionOrder/components/MaterialDetailDialog.vue b/src/views/productionManagement/productionOrder/components/MaterialDetailDialog.vue
new file mode 100644
index 0000000..370815e
--- /dev/null
+++ b/src/views/productionManagement/productionOrder/components/MaterialDetailDialog.vue
@@ -0,0 +1,284 @@
+<template>
+  <div>
+    <el-dialog v-model="dialogVisible"
+               title="棰嗘枡璇︽儏"
+               width="1400px"
+               @close="handleClose">
+      <el-table v-loading="materialDetailLoading"
+                :data="materialDetailTableData"
+                border
+                row-key="id">
+        <el-table-column label="宸ュ簭鍚嶇О"
+                         prop="operationName"
+                         min-width="180" />
+        <el-table-column label="鍘熸枡鍚嶇О"
+                         prop="productName"
+                         min-width="160" />
+        <el-table-column label="鍘熸枡鍨嬪彿"
+                         prop="model"
+                         min-width="180" />
+        <el-table-column label="鎵瑰彿"
+                         prop="batchNo"
+                         min-width="150" />
+        <el-table-column label="闇�姹傛暟閲�"
+                         prop="demandedQuantity"
+                         min-width="110" />
+        <el-table-column label="璁¢噺鍗曚綅"
+                         prop="unit"
+                         width="100" />
+        <el-table-column label="棰嗙敤鏁伴噺"
+                         prop="pickQuantity"
+                         min-width="110" />
+        <el-table-column label="琛ユ枡鏁伴噺"
+                         min-width="120">
+          <template #default="{ row }">
+            <el-button type="primary"
+                       link
+                       @click="handleViewSupplementRecord(row)">
+              {{ row.feedingQty ?? 0 }}
+            </el-button>
+          </template>
+        </el-table-column>
+        <el-table-column label="閫�鏂欐暟閲�"
+                         min-width="110">
+          <template #default="{ row }">
+            {{ row.returnQty ?? 0 }}
+          </template>
+        </el-table-column>
+        <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"
+                             placeholder="杈撳叆瀹為檯鏁伴噺"
+                             style="width: 100%;"
+                             :disabled="row.returned || orderRow?.end"
+                             @change="val => handleActualQtyChange(row, val)" />
+          </template>
+        </el-table-column>
+      </el-table>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button v-if="!orderRow?.end"
+                     type="warning"
+                     :loading="materialReturnConfirming"
+                     :disabled="!canOpenReturnSummary"
+                     @click="openReturnSummaryDialog">
+            閫�鏂欑‘璁�
+          </el-button>
+          <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+        </span>
+      </template>
+    </el-dialog>
+    <el-dialog v-model="supplementRecordDialogVisible"
+               title="琛ユ枡璁板綍"
+               width="800px">
+      <el-table v-loading="supplementRecordLoading"
+                :data="supplementRecordTableData"
+                border
+                row-key="id">
+        <el-table-column label="琛ユ枡鏁伴噺"
+                         prop="pickQuantity"
+                         min-width="120" />
+        <el-table-column label="琛ユ枡浜�"
+                         prop="supplementUserName"
+                         min-width="120" />
+        <el-table-column label="琛ユ枡鏃ユ湡"
+                         prop="supplementTime"
+                         min-width="160" />
+        <el-table-column label="琛ユ枡鍘熷洜"
+                         prop="feedingReason"
+                         min-width="200" />
+      </el-table>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="supplementRecordDialogVisible = false">鍏抽棴</el-button>
+        </span>
+      </template>
+    </el-dialog>
+    <el-dialog v-model="returnSummaryDialogVisible"
+               title="閫�鏂欐眹鎬荤‘璁�"
+               width="900px">
+      <el-table :data="returnSummaryList"
+                border
+                row-key="summaryKey">
+        <el-table-column label="鍘熸枡鍚嶇О"
+                         prop="materialName"
+                         min-width="180" />
+        <el-table-column label="鍘熸枡鍨嬪彿"
+                         prop="materialModel"
+                         min-width="180" />
+        <el-table-column label="璁¢噺鍗曚綅"
+                         prop="unit"
+                         min-width="100" />
+        <el-table-column label="閫�鏂欐眹鎬绘暟閲�"
+                         prop="returnQtyTotal"
+                         min-width="140" />
+      </el-table>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button type="primary"
+                     :loading="materialReturnConfirming"
+                     @click="handleReturnConfirm">纭鎻愪氦</el-button>
+          <el-button @click="returnSummaryDialogVisible = false">鍙栨秷</el-button>
+        </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+  import { computed, ref, watch } from "vue";
+  import { ElMessage } from "element-plus";
+  import {
+    listMaterialPickingDetail,
+    listMaterialSupplementRecord,
+    updateMaterialPickingLedger,
+  } from "@/api/productionManagement/productionOrder.js";
+
+  const props = defineProps({
+    modelValue: { type: Boolean, default: false },
+    orderRow: { type: Object, default: null },
+  });
+  const emit = defineEmits(["update:modelValue", "confirmed"]);
+
+  const dialogVisible = computed({
+    get: () => props.modelValue,
+    set: val => emit("update:modelValue", val),
+  });
+
+  const materialDetailLoading = ref(false);
+  const materialDetailTableData = ref([]);
+  const materialReturnConfirming = ref(false);
+  const supplementRecordDialogVisible = ref(false);
+  const supplementRecordLoading = ref(false);
+  const supplementRecordTableData = ref([]);
+  const returnSummaryDialogVisible = ref(false);
+  const returnSummaryList = ref([]);
+  const calcReturnQty = item =>
+    Number(item.pickQuantity || 0) +
+    Number(item.feedingQty || 0) -
+    Number(item.actualQty || 0);
+  const canOpenReturnSummary = computed(() =>
+    materialDetailTableData.value.some(
+      item => item.returned !== true && calcReturnQty(item) > 0
+    )
+  );
+
+  const loadDetailList = async () => {
+    if (!props.orderRow?.id) return;
+    materialDetailLoading.value = true;
+    materialDetailTableData.value = [];
+    try {
+      const res = await listMaterialPickingDetail(props.orderRow.id);
+      materialDetailTableData.value = (res.data || []).map(item => ({
+        ...item,
+        actualQty:
+          item.actualQty ??
+          Number(item.pickQuantity || 0) + Number(item.feedingQty || 0),
+        returnQty: item.returnQty ?? 0,
+      }));
+    } finally {
+      materialDetailLoading.value = false;
+    }
+  };
+
+  watch(
+    () => dialogVisible.value,
+    visible => {
+      if (visible) {
+        loadDetailList();
+      }
+    }
+  );
+
+  const handleClose = () => {
+    materialDetailTableData.value = [];
+  };
+
+  const handleActualQtyChange = (row, val) => {
+    row.returnQty = calcReturnQty(row);
+  };
+
+  const handleViewSupplementRecord = async row => {
+    if (!row?.id) return;
+    supplementRecordDialogVisible.value = true;
+    supplementRecordLoading.value = true;
+    supplementRecordTableData.value = [];
+    try {
+      const res = await listMaterialSupplementRecord({
+        pickId: row.id,
+        productionOrderId: props.orderRow.id,
+      });
+      supplementRecordTableData.value = res.data || [];
+    } finally {
+      supplementRecordLoading.value = false;
+    }
+  };
+
+  const buildReturnSummary = () => {
+    const map = new Map();
+    materialDetailTableData.value.forEach(item => {
+      const returnQty = calcReturnQty(item);
+      if (returnQty <= 0) return;
+      const key = `${item.productModelId || ""}_${item.productName || ""}_${
+        item.model || ""
+      }_${item.unit || ""}`;
+      const old = map.get(key) || {
+        summaryKey: key,
+        materialName: item.productName || "",
+        materialModel: item.model || "",
+        unit: item.unit || "",
+        returnQtyTotal: 0,
+      };
+      old.returnQtyTotal += returnQty;
+      map.set(key, old);
+    });
+    return Array.from(map.values());
+  };
+
+  const openReturnSummaryDialog = async () => {
+    if (!canOpenReturnSummary.value) {
+      ElMessage.warning("閫�鏂欐暟閲�=棰嗙敤鏁伴噺+琛ユ枡鏁伴噺-瀹為檯鏁伴噺锛屼笖闇�澶т簬0");
+      return;
+    }
+    returnSummaryList.value = buildReturnSummary();
+    returnSummaryDialogVisible.value = true;
+  };
+
+  const handleReturnConfirm = async () => {
+    if (!props.orderRow?.id) return;
+    materialReturnConfirming.value = true;
+    try {
+      await updateMaterialPickingLedger({
+        productionOrderId: props.orderRow.id,
+        productionOrderPickDto: materialDetailTableData.value.map(item => ({
+          id: item.id,
+          technologyOperationId: item.technologyOperationId,
+          operationName: item.operationName,
+          bom: item.bom === true,
+          productModelId: item.productModelId,
+          demandedQuantity: item.demandedQuantity,
+          unit: item.unit,
+          pickQuantity: item.pickQuantity,
+          batchNo: item.batchNo,
+          feedingQty: item.feedingQty,
+          returnQty: item.returnQty,
+          actualQty: item.actualQty,
+          feedingReason: item.feedingReason,
+          returned: true,
+        })),
+      });
+      returnSummaryDialogVisible.value = false;
+      dialogVisible.value = false;
+      emit("confirmed");
+    } finally {
+      materialReturnConfirming.value = false;
+    }
+  };
+</script>
+
+<style scoped lang="scss"></style>

--
Gitblit v1.9.3