This commit is contained in:
“hsc”
2026-09-04 17:38:57 +08:00
67 changed files with 5971 additions and 30 deletions
@@ -0,0 +1,21 @@
using Model;
using Model.Dto.Inspection;
using System.Threading.Tasks;
namespace Service.Interface
{
/// <summary>
/// 告警中心服务接口(全系统统一告警上报入口)
/// 其它模块(规则引擎/自动巡检/看板/数采等)只需注入本接口调用 RaiseAsync 即可产生告警,
/// 去重合并、落库、通知分发、规则计数均由告警中心内部完成,调用方无需关心
/// </summary>
public interface IAlertCenterService
{
/// <summary>
/// 上报一条告警
/// </summary>
/// <param name="dto">告警上报参数(除设备标识外均可空)</param>
/// <returns>返回告警消息 Idstring,雪花 Id);合并到已有告警时返回已有告警的 Id</returns>
Task<Result<string>> RaiseAsync(AlertRaiseDto dto);
}
}
@@ -1,10 +1,79 @@
using Model;
using Model.Dto.Inspection;
using Model.Entity.Inspection;
using Model.Mapper;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Service.Interface
{
/// <summary>
/// 消息告警 服务接口
/// 消息告警 服务接口(告警列表/闭环操作/统计分析)
/// </summary>
public interface IAlertMessageService
{
// TODO: 定义 消息告警 相关方法
/// <summary>
/// 分页查询告警(支持级别/状态/类型/来源/设备/关键字/时间范围筛选)
/// </summary>
Task<Result<List<AlertMessageDto>>> GetPagedAsync(int pageIndex, int pageSize, RefAsync<int> total,
AlertLevelEnum? level, AlertStatusEnum? status, AlertTypeEnum? type, AlertSourceEnum? source,
string? deviceCode, string? keyword, DateTime? startDate, DateTime? endDate);
/// <summary>
/// 告警详情
/// </summary>
Task<Result<AlertMessageDto>> GetByIdAsync(long id);
/// <summary>
/// 确认告警
/// </summary>
Task<Result<bool>> AcknowledgeAsync(long id, AlertOperateDto dto);
/// <summary>
/// 处理告警
/// </summary>
Task<Result<bool>> HandleAsync(long id, AlertOperateDto dto);
/// <summary>
/// 关闭告警
/// </summary>
Task<Result<bool>> CloseAsync(long id, AlertOperateDto dto);
/// <summary>
/// 忽略告警
/// </summary>
Task<Result<bool>> IgnoreAsync(long id, AlertOperateDto dto);
/// <summary>
/// 转工单(一期仅变更状态并记录 WorkOrderId,工单模块二期对接)
/// </summary>
Task<Result<bool>> ToWorkOrderAsync(long id, AlertOperateDto dto);
/// <summary>
/// 告警概览(列表页顶部卡片)
/// </summary>
Task<Result<AlertOverviewDto>> GetOverviewAsync();
/// <summary>
/// 趋势统计(granularityday/week/month
/// </summary>
Task<Result<List<AlertTrendItemDto>>> GetTrendAsync(string granularity, DateTime? startDate, DateTime? endDate);
/// <summary>
/// 分布统计(dimensiondevice/type/level/source
/// </summary>
Task<Result<List<AlertDistributionItemDto>>> GetDistributionAsync(string dimension, DateTime? startDate, DateTime? endDate);
/// <summary>
/// 高频告警 TOP 排名
/// </summary>
Task<Result<List<AlertTopItemDto>>> GetTopAsync(int topN, DateTime? startDate, DateTime? endDate);
/// <summary>
/// 处理及时率统计
/// </summary>
Task<Result<AlertTimelinessDto>> GetTimelinessAsync(DateTime? startDate, DateTime? endDate);
}
}
@@ -0,0 +1,67 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Service.Interface
{
/// <summary>
/// 通知消息(Notifier 统一入参:与具体渠道报文格式解耦)
/// </summary>
public class AlertNotifyMessage
{
/// <summary>
/// 消息标题
/// </summary>
public string Title { get; set; } = "设备告警";
/// <summary>
/// 消息正文(markdown 语法,各 Notifier 按需降级为纯文本)
/// </summary>
public string Content { get; set; } = string.Empty;
/// <summary>
/// @ 手机号列表(钉钉/企微支持;飞书文本追加展示)
/// </summary>
public List<string> AtMobiles { get; set; } = new();
}
/// <summary>
/// 通知发送结果
/// </summary>
public class NotifyResult
{
/// <summary>
/// 是否成功
/// </summary>
public bool Success { get; set; }
/// <summary>
/// 错误信息(失败时填写,含渠道响应原文摘要)
/// </summary>
public string? ErrorMsg { get; set; }
public static NotifyResult Ok() => new() { Success = true };
public static NotifyResult Fail(string msg) => new() { Success = false, ErrorMsg = msg };
}
/// <summary>
/// 告警通知渠道发送器抽象(一期:飞书/钉钉/企微 Webhook 机器人)
/// 扩展新渠道(如短信网关)只需实现本接口并在 DependencyInjection.AddAlertNotification 注册,调用方零改动
/// </summary>
public interface IAlertNotifier
{
/// <summary>
/// 本发送器支持的渠道类型
/// </summary>
Model.Entity.Inspection.NotifyChannelTypeEnum ChannelType { get; }
/// <summary>
/// 发送消息
/// </summary>
/// <param name="message">统一通知消息</param>
/// <param name="webhookUrl">渠道 Webhook 地址</param>
/// <param name="secret">加签密钥(可空:未开启加签)</param>
/// <param name="ct">取消令牌</param>
Task<NotifyResult> SendAsync(AlertNotifyMessage message, string webhookUrl, string? secret, CancellationToken ct = default);
}
}
@@ -0,0 +1,95 @@
using Model;
using Model.Dto.Inspection;
using Model.Entity.Inspection;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Service.Interface
{
/// <summary>
/// 告警通知配置服务接口(渠道/通知规则/推送日志/值班排班/跨网发件箱)
/// </summary>
public interface IAlertNotifyService
{
#region
/// <summary>渠道列表</summary>
Task<Result<List<AlertNotifyChannelDto>>> GetChannelsAsync();
/// <summary>新增渠道</summary>
Task<Result<bool>> AddChannelAsync(AlertNotifyChannelDto dto);
/// <summary>修改渠道(Secret 传空表示保持原值不覆盖)</summary>
Task<Result<bool>> UpdateChannelAsync(AlertNotifyChannelDto dto);
/// <summary>删除渠道(软删除)</summary>
Task<Result<bool>> DeleteChannelAsync(long id);
/// <summary>渠道测试推送(发送一条测试消息验证 Webhook 配置,结果写入推送日志)</summary>
Task<Result<bool>> TestSendAsync(long channelId);
#endregion
#region
/// <summary>规则列表</summary>
Task<Result<List<AlertNotifyRuleDto>>> GetRulesAsync();
/// <summary>新增规则</summary>
Task<Result<bool>> AddRuleAsync(AlertNotifyRuleDto dto);
/// <summary>修改规则</summary>
Task<Result<bool>> UpdateRuleAsync(AlertNotifyRuleDto dto);
/// <summary>删除规则(软删除)</summary>
Task<Result<bool>> DeleteRuleAsync(long id);
/// <summary>启用/停用规则</summary>
Task<Result<bool>> SetRuleEnabledAsync(long id, bool enabled);
#endregion
#region
/// <summary>推送日志分页(可按成功状态/渠道筛选)</summary>
Task<Result<List<AlertNotifyLogDto>>> GetLogsPagedAsync(int pageIndex, int pageSize, RefAsync<int> total,
bool? success, long channelId = 0);
#endregion
#region
/// <summary>值班排班列表(按日期范围)</summary>
Task<Result<List<DutyRosterDto>>> GetDutiesAsync(DateTime? startDate, DateTime? endDate);
/// <summary>新增排班</summary>
Task<Result<bool>> AddDutyAsync(DutyRosterDto dto);
/// <summary>修改排班</summary>
Task<Result<bool>> UpdateDutyAsync(DutyRosterDto dto);
/// <summary>删除排班(软删除)</summary>
Task<Result<bool>> DeleteDutyAsync(long id);
/// <summary>查询指定日期的值班人(通知规则关联值班人时使用)</summary>
Task<DutyRosterEntity?> GetDutyByDateAsync(DateTime date);
#endregion
#region AlertBridge
/// <summary>
/// 写入推送日志(供 AlertNotifyWorker 直连推送后复用)
/// </summary>
Task WriteLogAsync(long alertId, long channelId, string content, bool success, string? errorMsg, int retryCount);
/// <summary>
/// 写入跨网发件箱(供 AlertNotifyWorker 的 Outbox 模式复用)
/// </summary>
Task EnqueueOutboxAsync(long alertId, long channelId, AlertNotifyMessage message, List<string> atMobiles);
/// <summary>
/// 拉取待推送发件箱(原子标记为已拉取,防止多实例重复推送)
/// </summary>
Task<Result<List<AlertOutboxItemDto>>> PullOutboxAsync(int batch);
/// <summary>
/// 回写发件箱推送结果(成功/失败,失败累加重试次数并写推送日志)
/// </summary>
Task<Result<bool>> ReportOutboxResultAsync(long id, OutboxResultDto dto);
#endregion
}
}
@@ -1,6 +1,5 @@
using Model;
using Model.Dto.Inspection;
using Model.Entity.Inspection;
using System.Collections.Generic;
using System.Threading.Tasks;
@@ -12,10 +11,15 @@ namespace Service.Interface
public interface IAlertRuleService
{
/// <summary>
/// 获取全告警规则列表
/// 获取全告警规则列表OwnerType=0,不含产品/设备归属规则)
/// </summary>
Task<Result<List<AlertRuleDto>>> GetListAsync();
/// <summary>
/// 获取某归属对象下的规则列表(OwnerType=产品/设备,可选按点过滤)
/// </summary>
Task<Result<List<AlertRuleDto>>> GetOwnerRulesAsync(int ownerType, long ownerId, string? pointCode);
/// <summary>
/// 新增告警规则(前端传 DTOId 为 string
/// </summary>
@@ -0,0 +1,17 @@
using System.Threading.Tasks;
namespace Service.Interface
{
/// <summary>
/// 飞书通讯录服务:手机号 → open_id
/// 飞书 at 标签只认 open_id,不认手机号;群机器人 webhook 自身无查询能力,需自建应用凭证(FeishuConfig)。
/// </summary>
public interface IFeishuContactService
{
/// <summary>
/// 用手机号换取飞书 open_id;未配置应用凭证、查无此人或无权限时返回 null
/// </summary>
/// <param name="mobile">手机号(中国大陆 11 位)</param>
Task<string?> GetOpenIdByMobileAsync(string mobile);
}
}