using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Text.Json; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using ZhonTai.Admin.Core.Dto; using ZhonTai.Admin.Services; using ZhonTai.DynamicApi; using ZhonTai.DynamicApi.Attributes; using NPP.SmartSchedue.Api.Contracts.Services.Notification; using NPP.SmartSchedue.Api.Contracts.Services.Notification.Input; using NPP.SmartSchedue.Api.Contracts.Services.Notification.Output; using NPP.SmartSchedue.Api.Contracts.Domain.Notification; using NPP.SmartSchedue.Api.Repositories.Notification; using NPP.SmartSchedue.Api.Contracts.Core.Enums; using NPP.SmartSchedue.Api.Core.Consts; using ZhonTai.Admin.Core.GrpcServices; using ZhonTai.Admin.Core.GrpcServices.Dtos; namespace NPP.SmartSchedue.Api.Services.Notification; /// /// 通知服务 /// [DynamicApi(Area = "app")] public class NotificationService : BaseService, INotificationService, IDynamicApi { private readonly NotificationSettingRepository _notificationSettingRepository; private readonly PersonnelGroupRepository _personnelGroupRepository; private readonly NotificationHistoryRepository _notificationHistoryRepository; private readonly IEmailNotificationService _emailNotificationService; private readonly ISystemMessageService _systemMessageService; private readonly INotificationTemplateService _templateService; private readonly IUserGrpcService _userService; private readonly ILogger _logger; public NotificationService( NotificationSettingRepository notificationSettingRepository, PersonnelGroupRepository personnelGroupRepository, NotificationHistoryRepository notificationHistoryRepository, IEmailNotificationService emailNotificationService, ISystemMessageService systemMessageService, INotificationTemplateService templateService, IUserGrpcService userService, ILogger logger) { _notificationSettingRepository = notificationSettingRepository; _personnelGroupRepository = personnelGroupRepository; _notificationHistoryRepository = notificationHistoryRepository; _emailNotificationService = emailNotificationService; _systemMessageService = systemMessageService; _templateService = templateService; _userService = userService; _logger = logger; } #region 通知设置管理 /// /// 获取通知设置列表(可选过滤,含缓存) /// [HttpGet] public async Task> GetNotificationSettingListAsync(bool? isEnabled = null, long? personnelGroupId = null) { var cacheKey = $"{CacheKeys.NotificationSettingsKey}:all"; var cachedList = await Cache.GetAsync>(cacheKey); if ( cachedList != null && cachedList.Any()) { return cachedList; } var query = _notificationSettingRepository.Select.Include(a => a.PersonnelGroup); if (isEnabled != null) { query = query.Where(a => a.IsEnabled == isEnabled); } if (personnelGroupId.HasValue && personnelGroupId.Value > 0) { query = query.Where(a => a.PersonnelGroupId == personnelGroupId.Value); } var entities = await query.OrderByDescending(a => a.CreatedTime).ToListAsync(); var outputs = entities.Select(MapToNotificationSettingOutput).ToList(); Cache.Set(cacheKey, outputs, TimeSpan.FromHours(12)); return outputs; } /// /// 查询通知设置 /// [HttpGet] public async Task GetNotificationSettingAsync(long id) { _logger.LogInformation("开始查询通知设置,ID:{Id}", id); var entity = await _notificationSettingRepository.Select .WhereDynamic(id) .Include(a => a.PersonnelGroup) .ToOneAsync(); if (entity == null) { _logger.LogWarning("通知设置不存在,ID:{Id}", id); throw new Exception($"通知设置不存在,ID:{id}"); } var output = MapToNotificationSettingOutput(entity); _logger.LogInformation("成功查询通知设置,ID:{Id}", id); return output; } /// /// 查询通知设置分页 /// [HttpPost] public async Task> GetNotificationSettingPageAsync(PageInput input) { _logger.LogInformation("开始查询通知设置分页,页码:{Current},页大小:{Size}", input.CurrentPage, input.PageSize); var query = _notificationSettingRepository.Select .Include(a => a.PersonnelGroup); // 根据搜索条件过滤 if (!string.IsNullOrEmpty(input.Filter?.NotificationName)) { query = query.Where(a => a.NotificationName.Contains(input.Filter.NotificationName)); } if (input.Filter?.IsEnabled != null) { query = query.Where(a => a.IsEnabled == input.Filter.IsEnabled); } if (input.Filter?.PersonnelGroupId != null && input.Filter.PersonnelGroupId > 0) { query = query.Where(a => a.PersonnelGroupId == input.Filter.PersonnelGroupId); } var totalCount = await query.CountAsync(); var entities = await query .OrderByDescending(a => a.CreatedTime) .Page(input.CurrentPage, input.PageSize) .ToListAsync(); var outputs = entities.Select(MapToNotificationSettingOutput).ToList(); _logger.LogInformation("成功查询通知设置分页,总数:{Total},当前页数据:{Count}", totalCount, outputs.Count); return new PageOutput { List = outputs, Total = totalCount }; } /// /// 创建通知设置 /// [HttpPost] public async Task CreateNotificationSettingAsync(NotificationSettingCreateInput input) { _logger.LogInformation("开始创建通知设置:{NotificationName}", input.NotificationName); // 业务验证:检查通知设置名称是否已存在 var exists = await _notificationSettingRepository.ExistsNotificationNameAsync(input.NotificationName); if (exists) { _logger.LogWarning("通知设置名称已存在:{NotificationName}", input.NotificationName); throw new Exception($"通知设置名称已存在:{input.NotificationName}"); } // 验证人员组是否存在 var personnelGroup = await _personnelGroupRepository.GetAsync(input.PersonnelGroupId); if (personnelGroup == null) { _logger.LogWarning("人员组不存在,ID:{PersonnelGroupId}", input.PersonnelGroupId); throw new Exception($"人员组不存在,ID:{input.PersonnelGroupId}"); } // 业务验证:时间配置合法性检查 ValidateTimeConfiguration(input.StartTime, input.EndTime); // 业务验证:频次配置合法性检查 ValidateFrequencyConfiguration(input.FrequencyType, input.IntervalMinutes); // 业务验证:模板配置合法性检查 await ValidateTemplateConfiguration(input); var entity = new NotificationSettingEntity { NotificationName = input.NotificationName, Description = input.Description, IsEnabled = input.IsEnabled, StartTime = input.StartTime, EndTime = input.EndTime, FrequencyType = (int)input.FrequencyType, IntervalMinutes = input.IntervalMinutes, PersonnelGroupId = input.PersonnelGroupId, EmailSubjectTemplate = input.EmailSubjectTemplate, EmailContentTemplate = input.EmailContentTemplate, SystemMessageTitleTemplate = input.SystemMessageTitleTemplate, SystemMessageContentTemplate = input.SystemMessageContentTemplate, TriggerConditions = input.TriggerConditions, LastModifiedTime = DateTime.Now }; // 设置通知方式 entity.IsEmailEnabled = input.IsEmailEnabled; entity.IsSystemMessageEnabled = input.IsSystemMessageEnabled; entity = await _notificationSettingRepository.InsertAsync(entity); _logger.LogInformation("成功创建通知设置,ID:{Id},名称:{NotificationName}", entity.Id, entity.NotificationName); var cacheKey = $"{CacheKeys.NotificationSettingsKey}:all"; await ClearNotificationSettingCache(); return entity.Id; } /// /// 更新通知设置 /// [HttpPut] public async Task UpdateNotificationSettingAsync(NotificationSettingUpdateInput input) { _logger.LogInformation("开始更新通知设置,ID:{Id}", input.Id); var entity = await _notificationSettingRepository.GetAsync(input.Id); if (entity == null) { _logger.LogWarning("通知设置不存在,ID:{Id}", input.Id); throw new Exception($"通知设置不存在,ID:{input.Id}"); } // 业务验证:检查通知设置名称是否已存在(排除自己) var exists = await _notificationSettingRepository.ExistsNotificationNameAsync(input.NotificationName, input.Id); if (exists) { _logger.LogWarning("通知设置名称已存在:{NotificationName}", input.NotificationName); throw new Exception($"通知设置名称已存在:{input.NotificationName}"); } // 验证人员组是否存在 var personnelGroup = await _personnelGroupRepository.GetAsync(input.PersonnelGroupId); if (personnelGroup == null) { _logger.LogWarning("人员组不存在,ID:{PersonnelGroupId}", input.PersonnelGroupId); throw new Exception($"人员组不存在,ID:{input.PersonnelGroupId}"); } // 业务验证:时间配置合法性检查 ValidateTimeConfiguration(input.StartTime, input.EndTime); // 业务验证:频次配置合法性检查 ValidateFrequencyConfiguration(input.FrequencyType, input.IntervalMinutes); // 业务验证:模板配置合法性检查 await ValidateTemplateConfiguration(input); // 更新实体属性 entity.NotificationName = input.NotificationName; entity.Description = input.Description; entity.IsEnabled = input.IsEnabled; entity.StartTime = input.StartTime; entity.EndTime = input.EndTime; entity.FrequencyType = (int)input.FrequencyType; entity.IntervalMinutes = input.IntervalMinutes; entity.PersonnelGroupId = input.PersonnelGroupId; entity.EmailSubjectTemplate = input.EmailSubjectTemplate; entity.EmailContentTemplate = input.EmailContentTemplate; entity.SystemMessageTitleTemplate = input.SystemMessageTitleTemplate; entity.SystemMessageContentTemplate = input.SystemMessageContentTemplate; entity.TriggerConditions = input.TriggerConditions; entity.LastModifiedTime = DateTime.Now; // 设置通知方式 entity.IsEmailEnabled = input.IsEmailEnabled; entity.IsSystemMessageEnabled = input.IsSystemMessageEnabled; await _notificationSettingRepository.UpdateAsync(entity); _logger.LogInformation("成功更新通知设置,ID:{Id},名称:{NotificationName}", entity.Id, entity.NotificationName); var cacheKey = $"{CacheKeys.NotificationSettingsKey}:all"; await ClearNotificationSettingCache(); } /// /// 删除通知设置 /// [HttpDelete] public async Task DeleteNotificationSettingAsync(long id) { _logger.LogInformation("开始删除通知设置,ID:{Id}", id); var entity = await _notificationSettingRepository.GetAsync(id); if (entity == null) { _logger.LogWarning("通知设置不存在,ID:{Id}", id); throw new Exception($"通知设置不存在,ID:{id}"); } // 业务验证:检查是否存在关联的通知历史记录 var hasHistory = await _notificationHistoryRepository.Select .Where(a => a.NotificationSettingId == id) .AnyAsync(); if (hasHistory) { _logger.LogWarning("通知设置存在历史记录,无法删除,ID:{Id}", id); throw new Exception($"通知设置存在历史记录,无法删除,ID:{id}"); } await _notificationSettingRepository.DeleteAsync(id); _logger.LogInformation("成功删除通知设置,ID:{Id},名称:{NotificationName}", id, entity.NotificationName); await ClearNotificationSettingCache(); } /// /// 启用/禁用通知设置 /// [HttpPut] public async Task ToggleNotificationSettingAsync(long id, bool enabled) { _logger.LogInformation("开始{Action}通知设置,ID:{Id}", enabled ? "启用" : "禁用", id); var entity = await _notificationSettingRepository.GetAsync(id); if (entity == null) { _logger.LogWarning("通知设置不存在,ID:{Id}", id); throw new Exception($"通知设置不存在,ID:{id}"); } entity.IsEnabled = enabled; entity.LastModifiedTime = DateTime.Now; await _notificationSettingRepository.UpdateAsync(entity); _logger.LogInformation("成功{Action}通知设置,ID:{Id},名称:{NotificationName}", enabled ? "启用" : "禁用", id, entity.NotificationName); await ClearNotificationSettingCache(); } /// /// 清除消息配置缓存 /// private async Task ClearNotificationSettingCache() { var cacheKey = $"{CacheKeys.NotificationSettingsKey}:all"; Cache.ExistsAsync(cacheKey); } #endregion #region 人员组管理 /// /// 查询人员组 /// [HttpGet] public async Task GetPersonnelGroupAsync(long id) { _logger.LogInformation("开始查询人员组,ID:{Id}", id); var entity = await _personnelGroupRepository.Select .WhereDynamic(id) .ToOneAsync(); if (entity == null) { _logger.LogWarning("人员组不存在,ID:{Id}", id); throw new Exception($"人员组不存在,ID:{id}"); } var output = MapToPersonnelGroupOutput(entity); // 计算实际人员数量 var actualCount = await GetPersonnelGroupMembersAsync(id); output.TotalPersonnelCount = actualCount.Count; _logger.LogInformation("成功查询人员组,ID:{Id},实际人员数量:{Count}", id, output.TotalPersonnelCount); return output; } /// /// 查询人员组分页 /// [HttpPost] public async Task> GetPersonnelGroupPageAsync(PageInput input) { _logger.LogInformation("开始查询人员组分页,页码:{Current},页大小:{Size}", input.CurrentPage, input.PageSize); var query = _personnelGroupRepository.Select; // 根据搜索条件过滤 if (!string.IsNullOrEmpty(input.Filter?.GroupName)) { query = query.Where(a => a.GroupName.Contains(input.Filter.GroupName)); } if (input.Filter?.IsEnabled != null) { query = query.Where(a => a.IsEnabled == input.Filter.IsEnabled); } if (input.Filter?.GroupType != null && input.Filter?.GroupType != 0) { query = query.Where(a => a.GroupType == (int)input.Filter.GroupType); } var totalCount = await query.CountAsync(); var entities = await query .OrderByDescending(a => a.CreatedTime) .Page(input.CurrentPage, input.PageSize) .ToListAsync(); var outputs = entities.Select(MapToPersonnelGroupOutput).ToList(); // 批量计算实际人员数量 foreach (var output in outputs) { var actualMembers = await GetPersonnelGroupMembersAsync(output.Id); output.TotalPersonnelCount = actualMembers.Count; } _logger.LogInformation("成功查询人员组分页,总数:{Total},当前页数据:{Count}", totalCount, outputs.Count); return new PageOutput { List = outputs, Total = totalCount }; } /// /// 创建人员组 /// [HttpPost] public async Task CreatePersonnelGroupAsync(PersonnelGroupCreateInput input) { _logger.LogInformation("开始创建人员组:{GroupName}", input.GroupName); // 业务验证:检查人员组名称是否已存在 var exists = await _personnelGroupRepository.ExistsGroupNameAsync(input.GroupName); if (exists) { _logger.LogWarning("人员组名称已存在:{GroupName}", input.GroupName); throw new Exception($"人员组名称已存在:{input.GroupName}"); } // 业务验证:人员组配置合法性检查 ValidatePersonnelGroupConfiguration(input); var entity = new PersonnelGroupEntity { GroupName = input.GroupName, Description = input.Description, GroupType = (int)input.GroupType, IsEnabled = input.IsEnabled, StaticPersonnelIds = JsonSerializer.Serialize(input.StaticPersonnelIds), DynamicDepartmentIds = JsonSerializer.Serialize(input.DynamicDepartmentIds), DynamicPositions = JsonSerializer.Serialize(input.DynamicPositions), OnlyActivePersonnel = input.OnlyActivePersonnel, ExcludePersonnelIds = JsonSerializer.Serialize(input.ExcludePersonnelIds), LastModifiedTime = DateTime.Now }; entity = await _personnelGroupRepository.InsertAsync(entity); _logger.LogInformation("成功创建人员组,ID:{Id},名称:{GroupName}", entity.Id, entity.GroupName); return entity.Id; } /// /// 更新人员组 /// [HttpPut] public async Task UpdatePersonnelGroupAsync(PersonnelGroupUpdateInput input) { _logger.LogInformation("开始更新人员组,ID:{Id}", input.Id); var entity = await _personnelGroupRepository.GetAsync(input.Id); if (entity == null) { _logger.LogWarning("人员组不存在,ID:{Id}", input.Id); throw new Exception($"人员组不存在,ID:{input.Id}"); } // 业务验证:检查人员组名称是否已存在(排除自己) var exists = await _personnelGroupRepository.ExistsGroupNameAsync(input.GroupName, input.Id); if (exists) { _logger.LogWarning("人员组名称已存在:{GroupName}", input.GroupName); throw new Exception($"人员组名称已存在:{input.GroupName}"); } // 业务验证:人员组配置合法性检查 ValidatePersonnelGroupConfiguration(input); // 更新实体属性 entity.GroupName = input.GroupName; entity.Description = input.Description; entity.GroupType = (int)input.GroupType; entity.IsEnabled = input.IsEnabled; entity.StaticPersonnelIds = JsonSerializer.Serialize(input.StaticPersonnelIds); entity.DynamicDepartmentIds = JsonSerializer.Serialize(input.DynamicDepartmentIds); entity.DynamicPositions = JsonSerializer.Serialize(input.DynamicPositions); entity.OnlyActivePersonnel = input.OnlyActivePersonnel; entity.ExcludePersonnelIds = JsonSerializer.Serialize(input.ExcludePersonnelIds); entity.LastModifiedTime = DateTime.Now; await _personnelGroupRepository.UpdateAsync(entity); _logger.LogInformation("成功更新人员组,ID:{Id},名称:{GroupName}", entity.Id, entity.GroupName); } /// /// 删除人员组 /// [HttpDelete] public async Task DeletePersonnelGroupAsync(long id) { _logger.LogInformation("开始删除人员组,ID:{Id}", id); var entity = await _personnelGroupRepository.GetAsync(id); if (entity == null) { _logger.LogWarning("人员组不存在,ID:{Id}", id); throw new Exception($"人员组不存在,ID:{id}"); } // 业务验证:检查是否存在关联的通知设置 var hasNotificationSettings = await _notificationSettingRepository.Select .Where(a => a.PersonnelGroupId == id) .AnyAsync(); if (hasNotificationSettings) { _logger.LogWarning("人员组存在关联的通知设置,无法删除,ID:{Id}", id); throw new Exception($"人员组存在关联的通知设置,无法删除,ID:{id}"); } await _personnelGroupRepository.DeleteAsync(id); _logger.LogInformation("成功删除人员组,ID:{Id},名称:{GroupName}", id, entity.GroupName); } /// /// 获取人员组的实际人员列表 /// 根据决策点4:混合人员组,支持静态+动态规则 /// [HttpGet] public async Task> GetPersonnelGroupMembersAsync(long personnelGroupId) { _logger.LogInformation("开始获取人员组实际人员列表,人员组ID:{PersonnelGroupId}", personnelGroupId); var personnelGroup = await _personnelGroupRepository.GetAsync(personnelGroupId); if (personnelGroup == null) { _logger.LogWarning("人员组不存在,ID:{PersonnelGroupId}", personnelGroupId); throw new Exception($"人员组不存在,ID:{personnelGroupId}"); } var allPersonnelIds = new HashSet(); // 获取静态人员 var staticPersonnelIds = JsonSerializer.Deserialize>(personnelGroup.StaticPersonnelIds); if (staticPersonnelIds?.Any() == true) { foreach (var personnelId in staticPersonnelIds) { allPersonnelIds.Add(personnelId); } _logger.LogDebug("添加静态人员:{Count}个", staticPersonnelIds.Count); } // 获取动态人员(根据部门和职位规则) var groupType = (PersonnelGroupTypeEnum)personnelGroup.GroupType; if (groupType.HasFlag(PersonnelGroupTypeEnum.DynamicByDepartment) || groupType.HasFlag(PersonnelGroupTypeEnum.Mixed)) { var dynamicPersonnelIds = await GetDynamicPersonnelIds(personnelGroup); foreach (var personnelId in dynamicPersonnelIds) { allPersonnelIds.Add(personnelId); } _logger.LogDebug("添加动态人员:{Count}个", dynamicPersonnelIds.Count); } // 排除指定人员 var excludePersonnelIds = JsonSerializer.Deserialize>(personnelGroup.ExcludePersonnelIds); if (excludePersonnelIds?.Any() == true) { foreach (var excludeId in excludePersonnelIds) { allPersonnelIds.Remove(excludeId); } _logger.LogDebug("排除人员:{Count}个", excludePersonnelIds.Count); } var result = allPersonnelIds.ToList(); _logger.LogInformation("成功获取人员组实际人员列表,人员组ID:{PersonnelGroupId},人员总数:{Count}", personnelGroupId, result.Count); return result; } #endregion #region 通知发送 /// /// 发送通知 /// 决策点1:支持邮件和系统消息通知 /// [HttpPost] public async Task SendNotificationAsync(SendNotificationInput input) { _logger.LogInformation("开始发送通知,通知方式:{NotificationType},接收人数:{Count}", input.NotificationType, input.RecipientPersonnelIds.Count); var output = new SendNotificationOutput { TotalCount = input.RecipientPersonnelIds.Count, SendTime = DateTime.Now }; // 获取用户信息 var userInfoDict = await GetUserInfoDictionary(input.RecipientPersonnelIds); // 逐个发送通知 foreach (var personnelId in input.RecipientPersonnelIds) { var sendResult = new NotificationSendResult { RecipientPersonnelId = personnelId, NotificationType = input.NotificationType }; try { if (userInfoDict.TryGetValue(personnelId, out var userInfo)) { sendResult.RecipientPersonnelName = userInfo.Name; sendResult.RecipientEmail = userInfo.Email; // 创建通知历史记录 var historyId = await CreateNotificationHistory(input.SettingId, input, personnelId, userInfo); sendResult.NotificationHistoryId = historyId; // 发送通知 bool success = await SendSingleNotification(input, userInfo); if (success) { sendResult.SendStatus = NotificationStatusEnum.Success; sendResult.SendResult = "发送成功"; sendResult.SendTime = DateTime.Now; output.SuccessCount++; // 更新历史记录状态 await UpdateNotificationHistoryStatus(historyId, NotificationStatusEnum.Success, "发送成功", null); } else { sendResult.SendStatus = NotificationStatusEnum.Failed; sendResult.ErrorMessage = "发送失败"; output.FailedCount++; // 更新历史记录状态 await UpdateNotificationHistoryStatus(historyId, NotificationStatusEnum.Failed, null, "发送失败"); } } else { sendResult.SendStatus = NotificationStatusEnum.Failed; sendResult.ErrorMessage = "用户不存在"; output.FailedCount++; _logger.LogWarning("用户不存在,人员ID:{PersonnelId}", personnelId); } } catch (Exception ex) { sendResult.SendStatus = NotificationStatusEnum.Failed; sendResult.ErrorMessage = ex.Message; output.FailedCount++; _logger.LogError(ex, "发送通知异常,人员ID:{PersonnelId}", personnelId); // 更新历史记录状态 if (sendResult.NotificationHistoryId > 0) { await UpdateNotificationHistoryStatus(sendResult.NotificationHistoryId, NotificationStatusEnum.Failed, null, ex.Message); } } output.SendResults.Add(sendResult); output.NotificationHistoryIds.Add(sendResult.NotificationHistoryId); } output.IsAllSuccess = output.FailedCount == 0; if (output.FailedCount > 0) { output.OverallErrorMessage = $"部分发送失败,失败数量:{output.FailedCount}"; } _logger.LogInformation("完成发送通知,总数:{Total},成功:{Success},失败:{Failed}", output.TotalCount, output.SuccessCount, output.FailedCount); return output; } /// /// 发送群组通知(邮件发送一封给所有人,系统消息仍然单独发送) /// [HttpPost] public async Task SendGroupNotificationAsync(SendNotificationInput input) { _logger.LogInformation("开始发送群组通知,通知方式:{NotificationType},接收人数:{Count}", input.NotificationType, input.RecipientPersonnelIds.Count); var output = new SendNotificationOutput { TotalCount = input.RecipientPersonnelIds.Count, SendTime = DateTime.Now }; // 获取用户信息 var userInfoDict = await GetUserInfoDictionary(input.RecipientPersonnelIds); // 过滤出有效的用户信息 var validUsers = new List<(long personnelId, UserInfo userInfo)>(); foreach (var personnelId in input.RecipientPersonnelIds) { if (userInfoDict.TryGetValue(personnelId, out var userInfo)) { validUsers.Add((personnelId, userInfo)); } else { // 处理无效用户 var sendResult = new NotificationSendResult { RecipientPersonnelId = personnelId, NotificationType = input.NotificationType, SendStatus = NotificationStatusEnum.Failed, ErrorMessage = "用户不存在" }; output.SendResults.Add(sendResult); output.FailedCount++; _logger.LogWarning("用户不存在,人员ID:{PersonnelId}", personnelId); } } if (!validUsers.Any()) { output.IsAllSuccess = false; output.OverallErrorMessage = "没有有效的接收人"; return output; } try { if (input.NotificationType == NotificationTypeEnum.Email) { // 邮件通知:发送一封邮件给所有人 await SendGroupEmailNotification(input, validUsers, output); } else if (input.NotificationType == NotificationTypeEnum.SystemMessage) { // 系统消息:仍然逐个发送 await SendIndividualSystemMessages(input, validUsers, output); } } catch (Exception ex) { _logger.LogError(ex, "发送群组通知异常"); // 将所有结果标记为失败 foreach (var (personnelId, userInfo) in validUsers) { if (!output.SendResults.Any(r => r.RecipientPersonnelId == personnelId)) { var sendResult = new NotificationSendResult { RecipientPersonnelId = personnelId, RecipientPersonnelName = userInfo.Name, RecipientEmail = userInfo.Email, NotificationType = input.NotificationType, SendStatus = NotificationStatusEnum.Failed, ErrorMessage = ex.Message }; output.SendResults.Add(sendResult); output.FailedCount++; } } } output.IsAllSuccess = output.FailedCount == 0; if (output.FailedCount > 0) { output.OverallErrorMessage = $"部分发送失败,失败数量:{output.FailedCount}"; } _logger.LogInformation("完成发送群组通知,总数:{Total},成功:{Success},失败:{Failed}", output.TotalCount, output.SuccessCount, output.FailedCount); return output; } /// /// 批量发送通知 /// [HttpPost] public async Task> BatchSendNotificationAsync(List inputs) { _logger.LogInformation("开始批量发送通知,批次数量:{Count}", inputs.Count); var outputs = new List(); foreach (var input in inputs) { try { var output = await SendNotificationAsync(input); outputs.Add(output); } catch (Exception ex) { _logger.LogError(ex, "批量发送通知异常,通知类型:{NotificationType}", input.NotificationType); var errorOutput = new SendNotificationOutput { TotalCount = input.RecipientPersonnelIds.Count, FailedCount = input.RecipientPersonnelIds.Count, IsAllSuccess = false, OverallErrorMessage = ex.Message, SendTime = DateTime.Now }; outputs.Add(errorOutput); } } var totalSuccess = outputs.Sum(o => o.SuccessCount); var totalFailed = outputs.Sum(o => o.FailedCount); _logger.LogInformation("完成批量发送通知,批次数:{BatchCount},总成功:{Success},总失败:{Failed}", outputs.Count, totalSuccess, totalFailed); return outputs; } /// /// 根据通知设置发送通知 /// [HttpPost] public async Task SendNotificationBySettingAsync( long notificationSettingId, string businessType, long? businessId = null, string businessData = "", Dictionary templateVariables = null) { _logger.LogInformation("开始根据通知设置发送通知,设置ID:{SettingId},业务类型:{BusinessType}", notificationSettingId, businessType); // 获取通知设置 var notificationSetting = await _notificationSettingRepository.Select .WhereDynamic(notificationSettingId) .Include(a => a.PersonnelGroup) .ToOneAsync(); if (notificationSetting == null) { _logger.LogWarning("通知设置不存在,ID:{SettingId}", notificationSettingId); throw new Exception($"通知设置不存在,ID:{notificationSettingId}"); } if (!notificationSetting.IsEnabled) { _logger.LogWarning("通知设置已禁用,ID:{SettingId}", notificationSettingId); throw new Exception($"通知设置已禁用,ID:{notificationSettingId}"); } return new SendNotificationOutput { IsAllSuccess = true, OverallErrorMessage = "功能开发中", SendTime = DateTime.Now }; } #endregion #region 通知模板引擎(决策点7) /// /// 验证模板语法 /// [HttpPost] public async Task ValidateTemplateAsync(string template) { try { var result = await _templateService.ValidateTemplateAsync(new ValidateTemplateInput { Template = template }); return result.Success; } catch (Exception ex) { _logger.LogError(ex, "验证模板语法异常"); return false; } } #endregion #region 通知历史记录(决策点8) /// /// 查询通知历史记录 /// [HttpGet] public async Task GetNotificationHistoryAsync(long id) { _logger.LogInformation("开始查询通知历史记录,ID:{Id}", id); var entity = await _notificationHistoryRepository.Select .WhereDynamic(id) .Include(a => a.NotificationSetting) .ToOneAsync(); if (entity == null) { _logger.LogWarning("通知历史记录不存在,ID:{Id}", id); throw new Exception($"通知历史记录不存在,ID:{id}"); } var output = MapToNotificationHistoryOutput(entity); _logger.LogInformation("成功查询通知历史记录,ID:{Id}", id); return output; } /// /// 查询通知历史记录分页 /// [HttpPost] public async Task> GetNotificationHistoryPageAsync(PageInput input) { _logger.LogInformation("开始查询通知历史记录分页,页码:{Current},页大小:{Size}", input.CurrentPage, input.PageSize); var query = _notificationHistoryRepository.Select .Include(a => a.NotificationSetting); // 根据搜索条件过滤 if (input.Filter != null) { if (input.Filter.NotificationSettingId.HasValue && input.Filter.NotificationSettingId.Value > 0) { query = query.Where(a => a.NotificationSettingId == input.Filter.NotificationSettingId.Value); } if (input.Filter.RecipientPersonnelId.HasValue && input.Filter.RecipientPersonnelId.Value > 0) { query = query.Where(a => a.RecipientPersonnelId == input.Filter.RecipientPersonnelId.Value); } if (!string.IsNullOrEmpty(input.Filter.RecipientPersonnelName)) { query = query.Where(a => a.RecipientPersonnelName.Contains(input.Filter.RecipientPersonnelName)); } if (input.Filter.NotificationType.HasValue) { query = query.Where(a => a.NotificationType == (int)input.Filter.NotificationType.Value); } if (input.Filter.SendStatus.HasValue) { query = query.Where(a => a.SendStatus == (int)input.Filter.SendStatus.Value); } if (!string.IsNullOrEmpty(input.Filter.BusinessType)) { query = query.Where(a => a.BusinessType.Contains(input.Filter.BusinessType)); } if (input.Filter.StartTime.HasValue) { query = query.Where(a => a.CreatedTime >= input.Filter.StartTime.Value); } if (input.Filter.EndTime.HasValue) { query = query.Where(a => a.CreatedTime <= input.Filter.EndTime.Value); } } var totalCount = await query.CountAsync(); var entities = await query .OrderByDescending(a => a.CreatedTime) .Page(input.CurrentPage, input.PageSize) .ToListAsync(); var outputs = entities.Select(MapToNotificationHistoryOutput).ToList(); _logger.LogInformation("成功查询通知历史记录分页,总数:{Total},当前页数据:{Count}", totalCount, outputs.Count); return new PageOutput { List = outputs, Total = totalCount }; } /// /// 查询当前用户通知历史记录 /// [HttpPost] public async Task> GetNotificationHistoryByUserPageAsync() { var query = _notificationHistoryRepository.Select .Include(a => a.NotificationSetting); query = query.Where(a => a.RecipientPersonnelId == User.Id && a.NotificationType == 2 && a.IsDeleted == false); var totalCount = await query.CountAsync(); var entities = await query .OrderByDescending(a => a.CreatedTime) .Page(1, 10) .ToListAsync(); var outputs = entities.Select(MapToNotificationHistoryOutput).ToList(); return new PageOutput { List = outputs, Total = totalCount }; } /// /// 重试失败的通知 /// [HttpPost] public async Task RetryFailedNotificationAsync(long notificationHistoryId) { _logger.LogInformation("开始重试失败的通知,历史记录ID:{HistoryId}", notificationHistoryId); // 简化实现 await Task.Delay(100); _logger.LogInformation("完成重试失败的通知,历史记录ID:{HistoryId}", notificationHistoryId); return true; } /// /// 批量重试失败的通知 /// [HttpPost] public async Task BatchRetryFailedNotificationsAsync(List notificationHistoryIds) { _logger.LogInformation("开始批量重试失败的通知,数量:{Count}", notificationHistoryIds.Count); int successCount = 0; foreach (var historyId in notificationHistoryIds) { try { bool success = await RetryFailedNotificationAsync(historyId); if (success) successCount++; } catch (Exception ex) { _logger.LogError(ex, "批量重试失败通知异常,历史记录ID:{HistoryId}", historyId); } } _logger.LogInformation("完成批量重试失败的通知,总数:{Total},成功:{Success}", notificationHistoryIds.Count, successCount); return successCount; } /// /// 取消通知 /// [HttpPost] public async Task CancelNotificationAsync(long notificationHistoryId) { _logger.LogInformation("开始取消通知,历史记录ID:{HistoryId}", notificationHistoryId); try { var history = await _notificationHistoryRepository.GetAsync(notificationHistoryId); if (history == null) { _logger.LogWarning("通知历史记录不存在,ID:{HistoryId}", notificationHistoryId); return false; } // 只有待发送状态的通知才能取消 if (history.SendStatus != (int)NotificationStatusEnum.Pending) { _logger.LogWarning("只有待发送状态的通知才能取消,当前状态:{Status},ID:{HistoryId}", (NotificationStatusEnum)history.SendStatus, notificationHistoryId); return false; } history.SendStatus = (int)NotificationStatusEnum.Cancelled; history.SendResult = "通知已取消"; history.ActualSendTime = DateTime.Now; await _notificationHistoryRepository.UpdateAsync(history); _logger.LogInformation("成功取消通知,历史记录ID:{HistoryId}", notificationHistoryId); return true; } catch (Exception ex) { _logger.LogError(ex, "取消通知异常,历史记录ID:{HistoryId}", notificationHistoryId); return false; } } /// /// 批量取消通知 /// [HttpPost] public async Task BatchCancelNotificationsAsync(List notificationHistoryIds) { _logger.LogInformation("开始批量取消通知,数量:{Count}", notificationHistoryIds.Count); int successCount = 0; foreach (var historyId in notificationHistoryIds) { try { bool success = await CancelNotificationAsync(historyId); if (success) successCount++; } catch (Exception ex) { _logger.LogError(ex, "批量取消通知异常,历史记录ID:{HistoryId}", historyId); } } _logger.LogInformation("完成批量取消通知,总数:{Total},成功:{Success}", notificationHistoryIds.Count, successCount); return successCount; } #endregion #region 定时任务管理(决策点6) /// /// 创建定时通知任务 /// [HttpPost] public async Task CreateScheduledNotificationTaskAsync( long notificationSettingId, string businessType, long? businessId = null, string businessData = "", DateTime? plannedExecutionTime = null, string cronExpression = "") { _logger.LogInformation("开始创建定时通知任务,通知设置ID:{SettingId},业务类型:{BusinessType}", notificationSettingId, businessType); // 简化实现,返回模拟任务ID var taskId = DateTime.Now.Ticks; _logger.LogInformation("成功创建定时通知任务,任务ID:{TaskId}", taskId); return taskId; } /// /// 执行定时通知任务 /// [HttpPost] public async Task ExecuteScheduledNotificationTaskAsync(long taskId) { _logger.LogInformation("开始执行定时通知任务,任务ID:{TaskId}", taskId); await Task.Delay(100); _logger.LogInformation("成功执行定时通知任务,任务ID:{TaskId}", taskId); return true; } /// /// 获取待执行的定时任务列表 /// [HttpGet] public async Task> GetPendingNotificationTasksAsync() { await Task.CompletedTask; return new List(); } /// /// 启用/禁用定时任务 /// [HttpPut] public async Task ToggleNotificationTaskAsync(long taskId, bool enabled) { _logger.LogInformation("开始{Action}定时任务,任务ID:{TaskId}", enabled ? "启用" : "禁用", taskId); await Task.CompletedTask; _logger.LogInformation("成功{Action}定时任务,任务ID:{TaskId}", enabled ? "启用" : "禁用", taskId); } #endregion #region 通知统计 /// /// 获取通知发送统计信息 /// [HttpPost] public async Task> GetNotificationStatisticsAsync( DateTime startTime, DateTime endTime, long? notificationSettingId = null) { _logger.LogInformation("开始获取通知发送统计信息,时间范围:{StartTime} - {EndTime}", startTime, endTime); var statistics = new Dictionary { ["TotalCount"] = 0, ["SuccessCount"] = 0, ["FailedCount"] = 0, ["PendingCount"] = 0, ["SuccessRate"] = 0.0, ["EmailCount"] = 0, ["SystemMessageCount"] = 0, ["StatisticsTime"] = DateTime.Now }; _logger.LogInformation("成功获取通知发送统计信息"); return statistics; } #endregion #region 私有辅助方法 /// /// 用户信息DTO类 /// private class UserInfo { public long Id { get; set; } public string Name { get; set; } = ""; public string Email { get; set; } = ""; } /// /// 获取用户信息字典 /// private async Task> GetUserInfoDictionary(List personnelIds) { var userInfoDict = new Dictionary(); try { var cacheKey = CacheKeys.UserListKey; var cacheOrgUsers = Cache.Get>(cacheKey); if (cacheOrgUsers == null || (cacheOrgUsers != null && cacheOrgUsers.Count == 0)) { cacheOrgUsers = await _userService.GetUserList(); Cache.Set(cacheKey, cacheOrgUsers, new TimeSpan(8, 0, 0)); } foreach (var personnelId in personnelIds) { var cu = cacheOrgUsers.Where(x => x.Id == personnelId).FirstOrDefault(); userInfoDict[personnelId] = new UserInfo { Id = personnelId, Name = cu?.Name, Email = cu?.Email }; } } catch (Exception ex) { _logger.LogError(ex, "获取用户信息异常,人员ID列表:{PersonnelIds}", string.Join(",", personnelIds)); } return userInfoDict; } /// /// 发送单个通知 /// private async Task SendSingleNotification(SendNotificationInput input, UserInfo userInfo) { try { if (input.NotificationType == NotificationTypeEnum.Email) { return await SendEmailNotification(userInfo.Email, input.Title, input.Content); } else if (input.NotificationType == NotificationTypeEnum.SystemMessage) { return true; } return false; } catch (Exception ex) { _logger.LogError(ex, "发送单个通知异常,人员ID:{PersonnelId},通知方式:{NotificationType}", userInfo.Id, input.NotificationType); return false; } } /// /// 发送群组邮件通知(一封邮件发送给所有人) /// private async Task SendGroupEmailNotification(SendNotificationInput input, List<(long personnelId, UserInfo userInfo)> validUsers, SendNotificationOutput output) { try { // 收集所有有效的邮箱地址 var emailAddresses = validUsers .Where(u => !string.IsNullOrWhiteSpace(u.userInfo.Email)) .Select(u => u.userInfo.Email) .Distinct() .ToList(); if (!emailAddresses.Any()) { // 没有有效邮箱,标记所有用户为失败 foreach (var (personnelId, userInfo) in validUsers) { var sendResult = new NotificationSendResult { RecipientPersonnelId = personnelId, RecipientPersonnelName = userInfo.Name, RecipientEmail = userInfo.Email, NotificationType = input.NotificationType, SendStatus = NotificationStatusEnum.Failed, ErrorMessage = "邮箱地址无效" }; output.SendResults.Add(sendResult); output.FailedCount++; } return; } // 创建批量邮件发送请求 var batchEmailInput = new BatchSendEmailInput { Recipients = emailAddresses, Subject = input.Title, Content = input.Content, IsHtml = true }; // 发送批量邮件 var emailResult = await _emailNotificationService.BatchSendEmailAsync(batchEmailInput); var sendTime = DateTime.Now; // 为每个用户创建通知历史记录和发送结果 foreach (var (personnelId, userInfo) in validUsers) { try { // 创建通知历史记录 var historyId = await CreateNotificationHistory(input.SettingId, input, personnelId, userInfo); // 判断该用户的邮件是否发送成功 var userEmailResult = emailResult.Results.FirstOrDefault(r => r.RecipientEmail == userInfo.Email); var isSuccess = userEmailResult?.IsSuccess == true; var sendResult = new NotificationSendResult { RecipientPersonnelId = personnelId, RecipientPersonnelName = userInfo.Name, RecipientEmail = userInfo.Email, NotificationType = input.NotificationType, NotificationHistoryId = historyId, SendTime = sendTime }; if (isSuccess) { sendResult.SendStatus = NotificationStatusEnum.Success; sendResult.SendResult = "群组邮件发送成功"; output.SuccessCount++; // 更新历史记录状态 await UpdateNotificationHistoryStatus(historyId, NotificationStatusEnum.Success, "群组邮件发送成功", null); } else { sendResult.SendStatus = NotificationStatusEnum.Failed; sendResult.ErrorMessage = userEmailResult?.ErrorMessage ?? "群组邮件发送失败"; output.FailedCount++; // 更新历史记录状态 await UpdateNotificationHistoryStatus(historyId, NotificationStatusEnum.Failed, null, sendResult.ErrorMessage); } output.SendResults.Add(sendResult); output.NotificationHistoryIds.Add(historyId); } catch (Exception ex) { _logger.LogError(ex, "处理群组邮件发送结果异常,人员ID:{PersonnelId}", personnelId); var sendResult = new NotificationSendResult { RecipientPersonnelId = personnelId, RecipientPersonnelName = userInfo.Name, RecipientEmail = userInfo.Email, NotificationType = input.NotificationType, SendStatus = NotificationStatusEnum.Failed, ErrorMessage = ex.Message }; output.SendResults.Add(sendResult); output.FailedCount++; } } _logger.LogInformation("群组邮件发送完成,邮箱数量:{EmailCount},用户数量:{UserCount}", emailAddresses.Count, validUsers.Count); } catch (Exception ex) { _logger.LogError(ex, "发送群组邮件异常"); throw; } } /// /// 发送个人系统消息(逐个发送) /// private async Task SendIndividualSystemMessages(SendNotificationInput input, List<(long personnelId, UserInfo userInfo)> validUsers, SendNotificationOutput output) { try { foreach (var (personnelId, userInfo) in validUsers) { var sendResult = new NotificationSendResult { RecipientPersonnelId = personnelId, RecipientPersonnelName = userInfo.Name, RecipientEmail = userInfo.Email, NotificationType = input.NotificationType }; try { // 创建通知历史记录 var historyId = await CreateNotificationHistory(input.SettingId, input, personnelId, userInfo); sendResult.NotificationHistoryId = historyId; // 发送系统消息 var success = await SendSystemMessageNotification(personnelId, input.Title, input.Content); if (success) { sendResult.SendStatus = NotificationStatusEnum.Success; sendResult.SendResult = "系统消息发送成功"; sendResult.SendTime = DateTime.Now; output.SuccessCount++; // 更新历史记录状态 await UpdateNotificationHistoryStatus(historyId, NotificationStatusEnum.Success, "系统消息发送成功", null); } else { sendResult.SendStatus = NotificationStatusEnum.Failed; sendResult.ErrorMessage = "系统消息发送失败"; output.FailedCount++; // 更新历史记录状态 await UpdateNotificationHistoryStatus(historyId, NotificationStatusEnum.Failed, null, "系统消息发送失败"); } } catch (Exception ex) { sendResult.SendStatus = NotificationStatusEnum.Failed; sendResult.ErrorMessage = ex.Message; output.FailedCount++; _logger.LogError(ex, "发送系统消息异常,人员ID:{PersonnelId}", personnelId); // 更新历史记录状态 if (sendResult.NotificationHistoryId > 0) { await UpdateNotificationHistoryStatus(sendResult.NotificationHistoryId, NotificationStatusEnum.Failed, null, ex.Message); } } output.SendResults.Add(sendResult); output.NotificationHistoryIds.Add(sendResult.NotificationHistoryId); } _logger.LogInformation("个人系统消息发送完成,用户数量:{UserCount}", validUsers.Count); } catch (Exception ex) { _logger.LogError(ex, "发送个人系统消息异常"); throw; } } /// /// 发送邮件通知 /// private async Task SendEmailNotification(string email, string title, string content) { try { var sendEmailInput = new SendEmailInput { RecipientEmail = email, Subject = title, Content = content }; var result = await _emailNotificationService.SendEmailAsync(sendEmailInput); return result.IsSuccess; } catch (Exception ex) { _logger.LogError(ex, "发送邮件通知异常,邮箱:{Email}", email); return false; } } /// /// 发送系统消息通知 /// private async Task SendSystemMessageNotification(long personnelId, string title, string content) { try { var sendMessageInput = new SendSystemMessageInput { RecipientPersonnelId = personnelId, Title = title, Content = content }; var result = await _systemMessageService.SendSystemMessageAsync(sendMessageInput); return result.Success; } catch (Exception ex) { _logger.LogError(ex, "发送系统消息异常,人员ID:{PersonnelId}", personnelId); return false; } } /// /// 创建通知历史记录 /// private async Task CreateNotificationHistory(long? notificationSettingId, SendNotificationInput input, long personnelId, UserInfo userInfo) { try { var history = new NotificationHistoryEntity { NotificationSettingId = notificationSettingId ?? 0, RecipientPersonnelId = personnelId, RecipientPersonnelName = userInfo.Name, RecipientEmail = userInfo.Email, NotificationType = (int)input.NotificationType, NotificationTitle = input.Title, NotificationContent = input.Content, PlannedSendTime = input.PlannedSendTime ?? DateTime.Now, SendStatus = (int)NotificationStatusEnum.Pending, MaxRetryCount = input.MaxRetryCount, BusinessType = input.BusinessType, BusinessId = input.BusinessId, BusinessData = input.BusinessData }; history = await _notificationHistoryRepository.InsertAsync(history); return history.Id; } catch (Exception ex) { _logger.LogError(ex, "创建通知历史记录异常,人员ID:{PersonnelId}", personnelId); return 0; } } /// /// 更新通知历史记录状态 /// private async Task UpdateNotificationHistoryStatus(long historyId, NotificationStatusEnum status, string sendResult, string errorMessage) { try { if (historyId <= 0) return; var history = await _notificationHistoryRepository.GetAsync(historyId); if (history != null) { history.SendStatus = (int)status; history.SendResult = sendResult ?? ""; history.ErrorMessage = errorMessage ?? ""; if (status == NotificationStatusEnum.Success) { history.ActualSendTime = DateTime.Now; } await _notificationHistoryRepository.UpdateAsync(history); } } catch (Exception ex) { _logger.LogError(ex, "更新通知历史记录状态异常,历史记录ID:{HistoryId}", historyId); } } /// /// 映射到NotificationSettingOutput /// private NotificationSettingOutput MapToNotificationSettingOutput(NotificationSettingEntity entity) { return new NotificationSettingOutput { Id = entity.Id, NotificationName = entity.NotificationName, Description = entity.Description, IsEnabled = entity.IsEnabled, IsEmailEnabled = entity.IsEmailEnabled, IsSystemMessageEnabled = entity.IsSystemMessageEnabled, StartTime = entity.StartTime, EndTime = entity.EndTime, FrequencyType = (NotificationFrequencyEnum)entity.FrequencyType, IntervalMinutes = entity.IntervalMinutes, PersonnelGroupId = entity.PersonnelGroupId, PersonnelGroupName = entity.PersonnelGroup?.GroupName ?? "", EmailSubjectTemplate = entity.EmailSubjectTemplate, EmailContentTemplate = entity.EmailContentTemplate, SystemMessageTitleTemplate = entity.SystemMessageTitleTemplate, SystemMessageContentTemplate = entity.SystemMessageContentTemplate, TriggerConditions = entity.TriggerConditions, CreatedTime = entity.CreatedTime ?? DateTime.MinValue, ModifiedTime = entity.ModifiedTime, LastModifiedTime = entity.LastModifiedTime }; } /// /// 映射到PersonnelGroupOutput /// private PersonnelGroupOutput MapToPersonnelGroupOutput(PersonnelGroupEntity entity) { var staticPersonnelIds = JsonSerializer.Deserialize>(entity.StaticPersonnelIds) ?? new List(); var dynamicDepartmentIds = JsonSerializer.Deserialize>(entity.DynamicDepartmentIds) ?? new List(); var dynamicPositions = JsonSerializer.Deserialize>(entity.DynamicPositions) ?? new List(); var excludePersonnelIds = JsonSerializer.Deserialize>(entity.ExcludePersonnelIds) ?? new List(); return new PersonnelGroupOutput { Id = entity.Id, GroupName = entity.GroupName, Description = entity.Description, GroupType = (PersonnelGroupTypeEnum)entity.GroupType, IsEnabled = entity.IsEnabled, StaticPersonnelIds = staticPersonnelIds, DynamicDepartmentIds = dynamicDepartmentIds, DynamicPositions = dynamicPositions, OnlyActivePersonnel = entity.OnlyActivePersonnel, ExcludePersonnelIds = excludePersonnelIds, CreatedTime = entity.CreatedTime ?? DateTime.MinValue, ModifiedTime = entity.ModifiedTime, LastModifiedTime = entity.LastModifiedTime }; } /// /// 映射到NotificationHistoryOutput /// private NotificationHistoryOutput MapToNotificationHistoryOutput(NotificationHistoryEntity entity) { return new NotificationHistoryOutput { Id = entity.Id, NotificationSettingId = entity.NotificationSettingId, NotificationSettingName = entity.NotificationSetting?.NotificationName ?? "", RecipientPersonnelId = entity.RecipientPersonnelId, RecipientPersonnelName = entity.RecipientPersonnelName, RecipientEmail = entity.RecipientEmail, NotificationType = (NotificationTypeEnum)entity.NotificationType, NotificationTitle = entity.NotificationTitle, NotificationContent = entity.NotificationContent, PlannedSendTime = entity.PlannedSendTime, ActualSendTime = entity.ActualSendTime, SendStatus = (NotificationStatusEnum)entity.SendStatus, SendResult = entity.SendResult, ErrorMessage = entity.ErrorMessage, RetryCount = entity.RetryCount, MaxRetryCount = entity.MaxRetryCount, NextRetryTime = entity.NextRetryTime, BusinessType = entity.BusinessType, BusinessId = entity.BusinessId, BusinessData = entity.BusinessData, CreatedTime = entity.CreatedTime ?? DateTime.MinValue }; } #endregion #region 私有辅助方法验证 /// /// 验证时间配置合法性 /// private void ValidateTimeConfiguration(string startTime, string endTime) { if (!string.IsNullOrEmpty(startTime) && !string.IsNullOrEmpty(endTime)) { if (TimeOnly.TryParse(startTime, out var start) && TimeOnly.TryParse(endTime, out var end)) { if (start >= end) { throw new Exception("开始时间不能大于等于结束时间"); } } } } /// /// 验证频次配置合法性 /// private void ValidateFrequencyConfiguration(NotificationFrequencyEnum frequencyType, int? intervalMinutes) { if (frequencyType == NotificationFrequencyEnum.FixedInterval && (!intervalMinutes.HasValue || intervalMinutes.Value <= 0)) { throw new Exception("间隔频次时,间隔分钟数必须大于0"); } } /// /// 验证模板配置合法性 /// private async Task ValidateTemplateConfiguration(dynamic input) { if (!string.IsNullOrEmpty(input.EmailSubjectTemplate)) { var result = await _templateService.ValidateTemplateAsync(new ValidateTemplateInput { Template = input.EmailSubjectTemplate }); if (!result.Success) { throw new Exception($"邮件主题模板格式错误:{result.ErrorMessage}"); } } } /// /// 验证人员组配置合法性 /// private void ValidatePersonnelGroupConfiguration(PersonnelGroupCreateInput input) { var groupType = (PersonnelGroupTypeEnum)input.GroupType; if (groupType == PersonnelGroupTypeEnum.Static && (input.StaticPersonnelIds == null || !input.StaticPersonnelIds.Any())) { throw new Exception("静态人员组必须配置人员"); } if ((groupType == PersonnelGroupTypeEnum.DynamicByDepartment || groupType == PersonnelGroupTypeEnum.Mixed) && (input.DynamicDepartmentIds == null || !input.DynamicDepartmentIds.Any())) { throw new Exception("动态部门人员组必须配置部门"); } } /// /// 获取动态人员ID列表 /// private async Task> GetDynamicPersonnelIds(PersonnelGroupEntity personnelGroup) { var orgUserIds = new List(); var dynamicDepartmentIds = JsonSerializer.Deserialize>(personnelGroup.DynamicDepartmentIds); foreach (var orgId in dynamicDepartmentIds) { var cacheKey = CacheKeys.GetDynamicDepartmentKey(orgId); var cacheOrgUserIds = Cache.Get>(cacheKey); if (cacheOrgUserIds != null && cacheOrgUserIds.Any()) { orgUserIds.AddRange(cacheOrgUserIds.Select(m => m.Id).ToList()); } else { var orgUsers = await _userService.GetOrgUserList(orgId); Cache.Set(cacheKey, orgUsers, new TimeSpan(8, 0, 0)); orgUserIds.AddRange(orgUsers.Select(m => m.Id).ToList()); } } return orgUserIds; } #endregion }