refactor:重构预警通知,用户中心只使用站内信功能,接入飞书第三方库,直接调用飞书调用发送接口
This commit is contained in:
parent
ab348a0707
commit
0a4103abf5
@ -1,63 +0,0 @@
|
||||
namespace SJZY.Track.Application.Hangfire;
|
||||
|
||||
// 发送消息接口参数
|
||||
// https://centerapi.test.shijizhongyun.com/userApi/index.html?urls.primaryName=%E6%B6%88%E6%81%AF%E8%AE%A2%E9%98%85%E5%AE%9E%E4%BE%8B
|
||||
/// MsgSubscribeInstance/SendMessageByTemplate
|
||||
public class NotifyConfig
|
||||
{
|
||||
private const string ContentKey = "content"; //内容参数
|
||||
|
||||
public bool IsNeedToHandle { get; set; } = true; //是否需要处理(默认为未处理,传false为无需处理,针对站内信是否处理功能)
|
||||
public int MsgSource { get; set; } = 1; // 消息来源:1.消息 2.任务 3.流程 4.消息提醒
|
||||
public int SystemId { get; set; } = 9498; //子系统id 业务中台
|
||||
public string TemplateCode { get; set; } = "TrackWarningNotify"; //模板code
|
||||
public List<int> Channels { get; set; } //1:站内信 2.飞书 4.邮箱 8.短信 16.语音播报
|
||||
public List<Variable> Variables { get; set; } //模板参数
|
||||
public List<Receiver> Receivers { get; set; }
|
||||
|
||||
public sealed record Variable(string Key, string Value);
|
||||
|
||||
public sealed record Receiver(
|
||||
int ReceiverId, //接收人id : 内部用户Id,外部用户Id,或只有邮箱跟短信时不需要接收人Id
|
||||
int RecipientType = 1, //接收人类型 (1:内部用户 2.外部用户)
|
||||
string? ReceiverName = null, //接收人姓名
|
||||
string? Mail = null, //邮箱
|
||||
string? MobilePhone = null //手机号
|
||||
);
|
||||
|
||||
public static NotifyConfig CreateConfig(int userId, string message, List<int> notifyModes)
|
||||
{
|
||||
return new NotifyConfig
|
||||
{
|
||||
Channels = notifyModes,
|
||||
Receivers = new List<Receiver>(1)
|
||||
{
|
||||
new Receiver(userId)
|
||||
},
|
||||
Variables = new List<Variable>(1)
|
||||
{
|
||||
new Variable(ContentKey, message)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static NotifyConfig CreateConfig(int userId, string message)
|
||||
{
|
||||
return new NotifyConfig
|
||||
{
|
||||
Channels = new List<int>(2)
|
||||
{
|
||||
1,
|
||||
2
|
||||
},
|
||||
Receivers = new List<Receiver>
|
||||
{
|
||||
new Receiver(userId)
|
||||
},
|
||||
Variables = new List<Variable>
|
||||
{
|
||||
new Variable(ContentKey, message)
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,5 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
using SJZY.Track.Application.Contract.Dtos.Warning;
|
||||
using SJZY.Track.Application.Helpers;
|
||||
using SJZY.Track.Application.Options;
|
||||
using SJZY.Track.Application.Services.Warning.Model;
|
||||
using SJZY.Track.Domain.Aggregates.KPIAreaAggregate;
|
||||
@ -43,7 +42,7 @@ public sealed class WarningNotifyAggregator : ITransientDependency
|
||||
// 2.以人的维度聚合通知信息,并生成配置参数NotifyConfig
|
||||
// 3.构建并调度一个调用通知接口的立即执行任务
|
||||
// 4.绑定这个任务id(可能是多个)和jobId用户跟踪任务状态
|
||||
public async Task<(List<NotifyConfig> NotifyConfigs, HashSet<int> taskIds)> ScanNotifyAndAggregateAsync()
|
||||
public async Task<(List<WarningNotifyParam> NotifyConfigs, HashSet<int> taskIds)> ScanNotifyAndAggregateAsync()
|
||||
{
|
||||
// 构建查询游标 todo:全量查询需要优化,直接存缓存?
|
||||
// var options = _optionsMonitor.CurrentValue;
|
||||
@ -210,7 +209,7 @@ public sealed class WarningNotifyAggregator : ITransientDependency
|
||||
|
||||
// 2.检查明细中为人工介入的状态
|
||||
var detailsIdSet = filtered.Select(x => x.WarningDetailsId).ToHashSet();
|
||||
var warningDetails = await _warningDetailsEsRepository.GetReturnWarningDetailsAsync(new GetReturnWarningDetailsVO()
|
||||
var warningDetails = await _warningDetailsEsRepository.GetReturnWarningDetailsAsync(new GetReturnWarningDetailsVO
|
||||
{
|
||||
DetailsIds = detailsIdSet,
|
||||
Status = new HashSet<int>(1)
|
||||
@ -261,10 +260,9 @@ public sealed class WarningNotifyAggregator : ITransientDependency
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<NotifyConfig> BuildNotifyConfigs(List<WarningNotifyTaskEntity> needNotifyTasks)
|
||||
private List<WarningNotifyParam> BuildNotifyConfigs(List<WarningNotifyTaskEntity> needNotifyTasks)
|
||||
{
|
||||
var systemId = _optionsMonitor.CurrentValue.MiddleSystemId;
|
||||
var result = new List<NotifyConfig>();
|
||||
var result = new List<WarningNotifyParam>();
|
||||
if (needNotifyTasks.Count == 0) return result;
|
||||
|
||||
// 1.以人的维度对不同类别的预警通知分组聚合
|
||||
@ -293,109 +291,51 @@ public sealed class WarningNotifyAggregator : ITransientDependency
|
||||
}
|
||||
}
|
||||
|
||||
// 2.使用消息模板构建通知消息,并发送通知
|
||||
// 2.使用消息模板构建通知参数,稍后排队发送通知
|
||||
foreach (var (userId, typeNotifyTaskDict) in userIdNotifyTaskDict)
|
||||
{
|
||||
var notifyMessage = BuildNotifyMessage(typeNotifyTaskDict);
|
||||
//聚合时出现 用户a
|
||||
//接收回传预警,命中规则1,通知方式(飞书,站内信) ,命中规则2,通知方式(飞书)
|
||||
//接收运输预警,命中规则1,通知方式(飞书,站内信) ,命中规则2,通知方式(飞书)
|
||||
//接收完整预警,命中规则1,通知方式(飞书) ,命中规则2,通知方式(飞书,站内信)
|
||||
//此时聚合后,消息为:总共6条预警消息,其中回传xx条,运输xx条,完整xx条
|
||||
//同时使用飞书和站内信两种方式通知
|
||||
var config = NotifyConfig.CreateConfig(userId, notifyMessage, new List<int>
|
||||
{
|
||||
1,
|
||||
2
|
||||
});
|
||||
config.SystemId = systemId;
|
||||
result.Add(config);
|
||||
result.Add(BuildNotifyParam(userId, typeNotifyTaskDict));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private string BuildNotifyMessage(Dictionary<int, List<WarningNotifyTaskEntity>> typeNotifyTaskDict)
|
||||
private WarningNotifyParam BuildNotifyParam(int userId, Dictionary<int, List<WarningNotifyTaskEntity>> typeNotifyTaskDict)
|
||||
{
|
||||
var options = _optionsMonitor.CurrentValue;
|
||||
var hours = options.ScanWarningNotifyTaskHourInterval;
|
||||
var transportCount = 0;
|
||||
var transportLastNHoursCount = 0;
|
||||
var returnCount = 0;
|
||||
var returnLastNHoursCount = 0;
|
||||
var completeCount = 0;
|
||||
var completeLastNHoursCount = 0;
|
||||
Func<WarningNotifyTaskEntity, bool> hoursNBefore = x => DateTime.Now - x.CreateTime <= TimeSpan.FromHours(hours);
|
||||
var param = new WarningNotifyParam
|
||||
{
|
||||
UserId = userId,
|
||||
Hours = hours
|
||||
};
|
||||
|
||||
// tips:获取过去x小时的增量
|
||||
Func<WarningNotifyTaskEntity, bool> hoursNBefore = x => DateTime.Now - x.CreateTime <= TimeSpan.FromHours(hours);
|
||||
if (typeNotifyTaskDict.TryGetValue(WarningRuleType.运输时效预警.GetHashCode(), out var transportTimelinessNotifyTasks))
|
||||
{
|
||||
transportLastNHoursCount = transportTimelinessNotifyTasks.Count(hoursNBefore);
|
||||
transportCount = transportTimelinessNotifyTasks.Count;
|
||||
param.TransportLastNHoursCount = transportTimelinessNotifyTasks.Count(hoursNBefore);
|
||||
param.TransportCount = transportTimelinessNotifyTasks.Count;
|
||||
}
|
||||
|
||||
if (typeNotifyTaskDict.TryGetValue(WarningRuleType.回传时效预警.GetHashCode(), out var returnTimelinessNotifyTasks))
|
||||
{
|
||||
returnLastNHoursCount = returnTimelinessNotifyTasks.Count(hoursNBefore);
|
||||
returnCount = returnTimelinessNotifyTasks.Count;
|
||||
param.ReturnLastNHoursCount = returnTimelinessNotifyTasks.Count(hoursNBefore);
|
||||
param.ReturnCount = returnTimelinessNotifyTasks.Count;
|
||||
}
|
||||
|
||||
if (typeNotifyTaskDict.TryGetValue(WarningRuleType.完整预警.GetHashCode(), out var completeWarningNotifyTasks))
|
||||
{
|
||||
completeLastNHoursCount = completeWarningNotifyTasks.Count(hoursNBefore);
|
||||
completeCount = completeWarningNotifyTasks.Count;
|
||||
param.CompleteLastNHoursCount = completeWarningNotifyTasks.Count(hoursNBefore);
|
||||
param.CompleteCount = completeWarningNotifyTasks.Count;
|
||||
}
|
||||
|
||||
return NotifyMessageBuilder.Build(
|
||||
hours,
|
||||
transportCount,
|
||||
transportLastNHoursCount,
|
||||
returnCount,
|
||||
returnLastNHoursCount,
|
||||
completeCount,
|
||||
completeLastNHoursCount
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 标题:预警通知
|
||||
// 内容:尊敬的用户,截止到2024-12-13 10:00:01(UTC +8:00),轨迹中心监测到与您相关的预警风险信息共计299 条,请及时处理,详情如下:
|
||||
// 运输时效预警共计100条,其中过去4小时内新增的预警10条,查看详情
|
||||
// 回传时效预警共计99条,其中过去4小时内新增的预警10条,查看详情
|
||||
// 轨迹完整预警共计100条,其中过去4小时内新增的预警10条,查看详情
|
||||
public static class NotifyMessageBuilder
|
||||
{
|
||||
public const string Title = "预警通知";
|
||||
|
||||
public static string Build(int hours,
|
||||
int transportCount, int transportLastNHoursCount,
|
||||
int returnCount, int returnLastNHoursCount,
|
||||
int completeCount, int completeLastNHoursCount)
|
||||
{
|
||||
var dateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
var totalCount = transportCount + returnCount + completeCount;
|
||||
// todo:无法使用a标签填充(可能是为了安全考虑),需要具体给定一个样式
|
||||
var url1 = "";
|
||||
var url2 = "";
|
||||
var url3 = "";
|
||||
|
||||
var message = $"{Title}\n尊敬的用户,截止到{dateTime}({BuildLocalTimezoneStr()}),轨迹中心监测到与您相关的预警风险信息共计{totalCount} 条,请及时处理,详情如下:";
|
||||
|
||||
if (transportCount > 0)
|
||||
message += $"\n运输时效预警共计{transportCount}条,其中过去{hours}小时内新增的预警{transportLastNHoursCount}条";
|
||||
if (returnCount > 0)
|
||||
message += $"\n回传时效预警共计{returnCount}条,其中过去{hours}小时内新增的预警{returnLastNHoursCount}条";
|
||||
if (completeCount > 0)
|
||||
message += $"\n轨迹完整预警共计{completeCount}条,其中过去{hours}小时内新增的预警{completeLastNHoursCount}条";
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
// 构建本地时区字符串标识 e.g UTC +8:00
|
||||
private static string BuildLocalTimezoneStr()
|
||||
{
|
||||
var offset = TimeZoneInfo.Local.BaseUtcOffset;
|
||||
var flag = offset.Hours > 0 ? "+" : "";
|
||||
var offsetStr = offset.ToString().RemovePostFix(":00");
|
||||
return $"UTC {flag}{offsetStr}";
|
||||
return param;
|
||||
}
|
||||
}
|
||||
|
||||
122
src/SJZY.Track.Application/Hangfire/WarningNotifyBuilder.cs
Normal file
122
src/SJZY.Track.Application/Hangfire/WarningNotifyBuilder.cs
Normal file
@ -0,0 +1,122 @@
|
||||
using FeishuNetSdk;
|
||||
using FeishuNetSdk.Im;
|
||||
using FeishuNetSdk.Im.Dtos;
|
||||
using SJZY.UserCenter.SharedModel.Dtos.Message;
|
||||
using SJZY.UserCenter.SharedModel.Enums;
|
||||
|
||||
namespace SJZY.Track.Application.Hangfire;
|
||||
|
||||
// 标题:预警通知
|
||||
// 内容:尊敬的用户,截止到2024-12-13 10:00:01(UTC +8:00),轨迹中心监测到与您相关的预警风险信息共计299 条,请及时处理,详情如下:
|
||||
// 运输时效预警共计100条,其中过去4小时内新增的预警10条,查看详情
|
||||
// 回传时效预警共计99条,其中过去4小时内新增的预警10条,查看详情
|
||||
// 轨迹完整预警共计100条,其中过去4小时内新增的预警10条,查看详情
|
||||
public static class WarningNotifyBuilder
|
||||
{
|
||||
private const string Title = "预警通知";
|
||||
|
||||
// 构建站内信发消息请求体
|
||||
public static SendMessageByTemplateInput BuildZhanNeiXinMessage(WarningNotifyParam param, int systemId)
|
||||
{
|
||||
const string templateCode = "TrackWarningNotify"; // 模板code
|
||||
const string contentKey = "content"; //内容参数
|
||||
var dateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
var totalCount = param.TransportCount + param.ReturnCount + param.CompleteCount;
|
||||
|
||||
// todo:无法使用a标签填充(可能是为了安全考虑),需要具体给定一个样式
|
||||
var url1 = "";
|
||||
var url2 = "";
|
||||
var url3 = "";
|
||||
|
||||
var content = $"{Title}\n尊敬的用户,截止到{dateTime}({BuildLocalTimezoneStr()}),轨迹中心监测到与您相关的预警风险信息共计{totalCount} 条,请及时处理,详情如下:";
|
||||
|
||||
if (param.TransportCount > 0)
|
||||
content += $"\n运输时效预警共计{param.TransportCount}条,其中过去{param.Hours}小时内新增的预警{param.TransportLastNHoursCount}条";
|
||||
if (param.ReturnCount > 0)
|
||||
content += $"\n回传时效预警共计{param.ReturnCount}条,其中过去{param.Hours}小时内新增的预警{param.ReturnLastNHoursCount}条";
|
||||
if (param.CompleteCount > 0)
|
||||
content += $"\n轨迹完整预警共计{param.CompleteCount}条,其中过去{param.Hours}小时内新增的预警{param.CompleteLastNHoursCount}条";
|
||||
|
||||
// 构建用户中心发消息请求体对象
|
||||
var dto = new SendMessageByTemplateInput
|
||||
{
|
||||
IsNeedToHandle = true,
|
||||
MsgSource = MsgSourceEnum.消息,
|
||||
SystemId = systemId,
|
||||
templateCode = templateCode,
|
||||
channels = new List<ChannelEnum>(1)
|
||||
{
|
||||
ChannelEnum.站内信
|
||||
},
|
||||
variables = new List<VariableDto>(1)
|
||||
{
|
||||
new VariableDto
|
||||
{
|
||||
Key = contentKey,
|
||||
Value = content
|
||||
}
|
||||
},
|
||||
receivers = new List<MsgInstanceReceiverInput>(1)
|
||||
{
|
||||
new MsgInstanceReceiverInput
|
||||
{
|
||||
RecipientType = 1, //接收人类型 (1:内部用户 2.外部用户)
|
||||
ReceiverId = param.UserId, //接收人id
|
||||
ReceiverName = null, //接收人名称
|
||||
Mail = null, // 邮箱
|
||||
MobilePhone = null, // 手机号
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
// 构建飞书卡片发消息请求体
|
||||
public static PostImV1MessagesBodyDto BuildFeiShuCard(WarningNotifyParam param, string fsUserId)
|
||||
{
|
||||
var totalCount = param.TransportCount + param.ReturnCount + param.CompleteCount;
|
||||
var body = new List<object>
|
||||
{
|
||||
new MarkdownElement(Content: $"尊敬的用户,截止到{DateTime.Now:yyyy-MM-dd HH:mm:ss}({BuildLocalTimezoneStr()}),轨迹中心监测到与您相关的预警风险信息共计{totalCount} 条,请及时处理,详情如下:", TextAlign: "left", TextSize: "normal_v2")
|
||||
};
|
||||
// todo:补充点击链接
|
||||
var url1 = "";
|
||||
var url2 = "";
|
||||
var url3 = "";
|
||||
if (param.TransportCount > 0)
|
||||
body.Add(new MarkdownElement(Content: $"运输时效预警共计{param.TransportCount}条,其中过去{param.Hours}小时内新增的预警{param.TransportLastNHoursCount}条 [查看详情]({url1})", TextAlign: "left", TextSize: "normal_v2"));
|
||||
if (param.ReturnCount > 0)
|
||||
body.Add(new MarkdownElement(Content: $"轨迹回传时效预警共计{param.ReturnCount}条,其中过去{param.Hours}小时内新增的预警{param.ReturnLastNHoursCount}条 [查看详情]({url2})", TextAlign: "left", TextSize: "normal_v2"));
|
||||
if (param.CompleteCount > 0)
|
||||
body.Add(new MarkdownElement(Content: $"轨迹完整预警共计{param.CompleteCount}条,其中过去{param.Hours}小时内新增的预警{param.CompleteLastNHoursCount}条 [查看详情]({url3})", TextAlign: "left", TextSize: "normal_v2"));
|
||||
|
||||
var dto = new PostImV1MessagesBodyDto
|
||||
{
|
||||
MsgType = "interactive",
|
||||
ReceiveId = fsUserId
|
||||
};
|
||||
dto.SetContent(new ElementsCardV2Dto
|
||||
{
|
||||
// 配置卡片全局行为
|
||||
Config = new ElementsCardV2Dto.ConfigSuffix(),
|
||||
Header = new ElementsCardV2Dto.HeaderSuffix()
|
||||
{
|
||||
Title = new HeaderTitleElement(Title),
|
||||
Template = "red"
|
||||
},
|
||||
Body = new ElementsCardV2Dto.BodySuffix(body.ToArray()),
|
||||
});
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
// 构建本地时区字符串标识 e.g UTC +8:00
|
||||
private static string BuildLocalTimezoneStr()
|
||||
{
|
||||
var offset = TimeZoneInfo.Local.BaseUtcOffset;
|
||||
var flag = offset.Hours > 0 ? "+" : "";
|
||||
var offsetStr = offset.ToString().RemovePostFix(":00");
|
||||
return $"UTC {flag}{offsetStr}";
|
||||
}
|
||||
}
|
||||
23
src/SJZY.Track.Application/Hangfire/WarningNotifyParam.cs
Normal file
23
src/SJZY.Track.Application/Hangfire/WarningNotifyParam.cs
Normal file
@ -0,0 +1,23 @@
|
||||
namespace SJZY.Track.Application.Hangfire;
|
||||
|
||||
/// <summary>
|
||||
/// 构建轨迹预警通知消息所需的参数
|
||||
/// </summary>
|
||||
public class WarningNotifyParam
|
||||
{
|
||||
public int UserId { get; set; }
|
||||
|
||||
public int Hours { get; set; }
|
||||
|
||||
public int TransportCount { get; set; }
|
||||
|
||||
public int TransportLastNHoursCount { get; set; }
|
||||
|
||||
public int ReturnCount { get; set; }
|
||||
|
||||
public int ReturnLastNHoursCount { get; set; }
|
||||
|
||||
public int CompleteCount { get; set; }
|
||||
|
||||
public int CompleteLastNHoursCount { get; set; }
|
||||
}
|
||||
@ -1,3 +1,4 @@
|
||||
using FeishuNetSdk;
|
||||
using Hangfire;
|
||||
using Microsoft.Extensions.Options;
|
||||
using SJZY.Expand.ABP.Core.Logger;
|
||||
@ -11,9 +12,8 @@ using SJZY.Track.Domain.Aggregates.WarningAggregate.Return;
|
||||
using SJZY.Track.Domain.Dtos.Warning;
|
||||
using SJZY.Track.Domain.Enums;
|
||||
using SJZY.Track.Domain.Extensions;
|
||||
using SJZY.Track.Domain.Queries;
|
||||
using SJZY.UserCenter.HttpApi.Services.Message;
|
||||
using SJZY.UserCenter.SharedModel.Dtos.Message;
|
||||
using SJZY.UserCenter.SharedModel.Enums;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Volo.Abp.Http.Client.DynamicProxying;
|
||||
|
||||
@ -21,8 +21,8 @@ namespace SJZY.Track.Application.Hangfire;
|
||||
|
||||
public interface IWarningTaskService
|
||||
{
|
||||
[AutomaticRetry(Attempts = 3)]
|
||||
Task CallNotifyAsync(NotifyConfig config, CancellationToken ct);
|
||||
[AutomaticRetry(Attempts = 1)]
|
||||
Task CallNotifyAsync(WarningNotifyParam param, CancellationToken ct);
|
||||
|
||||
[AutomaticRetry(Attempts = 3, ExceptOn = new[] { typeof(BusinessException) })]
|
||||
Task CallTrackRetryPushAsync(ReturnWarningRetryPushTaskEntity entity, CancellationToken ct);
|
||||
@ -30,51 +30,57 @@ public interface IWarningTaskService
|
||||
|
||||
public class WarningTaskService : IWarningTaskService, ITransientDependency
|
||||
{
|
||||
private readonly IOptionsMonitor<InterfaceRelayParamsConfigOptions> _interfaceRelayOptions;
|
||||
private readonly IOptionsMonitor<TrackWarningTaskOptions> _warningTaskOptions;
|
||||
private readonly IHttpClientProxy<IRequestSendMessageService> _requestSendMessageService;
|
||||
private readonly IHttpClientProxy<IInterfaceForwardServiceV2> _interfaceForwardServiceV2;
|
||||
private readonly IOptionsMonitor<InterfaceRelayParamsConfigOptions> _options;
|
||||
private readonly IFeishuTenantApi _feishuTenantApi;
|
||||
private readonly IWarningDetailsEsRepository _warningDetailsEsRepository;
|
||||
private readonly IWarningTaskRepository _warningTaskRepository;
|
||||
private readonly IVFsUserQueries _vfsUserQueries;
|
||||
|
||||
public WarningTaskService(IHttpClientProxy<IInterfaceForwardServiceV2> interfaceForwardServiceV2, IOptionsMonitor<InterfaceRelayParamsConfigOptions> options, IHttpClientProxy<IRequestSendMessageService> requestSendMessageService, IWarningDetailsEsRepository warningDetailsEsRepository, IWarningTaskRepository warningTaskRepository)
|
||||
public WarningTaskService(
|
||||
IOptionsMonitor<InterfaceRelayParamsConfigOptions> interfaceRelayOptions,
|
||||
IOptionsMonitor<TrackWarningTaskOptions> warningTaskOptions,
|
||||
IHttpClientProxy<IInterfaceForwardServiceV2> interfaceForwardServiceV2,
|
||||
IHttpClientProxy<IRequestSendMessageService> requestSendMessageService,
|
||||
IFeishuTenantApi feishuTenantApi,
|
||||
IWarningDetailsEsRepository warningDetailsEsRepository,
|
||||
IWarningTaskRepository warningTaskRepository,
|
||||
IVFsUserQueries vfsUserQueries)
|
||||
{
|
||||
_interfaceRelayOptions = interfaceRelayOptions;
|
||||
_warningTaskOptions = warningTaskOptions;
|
||||
_interfaceForwardServiceV2 = interfaceForwardServiceV2;
|
||||
_requestSendMessageService = requestSendMessageService;
|
||||
_feishuTenantApi = feishuTenantApi;
|
||||
_warningDetailsEsRepository = warningDetailsEsRepository;
|
||||
_warningTaskRepository = warningTaskRepository;
|
||||
_options = options;
|
||||
_vfsUserQueries = vfsUserQueries;
|
||||
}
|
||||
|
||||
#region 用户中心调用,通知(一次)
|
||||
|
||||
[AutomaticRetry(Attempts = 3)]
|
||||
public async Task CallNotifyAsync(NotifyConfig config, CancellationToken ct)
|
||||
[AutomaticRetry(Attempts = 1)]
|
||||
public async Task CallNotifyAsync(WarningNotifyParam param, CancellationToken ct)
|
||||
{
|
||||
ct.ThrowIfCancellationRequested();
|
||||
var r = await _requestSendMessageService.Service.SendMessageByTemplateAsync(new SendMessageByTemplateInput
|
||||
{
|
||||
IsNeedToHandle = config.IsNeedToHandle,
|
||||
MsgSource = (MsgSourceEnum) config.MsgSource,
|
||||
SystemId = config.SystemId,
|
||||
templateCode = config.TemplateCode,
|
||||
channels = config.Channels.Select(x => (ChannelEnum) x).ToList(),
|
||||
variables = config.Variables.Select(x => new VariableDto()
|
||||
{
|
||||
Key = x.Key,
|
||||
Value = x.Value
|
||||
}).ToList(),
|
||||
receivers = config.Receivers.Select(x => new MsgInstanceReceiverInput()
|
||||
{
|
||||
ReceiverId = x.ReceiverId,
|
||||
RecipientType = x.RecipientType
|
||||
}).ToList(),
|
||||
});
|
||||
var options = _warningTaskOptions.CurrentValue;
|
||||
|
||||
// 发送站内信
|
||||
// https://centerapi.test.shijizhongyun.com/userApi/index.html?urls.primaryName=%E6%B6%88%E6%81%AF%E8%AE%A2%E9%98%85%E5%AE%9E%E4%BE%8B
|
||||
// MsgSubscribeInstance/SendMessageByTemplate
|
||||
var r = await _requestSendMessageService.Service.SendMessageByTemplateAsync(WarningNotifyBuilder.BuildZhanNeiXinMessage(param, options.MiddleSystemId));
|
||||
if (r.Code != GlobalConst.SuccessCode)
|
||||
{
|
||||
throw new BusinessException(message: $"用户中心调用失败:SendMessageByTemplateAsync" +
|
||||
$"Msg:{r.Msg}");
|
||||
}
|
||||
throw new BusinessException(message: $"用户中心调用失败:SendMessageByTemplateAsync Msg:{r.Msg}");
|
||||
|
||||
// 发送FeiShu卡片信息
|
||||
var fsUserId = await _vfsUserQueries.GetFirstAsync(x => x.UserCenterId == param.UserId, y => y.FsEmployeeId);
|
||||
if (string.IsNullOrWhiteSpace(fsUserId))
|
||||
throw new BusinessException(message: "查询用户中心失败:SendMessageByTemplateAsync Msg:未找到用户对应的飞书用户Id");
|
||||
var res = await _feishuTenantApi.PostImV1MessagesAsync("user_id", WarningNotifyBuilder.BuildFeiShuCard(param, fsUserId));
|
||||
if (res.Code != 0)
|
||||
throw new BusinessException(message: $"飞书调用失败:SendMessageByTemplateAsync Msg:{res.Msg}");
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -107,8 +113,8 @@ public class WarningTaskService : IWarningTaskService, ITransientDependency
|
||||
using (Track2InterfaceRelaySubSystemContext.Use(new Track2InterfaceRelaySubSystemContext(task.SubSystemCode)))
|
||||
{
|
||||
var upStreamCode = isAdd
|
||||
? _options.CurrentValue.PushTrackInterfaceCode
|
||||
: _options.CurrentValue.TrackUpdateInterfaceCode;
|
||||
? _interfaceRelayOptions.CurrentValue.PushTrackInterfaceCode
|
||||
: _interfaceRelayOptions.CurrentValue.TrackUpdateInterfaceCode;
|
||||
|
||||
var r = await _interfaceForwardServiceV2.Service.BatchForwardThenPushToQueueAsync(
|
||||
upStreamCode: upStreamCode,
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BSI.Stack.Rabbit" Version="2.1.4" />
|
||||
<PackageReference Include="Confluent.Kafka" Version="2.10.0" />
|
||||
<PackageReference Include="FeishuNetSdk" Version="2.4.6" />
|
||||
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.18" />
|
||||
<PackageReference Include="Hangfire.Redis.StackExchange" Version="1.9.4" />
|
||||
<PackageReference Include="Savorboard.CAP.InMemoryMessageQueue" Version="8.2.1"/>
|
||||
|
||||
7
src/SJZY.Track.Domain/Queries/IVFsUserQueries.cs
Normal file
7
src/SJZY.Track.Domain/Queries/IVFsUserQueries.cs
Normal file
@ -0,0 +1,7 @@
|
||||
using SJZY.Track.Domain.VEntities;
|
||||
|
||||
namespace SJZY.Track.Domain.Queries;
|
||||
|
||||
public interface IVFsUserQueries : IBasicQuery<VFSUserEntity>
|
||||
{
|
||||
}
|
||||
65
src/SJZY.Track.Domain/VEntities/VFSUserEntity.cs
Normal file
65
src/SJZY.Track.Domain/VEntities/VFSUserEntity.cs
Normal file
@ -0,0 +1,65 @@
|
||||
namespace SJZY.Track.Domain.VEntities;
|
||||
|
||||
/// <summary>
|
||||
/// 飞书用户表,用户中心用户关联飞书用户
|
||||
/// </summary>
|
||||
[SugarTable("v_fs_user")]
|
||||
public class VFSUserEntity : IEntity
|
||||
{
|
||||
[SugarColumn(ColumnName = "Id", IsPrimaryKey = true, IsIdentity = true)]
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户中心id
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "user_center_id")]
|
||||
public int UserCenterId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户名
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "user_name")]
|
||||
public string UserName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户手机号
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "mobile")]
|
||||
public string Mobile { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 飞书 union id
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "union_id")]
|
||||
public string UnionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 飞书 user id
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "fs_employee_id")]
|
||||
public string FsEmployeeId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 飞书头像
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "avatar")]
|
||||
public string Avatar { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 自建的飞书登录应用下的OpenId
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "fsloginApp_openid")]
|
||||
public string FsLoginAppOpenId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "create_time")]
|
||||
public DateTime CreateTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 更新时间
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "update_time")]
|
||||
public DateTime UpdateTime { get; set; }
|
||||
}
|
||||
9
src/SJZY.Track.Repository/Queries/VFsUserQueries.cs
Normal file
9
src/SJZY.Track.Repository/Queries/VFsUserQueries.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using SJZY.Track.Domain.Queries;
|
||||
using SJZY.Track.Domain.VEntities;
|
||||
|
||||
namespace SJZY.Track.Repository.Queries;
|
||||
|
||||
public class VFsUserQueries: BasicQuery<VFSUserEntity>, IVFsUserQueries, ITransientDependency
|
||||
{
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user