From 0a4103abf5d5c2686b491eb39985fd4e189e5e34 Mon Sep 17 00:00:00 2001 From: hardstylewyl <827778732@qq.com> Date: Thu, 5 Jun 2025 17:45:50 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=E9=87=8D=E6=9E=84=E9=A2=84=E8=AD=A6?= =?UTF-8?q?=E9=80=9A=E7=9F=A5=EF=BC=8C=E7=94=A8=E6=88=B7=E4=B8=AD=E5=BF=83?= =?UTF-8?q?=E5=8F=AA=E4=BD=BF=E7=94=A8=E7=AB=99=E5=86=85=E4=BF=A1=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=EF=BC=8C=E6=8E=A5=E5=85=A5=E9=A3=9E=E4=B9=A6=E7=AC=AC?= =?UTF-8?q?=E4=B8=89=E6=96=B9=E5=BA=93=EF=BC=8C=E7=9B=B4=E6=8E=A5=E8=B0=83?= =?UTF-8?q?=E7=94=A8=E9=A3=9E=E4=B9=A6=E8=B0=83=E7=94=A8=E5=8F=91=E9=80=81?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Hangfire/NotifyConfig.cs | 63 --------- .../Hangfire/WarningNotifyAggregator.cs | 102 +++------------ .../Hangfire/WarningNotifyBuilder.cs | 122 ++++++++++++++++++ .../Hangfire/WarningNotifyParam.cs | 23 ++++ .../Hangfire/WarningTaskService.cs | 72 ++++++----- .../SJZY.Track.Application.csproj | 1 + .../Queries/IVFsUserQueries.cs | 7 + .../VEntities/VFSUserEntity.cs | 65 ++++++++++ .../Queries/VFsUserQueries.cs | 9 ++ 9 files changed, 287 insertions(+), 177 deletions(-) delete mode 100644 src/SJZY.Track.Application/Hangfire/NotifyConfig.cs create mode 100644 src/SJZY.Track.Application/Hangfire/WarningNotifyBuilder.cs create mode 100644 src/SJZY.Track.Application/Hangfire/WarningNotifyParam.cs create mode 100644 src/SJZY.Track.Domain/Queries/IVFsUserQueries.cs create mode 100644 src/SJZY.Track.Domain/VEntities/VFSUserEntity.cs create mode 100644 src/SJZY.Track.Repository/Queries/VFsUserQueries.cs diff --git a/src/SJZY.Track.Application/Hangfire/NotifyConfig.cs b/src/SJZY.Track.Application/Hangfire/NotifyConfig.cs deleted file mode 100644 index 861be32b..00000000 --- a/src/SJZY.Track.Application/Hangfire/NotifyConfig.cs +++ /dev/null @@ -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 Channels { get; set; } //1:站内信 2.飞书 4.邮箱 8.短信 16.语音播报 - public List Variables { get; set; } //模板参数 - public List 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 notifyModes) - { - return new NotifyConfig - { - Channels = notifyModes, - Receivers = new List(1) - { - new Receiver(userId) - }, - Variables = new List(1) - { - new Variable(ContentKey, message) - } - }; - } - - public static NotifyConfig CreateConfig(int userId, string message) - { - return new NotifyConfig - { - Channels = new List(2) - { - 1, - 2 - }, - Receivers = new List - { - new Receiver(userId) - }, - Variables = new List - { - new Variable(ContentKey, message) - } - }; - } -} diff --git a/src/SJZY.Track.Application/Hangfire/WarningNotifyAggregator.cs b/src/SJZY.Track.Application/Hangfire/WarningNotifyAggregator.cs index ca1d81c3..c49df4aa 100644 --- a/src/SJZY.Track.Application/Hangfire/WarningNotifyAggregator.cs +++ b/src/SJZY.Track.Application/Hangfire/WarningNotifyAggregator.cs @@ -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 NotifyConfigs, HashSet taskIds)> ScanNotifyAndAggregateAsync() + public async Task<(List NotifyConfigs, HashSet 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(1) @@ -261,10 +260,9 @@ public sealed class WarningNotifyAggregator : ITransientDependency return result; } - private List BuildNotifyConfigs(List needNotifyTasks) + private List BuildNotifyConfigs(List needNotifyTasks) { - var systemId = _optionsMonitor.CurrentValue.MiddleSystemId; - var result = new List(); + var result = new List(); 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 - { - 1, - 2 - }); - config.SystemId = systemId; - result.Add(config); + result.Add(BuildNotifyParam(userId, typeNotifyTaskDict)); } return result; } - private string BuildNotifyMessage(Dictionary> typeNotifyTaskDict) + private WarningNotifyParam BuildNotifyParam(int userId, Dictionary> 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 hoursNBefore = x => DateTime.Now - x.CreateTime <= TimeSpan.FromHours(hours); + var param = new WarningNotifyParam + { + UserId = userId, + Hours = hours + }; + // tips:获取过去x小时的增量 + Func 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; } } diff --git a/src/SJZY.Track.Application/Hangfire/WarningNotifyBuilder.cs b/src/SJZY.Track.Application/Hangfire/WarningNotifyBuilder.cs new file mode 100644 index 00000000..997d3533 --- /dev/null +++ b/src/SJZY.Track.Application/Hangfire/WarningNotifyBuilder.cs @@ -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(1) + { + ChannelEnum.站内信 + }, + variables = new List(1) + { + new VariableDto + { + Key = contentKey, + Value = content + } + }, + receivers = new List(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 + { + 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}"; + } +} diff --git a/src/SJZY.Track.Application/Hangfire/WarningNotifyParam.cs b/src/SJZY.Track.Application/Hangfire/WarningNotifyParam.cs new file mode 100644 index 00000000..c4b1de4b --- /dev/null +++ b/src/SJZY.Track.Application/Hangfire/WarningNotifyParam.cs @@ -0,0 +1,23 @@ +namespace SJZY.Track.Application.Hangfire; + +/// +/// 构建轨迹预警通知消息所需的参数 +/// +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; } +} diff --git a/src/SJZY.Track.Application/Hangfire/WarningTaskService.cs b/src/SJZY.Track.Application/Hangfire/WarningTaskService.cs index defaf532..050d461d 100644 --- a/src/SJZY.Track.Application/Hangfire/WarningTaskService.cs +++ b/src/SJZY.Track.Application/Hangfire/WarningTaskService.cs @@ -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 _interfaceRelayOptions; + private readonly IOptionsMonitor _warningTaskOptions; private readonly IHttpClientProxy _requestSendMessageService; private readonly IHttpClientProxy _interfaceForwardServiceV2; - private readonly IOptionsMonitor _options; + private readonly IFeishuTenantApi _feishuTenantApi; private readonly IWarningDetailsEsRepository _warningDetailsEsRepository; private readonly IWarningTaskRepository _warningTaskRepository; + private readonly IVFsUserQueries _vfsUserQueries; - public WarningTaskService(IHttpClientProxy interfaceForwardServiceV2, IOptionsMonitor options, IHttpClientProxy requestSendMessageService, IWarningDetailsEsRepository warningDetailsEsRepository, IWarningTaskRepository warningTaskRepository) + public WarningTaskService( + IOptionsMonitor interfaceRelayOptions, + IOptionsMonitor warningTaskOptions, + IHttpClientProxy interfaceForwardServiceV2, + IHttpClientProxy 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, diff --git a/src/SJZY.Track.Application/SJZY.Track.Application.csproj b/src/SJZY.Track.Application/SJZY.Track.Application.csproj index 34159b3e..06efb7c6 100644 --- a/src/SJZY.Track.Application/SJZY.Track.Application.csproj +++ b/src/SJZY.Track.Application/SJZY.Track.Application.csproj @@ -10,6 +10,7 @@ + diff --git a/src/SJZY.Track.Domain/Queries/IVFsUserQueries.cs b/src/SJZY.Track.Domain/Queries/IVFsUserQueries.cs new file mode 100644 index 00000000..debda110 --- /dev/null +++ b/src/SJZY.Track.Domain/Queries/IVFsUserQueries.cs @@ -0,0 +1,7 @@ +using SJZY.Track.Domain.VEntities; + +namespace SJZY.Track.Domain.Queries; + +public interface IVFsUserQueries : IBasicQuery +{ +} diff --git a/src/SJZY.Track.Domain/VEntities/VFSUserEntity.cs b/src/SJZY.Track.Domain/VEntities/VFSUserEntity.cs new file mode 100644 index 00000000..71297838 --- /dev/null +++ b/src/SJZY.Track.Domain/VEntities/VFSUserEntity.cs @@ -0,0 +1,65 @@ +namespace SJZY.Track.Domain.VEntities; + +/// +/// 飞书用户表,用户中心用户关联飞书用户 +/// +[SugarTable("v_fs_user")] +public class VFSUserEntity : IEntity +{ + [SugarColumn(ColumnName = "Id", IsPrimaryKey = true, IsIdentity = true)] + public int Id { get; set; } + + /// + /// 用户中心id + /// + [SugarColumn(ColumnName = "user_center_id")] + public int UserCenterId { get; set; } + + /// + /// 用户名 + /// + [SugarColumn(ColumnName = "user_name")] + public string UserName { get; set; } + + /// + /// 用户手机号 + /// + [SugarColumn(ColumnName = "mobile")] + public string Mobile { get; set; } + + /// + /// 飞书 union id + /// + [SugarColumn(ColumnName = "union_id")] + public string UnionId { get; set; } + + /// + /// 飞书 user id + /// + [SugarColumn(ColumnName = "fs_employee_id")] + public string FsEmployeeId { get; set; } + + /// + /// 飞书头像 + /// + [SugarColumn(ColumnName = "avatar")] + public string Avatar { get; set; } + + /// + /// 自建的飞书登录应用下的OpenId + /// + [SugarColumn(ColumnName = "fsloginApp_openid")] + public string FsLoginAppOpenId { get; set; } + + /// + /// 创建时间 + /// + [SugarColumn(ColumnName = "create_time")] + public DateTime CreateTime { get; set; } + + /// + /// 更新时间 + /// + [SugarColumn(ColumnName = "update_time")] + public DateTime UpdateTime { get; set; } +} diff --git a/src/SJZY.Track.Repository/Queries/VFsUserQueries.cs b/src/SJZY.Track.Repository/Queries/VFsUserQueries.cs new file mode 100644 index 00000000..fb047384 --- /dev/null +++ b/src/SJZY.Track.Repository/Queries/VFsUserQueries.cs @@ -0,0 +1,9 @@ +using SJZY.Track.Domain.Queries; +using SJZY.Track.Domain.VEntities; + +namespace SJZY.Track.Repository.Queries; + +public class VFsUserQueries: BasicQuery, IVFsUserQueries, ITransientDependency +{ + +}