Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
commit
f33d3d474b
|
@ -140,6 +140,7 @@ builder.Services.AddJWTAuthSetup(_configuration);
|
||||||
// MediatR 进程内消息 事件解耦 从程序集中 注册命令和handler对应关系
|
// MediatR 进程内消息 事件解耦 从程序集中 注册命令和handler对应关系
|
||||||
//builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<ConsistencyVerificationHandler>());
|
//builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<ConsistencyVerificationHandler>());
|
||||||
|
|
||||||
|
#region MassTransit
|
||||||
//masstransit组件 也支持MediatR 中介者模式,但是支持分布式,考虑后续,所以在次替代MediatR
|
//masstransit组件 也支持MediatR 中介者模式,但是支持分布式,考虑后续,所以在次替代MediatR
|
||||||
builder.Services.AddMediator(cfg =>
|
builder.Services.AddMediator(cfg =>
|
||||||
{
|
{
|
||||||
|
@ -150,6 +151,14 @@ builder.Services.AddMassTransit(cfg =>
|
||||||
{
|
{
|
||||||
cfg.UsingInMemory();
|
cfg.UsingInMemory();
|
||||||
});
|
});
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region FusionCache
|
||||||
|
|
||||||
|
builder.Services.AddFusionCache();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
// EasyCaching 缓存
|
// EasyCaching 缓存
|
||||||
builder.Services.AddEasyCachingSetup(_configuration);
|
builder.Services.AddEasyCachingSetup(_configuration);
|
||||||
|
|
|
@ -9,6 +9,7 @@ using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using SharpCompress.Common;
|
using SharpCompress.Common;
|
||||||
|
using ZiggyCreatures.Caching.Fusion;
|
||||||
|
|
||||||
namespace IRaCIS.Application.Services.BackGroundJob
|
namespace IRaCIS.Application.Services.BackGroundJob
|
||||||
{
|
{
|
||||||
|
@ -21,28 +22,16 @@ namespace IRaCIS.Application.Services.BackGroundJob
|
||||||
Task InitHangfireJobTaskAsync();
|
Task InitHangfireJobTaskAsync();
|
||||||
|
|
||||||
}
|
}
|
||||||
public class IRaCISCHangfireJob : IIRaCISHangfireJob
|
public class IRaCISCHangfireJob(IRepository<Trial> _trialRepository,
|
||||||
|
IEasyCachingProvider _provider,
|
||||||
|
ILogger<IRaCISCHangfireJob> _logger,
|
||||||
|
IRepository<SystemAnonymization> _systemAnonymizationRepository,
|
||||||
|
IRepository<Internationalization> _internationalizationRepository,
|
||||||
|
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigRepository
|
||||||
|
) : IIRaCISHangfireJob
|
||||||
{
|
{
|
||||||
public static string JsonFileFolder = Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources);
|
public static string JsonFileFolder = Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources);
|
||||||
|
|
||||||
private readonly IRepository<Trial> _trialRepository;
|
|
||||||
private readonly IEasyCachingProvider _provider;
|
|
||||||
private readonly ILogger<IRaCISCHangfireJob> _logger;
|
|
||||||
private readonly IRepository<SystemAnonymization> _systemAnonymizationRepository;
|
|
||||||
private readonly IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigRepository;
|
|
||||||
private readonly IRepository<Internationalization> _internationalizationRepository;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public IRaCISCHangfireJob(IRepository<Trial> trialRepository, ILogger<IRaCISCHangfireJob> logger, IEasyCachingProvider provider, IRepository<TrialEmailNoticeConfig> trialEmailNoticeConfigRepository, IRepository<Internationalization> internationalizationRepository, IRepository<SystemAnonymization> systemAnonymizationRepository)
|
|
||||||
{
|
|
||||||
_trialRepository = trialRepository;
|
|
||||||
_provider = provider;
|
|
||||||
_logger = logger;
|
|
||||||
_trialEmailNoticeConfigRepository = trialEmailNoticeConfigRepository;
|
|
||||||
_internationalizationRepository = internationalizationRepository;
|
|
||||||
_systemAnonymizationRepository = systemAnonymizationRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task InitHangfireJobTaskAsync()
|
public async Task InitHangfireJobTaskAsync()
|
||||||
{
|
{
|
||||||
|
@ -52,7 +41,7 @@ namespace IRaCIS.Application.Services.BackGroundJob
|
||||||
//项目状态 立即加载到缓存中
|
//项目状态 立即加载到缓存中
|
||||||
await MemoryCacheTrialStatusAsync();
|
await MemoryCacheTrialStatusAsync();
|
||||||
|
|
||||||
await MemoryCacheAnonymizeData();
|
//await MemoryCacheAnonymizeData();
|
||||||
|
|
||||||
|
|
||||||
//创建项目缓存 定时任务
|
//创建项目缓存 定时任务
|
||||||
|
@ -69,29 +58,8 @@ namespace IRaCIS.Application.Services.BackGroundJob
|
||||||
_logger.LogInformation("项目启动 hangfire 任务初始化 执行结束");
|
_logger.LogInformation("项目启动 hangfire 任务初始化 执行结束");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 缓存项目状态
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task MemoryCacheTrialStatusAsync()
|
|
||||||
{
|
|
||||||
|
|
||||||
var list = await _trialRepository.Select(t => new { TrialId = t.Id, TrialStatusStr = t.TrialStatusStr })
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
list.ForEach(t => _provider.Set(t.TrialId.ToString(), t.TrialStatusStr, TimeSpan.FromDays(7)));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task MemoryCacheAnonymizeData()
|
|
||||||
{
|
|
||||||
var systemAnonymizationList = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
|
|
||||||
|
|
||||||
_provider.Set(StaticData.Anonymize.Anonymize_AddFixedFiled, systemAnonymizationList.Where(t => t.IsAdd && t.IsFixed).ToList(), TimeSpan.FromDays(7));
|
|
||||||
_provider.Set(StaticData.Anonymize.Anonymize_AddIRCInfoFiled, systemAnonymizationList.Where(t => t.IsAdd && t.IsFixed == false).ToList(), TimeSpan.FromDays(7));
|
|
||||||
_provider.Set(StaticData.Anonymize.Anonymize_FixedField, systemAnonymizationList.Where(t => t.IsAdd == false && t.IsFixed).ToList(), TimeSpan.FromDays(7));
|
|
||||||
_provider.Set(StaticData.Anonymize.Anonymize_IRCInfoField, systemAnonymizationList.Where(t => t.IsAdd == false && t.IsFixed == false).ToList(), TimeSpan.FromDays(7));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -136,6 +104,36 @@ namespace IRaCIS.Application.Services.BackGroundJob
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#region 废弃 前端上传的时候获取
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 缓存项目状态--之前是启动的时候就获取所有的项目进行缓存,加上定时任务刷新,现在的话,改为是按照需要进行缓存请求数据库
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task MemoryCacheTrialStatusAsync()
|
||||||
|
{
|
||||||
|
|
||||||
|
var list = await _trialRepository.Select(t => new { TrialId = t.Id, TrialStatusStr = t.TrialStatusStr })
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
list.ForEach(t => _provider.Set(t.TrialId.ToString(), t.TrialStatusStr, TimeSpan.FromDays(7)));
|
||||||
|
|
||||||
|
}
|
||||||
|
public async Task MemoryCacheAnonymizeData()
|
||||||
|
{
|
||||||
|
var systemAnonymizationList = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
|
||||||
|
|
||||||
|
_provider.Set(StaticData.Anonymize.Anonymize_AddFixedFiled, systemAnonymizationList.Where(t => t.IsAdd && t.IsFixed).ToList(), TimeSpan.FromDays(7));
|
||||||
|
_provider.Set(StaticData.Anonymize.Anonymize_AddIRCInfoFiled, systemAnonymizationList.Where(t => t.IsAdd && t.IsFixed == false).ToList(), TimeSpan.FromDays(7));
|
||||||
|
_provider.Set(StaticData.Anonymize.Anonymize_FixedField, systemAnonymizationList.Where(t => t.IsAdd == false && t.IsFixed).ToList(), TimeSpan.FromDays(7));
|
||||||
|
_provider.Set(StaticData.Anonymize.Anonymize_IRCInfoField, systemAnonymizationList.Where(t => t.IsAdd == false && t.IsFixed == false).ToList(), TimeSpan.FromDays(7));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
using Microsoft.Extensions.Localization;
|
using Microsoft.Extensions.Localization;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using ZiggyCreatures.Caching.Fusion;
|
||||||
using static IRaCIS.Core.Domain.Share.StaticData;
|
using static IRaCIS.Core.Domain.Share.StaticData;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Filter
|
namespace IRaCIS.Core.Application.Filter
|
||||||
|
@ -16,36 +17,25 @@ namespace IRaCIS.Core.Application.Filter
|
||||||
{
|
{
|
||||||
private readonly IEasyCachingProvider _provider;
|
private readonly IEasyCachingProvider _provider;
|
||||||
private readonly IUserInfo _userInfo;
|
private readonly IUserInfo _userInfo;
|
||||||
|
private readonly IFusionCache _fusionCache;
|
||||||
public IStringLocalizer _localizer;
|
public IStringLocalizer _localizer;
|
||||||
private readonly List<string> _trialOptList=new List<string>();
|
private readonly List<string> _trialOptList=new List<string>();
|
||||||
|
|
||||||
|
|
||||||
public TrialResourceFilter(IEasyCachingProvider provider, IStringLocalizer localizer , IUserInfo userInfo, string trialOpt = null, string trialOpt2 = null, string trialOpt3 = null)
|
public TrialResourceFilter(IFusionCache fusionCache, IEasyCachingProvider provider, IStringLocalizer localizer , IUserInfo userInfo, string trialOpt = null, string trialOpt2 = null, string trialOpt3 = null)
|
||||||
{
|
{
|
||||||
|
_fusionCache = fusionCache;
|
||||||
_provider = provider;
|
_provider = provider;
|
||||||
_userInfo = userInfo;
|
_userInfo = userInfo;
|
||||||
_localizer = localizer;
|
_localizer = localizer;
|
||||||
//_trialOpt = trialOpt;
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(trialOpt)) _trialOptList.Add(trialOpt.Trim());
|
if (!string.IsNullOrWhiteSpace(trialOpt)) _trialOptList.Add(trialOpt.Trim());
|
||||||
if (!string.IsNullOrWhiteSpace(trialOpt2)) _trialOptList.Add(trialOpt2.Trim());
|
if (!string.IsNullOrWhiteSpace(trialOpt2)) _trialOptList.Add(trialOpt2.Trim());
|
||||||
if (!string.IsNullOrWhiteSpace(trialOpt3)) _trialOptList.Add(trialOpt3.Trim());
|
if (!string.IsNullOrWhiteSpace(trialOpt3)) _trialOptList.Add(trialOpt3.Trim());
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StaticData
|
||||||
|
|
||||||
//public TrialResourceFilter(IEasyCachingProvider provider, IUserInfo userInfo)
|
|
||||||
//{
|
|
||||||
// _provider = provider;
|
|
||||||
// _userInfo = userInfo;
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//优先选择异步的方法
|
//优先选择异步的方法
|
||||||
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
|
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
|
||||||
|
|
|
@ -86,6 +86,7 @@
|
||||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.5" />
|
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.5" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.2" />
|
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.2" />
|
||||||
<PackageReference Include="MassTransit.AspNetCore" Version="7.3.1" />
|
<PackageReference Include="MassTransit.AspNetCore" Version="7.3.1" />
|
||||||
|
<PackageReference Include="ZiggyCreatures.FusionCache" Version="1.3.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -15192,11 +15192,14 @@
|
||||||
<param name="inQuery"></param>
|
<param name="inQuery"></param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:IRaCIS.Application.Services.PatientService.SubmitVisitStudyBinding(IRaCIS.Application.Contracts.SubmitVisitStudyBindingCommand)">
|
<member name="M:IRaCIS.Application.Services.PatientService.SubmitVisitStudyBinding(IRaCIS.Application.Contracts.SubmitVisitStudyBindingCommand,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomSeries},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomInstance})">
|
||||||
<summary>
|
<summary>
|
||||||
提交 患者检查和访视的绑定
|
提交 患者检查和访视的绑定
|
||||||
</summary>
|
</summary>
|
||||||
<param name="inCommand"></param>
|
<param name="inCommand"></param>
|
||||||
|
<param name="_dicomstudyRepository"></param>
|
||||||
|
<param name="_dicomSeriesRepository"></param>
|
||||||
|
<param name="_dicomInstanceRepository"></param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:IRaCIS.Application.Services.SubjectService.AddOrUpdateSubject(IRaCIS.Application.Contracts.SubjectCommand)">
|
<member name="M:IRaCIS.Application.Services.SubjectService.AddOrUpdateSubject(IRaCIS.Application.Contracts.SubjectCommand)">
|
||||||
|
|
|
@ -205,6 +205,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
||||||
study.TrialId = incommand.TrialId;
|
study.TrialId = incommand.TrialId;
|
||||||
study.SubjectId = incommand.SubjectId;
|
study.SubjectId = incommand.SubjectId;
|
||||||
study.SubjectVisitId = incommand.SubjectVisitId;
|
study.SubjectVisitId = incommand.SubjectVisitId;
|
||||||
|
study.IsFromPACS = false;
|
||||||
|
|
||||||
//如果因为意外情况,连续点击两次,导致第一次插入了,第二次进来也会插入,在此判断一下
|
//如果因为意外情况,连续点击两次,导致第一次插入了,第二次进来也会插入,在此判断一下
|
||||||
var findStudy = await _dicomstudyRepository.FirstOrDefaultAsync(t => t.Id == study.Id);
|
var findStudy = await _dicomstudyRepository.FirstOrDefaultAsync(t => t.Id == study.Id);
|
||||||
|
@ -279,6 +280,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
||||||
studyMonitor.StudyCode = study.StudyCode;
|
studyMonitor.StudyCode = study.StudyCode;
|
||||||
|
|
||||||
//特殊处理逻辑
|
//特殊处理逻辑
|
||||||
|
study.IsFromPACS = false;
|
||||||
study.Modalities = string.Join("、", incommand.Study.SeriesList.Select(t => t.Modality).Union(study.Modalities.Split("、", StringSplitOptions.RemoveEmptyEntries)).Distinct());
|
study.Modalities = string.Join("、", incommand.Study.SeriesList.Select(t => t.Modality).Union(study.Modalities.Split("、", StringSplitOptions.RemoveEmptyEntries)).Distinct());
|
||||||
SpecialArchiveStudyDeal(study);
|
SpecialArchiveStudyDeal(study);
|
||||||
modalitys = study.Modalities;
|
modalitys = study.Modalities;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using Castle.Core.Internal;
|
using IRaCIS.Application.Contracts;
|
||||||
using IRaCIS.Application.Contracts;
|
|
||||||
using IRaCIS.Core.Application.Contracts;
|
using IRaCIS.Core.Application.Contracts;
|
||||||
using IRaCIS.Core.Application.Contracts.DTO;
|
using IRaCIS.Core.Application.Contracts.DTO;
|
||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
|
|
@ -187,7 +187,7 @@ namespace IRaCIS.Core.Application.Contracts
|
||||||
public DateTime CreateTime { get; set; }
|
public DateTime CreateTime { get; set; }
|
||||||
|
|
||||||
[DictionaryTranslateAttribute("YesOrNo")]
|
[DictionaryTranslateAttribute("YesOrNo")]
|
||||||
public bool IsConfirmed { get; set; }
|
public bool IsConfirmed => ConfirmTime != null;
|
||||||
|
|
||||||
public string RealName { get; set; }
|
public string RealName { get; set; }
|
||||||
|
|
||||||
|
|
|
@ -382,7 +382,7 @@ namespace IRaCIS.Application.Contracts
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SubmitVisitStudyBindingCommand
|
public class VerifyPacsImageCommand
|
||||||
{
|
{
|
||||||
[NotDefault]
|
[NotDefault]
|
||||||
public Guid TrialId { get; set; }
|
public Guid TrialId { get; set; }
|
||||||
|
@ -396,6 +396,13 @@ namespace IRaCIS.Application.Contracts
|
||||||
public List<Guid> SCPStudyIdList { get; set; }
|
public List<Guid> SCPStudyIdList { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class SubmitVisitStudyBindingCommand: VerifyPacsImageCommand
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
public List<Guid> ReUploadSCPStudyIdList { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class SubjectVisitSelectQuery
|
public class SubjectVisitSelectQuery
|
||||||
{
|
{
|
||||||
[NotDefault]
|
[NotDefault]
|
||||||
|
|
|
@ -264,7 +264,7 @@ namespace IRaCIS.Core.Application.Contracts
|
||||||
|
|
||||||
public bool IsCriticalSequence { get; set; } = false;
|
public bool IsCriticalSequence { get; set; } = false;
|
||||||
|
|
||||||
public int SeriesCount =>SeriesList.Count;
|
public int SeriesCount => SeriesList.Count;
|
||||||
public int InstanceCount { get; set; }
|
public int InstanceCount { get; set; }
|
||||||
|
|
||||||
public bool IsDicom { get; set; } = true;
|
public bool IsDicom { get; set; } = true;
|
||||||
|
@ -369,6 +369,16 @@ namespace IRaCIS.Core.Application.Contracts
|
||||||
public List<string> SOPInstanceUIDList { get; set; }
|
public List<string> SOPInstanceUIDList { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class VerifySCPStudyUploadResult
|
||||||
|
{
|
||||||
|
public Guid SCPStudyId { get; set; }
|
||||||
|
|
||||||
|
public string ErrorMesseage { get; set; } = String.Empty;
|
||||||
|
|
||||||
|
public bool AllowUpload { get; set; } = false;
|
||||||
|
|
||||||
|
public bool AllowReUpload { get; set; } = false;
|
||||||
|
}
|
||||||
|
|
||||||
public class VerifyStudyUploadResult
|
public class VerifyStudyUploadResult
|
||||||
{
|
{
|
||||||
|
|
|
@ -54,10 +54,12 @@ namespace IRaCIS.Application.Services
|
||||||
private readonly IRepository<SCPStudy> _scpStudyRepository;
|
private readonly IRepository<SCPStudy> _scpStudyRepository;
|
||||||
private readonly IRepository<Subject> _subjectRepository;
|
private readonly IRepository<Subject> _subjectRepository;
|
||||||
private readonly IRepository<SubjectVisit> _subjectVisitRepository;
|
private readonly IRepository<SubjectVisit> _subjectVisitRepository;
|
||||||
|
private readonly IRepository<Dictionary> _dictionaryRepository;
|
||||||
private readonly IDistributedLockProvider _distributedLockProvider;
|
private readonly IDistributedLockProvider _distributedLockProvider;
|
||||||
|
|
||||||
public PatientService(IRepository<SCPStudy> studyRepository, IRepository<Trial> trialRepository, IRepository<SCPPatient> patientRepository, IRepository<Subject> subjectRepository, IRepository<SubjectVisit> subjectVisitRepository, IDistributedLockProvider distributedLockProvider)
|
public PatientService(IRepository<SCPStudy> studyRepository, IRepository<Dictionary> dictionaryRepository, IRepository<Trial> trialRepository, IRepository<SCPPatient> patientRepository, IRepository<Subject> subjectRepository, IRepository<SubjectVisit> subjectVisitRepository, IDistributedLockProvider distributedLockProvider)
|
||||||
{
|
{
|
||||||
|
_dictionaryRepository = dictionaryRepository;
|
||||||
_scpStudyRepository = studyRepository;
|
_scpStudyRepository = studyRepository;
|
||||||
_trialRepository = trialRepository;
|
_trialRepository = trialRepository;
|
||||||
_patientRepository = patientRepository;
|
_patientRepository = patientRepository;
|
||||||
|
@ -75,7 +77,7 @@ namespace IRaCIS.Application.Services
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<IResponseOutput<PageOutput<SCPImageUploadView>>> GetSCPImageUploadList(SCPImageUploadQuery inQuery)
|
public async Task<IResponseOutput<PageOutput<SCPImageUploadView>>> GetSCPImageUploadList(SCPImageUploadQuery inQuery)
|
||||||
{
|
{
|
||||||
var query = _repository.Where<SCPImageUpload>(t=>t.TrialId==inQuery.TrialId)
|
var query = _repository.Where<SCPImageUpload>(t => t.TrialId == inQuery.TrialId)
|
||||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.CalledAE), t => t.CalledAE.Contains(inQuery.CalledAE))
|
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.CalledAE), t => t.CalledAE.Contains(inQuery.CalledAE))
|
||||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.CallingAEIP), t => t.CallingAEIP.Contains(inQuery.CallingAEIP))
|
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.CallingAEIP), t => t.CallingAEIP.Contains(inQuery.CallingAEIP))
|
||||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.CallingAE), t => t.CallingAE.Contains(inQuery.CallingAE))
|
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.CallingAE), t => t.CallingAE.Contains(inQuery.CallingAE))
|
||||||
|
@ -283,23 +285,122 @@ namespace IRaCIS.Application.Services
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<List<VerifySCPStudyUploadResult>> VerifyPacsImage(VerifyPacsImageCommand inCommand)
|
||||||
|
{
|
||||||
|
var trialId = inCommand.TrialId;
|
||||||
|
|
||||||
|
var subjectId = inCommand.SubjectId;
|
||||||
|
|
||||||
|
var isVerifyVisitImageDate = await _repository.Where<Trial>(t => t.Id == inCommand.TrialId).Select(t => t.IsVerifyVisitImageDate).FirstNotNullAsync();
|
||||||
|
|
||||||
|
var result = new List<VerifySCPStudyUploadResult>();
|
||||||
|
|
||||||
|
var visitList = _repository.Where<SubjectVisit>(t => t.SubjectId == inCommand.SubjectId).Select(t => new { t.VisitNum, t.EarliestScanDate, t.LatestScanDate, t.Id }).ToList();
|
||||||
|
|
||||||
|
var currentVisitNum = visitList.First(t => t.Id == inCommand.SubjectVisitId).VisitNum;
|
||||||
|
|
||||||
|
var scpStudyList = _scpStudyRepository.Where(t => inCommand.SCPStudyIdList.Contains(t.Id)).Select(t => new { StudyDate = t.StudyTime, t.Id }).ToList();
|
||||||
|
|
||||||
|
foreach (var waitUploadItem in scpStudyList)
|
||||||
|
{
|
||||||
|
if (isVerifyVisitImageDate)
|
||||||
|
{
|
||||||
|
//小于当前访视 最近的最晚拍片
|
||||||
|
var before = visitList.Where(u => u.VisitNum < currentVisitNum).Max(k => k.LatestScanDate);
|
||||||
|
|
||||||
|
if (before != null && waitUploadItem.StudyDate != null && before > waitUploadItem.StudyDate)
|
||||||
|
{
|
||||||
|
|
||||||
|
// $"当前访视检查时间{waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")}不能早于前序访视检查时间{before?.ToString("yyyy-MM-dd")},请核对检查数据是否有误",
|
||||||
|
result.Add(new VerifySCPStudyUploadResult() { ErrorMesseage = _localizer["Study_VisitBeforePrevError", waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")!, before?.ToString("yyyy-MM-dd")!] });
|
||||||
|
}
|
||||||
|
|
||||||
|
//大于当前访视 最近的最早拍片日期
|
||||||
|
var after = visitList.Where(u => u.VisitNum > currentVisitNum).Min(k => k.EarliestScanDate);
|
||||||
|
|
||||||
|
if (after != null && waitUploadItem.StudyDate != null && after < waitUploadItem.StudyDate)
|
||||||
|
{
|
||||||
|
// $"当前访视检查时间{waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")}不能晚于该访视之后的检查时间{after?.ToString("yyyy-MM-dd")},请核对检查数据是否有误"
|
||||||
|
result.Add(new VerifySCPStudyUploadResult() { ErrorMesseage = _localizer["Study_VisitAfterSubseqError", waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")!, after?.ToString("yyyy-MM-dd")!]});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var verifyStudyInfo = _repository.Where<DicomStudy>(t => t.TrialId == trialId && t.Id == waitUploadItem.Id).ProjectTo<VerifyStudyDto>(_mapper.ConfigurationProvider).FirstOrDefault();
|
||||||
|
|
||||||
|
var currentStudyResult = new VerifySCPStudyUploadResult();
|
||||||
|
|
||||||
|
//数据库不存在该检查 允许上传
|
||||||
|
if (verifyStudyInfo == null)
|
||||||
|
{
|
||||||
|
currentStudyResult.AllowUpload = true;
|
||||||
|
}
|
||||||
|
//数据库该项目有该检查 看是否支持重传
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//是同一个受试者 支持重传
|
||||||
|
if (verifyStudyInfo.SubjectId == subjectId && verifyStudyInfo.SubjectVisitId == inCommand.SubjectVisitId)
|
||||||
|
{
|
||||||
|
currentStudyResult.AllowReUpload = true;
|
||||||
|
}
|
||||||
|
//不是同一个受试者
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//有默认值,其实不用写,这里为了好理解
|
||||||
|
currentStudyResult.AllowUpload = false;
|
||||||
|
|
||||||
|
currentStudyResult.AllowReUpload = false;
|
||||||
|
|
||||||
|
//$"此处不可以上传。当前影像检查已经上传给受试者{verifyStudyInfo.SubjectCode}的{verifyStudyInfo.VisitName}"
|
||||||
|
currentStudyResult.ErrorMesseage = _localizer["Study_ImgAlreadyUploaded", verifyStudyInfo.SubjectCode, verifyStudyInfo.VisitName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Add(currentStudyResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 提交 患者检查和访视的绑定
|
/// 提交 患者检查和访视的绑定
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="inCommand"></param>
|
/// <param name="inCommand"></param>
|
||||||
|
/// <param name="_dicomstudyRepository"></param>
|
||||||
|
/// <param name="_dicomSeriesRepository"></param>
|
||||||
|
/// <param name="_dicomInstanceRepository"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[UnitOfWork]
|
[UnitOfWork]
|
||||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||||
public async Task<IResponseOutput> SubmitVisitStudyBinding(SubmitVisitStudyBindingCommand inCommand)
|
public async Task<IResponseOutput> SubmitVisitStudyBinding(SubmitVisitStudyBindingCommand inCommand,
|
||||||
|
[FromServices]IRepository<DicomStudy> _dicomstudyRepository,
|
||||||
|
[FromServices] IRepository<DicomSeries> _dicomSeriesRepository,
|
||||||
|
[FromServices] IRepository<DicomInstance> _dicomInstanceRepository)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
//这里要做校验 + 同时验证本地系统里面的影像是否存在pacs推过来的
|
||||||
|
|
||||||
|
var copyCommand = inCommand.Clone();
|
||||||
|
copyCommand.SCPStudyIdList = inCommand.SCPStudyIdList.Union(inCommand.ReUploadSCPStudyIdList).ToList();
|
||||||
|
var verifyResult = await VerifyPacsImage(copyCommand);
|
||||||
|
|
||||||
|
var allowUploadList = verifyResult.Where(u => u.AllowUpload == true).Select(t => t.SCPStudyId).ToList();
|
||||||
|
var allowReUploadList = verifyResult.Where(u => u.AllowReUpload == true).Select(t => t.SCPStudyId).ToList();
|
||||||
|
|
||||||
|
if (inCommand.SCPStudyIdList.All(t => allowUploadList.Contains(t)) && inCommand.ReUploadSCPStudyIdList.All(t => allowReUploadList.Contains(t)))
|
||||||
|
{
|
||||||
|
throw new BusinessValidationFailedException("对接提示: 前端提交的检查有不能上传的,请刷新页面调用验证接口重试!");
|
||||||
|
}
|
||||||
|
|
||||||
var subjectId = inCommand.SubjectId;
|
var subjectId = inCommand.SubjectId;
|
||||||
var subjectVisitId = inCommand.SubjectVisitId;
|
var subjectVisitId = inCommand.SubjectVisitId;
|
||||||
var trialId = inCommand.TrialId;
|
var trialId = inCommand.TrialId;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var @lock = _distributedLockProvider.CreateLock($"StudyCode");
|
var @lock = _distributedLockProvider.CreateLock($"StudyCode");
|
||||||
|
|
||||||
using (await @lock.AcquireAsync())
|
using (await @lock.AcquireAsync())
|
||||||
|
@ -308,6 +409,7 @@ namespace IRaCIS.Application.Services
|
||||||
|
|
||||||
int currentNextCodeInt = dbStudyCodeIntMax + 1;
|
int currentNextCodeInt = dbStudyCodeIntMax + 1;
|
||||||
|
|
||||||
|
//新增的,上传的
|
||||||
foreach (var scpStudyId in inCommand.SCPStudyIdList)
|
foreach (var scpStudyId in inCommand.SCPStudyIdList)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -315,7 +417,6 @@ namespace IRaCIS.Application.Services
|
||||||
|
|
||||||
if (find != null)
|
if (find != null)
|
||||||
{
|
{
|
||||||
|
|
||||||
var newStuty = _mapper.Map<DicomStudy>(find.SCPStudy);
|
var newStuty = _mapper.Map<DicomStudy>(find.SCPStudy);
|
||||||
|
|
||||||
await _repository.AddAsync(newStuty);
|
await _repository.AddAsync(newStuty);
|
||||||
|
@ -362,6 +463,93 @@ namespace IRaCIS.Application.Services
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var scpStudyId in inCommand.ReUploadSCPStudyIdList)
|
||||||
|
{
|
||||||
|
|
||||||
|
var study = await _dicomstudyRepository.FirstOrDefaultAsync(t => t.Id == scpStudyId);
|
||||||
|
|
||||||
|
var instanceIdList = _dicomInstanceRepository.Where(t => t.Id == scpStudyId).Select(t => t.Id).ToList();
|
||||||
|
|
||||||
|
var scpStudy = _scpStudyRepository.Where(t => t.Id == scpStudyId).Include(t=>t.SeriesList).ThenInclude(t=>t.SCPInstanceList).FirstOrDefault();
|
||||||
|
|
||||||
|
//以最后一次为准
|
||||||
|
study.IsFromPACS = true;
|
||||||
|
//特殊处理逻辑
|
||||||
|
study.Modalities = string.Join("、", scpStudy.SeriesList.Select(t => t.Modality).Union(study.Modalities.Split("、", StringSplitOptions.RemoveEmptyEntries)).Distinct());
|
||||||
|
|
||||||
|
SpecialArchiveStudyDeal(study);
|
||||||
|
|
||||||
|
|
||||||
|
// 少了整个序列
|
||||||
|
|
||||||
|
//某个序列下少了instance
|
||||||
|
foreach (var seriesItem in scpStudy.SeriesList)
|
||||||
|
{
|
||||||
|
var seriesId = IdentifierHelper.CreateGuid(seriesItem.StudyInstanceUid, seriesItem.SeriesInstanceUid, trialId.ToString());
|
||||||
|
|
||||||
|
DicomSeries dicomSeries = await _dicomSeriesRepository.FirstOrDefaultAsync(t => t.Id == seriesId);
|
||||||
|
|
||||||
|
//判断重复
|
||||||
|
if (dicomSeries == null)
|
||||||
|
{
|
||||||
|
var series = _mapper.Map<DicomSeries>(seriesItem);
|
||||||
|
|
||||||
|
series.SeqId = Guid.Empty;
|
||||||
|
series.TrialId = trialId;
|
||||||
|
series.SubjectId = subjectId;
|
||||||
|
series.SubjectVisitId = subjectVisitId;
|
||||||
|
|
||||||
|
|
||||||
|
dicomSeries = await _dicomSeriesRepository.AddAsync(series);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
foreach (var instanceItem in seriesItem.SCPInstanceList)
|
||||||
|
{
|
||||||
|
var instance = _mapper.Map<DicomInstance>(instanceItem);
|
||||||
|
|
||||||
|
instance.SeqId = Guid.Empty;
|
||||||
|
instance.TrialId = trialId;
|
||||||
|
instance.SubjectId = subjectId;
|
||||||
|
instance.SubjectVisitId = subjectVisitId;
|
||||||
|
|
||||||
|
await _dicomInstanceRepository.AddAsync(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
//新的序列 那么 检查的序列数量+1
|
||||||
|
study.SeriesCount += 1;
|
||||||
|
|
||||||
|
study.InstanceCount += seriesItem.SCPInstanceList.Count;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//该序列掉了instance
|
||||||
|
dicomSeries.InstanceCount += seriesItem.SCPInstanceList.Count;
|
||||||
|
|
||||||
|
var newInstanceList = seriesItem.SCPInstanceList.Where(t => !instanceIdList.Contains(t.Id));
|
||||||
|
|
||||||
|
foreach (var instanceItem in newInstanceList)
|
||||||
|
{
|
||||||
|
var instance = _mapper.Map<DicomInstance>(instanceItem);
|
||||||
|
|
||||||
|
instance.SeqId = Guid.Empty;
|
||||||
|
instance.TrialId = trialId;
|
||||||
|
instance.SubjectId = subjectId;
|
||||||
|
instance.SubjectVisitId = subjectVisitId;
|
||||||
|
|
||||||
|
await _dicomInstanceRepository.AddAsync(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
study.InstanceCount += newInstanceList.Count();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await _repository.SaveChangesAsync();
|
||||||
|
await _repository.BatchUpdateAsync<SCPPatient>(t => t.Id == scpStudy.PatientId, u => new SCPPatient() { SubjectId = subjectId });
|
||||||
|
await _repository.BatchUpdateAsync<SCPStudy>(t => t.Id == scpStudyId, u => new SCPStudy() { SubjectVisitId = subjectVisitId });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,6 +561,43 @@ namespace IRaCIS.Application.Services
|
||||||
return ResponseOutput.Ok();
|
return ResponseOutput.Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void SpecialArchiveStudyDeal(DicomStudy study)
|
||||||
|
{
|
||||||
|
#region 特殊逻辑
|
||||||
|
|
||||||
|
|
||||||
|
if (study.PatientBirthDate.Length == 8)
|
||||||
|
{
|
||||||
|
study.PatientBirthDate = $"{study.PatientBirthDate[0]}{study.PatientBirthDate[1]}{study.PatientBirthDate[2]}{study.PatientBirthDate[3]}-{study.PatientBirthDate[4]}{study.PatientBirthDate[5]}-{study.PatientBirthDate[6]}{study.PatientBirthDate[7]}";
|
||||||
|
}
|
||||||
|
|
||||||
|
var dicModalityList = _dictionaryRepository.Where(t => t.Code == "Modality").SelectMany(t => t.ChildList.Select(c => c.Value)).ToList();
|
||||||
|
|
||||||
|
|
||||||
|
var modality = study.Modalities;
|
||||||
|
|
||||||
|
var modalityForEdit = dicModalityList.Contains(modality) ? modality : String.Empty;
|
||||||
|
|
||||||
|
if (modality == "MR")
|
||||||
|
{
|
||||||
|
modalityForEdit = "MRI";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modality == "PT")
|
||||||
|
{
|
||||||
|
modalityForEdit = "PET";
|
||||||
|
}
|
||||||
|
if (modality == "PT、CT")
|
||||||
|
{
|
||||||
|
modalityForEdit = "PET-CT";
|
||||||
|
}
|
||||||
|
|
||||||
|
study.ModalityForEdit = modalityForEdit;
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ public static class StaticData
|
||||||
public static Dictionary<string, string> Log_Locoalize_Dic = new Dictionary<string, string>();
|
public static Dictionary<string, string> Log_Locoalize_Dic = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
|
||||||
|
#region 国际化
|
||||||
public static readonly string En_US_Json = "en-US.json";
|
public static readonly string En_US_Json = "en-US.json";
|
||||||
public static readonly string Zh_CN_Json = "zh-CN.json";
|
public static readonly string Zh_CN_Json = "zh-CN.json";
|
||||||
|
|
||||||
|
@ -70,8 +71,10 @@ public static class StaticData
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region 字典表项固定值
|
#region 字典表项固定值
|
||||||
|
|
||||||
public static readonly string Title = "Title";
|
public static readonly string Title = "Title";
|
||||||
public static readonly string ReadingType = "ReadingType";
|
public static readonly string ReadingType = "ReadingType";
|
||||||
public static readonly string Subspeciality = "Subspeciality";
|
public static readonly string Subspeciality = "Subspeciality";
|
||||||
|
@ -80,6 +83,7 @@ public static class StaticData
|
||||||
public static readonly string Criterion = "Criterion";
|
public static readonly string Criterion = "Criterion";
|
||||||
public static readonly string ReviewType = "ReviewType";
|
public static readonly string ReviewType = "ReviewType";
|
||||||
public static readonly string ReadingStandard = "ReadingStandard";
|
public static readonly string ReadingStandard = "ReadingStandard";
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue