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());
}