Asoka.Wang 2b3f9acdce 123
2025-09-22 19:09:47 +08:00

1805 lines
68 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
/// <summary>
/// 通知服务
/// </summary>
[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<NotificationService> _logger;
public NotificationService(
NotificationSettingRepository notificationSettingRepository,
PersonnelGroupRepository personnelGroupRepository,
NotificationHistoryRepository notificationHistoryRepository,
IEmailNotificationService emailNotificationService,
ISystemMessageService systemMessageService,
INotificationTemplateService templateService,
IUserGrpcService userService,
ILogger<NotificationService> logger)
{
_notificationSettingRepository = notificationSettingRepository;
_personnelGroupRepository = personnelGroupRepository;
_notificationHistoryRepository = notificationHistoryRepository;
_emailNotificationService = emailNotificationService;
_systemMessageService = systemMessageService;
_templateService = templateService;
_userService = userService;
_logger = logger;
}
#region
/// <summary>
/// 获取通知设置列表(可选过滤,含缓存)
/// </summary>
[HttpGet]
public async Task<List<NotificationSettingOutput>> GetNotificationSettingListAsync(bool? isEnabled = null, long? personnelGroupId = null)
{
var cacheKey = $"{CacheKeys.NotificationSettingsKey}:all";
var cachedList = await Cache.GetAsync<List<NotificationSettingOutput>>(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;
}
/// <summary>
/// 查询通知设置
/// </summary>
[HttpGet]
public async Task<NotificationSettingOutput> 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;
}
/// <summary>
/// 查询通知设置分页
/// </summary>
[HttpPost]
public async Task<PageOutput<NotificationSettingOutput>> GetNotificationSettingPageAsync(PageInput<NotificationSettingPageInput> 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<NotificationSettingOutput>
{
List = outputs,
Total = totalCount
};
}
/// <summary>
/// 创建通知设置
/// </summary>
[HttpPost]
public async Task<long> 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;
}
/// <summary>
/// 更新通知设置
/// </summary>
[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();
}
/// <summary>
/// 删除通知设置
/// </summary>
[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();
}
/// <summary>
/// 启用/禁用通知设置
/// </summary>
[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();
}
/// <summary>
/// 清除消息配置缓存
/// </summary>
private async Task ClearNotificationSettingCache()
{
var cacheKey = $"{CacheKeys.NotificationSettingsKey}:all";
Cache.ExistsAsync(cacheKey);
}
#endregion
#region
/// <summary>
/// 查询人员组
/// </summary>
[HttpGet]
public async Task<PersonnelGroupOutput> 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;
}
/// <summary>
/// 查询人员组分页
/// </summary>
[HttpPost]
public async Task<PageOutput<PersonnelGroupOutput>> GetPersonnelGroupPageAsync(PageInput<PersonnelGroupGetPageInput> 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<PersonnelGroupOutput>
{
List = outputs,
Total = totalCount
};
}
/// <summary>
/// 创建人员组
/// </summary>
[HttpPost]
public async Task<long> 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;
}
/// <summary>
/// 更新人员组
/// </summary>
[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);
}
/// <summary>
/// 删除人员组
/// </summary>
[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);
}
/// <summary>
/// 获取人员组的实际人员列表
/// 根据决策点4混合人员组支持静态+动态规则
/// </summary>
[HttpGet]
public async Task<List<long>> 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<long>();
// 获取静态人员
var staticPersonnelIds = JsonSerializer.Deserialize<List<long>>(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<List<long>>(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
/// <summary>
/// 发送通知
/// 决策点1支持邮件和系统消息通知
/// </summary>
[HttpPost]
public async Task<SendNotificationOutput> 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;
}
/// <summary>
/// 发送群组通知(邮件发送一封给所有人,系统消息仍然单独发送)
/// </summary>
[HttpPost]
public async Task<SendNotificationOutput> 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;
}
/// <summary>
/// 批量发送通知
/// </summary>
[HttpPost]
public async Task<List<SendNotificationOutput>> BatchSendNotificationAsync(List<SendNotificationInput> inputs)
{
_logger.LogInformation("开始批量发送通知,批次数量:{Count}", inputs.Count);
var outputs = new List<SendNotificationOutput>();
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;
}
/// <summary>
/// 根据通知设置发送通知
/// </summary>
[HttpPost]
public async Task<SendNotificationOutput> SendNotificationBySettingAsync(
long notificationSettingId,
string businessType,
long? businessId = null,
string businessData = "",
Dictionary<string, string> 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
/// <summary>
/// 验证模板语法
/// </summary>
[HttpPost]
public async Task<bool> 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
/// <summary>
/// 查询通知历史记录
/// </summary>
[HttpGet]
public async Task<NotificationHistoryOutput> 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;
}
/// <summary>
/// 查询通知历史记录分页
/// </summary>
[HttpPost]
public async Task<PageOutput<NotificationHistoryOutput>> GetNotificationHistoryPageAsync(PageInput<NotificationHistoryPageInput> 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<NotificationHistoryOutput>
{
List = outputs,
Total = totalCount
};
}
/// <summary>
/// 查询当前用户通知历史记录
/// </summary>
[HttpPost]
public async Task<PageOutput<NotificationHistoryOutput>> 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<NotificationHistoryOutput>
{
List = outputs,
Total = totalCount
};
}
/// <summary>
/// 重试失败的通知
/// </summary>
[HttpPost]
public async Task<bool> RetryFailedNotificationAsync(long notificationHistoryId)
{
_logger.LogInformation("开始重试失败的通知历史记录ID{HistoryId}", notificationHistoryId);
// 简化实现
await Task.Delay(100);
_logger.LogInformation("完成重试失败的通知历史记录ID{HistoryId}", notificationHistoryId);
return true;
}
/// <summary>
/// 批量重试失败的通知
/// </summary>
[HttpPost]
public async Task<int> BatchRetryFailedNotificationsAsync(List<long> 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;
}
/// <summary>
/// 取消通知
/// </summary>
[HttpPost]
public async Task<bool> 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;
}
}
/// <summary>
/// 批量取消通知
/// </summary>
[HttpPost]
public async Task<int> BatchCancelNotificationsAsync(List<long> 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
/// <summary>
/// 创建定时通知任务
/// </summary>
[HttpPost]
public async Task<long> 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;
}
/// <summary>
/// 执行定时通知任务
/// </summary>
[HttpPost]
public async Task<bool> ExecuteScheduledNotificationTaskAsync(long taskId)
{
_logger.LogInformation("开始执行定时通知任务任务ID{TaskId}", taskId);
await Task.Delay(100);
_logger.LogInformation("成功执行定时通知任务任务ID{TaskId}", taskId);
return true;
}
/// <summary>
/// 获取待执行的定时任务列表
/// </summary>
[HttpGet]
public async Task<List<long>> GetPendingNotificationTasksAsync()
{
await Task.CompletedTask;
return new List<long>();
}
/// <summary>
/// 启用/禁用定时任务
/// </summary>
[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
/// <summary>
/// 获取通知发送统计信息
/// </summary>
[HttpPost]
public async Task<Dictionary<string, object>> GetNotificationStatisticsAsync(
DateTime startTime,
DateTime endTime,
long? notificationSettingId = null)
{
_logger.LogInformation("开始获取通知发送统计信息,时间范围:{StartTime} - {EndTime}", startTime, endTime);
var statistics = new Dictionary<string, object>
{
["TotalCount"] = 0,
["SuccessCount"] = 0,
["FailedCount"] = 0,
["PendingCount"] = 0,
["SuccessRate"] = 0.0,
["EmailCount"] = 0,
["SystemMessageCount"] = 0,
["StatisticsTime"] = DateTime.Now
};
_logger.LogInformation("成功获取通知发送统计信息");
return statistics;
}
#endregion
#region
/// <summary>
/// 用户信息DTO类
/// </summary>
private class UserInfo
{
public long Id { get; set; }
public string Name { get; set; } = "";
public string Email { get; set; } = "";
}
/// <summary>
/// 获取用户信息字典
/// </summary>
private async Task<Dictionary<long, UserInfo>> GetUserInfoDictionary(List<long> personnelIds)
{
var userInfoDict = new Dictionary<long, UserInfo>();
try
{
var cacheKey = CacheKeys.UserListKey;
var cacheOrgUsers = Cache.Get<List<UserGrpcOutput>>(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;
}
/// <summary>
/// 发送单个通知
/// </summary>
private async Task<bool> 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;
}
}
/// <summary>
/// 发送群组邮件通知(一封邮件发送给所有人)
/// </summary>
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;
}
}
/// <summary>
/// 发送个人系统消息(逐个发送)
/// </summary>
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;
}
}
/// <summary>
/// 发送邮件通知
/// </summary>
private async Task<bool> 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;
}
}
/// <summary>
/// 发送系统消息通知
/// </summary>
private async Task<bool> 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;
}
}
/// <summary>
/// 创建通知历史记录
/// </summary>
private async Task<long> 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;
}
}
/// <summary>
/// 更新通知历史记录状态
/// </summary>
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);
}
}
/// <summary>
/// 映射到NotificationSettingOutput
/// </summary>
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
};
}
/// <summary>
/// 映射到PersonnelGroupOutput
/// </summary>
private PersonnelGroupOutput MapToPersonnelGroupOutput(PersonnelGroupEntity entity)
{
var staticPersonnelIds = JsonSerializer.Deserialize<List<long>>(entity.StaticPersonnelIds) ?? new List<long>();
var dynamicDepartmentIds = JsonSerializer.Deserialize<List<long>>(entity.DynamicDepartmentIds) ?? new List<long>();
var dynamicPositions = JsonSerializer.Deserialize<List<string>>(entity.DynamicPositions) ?? new List<string>();
var excludePersonnelIds = JsonSerializer.Deserialize<List<long>>(entity.ExcludePersonnelIds) ?? new List<long>();
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
};
}
/// <summary>
/// 映射到NotificationHistoryOutput
/// </summary>
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
/// <summary>
/// 验证时间配置合法性
/// </summary>
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("开始时间不能大于等于结束时间");
}
}
}
}
/// <summary>
/// 验证频次配置合法性
/// </summary>
private void ValidateFrequencyConfiguration(NotificationFrequencyEnum frequencyType, int? intervalMinutes)
{
if (frequencyType == NotificationFrequencyEnum.FixedInterval && (!intervalMinutes.HasValue || intervalMinutes.Value <= 0))
{
throw new Exception("间隔频次时间隔分钟数必须大于0");
}
}
/// <summary>
/// 验证模板配置合法性
/// </summary>
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}");
}
}
}
/// <summary>
/// 验证人员组配置合法性
/// </summary>
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("动态部门人员组必须配置部门");
}
}
/// <summary>
/// 获取动态人员ID列表
/// </summary>
private async Task<List<long>> GetDynamicPersonnelIds(PersonnelGroupEntity personnelGroup)
{
var orgUserIds = new List<long>();
var dynamicDepartmentIds = JsonSerializer.Deserialize<List<long>>(personnelGroup.DynamicDepartmentIds);
foreach (var orgId in dynamicDepartmentIds)
{
var cacheKey = CacheKeys.GetDynamicDepartmentKey(orgId);
var cacheOrgUserIds = Cache.Get<List<UserOrgGrpcOutput>>(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
}