From bfa9cabc4fe74da05c3d1eb5148929551c4d87c2 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期四, 28 五月 2026 09:13:01 +0800
Subject: [PATCH] 中兴实强new 1.生产订单领料时如果库存不足可以提交采购申请单 2.采购申请单通知点击跳转是根据合同号直接进行查询
---
src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue | 123 ++++++++++++++++++++++++++++++++++------
1 files changed, 104 insertions(+), 19 deletions(-)
diff --git a/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue b/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue
index 210dbba..85fbe35 100644
--- a/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue
+++ b/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue
@@ -2,7 +2,7 @@
<div>
<el-dialog v-model="dialogVisible"
title="棰嗘枡鍙拌处"
- width="1200px"
+ width="1400px"
@close="handleClose">
<div class="material-toolbar">
<el-button type="primary"
@@ -65,10 +65,18 @@
</el-select>
</template>
</el-table-column>
+ <el-table-column label="搴撳瓨鏁伴噺"
+ min-width="120">
+ <template #default="{ row }">
+ <span :class="{ 'text-danger': isStockInsufficient(row) }">
+ {{ row.stockQuantity ?? '-' }}
+ </span>
+ </template>
+ </el-table-column>
<el-table-column label="闇�姹傛暟閲�"
min-width="120">
<template #default="{ row }">
- <span v-if="row.bom === true">{{ row.demandedQuantity ?? "-" }}</span>
+ <span v-if="row.bom === true" :class="{ 'text-danger': isStockInsufficient(row) }">{{ row.demandedQuantity ?? "-" }}</span>
<el-input-number v-else
v-model="row.demandedQuantity"
:min="0"
@@ -76,6 +84,7 @@
:step="1"
controls-position="right"
style="width: 100%;"
+ :class="{ 'is-stock-insufficient': isStockInsufficient(row) }"
@change="val => handleRequiredQtyChange(row, val)" />
</template>
</el-table-column>
@@ -109,8 +118,12 @@
</el-table>
<template #footer>
<span class="dialog-footer">
+ <el-button v-if="hasInsufficientStock"
+ type="warning"
+ @click="openPurchaseRequestDialog">閲囪喘鐢宠</el-button>
<el-button type="primary"
:loading="materialSaving"
+ :disabled="isSaveDisabled"
@click="handleMaterialSave">淇濆瓨</el-button>
<el-button @click="dialogVisible = false">鍙栨秷</el-button>
</span>
@@ -119,6 +132,10 @@
<ProductSelectDialog v-model="materialProductDialogVisible"
@confirm="handleMaterialProductConfirm"
single />
+ <PurchaseRequestDialog v-model="purchaseRequestDialogVisible"
+ :insufficient-items="insufficientStockItems"
+ :order-row="props.orderRow"
+ @saved="handlePurchaseRequestSaved" />
<!-- request-url="/stockInventory/rawMaterials" -->
</div>
</template>
@@ -127,18 +144,18 @@
import { computed, ref, watch } from "vue";
import { ElMessage } from "element-plus";
import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
+ import PurchaseRequestDialog from "./PurchaseRequestDialog.vue";
import {
findProductProcessRouteItemList,
listMain,
} from "@/api/productionManagement/productProcessRoute.js";
import {
- listMaterialPickingDetail,
listMaterialPickingBom,
- listMaterialPickingLedger,
saveMaterialPickingLedger,
updateMaterialPickingLedger,
} from "@/api/productionManagement/productionOrder.js";
import { queryList2 } from "@/api/productionManagement/productStructure.js";
+
const props = defineProps({
modelValue: { type: Boolean, default: false },
@@ -155,6 +172,51 @@
const materialTableLoading = ref(false);
const materialSaving = ref(false);
const materialTableData = ref([]);
+ const purchaseRequestDialogVisible = ref(false);
+
+ const isSaveDisabled = computed(() => {
+ if (materialTableData.value.length === 0) return true;
+ return !materialTableData.value.some(row => {
+ // 妫�鏌ユ槸鍚︽湁浠讳綍鐢ㄦ埛杈撳叆鍐呭
+ const hasBatch = Array.isArray(row.batchNo) && row.batchNo.length > 0;
+ const hasPickQty =
+ row.pickQty !== null && row.pickQty !== undefined && row.pickQty !== 0;
+
+ if (row.bom) {
+ // 瀵逛簬鏉ヨ嚜BOM鐨勮锛岃緭鍏ユ鍙湁鈥滄壒鍙封�濆拰鈥滈鐢ㄦ暟閲忊��
+ return hasBatch || hasPickQty;
+ } else {
+ // 瀵逛簬鏂板琛岋紝杈撳叆妗嗗寘鎷�滃伐搴忊�濄�佲�滃師鏂欌�濄�佲�滈渶姹傛暟閲忊�濄�佲�滄壒鍙封�濆拰鈥滈鐢ㄦ暟閲忊��
+ const hasOperation = !!row.operationName;
+ const hasMaterial = !!row.materialName;
+ const hasDemanded =
+ row.demandedQuantity !== null &&
+ row.demandedQuantity !== undefined &&
+ row.demandedQuantity !== 0;
+ return (
+ hasBatch || hasPickQty || hasOperation || hasMaterial || hasDemanded
+ );
+ }
+ });
+ });
+
+ // 鍒ゆ柇搴撳瓨鏄惁涓嶈冻
+ const isStockInsufficient = (row) => {
+ const stockQuantity = Number(row.stockQuantity ?? 0);
+ const demandedQty = Number(row.demandedQuantity ?? 0);
+ return demandedQty > 0 && stockQuantity > 0 && demandedQty > stockQuantity;
+ };
+
+ // 搴撳瓨涓嶈冻鐨勮
+ const insufficientStockItems = computed(() => {
+ return materialTableData.value.filter(row => isStockInsufficient(row));
+ });
+
+ // 鏄惁鏈夊簱瀛樹笉瓒�
+ const hasInsufficientStock = computed(() => {
+ return insufficientStockItems.value.length > 0;
+ });
+
const processOptions = ref([]);
const currentMaterialSelectRowIndex = ref(-1);
let materialTempId = 0;
@@ -178,6 +240,7 @@
: row.batchNo
: [],
batchNoList: row.batchNoList || [],
+ stockQuantity: row.stockQuantity ?? row.stockQty ?? null,
});
const getProcessOptions = async () => {
@@ -211,22 +274,14 @@
materialTableData.value = [];
await getProcessOptions();
try {
- const detailRes = await listMaterialPickingDetail(props.orderRow.id);
- const detailList = Array.isArray(detailRes?.data)
- ? detailRes.data
- : detailRes?.data?.records || [];
- if (detailList.length > 0) {
- isDetail.value = true;
- materialTableData.value = detailList.map(item => createMaterialRow(item));
- return;
- } else {
+ // 鐩存帴璋冪敤listMaterialPickingBom鎺ュ彛鑾峰彇搴撳瓨鏁伴噺
+ const bomRes = await listMaterialPickingBom(props.orderRow.id);
+ const bomList = Array.isArray(bomRes?.data)
+ ? bomRes.data
+ : bomRes?.data?.records || [];
+ if (bomList.length > 0) {
isDetail.value = false;
- const bomRes = await listMaterialPickingBom(props.orderRow.id);
- const bomList = Array.isArray(bomRes?.data)
- ? bomRes.data
- : bomRes?.data?.records || [];
materialTableData.value = bomList.map(item => createMaterialRow(item));
- return;
}
} finally {
materialTableLoading.value = false;
@@ -277,7 +332,7 @@
materialProductDialogVisible.value = true;
};
- const handleMaterialProductConfirm = products => {
+ const handleMaterialProductConfirm = async (products) => {
console.log(products, "products");
if (!products || products.length === 0) return;
@@ -312,12 +367,20 @@
!item.materialName ||
(Number(item.pickQty) > 0 &&
(!item.batchNo || item.batchNo.length === 0)) ||
+ (item.batchNo && item.batchNo.length > 0 && Number(item.pickQty) <= 0) ||
item.demandedQuantity === null ||
item.demandedQuantity === undefined ||
item.pickQty === null ||
item.pickQty === undefined
);
if (invalidRow) {
+ if (
+ invalidRow.batchNo &&
+ invalidRow.batchNo.length > 0 &&
+ Number(invalidRow.pickQty) <= 0
+ ) {
+ return { valid: false, message: "閫夋嫨浜嗘壒鍙锋椂锛岄鐢ㄦ暟閲忓繀椤诲ぇ浜庨浂" };
+ }
return { valid: false, message: "璇峰畬鍠勫伐搴忋�佸師鏂欍�佹壒鍙峰拰鏁伴噺鍚庡啀淇濆瓨" };
}
return { valid: true, message: "" };
@@ -381,6 +444,17 @@
materialSaving.value = false;
}
};
+
+ // 鎵撳紑閲囪喘鐢宠瀵硅瘽妗�
+ const openPurchaseRequestDialog = () => {
+ purchaseRequestDialogVisible.value = true;
+ };
+
+ // 閲囪喘鐢宠淇濆瓨鍥炶皟
+ const handlePurchaseRequestSaved = () => {
+ // 閲囪喘鐢宠淇濆瓨鎴愬姛鍚庡埛鏂版暟鎹�
+ loadMaterialData();
+ };
</script>
<style scoped lang="scss">
@@ -388,4 +462,15 @@
margin-bottom: 12px;
text-align: right;
}
+
+ .text-danger {
+ color: #f56c6c;
+ font-weight: bold;
+ }
+
+ :deep(.is-stock-insufficient) {
+ .el-input__wrapper {
+ box-shadow: 0 0 0 1px #f56c6c inset;
+ }
+ }
</style>
--
Gitblit v1.9.3