diff --git a/aucma-base/src/main/java/com/aucma/base/controller/ProcessAlertController.java b/aucma-base/src/main/java/com/aucma/base/controller/ProcessAlertController.java index 71819e9..3a01c14 100644 --- a/aucma-base/src/main/java/com/aucma/base/controller/ProcessAlertController.java +++ b/aucma-base/src/main/java/com/aucma/base/controller/ProcessAlertController.java @@ -94,4 +94,15 @@ public class ProcessAlertController extends BaseController { int count = processAlertService.checkThresholdAlerts(); return success("检查完成,生成预警 " + count + " 条"); } + + /** + * 批量标记预警为已处理 + */ + @PreAuthorize("@ss.hasPermi('base:processAlert:edit')") + @Log(title = "批量标记预警已处理", businessType = BusinessType.UPDATE) + @PutMapping("/batchMarkProcessed") + public AjaxResult batchMarkProcessed(@RequestBody Long[] alertIds) { + int count = processAlertService.batchMarkAsProcessed(alertIds, getUsername()); + return success("成功标记 " + count + " 条预警为已处理"); + } } diff --git a/aucma-base/src/main/java/com/aucma/base/mapper/ProcessAlertMapper.java b/aucma-base/src/main/java/com/aucma/base/mapper/ProcessAlertMapper.java index aae6f5e..b5cc59d 100644 --- a/aucma-base/src/main/java/com/aucma/base/mapper/ProcessAlertMapper.java +++ b/aucma-base/src/main/java/com/aucma/base/mapper/ProcessAlertMapper.java @@ -58,4 +58,22 @@ public interface ProcessAlertMapper { * @return 结果 */ public int deleteProcessAlertByAlertIds(Long[] alertIds); + + /** + * 查询指定设备和参数的未处理预警 + * + * @param deviceCode 设备编码 + * @param paramCode 参数编码 + * @return 工艺预警 + */ + public ProcessAlert selectUnhandledAlert(String deviceCode, String paramCode); + + /** + * 查询指定设备和参数的最新预警(包含已处理) + * + * @param deviceCode 设备编码 + * @param paramCode 参数编码 + * @return 工艺预警 + */ + public ProcessAlert selectLatestAlert(String deviceCode, String paramCode); } diff --git a/aucma-base/src/main/java/com/aucma/base/service/IProcessAlertService.java b/aucma-base/src/main/java/com/aucma/base/service/IProcessAlertService.java index 7a11133..a6cd53e 100644 --- a/aucma-base/src/main/java/com/aucma/base/service/IProcessAlertService.java +++ b/aucma-base/src/main/java/com/aucma/base/service/IProcessAlertService.java @@ -23,4 +23,12 @@ public interface IProcessAlertService { * @return 生成的预警数量 */ public int checkThresholdAlerts(); + + /** + * 批量标记预警为已处理 + * @param alertIds 预警ID数组 + * @param handleUser 处理人 + * @return 处理的数量 + */ + public int batchMarkAsProcessed(Long[] alertIds, String handleUser); } diff --git a/aucma-base/src/main/java/com/aucma/base/service/impl/ProcessAlertServiceImpl.java b/aucma-base/src/main/java/com/aucma/base/service/impl/ProcessAlertServiceImpl.java index 894b10e..dffdee5 100644 --- a/aucma-base/src/main/java/com/aucma/base/service/impl/ProcessAlertServiceImpl.java +++ b/aucma-base/src/main/java/com/aucma/base/service/impl/ProcessAlertServiceImpl.java @@ -136,26 +136,60 @@ public class ProcessAlertServiceImpl implements IProcessAlertService { } if (alertType != null) { - // 生成预警记录 - ProcessAlert alert = new ProcessAlert(); - alert.setAlertCode("ALERT-" + sdf.format(now) + "-" + (alertCount + 1)); - alert.setAlertType("参数超限"); - alert.setAlertLevel(param.getAlertLevel() != null ? param.getAlertLevel() : "1"); - alert.setDeviceCode(param.getDeviceCode()); - alert.setDeviceName(param.getDeviceName()); - alert.setParamCode(param.getParamCode()); - alert.setParamName(param.getParamName()); - alert.setAlertContent(param.getParamName() + alertType + ",当前值:" + paramValueStr + ",阈值:" + thresholdValue); - alert.setAlertValue(paramValueStr); - alert.setThresholdValue(thresholdValue); - alert.setAlertTime(latestVal.getCollectTime() != null ? latestVal.getCollectTime() : now); - alert.setAlertStatus("0"); - alert.setIsFlag("1"); - alert.setCreateTime(now); + // 检查是否已存在未处理的预警(去重) + ProcessAlert existingAlert = processAlertMapper.selectUnhandledAlert( + param.getDeviceCode(), + param.getParamCode() + ); - insertProcessAlert(alert); - alertCount++; - log.info("生成预警: {}", alert.getAlertContent()); + if (existingAlert != null) { + // 已存在未处理的预警,更新预警值和时间 + existingAlert.setAlertValue(paramValueStr); + existingAlert.setAlertTime(latestVal.getCollectTime() != null ? latestVal.getCollectTime() : now); + existingAlert.setAlertContent(param.getParamName() + alertType + ",当前值:" + paramValueStr + ",阈值:" + thresholdValue); + updateProcessAlert(existingAlert); + log.info("更新未处理预警: {}", existingAlert.getAlertContent()); + } else { + // 查询最新预警(包含已处理) + ProcessAlert latestAlert = processAlertMapper.selectLatestAlert( + param.getDeviceCode(), + param.getParamCode() + ); + + // 如果存在已处理的预警,检查预警冷却时间(5分钟) + if (latestAlert != null && "2".equals(latestAlert.getAlertStatus())) { + long timeDiff = now.getTime() - latestAlert.getAlertTime().getTime(); + long cooldownMinutes = 5; // 预警冷却时间5分钟 + + if (timeDiff < cooldownMinutes * 60 * 1000) { + // 还在冷却期内,不生成新预警 + log.debug("预警冷却期内,跳过: deviceCode={}, paramCode={}", + param.getDeviceCode(), param.getParamCode()); + continue; + } + } + + // 生成新的预警记录 + ProcessAlert alert = new ProcessAlert(); + alert.setAlertCode("ALERT-" + sdf.format(now) + "-" + (alertCount + 1)); + alert.setAlertType("参数超限"); + alert.setAlertLevel(param.getAlertLevel() != null ? param.getAlertLevel() : "1"); + alert.setDeviceCode(param.getDeviceCode()); + alert.setDeviceName(param.getDeviceName()); + alert.setParamCode(param.getParamCode()); + alert.setParamName(param.getParamName()); + alert.setAlertContent(param.getParamName() + alertType + ",当前值:" + paramValueStr + ",阈值:" + thresholdValue); + alert.setAlertValue(paramValueStr); + alert.setThresholdValue(thresholdValue); + alert.setAlertTime(latestVal.getCollectTime() != null ? latestVal.getCollectTime() : now); + alert.setAlertStatus("0"); + alert.setIsFlag("1"); + alert.setCreateTime(now); + + insertProcessAlert(alert); + alertCount++; + log.info("生成新预警: {}", alert.getAlertContent()); + } } } catch (NumberFormatException e) { log.warn("参数值无法转换为数字: paramCode={}, value={}", param.getParamCode(), paramValueStr); @@ -167,4 +201,33 @@ public class ProcessAlertServiceImpl implements IProcessAlertService { return alertCount; } + + @Override + public int batchMarkAsProcessed(Long[] alertIds, String handleUser) { + if (alertIds == null || alertIds.length == 0) { + return 0; + } + + int count = 0; + Date now = DateUtils.getNowDate(); + + for (Long alertId : alertIds) { + try { + ProcessAlert alert = processAlertMapper.selectProcessAlertByAlertId(alertId); + if (alert != null && !"2".equals(alert.getAlertStatus())) { + alert.setAlertStatus("2"); // 已处理 + alert.setHandleUser(handleUser); + alert.setHandleTime(now); + alert.setHandleResult("批量标记为已处理"); + processAlertMapper.updateProcessAlert(alert); + count++; + log.info("批量标记预警已处理: alertId={}, alertCode={}", alertId, alert.getAlertCode()); + } + } catch (Exception e) { + log.error("标记预警已处理失败: alertId={}", alertId, e); + } + } + + return count; + } } diff --git a/aucma-base/src/main/resources/mapper/base/ProcessAlertMapper.xml b/aucma-base/src/main/resources/mapper/base/ProcessAlertMapper.xml index 6a4d082..f3e2d1d 100644 --- a/aucma-base/src/main/resources/mapper/base/ProcessAlertMapper.xml +++ b/aucma-base/src/main/resources/mapper/base/ProcessAlertMapper.xml @@ -149,4 +149,25 @@ #{alertId} + + + + + + diff --git a/aucma-production/src/main/java/com/aucma/production/service/IAndonDashboardService.java b/aucma-production/src/main/java/com/aucma/production/service/IAndonDashboardService.java new file mode 100644 index 0000000..39ea5d2 --- /dev/null +++ b/aucma-production/src/main/java/com/aucma/production/service/IAndonDashboardService.java @@ -0,0 +1,68 @@ +package com.aucma.production.service; + +import com.aucma.production.domain.dto.AndonDashboardDTO; + +/** + * 安灯生产监控看板Service接口 + * + * @author Yinq + * @date 2025-12-30 + */ +public interface IAndonDashboardService { + + /** + * 获取完整的看板数据 + * + * @param productLineCode 产线编码(可选,为空则查询全部) + * @return 看板数据 + */ + AndonDashboardDTO getDashboardData(String productLineCode); + + /** + * 获取设备状态统计 + * + * @param productLineCode 产线编码(可选) + * @return 设备状态统计 + */ + AndonDashboardDTO.DeviceStatusSummary getDeviceStatusSummary(String productLineCode); + + /** + * 获取任务完成情况 + * + * @param productLineCode 产线编码(可选) + * @return 任务完成情况 + */ + AndonDashboardDTO.TaskCompletionSummary getTaskCompletionSummary(String productLineCode); + + /** + * 获取OEE数据 + * + * @param productLineCode 产线编码(可选) + * @return OEE数据 + */ + AndonDashboardDTO.OeeSummary getOeeSummary(String productLineCode); + + /** + * 获取利用率统计 + * + * @param productLineCode 产线编码(可选) + * @return 利用率统计 + */ + AndonDashboardDTO.UtilizationSummary getUtilizationSummary(String productLineCode); + + /** + * 获取品质数据 + * + * @param productLineCode 产线编码(可选) + * @return 品质数据 + */ + AndonDashboardDTO.QualitySummary getQualitySummary(String productLineCode); + + /** + * 获取安灯事件统计 + * + * @param productLineCode 产线编码(可选) + * @return 安灯事件统计 + */ + AndonDashboardDTO.AndonEventSummary getAndonEventSummary(String productLineCode); +} diff --git a/aucma-production/src/main/java/com/aucma/production/service/impl/AndonEventAssignmentServiceImpl.java b/aucma-production/src/main/java/com/aucma/production/service/impl/AndonEventAssignmentServiceImpl.java index f516a34..e02122f 100644 --- a/aucma-production/src/main/java/com/aucma/production/service/impl/AndonEventAssignmentServiceImpl.java +++ b/aucma-production/src/main/java/com/aucma/production/service/impl/AndonEventAssignmentServiceImpl.java @@ -88,7 +88,11 @@ public class AndonEventAssignmentServiceImpl implements IAndonEventAssignmentSer // 根据状态补充派工自身的里程碑时间 if (andonEventAssignment.getStatus() != null) { String status = andonEventAssignment.getStatus(); - // 当状态变为DONE时,设置finishTime为当前时间(安灯事件结束) + // 当状态变为已接单时,自动设置接单时间 + if (AnDonConstants.AssignmentStatus.ACCEPTED.equals(status) && andonEventAssignment.getAcceptTime() == null) { + andonEventAssignment.setAcceptTime(DateUtils.getNowDate()); + } + // 当状态变为已完成时,自动设置完成时间 if (AnDonConstants.AssignmentStatus.DONE.equals(status) && andonEventAssignment.getFinishTime() == null) { andonEventAssignment.setFinishTime(DateUtils.getNowDate()); }