pacs 直连 增加修改
continuous-integration/drone/push Build is passing Details

IRC_NewDev
hang 2024-07-04 13:12:10 +08:00
parent a615b5cefd
commit 0c7495870b
11 changed files with 516 additions and 1334 deletions

View File

@ -24,39 +24,7 @@ using IRaCIS.Core.Infrastructure;
namespace IRaCIS.Core.SCP.Service
{
/// <summary>
/// 后台托管服务的方式运行
/// </summary>
//public class CStoreSCPHostedService : IHostedService
//{
// private readonly ILogger<CStoreSCPHostedService> _logger;
// private readonly IDicomServerFactory _dicomServerFactory;
// private IDicomServer? _server;
// public CStoreSCPHostedService(ILogger<CStoreSCPHostedService> logger, IDicomServerFactory dicomServerFactory)
// {
// _logger = logger ?? throw new ArgumentNullException(nameof(logger));
// _dicomServerFactory = dicomServerFactory ?? throw new ArgumentNullException(nameof(dicomServerFactory));
// }
// public async Task StartAsync(CancellationToken cancellationToken)
// {
// _logger.LogInformation("Starting DICOM server");
// _server = _dicomServerFactory.Create<CStoreSCPService>(104);
// _logger.LogInformation("DICOM server is running");
// }
// public Task StopAsync(CancellationToken cancellationToken)
// {
// if (_server != null)
// {
// _server.Stop();
// _server.Dispose();
// _server = null;
// }
// return Task.CompletedTask;
// }
//}
public class DicomSCPServiceOption
{
public List<string> CalledAEList { get; set; }
@ -75,6 +43,11 @@ namespace IRaCIS.Core.SCP.Service
private SCPImageUpload _upload { get; set; }
private Guid _trialId { get; set; }
private Guid _trialSiteId { get; set; }
private static readonly DicomTransferSyntax[] _acceptedTransferSyntaxes = new DicomTransferSyntax[]
{
@ -121,15 +94,37 @@ namespace IRaCIS.Core.SCP.Service
_serviceProvider = (IServiceProvider)this.UserState;
var option = _serviceProvider.GetService<IOptionsMonitor<DicomSCPServiceOption>>().CurrentValue;
var _trialDicomAERepository = _serviceProvider.GetService<IRepository<TrialDicomAE>>();
var calledAEList = option.CalledAEList;
if (!calledAEList.Contains(association.CalledAE))
var trialDicomAEList = _trialDicomAERepository.Select(t => new { t.CalledAE, t.TrialId }).ToList();
var trialCalledAEList = trialDicomAEList.Select(t => t.CalledAE).ToList();
//if (association.CalledAE != "STORESCP")
var findCalledAE = trialDicomAEList.Where(t => t.CalledAE == association.CalledAE).FirstOrDefault();
var isCanReceiveIamge = false;
if (findCalledAE!=null)
{
_trialId = findCalledAE.TrialId;
var _trialSiteDicomAERepository = _serviceProvider.GetService<IRepository<TrialSiteDicomAE>>();
var findTrialSiteAE = _trialSiteDicomAERepository.Where(t=>t.CallingAE==association.CallingAE ).FirstOrDefault();
if (findTrialSiteAE!=null)
{
_trialSiteId= findTrialSiteAE.TrialSiteId;
isCanReceiveIamge = true;
}
}
if (!trialCalledAEList.Contains(association.CalledAE) || isCanReceiveIamge==false)
{
Log.Logger.Warning($"拒绝CalledAE:{association.CalledAE}的连接");
@ -152,6 +147,8 @@ namespace IRaCIS.Core.SCP.Service
}
}
return SendAssociationAcceptAsync(association);
}
@ -167,7 +164,7 @@ namespace IRaCIS.Core.SCP.Service
_upload.EndTime = DateTime.Now;
_upload.StudyCount = _SCPStudyIdList.Count;
await _SCPImageUploadRepository.AddAsync(_upload,true);
await _SCPImageUploadRepository.AddAsync(_upload, true);
await SendAssociationReleaseResponseAsync();
}
@ -175,11 +172,9 @@ namespace IRaCIS.Core.SCP.Service
private async Task DataMaintenanceAsaync()
{
Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE}传输结束开始维护数据处理检查Modality 以及自动创建访视,绑定检查");
Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE}传输结束开始维护数据处理检查Modality");
//var patientStudyService = _serviceProvider.GetService<IPatientStudyService>();
//await patientStudyService.AutoBindingPatientStudyVisitAsync(_SCPStudyIdList);
//处理检查Modality
var _dictionaryRepository = _serviceProvider.GetService<IRepository<Dictionary>>();
@ -262,7 +257,7 @@ namespace IRaCIS.Core.SCP.Service
var _distributedLockProvider = _serviceProvider.GetService<IDistributedLockProvider>();
var storeRelativePath = string.Empty;
var ossFolderPath = $"Dicom/{studyInstanceUid}";
var ossFolderPath = $"{_trialId}/Image/PACS/{_trialSiteId}{studyInstanceUid}";
long fileSize = 0;
@ -295,7 +290,7 @@ namespace IRaCIS.Core.SCP.Service
{
try
{
var scpStudyId = await dicomArchiveService.ArchiveDicomFileAsync(request.Dataset, storeRelativePath, Association.CallingAE, Association.CalledAE);
var scpStudyId = await dicomArchiveService.ArchiveDicomFileAsync(request.Dataset,_trialId,_trialSiteId, storeRelativePath, Association.CallingAE, Association.CalledAE);
if (!_SCPStudyIdList.Contains(scpStudyId))
{
@ -324,11 +319,6 @@ namespace IRaCIS.Core.SCP.Service
series.ImageResizePath = seriesPath;
//await _seriesRepository.BatchUpdateNoTrackingAsync(t => t.Id == seriesId, u => new SCPSeries() { ImageResizePath = seriesPath });
}
}
@ -347,7 +337,7 @@ namespace IRaCIS.Core.SCP.Service
//监控信息设置
_upload.FileCount++;
_upload.FileSize= _upload.FileSize+ fileSize;
_upload.FileSize = _upload.FileSize + fileSize;
return new DicomCStoreResponse(request, DicomStatus.Success);
}

View File

@ -50,7 +50,7 @@ namespace IRaCIS.Core.SCP.Service
/// <param name="dataset"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<Guid> ArchiveDicomFileAsync(DicomDataset dataset, string fileRelativePath, string callingAE, string calledAE)
public async Task<Guid> ArchiveDicomFileAsync(DicomDataset dataset, Guid trialId, Guid trialSiteId, string fileRelativePath, string callingAE, string calledAE)
{
string studyInstanceUid = dataset.GetString(DicomTag.StudyInstanceUID);
string seriesInstanceUid = dataset.GetString(DicomTag.SeriesInstanceUID);
@ -59,9 +59,9 @@ namespace IRaCIS.Core.SCP.Service
string patientIdStr = dataset.GetString(DicomTag.PatientID);
//Guid patientId= IdentifierHelper.CreateGuid(patientIdStr);
Guid studyId = IdentifierHelper.CreateGuid(studyInstanceUid);
Guid seriesId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid);
Guid instanceId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, sopInstanceUid);
Guid studyId = IdentifierHelper.CreateGuid(studyInstanceUid,trialId.ToString());
Guid seriesId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, trialId.ToString());
Guid instanceId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, sopInstanceUid, trialId.ToString());
var isStudyNeedAdd = false;
var isSeriesNeedAdd = false;
@ -88,6 +88,8 @@ namespace IRaCIS.Core.SCP.Service
findPatient = new SCPPatient()
{
Id = NewId.NextSequentialGuid(),
TrialId=trialId,
TrialSiteId=trialSiteId,
PatientIdStr = dataset.GetSingleValueOrDefault(DicomTag.PatientID, string.Empty),
PatientName = dataset.GetSingleValueOrDefault(DicomTag.PatientName, string.Empty),
PatientAge = dataset.GetSingleValueOrDefault(DicomTag.PatientAge, string.Empty),
@ -145,6 +147,8 @@ namespace IRaCIS.Core.SCP.Service
PatientId = findPatient.Id,
Id = studyId,
TrialId = trialId,
TrialSiteId = trialSiteId,
StudyInstanceUid = studyInstanceUid,
StudyTime = studyTime,
Modalities = dataset.GetSingleValueOrDefault(DicomTag.Modality, string.Empty),

View File

@ -5,7 +5,7 @@ namespace IRaCIS.Core.SCP.Service
{
public interface IDicomArchiveService
{
Task<Guid> ArchiveDicomFileAsync(DicomDataset dicomDataset,string fileRelativePath,string callingAE,string calledAE);
Task<Guid> ArchiveDicomFileAsync(DicomDataset dicomDataset,Guid trialId,Guid trialSiteId, string fileRelativePath,string callingAE,string calledAE);
}
}

View File

@ -9818,7 +9818,7 @@
DicomAEService
</summary>
</member>
<member name="M:IRaCIS.Core.Application.Service.TrialDicomAEService.GetTrialDicomAEList(System.Guid)">
<member name="M:IRaCIS.Core.Application.Service.TrialDicomAEService.GetTrialDicomAE(System.Guid)">
<summary>
获取项目dicom AE 配置信息otherinfo里面有IsPACSConnect IsTrialPACSConfirmed
</summary>
@ -15048,6 +15048,41 @@
<param name="status">9-拒绝入组10-确认入组</param>
<returns></returns>
</member>
<member name="M:IRaCIS.Application.Services.PatientService.GetSCPImageUploadList(IRaCIS.Application.Contracts.SCPImageUploadQuery)">
<summary>
scp 影像推送记录表
</summary>
<param name="inQuery"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Application.Services.PatientService.GetPatientList(IRaCIS.Application.Contracts.PatientTrialQuery)">
<summary>
影像检查列表-患者为维度组织
</summary>
<param name="inQuery"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Application.Services.PatientService.GetPatientStudyList(IRaCIS.Application.Contracts.PatientStudyInfoQuery)">
<summary>
影像检查列表-> 获取患者的检查列表
</summary>
<param name="inQuery"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Application.Services.PatientService.GetVisitPatientStudyFilterList(IRaCIS.Application.Contracts.VisitPatientStudyFilterQuery)">
<summary>
影像访视上传 检查列表
</summary>
<param name="inQuery"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Application.Services.PatientService.SubmitVisitStudyBinding(IRaCIS.Application.Contracts.SubmitVisitStudyBindingCommand)">
<summary>
提交 患者检查和访视的绑定
</summary>
<param name="inCommand"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Application.Services.SubjectService.AddOrUpdateSubject(IRaCIS.Application.Contracts.SubjectCommand)">
<summary>
添加或更新受试者信息[New]

View File

@ -224,31 +224,41 @@ namespace IRaCIS.Application.Contracts
{
public string? PatientIdStr { get; set; }
public string? PatientName { get; set; }
public List<string> CalledAEList { get; set; } = new List<string>();
//public List<string> CalledAEList { get; set; } = new List<string>();
public string? CallingAE { get; set; }
public string? ExperimentName { get; set; } = string.Empty;
public string? CalledAE { get; set; }
public DateTime? BeginPushTime { get; set; }
public DateTime? EndPushTime { get; set; }
public string SubejctCode { get; set; }
public string TrialSiteKeyInfo { get; set; }
}
public class PatientTrialView : PatientQueryView
public class PatientSubjectView : PatientQueryView
{
public int? StudyCount { get; set; }
public List<PatientTrialStatInfo> TrialList { get; set; }
public Guid? SubejctId { get; set; }
public Guid TrialId { get; set; }
public string? SubjectCode { get; set; }
public string? TrialSiteCode { get; set; }
public string? TrialSiteName { get; set; }
public string? TrialSiteAliasName { get; set; }
}
public class PatientTrialStatInfo
{
public int? VisitCount { get; set; }
public string ExperimentName { get; set; }
}
public class PatientQuery : PageInput
{
@ -377,7 +387,10 @@ namespace IRaCIS.Application.Contracts
[NotDefault]
public Guid SubjectId { get; set; }
public List<Guid> SubjectVisitIdList { get; set; }
[NotDefault]
public Guid SubjectVisitId { get; set; }
public List<Guid> SCPStudyIdList { get; set; }
}
public class SubjectVisitSelectQuery
@ -938,6 +951,8 @@ namespace IRaCIS.Application.Contracts
public class SCPImageUploadQuery : PageInput
{
public string TrialSiteKeyInfo { get; set; }
public string? CallingAE { get; set; }
public string? CalledAE { get; set; }
@ -966,7 +981,18 @@ namespace IRaCIS.Application.Contracts
public long FileSize { get; set; }
public int StudyCount { get; set; }
public Guid TrialId { get; set; }
public Guid TrialSiteId { get; set; }
public string TrialSiteCode { get; set; }
public string TrialSiteName { get; set; }
public string TrialSiteAliasName { get; set; }
}
public class VisitPatientStudyView : PatientStudySelectDto
{
@ -990,7 +1016,20 @@ namespace IRaCIS.Application.Contracts
}
public class PatientStudySimpleView
public class VisitPatientStudyFilterQuery : PageInput
{
[NotDefault]
public Guid SubjectId { get; set; }
[NotDefault]
public Guid SubjectVisitId { get; set; }
public DateTime? EarliestStudyTime { get; set; }
public DateTime? LatestStudyTime { get; set; }
public string? Modalities { get; set; }
}
public class VisitPatientStudyFilterView
{
public Guid SCPStudyId { get; set; }
@ -1006,9 +1045,32 @@ namespace IRaCIS.Application.Contracts
public string CalledAE { get; set; } = string.Empty;
public string CallingAE { get; set; } = string.Empty;
}
public class PatientStudySimpleView: VisitPatientStudyFilterView
{
public Guid? SubjectVisitId { get; set; }
public string? VisitName { get; set; }
public string? BlindName { get; set; } = string.Empty;
//public SubjectVisitInfo SubejectVisit { get; set; }
}
public class SubjectVisitInfo
{
public Guid Id { get; set; }
public string VisitName { get; set; }
public decimal VisitNum { get; set; }
public string BlindName { get; set; } = string.Empty;
}
public class PatientSeriesDTO

File diff suppressed because it is too large Load Diff

View File

@ -112,6 +112,14 @@ namespace IRaCIS.Core.Application.Service
.ForMember(d => d.InstanceInfoList, u => u.MapFrom(s => s.InstanceList));
CreateMap<TaskInstance, InstanceBasicInfo>();
CreateMap<SCPImageUpload, SCPImageUploadView>()
.ForMember(d => d.TrialSiteCode, u => u.MapFrom(s => s.TrialSite.TrialSiteCode))
.ForMember(d => d.TrialSiteAliasName, u => u.MapFrom(s => s.TrialSite.TrialSiteAliasName))
.ForMember(d => d.TrialSiteName, u => u.MapFrom(s => s.TrialSite.TrialSiteName))
;
}
}

View File

@ -99,5 +99,8 @@ namespace IRaCIS.Core.Domain.Models
public Guid? DeleteUserId { get; set; }
public bool IsFromPACS { get; set; }
}
}

View File

@ -55,6 +55,19 @@ namespace IRaCIS.Core.Domain.Models
public int StudyCount { get; set; }
public Guid TrialId { get; set; }
public Guid TrialSiteId { get; set; }
[JsonIgnore]
public Trial Trial { get; set; }
[JsonIgnore]
public TrialSite TrialSite { get; set; }
}

View File

@ -29,9 +29,17 @@ namespace IRaCIS.Core.Domain.Models
public DateTime LatestPushTime { get; set; }
public Guid? SubjectId { get; set; }
public Guid TrialId { get; set; }
public Guid TrialSiteId { get; set; }
[JsonIgnore]
public Subject Subject { get; set; }
public Guid? SubjectId { get; set; }
[JsonIgnore]
public Trial Trial { get; set; }
[JsonIgnore]
public TrialSite TrialSite { get; set; }
}
}

View File

@ -84,12 +84,20 @@ namespace IRaCIS.Core.Domain.Models
public bool IsUploadFinished { get; set; }
public Guid TrialId { get; set; }
public Guid TrialSiteId { get; set; }
public Guid? SubjectVisitId { get; set; }
[JsonIgnore]
public SubjectVisit SubjectVisit { get; set; }
[JsonIgnore]
public Trial Trial { get; set; }
[JsonIgnore]
public TrialSite TrialSite { get; set; }
}
}