From 50552c590564e51349229d4f2e26a147109adc60 Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期五, 27 三月 2026 17:55:07 +0800
Subject: [PATCH] feat:1.生产订单增加领用弹窗(数据输入和输出)

---
 src/views/productionManagement/productionOrder/MaterialRequisitionDialog.vue |  226 +++++++++++++++++++++++++++++++++++++++++++++
 src/views/productionManagement/productionOrder/index.vue                     |   25 +++++
 src/api/productionManagement/productionOrder.js                              |   18 +++
 3 files changed, 269 insertions(+), 0 deletions(-)

diff --git a/src/api/productionManagement/productionOrder.js b/src/api/productionManagement/productionOrder.js
index 8adc47f..5d3db7b 100644
--- a/src/api/productionManagement/productionOrder.js
+++ b/src/api/productionManagement/productionOrder.js
@@ -147,6 +147,24 @@
   });
 }
 
+//鏍规嵁璁㈠崟鐨刡omId鏌ヨ搴撳瓨鍘熸潗鏂�
+export function getByBomId(query) {
+  return request({
+    url: "/productOrder/getByBomId",
+    method: "get",
+    params: query,
+  });
+}
+
+//淇濆瓨鐢熶骇璁㈠崟棰嗘枡
+export function drawMaterials(data) {
+  return request({
+    url: "/productOrder/drawMaterials",
+    method: "post",
+    data: data,
+  });
+}
+
 export function getProductOrderBatchNoOptions() {
   return request({
     url: "/productOrder/getProductOrderBatchNo",
diff --git a/src/views/productionManagement/productionOrder/MaterialRequisitionDialog.vue b/src/views/productionManagement/productionOrder/MaterialRequisitionDialog.vue
new file mode 100644
index 0000000..ab3bd63
--- /dev/null
+++ b/src/views/productionManagement/productionOrder/MaterialRequisitionDialog.vue
@@ -0,0 +1,226 @@
+<template>
+  <el-dialog
+    v-model="visible"
+    title="棰嗘枡"
+    width="1000px"
+    top="3vh"
+    :close-on-click-modal="false"
+    destroy-on-close
+    class="material-requisition-dialog"
+  >
+    <div class="material-requisition-form">
+      <!-- 鍘熸潗鏂欏垪琛� -->
+      <el-table :data="materialList" border style="width: 100%" height="65vh">
+        <el-table-column type="index" label="搴忓彿" width="60" align="center" />
+        <el-table-column prop="productName" label="浜у搧鍚嶇О" min-width="150" />
+        <el-table-column prop="model" label="鍨嬪彿" min-width="150" />
+        <!-- <el-table-column prop="batchNo" label="鎵瑰彿" min-width="150">
+          <template #default="{ row }">
+            <el-select
+              v-model="row.batchNo"
+              placeholder="璇烽�夋嫨鎵瑰彿"
+              clearable
+              style="width: 100%"
+            >
+              <el-option
+                v-for="item in row.batchOptions || []"
+                :key="item.batchNo"
+                :label="item.batchNo"
+                :value="item.batchNo"
+              />
+            </el-select>
+          </template>
+        </el-table-column> -->
+        <el-table-column prop="unit" label="鍗曚綅" width="80" align="center" />
+        <el-table-column prop="qualitity" label="鏁伴噺" width="100" align="center">
+          <template #default="{ row }">
+            {{ row.qualitity || 0 }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="requisitionQty" label="棰嗙敤鏁伴噺" width="120" align="center">
+          <template #default="{ row }">
+            <el-input-number
+              v-model="row.requisitionQty"
+              :min="0"
+              :precision="2"
+              :controls="false"
+              :disabled="!row.qualitity || hasDrawMaterials"
+              style="width: 100%"
+            />
+          </template>
+        </el-table-column>
+        <el-table-column prop="remark" label="澶囨敞" min-width="150">
+        </el-table-column>
+      </el-table>
+    </div>
+
+    <template #footer>
+      <span class="dialog-footer">
+        <el-button type="primary" :loading="saving" @click="handleConfirm">纭� 璁�</el-button>
+        <el-button @click="handleCancel">鍙� 娑�</el-button>
+      </span>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup>
+import { ref, reactive, computed, watch } from 'vue';
+import { ElMessage } from 'element-plus';
+import { getByBomId, drawMaterials } from '@/api/productionManagement/productionOrder.js';
+
+const props = defineProps({
+  modelValue: {
+    type: Boolean,
+    default: false
+  },
+  orderData: {
+    type: Object,
+    default: () => ({})
+  }
+});
+
+const emit = defineEmits(['update:modelValue', 'confirm']);
+
+const visible = computed({
+  get: () => props.modelValue,
+  set: (val) => emit('update:modelValue', val)
+});
+
+const loading = ref(false);
+const saving = ref(false);
+const materialList = ref([]);
+const hasDrawMaterials = ref(false);
+
+// 鐩戝惉寮规鎵撳紑锛屽姞杞芥暟鎹�
+watch(() => props.modelValue, (val) => {
+  if (val && props.orderData) {
+    loadMaterialList();
+  }
+});
+
+const loadMaterialList = async () => {
+  const order = props.orderData;
+  const drawMaterialsData = order.drawMaterials;
+
+  // 濡傛灉宸叉湁棰嗘枡鏁版嵁锛岀洿鎺ヤ娇鐢�
+  if (drawMaterialsData) {
+    hasDrawMaterials.value = true;
+    try {
+      const list = typeof drawMaterialsData === 'string'
+        ? JSON.parse(drawMaterialsData)
+        : drawMaterialsData;
+      materialList.value = list.map(item => ({
+        ...item,
+        requisitionQty: item.requisitionQty || 0
+      }));
+      return;
+    } catch (e) {
+      console.error('瑙f瀽棰嗘枡鏁版嵁澶辫触:', e);
+    }
+  }
+
+  // 娌℃湁棰嗘枡鏁版嵁锛岃皟鐢ㄦ帴鍙f煡璇�
+  hasDrawMaterials.value = false;
+  const bomId = order?.bomId;
+  if (!bomId) {
+    ElMessage.warning('褰撳墠璁㈠崟缂哄皯BOM淇℃伅');
+    return;
+  }
+
+  loading.value = true;
+  try {
+    const res = await getByBomId({ bomId });
+    const data = res.data || [];
+    // 澶勭悊鏁版嵁锛屾坊鍔犻鐢ㄦ暟閲忓瓧娈靛拰鎵瑰彿閫夐」
+    materialList.value = data.map(item => ({
+      ...item,
+      requisitionQty: item.qualitity ? 0 : 0,
+      batchNo: item.batchNo || '',
+      remark: item.remark || '',
+      // 鎵瑰彿閫夐」锛屼粠搴撳瓨鍘熸潗鏂欎俊鎭腑鑾峰彇
+      batchOptions: item.inventoryList || []
+    }));
+  } catch (error) {
+    console.error('鏌ヨ鍘熸潗鏂欏垪琛ㄥけ璐�:', error);
+    ElMessage.error('鏌ヨ鍘熸潗鏂欏垪琛ㄥけ璐�');
+    materialList.value = [];
+  } finally {
+    loading.value = false;
+  }
+};
+
+const handleCancel = () => {
+  visible.value = false;
+  materialList.value = [];
+  hasDrawMaterials.value = false;
+};
+
+const handleConfirm = async () => {
+  const orderId = props.orderData?.id;
+  if (!orderId) {
+    ElMessage.error('璁㈠崟ID涓嶅瓨鍦�');
+    return;
+  }
+
+  const drawMaterialsList = materialList.value.map(item => ({
+    ...item,
+    requisitionQty: item.requisitionQty || 0
+  }));
+
+  const postData = {
+    id: orderId,
+    drawMaterials: JSON.stringify(drawMaterialsList)
+  };
+
+  saving.value = true;
+  try {
+    await drawMaterials(postData);
+    ElMessage.success('棰嗘枡淇濆瓨鎴愬姛');
+    visible.value = false;
+    materialList.value = [];
+    hasDrawMaterials.value = false;
+  } catch (error) {
+    console.error('淇濆瓨棰嗘枡澶辫触:', error);
+    ElMessage.error('淇濆瓨棰嗘枡澶辫触');
+  } finally {
+    saving.value = false;
+  }
+};
+</script>
+
+<style scoped lang="scss">
+.material-requisition-form {
+  .el-table {
+    margin-top: 10px;
+  }
+}
+
+.dialog-footer {
+  display: flex;
+  justify-content: flex-end;
+  gap: 10px;
+}
+
+:deep(.el-dialog) {
+  height: 85vh;
+  margin-top: 3vh !important;
+  display: flex;
+  flex-direction: column;
+}
+
+:deep(.el-dialog__body) {
+  flex: 1;
+  overflow-y: auto;
+  padding: 15px 20px;
+}
+
+:deep(.el-dialog__header) {
+  padding: 15px 20px;
+  border-bottom: 1px solid #e4e7ed;
+}
+
+:deep(.el-dialog__footer) {
+  padding: 15px 20px;
+  border-top: 1px solid #e4e7ed;
+}
+</style>
diff --git a/src/views/productionManagement/productionOrder/index.vue b/src/views/productionManagement/productionOrder/index.vue
index 8c254da..49624b6 100644
--- a/src/views/productionManagement/productionOrder/index.vue
+++ b/src/views/productionManagement/productionOrder/index.vue
@@ -102,6 +102,12 @@
       :order-data="currentOrderData"
       @save="handleSaveClearanceRecord"
     />
+
+    <!-- 棰嗘枡寮规 -->
+    <material-requisition-dialog
+      v-model="materialRequisitionVisible"
+      :order-data="currentOrderData"
+    />
   </div>
 </template>
 
@@ -123,6 +129,7 @@
 
 const NewProductOrder = defineAsyncComponent(() => import("@/views/productionManagement/productionOrder/New.vue"));
 const ClearanceRecordDialog = defineAsyncComponent(() => import("@/views/productionManagement/productionOrder/ClearanceRecordDialog.vue"));
+const MaterialRequisitionDialog = defineAsyncComponent(() => import("@/views/productionManagement/productionOrder/MaterialRequisitionDialog.vue"));
 
 const {proxy} = getCurrentInstance();
 
@@ -244,6 +251,14 @@
           handleClearanceRecord(row);
         },
       },
+      {
+        name: "棰嗘枡",
+        type: "text",
+        showHide: row => !row.isEnd,
+        clickFun: row => {
+          handleMaterialRequisition(row);
+        },
+      },
     ],
   },
 ]);
@@ -310,6 +325,9 @@
 // 娓呭満璁板綍寮规
 const clearanceDialogVisible = ref(false);
 const currentOrderData = ref({});
+
+// 棰嗘枡寮规
+const materialRequisitionVisible = ref(false);
 const bindForm = reactive({
   orderId: null,
   routeId: null,
@@ -525,6 +543,13 @@
     proxy.$modal.msgError("娓呭満璁板綍淇濆瓨澶辫触");
   }
 };
+
+// 鎵撳紑棰嗘枡寮规
+const handleMaterialRequisition = (row) => {
+  currentOrderData.value = row;
+  materialRequisitionVisible.value = true;
+};
+
 onMounted(() => {
   getList();
 });

--
Gitblit v1.9.3