| src/api/productionManagement/productionOrder.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/fileManagement/borrow/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/fileManagement/document/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/fileManagement/return/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/inventoryManagement/stockManagement/New.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/productionManagement/productionOrder/components/MaterialDetailDialog.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/productionManagement/productionOrder/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/productionManagement/workOrderManagement/components/MaterialDialog.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/api/productionManagement/productionOrder.js
@@ -72,23 +72,47 @@ } // 生产订单-保存领料台账 // export function saveMaterialPickingLedger(data) { // return request({ // url: "/productOrderMaterial/save", // method: "post", // data, // }); // } export function saveMaterialPickingLedger(data) { return request({ url: "/productOrderMaterial/save", url: "/productionOrderPick/savePick", method: "post", data, }); } // 生产订单-领料详情列表 export function listMaterialPickingDetail(query) { export function updateMaterialPickingLedger(data) { return request({ url: "/productOrderMaterial/detailList", method: "get", params: query, url: "/productionOrderPick/updatePick", method: "post", data, }); } // 生产订单-领料详情列表 // export function listMaterialPickingDetail(query) { // return request({ // url: "/productOrderMaterial/detailList", // method: "get", // params: query, // }); // } export function listMaterialPickingBom(productionOrderId) { return request({ url: "/productionOrder/pick/" + productionOrderId, method: "get", }); } export function listMaterialPickingDetail(productionOrderId) { return request({ url: "/productionOrderPick/detail/" + productionOrderId, method: "get", }); } // 生产订单-补料记录列表 export function listMaterialSupplementRecord(query) { return request({ src/views/fileManagement/borrow/index.vue
@@ -100,16 +100,14 @@ </el-col> <el-col :span="12"> <el-form-item label="借阅书籍:" prop="documentationId"> <!-- <el-select v-model="borrowForm.documentationId" placeholder="请选择借阅书籍" style="width: 100%" @change="handleScanContent"> <el-option v-for="item in documentList" :key="item.id" :label="item.docName || item.name" :value="item.id" /> </el-select> --> <div style="display: flex; gap: 10px;"> <el-select v-model="borrowForm.documentationId" placeholder="请选择借阅书籍" style="flex: 1;width: 100px;" @change="handleSelectChange"> <el-select v-if="borrowOperationType !== 'edit'" v-model="borrowForm.documentationId" placeholder="请选择借阅书籍" style="flex: 1;width: 100px;" @change="handleSelectChange" > <el-option v-for="item in documentList" :key="item.id" @@ -118,6 +116,13 @@ /> </el-select> <el-input v-else v-model="currentEditDocName" style="flex: 1;width: 100px;" disabled /> <el-input v-if="borrowOperationType !== 'edit'" v-model="scanContent" placeholder="扫码输入" style="width: 100px;" @@ -205,6 +210,7 @@ const selectedRows = ref([]); const documentList = ref([]); // 文档列表,用于借阅书籍选择 const scanContent = ref() // 扫码内容 const currentEditDocName = ref(''); // 编辑时存储的文档名称 // 分页相关 const pagination = reactive({ currentPage: 1, @@ -282,6 +288,7 @@ { name: "编辑", type: "text", disabled: (row) => row.borrowStatus === '归还', clickFun: (row) => { openBorrowDia('edit', row) }, @@ -428,11 +435,14 @@ if (type === "edit") { // 编辑模式,加载现有数据 Object.assign(borrowForm, data); // 存储文档名称用于显示 currentEditDocName.value = data.docName || ''; } else { // 新增模式,清空表单 Object.keys(borrowForm).forEach(key => { borrowForm[key] = ""; }); currentEditDocName.value = ''; // 清空编辑时的文档名称 // 设置默认状态 borrowForm.borrowStatus = "借阅"; // 设置当前日期为借阅日期 @@ -445,6 +455,7 @@ proxy.$refs.borrowFormRef.resetFields(); borrowDia.value = false; scanContent.value = ''; // 清空扫码内容 currentEditDocName.value = ''; // 清空编辑时的文档名称 }; // 提交借阅表单 src/views/fileManagement/document/index.vue
@@ -862,12 +862,14 @@ documentForm[key] = ""; }); documentForm.attachments = []; // 新增模式下也清空附件 // 设置默认值 - 使用字典数据的第一个选项作为默认值 // 设置默认值 - 文档状态默认设置为"正常" if (document_status.value && document_status.value.length > 0) { documentForm.docStatus = document_status.value[0].value; const normalStatus = document_status.value.find(item => item.label === '正常'); documentForm.docStatus = normalStatus ? normalStatus.value : document_status.value[0].value; } if (document_urgency.value && document_urgency.value.length > 0) { documentForm.urgencyLevel = document_urgency.value[0].value; const normalUrgency = document_urgency.value.find(item => item.label === '普通'); documentForm.urgencyLevel = normalUrgency ? normalUrgency.value : document_urgency.value[0].value; } } }; src/views/fileManagement/return/index.vue
@@ -103,16 +103,14 @@ <el-row :gutter="20"> <el-col :span="12"> <el-form-item label="文档:" prop="borrowId"> <!-- <el-select v-model="returnForm.borrowId" placeholder="请选择文档" style="flex: 1;" @change="handleDocumentChange"> <el-option v-for="item in documentList" :key="item.id" :label="item.docName || item.name" :value="item.id" /> </el-select> --> <div style="display: flex; gap: 10px;"> <el-select v-model="returnForm.borrowId" placeholder="请选择文档" style="width: 120px;" @change="handleDocumentChange"> <el-select v-if="returnOperationType !== 'edit'" v-model="returnForm.borrowId" placeholder="请选择文档" style="width: 120px;" @change="handleDocumentChange" > <el-option v-for="item in documentList" :key="item.id" @@ -121,6 +119,13 @@ /> </el-select> <el-input v-else v-model="currentEditDocName" style="width: 120px;" disabled /> <el-input v-if="returnOperationType !== 'edit'" v-model="scanContent" placeholder="扫码输入" style="flex: 1;" @@ -215,6 +220,7 @@ const documentList = ref([]); // 文档列表 const borrowInfoList = ref([]); // 借阅信息列表 const scanContent = ref(); // 扫码内容 const currentEditDocName = ref(''); // 编辑时存储的文档名称 // 分页相关 const pagination = reactive({ @@ -286,6 +292,7 @@ { name: "编辑", type: "text", disabled: (row) => row.borrowStatus === '归还', clickFun: (row) => { openReturnDia('edit', row) }, @@ -396,15 +403,14 @@ if (type === "edit") { // 编辑模式,加载现有数据 Object.assign(returnForm, data); // 编辑模式下,文档选择后自动填充借阅人和应归还日期 if (returnForm.borrowId) { handleDocumentChange(returnForm.borrowId); } // 存储文档名称用于显示 currentEditDocName.value = data.docName || ''; } else { // 新增模式,清空表单 Object.keys(returnForm).forEach(key => { returnForm[key] = ""; }); currentEditDocName.value = ''; // 清空编辑时的文档名称 // 设置默认状态 returnForm.borrowStatus = "归还"; // 设置当前日期为归还日期 @@ -418,6 +424,7 @@ returnDia.value = false; scanContent.value = ''; // 清空扫码内容 borrowInfoList.value = []; // 清空借阅信息列表 currentEditDocName.value = ''; // 清空编辑时的文档名称 }; // 提交归还表单 src/views/inventoryManagement/stockManagement/New.vue
@@ -1,14 +1,14 @@ <template> <div> <el-dialog v-model="isShow" <el-dialog v-model="isShow" title="新增库存" width="800" @close="closeModal" > <el-form label-width="140px" :model="formState" label-position="top" ref="formRef"> <el-form-item label="产品名称" @close="closeModal"> <el-form label-width="140px" :model="formState" label-position="top" ref="formRef"> <el-form-item label="产品名称" prop="productModelId" :rules="[ { @@ -16,29 +16,23 @@ message: '请选择产品', trigger: 'change', } ]" > <el-button type="primary" @click="showProductSelectDialog = true"> ]"> <el-button type="primary" @click="showProductSelectDialog = true"> {{ formState.productName ? formState.productName : '选择产品' }} </el-button> </el-form-item> <el-form-item label="规格" prop="productModelName" > <el-input v-model="formState.productModelName" disabled /> <el-form-item label="规格" prop="productModelName"> <el-input v-model="formState.productModelName" disabled /> </el-form-item> <el-form-item label="单位" prop="unit" > <el-input v-model="formState.unit" disabled /> <el-form-item label="单位" prop="unit"> <el-input v-model="formState.unit" disabled /> </el-form-item> <el-form-item label="库存类型" <el-form-item label="库存类型" prop="type" :rules="[ { @@ -46,51 +40,58 @@ message: '请选择库存类型', trigger: 'change', } ]" > <el-select v-model="formState.type" placeholder="请选择库存类型"> <el-option label="合格库存" value="qualified" /> <el-option label="不合格库存" value="unqualified" /> ]"> <el-select v-model="formState.type" placeholder="请选择库存类型"> <el-option label="合格库存" value="qualified" /> <el-option label="不合格库存" value="unqualified" /> </el-select> </el-form-item> <el-form-item label="库存数量" prop="qualitity" > <el-input-number v-model="formState.qualitity" :step="1" :min="1" style="width: 100%" /> <el-form-item label="库存数量" prop="qualitity"> <el-input-number v-model="formState.qualitity" :step="1" :min="1" style="width: 100%" /> </el-form-item> <el-form-item label="批号" <el-form-item label="批号" prop="batchNo" > <el-input v-model="formState.batchNo" placeholder="请输入批号" /> :rules="[ { required: true, message: '请输入批号', trigger: 'blur', } ]"> <el-input v-model="formState.batchNo" placeholder="请输入批号" /> </el-form-item> <el-form-item v-if="formState.type === 'qualified'" <el-form-item v-if="formState.type === 'qualified'" label="库存预警数量" prop="warnNum" > <el-input-number v-model="formState.warnNum" :step="1" :min="0" :max="formState.qualitity" style="width: 100%" /> prop="warnNum"> <el-input-number v-model="formState.warnNum" :step="1" :min="0" :max="formState.qualitity" style="width: 100%" /> </el-form-item> <el-form-item label="备注" prop="remark"> <el-input v-model="formState.remark" type="textarea" /> <el-form-item label="备注" prop="remark"> <el-input v-model="formState.remark" type="textarea" /> </el-form-item> </el-form> <!-- 产品选择弹窗 --> <ProductSelectDialog v-model="showProductSelectDialog" <ProductSelectDialog v-model="showProductSelectDialog" @confirm="handleProductSelect" :top-product-parent-id="props.topProductParentId" single /> single /> <template #footer> <div class="dialog-footer"> <el-button type="primary" @click="handleSubmit">确认</el-button> <el-button type="primary" @click="handleSubmit">确认</el-button> <el-button @click="closeModal">取消</el-button> </div> </template> @@ -113,10 +114,10 @@ type: Number, default: undefined, required: false, } }, }); const emit = defineEmits(['update:visible', 'completed']); const emit = defineEmits(["update:visible", "completed"]); // 响应式数据(替代选项式的 data) const formState = ref({ @@ -129,7 +130,7 @@ qualitity: 0, batchNo: null, warnNum: 0, remark: '', remark: "", }); const isShow = computed({ @@ -137,20 +138,23 @@ return props.visible; }, set(val) { emit('update:visible', val); emit("update:visible", val); }, }); const showProductSelectDialog = ref(false); // 批号为空时转为 null watch(() => formState.value.batchNo, (val) => { if (val === '') { watch( () => formState.value.batchNo, val => { if (val === "") { formState.value.batchNo = null; } }); } ); let { proxy } = getCurrentInstance() let { proxy } = getCurrentInstance(); const closeModal = () => { // 重置表单数据 @@ -164,13 +168,13 @@ qualitity: 0, batchNo: null, warnNum: 0, remark: '', remark: "", }; isShow.value = false; }; // 产品选择处理 const handleProductSelect = async (products) => { const handleProductSelect = async products => { if (products && products.length > 0) { const product = products[0]; formState.value.productId = product.productId; @@ -180,7 +184,7 @@ formState.value.unit = product.unit; showProductSelectDialog.value = false; // 触发表单验证更新 proxy.$refs["formRef"]?.validateField('productModelId'); proxy.$refs["formRef"]?.validateField("productModelId"); } }; @@ -196,29 +200,27 @@ proxy.$modal.msgError("请选择规格"); return; } if (formState.value.type === 'qualified') { if (formState.value.type === "qualified") { addStockInRecordOnly(formState.value).then(res => { // 关闭模态框 isShow.value = false; // 告知父组件已完成 emit('completed'); emit("completed"); proxy.$modal.msgSuccess("提交成功"); }) }); } else { formState.value.warnNum = 0; createStockUnInventory(formState.value).then(res => { // 关闭模态框 isShow.value = false; // 告知父组件已完成 emit('completed'); emit("completed"); proxy.$modal.msgSuccess("提交成功"); }) }); } } }) }); }; defineExpose({ closeModal, src/views/productionManagement/productionOrder/components/MaterialDetailDialog.vue
@@ -1,44 +1,82 @@ <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"> <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)"> <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-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" <el-button type="warning" :loading="materialReturnConfirming" :disabled="!canOpenReturnSummary" @click="openReturnSummaryDialog" > @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="supplementUserName" min-width="120" /> <el-table-column label="补料日期" prop="supplementTime" min-width="160" /> <el-table-column label="补料原因" prop="supplementReason" min-width="200" /> <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="supplementUserName" min-width="120" /> <el-table-column label="补料日期" prop="supplementTime" min-width="160" /> <el-table-column label="补料原因" prop="supplementReason" min-width="200" /> </el-table> <template #footer> <span class="dialog-footer"> @@ -46,18 +84,30 @@ </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-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 type="primary" :loading="materialReturnConfirming" @click="handleReturnConfirm">确认提交</el-button> <el-button @click="returnSummaryDialogVisible = false">取消</el-button> </span> </template> @@ -68,7 +118,11 @@ <script setup> import { computed, ref, watch } from "vue"; import { ElMessage } from "element-plus"; import { listMaterialPickingDetail, listMaterialSupplementRecord, confirmMaterialReturn } from "@/api/productionManagement/productionOrder.js"; import { listMaterialPickingDetail, listMaterialSupplementRecord, confirmMaterialReturn, } from "@/api/productionManagement/productionOrder.js"; const props = defineProps({ modelValue: { type: Boolean, default: false }, @@ -90,7 +144,9 @@ const returnSummaryDialogVisible = ref(false); const returnSummaryList = ref([]); const calcReturnQty = item => Number(item.pickQty || 0) + Number(item.supplementQty || 0) - Number(item.actualQty || 0); Number(item.pickQuantity || 0) + Number(item.supplementQty || 0) - Number(item.actualQty || 0); const canOpenReturnSummary = computed(() => materialDetailTableData.value.some(item => calcReturnQty(item) > 0) ); @@ -100,7 +156,7 @@ materialDetailLoading.value = true; materialDetailTableData.value = []; try { const res = await listMaterialPickingDetail({ orderId: props.orderRow.id }); const res = await listMaterialPickingDetail(props.orderRow.id); materialDetailTableData.value = res.data || []; } finally { materialDetailLoading.value = false; @@ -126,7 +182,9 @@ supplementRecordLoading.value = true; supplementRecordTableData.value = []; try { const res = await listMaterialSupplementRecord({ materialDetailId: row.id }); const res = await listMaterialSupplementRecord({ materialDetailId: row.id, }); supplementRecordTableData.value = res.data || []; } finally { supplementRecordLoading.value = false; @@ -138,11 +196,13 @@ materialDetailTableData.value.forEach(item => { const returnQty = calcReturnQty(item); if (returnQty <= 0) return; const key = `${item.materialModelId || ""}_${item.materialName || ""}_${item.materialModel || ""}_${item.unit || ""}`; const key = `${item.productModelId || ""}_${item.productName || ""}_${ item.model || "" }_${item.unit || ""}`; const old = map.get(key) || { summaryKey: key, materialName: item.materialName || "", materialModel: item.materialModel || "", materialName: item.productName || "", materialModel: item.model || "", unit: item.unit || "", returnQtyTotal: 0, }; src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue
@@ -13,25 +13,25 @@ border row-key="tempId"> <el-table-column label="工序名称" min-width="180"> min-width="140"> <template #default="{ row }"> <span v-if="row.bom === true">{{ row.processName || "-" }}</span> <span v-if="row.bom === true">{{ row.operationName || "-" }}</span> <el-select v-else v-model="row.processName" v-model="row.operationName" placeholder="请选择工序" clearable filterable style="width: 100%;" @change="val => handleProcessNameChange(row, val)"> <el-option v-for="item in processOptions" :key="item.id" :key="item.technologyOperationId" :label="item.name" :value="item.name" /> </el-select> </template> </el-table-column> <el-table-column label="原料名称" min-width="160"> min-width="140"> <template #default="{ row }"> <span v-if="row.bom === true">{{ row.materialName || "-" }}</span> <el-button v-else @@ -43,17 +43,37 @@ </template> </el-table-column> <el-table-column label="原料型号" min-width="180"> min-width="140"> <template #default="{ row }"> {{ row.materialModel || "-" }} </template> </el-table-column> <!-- 批号多选 --> <el-table-column min-width="200"> <template #header> <span style="color: #f56c6c; margin-right: 4px;">*</span> <span>批号</span> </template> <template #default="{ row }"> <el-select v-model="row.batchNo" multiple collapse-tags collapse-tags-indicator placeholder="请选择批号" style="width: 100%;"> <el-option v-for="item in row.batchNoList" :key="item" :label="item" :value="item" /> </el-select> </template> </el-table-column> <el-table-column label="需求数量" min-width="120"> <template #default="{ row }"> <span v-if="row.bom === true">{{ row.requiredQty ?? "-" }}</span> <span v-if="row.bom === true">{{ row.demandedQuantity ?? "-" }}</span> <el-input-number v-else v-model="row.requiredQty" v-model="row.demandedQuantity" :min="0" :precision="3" :step="1" @@ -63,7 +83,7 @@ </template> </el-table-column> <el-table-column label="计量单位" width="120"> width="100"> <template #default="{ row }"> {{ row.unit || "-" }} </template> @@ -110,12 +130,18 @@ import { computed, ref, watch } from "vue"; import { ElMessage } from "element-plus"; import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue"; import { findProductProcessRouteItemList } from "@/api/productionManagement/productProcessRoute.js"; 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 }, @@ -139,16 +165,22 @@ const createMaterialRow = (row = {}) => ({ tempId: row.id || `temp_${++materialTempId}`, id: row.id, processId: row.processId, productProcessId: row.productProcessId || row.processId, processName: row.processName || "", processId: row.processId || row.technologyOperationId, technologyOperationId: row.technologyOperationId || row.processId, operationName: row.operationName || "", bom: row.bom === true, materialModelId: row.materialModelId, materialName: row.materialName || "", materialModel: row.materialModel || "", requiredQty: Number(row.requiredQty ?? 0), materialModelId: row.materialModelId || row.productModelId, materialName: row.materialName || row.productName || "", materialModel: row.materialModel || row.model || "", demandedQuantity: Number(row.requiredQty ?? row.demandedQuantity ?? 0), unit: row.unit || "", pickQty: Number(row.pickQty ?? row.requiredQty ?? 0), pickQty: Number(row.pickQty ?? row.pickQuantity ?? 0), batchNo: row.batchNo ? typeof row.batchNo === "string" ? row.batchNo.split(",") : row.batchNo : [], batchNoList: row.batchNoList || [], }); const getProcessOptions = async () => { @@ -161,19 +193,20 @@ : res?.data?.records || []; const processMap = new Map(); routeList.forEach(item => { const processId = item.processId; const processName = item.processName; if (!processId || !processName) return; const key = `${processId}_${processName}`; const processId = item.technologyOperationId; const operationName = item.operationName; if (!processId || !operationName) return; const key = `${processId}_${operationName}`; if (!processMap.has(key)) { processMap.set(key, { id: processId, name: processName, name: operationName, }); } }); processOptions.value = Array.from(processMap.values()); }; const isDetail = ref(true); const loadMaterialData = async () => { if (!props.orderRow?.id) return; @@ -181,23 +214,23 @@ materialTableData.value = []; await getProcessOptions(); try { const detailRes = await listMaterialPickingDetail({ orderId: props.orderRow.id, }); 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 { 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; } const ledgerRes = await listMaterialPickingLedger({ orderId: props.orderRow.id, }); const ledgerList = Array.isArray(ledgerRes?.data) ? ledgerRes.data : ledgerRes?.data?.records || []; materialTableData.value = ledgerList.map(item => createMaterialRow(item)); } finally { materialTableLoading.value = false; } @@ -225,14 +258,16 @@ materialTableData.value.splice(index, 1); }; const handleProcessNameChange = (row, processName) => { const process = processOptions.value.find(item => item.name === processName); row.productProcessId = process?.id; const handleProcessNameChange = (row, operationName) => { const process = processOptions.value.find( item => item.name === operationName ); row.technologyOperationId = process?.technologyOperationId; }; const handleRequiredQtyChange = (row, val) => { const required = Number(val ?? 0); row.requiredQty = required; row.demandedQuantity = required; if (!row.pickQty || Number(row.pickQty) === 0) { row.pickQty = required; } @@ -246,6 +281,8 @@ }; const handleMaterialProductConfirm = products => { console.log(products, "products"); if (!products || products.length === 0) return; const index = currentMaterialSelectRowIndex.value; if (index < 0 || !materialTableData.value[index]) return; @@ -257,6 +294,7 @@ product.materialName || product.productName || product.name || ""; row.materialModel = product.materialModel || product.model || ""; row.unit = product.unit || product.measureUnit || ""; row.batchNoList = product.batchNoList; currentMaterialSelectRowIndex.value = -1; materialProductDialogVisible.value = false; }; @@ -266,22 +304,24 @@ return { valid: false, message: "请先新增领料数据" }; } const invalidNewRow = materialTableData.value.find( item => item.bom !== true && (!item.processName || !item.materialName) item => item.bom !== true && (!item.operationName || !item.materialName) ); if (invalidNewRow) { return { valid: false, message: "新增行的工序名称和原料名称为必填项" }; } const invalidRow = materialTableData.value.find( item => !item.processName || !item.operationName || !item.materialName || item.requiredQty === null || item.requiredQty === undefined || !item.batchNo || item.batchNo.length === 0 || item.demandedQuantity === null || item.demandedQuantity === undefined || item.pickQty === null || item.pickQty === undefined ); if (invalidRow) { return { valid: false, message: "请完善工序、原料和数量后再保存" }; return { valid: false, message: "请完善工序、原料、批号和数量后再保存" }; } return { valid: true, message: "" }; }; @@ -295,22 +335,49 @@ } materialSaving.value = true; try { await saveMaterialPickingLedger({ orderId: props.orderRow.id, items: materialTableData.value.map(item => ({ if (isDetail.value) { await updateMaterialPickingLedger({ productionOrderId: props.orderRow.id, productionOrderPickDto: materialTableData.value.map(item => ({ id: item.id, processId: item.processName, productProcessId: item.productProcessId, processName: item.processName, // processId: item.operationName, technologyOperationId: item.technologyOperationId, operationName: item.operationName, bom: item.bom === true, materialModelId: item.materialModelId, materialName: item.materialName, materialModel: item.materialModel, requiredQty: item.requiredQty, productModelId: item.materialModelId, // materialName: item.materialName, // materialModel: item.materialModel, demandedQuantity: item.demandedQuantity, unit: item.unit, pickQty: item.pickQty, pickQuantity: item.pickQty, batchNo: Array.isArray(item.batchNo) ? item.batchNo.join(",") : item.batchNo, })), }); } else { await saveMaterialPickingLedger({ productionOrderId: props.orderRow.id, productionOrderPickDto: materialTableData.value.map(item => ({ id: item.id, // processId: item.operationName, technologyOperationId: item.technologyOperationId, operationName: item.operationName, bom: item.bom === true, productModelId: item.materialModelId, // materialName: item.materialName, // materialModel: item.materialModel, demandedQuantity: item.demandedQuantity, unit: item.unit, pickQuantity: item.pickQty, batchNo: Array.isArray(item.batchNo) ? item.batchNo.join(",") : item.batchNo, })), }); } ElMessage({ message: "领料成功", type: "success" }); emit("saved"); dialogVisible.value = false; } finally { src/views/productionManagement/productionOrder/index.vue
@@ -304,7 +304,7 @@ label: "操作", align: "center", fixed: "right", width: 340, width: 360, operation: [ { name: "工艺路线", @@ -337,27 +337,20 @@ showSourceData(row); }, }, // { // name: "产品结构", // type: "text", // clickFun: row => { // showProductStructure(row); // }, // }, // { // name: "领料", // type: "text", // clickFun: row => { // openMaterialDialog(row); // }, // }, // { // name: "领料详情", // type: "text", // clickFun: row => { // openMaterialDetailDialog(row); // }, // }, { name: "领料", type: "text", clickFun: row => { openMaterialDialog(row); }, }, { name: "领料详情", type: "text", clickFun: row => { openMaterialDetailDialog(row); }, }, ], }, ]); src/views/productionManagement/workOrderManagement/components/MaterialDialog.vue
@@ -1,86 +1,119 @@ <template> <div> <el-dialog v-model="dialogVisible" <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"> @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" <el-input-number v-model="row.actualQty" :min="0" :precision="3" :step="1" controls-position="right" style="width: 100%;" /> style="width: 100%;" /> </template> </el-table-column> <el-table-column label="操作" align="center" fixed="right" width="180"> <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> <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 type="primary" :loading="pickSubmitting" @click="handleSubmitPick">领用</el-button> <el-button @click="dialogVisible = false">取消</el-button> </span> </template> </el-dialog> <FormDialog v-model="supplementDialogVisible" <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" @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%;" /> style="width: 100%;" /> </el-form-item> <el-form-item label="补料原因" prop="supplementReason"> <el-input v-model="supplementForm.supplementReason" <el-form-item label="补料原因" prop="supplementReason"> <el-input v-model="supplementForm.supplementReason" type="textarea" :rows="3" maxlength="200" show-word-limit placeholder="请输入补料原因" /> placeholder="请输入补料原因" /> </el-form-item> </el-form> <template #footer> <span class="dialog-footer"> <el-button type="primary" :loading="supplementSubmitting" @click="handleSubmitSupplement">确定</el-button> <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-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"> @@ -139,8 +172,12 @@ const supplementRecordTableData = ref([]); const supplementRules = { supplementQty: [{ required: true, message: "请输入补料数量", trigger: "blur" }], supplementReason: [{ required: true, message: "请输入补料原因", trigger: "blur" }], supplementQty: [ { required: true, message: "请输入补料数量", trigger: "blur" }, ], supplementReason: [ { required: true, message: "请输入补料原因", trigger: "blur" }, ], }; const loadMaterialTable = async row => { if (!row?.id) return; @@ -235,7 +272,12 @@ if (materialTableData.value.length === 0) { return { valid: false, message: "暂无可领用物料" }; } const invalidRow = materialTableData.value.find(item => item.actualQty === null || item.actualQty === undefined || item.actualQty === ""); const invalidRow = materialTableData.value.find( item => item.actualQty === null || item.actualQty === undefined || item.actualQty === "" ); if (invalidRow) { return { valid: false, message: "请填写实际数量后再领用" }; }