修改
continuous-integration/drone/push Build is passing Details

Test_IRC_Net8
he 2025-04-17 15:33:44 +08:00
parent d125ff6324
commit c0d6eb3203
12 changed files with 19802 additions and 4 deletions

View File

@ -20,6 +20,8 @@ namespace IRaCIS.Core.API.HostService;
public class HangfireHostService(IRecurringMessageScheduler _recurringMessageScheduler,
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigRepository,
IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
IMediator _mediator,
ILogger<HangfireHostService> _logger) : IHostedService
{
@ -55,6 +57,20 @@ public class HangfireHostService(IRecurringMessageScheduler _recurringMessageSch
}
// 系统邮件定时任务
var systemTaskInfoList = await _emailNoticeConfigrepository.Where(t => t.EmailCron != string.Empty && t.IsAutoSend)
.Select(t => new { t.Id, t.Code, t.EmailCron, t.BusinessScenarioEnum, })
.ToListAsync();
foreach (var task in systemTaskInfoList)
{
//利用主键作为任务Id
var jobId = $"{task.Id}_({task.BusinessScenarioEnum})";
HangfireJobHelper.AddOrUpdateSystemCronJob(jobId, task.BusinessScenarioEnum, task.EmailCron);
}
//await _recurringMessageScheduler.ScheduleRecurringPublish(new QCImageQuestionSchedule() { CronExpression = "0/3 * * * * ? " }, new MasstransiTestCommand { value = "message at " + DateTime.Now.ToString() });

View File

@ -77,13 +77,26 @@ namespace IRaCIS.Core.Application.Helper
case EmailBusinessScenario.ExpeditedReading:
HangfireJobHelper.AddOrUpdateCronJob<IMediator>(jobId, t => t.Send(new UrgentIRUnReadTaskRecurringEvent() { TrialId = trialId }, default), emailCron);
break;
default:
break;
}
}
public static void AddOrUpdateSystemCronJob(string jobId, EmailBusinessScenario businessScenario, string emailCron)
{
switch (businessScenario)
{
case EmailBusinessScenario.GeneralTraining_ExpirationNotification:
HangfireJobHelper.AddOrUpdateCronJob<IMediator>(jobId, t => t.Send(new SystemDocumentErverDayEvent() { }, default), emailCron);
break;
default:
break;
}
}
}
}

View File

@ -14338,6 +14338,11 @@
影像质控
</summary>
</member>
<member name="T:IRaCIS.Core.Application.MassTransit.Consumer.SystemDocumentErverDayEvent">
<summary>
定时提醒
</summary>
</member>
<member name="T:IRaCIS.Core.Application.MassTransit.Consumer.QCImageQuestionRecurringSchedule">
<summary>
QC 影像质疑待处理
@ -14363,6 +14368,26 @@
10分钟检测通知IR 已通知的进行标注,下次不会再通知
</summary>
</member>
<member name="T:IRaCIS.Core.Application.MassTransit.Recurring.SystemDocumentErverDayEventConsumer">
<summary>
定时提醒
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Recurring.SystemDocumentErverDayEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocument},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.IdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocConfirmedIdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.EmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<summary>
定时提醒
</summary>
</member>
<member name="T:IRaCIS.Core.Application.MassTransit.Recurring.SystemDocumentPublishEventConsumer">
<summary>
生效通知
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Recurring.SystemDocumentPublishEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocument},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.IdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocConfirmedIdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.EmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<summary>
生效通知
</summary>
</member>
<member name="T:IRaCIS.Core.Application.ViewModel.TaskAllocationRuleView">
<summary> TaskAllocationRuleView 列表视图模型 </summary>
</member>
@ -15881,6 +15906,11 @@
新员工培训天数
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Contracts.SystemDocumentAddOrEdit.IsPublish">
<summary>
是否发布
</summary>
</member>
<member name="T:IRaCIS.Core.Application.Contracts.TrialDocumentUserConfirmView">
<summary> TrialDocumentUserConfirmView 列表视图模型 </summary>
</member>
@ -16992,7 +17022,7 @@
SystemDocumentService
</summary>
</member>
<member name="M:IRaCIS.Core.Application.Services.SystemDocumentService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocument},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocumentAttachment},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.IdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocConfirmedIdentityUser},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<member name="M:IRaCIS.Core.Application.Services.SystemDocumentService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocument},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},MassTransit.Mediator.IScopedMediator,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocumentAttachment},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.IdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocConfirmedIdentityUser},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<summary>
SystemDocumentService
</summary>
@ -17025,6 +17055,12 @@
<param name="inQuery"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Services.SystemDocumentService.PublishSystemDocument(IRaCIS.Core.Application.Contracts.PublishSystemDocumentInDto)">
<summary>
发布系统文档
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Services.SystemDocumentService.getWaitSignSysDocList(IRaCIS.Core.Application.Contracts.SystemDocumentQuery)">
<summary>
获取需要签署的系统文档列表

View File

@ -37,4 +37,18 @@ public class UrgentIRUnReadTaskRecurringEvent : DomainEvent
public Guid TrialId { get; set; }
}
/// <summary>
/// 定时提醒
/// </summary>
public class SystemDocumentErverDayEvent : DomainEvent
{
}
public class SystemDocumentPublishEvent : DomainEvent
{
public List<Guid> Ids { get; set; }
}

View File

@ -0,0 +1,197 @@
using DocumentFormat.OpenXml;
using IRaCIS.Application.Contracts;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.MassTransit.Consumer;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Domain.Models;
using MassTransit;
using Microsoft.Extensions.Options;
using MimeKit;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reactive.Joins;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.MassTransit.Recurring
{
/// <summary>
/// 定时提醒
/// </summary>
public class SystemDocumentErverDayEventConsumer(
IRepository<ReadingQuestionCriterionTrial> _trialReadingCriterionRepository,
IRepository<VisitTask> _visitTaskRepository,
IRepository<SystemDocument> _systemDocumentRepository,
IRepository<IdentityUser> _identityUserRepository,
IRepository<SystemDocConfirmedIdentityUser> _systemDocConfirmedUserRepository,
IRepository<Dictionary> _dictionaryRepository,
IRepository<TrialUserRole> _trialUserRoleRepository,
IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig) : IConsumer<SystemDocumentErverDayEvent>
{
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
public async Task Consume(ConsumeContext<SystemDocumentErverDayEvent> context)
{
DateTime now = DateTime.Now;
if (now.Hour == 9)
{
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
var systemDocQuery =
from sysDoc in _systemDocumentRepository.AsQueryable(false)
from identityUser in _identityUserRepository.AsQueryable(false).Where(t => t.UserRoleList.Where(t => t.IsUserRoleDisabled == false).Any(t => sysDoc.NeedConfirmedUserTypeList.AsQueryable().Any(c => c.NeedConfirmUserTypeId == t.UserTypeId)))
join confirm in _systemDocConfirmedUserRepository.Where() on new { ConfirmUserId = identityUser.Id, SystemDocumentId = sysDoc.Id } equals new { confirm.ConfirmUserId, confirm.SystemDocumentId } into cc
from confirm in cc.DefaultIfEmpty()
select new UnionDocumentWithConfirmInfoView()
{
IsSystemDoc = true,
Id = sysDoc.Id,
CreateTime = sysDoc.CreateTime,
IsDeleted = sysDoc.IsDeleted,
SignViewMinimumMinutes = sysDoc.SignViewMinimumMinutes,
Name = sysDoc.Name,
Path = sysDoc.Path,
FileTypeId = sysDoc.FileTypeId,
UpdateTime = sysDoc.UpdateTime,
ConfirmUserId = identityUser.Id,
ConfirmTime = confirm.ConfirmTime,
RealName = identityUser.FullName,
UserName = identityUser.UserName,
FullFilePath = sysDoc.Path
};
var datalist = await systemDocQuery.IgnoreQueryFilters().Where(t => !(t.IsDeleted == true && t.ConfirmTime == null))
.Where(x => x.ConfirmTime != null).ToListAsync();
datalist = datalist.Where(x => x.SuggestFinishTime != null && x.SuggestFinishTime.Value.Date == DateTime.Now.Date).ToList();
var confirmUserIdList = datalist.Select(t => t.ConfirmUserId).Distinct().ToList();
var userinfoList = await _identityUserRepository.Where(x => confirmUserIdList.Contains(x.Id)).ToListAsync();
foreach (var userinfo in userinfoList)
{
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var topicStr = string.Format(input.topicStr, companyName);
var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
userinfo.UserName // 用户名 {0}
);
return (topicStr, htmlBodyStr);
};
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(_emailNoticeConfigrepository,
EmailBusinessScenario.GeneralTraining_ExpirationNotification,
messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
}
}
}
}
/// <summary>
/// 生效通知
/// </summary>
public class SystemDocumentPublishEventConsumer(
IRepository<ReadingQuestionCriterionTrial> _trialReadingCriterionRepository,
IRepository<VisitTask> _visitTaskRepository,
IRepository<SystemDocument> _systemDocumentRepository,
IRepository<IdentityUser> _identityUserRepository,
IRepository<SystemDocConfirmedIdentityUser> _systemDocConfirmedUserRepository,
IRepository<Dictionary> _dictionaryRepository,
IRepository<TrialUserRole> _trialUserRoleRepository,
IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig) : IConsumer<SystemDocumentPublishEvent>
{
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
public async Task Consume(ConsumeContext<SystemDocumentPublishEvent> context)
{
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
var systemDocQuery =
from sysDoc in _systemDocumentRepository.AsQueryable(false).Where(x=> context.Message.Ids.Contains(x.Id))
from identityUser in _identityUserRepository.AsQueryable(false).Where(t => t.UserRoleList.Where(t => t.IsUserRoleDisabled == false).Any(t => sysDoc.NeedConfirmedUserTypeList.AsQueryable().Any(c => c.NeedConfirmUserTypeId == t.UserTypeId)))
select new UnionDocumentWithConfirmInfoView()
{
IsSystemDoc = true,
Id = sysDoc.Id,
CreateTime = sysDoc.CreateTime,
IsDeleted = sysDoc.IsDeleted,
SignViewMinimumMinutes = sysDoc.SignViewMinimumMinutes,
Name = sysDoc.Name,
Path = sysDoc.Path,
FileTypeId = sysDoc.FileTypeId,
UpdateTime = sysDoc.UpdateTime,
ConfirmUserId = identityUser.Id,
RealName = identityUser.FullName,
UserName = identityUser.UserName,
FullFilePath = sysDoc.Path
};
var datalist = await systemDocQuery.IgnoreQueryFilters().ToListAsync();
var confirmUserIdList = datalist.Select(t => t.ConfirmUserId).Distinct().ToList();
var userinfoList = await _identityUserRepository.Where(x => confirmUserIdList.Contains(x.Id)).ToListAsync();
foreach (var userinfo in userinfoList)
{
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var topicStr = string.Format(input.topicStr, companyName);
var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
userinfo.UserName // 用户名 {0}
);
return (topicStr, htmlBodyStr);
};
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(_emailNoticeConfigrepository,
EmailBusinessScenario.GeneralTraining_EffectiveNotification,
messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
}
}
}
}

View File

@ -350,6 +350,18 @@ namespace IRaCIS.Core.Application.Contracts
/// </summary>
public int? NewStaffTrainDays { get; set; }
/// <summary>
/// 是否发布
/// </summary>
public bool IsPublish { get; set; } = false;
}
public class PublishSystemDocumentInDto
{
public List<Guid> Ids { get; set; }
}
public class AddOrEditSystemDocument : SystemDocumentAddOrEdit

View File

@ -5,8 +5,12 @@
//--------------------------------------------------------------------
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain;
using Microsoft.AspNetCore.Mvc;
using UserRole = IRaCIS.Core.Domain.Models.UserRole;
using IRaCIS.Core.Application.MassTransit.Consumer;
using MassTransit.Mediator;
namespace IRaCIS.Core.Application.Services
{
@ -16,6 +20,7 @@ namespace IRaCIS.Core.Application.Services
[ApiExplorerSettings(GroupName = "Trial")]
public class SystemDocumentService(IRepository<SystemDocument> _systemDocumentRepository,
IRepository<UserRole> _userRoleRepository,
IScopedMediator _mediatorScoped,
IRepository<SystemDocumentAttachment> _systemDocumentAttachmentRepository,
IRepository<IdentityUser> _identityUserRepository,
IRepository<SystemDocConfirmedIdentityUser> _systemDocConfirmedUserRepository, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, ISystemDocumentService
@ -156,6 +161,28 @@ namespace IRaCIS.Core.Application.Services
}
/// <summary>
/// 发布系统文档
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> PublishSystemDocument(PublishSystemDocumentInDto inDto)
{
await _systemDocumentRepository.UpdatePartialFromQueryAsync(x => inDto.Ids.Contains(x.Id), x => new SystemDocument()
{
IsPublish = true,
IsDeleted = false,
});
var result = await _systemDocumentRepository.SaveChangesAsync();
await _mediatorScoped.Publish(new SystemDocumentPublishEvent() { Ids = inDto.Ids });
return ResponseOutput.Result(result);
}
[HttpDelete("{systemDocumentId:guid}")]
public async Task<IResponseOutput> AbandonSystemDocumentAsync(Guid systemDocumentId)
{

View File

@ -243,6 +243,18 @@ namespace IRaCIS.Core.Domain.Share
/// </summary>
Reviewer_CV_Collection = 57,
/// <summary>
/// 通用培训 - 生效通知
/// </summary>
GeneralTraining_EffectiveNotification=58,
/// <summary>
/// 通用培训 - 到期通知
/// </summary>
GeneralTraining_ExpirationNotification = 59,
}

View File

@ -40,7 +40,14 @@ public class SystemDocument : BaseFullDeleteAuditEntity
/// </summary>
public int? NewStaffTrainDays { get; set; }
/// <summary>
/// 是否发布
/// </summary>
public bool IsPublish { get; set; } = true;
}
[Comment("后台 - 系统签署文档附件")]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,29 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace IRaCIS.Core.Infra.EFCore.Migrations
{
/// <inheritdoc />
public partial class Publish : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "IsPublish",
table: "SystemDocument",
type: "bit",
nullable: false,
defaultValue: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "IsPublish",
table: "SystemDocument");
}
}
}

View File

@ -9666,6 +9666,9 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<bool>("IsPublish")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(400)