From 6361501810a76b6809162cac99b0d9c1faba3715 Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期四, 16 四月 2026 15:10:02 +0800
Subject: [PATCH] fix: 对退料请求做限制
---
src/views/productionManagement/productionOrder/components/MaterialDetailDialog.vue | 264 ++++++++++
src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue | 241 +++++++++
src/views/productionManagement/workOrderManagement/components/MaterialDialog.vue | 296 +++++++++++
src/views/productionManagement/productionOrder/index.vue | 385 ---------------
src/views/productionManagement/workOrderManagement/index.vue | 297 -----------
5 files changed, 818 insertions(+), 665 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..f93199a
--- /dev/null
+++ b/src/views/productionManagement/productionOrder/components/MaterialDetailDialog.vue
@@ -0,0 +1,264 @@
+<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="processName" min-width="180" />
+ <el-table-column label="鍘熸枡鍚嶇О" prop="materialName" min-width="160" />
+ <el-table-column label="鍘熸枡鍨嬪彿" prop="materialModel" min-width="180" />
+ <el-table-column label="闇�姹傛暟閲�" prop="requiredQty" min-width="110" />
+ <el-table-column label="璁¢噺鍗曚綅" prop="unit" width="100" />
+ <el-table-column label="棰嗙敤鏁伴噺" prop="pickQty" min-width="110" />
+ <el-table-column label="琛ユ枡鏁伴噺" min-width="120">
+ <template #default="{ row }">
+ <el-button type="primary" link @click="handleViewSupplementRecord(row)">
+ {{ row.supplementQty ?? 0 }}
+ </el-button>
+ </template>
+ </el-table-column>
+ <el-table-column label="閫�鏂欐暟閲�" prop="returnQty" min-width="110" />
+ <el-table-column label="瀹為檯鏁伴噺" prop="actualQty" min-width="110" />
+ </el-table>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button
+ 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="supplementQty" min-width="120" />
+ <el-table-column label="琛ユ枡鏃堕棿" prop="supplementTime" min-width="180" />
+ <el-table-column label="澶囨敞" prop="remark" 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>
+
+ <el-card class="approver-card" shadow="never">
+ <template #header>
+ <div class="card-header-wrapper">
+ <span class="card-title">瀹℃壒浜洪�夋嫨</span>
+ <el-button type="primary" size="small" @click="addApproverNode">鏂板鑺傜偣</el-button>
+ </div>
+ </template>
+ <div class="approver-nodes-container">
+ <div v-for="(node, index) in approverNodes" :key="node.id" class="approver-node-item">
+ <div class="approver-node-label">
+ <span class="node-step">{{ index + 1 }}</span>
+ <span class="node-text">瀹℃壒浜�</span>
+ </div>
+ <el-select v-model="node.userId" placeholder="閫夋嫨浜哄憳" class="approver-select" clearable>
+ <el-option v-for="user in userList" :key="user.userId" :label="user.nickName" :value="user.userId" />
+ </el-select>
+ <el-button v-if="approverNodes.length > 1" type="danger" size="small" @click="removeApproverNode(index)">
+ 鍒犻櫎
+ </el-button>
+ </div>
+ </div>
+ </el-card>
+
+ <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, confirmMaterialReturn } from "@/api/productionManagement/productionOrder.js";
+import { userListNoPageByTenantId } from "@/api/system/user.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 userList = ref([]);
+const approverNodes = ref([{ id: Date.now(), userId: undefined }]);
+const canOpenReturnSummary = computed(() =>
+ materialDetailTableData.value.some(item => Number(item.returnQty || 0) > 0)
+);
+
+const loadDetailList = async () => {
+ if (!props.orderRow?.id) return;
+ materialDetailLoading.value = true;
+ materialDetailTableData.value = [];
+ try {
+ const res = await listMaterialPickingDetail({ orderId: props.orderRow.id });
+ materialDetailTableData.value = res.data || [];
+ } finally {
+ materialDetailLoading.value = false;
+ }
+};
+
+watch(
+ () => dialogVisible.value,
+ visible => {
+ if (visible) {
+ loadDetailList();
+ }
+ }
+);
+
+const handleClose = () => {
+ materialDetailTableData.value = [];
+};
+
+const handleViewSupplementRecord = async row => {
+ if (!row?.id) return;
+ supplementRecordDialogVisible.value = true;
+ supplementRecordLoading.value = true;
+ supplementRecordTableData.value = [];
+ try {
+ const res = await listMaterialSupplementRecord({ materialDetailId: row.id });
+ supplementRecordTableData.value = res.data || [];
+ } finally {
+ supplementRecordLoading.value = false;
+ }
+};
+
+const buildReturnSummary = () => {
+ const map = new Map();
+ materialDetailTableData.value.forEach(item => {
+ const key = `${item.materialModelId || ""}_${item.materialName || ""}_${item.materialModel || ""}_${item.unit || ""}`;
+ const old = map.get(key) || {
+ summaryKey: key,
+ materialName: item.materialName || "",
+ materialModel: item.materialModel || "",
+ unit: item.unit || "",
+ returnQtyTotal: 0,
+ };
+ old.returnQtyTotal += Number(item.returnQty || 0);
+ map.set(key, old);
+ });
+ return Array.from(map.values());
+};
+
+const loadUserList = async () => {
+ if (userList.value.length > 0) return;
+ const res = await userListNoPageByTenantId();
+ userList.value = res.data || [];
+};
+
+const openReturnSummaryDialog = async () => {
+ if (!canOpenReturnSummary.value) {
+ ElMessage.warning("閫�鏂欐暟閲忓ぇ浜�0鏃舵墠鑳介��鏂欑‘璁�");
+ return;
+ }
+ returnSummaryList.value = buildReturnSummary();
+ approverNodes.value = [{ id: Date.now(), userId: undefined }];
+ await loadUserList();
+ returnSummaryDialogVisible.value = true;
+};
+
+const addApproverNode = () => {
+ approverNodes.value.push({ id: Date.now() + Math.random(), userId: undefined });
+};
+
+const removeApproverNode = index => {
+ approverNodes.value.splice(index, 1);
+};
+
+const handleReturnConfirm = async () => {
+ if (!props.orderRow?.id) return;
+ const approverList = approverNodes.value
+ .filter(item => item.userId)
+ .map((item, index) => ({ userId: item.userId, sort: index + 1 }));
+ if (approverList.length === 0) {
+ ElMessage.warning("璇疯嚦灏戦�夋嫨涓�浣嶅鎵逛汉");
+ return;
+ }
+ materialReturnConfirming.value = true;
+ try {
+ await confirmMaterialReturn({
+ orderId: props.orderRow.id,
+ returnSummaryList: returnSummaryList.value,
+ approverList,
+ });
+ returnSummaryDialogVisible.value = false;
+ dialogVisible.value = false;
+ emit("confirmed");
+ } finally {
+ materialReturnConfirming.value = false;
+ }
+};
+</script>
+
+<style scoped lang="scss">
+.approver-card {
+ margin-top: 12px;
+}
+.card-header-wrapper {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+.approver-nodes-container {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+}
+.approver-node-item {
+ display: flex;
+ gap: 8px;
+ align-items: center;
+}
+.approver-node-label {
+ display: flex;
+ gap: 4px;
+ min-width: 88px;
+ align-items: center;
+}
+.node-step {
+ width: 20px;
+ height: 20px;
+ line-height: 20px;
+ text-align: center;
+ border-radius: 50%;
+ background: #409eff;
+ color: #fff;
+ font-size: 12px;
+}
+.approver-select {
+ flex: 1;
+}
+</style>
diff --git a/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue b/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue
new file mode 100644
index 0000000..f9db112
--- /dev/null
+++ b/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue
@@ -0,0 +1,241 @@
+<template>
+ <div>
+ <el-dialog v-model="dialogVisible" title="棰嗘枡鍙拌处" width="1200px" @close="handleClose">
+ <div class="material-toolbar">
+ <el-button type="primary" @click="handleAddMaterialRow">鏂板</el-button>
+ </div>
+ <el-table v-loading="materialTableLoading" :data="materialTableData" border row-key="tempId">
+ <el-table-column label="宸ュ簭鍚嶇О" min-width="180">
+ <template #default="{ row }">
+ <el-select
+ v-model="row.processId"
+ placeholder="璇烽�夋嫨宸ュ簭"
+ clearable
+ filterable
+ style="width: 100%;"
+ @change="val => handleProcessChange(row, val)"
+ >
+ <el-option v-for="item in processOptions" :key="item.id" :label="item.name" :value="item.id" />
+ </el-select>
+ </template>
+ </el-table-column>
+ <el-table-column label="鍘熸枡鍚嶇О" min-width="160">
+ <template #default="{ row }">
+ <el-button type="primary" link @click="openMaterialProductSelect(row)">
+ {{ row.materialName || "閫夋嫨鍘熸枡" }}
+ </el-button>
+ </template>
+ </el-table-column>
+ <el-table-column label="鍘熸枡鍨嬪彿" min-width="180">
+ <template #default="{ row }">
+ {{ row.materialModel || "-" }}
+ </template>
+ </el-table-column>
+ <el-table-column label="闇�姹傛暟閲�" min-width="120">
+ <template #default="{ row }">
+ <el-input-number
+ v-model="row.requiredQty"
+ :min="0"
+ :precision="3"
+ :step="1"
+ controls-position="right"
+ style="width: 100%;"
+ @change="val => handleRequiredQtyChange(row, val)"
+ />
+ </template>
+ </el-table-column>
+ <el-table-column label="璁¢噺鍗曚綅" width="120">
+ <template #default="{ row }">
+ {{ row.unit || "-" }}
+ </template>
+ </el-table-column>
+ <el-table-column label="棰嗙敤鏁伴噺" min-width="120">
+ <template #default="{ row }">
+ <el-input-number
+ v-model="row.pickQty"
+ :min="0"
+ :precision="3"
+ :step="1"
+ controls-position="right"
+ style="width: 100%;"
+ />
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" width="90" fixed="right">
+ <template #default="{ $index }">
+ <el-button type="danger" link @click="handleDeleteMaterialRow($index)">鍒犻櫎</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button type="primary" :loading="materialSaving" @click="handleMaterialSave">淇濆瓨</el-button>
+ <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+ </span>
+ </template>
+ </el-dialog>
+
+ <ProductSelectDialog
+ v-model="materialProductDialogVisible"
+ @confirm="handleMaterialProductConfirm"
+ single
+ />
+ </div>
+</template>
+
+<script setup>
+import { computed, ref, watch } from "vue";
+import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
+import { processList } from "@/api/productionManagement/productionProcess.js";
+import { listMaterialPickingLedger, saveMaterialPickingLedger } from "@/api/productionManagement/productionOrder.js";
+
+const props = defineProps({
+ modelValue: { type: Boolean, default: false },
+ orderRow: { type: Object, default: null },
+});
+const emit = defineEmits(["update:modelValue", "saved"]);
+
+const dialogVisible = computed({
+ get: () => props.modelValue,
+ set: val => emit("update:modelValue", val),
+});
+
+const materialProductDialogVisible = ref(false);
+const materialTableLoading = ref(false);
+const materialSaving = ref(false);
+const materialTableData = ref([]);
+const processOptions = ref([]);
+const currentMaterialSelectRowIndex = ref(-1);
+let materialTempId = 0;
+
+const createMaterialRow = (row = {}) => ({
+ tempId: row.id || `temp_${++materialTempId}`,
+ id: row.id,
+ processId: row.processId,
+ processName: row.processName || "",
+ materialModelId: row.materialModelId,
+ materialName: row.materialName || "",
+ materialModel: row.materialModel || "",
+ requiredQty: Number(row.requiredQty ?? 0),
+ unit: row.unit || "",
+ pickQty: Number(row.pickQty ?? row.requiredQty ?? 0),
+});
+
+const getProcessOptions = async () => {
+ if (processOptions.value.length > 0) return;
+ const res = await processList({});
+ processOptions.value = res.data || [];
+};
+
+const loadMaterialData = async () => {
+ if (!props.orderRow?.id) return;
+ materialTableLoading.value = true;
+ materialTableData.value = [];
+ await getProcessOptions();
+ try {
+ const res = await listMaterialPickingLedger({ orderId: props.orderRow.id });
+ materialTableData.value = (res.data || []).map(item => createMaterialRow(item));
+ } finally {
+ materialTableLoading.value = false;
+ }
+};
+
+watch(
+ () => dialogVisible.value,
+ visible => {
+ if (visible) {
+ loadMaterialData();
+ }
+ }
+);
+
+const handleClose = () => {
+ materialTableData.value = [];
+ currentMaterialSelectRowIndex.value = -1;
+};
+
+const handleAddMaterialRow = () => {
+ materialTableData.value.push(createMaterialRow());
+};
+
+const handleDeleteMaterialRow = index => {
+ materialTableData.value.splice(index, 1);
+};
+
+const handleProcessChange = (row, processId) => {
+ const process = processOptions.value.find(item => item.id === processId);
+ row.processName = process?.name || "";
+};
+
+const handleRequiredQtyChange = (row, val) => {
+ const required = Number(val ?? 0);
+ row.requiredQty = required;
+ if (!row.pickQty || Number(row.pickQty) === 0) {
+ row.pickQty = required;
+ }
+};
+
+const openMaterialProductSelect = row => {
+ currentMaterialSelectRowIndex.value = materialTableData.value.findIndex(item => item.tempId === row.tempId);
+ materialProductDialogVisible.value = true;
+};
+
+const handleMaterialProductConfirm = products => {
+ if (!products || products.length === 0) return;
+ const index = currentMaterialSelectRowIndex.value;
+ if (index < 0 || !materialTableData.value[index]) return;
+ const product = products[0];
+ const row = materialTableData.value[index];
+ row.materialModelId = product.id;
+ row.materialName = product.productName || "";
+ row.materialModel = product.model || "";
+ row.unit = product.unit || "";
+ currentMaterialSelectRowIndex.value = -1;
+ materialProductDialogVisible.value = false;
+};
+
+const validateMaterialRows = () => {
+ if (materialTableData.value.length === 0) return false;
+ return !materialTableData.value.find(
+ item =>
+ !item.processId ||
+ !item.materialModelId ||
+ item.requiredQty === null ||
+ item.requiredQty === undefined ||
+ item.pickQty === null ||
+ item.pickQty === undefined
+ );
+};
+
+const handleMaterialSave = async () => {
+ if (!props.orderRow?.id || !validateMaterialRows()) return;
+ materialSaving.value = true;
+ try {
+ await saveMaterialPickingLedger({
+ orderId: props.orderRow.id,
+ items: materialTableData.value.map(item => ({
+ id: item.id,
+ processId: item.processId,
+ processName: item.processName,
+ materialModelId: item.materialModelId,
+ materialName: item.materialName,
+ materialModel: item.materialModel,
+ requiredQty: item.requiredQty,
+ unit: item.unit,
+ pickQty: item.pickQty,
+ })),
+ });
+ emit("saved");
+ dialogVisible.value = false;
+ } finally {
+ materialSaving.value = false;
+ }
+};
+</script>
+
+<style scoped lang="scss">
+.material-toolbar {
+ margin-bottom: 12px;
+ text-align: right;
+}
+</style>
diff --git a/src/views/productionManagement/productionOrder/index.vue b/src/views/productionManagement/productionOrder/index.vue
index c66a0ec..cc0de4e 100644
--- a/src/views/productionManagement/productionOrder/index.vue
+++ b/src/views/productionManagement/productionOrder/index.vue
@@ -91,161 +91,16 @@
</template>
</el-dialog>
- <el-dialog
+ <MaterialLedgerDialog
v-model="materialDialogVisible"
- title="棰嗘枡鍙拌处"
- width="1200px"
- @close="handleMaterialDialogClose"
- >
- <div class="material-toolbar">
- <el-button type="primary" @click="handleAddMaterialRow">鏂板</el-button>
- </div>
- <el-table
- v-loading="materialTableLoading"
- :data="materialTableData"
- border
- row-key="tempId"
- >
- <el-table-column label="宸ュ簭鍚嶇О" min-width="180">
- <template #default="{ row }">
- <el-select
- v-model="row.processId"
- placeholder="璇烽�夋嫨宸ュ簭"
- clearable
- filterable
- style="width: 100%;"
- @change="val => handleProcessChange(row, val)"
- >
- <el-option
- v-for="item in processOptions"
- :key="item.id"
- :label="item.name"
- :value="item.id"
- />
- </el-select>
- </template>
- </el-table-column>
- <el-table-column label="鍘熸枡鍚嶇О" min-width="160">
- <template #default="{ row }">
- <el-button type="primary" link @click="openMaterialProductSelect(row)">
- {{ row.materialName || "閫夋嫨鍘熸枡" }}
- </el-button>
- </template>
- </el-table-column>
- <el-table-column label="鍘熸枡鍨嬪彿" min-width="180">
- <template #default="{ row }">
- {{ row.materialModel || "-" }}
- </template>
- </el-table-column>
- <el-table-column label="闇�姹傛暟閲�" min-width="120">
- <template #default="{ row }">
- <el-input-number
- v-model="row.requiredQty"
- :min="0"
- :precision="3"
- :step="1"
- controls-position="right"
- style="width: 100%;"
- @change="val => handleRequiredQtyChange(row, val)"
- />
- </template>
- </el-table-column>
- <el-table-column label="璁¢噺鍗曚綅" width="120">
- <template #default="{ row }">
- {{ row.unit || "-" }}
- </template>
- </el-table-column>
- <el-table-column label="棰嗙敤鏁伴噺" min-width="120">
- <template #default="{ row }">
- <el-input-number
- v-model="row.pickQty"
- :min="0"
- :precision="3"
- :step="1"
- controls-position="right"
- style="width: 100%;"
- />
- </template>
- </el-table-column>
- <el-table-column label="鎿嶄綔" width="90" fixed="right">
- <template #default="{ $index }">
- <el-button type="danger" link @click="handleDeleteMaterialRow($index)">鍒犻櫎</el-button>
- </template>
- </el-table-column>
- </el-table>
- <template #footer>
- <span class="dialog-footer">
- <el-button type="primary" :loading="materialSaving" @click="handleMaterialSave">淇濆瓨</el-button>
- <el-button @click="materialDialogVisible = false">鍙栨秷</el-button>
- </span>
- </template>
- </el-dialog>
-
- <ProductSelectDialog
- v-model="materialProductDialogVisible"
- @confirm="handleMaterialProductConfirm"
- single
+ :order-row="currentMaterialOrder"
+ @saved="getList"
/>
-
- <el-dialog
+ <MaterialDetailDialog
v-model="materialDetailDialogVisible"
- title="棰嗘枡璇︽儏"
- width="1400px"
- @close="handleMaterialDetailDialogClose"
- >
- <el-table
- v-loading="materialDetailLoading"
- :data="materialDetailTableData"
- border
- row-key="id"
- >
- <el-table-column label="宸ュ簭鍚嶇О" prop="processName" min-width="180" />
- <el-table-column label="鍘熸枡鍚嶇О" prop="materialName" min-width="160" />
- <el-table-column label="鍘熸枡鍨嬪彿" prop="materialModel" min-width="180" />
- <el-table-column label="闇�姹傛暟閲�" prop="requiredQty" min-width="110" />
- <el-table-column label="璁¢噺鍗曚綅" prop="unit" width="100" />
- <el-table-column label="棰嗙敤鏁伴噺" prop="pickQty" min-width="110" />
- <el-table-column label="琛ユ枡鏁伴噺" min-width="120">
- <template #default="{ row }">
- <el-button type="primary" link @click="handleViewSupplementRecord(row)">
- {{ row.supplementQty ?? 0 }}
- </el-button>
- </template>
- </el-table-column>
- <el-table-column label="閫�鏂欐暟閲�" prop="returnQty" min-width="110" />
- <el-table-column label="瀹為檯鏁伴噺" prop="actualQty" min-width="110" />
- </el-table>
- <template #footer>
- <span class="dialog-footer">
- <el-button type="warning" :loading="materialReturnConfirming" @click="handleReturnConfirm">
- 閫�鏂欑‘璁�
- </el-button>
- <el-button @click="materialDetailDialogVisible = 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="supplementQty" min-width="120" />
- <el-table-column label="琛ユ枡鏃堕棿" prop="supplementTime" min-width="180" />
- <el-table-column label="澶囨敞" prop="remark" min-width="200" />
- </el-table>
- <template #footer>
- <span class="dialog-footer">
- <el-button @click="supplementRecordDialogVisible = false">鍏抽棴</el-button>
- </span>
- </template>
- </el-dialog>
+ :order-row="currentMaterialDetailOrder"
+ @confirmed="getList"
+ />
<new-product-order v-if="isShowNewModal"
v-model:visible="isShowNewModal"
@@ -258,20 +113,15 @@
import { ElMessageBox } from "element-plus";
import dayjs from "dayjs";
import { useRouter } from "vue-router";
- import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
import {
productOrderListPage,
listProcessRoute,
bindingRoute,
listProcessBom, delProductOrder,
- listMaterialPickingLedger,
- saveMaterialPickingLedger,
- listMaterialPickingDetail,
- listMaterialSupplementRecord,
- confirmMaterialReturn,
} from "@/api/productionManagement/productionOrder.js";
import { listMain as getOrderProcessRouteMain } from "@/api/productionManagement/productProcessRoute.js";
- import { processList } from "@/api/productionManagement/productionProcess.js";
+ import MaterialLedgerDialog from "@/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue";
+ import MaterialDetailDialog from "@/views/productionManagement/productionOrder/components/MaterialDetailDialog.vue";
import PIMTable from "@/components/PIMTable/PIMTable.vue";
const NewProductOrder = defineAsyncComponent(() => import("@/views/productionManagement/productionOrder/New.vue"));
@@ -454,35 +304,9 @@
routeId: null,
});
const materialDialogVisible = ref(false);
- const materialProductDialogVisible = ref(false);
- const materialTableLoading = ref(false);
- const materialSaving = ref(false);
- const materialTableData = ref([]);
- const processOptions = ref([]);
const currentMaterialOrder = ref(null);
- const currentMaterialSelectRowIndex = ref(-1);
const materialDetailDialogVisible = ref(false);
- const materialDetailLoading = ref(false);
- const materialDetailTableData = ref([]);
- const materialReturnConfirming = ref(false);
const currentMaterialDetailOrder = ref(null);
- const supplementRecordDialogVisible = ref(false);
- const supplementRecordLoading = ref(false);
- const supplementRecordTableData = ref([]);
- let materialTempId = 0;
-
- const createMaterialRow = (row = {}) => ({
- tempId: row.id || `temp_${++materialTempId}`,
- id: row.id,
- processId: row.processId,
- processName: row.processName || "",
- materialModelId: row.materialModelId,
- materialName: row.materialName || "",
- materialModel: row.materialModel || "",
- requiredQty: Number(row.requiredQty ?? 0),
- unit: row.unit || "",
- pickQty: Number(row.pickQty ?? row.requiredQty ?? 0),
- });
const openBindRouteDialog = async row => {
bindForm.orderId = row.id;
@@ -528,199 +352,14 @@
}
};
- const getProcessOptions = async () => {
- if (processOptions.value.length > 0) return;
- try {
- const res = await processList({});
- processOptions.value = res.data || [];
- } catch (e) {
- console.error("鑾峰彇宸ュ簭鍒楄〃澶辫触锛�", e);
- proxy.$modal.msgError("鑾峰彇宸ュ簭鍒楄〃澶辫触");
- }
- };
-
- const openMaterialDialog = async row => {
+ const openMaterialDialog = row => {
currentMaterialOrder.value = row;
materialDialogVisible.value = true;
- materialTableLoading.value = true;
- materialTableData.value = [];
- await getProcessOptions();
- try {
- const res = await listMaterialPickingLedger({ orderId: row.id });
- const list = res.data || [];
- materialTableData.value = list.map(item => createMaterialRow(item));
- } catch (e) {
- console.error("鑾峰彇棰嗘枡鍙拌处澶辫触锛�", e);
- proxy.$modal.msgError("鑾峰彇棰嗘枡鍙拌处澶辫触");
- } finally {
- materialTableLoading.value = false;
- }
- };
-
- const handleMaterialDialogClose = () => {
- materialTableData.value = [];
- currentMaterialOrder.value = null;
- currentMaterialSelectRowIndex.value = -1;
- };
-
- const handleAddMaterialRow = () => {
- materialTableData.value.push(createMaterialRow());
- };
-
- const handleDeleteMaterialRow = index => {
- materialTableData.value.splice(index, 1);
- };
-
- const handleProcessChange = (row, processId) => {
- const process = processOptions.value.find(item => item.id === processId);
- row.processName = process?.name || "";
- };
-
- const handleRequiredQtyChange = (row, val) => {
- const required = Number(val ?? 0);
- row.requiredQty = required;
- if (!row.pickQty || Number(row.pickQty) === 0) {
- row.pickQty = required;
- }
- };
-
- const openMaterialProductSelect = row => {
- currentMaterialSelectRowIndex.value = materialTableData.value.findIndex(item => item.tempId === row.tempId);
- materialProductDialogVisible.value = true;
- };
-
- const handleMaterialProductConfirm = products => {
- if (!products || products.length === 0) return;
- const index = currentMaterialSelectRowIndex.value;
- if (index < 0 || !materialTableData.value[index]) return;
- const product = products[0];
- const row = materialTableData.value[index];
- row.materialModelId = product.id;
- row.materialName = product.productName || "";
- row.materialModel = product.model || "";
- row.unit = product.unit || "";
- currentMaterialSelectRowIndex.value = -1;
- materialProductDialogVisible.value = false;
- };
-
- const validateMaterialRows = () => {
- if (materialTableData.value.length === 0) {
- proxy.$modal.msgWarning("璇疯嚦灏戞柊澧炰竴鏉¢鏂欒褰�");
- return false;
- }
- const invalidRow = materialTableData.value.find(
- item =>
- !item.processId ||
- !item.materialModelId ||
- item.requiredQty === null ||
- item.requiredQty === undefined ||
- item.pickQty === null ||
- item.pickQty === undefined
- );
- if (invalidRow) {
- proxy.$modal.msgWarning("璇峰畬鍠勯鏂欏彴璐﹀繀濉瓧娈�");
- return false;
- }
- return true;
- };
-
- const handleMaterialSave = async () => {
- if (!currentMaterialOrder.value?.id) {
- proxy.$modal.msgWarning("鏈幏鍙栧埌褰撳墠鐢熶骇璁㈠崟");
- return;
- }
- if (!validateMaterialRows()) return;
- materialSaving.value = true;
- try {
- await saveMaterialPickingLedger({
- orderId: currentMaterialOrder.value.id,
- items: materialTableData.value.map(item => ({
- id: item.id,
- processId: item.processId,
- processName: item.processName,
- materialModelId: item.materialModelId,
- materialName: item.materialName,
- materialModel: item.materialModel,
- requiredQty: item.requiredQty,
- unit: item.unit,
- pickQty: item.pickQty,
- })),
- });
- proxy.$modal.msgSuccess("淇濆瓨鎴愬姛");
- materialDialogVisible.value = false;
- } catch (e) {
- console.error("淇濆瓨棰嗘枡鍙拌处澶辫触锛�", e);
- proxy.$modal.msgError("淇濆瓨棰嗘枡鍙拌处澶辫触");
- } finally {
- materialSaving.value = false;
- }
};
const openMaterialDetailDialog = async row => {
currentMaterialDetailOrder.value = row;
materialDetailDialogVisible.value = true;
- materialDetailLoading.value = true;
- materialDetailTableData.value = [];
- try {
- const res = await listMaterialPickingDetail({ orderId: row.id });
- materialDetailTableData.value = res.data || [];
- } catch (e) {
- console.error("鑾峰彇棰嗘枡璇︽儏澶辫触锛�", e);
- proxy.$modal.msgError("鑾峰彇棰嗘枡璇︽儏澶辫触");
- } finally {
- materialDetailLoading.value = false;
- }
- };
-
- const handleMaterialDetailDialogClose = () => {
- materialDetailTableData.value = [];
- currentMaterialDetailOrder.value = null;
- };
-
- const handleViewSupplementRecord = async row => {
- if (!row?.id) {
- proxy.$modal.msgWarning("缂哄皯棰嗘枡鏄庣粏ID锛屾棤娉曟煡鐪嬭ˉ鏂欒褰�");
- return;
- }
- supplementRecordDialogVisible.value = true;
- supplementRecordLoading.value = true;
- supplementRecordTableData.value = [];
- try {
- const res = await listMaterialSupplementRecord({ materialDetailId: row.id });
- supplementRecordTableData.value = res.data || [];
- } catch (e) {
- console.error("鑾峰彇琛ユ枡璁板綍澶辫触锛�", e);
- proxy.$modal.msgError("鑾峰彇琛ユ枡璁板綍澶辫触");
- } finally {
- supplementRecordLoading.value = false;
- }
- };
-
- const handleReturnConfirm = async () => {
- if (!currentMaterialDetailOrder.value?.id) {
- proxy.$modal.msgWarning("鏈幏鍙栧埌褰撳墠鐢熶骇璁㈠崟");
- return;
- }
- try {
- await ElMessageBox.confirm("纭鎵ц閫�鏂欑‘璁わ紵", "鎻愮ず", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- });
- } catch (e) {
- return;
- }
- materialReturnConfirming.value = true;
- try {
- await confirmMaterialReturn({ orderId: currentMaterialDetailOrder.value.id });
- proxy.$modal.msgSuccess("閫�鏂欑‘璁ゆ垚鍔�");
- openMaterialDetailDialog(currentMaterialDetailOrder.value);
- } catch (e) {
- console.error("閫�鏂欑‘璁ゅけ璐ワ細", e);
- proxy.$modal.msgError("閫�鏂欑‘璁ゅけ璐�");
- } finally {
- materialReturnConfirming.value = false;
- }
};
// 鏌ヨ鍒楄〃
@@ -875,8 +514,4 @@
margin-top: unset;
}
-.material-toolbar {
- margin-bottom: 12px;
- text-align: right;
-}
</style>
diff --git a/src/views/productionManagement/workOrderManagement/components/MaterialDialog.vue b/src/views/productionManagement/workOrderManagement/components/MaterialDialog.vue
new file mode 100644
index 0000000..e5eee56
--- /dev/null
+++ b/src/views/productionManagement/workOrderManagement/components/MaterialDialog.vue
@@ -0,0 +1,296 @@
+<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="閫�鏂欐暟閲�" 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>
+ </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,
+ addWorkOrderMaterialReturn,
+ listWorkOrderMaterialSupplementRecord,
+} 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 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 supplementRules = {
+ supplementQty: [{ required: true, message: "璇疯緭鍏ヨˉ鏂欐暟閲�", trigger: "blur" }],
+ supplementReason: [{ required: true, message: "璇疯緭鍏ヨˉ鏂欏師鍥�", trigger: "blur" }],
+};
+const returnRules = {
+ returnQty: [{ 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 openReturnDialog = row => {
+ currentMaterialRow.value = row;
+ returnForm.returnQty = null;
+ returnDialogVisible.value = true;
+ nextTick(() => {
+ returnFormRef.value?.clearValidate();
+ });
+};
+
+const handleSubmitReturn = () => {
+ returnFormRef.value?.validate(async valid => {
+ if (!valid || !currentMaterialRow.value?.id) {
+ ElMessage.warning("缂哄皯鐗╂枡鏄庣粏ID");
+ return;
+ }
+ const returnQty = Number(returnForm.returnQty);
+ const minQty =
+ Number(currentMaterialRow.value.pickQty || 0) +
+ Number(currentMaterialRow.value.supplementQty || 0);
+ if (returnQty < minQty) {
+ ElMessage.warning(`閫�鏂欐暟閲忎笉鑳戒綆浜庨鐢ㄦ暟閲�+琛ユ枡鏁伴噺锛�${minQty}锛塦);
+ return;
+ }
+ returnSubmitting.value = true;
+ try {
+ await addWorkOrderMaterialReturn({
+ materialLedgerId: currentMaterialRow.value.id,
+ returnQty,
+ workOrderId: currentMaterialOrderRow.value?.id,
+ });
+ returnDialogVisible.value = false;
+ await loadMaterialTable(currentMaterialOrderRow.value);
+ ElMessage.success("閫�鏂欐垚鍔�");
+ emit("refresh");
+ } catch (e) {
+ console.error("閫�鏂欏け璐�", e);
+ ElMessage.error("閫�鏂欏け璐�");
+ } 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);
+ ElMessage.error("鑾峰彇琛ユ枡璁板綍澶辫触");
+ } finally {
+ supplementRecordLoading.value = false;
+ }
+};
+</script>
diff --git a/src/views/productionManagement/workOrderManagement/index.vue b/src/views/productionManagement/workOrderManagement/index.vue
index 9ffbd3f..d0f9389 100644
--- a/src/views/productionManagement/workOrderManagement/index.vue
+++ b/src/views/productionManagement/workOrderManagement/index.vue
@@ -164,146 +164,11 @@
</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>
+ <MaterialDialog
+ v-model="materialDialogVisible"
+ :row-data="currentMaterialOrderRow"
+ @refresh="getList"
+ />
<FilesDia ref="workOrderFilesRef" />
</div>
@@ -317,16 +182,12 @@
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";
+ import MaterialDialog from "./components/MaterialDialog.vue";
const { proxy } = getCurrentInstance();
const tableColumn = ref([
@@ -492,13 +353,6 @@
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 => {
@@ -556,26 +410,7 @@
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,
@@ -727,127 +562,9 @@
reportDialogVisible.value = true;
};
- const openMaterialDialog = async row => {
+ const openMaterialDialog = 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 = () => {
--
Gitblit v1.9.3