using Model; using Model.Dto.Inspection; using Model.Entity.Inspection; using Model.Mapper; using ORM; using Service.Interface; using SqlSugar; using System; using System.Threading.Tasks; namespace Service.Implement { /// /// 告警中心服务实现(全系统统一告警上报入口) /// 职责:默认内容生成 → 去重合并(防告警风暴)→ 落库 → 规则触发计数 → 通知队列入队 /// public class AlertCenterService : IAlertCenterService { /// /// 合并窗口(分钟):窗口内同设备+同测点+同类型的活跃告警不新建记录,只累加触发次数。 /// 后续可迁移到系统参数配置模块动态调整 /// private const int MergeWindowMinutes = 5; /// /// 上报一条告警 /// public async Task> RaiseAsync(AlertRaiseDto dto) { if (dto == null) { return Result.Error("告警上报参数为空"); } if (string.IsNullOrWhiteSpace(dto.DeviceCode) && string.IsNullOrWhiteSpace(dto.Content)) { return Result.Error("设备编号与告警内容不能同时为空"); } try { var now = DateTime.Now; // ===== 去重合并:窗口内相同 设备+测点+类型 的活跃告警(未确认/已确认)只累加不新建 ===== var active = await SqlSugarContext.DbContext.Queryable() .Where(x => x.IsDel == 0) .Where(x => x.DeviceCode == dto.DeviceCode && x.Metric == dto.Metric && x.AlertType == dto.AlertType) .Where(x => x.AlertStatus == AlertStatusEnum.Unacknowledged || x.AlertStatus == AlertStatusEnum.Acknowledged) .Where(x => x.LastAlertTime >= now.AddMinutes(-MergeWindowMinutes)) .FirstAsync(); if (active != null) { // 累加触发次数、刷新最近告警时间与当前值;级别取更高者(告警升级) var mergedLevel = active.AlertLevel > dto.AlertLevel ? active.AlertLevel : dto.AlertLevel; await SqlSugarContext.DbContext.Updateable() .SetColumns(x => new AlertMessageEntity { TriggerCount = x.TriggerCount + 1, LastAlertTime = now, CurrentValue = dto.CurrentValue ?? x.CurrentValue, AlertLevel = mergedLevel }) .Where(x => x.Id == active.Id) .ExecuteCommandAsync(); // 合并告警也入队(是否真正推送由 Worker 按通知规则静默期决定) AlertNotifyBus.Publish(active.Id, false); return Result.Success(active.Id.ToString()); } // ===== 新告警:生成默认内容 → 落库 → 规则计数 → 入队 ===== var entity = dto.ToEntity(); if (string.IsNullOrWhiteSpace(entity.Content)) { entity.Content = BuildDefaultContent(entity); } entity.CreateTime = now; entity.FirstAlertTime = now; entity.LastAlertTime = now; entity.TriggerCount = 1; entity.AlertStatus = AlertStatusEnum.Unacknowledged; await SqlSugarContext.DbContext.Insertable(entity).ExecuteCommandAsync(); // 来源为规则引擎时,回写规则触发统计(与黄的规则引擎模块联动) if (entity.RuleId > 0) { await SqlSugarContext.DbContext.Updateable() .SetColumns(x => new AlertRuleEntity { TriggerCount = x.TriggerCount + 1, LastAlarmTime = now }) .Where(x => x.Id == entity.RuleId) .ExecuteCommandAsync(); } AlertNotifyBus.Publish(entity.Id, true); return Result.Success(entity.Id.ToString()); } catch (Exception ex) { return Result.Error("告警上报失败", ex); } } /// /// 按内置模板生成默认告警内容(后续可由通知模板模块接管,见 TemplateCode 预留字段) /// private static string BuildDefaultContent(AlertMessageEntity e) { string device = string.IsNullOrWhiteSpace(e.DeviceName) ? e.DeviceCode ?? "未知设备" : $"{e.DeviceName}({e.DeviceCode})"; string metric = string.IsNullOrWhiteSpace(e.Metric) ? "" : $" 测点[{e.Metric}]"; string value = e.CurrentValue.HasValue ? $" 当前值 {e.CurrentValue.Value}" : ""; string threshold = e.ThresholdValue.HasValue ? $",阈值 {e.ThresholdValue.Value}" : ""; return $"{device}{metric} 触发告警:{value}{threshold}"; } } }