diff --git a/klp-flow/src/main/java/com/klp/flow/domain/EqpMaintenancePlanDetail.java b/klp-flow/src/main/java/com/klp/flow/domain/EqpMaintenancePlanDetail.java index 1be5a9ede..68ea2c5fc 100644 --- a/klp-flow/src/main/java/com/klp/flow/domain/EqpMaintenancePlanDetail.java +++ b/klp-flow/src/main/java/com/klp/flow/domain/EqpMaintenancePlanDetail.java @@ -55,6 +55,12 @@ public class EqpMaintenancePlanDetail extends BaseEntity { * 维修内容描述 */ private String repairContent; + private String lineExecutor; + private String equipmentExecutor; + private String plannedCompleteTime; + private String actualCompleteTime; + private String totalHours; + private String acceptanceUser; /** * 维修负责人 */ diff --git a/klp-flow/src/main/java/com/klp/flow/domain/bo/EqpMaintenancePlanDetailBo.java b/klp-flow/src/main/java/com/klp/flow/domain/bo/EqpMaintenancePlanDetailBo.java index f02ccc350..f0709efc8 100644 --- a/klp-flow/src/main/java/com/klp/flow/domain/bo/EqpMaintenancePlanDetailBo.java +++ b/klp-flow/src/main/java/com/klp/flow/domain/bo/EqpMaintenancePlanDetailBo.java @@ -62,6 +62,12 @@ public class EqpMaintenancePlanDetailBo extends BaseEntity { * 维修内容描述 */ private String repairContent; + private String lineExecutor; + private String equipmentExecutor; + private String plannedCompleteTime; + private String actualCompleteTime; + private String totalHours; + private String acceptanceUser; /** * 维修负责人 diff --git a/klp-flow/src/main/java/com/klp/flow/domain/vo/EqpMaintenancePlanDetailVo.java b/klp-flow/src/main/java/com/klp/flow/domain/vo/EqpMaintenancePlanDetailVo.java index 61569a24a..537f9bb83 100644 --- a/klp-flow/src/main/java/com/klp/flow/domain/vo/EqpMaintenancePlanDetailVo.java +++ b/klp-flow/src/main/java/com/klp/flow/domain/vo/EqpMaintenancePlanDetailVo.java @@ -25,80 +25,92 @@ public class EqpMaintenancePlanDetailVo { /** * 明细ID */ - @ExcelProperty(value = "明细ID") + @ExcelProperty(value = "编号") private Long detailId; /** * 维修计划ID */ - @ExcelProperty(value = "维修计划ID") private Long planId; /** * 产线名称 */ - @ExcelProperty(value = "产线名称") private String productionLine; /** * 设备部件名称 */ - @ExcelProperty(value = "设备部件名称") private String componentName; /** * 单条维修项计划执行日期 */ - @ExcelProperty(value = "单条维修项计划执行日期") + @ExcelProperty(value = "时间") + @JsonFormat(pattern = "yyyy-MM-dd") private Date itemPlanDate; /** * 明细类型:0=保养 1=维修 */ - @ExcelProperty(value = "明细类型:0=保养 1=维修") + @ExcelProperty(value = "明细类型", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "0=保养,1=维修") private Long maintenanceCategory; /** * 明细完成状态:0=未开始 1=进行中 2=已完成 */ - @ExcelProperty(value = "明细完成状态:0=未开始 1=进行中 2=已完成") + @ExcelProperty(value = "是否完成", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "0=否,1=否,2=是") private Long detailStatus; /** * 维修内容描述 */ - @ExcelProperty(value = "维修内容描述") + @ExcelProperty(value = "具体工作内容") private String repairContent; + @ExcelProperty(value = "产线执行人员") + private String lineExecutor; + + @ExcelProperty(value = "设备执行人员") + private String equipmentExecutor; + + @ExcelProperty(value = "预计完成时间") + private String plannedCompleteTime; + + @ExcelProperty(value = "实际完成时间") + private String actualCompleteTime; + + @ExcelProperty(value = "总耗时(h)") + private String totalHours; + + @ExcelProperty(value = "验收人") + private String acceptanceUser; + /** * 维修负责人 */ - @ExcelProperty(value = "维修负责人") private String repairUser; /** * 完成时间(打勾时记录) */ - @ExcelProperty(value = "完成时间", converter = ExcelDictConvert.class) - @ExcelDictFormat(readConverterExp = "打=勾时记录") private Date completeTime; /** * 实际支出金额(元) */ - @ExcelProperty(value = "实际支出金额(元)") private BigDecimal actualCost; /** * 完成进度百分比(0-100) */ - @ExcelProperty(value = "完成进度百分比(0-100)") private Long progressRate; /** * 目标厂家 */ - @ExcelProperty(value = "目标厂家") private String targetManufacturer; /** diff --git a/klp-flow/src/main/resources/mapper/flow/EqpMaintenancePlanDetailMapper.xml b/klp-flow/src/main/resources/mapper/flow/EqpMaintenancePlanDetailMapper.xml index a51a88805..6732e384d 100644 --- a/klp-flow/src/main/resources/mapper/flow/EqpMaintenancePlanDetailMapper.xml +++ b/klp-flow/src/main/resources/mapper/flow/EqpMaintenancePlanDetailMapper.xml @@ -13,6 +13,12 @@ + + + + + + diff --git a/klp-ui/src/utils/enum.js b/klp-ui/src/utils/enum.js index ea440f4fc..4787c34a8 100644 --- a/klp-ui/src/utils/enum.js +++ b/klp-ui/src/utils/enum.js @@ -12,4 +12,14 @@ export const MemoInputStorageKey = { packagingRequirement: 'packagingRequirement', // 打包要求 coilSpec: 'coilSpec', // 钢卷规格 coatingType: 'coatingType', // 钢卷镀层种类 -} \ No newline at end of file + transferNo: 'transferNo', // 调拨单号 + transferName: 'transferName', // 调拨单名称 + maintenanceRepairContent: 'maintenanceRepairContent', // 维修明细-具体工作内容 + maintenanceLineExecutor: 'maintenanceLineExecutor', // 维修明细-产线执行人员 + maintenanceEquipmentExecutor: 'maintenanceEquipmentExecutor', // 维修明细-设备执行人员 + maintenancePlannedCompleteTime: 'maintenancePlannedCompleteTime', // 维修明细-预计完成时间 + maintenanceActualCompleteTime: 'maintenanceActualCompleteTime', // 维修明细-实际完成时间 + maintenanceTotalHours: 'maintenanceTotalHours', // 维修明细-总耗时 + maintenanceAcceptanceUser: 'maintenanceAcceptanceUser', // 维修明细-验收人 + maintenanceRemark: 'maintenanceRemark', // 维修明细-备注 +} diff --git a/klp-ui/src/views/wms/post/eqp/approval.vue b/klp-ui/src/views/wms/post/eqp/approval.vue index 5cdfa9ab2..b937bba68 100644 --- a/klp-ui/src/views/wms/post/eqp/approval.vue +++ b/klp-ui/src/views/wms/post/eqp/approval.vue @@ -103,20 +103,23 @@ 维修明细 · Maintenance Details - - - - + + - - - - + + - + + + + + + + + + + +
暂无维修明细
diff --git a/klp-ui/src/views/wms/post/eqp/execute.vue b/klp-ui/src/views/wms/post/eqp/execute.vue index ddb6af688..ed50a8a7d 100644 --- a/klp-ui/src/views/wms/post/eqp/execute.vue +++ b/klp-ui/src/views/wms/post/eqp/execute.vue @@ -92,16 +92,19 @@ 维修明细进度 · Detail Progress - - - - + + - - + + + + + + + + + + @@ -240,18 +321,18 @@ import { listMaintenancePlanDetail, addMaintenancePlanDetail, updateMaintenanceP import { listEquipmentInspectionRecord } from "@/api/mes/eqp/equipmentInspectionRecord"; import { listProductionLine } from "@/api/wms/productionLine"; import DragResizePanel from "@/components/DragResizePanel/index.vue"; +import MemoInput from "@/components/MemoInput/index.vue"; import { parseTime } from '@/utils/klp' export default { name: "EqpMaintenance", - components: { DragResizePanel }, + components: { DragResizePanel, MemoInput }, data() { return { loading: false, detailLoading: false, buttonLoading: false, inspectionLoading: false, - detailButtonLoading: false, total: 0, dataList: [], currentRow: null, @@ -273,11 +354,7 @@ export default { inspectionQueried: false, selectedInspectionRows: [], // 维修明细 - detailList: [], - detailDialogVisible: false, - detailDialogTitle: "", - detailForm: {}, - editingDetailId: null + detailList: [] }; }, created() { @@ -324,7 +401,9 @@ export default { loadDetailList(planId) { var self = this; listMaintenancePlanDetail({ planId: planId, pageNum: 1, pageSize: 999 }).then(function(r) { - self.detailList = r.rows || []; + self.detailList = (r.rows || []).map(function(item) { + return self.decorateDetailRow(item); + }); }); }, // ---- 检修记录查询 ---- @@ -373,9 +452,17 @@ export default { componentName: rec.partName || '', productionLine: self.currentRow.productionLine || rec.productionLine || '', maintenanceCategory: 1, + itemPlanDate: rec.inspectTime ? parseTime(rec.inspectTime, '{y}-{m}-{d}') : parseTime(new Date(), '{y}-{m}-{d}'), repairContent: rec.abnormalDesc || '', + lineExecutor: rec.inspector || '', + equipmentExecutor: '', + plannedCompleteTime: '', + actualCompleteTime: '', + totalHours: '', + acceptanceUser: '', repairUser: rec.inspector || '', - detailStatus: 0 + detailStatus: 0, + remark: rec.remark || '' }); }); Promise.all(promises).then(function() { @@ -464,56 +551,139 @@ export default { }, // ---- 明细管理 ---- handleAddDetail() { - this.detailForm = { - planId: this.currentRow.planId, - componentName: '', - productionLine: this.currentRow.productionLine || '', - maintenanceCategory: 1, - repairContent: '', - repairUser: '', - itemPlanDate: undefined, - targetManufacturer: '', - detailStatus: 0 - }; - this.editingDetailId = null; - this.detailDialogTitle = "添加维修明细"; - this.detailDialogVisible = true; - }, - handleEditDetail(row) { - this.detailForm = Object.assign({}, row); - this.editingDetailId = row.detailId; - this.detailDialogTitle = "编辑维修明细"; - this.detailDialogVisible = true; - }, - submitDetailForm() { - if (!this.detailForm.componentName) { - this.$modal.msgWarning("请输入设备部件名称"); + if (!this.currentRow || !this.currentRow.planId) return; + if (this.getEditingDetailRow()) { + this.$modal.msgWarning("请先保存或取消当前编辑行"); return; } - var self = this; - this.detailButtonLoading = true; - if (this.editingDetailId) { - updateMaintenancePlanDetail(this.detailForm).then(function() { - self.$modal.msgSuccess("修改成功"); - self.detailDialogVisible = false; - self.loadDetailList(self.currentRow.planId); - }).finally(function() { self.detailButtonLoading = false; }); - } else { - addMaintenancePlanDetail(this.detailForm).then(function() { - self.$modal.msgSuccess("添加成功"); - self.detailDialogVisible = false; - self.loadDetailList(self.currentRow.planId); - }).finally(function() { self.detailButtonLoading = false; }); + var row = this.decorateDetailRow(this.getDefaultDetailRow()); + row._isNew = true; + row._editing = true; + row._origin = null; + this.detailList.unshift(row); + }, + handleEditDetail(row) { + if (!row) return; + var editing = this.getEditingDetailRow(); + if (editing && editing !== row) { + this.$modal.msgWarning("请先保存或取消当前编辑行"); + return; } + this.beginDetailEdit(row); + }, + beginDetailEdit(row) { + if (!row) return; + row._origin = JSON.parse(JSON.stringify({ + itemPlanDate: row.itemPlanDate, + repairContent: row.repairContent, + lineExecutor: row.lineExecutor, + equipmentExecutor: row.equipmentExecutor, + plannedCompleteTime: row.plannedCompleteTime, + actualCompleteTime: row.actualCompleteTime, + totalHours: row.totalHours, + acceptanceUser: row.acceptanceUser, + detailStatus: row.detailStatus, + remark: row.remark + })); + row._editing = true; + }, + cancelEditDetail(row) { + if (!row) return; + if (row._isNew) { + this.detailList = this.detailList.filter(function(r) { return r !== row; }); + return; + } + if (row._origin) { + row.itemPlanDate = row._origin.itemPlanDate; + row.repairContent = row._origin.repairContent; + row.lineExecutor = row._origin.lineExecutor; + row.equipmentExecutor = row._origin.equipmentExecutor; + row.plannedCompleteTime = row._origin.plannedCompleteTime; + row.actualCompleteTime = row._origin.actualCompleteTime; + row.totalHours = row._origin.totalHours; + row.acceptanceUser = row._origin.acceptanceUser; + row.detailStatus = row._origin.detailStatus; + row.remark = row._origin.remark; + } + row._editing = false; + row._origin = null; }, handleDeleteDetail(row) { var self = this; + if (!row) return; + if (row._isNew) { + this.detailList = this.detailList.filter(function(r) { return r !== row; }); + return; + } this.$modal.confirm('确认删除该维修明细?').then(function() { return delMaintenancePlanDetail(row.detailId); }).then(function() { self.$modal.msgSuccess("删除成功"); self.loadDetailList(self.currentRow.planId); }).catch(function() { }); + }, + getEditingDetailRow() { + return this.detailList.find(function(r) { return r && r._editing; }) || null; + }, + decorateDetailRow(row) { + var r = row || {}; + if (!r._rowKey) r._rowKey = r.detailId ? ("detail_" + r.detailId) : ("tmp_" + Date.now() + "_" + Math.random().toString(16).slice(2)); + if (typeof r._editing !== 'boolean') r._editing = false; + if (typeof r._isNew !== 'boolean') r._isNew = false; + if (!r._origin) r._origin = null; + if (r.detailStatus === undefined || r.detailStatus === null) r.detailStatus = 0; + return r; + }, + getDefaultDetailRow() { + return { + planId: this.currentRow.planId, + componentName: '', + productionLine: this.currentRow.productionLine || '', + maintenanceCategory: 1, + itemPlanDate: parseTime(new Date(), '{y}-{m}-{d}'), + repairContent: '', + lineExecutor: '', + equipmentExecutor: '', + plannedCompleteTime: '', + actualCompleteTime: '', + totalHours: '', + acceptanceUser: '', + detailStatus: 0, + remark: '' + }; + }, + buildDetailPayload(row) { + return { + detailId: row.detailId, + planId: this.currentRow.planId, + componentName: row.componentName, + productionLine: this.currentRow.productionLine || row.productionLine || '', + maintenanceCategory: row.maintenanceCategory === undefined ? 1 : row.maintenanceCategory, + itemPlanDate: row.itemPlanDate, + repairContent: row.repairContent, + lineExecutor: row.lineExecutor, + equipmentExecutor: row.equipmentExecutor, + plannedCompleteTime: row.plannedCompleteTime, + actualCompleteTime: row.actualCompleteTime, + totalHours: row.totalHours, + acceptanceUser: row.acceptanceUser, + detailStatus: row.detailStatus, + remark: row.remark + }; + }, + saveDetailRow(row) { + if (!row) return; + if (!row.repairContent) { + this.$modal.msgWarning("请输入具体工作内容"); + return; + } + var self = this; + var payload = this.buildDetailPayload(row); + var api = row._isNew || !row.detailId ? addMaintenancePlanDetail : updateMaintenancePlanDetail; + api(payload).then(function() { + self.$modal.msgSuccess(row._isNew || !row.detailId ? "添加成功" : "修改成功"); + self.loadDetailList(self.currentRow.planId); + }); } } }; @@ -530,6 +700,11 @@ export default { .search-row { display: flex; align-items: center; gap: 6px; padding: 0 14px 10px; background: #f5f7fa; } .search-row .el-input { flex: 1; } .list-body { flex: 1; overflow-y: auto; padding: 0 6px; } +.list-body { scrollbar-width: thin; scrollbar-color: rgba(144, 147, 153, 0.45) transparent; } +.list-body::-webkit-scrollbar { width: 8px; height: 8px; } +.list-body::-webkit-scrollbar-track { background: transparent; } +.list-body::-webkit-scrollbar-thumb { background: rgba(144, 147, 153, 0.35); border-radius: 6px; } +.list-body::-webkit-scrollbar-thumb:hover { background: rgba(144, 147, 153, 0.55); } .list-item { display: flex; align-items: center; padding: 10px 12px; margin-bottom: 2px; cursor: pointer; border-radius: 6px; transition: all 0.15s; } .list-item:hover { background: #ebeef5; } .list-item.active { background: #d9ecff; } @@ -546,7 +721,7 @@ export default { /* ========== 右侧面板 ========== */ .right-panel { height: 100%; overflow: hidden; display: flex; flex-direction: column; background: #faf8f5; } .empty-tip { display: flex; align-items: center; justify-content: center; height: 100%; color: #909399; font-size: 14px; gap: 8px; } -.right-content { flex: 1; display: flex; flex-direction: column; overflow: hidden; padding: 12px 16px; } +.right-content { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; padding: 12px 16px; } /* 基本信息栏 */ .info-bar { display: flex; align-items: center; justify-content: space-between; padding: 8px 16px; background: #fff; border: 1px solid #e4e7ed; border-radius: 4px; margin-bottom: 10px; flex-shrink: 0; } @@ -563,10 +738,25 @@ export default { .section-count { font-size: 12px; color: #909399; } .section-actions { display: flex; align-items: center; gap: 6px; } .inspection-section .el-table { flex: 1; overflow-y: auto; } +.inspection-section .el-table { scrollbar-width: thin; scrollbar-color: rgba(144, 147, 153, 0.45) transparent; } +.detail-section .el-table { scrollbar-width: thin; scrollbar-color: rgba(144, 147, 153, 0.45) transparent; } +.inspection-section ::v-deep .el-table, +.detail-section ::v-deep .el-table { display: flex; flex-direction: column; height: 100%; } +.inspection-section ::v-deep .el-table__body-wrapper, +.detail-section ::v-deep .el-table__body-wrapper { flex: 1; min-height: 0; } +.inspection-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar, +.detail-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar { width: 8px; height: 8px; } +.inspection-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar-track, +.detail-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar-track { background: transparent; } +.inspection-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar-thumb, +.detail-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar-thumb { background: rgba(144, 147, 153, 0.35); border-radius: 6px; } +.inspection-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar-thumb:hover, +.detail-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar-thumb:hover { background: rgba(144, 147, 153, 0.55); } /* 下半部分:维修明细 */ .detail-section { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; background: #fff; border: 1px solid #e4e7ed; border-radius: 4px; } .detail-section .el-table { flex: 1; overflow-y: auto; } +.cell-pre-wrap { white-space: pre-wrap; word-break: break-all; line-height: 18px; } .empty-data { padding: 24px 0; text-align: center; color: #c0c4cc; font-size: 13px; } diff --git a/script/sql/mysql/update/update_20260707_eqp_maintenance_plan_detail_fields.sql b/script/sql/mysql/update/update_20260707_eqp_maintenance_plan_detail_fields.sql new file mode 100644 index 000000000..aaff01765 --- /dev/null +++ b/script/sql/mysql/update/update_20260707_eqp_maintenance_plan_detail_fields.sql @@ -0,0 +1,8 @@ +ALTER TABLE eqp_maintenance_plan_detail + ADD COLUMN line_executor varchar(64) NULL, + ADD COLUMN equipment_executor varchar(64) NULL, + ADD COLUMN planned_complete_time varchar(64) NULL, + ADD COLUMN actual_complete_time varchar(64) NULL, + ADD COLUMN total_hours varchar(64) NULL, + ADD COLUMN acceptance_user varchar(64) NULL; +