From 86fa02175b71ab774df3b64633ba4b8a56fa232d Mon Sep 17 00:00:00 2001 From: "zangch@mesnac.com" Date: Tue, 18 Nov 2025 08:51:08 +0800 Subject: [PATCH] =?UTF-8?q?feat(report):=20=E6=96=B0=E5=A2=9EDMS=E8=AE=BE?= =?UTF-8?q?=E5=A4=87=E7=9B=B8=E5=85=B3=E5=88=86=E6=9E=90=E6=8A=A5=E8=A1=A8?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增设备故障分析报表实体类DeviceFaultAnalysisReport,包含设备编码、名称、故障类型等属性 - 新增设备OEE分析报表实体类DeviceOeeReport,支持计算计划运行时间、停机时间、可用率等指标 - 新增维修工时统计报表实体类RepairHoursReport,统计执行人工单数量及工时 - 实现DmsReportMapper接口,定义设备故障分析、维修工时统计及设备OEE分析的数据库查询方法 - 编写对应的MyBatis映射文件DmsReportMapper.xml,支持动态查询参数和数据聚合 - 实现IDmsReportService接口及其实现类DmsReportServiceImpl,封装业务逻辑及OEE指标计算 - 新增DmsReportController,提供设备故障分析、维修工时统计、设备OEE分析的REST接口及Excel导出功能 - 支持传入时间等参数过滤报表数据,保证数据准确性和灵活性 --- .../controller/DmsReportController.java | 102 ++++++++++++++ .../domain/DeviceFaultAnalysisReport.java | 79 +++++++++++ .../aucma/report/domain/DeviceOeeReport.java | 118 +++++++++++++++++ .../report/domain/RepairHoursReport.java | 79 +++++++++++ .../aucma/report/mapper/DmsReportMapper.java | 29 ++++ .../report/service/IDmsReportService.java | 29 ++++ .../service/impl/DmsReportServiceImpl.java | 125 ++++++++++++++++++ .../mapper/report/DmsReportMapper.xml | 106 +++++++++++++++ 8 files changed, 667 insertions(+) create mode 100644 aucma-report/src/main/java/com/aucma/report/controller/DmsReportController.java create mode 100644 aucma-report/src/main/java/com/aucma/report/domain/DeviceFaultAnalysisReport.java create mode 100644 aucma-report/src/main/java/com/aucma/report/domain/DeviceOeeReport.java create mode 100644 aucma-report/src/main/java/com/aucma/report/domain/RepairHoursReport.java create mode 100644 aucma-report/src/main/java/com/aucma/report/mapper/DmsReportMapper.java create mode 100644 aucma-report/src/main/java/com/aucma/report/service/IDmsReportService.java create mode 100644 aucma-report/src/main/java/com/aucma/report/service/impl/DmsReportServiceImpl.java create mode 100644 aucma-report/src/main/resources/mapper/report/DmsReportMapper.xml diff --git a/aucma-report/src/main/java/com/aucma/report/controller/DmsReportController.java b/aucma-report/src/main/java/com/aucma/report/controller/DmsReportController.java new file mode 100644 index 0000000..a5c6b97 --- /dev/null +++ b/aucma-report/src/main/java/com/aucma/report/controller/DmsReportController.java @@ -0,0 +1,102 @@ +package com.aucma.report.controller; + +import com.aucma.common.core.controller.BaseController; +import com.aucma.common.core.domain.AjaxResult; +import com.aucma.common.utils.poi.ExcelUtil; +import com.aucma.report.domain.DeviceFaultAnalysisReport; +import com.aucma.report.domain.DeviceOeeReport; +import com.aucma.report.domain.RepairHoursReport; +import com.aucma.report.service.IDmsReportService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletResponse; +import java.util.List; +import java.util.Map; + +/** + * DMS 设备报表 Controller + */ +@RestController +@RequestMapping("/report/dmsReport") +public class DmsReportController extends BaseController { + + @Autowired + private IDmsReportService dmsReportService; + + /** + * 设备故障分析 + */ + @GetMapping("/deviceFaultAnalysis") + public AjaxResult deviceFaultAnalysis(@RequestParam(required = false) Map params) { + List list = dmsReportService.deviceFaultAnalysisList(params); + return success(list); + } + + /** + * 设备故障分析导出 + */ + @PostMapping("/deviceFaultAnalysis/export") + public void deviceFaultAnalysisExport(HttpServletResponse response, + @RequestParam(required = false) Map params) { + if (params != null) { + params.put("pageNum", null); + params.put("pageSize", null); + } + List list = dmsReportService.deviceFaultAnalysisList(params); + ExcelUtil util = new ExcelUtil<>(DeviceFaultAnalysisReport.class); + util.exportExcel(response, list, "设备故障分析"); + } + + /** + * 维修工时统计 + */ + @GetMapping("/repairHoursStat") + public AjaxResult repairHoursStat(@RequestParam(required = false) Map params) { + List list = dmsReportService.repairHoursReportList(params); + return success(list); + } + + /** + * 维修工时统计导出 + */ + @PostMapping("/repairHoursStat/export") + public void repairHoursStatExport(HttpServletResponse response, + @RequestParam(required = false) Map params) { + if (params != null) { + params.put("pageNum", null); + params.put("pageSize", null); + } + List list = dmsReportService.repairHoursReportList(params); + ExcelUtil util = new ExcelUtil<>(RepairHoursReport.class); + util.exportExcel(response, list, "维修工时统计"); + } + + /** + * 设备 OEE 分析 + */ + @GetMapping("/deviceOeeAnalysis") + public AjaxResult deviceOeeAnalysis(@RequestParam(required = false) Map params) { + List list = dmsReportService.deviceOeeReportList(params); + return success(list); + } + + /** + * 设备 OEE 分析导出 + */ + @PostMapping("/deviceOeeAnalysis/export") + public void deviceOeeAnalysisExport(HttpServletResponse response, + @RequestParam(required = false) Map params) { + if (params != null) { + params.put("pageNum", null); + params.put("pageSize", null); + } + List list = dmsReportService.deviceOeeReportList(params); + ExcelUtil util = new ExcelUtil<>(DeviceOeeReport.class); + util.exportExcel(response, list, "设备OEE分析"); + } +} diff --git a/aucma-report/src/main/java/com/aucma/report/domain/DeviceFaultAnalysisReport.java b/aucma-report/src/main/java/com/aucma/report/domain/DeviceFaultAnalysisReport.java new file mode 100644 index 0000000..e952372 --- /dev/null +++ b/aucma-report/src/main/java/com/aucma/report/domain/DeviceFaultAnalysisReport.java @@ -0,0 +1,79 @@ +package com.aucma.report.domain; + +import com.aucma.common.annotation.Excel; +import com.aucma.common.core.domain.BaseEntity; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * 设备故障分析报表 + * + * 数据来源:dms_bills_fault_instance + base_deviceledger + */ +public class DeviceFaultAnalysisReport extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** 设备编码 */ + @Excel(name = "设备编码") + @JsonProperty("DEVICE_CODE") + private String DEVICE_CODE; + + /** 设备名称 */ + @Excel(name = "设备名称") + @JsonProperty("DEVICE_NAME") + private String DEVICE_NAME; + + /** 故障类型 */ + @Excel(name = "故障类型") + @JsonProperty("FAULT_TYPE") + private String FAULT_TYPE; + + /** 故障次数 */ + @Excel(name = "故障次数") + @JsonProperty("FAULT_COUNT") + private Long FAULT_COUNT; + + /** 故障时长(分钟) */ + @Excel(name = "故障时长(分钟)") + @JsonProperty("FAULT_DURATION_MINUTES") + private Long FAULT_DURATION_MINUTES; + + public String getDEVICE_CODE() { + return DEVICE_CODE; + } + + public void setDEVICE_CODE(String DEVICE_CODE) { + this.DEVICE_CODE = DEVICE_CODE; + } + + public String getDEVICE_NAME() { + return DEVICE_NAME; + } + + public void setDEVICE_NAME(String DEVICE_NAME) { + this.DEVICE_NAME = DEVICE_NAME; + } + + public String getFAULT_TYPE() { + return FAULT_TYPE; + } + + public void setFAULT_TYPE(String FAULT_TYPE) { + this.FAULT_TYPE = FAULT_TYPE; + } + + public Long getFAULT_COUNT() { + return FAULT_COUNT; + } + + public void setFAULT_COUNT(Long FAULT_COUNT) { + this.FAULT_COUNT = FAULT_COUNT; + } + + public Long getFAULT_DURATION_MINUTES() { + return FAULT_DURATION_MINUTES; + } + + public void setFAULT_DURATION_MINUTES(Long FAULT_DURATION_MINUTES) { + this.FAULT_DURATION_MINUTES = FAULT_DURATION_MINUTES; + } +} diff --git a/aucma-report/src/main/java/com/aucma/report/domain/DeviceOeeReport.java b/aucma-report/src/main/java/com/aucma/report/domain/DeviceOeeReport.java new file mode 100644 index 0000000..923cc39 --- /dev/null +++ b/aucma-report/src/main/java/com/aucma/report/domain/DeviceOeeReport.java @@ -0,0 +1,118 @@ +package com.aucma.report.domain; + +import com.aucma.common.annotation.Excel; +import com.aucma.common.core.domain.BaseEntity; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * 设备 OEE 分析报表 + * + * 注意:当前实现为基于 DMS 数据的近似计算,可用率等口径后续可根据现场要求调整。 + */ +public class DeviceOeeReport extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** 设备编码 */ + @Excel(name = "设备编码") + @JsonProperty("DEVICE_CODE") + private String DEVICE_CODE; + + /** 设备名称 */ + @Excel(name = "设备名称") + @JsonProperty("DEVICE_NAME") + private String DEVICE_NAME; + + /** 可用率 */ + @Excel(name = "可用率") + @JsonProperty("AVAILABILITY") + private Double AVAILABILITY; + + /** 性能稼动率 */ + @Excel(name = "性能稼动率") + @JsonProperty("PERFORMANCE") + private Double PERFORMANCE; + + /** 良品率 */ + @Excel(name = "良品率") + @JsonProperty("QUALITY") + private Double QUALITY; + + /** OEE */ + @Excel(name = "OEE") + @JsonProperty("OEE") + private Double OEE; + + /** 计划运行时间(分钟) */ + @Excel(name = "计划运行时间(分钟)") + @JsonProperty("PLANNED_TIME_MINUTES") + private Long PLANNED_TIME_MINUTES; + + /** 停机时间(分钟) */ + @Excel(name = "停机时间(分钟)") + @JsonProperty("DOWNTIME_MINUTES") + private Long DOWNTIME_MINUTES; + + public String getDEVICE_CODE() { + return DEVICE_CODE; + } + + public void setDEVICE_CODE(String DEVICE_CODE) { + this.DEVICE_CODE = DEVICE_CODE; + } + + public String getDEVICE_NAME() { + return DEVICE_NAME; + } + + public void setDEVICE_NAME(String DEVICE_NAME) { + this.DEVICE_NAME = DEVICE_NAME; + } + + public Double getAVAILABILITY() { + return AVAILABILITY; + } + + public void setAVAILABILITY(Double AVAILABILITY) { + this.AVAILABILITY = AVAILABILITY; + } + + public Double getPERFORMANCE() { + return PERFORMANCE; + } + + public void setPERFORMANCE(Double PERFORMANCE) { + this.PERFORMANCE = PERFORMANCE; + } + + public Double getQUALITY() { + return QUALITY; + } + + public void setQUALITY(Double QUALITY) { + this.QUALITY = QUALITY; + } + + public Double getOEE() { + return OEE; + } + + public void setOEE(Double OEE) { + this.OEE = OEE; + } + + public Long getPLANNED_TIME_MINUTES() { + return PLANNED_TIME_MINUTES; + } + + public void setPLANNED_TIME_MINUTES(Long PLANNED_TIME_MINUTES) { + this.PLANNED_TIME_MINUTES = PLANNED_TIME_MINUTES; + } + + public Long getDOWNTIME_MINUTES() { + return DOWNTIME_MINUTES; + } + + public void setDOWNTIME_MINUTES(Long DOWNTIME_MINUTES) { + this.DOWNTIME_MINUTES = DOWNTIME_MINUTES; + } +} diff --git a/aucma-report/src/main/java/com/aucma/report/domain/RepairHoursReport.java b/aucma-report/src/main/java/com/aucma/report/domain/RepairHoursReport.java new file mode 100644 index 0000000..e2c44ba --- /dev/null +++ b/aucma-report/src/main/java/com/aucma/report/domain/RepairHoursReport.java @@ -0,0 +1,79 @@ +package com.aucma.report.domain; + +import com.aucma.common.annotation.Excel; +import com.aucma.common.core.domain.BaseEntity; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * 维修工时统计报表 + * + * 数据来源:dms_repair_work_order + */ +public class RepairHoursReport extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** 执行人ID */ + @Excel(name = "执行人ID") + @JsonProperty("EXECUTOR_ID") + private Long EXECUTOR_ID; + + /** 执行人姓名 */ + @Excel(name = "执行人") + @JsonProperty("EXECUTOR_NAME") + private String EXECUTOR_NAME; + + /** 工单数量 */ + @Excel(name = "工单数量") + @JsonProperty("ORDER_COUNT") + private Long ORDER_COUNT; + + /** 合计工时(小时) */ + @Excel(name = "合计工时(h)") + @JsonProperty("TOTAL_HOURS") + private Double TOTAL_HOURS; + + /** 平均工时(小时) */ + @Excel(name = "平均工时(h)") + @JsonProperty("AVG_HOURS") + private Double AVG_HOURS; + + public Long getEXECUTOR_ID() { + return EXECUTOR_ID; + } + + public void setEXECUTOR_ID(Long EXECUTOR_ID) { + this.EXECUTOR_ID = EXECUTOR_ID; + } + + public String getEXECUTOR_NAME() { + return EXECUTOR_NAME; + } + + public void setEXECUTOR_NAME(String EXECUTOR_NAME) { + this.EXECUTOR_NAME = EXECUTOR_NAME; + } + + public Long getORDER_COUNT() { + return ORDER_COUNT; + } + + public void setORDER_COUNT(Long ORDER_COUNT) { + this.ORDER_COUNT = ORDER_COUNT; + } + + public Double getTOTAL_HOURS() { + return TOTAL_HOURS; + } + + public void setTOTAL_HOURS(Double TOTAL_HOURS) { + this.TOTAL_HOURS = TOTAL_HOURS; + } + + public Double getAVG_HOURS() { + return AVG_HOURS; + } + + public void setAVG_HOURS(Double AVG_HOURS) { + this.AVG_HOURS = AVG_HOURS; + } +} diff --git a/aucma-report/src/main/java/com/aucma/report/mapper/DmsReportMapper.java b/aucma-report/src/main/java/com/aucma/report/mapper/DmsReportMapper.java new file mode 100644 index 0000000..9096f0d --- /dev/null +++ b/aucma-report/src/main/java/com/aucma/report/mapper/DmsReportMapper.java @@ -0,0 +1,29 @@ +package com.aucma.report.mapper; + +import com.aucma.report.domain.DeviceFaultAnalysisReport; +import com.aucma.report.domain.RepairHoursReport; +import com.aucma.report.domain.DeviceOeeReport; + +import java.util.List; +import java.util.Map; + +/** + * DMS 相关设备报表 Mapper + */ +public interface DmsReportMapper { + + /** + * 设备故障分析 + */ + List deviceFaultAnalysisList(Map hashMap); + + /** + * 维修工时统计 + */ + List repairHoursReportList(Map hashMap); + + /** + * 设备 OEE 分析(仅返回停机时长等基础数据,OEE 在 Service 中计算) + */ + List deviceOeeReportList(Map hashMap); +} diff --git a/aucma-report/src/main/java/com/aucma/report/service/IDmsReportService.java b/aucma-report/src/main/java/com/aucma/report/service/IDmsReportService.java new file mode 100644 index 0000000..9e3a9f4 --- /dev/null +++ b/aucma-report/src/main/java/com/aucma/report/service/IDmsReportService.java @@ -0,0 +1,29 @@ +package com.aucma.report.service; + +import com.aucma.report.domain.DeviceFaultAnalysisReport; +import com.aucma.report.domain.RepairHoursReport; +import com.aucma.report.domain.DeviceOeeReport; + +import java.util.List; +import java.util.Map; + +/** + * DMS 设备报表 Service 接口 + */ +public interface IDmsReportService { + + /** + * 设备故障分析 + */ + List deviceFaultAnalysisList(Map params); + + /** + * 维修工时统计 + */ + List repairHoursReportList(Map params); + + /** + * 设备 OEE 分析 + */ + List deviceOeeReportList(Map params); +} diff --git a/aucma-report/src/main/java/com/aucma/report/service/impl/DmsReportServiceImpl.java b/aucma-report/src/main/java/com/aucma/report/service/impl/DmsReportServiceImpl.java new file mode 100644 index 0000000..ba443f5 --- /dev/null +++ b/aucma-report/src/main/java/com/aucma/report/service/impl/DmsReportServiceImpl.java @@ -0,0 +1,125 @@ +package com.aucma.report.service.impl; + +import com.aucma.report.domain.DeviceFaultAnalysisReport; +import com.aucma.report.domain.DeviceOeeReport; +import com.aucma.report.domain.RepairHoursReport; +import com.aucma.report.mapper.DmsReportMapper; +import com.aucma.report.service.IDmsReportService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * DMS 设备报表 Service 实现 + */ +@Service +public class DmsReportServiceImpl implements IDmsReportService { + + @Autowired + private DmsReportMapper dmsReportMapper; + + @Override + public List deviceFaultAnalysisList(Map params) { + return dmsReportMapper.deviceFaultAnalysisList(params); + } + + @Override + public List repairHoursReportList(Map params) { + return dmsReportMapper.repairHoursReportList(params); + } + + @Override + public List deviceOeeReportList(Map params) { + List list = dmsReportMapper.deviceOeeReportList(params); + long plannedMinutes = calculatePlannedMinutes(params); + if (plannedMinutes <= 0) { + // 默认按一天 24 小时计算 + plannedMinutes = 24L * 60L; + } + for (DeviceOeeReport item : list) { + if (item == null) { + continue; + } + item.setPLANNED_TIME_MINUTES(plannedMinutes); + Long downtime = item.getDOWNTIME_MINUTES(); + if (downtime == null) { + downtime = 0L; + } + double availability; + if (plannedMinutes <= 0) { + availability = 1.0D; + } else { + availability = (double) (plannedMinutes - downtime) / (double) plannedMinutes; + if (availability < 0) { + availability = 0; + } + if (availability > 1) { + availability = 1; + } + } + // 当前版本暂不从生产/质量模块获取性能与良品率,先按 1 处理,可后续扩展 + double performance = 1.0D; + double quality = 1.0D; + + item.setAVAILABILITY(round(availability, 4)); + item.setPERFORMANCE(round(performance, 4)); + item.setQUALITY(round(quality, 4)); + item.setOEE(round(availability * performance * quality, 4)); + } + return list; + } + + /** + * 根据前端传入的 beginTime/endTime 计算计划时间(分钟) + */ + private long calculatePlannedMinutes(Map params) { + if (params == null) { + return 0L; + } + Object beginObj = params.get("beginTime"); + Object endObj = params.get("endTime"); + if (beginObj == null || endObj == null) { + return 0L; + } + String beginStr = String.valueOf(beginObj); + String endStr = String.valueOf(endObj); + if (beginStr.isEmpty() || endStr.isEmpty()) { + return 0L; + } + // 统一补上时间,按自然日计算 + if (beginStr.length() == 10) { + beginStr = beginStr + " 00:00:00"; + } + if (endStr.length() == 10) { + endStr = endStr + " 23:59:59"; + } + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + try { + Date begin = sdf.parse(beginStr); + Date end = sdf.parse(endStr); + if (begin == null || end == null) { + return 0L; + } + long diffMillis = end.getTime() - begin.getTime(); + if (diffMillis <= 0) { + return 0L; + } + return diffMillis / (1000L * 60L); + } catch (ParseException e) { + return 0L; + } + } + + private double round(double value, int scale) { + if (scale < 0) { + return value; + } + double factor = Math.pow(10, scale); + return Math.round(value * factor) / factor; + } +} diff --git a/aucma-report/src/main/resources/mapper/report/DmsReportMapper.xml b/aucma-report/src/main/resources/mapper/report/DmsReportMapper.xml new file mode 100644 index 0000000..7ed5596 --- /dev/null +++ b/aucma-report/src/main/resources/mapper/report/DmsReportMapper.xml @@ -0,0 +1,106 @@ + + + + + + + + + + + + + +