<template> <div> <el-card> <el-form ref="form" :model="form" :rules="rules" label-width="120px"> <el-divider content-position="left"><span style="font-weight: bold; font-size: larger;">工单信息</span></el-divider> <el-row :gutter="10"> <el-col :span="12"> <el-form-item label="工单号:">{{ form.orderCode }}</el-form-item> <el-form-item label="成品编码:">{{ form.materialCode }}</el-form-item> <el-form-item label="计划开始时间:">{{ parseTime(form.planBeginTime) }}</el-form-item> <el-form-item label="计划数量/已派工数量/完成数量:" label-width="220px"> {{ form.planAmount }}/{{ form.dispatchAmount }}/{{ form.completeAmount }} </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="工艺路线:">{{ form.dispatchName }}</el-form-item> <el-form-item label="成品名称:">{{ form.materialName }}</el-form-item> <el-form-item label="计划结束时间:">{{ parseTime(form.planEndTime) }}</el-form-item> </el-col> </el-row> <el-divider content-position="left"><span style="font-weight: bold; font-size: larger;">派工信息</span></el-divider> <el-row :gutter="10" class="mb8"> <el-col :span="1.5"> <el-button icon="el-icon-plus" size="mini" type="primary" @click="handleAddMesProductPlan">新增 </el-button> </el-col> <!-- <el-col :span="1.5">--> <!-- <el-button type="danger" icon="el-icon-delete" size="mini" @click="handleDeleteMesProductPlan">删除--> <!-- </el-button>--> <!-- </el-col>--> </el-row> <el-table ref="mesProductPlan" :data="mesProductPlanList" :row-class-name="rowMesProductPlanIndex" @selection-change="handleMesProductPlanSelectionChange"> <el-table-column align="center" type="selection" width="50"/> <el-table-column v-if="false" align="center" label="序号" prop="index" width="50"/> <el-table-column align="center" label="派工单号" prop="dispatchCode" width="190"> <template slot-scope="scope"> <el-input v-model="scope.row.dispatchCode" :disabled="true"/> </template> </el-table-column> <el-table-column align="center" label="工序" prop="processName" width="140"> <template slot-scope="scope"> <el-input v-model="scope.row.processName" :disabled="true"/> </template> </el-table-column> <el-table-column align="center" label="步骤" prop="processOrder"> <template slot-scope="scope"> <el-input v-model="scope.row.processOrder" :disabled="true"/> </template> </el-table-column> <el-table-column align="center" label="工位" prop="stationName" width="140"> <template slot-scope="scope"> <el-input v-model="scope.row.stationName" :disabled="true"/> </template> </el-table-column> <el-table-column align="center" label="派工数量" prop="planAmount" width="100"> <template slot-scope="scope"> <el-input v-model="scope.row.planAmount" :disabled="scope.row.oldRowFlag"/> </template> </el-table-column> <el-table-column align="center" label="派工标准工时" prop="productionTime" width="100"> <template slot-scope="scope"> <el-input v-model="scope.row.productionTime" :disabled="scope.row.oldRowFlag"/> </template> </el-table-column> <el-table-column align="center" label="计划开始时间" prop="planBeginTime" width="230"> <template slot-scope="scope"> <el-date-picker v-model="scope.row.planBeginTime" :disabled="scope.row.oldRowFlag" clearable placeholder="请选择计划开始时间" type="datetime" value-format="yyyy-MM-dd HH:mm:ss"/> </template> </el-table-column> <el-table-column align="center" label="计划完成时间" prop="planEndTime" width="230"> <template slot-scope="scope"> <el-date-picker v-model="scope.row.planEndTime" :disabled="scope.row.oldRowFlag" clearable placeholder="请选择计划完成时间" type="datetime" value-format="yyyy-MM-dd HH:mm:ss"/> </template> </el-table-column> <el-table-column align="center" label="状态" prop="planStatus" width="150"> <template slot-scope="scope"> <el-select v-model="scope.row.planStatus" :disabled="true" placeholder="请选择状态"> <el-option v-for="dict in dict.type.product_status" :key="dict.value" :label="dict.label" :value="dict.value" /> </el-select> </template> </el-table-column> <el-table-column align="center" class-name="small-padding fixed-width" label="操作" width="50"> <template slot-scope="scope"> <el-button icon="el-icon-search" size="mini" type="primary" @click="handleDrawing(scope.row)" >图纸 </el-button> </template> </el-table-column> </el-table> </el-form> <el-form label-width="100px"> <el-form-item style="text-align: center;margin-left:-100px;margin-top:10px;"> <el-button type="primary" @click="submitForm()">提交</el-button> <el-button @click="close()">返回</el-button> </el-form-item> </el-form> </el-card> <el-dialog :visible.sync="blueprintModel" title="上传图纸" width="30%" @before-close="blueprintModel = false"> <el-upload ref="upload" :auto-upload="false" action="#" multiple list-type="picture-card"> <i slot="default" class="el-icon-plus"></i> <div slot="file" slot-scope="{file}"> <img v-if="isAssetTypeAnImage(file.name)" :alt="file.name" :src="file.url" class="el-upload-list__item-thumbnail" > <span v-else>{{ file.name }}</span> <span class="el-upload-list__item-actions"> <span v-if="isAssetTypeAnImage(file.name)" class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)" > <i class="el-icon-zoom-in"></i> </span> <span class="el-upload-list__item-delete" @click="handleDownload(file)" > <i class="el-icon-download"></i> </span> <span class="el-upload-list__item-delete" @click="$refs.upload.handleRemove(file)" > <i class="el-icon-delete"></i> </span> </span> </div> </el-upload> <span slot="footer" class="dialog-footer"> <el-button @click="blueprintModel = false">取 消</el-button> <el-button type="primary" @click="blueprintModel = false">确 定</el-button> </span> </el-dialog> <el-dialog :visible.sync="pictureDetailModel"> <img :src="dialogImageUrl" alt="" width="100%"> </el-dialog> </div> </template> <script> import {getProductOrder} from "@//api/mes/productOrder"; import {getDispatchCode, getProductPlan, orderAddMesProductPlanList} from "@//api/mes/productplan"; import {getStationByRouteId} from "@//api/mes/baseRoute"; export default { name: "productPlanEdit", dicts: ['active_flag', 'product_status'], data() { return { blueprintModel: false, pictureDetailModel: false, dialogImageUrl: '', // 选中选项卡的 name activeName: "columnInfo", // 表格的高度 tableHeight: document.documentElement.scrollHeight - 245 + "px", // 表信息 tables: [], // 表列信息 columns: [], // 生产派工表格数据 productplanList: [], // 生产计划表格数据 mesProductPlanList: [], // 表详细信息 info: {}, // 表单参数 form: {}, // 表单校验 rules: { productOrderId: [ {required: true, message: "生产工单ID不能为空", trigger: "blur"} ], planCode: [ {required: true, message: "计划编号不能为空", trigger: "blur"} ], dispatchCode: [ {required: true, message: "派工单号不能为空", trigger: "blur"} ], materialId: [ {required: true, message: "物料ID不能为空", trigger: "blur"} ], materialBomId: [ {required: true, message: "物料bomID不能为空", trigger: "blur"} ], stationId: [ {required: true, message: "工位ID不能为空", trigger: "blur"} ], planStatus: [ {required: true, message: "计划状态不能为空", trigger: "change"} ], isFlag: [ {required: true, message: "是否标识不能为空", trigger: "change"} ], }, }; }, created() { const productOrderId = this.$route.params && this.$route.params.productOrderId; if (productOrderId) { // 获取表详细信息 getProductOrder(productOrderId).then(res => { this.form = res.data; }); getProductPlan({productOrderId: productOrderId}).then(res => { res.data.forEach(e => { // 新添加列标识 false=新添加,true=历史行 e.oldRowFlag = true; this.mesProductPlanList.push(e); }) }) } }, methods: { isAssetTypeAnImage(ext) { let suffix = ext.lastIndexOf("."); let name = ext.substr(suffix + 1); return [ 'png', 'jpg', 'jpeg'].includes(name.toLowerCase()) }, /** 提交按钮 */ submitForm() { let dataList = this.mesProductPlanList.filter(plan => !plan.oldRowFlag); if (dataList.length === 0) { this.close(); return; } // 校验派工数量(已派工数量 + 派工数量 <= 计划数量) // 按照processId分组,所有分组的planAmount之和是否相等,相等后输出planAmount之和的值 const sumList = dataList.reduce((result, {processId, planAmount}) => { const numericAmount = parseInt(planAmount, 10); if (!this.isPositiveInteger(numericAmount)) { this.$modal.msgError("派工数量须为大于0的正整数!"); return; } result[processId] = (result[processId] || 0) + numericAmount; return result; }, {}); const uniqueSum = new Set(Object.values(sumList)); if (uniqueSum.size === 1) { const finalSum = Array.from(uniqueSum)[0]; let dispatchedAmount = this.form.dispatchAmount + finalSum; if (dispatchedAmount > this.form.planAmount) { this.$modal.msgError("每个工序的派工数量之和需小于等于该工单计划数量!"); return; } dataList.forEach(e => { e.dispatchedAmount = dispatchedAmount; } ) } else { this.$modal.msgError("每个工序的派工数量之和需相等!"); return; } orderAddMesProductPlanList(dataList).then(res => { this.$modal.msgSuccess(res.msg); this.close(); }); } , /** 生产计划明细序号 */ rowMesProductPlanIndex({row, rowIndex}) { row.index = rowIndex + 1; } , /** 复选框选中数据 */ handleMesProductPlanSelectionChange(selection) { this.checkedMesProductPlan = selection.map(item => item.index) } , /** 关闭按钮 */ close() { const obj = {path: "/mes/plan/productOrder", query: {t: Date.now(), pageNum: this.$route.query.pageNum}}; this.$tab.closeOpenPage(obj); } , /** 查看图纸 */ handleDrawing(row) { this.blueprintModel = true } , /** 生产计划添加按钮操作 */ handleAddMesProductPlan() { let dispatchCode = ""; getDispatchCode().then(res => { dispatchCode = res.msg; getStationByRouteId(this.form.dispatchId).then(res => { if (res.data.length === 0) { this.$modal.msgError("工艺路线未维护工位信息!"); } let lastProcessId = null; res.data.forEach(e => { let obj = {}; obj.dispatchCode = dispatchCode; obj.processId = e.processId; obj.processName = e.processName; obj.processOrder = e.processOrder; obj.stationId = e.stationId; obj.stationName = e.stationName; obj.productionTime = 0; obj.planBeginTime = this.form.planBeginTime; obj.planEndTime = this.form.planEndTime; obj.planStatus = '1'; // multiStationFlag:一个工序对应工位个数 if (e.multiStationFlag > 1) { obj.planAmount = 0; } else { obj.planAmount = this.form.planAmount - this.form.dispatchAmount; } obj.materialId = this.form.materialId; obj.materialBomId = this.form.materialBomId; obj.productOrderId = this.form.productOrderId; // 上一工序ID if (lastProcessId == null || lastProcessId === obj.processId) { obj.lastProcessId = 0; } else { obj.lastProcessId = lastProcessId; } lastProcessId = e.processId; // 新添加列标识 false=新添加,true=历史行 obj.oldRowFlag = false; this.mesProductPlanList.push(obj); }) }) }) } , isPositiveInteger(value) { // 使用正则表达式匹配正整数 return /^[1-9]\d*$/.test(value); } , /** 生产计划明细删除按钮操作 */ handleDeleteMesProductPlan() { if (this.checkedMesProductPlan.length == 0) { this.$modal.msgError("请先选择要删除的生产计划明细数据"); } else { const mesProductPlanList = this.mesProductPlanList; const checkedMesProductPlan = this.checkedMesProductPlan; this.mesProductPlanList = mesProductPlanList.filter(function (item) { return checkedMesProductPlan.indexOf(item.index) == -1 }); } }, handlePictureCardPreview(file) { this.dialogImageUrl = file.url; this.pictureDetailModel = true; } , handleDownload(file) { console.log(file); } }, mounted() { const el = this.$refs.dragTable.$el.querySelectorAll(".el-table__body-wrapper > table > tbody")[0]; // const sortable = Sortable.create(el, { // handle: ".allowDrag", // onEnd: evt => { // const targetRow = this.columns.splice(evt.oldIndex, 1)[0]; // this.columns.splice(evt.newIndex, 0, targetRow); // for (let index in this.columns) { // this.columns[index].sort = parseInt(index) + 1; // } // } // }); } } ; </script>