整理检查服务
parent
5d96df5d00
commit
d8098a948a
|
@ -136,9 +136,9 @@ namespace IRaCIS.Core.API.Controllers
|
|||
|
||||
|
||||
|
||||
/// <summary> 流式上传 Dicom上传 需要返回文件数量 </summary>
|
||||
/// <summary> 流式上传 Dicom上传 </summary>
|
||||
[Route("base")]
|
||||
public virtual async Task<int> DicomFileUploadAsync(Func<string ,Stream, Task> filePathFunc)
|
||||
public virtual async Task<int> DicomFileUploadAsync(Func<string, Stream, Task> filePathFunc)
|
||||
{
|
||||
|
||||
var fileCount = 0;
|
||||
|
@ -155,7 +155,7 @@ namespace IRaCIS.Core.API.Controllers
|
|||
if (hasContentDispositionHeader)
|
||||
{
|
||||
|
||||
var fileName = contentDisposition.FileName.Value??String.Empty;
|
||||
var fileName = contentDisposition.FileName.Value ?? String.Empty;
|
||||
|
||||
string mediaType = section.ContentType ?? String.Empty;
|
||||
|
||||
|
@ -172,8 +172,6 @@ namespace IRaCIS.Core.API.Controllers
|
|||
++fileCount;
|
||||
|
||||
await filePathFunc(entry.Key, entry.OpenEntryStream());
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -186,11 +184,8 @@ namespace IRaCIS.Core.API.Controllers
|
|||
|
||||
await filePathFunc(fileName, section.Body);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
section = await reader.ReadNextSectionAsync();
|
||||
}
|
||||
|
@ -223,186 +218,6 @@ namespace IRaCIS.Core.API.Controllers
|
|||
_userInfo = userInfo;
|
||||
}
|
||||
|
||||
/// <summary>Dicom 归档</summary>
|
||||
[HttpPost, Route("Study/ArchiveStudy1/{trialId:guid}")]
|
||||
[DisableFormValueModelBinding]
|
||||
[DisableRequestSizeLimit]
|
||||
[TypeFilter(typeof(TrialResourceFilter))]
|
||||
public async Task<IResponseOutput> ArchiveStudy([FromForm] ArchiveStudyCommand archiveStudyCommand,
|
||||
[FromServices] ILogger<UploadDownLoadController> _logger,
|
||||
[FromServices] IEasyCachingProvider _provider,
|
||||
[FromServices] IStudyService _studyService,
|
||||
[FromServices] IDicomArchiveService _dicomArchiveService
|
||||
)
|
||||
{
|
||||
|
||||
string studycode = string.Empty;
|
||||
var startTime = DateTime.Now;
|
||||
|
||||
if (_provider.Exists("StudyUid_" + archiveStudyCommand.StudyInstanceUid))
|
||||
{
|
||||
return ResponseOutput.NotOk("当前已有人正在上传和归档该检查!");
|
||||
}
|
||||
else
|
||||
{
|
||||
_provider.Set("StudyUid_" + archiveStudyCommand.StudyInstanceUid, _userInfo.Id, TimeSpan.FromMinutes(30));
|
||||
}
|
||||
|
||||
var archiveResult = new DicomArchiveResult();
|
||||
var archivedStudyIds = new List<Guid>();
|
||||
|
||||
var (seriesInstanceUidList, sopInstanceUidList) = (new List<string>(), new List<string>());
|
||||
|
||||
//重传的时候,找出当前检查已经上传的series instance
|
||||
if (archiveStudyCommand.AbandonStudyId != null)
|
||||
{
|
||||
(seriesInstanceUidList, sopInstanceUidList) = _studyService.GetHasUploadSeriesAndInstance(archiveStudyCommand.AbandonStudyId.Value);
|
||||
}
|
||||
|
||||
var savedInfo = _studyService.GetSaveToDicomInfo(archiveStudyCommand.SubjectVisitId);
|
||||
|
||||
|
||||
var boundary = HeaderUtilities.RemoveQuotes(MediaTypeHeaderValue.Parse(Request.ContentType).Boundary).Value;
|
||||
var reader = new MultipartReader(boundary, HttpContext.Request.Body);
|
||||
var section = await reader.ReadNextSectionAsync();
|
||||
while (section != null)
|
||||
{
|
||||
//采用post方式 这里多加一个判断 过滤其他参数
|
||||
if (string.IsNullOrEmpty(section.ContentType))
|
||||
{
|
||||
section = await reader.ReadNextSectionAsync();
|
||||
continue;
|
||||
}
|
||||
|
||||
var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);
|
||||
if (hasContentDispositionHeader)
|
||||
{
|
||||
string fileName = contentDisposition.FileName.Value;
|
||||
try
|
||||
{
|
||||
|
||||
string mediaType = section.ContentType;
|
||||
|
||||
if (mediaType.Contains("zip"))
|
||||
{
|
||||
var partStream = section.Body;
|
||||
using (var zipArchive = new ZipArchive(partStream, ZipArchiveMode.Read))
|
||||
{
|
||||
foreach (var entry in zipArchive.Entries)
|
||||
{
|
||||
if (entry.FullName.EndsWith("/")) continue;
|
||||
try
|
||||
{
|
||||
++archiveResult.ReceivedFileCount;
|
||||
using (var memoryStream = new MemoryStream())
|
||||
{
|
||||
await section.Body.CopyToAsync(memoryStream);
|
||||
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
var archiveStudyId = await _dicomArchiveService.ArchiveDicomStreamAsync(memoryStream, savedInfo, seriesInstanceUidList, sopInstanceUidList);
|
||||
studycode = archiveStudyId.Item2;
|
||||
if (!archivedStudyIds.Contains(archiveStudyId.Item1))
|
||||
archivedStudyIds.Add(archiveStudyId.Item1);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
archiveResult.ErrorFiles.Add($"{fileName}/{entry.FullName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
++archiveResult.ReceivedFileCount;
|
||||
|
||||
|
||||
if (mediaType.Contains("octet-stream"))
|
||||
{
|
||||
using (var memoryStream = new MemoryStream())
|
||||
{
|
||||
await section.Body.CopyToAsync(memoryStream);
|
||||
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
var archiveStudyId = await _dicomArchiveService.ArchiveDicomStreamAsync(memoryStream, savedInfo, seriesInstanceUidList, sopInstanceUidList);
|
||||
studycode = archiveStudyId.Item2;
|
||||
|
||||
|
||||
if (!archivedStudyIds.Contains(archiveStudyId.Item1))
|
||||
archivedStudyIds.Add(archiveStudyId.Item1);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e.Message + e.StackTrace);
|
||||
|
||||
archiveResult.ErrorFiles.Add(fileName);
|
||||
|
||||
_provider.Remove("StudyUid_" + archiveStudyCommand.StudyInstanceUid);
|
||||
|
||||
}
|
||||
}
|
||||
section = await reader.ReadNextSectionAsync();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (archivedStudyIds.Count > 0) // 上传成功,处理逻辑
|
||||
{
|
||||
|
||||
|
||||
// 同一个访视 多个线程上传处理 批量保存 可能造成死锁 https://www.cnblogs.com/johnblogs/p/9945767.html
|
||||
|
||||
await _dicomArchiveService.DicomDBDataSaveChange();
|
||||
|
||||
//sw.Stop();
|
||||
_studyService.UploadOrReUploadNeedTodo(archiveStudyCommand, archivedStudyIds, ref archiveResult, new StudyMonitor()
|
||||
{
|
||||
TrialId = savedInfo.TrialId,
|
||||
SiteId = savedInfo.SiteId,
|
||||
SubjectId = savedInfo.SubjectId,
|
||||
SubjectVisitId = savedInfo.SubjectVisitId,
|
||||
StudyId = archivedStudyIds[0],
|
||||
|
||||
StudyCode = studycode,
|
||||
UploadStartTime = startTime,
|
||||
UploadFinishedTime = DateTime.Now,
|
||||
//TotalMillisecondsInterval = (DateTime.Now- startTime).TotalMilliseconds,
|
||||
FileSize = (decimal)HttpContext.Request.ContentLength,
|
||||
FileCount = archiveResult.ReceivedFileCount,
|
||||
IsDicom = true,
|
||||
IsDicomReUpload = archiveStudyCommand.AbandonStudyId != null,
|
||||
IP = _userInfo.IP
|
||||
});
|
||||
|
||||
_provider.Remove("StudyUid_" + archiveStudyCommand.StudyInstanceUid);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return ResponseOutput.NotOk("未完成该检查的归档");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
_logger.LogError(e.Message + e.StackTrace);
|
||||
|
||||
_provider.Remove("StudyUid_" + archiveStudyCommand.StudyInstanceUid);
|
||||
|
||||
return ResponseOutput.NotOk(e.Message, ApiResponseCodeEnum.ProgramException);
|
||||
|
||||
}
|
||||
|
||||
return ResponseOutput.Ok(archiveResult);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>Dicom 归档</summary>
|
||||
[HttpPost, Route("Study/ArchiveStudy/{trialId:guid}")]
|
||||
|
@ -413,7 +228,8 @@ namespace IRaCIS.Core.API.Controllers
|
|||
[FromServices] ILogger<UploadDownLoadController> _logger,
|
||||
[FromServices] IEasyCachingProvider _provider,
|
||||
[FromServices] IStudyService _studyService,
|
||||
[FromServices] IDicomArchiveService _dicomArchiveService
|
||||
[FromServices] IDicomArchiveService _dicomArchiveService,
|
||||
[FromServices] IRepository _repository
|
||||
)
|
||||
{
|
||||
|
||||
|
@ -438,42 +254,48 @@ namespace IRaCIS.Core.API.Controllers
|
|||
//重传的时候,找出当前检查已经上传的series instance
|
||||
if (archiveStudyCommand.AbandonStudyId != null)
|
||||
{
|
||||
(seriesInstanceUidList, sopInstanceUidList) =_studyService.GetHasUploadSeriesAndInstance(archiveStudyCommand.AbandonStudyId.Value);
|
||||
(seriesInstanceUidList, sopInstanceUidList) = _studyService.GetHasUploadSeriesAndInstance(archiveStudyCommand.AbandonStudyId.Value);
|
||||
}
|
||||
|
||||
var savedInfo = _studyService.GetSaveToDicomInfo(archiveStudyCommand.SubjectVisitId);
|
||||
|
||||
archiveResult.ReceivedFileCount= await DicomFileUploadAsync(async (fileName, fileStream) =>
|
||||
{
|
||||
archiveResult.ReceivedFileCount = await DicomFileUploadAsync(async (fileName, fileStream) =>
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
using (var memoryStream = new MemoryStream())
|
||||
{
|
||||
await fileStream.CopyToAsync(memoryStream);
|
||||
try
|
||||
{
|
||||
using (var memoryStream = new MemoryStream())
|
||||
{
|
||||
await fileStream.CopyToAsync(memoryStream);
|
||||
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
var archiveStudyId = await _dicomArchiveService.ArchiveDicomStreamAsync(memoryStream, savedInfo, seriesInstanceUidList, sopInstanceUidList);
|
||||
studycode = archiveStudyId.Item2;
|
||||
var (studyId, studyCode) = await _dicomArchiveService.ArchiveDicomStreamAsync(memoryStream, savedInfo, seriesInstanceUidList, sopInstanceUidList);
|
||||
|
||||
|
||||
if (!archivedStudyIds.Contains(archiveStudyId.Item1))
|
||||
archivedStudyIds.Add(archiveStudyId.Item1);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e.Message + e.StackTrace);
|
||||
|
||||
archiveResult.ErrorFiles.Add(fileName);
|
||||
|
||||
_provider.Remove("StudyUid_" + archiveStudyCommand.StudyInstanceUid);
|
||||
|
||||
}
|
||||
if (!archivedStudyIds.Contains(studyId))
|
||||
{
|
||||
archivedStudyIds.Add(studyId);
|
||||
archiveResult.ArchivedDicomStudies.Add(new DicomStudyBasicDTO() { StudyCode = studyCode, Id = studyId });
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e.Message + e.StackTrace);
|
||||
|
||||
archiveResult.ErrorFiles.Add(fileName);
|
||||
|
||||
_provider.Remove("StudyUid_" + archiveStudyCommand.StudyInstanceUid);
|
||||
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
try
|
||||
|
@ -485,7 +307,9 @@ namespace IRaCIS.Core.API.Controllers
|
|||
|
||||
await _dicomArchiveService.DicomDBDataSaveChange();
|
||||
|
||||
_studyService.UploadOrReUploadNeedTodo(archiveStudyCommand, archivedStudyIds, ref archiveResult, new StudyMonitor()
|
||||
archiveResult.ReuploadNewStudyId = archivedStudyIds[0] == archiveStudyCommand.AbandonStudyId ? archivedStudyIds[0] : Guid.Empty;
|
||||
|
||||
await _repository.AddAsync(new StudyMonitor()
|
||||
{
|
||||
TrialId = savedInfo.TrialId,
|
||||
SiteId = savedInfo.SiteId,
|
||||
|
@ -496,20 +320,22 @@ namespace IRaCIS.Core.API.Controllers
|
|||
StudyCode = studycode,
|
||||
UploadStartTime = startTime,
|
||||
UploadFinishedTime = DateTime.Now,
|
||||
//TotalMillisecondsInterval = (DateTime.Now- startTime).TotalMilliseconds,
|
||||
FileSize = (decimal)HttpContext.Request.ContentLength,
|
||||
FileCount = archiveResult.ReceivedFileCount,
|
||||
IsDicom = true,
|
||||
IsDicomReUpload = archiveStudyCommand.AbandonStudyId != null,
|
||||
IP = _userInfo.IP
|
||||
});
|
||||
}, true);
|
||||
|
||||
|
||||
//_studyService.UploadOrReUploadNeedTodo(archiveStudyCommand, archivedStudyIds, ref archiveResult, );
|
||||
|
||||
_provider.Remove("StudyUid_" + archiveStudyCommand.StudyInstanceUid);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return ResponseOutput.NotOk("未完成该检查的归档");
|
||||
return ResponseOutput.NotOk(archiveResult);
|
||||
}
|
||||
|
||||
|
||||
|
@ -543,7 +369,7 @@ namespace IRaCIS.Core.API.Controllers
|
|||
[HttpPost("ClinicalData/UploadVisitClinicalData/{trialId:guid}/{subjectVisitId:guid}")]
|
||||
[DisableRequestSizeLimit]
|
||||
[Authorize(Policy = IRaCISPolicy.CRC)]
|
||||
public async Task<IResponseOutput> UploadVisitClinicalData( Guid subjectVisitId, [FromServices] IRepository _repository)
|
||||
public async Task<IResponseOutput> UploadVisitClinicalData(Guid subjectVisitId, [FromServices] IRepository _repository)
|
||||
{
|
||||
await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId);
|
||||
|
||||
|
|
|
@ -159,12 +159,9 @@
|
|||
<summary> 流式上传 通用封装 不返回任何数据,后续还有事情处理 </summary>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.UploadBaseController.DicomFileUploadAsync(System.Func{System.String,System.IO.Stream,System.Threading.Tasks.Task})">
|
||||
<summary> 流式上传 Dicom上传 需要返回文件数量 </summary>
|
||||
<summary> 流式上传 Dicom上传 </summary>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.StudyController.ArchiveStudy(IRaCIS.Core.Application.Contracts.ArchiveStudyCommand,Microsoft.Extensions.Logging.ILogger{IRaCIS.Core.API.Controllers.UploadDownLoadController},EasyCaching.Core.IEasyCachingProvider,IRaCIS.Application.Interfaces.IStudyService,IRaCIS.Core.Application.Contracts.Dicom.IDicomArchiveService)">
|
||||
<summary>Dicom 归档</summary>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.StudyController.ArchiveStudyNew(IRaCIS.Core.Application.Contracts.ArchiveStudyCommand,Microsoft.Extensions.Logging.ILogger{IRaCIS.Core.API.Controllers.UploadDownLoadController},EasyCaching.Core.IEasyCachingProvider,IRaCIS.Application.Interfaces.IStudyService,IRaCIS.Core.Application.Contracts.Dicom.IDicomArchiveService)">
|
||||
<member name="M:IRaCIS.Core.API.Controllers.StudyController.ArchiveStudyNew(IRaCIS.Core.Application.Contracts.ArchiveStudyCommand,Microsoft.Extensions.Logging.ILogger{IRaCIS.Core.API.Controllers.UploadDownLoadController},EasyCaching.Core.IEasyCachingProvider,IRaCIS.Core.Application.Contracts.IStudyService,IRaCIS.Core.Application.Contracts.Dicom.IDicomArchiveService,IRaCIS.Core.Infra.EFCore.IRepository)">
|
||||
<summary>Dicom 归档</summary>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.StudyController.UploadVisitClinicalData(System.Guid,IRaCIS.Core.Infra.EFCore.IRepository)">
|
||||
|
|
|
@ -160,6 +160,13 @@
|
|||
批量验证 检查是否可以上传 并告知原因
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.Application.Service.ImageAndDoc.StudyService.GetSaveToDicomInfo(System.Guid)">
|
||||
<summary>
|
||||
获取保存到Dicom文件中的信息
|
||||
</summary>
|
||||
<param name="subjectVisitId"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:IRaCIS.Core.Application.Service.SystemAnonymizationService">
|
||||
<summary>
|
||||
SystemAnonymizationService
|
||||
|
@ -2223,13 +2230,6 @@
|
|||
分页获取奖励单价列表
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Application.Services.StudyService.GetSaveToDicomInfo(System.Guid)">
|
||||
<summary>
|
||||
获取保存到Dicom文件中的信息
|
||||
</summary>
|
||||
<param name="subjectVisitId"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Application.Services.CroService.GetCroList(IRaCIS.Application.Contracts.CROCompanyQueryDTO)">
|
||||
<summary> 分页获取CRO列表 </summary>
|
||||
</member>
|
||||
|
|
|
@ -7,6 +7,7 @@ namespace IRaCIS.Core.Application.Contracts.Dicom.DTO
|
|||
{
|
||||
public int ReceivedFileCount { get; set; }
|
||||
public ICollection<string> ErrorFiles { get; set; }
|
||||
|
||||
public ICollection<DicomStudyBasicDTO> ArchivedDicomStudies { get; set; }
|
||||
|
||||
public Guid ReuploadNewStudyId { get; set; } = Guid.Empty;
|
||||
|
@ -15,6 +16,7 @@ namespace IRaCIS.Core.Application.Contracts.Dicom.DTO
|
|||
{
|
||||
ReceivedFileCount = 0;
|
||||
ErrorFiles = new List<string>();
|
||||
|
||||
ArchivedDicomStudies = new List<DicomStudyBasicDTO>();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace IRaCIS.Core.Application.Services
|
|||
return success;
|
||||
}
|
||||
|
||||
public async Task<Tuple<Guid, string>> ArchiveDicomStreamAsync(Stream dicomStream,
|
||||
public async Task<(Guid StudyId, string StudyCode)> ArchiveDicomStreamAsync(Stream dicomStream,
|
||||
DicomTrialSiteSubjectInfo addtionalInfo, List<string> seriesInstanceUidList, List<string> instanceUidList)
|
||||
{
|
||||
|
||||
|
@ -63,7 +63,7 @@ namespace IRaCIS.Core.Application.Services
|
|||
|
||||
if (instanceUidList.Any(t => t == sopInstanceUid))
|
||||
{
|
||||
return new Tuple<Guid, string>(IdentifierHelper.CreateGuid(studyInstanceUid, addtionalInfo.TrialId.ToString()), string.Empty) ;
|
||||
return (IdentifierHelper.CreateGuid(studyInstanceUid, addtionalInfo.TrialId.ToString()), string.Empty) ;
|
||||
}
|
||||
|
||||
|
||||
|
@ -116,52 +116,6 @@ namespace IRaCIS.Core.Application.Services
|
|||
}
|
||||
|
||||
|
||||
#region 调整废弃
|
||||
////按照配置文件 匿名化
|
||||
//foreach (var anonymizeItem in SystemConfig.AnonymizeTagList)
|
||||
//{
|
||||
// if (anonymizeItem.Enable)
|
||||
// {
|
||||
// ushort group = Convert.ToUInt16(anonymizeItem.Group, 16);
|
||||
// ushort element = Convert.ToUInt16(anonymizeItem.Element, 16);
|
||||
// dataset.AddOrUpdate(new DicomTag(group, element), anonymizeItem.ReplaceValue);
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
//if (AppSettings.AddClinicalInfo) //是否需要写入临床信息
|
||||
//{
|
||||
// //Dicom 文件中写入临床信息
|
||||
// dataset.AddOrUpdate(DicomTag.ClinicalTrialProtocolID, addtionalInfo.TrialCode); //Trial
|
||||
// dataset.AddOrUpdate(DicomTag.ClinicalTrialProtocolName, addtionalInfo.TrialIndication); //indication
|
||||
// dataset.AddOrUpdate(DicomTag.ClinicalTrialSponsorName, addtionalInfo.Sponsor);//sponsor
|
||||
// dataset.AddOrUpdate(DicomTag.ClinicalTrialSiteID, addtionalInfo.SiteCode); //SiteId
|
||||
// dataset.AddOrUpdate(DicomTag.ClinicalTrialSiteName, addtionalInfo.SiteName);//SiteName
|
||||
// dataset.AddOrUpdate(DicomTag.ClinicalTrialSubjectID, addtionalInfo.SubjectCode + " " + addtionalInfo.SubjectSex);//SubjectId
|
||||
// dataset.AddOrUpdate(DicomTag.ClinicalTrialTimePointID, addtionalInfo.VisitNum.ToString()); // TimePoint
|
||||
// dataset.AddOrUpdate(DicomTag.ClinicalTrialTimePointDescription, addtionalInfo.VisitName + " " + addtionalInfo.SVUPDES);
|
||||
//}
|
||||
|
||||
//DicomStudy dicomStudy = null;
|
||||
//DicomSeries dicomSeries = null;
|
||||
//DicomInstance dicomInstance = null;
|
||||
|
||||
//lock (lockTest)
|
||||
//{
|
||||
// dicomStudy = CreateDicomStudy(dataset, addtionalInfo, out bool isStudyNeedAdd);
|
||||
// dicomSeries = CreateDicomSeries(dataset, dicomStudy, out bool isSeriesNeedAdd);
|
||||
// dicomInstance = CreateDicomInstance(dataset, dicomStudy, dicomSeries);
|
||||
|
||||
// if (isStudyNeedAdd) _studyRepository.Add(dicomStudy);
|
||||
// if (isSeriesNeedAdd) _seriesRepository.Add(dicomSeries);
|
||||
// _instanceRepository.Add(dicomInstance);
|
||||
//}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
DicomStudy dicomStudy = CreateDicomStudy(dataset, addtionalInfo, out bool isStudyNeedAdd);
|
||||
DicomSeries dicomSeries = CreateDicomSeries(dataset, dicomStudy, out bool isSeriesNeedAdd);
|
||||
DicomInstance dicomInstance = CreateDicomInstance(dataset, dicomStudy, dicomSeries);
|
||||
|
@ -210,7 +164,7 @@ namespace IRaCIS.Core.Application.Services
|
|||
if (dataset.InternalTransferSyntax.IsEncapsulated) await dicomFile.SaveAsync(filePath);
|
||||
else await dicomFile.Clone(DicomTransferSyntax.RLELossless).SaveAsync(filePath); //RLELossless
|
||||
}
|
||||
return new Tuple<Guid, string>(dicomInstance.StudyId, dicomStudy.StudyCode);
|
||||
return (dicomInstance.StudyId, dicomStudy.StudyCode);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{
|
||||
public interface IDicomArchiveService
|
||||
{
|
||||
Task<Tuple<Guid,string>> ArchiveDicomStreamAsync(Stream dicomStream, DicomTrialSiteSubjectInfo addtionalInfo, List<string> seriesInstanceUidList, List<string> instanceUidList);
|
||||
Task<(Guid StudyId, string StudyCode)> ArchiveDicomStreamAsync(Stream dicomStream, DicomTrialSiteSubjectInfo addtionalInfo, List<string> seriesInstanceUidList, List<string> instanceUidList);
|
||||
//ICollection<DicomStudyDTO> GetArchivedStudyList(List<Guid> archivedStudyIds);
|
||||
|
||||
Task<bool> DicomDBDataSaveChange();
|
||||
|
|
|
@ -1,97 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using IRaCIS.Core.Application.Contracts.Dicom.DTO;
|
||||
using System.Threading.Tasks;
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using IRaCIS.Core.Application.Contracts;
|
||||
using IRaCIS.Core.Application.Contracts;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace IRaCIS.Application.Interfaces
|
||||
namespace IRaCIS.Core.Application.Contracts
|
||||
{
|
||||
public interface IStudyService
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
//IResponseOutput ForwardStudy(Guid studyId);
|
||||
|
||||
DicomTrialSiteSubjectInfo GetSaveToDicomInfo(Guid subjctVisitId);
|
||||
|
||||
(List<string> SeriesInstanceUid, List<string> SopInstanceUid) GetHasUploadSeriesAndInstance(Guid studyId);
|
||||
|
||||
|
||||
void UploadOrReUploadNeedTodo(ArchiveStudyCommand archiveStudyCommand, List<Guid> archiveStudyIds, ref DicomArchiveResult reusult, StudyMonitor monitor);
|
||||
|
||||
|
||||
|
||||
//PageOutput<StudyDTO> GetStudyList(StudyQueryDTO queryDto);
|
||||
|
||||
|
||||
//Task<IResponseOutput> DicomAnonymize(Guid studyId, string optuserName);
|
||||
|
||||
|
||||
//List<StudyStatusDetailDTO> GetStudyStatusDetailList(Guid studyId);
|
||||
|
||||
|
||||
//IEnumerable<RelationVisitDTO> GetRelationVisitList(decimal visitNum, string tpCode);
|
||||
//List<SubjectVisitStudyDTO> GetSubjectVisitStudyList(Guid trialId, Guid siteId, Guid subjectId, Guid subjectVisitId);
|
||||
|
||||
//PageOutput<DistributeReviewerStudyStatusDTO> GetDistributeStudyList(StudyStatusQueryDTO studyStatusQueryDto);
|
||||
|
||||
|
||||
//IEnumerable<RelationStudyDTO> GetAllRelationStudyList(Guid studyId);
|
||||
|
||||
|
||||
//IEnumerable<StudyStatDTO> GetStudyStatList(Guid trialId, Guid subjectId, Guid siteId);
|
||||
|
||||
|
||||
//bool UpdateReUploadNewStudyCode(Guid studyId, Guid newStudyId);
|
||||
|
||||
|
||||
//void ReUploadSameStudy(Guid subjectVisitId, Guid studyId);
|
||||
|
||||
|
||||
//VerifyStudyUploadResult VerifyStudyAllowUpload(string studyInstanceUid, Guid trialId, Guid? studyId);
|
||||
|
||||
//List< VerifyStudyUploadResult> VerifyStudyAllowUpload(VerifyUploadOrReupload verifyList);
|
||||
|
||||
//void ClearStudyInstanceAndSeriseData(Guid studyId);
|
||||
|
||||
//IResponseOutput DeleteStudy(Guid id);
|
||||
|
||||
|
||||
|
||||
//Guid AddSubjectVisit(Guid subjectId, Guid siteId, Guid visitStageId, DateTime? SVSTDTC, DateTime? SVENDTC);
|
||||
//void UpdateSubjectLatestInfo(Guid subjectVisitId);
|
||||
|
||||
//void UpdateSubjectVisit(Guid subjectVisitId, Guid studyId);
|
||||
|
||||
//bool DistributeStudy(StudyReviewerCommand studyReviewer);
|
||||
|
||||
//IResponseOutput EditStudyReviewer(StudyReviewerEditCommand studyReviewerEditCommand);
|
||||
|
||||
|
||||
//void UploadStudyDeal(Guid studyId);
|
||||
|
||||
|
||||
//List<ReviewerDistributionDTO> GetReviewerListByTrialId(Guid trialId);
|
||||
|
||||
//IResponseOutput UpdateStudyStatus(StudyStatusDetailCommand studyStatusDetailDTO);
|
||||
|
||||
//string GetStudyPreview(Guid studyId);
|
||||
//DicomStudyDTO GetStudyItem(Guid studyId);
|
||||
|
||||
////bool SaveImageLabel(ImageLabelDTO label);
|
||||
//bool SaveImageLabelList(ImageLabelCommand imageLabelCommand);
|
||||
//IEnumerable<ImageLabelDTO> GetImageLabel(string tpCode);
|
||||
|
||||
//IResponseOutput DealNonDicomFile(Dictionary<string,string> filePathDic, ArchiveStudyCommand archiveStudyCommand);
|
||||
//bool ReUploadDifferentStudy(Guid subjectVisitId, Guid abandonStudyId, Guid newStudyId);
|
||||
|
||||
|
||||
//List<QANoticeDTO> GetQANoticeList(Guid studyId);
|
||||
|
||||
|
||||
|
||||
IResponseOutput<List<RelationStudyDTO>> GetAllRelationStudyList(Guid subjectVisitId);
|
||||
Task<PageOutput<UnionStudyViewModel>> GetDicomAndNoneDicomStudyList(StudyQuery studyQuery);
|
||||
Task<PageOutput<UnionStudyMonitorModel>> GetDicomAndNoneDicomStudyMonitorList(StudyQuery studyQuery);
|
||||
(List<string> SeriesInstanceUid, List<string> SopInstanceUid) GetHasUploadSeriesAndInstance(Guid studyId);
|
||||
DicomTrialSiteSubjectInfo GetSaveToDicomInfo(Guid subjectVisitId);
|
||||
IResponseOutput<DicomStudyDTO> Item(Guid studyId);
|
||||
Task<FileContentResult> Preview(Guid studyId);
|
||||
IResponseOutput<List<VerifyStudyUploadResult>> VerifyStudyAllowUpload(VerifyUploadOrReupload verifyInfo);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,586 +0,0 @@
|
|||
using IRaCIS.Core.Application.Contracts;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using IRaCIS.Core.Application.Dicom;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using IRaCIS.Core.Application.Services;
|
||||
using EasyCaching.Core;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
||||
{
|
||||
[ApiExplorerSettings(GroupName = "Image")]
|
||||
public class StudyService : BaseService
|
||||
{
|
||||
|
||||
private readonly DicomFileStoreHelper _dicomFileStoreHelper;
|
||||
private readonly IEasyCachingProvider _provider;
|
||||
|
||||
public StudyService(DicomFileStoreHelper dicomFileStoreHelper, IEasyCachingProvider provider)
|
||||
{
|
||||
_dicomFileStoreHelper = dicomFileStoreHelper;
|
||||
_provider = provider;
|
||||
}
|
||||
|
||||
|
||||
private Expression<Func<DicomStudy, bool>> GetDicomStudySubjectVisitFilter(string[]? VisitPlanArray)
|
||||
{
|
||||
Expression<Func<DicomStudy, bool>> svExpression = x => true;
|
||||
|
||||
bool isNeedVisitSearch = VisitPlanArray != null && VisitPlanArray?.Length > 0;
|
||||
|
||||
if (isNeedVisitSearch)
|
||||
{
|
||||
var inPlanArray = VisitPlanArray!.Where(t => !t.Contains('.')).Select(t => decimal.Parse(t)).ToArray();
|
||||
var isSelectOutPlan = VisitPlanArray!.Any(t => t.Contains('.'));
|
||||
|
||||
|
||||
if (inPlanArray.Length > 0)
|
||||
{
|
||||
svExpression = svExpression.And(t => inPlanArray.Contains(t.SubjectVisit.VisitNum));
|
||||
}
|
||||
|
||||
|
||||
if (isSelectOutPlan)
|
||||
{
|
||||
svExpression = svExpression.Or(t => t.SubjectVisit.InPlan == false);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return svExpression;
|
||||
}
|
||||
|
||||
|
||||
private Expression<Func<NoneDicomStudy, bool>> GetNoneDicomStudySubjectVisitFilter(string[]? VisitPlanArray)
|
||||
{
|
||||
Expression<Func<NoneDicomStudy, bool>> svExpression = x => true;
|
||||
|
||||
bool isNeedVisitSearch = VisitPlanArray != null && VisitPlanArray?.Length > 0;
|
||||
|
||||
if (isNeedVisitSearch)
|
||||
{
|
||||
var inPlanArray = VisitPlanArray!.Where(t => !t.Contains('.')).Select(t => decimal.Parse(t)).ToArray();
|
||||
var isSelectOutPlan = VisitPlanArray!.Any(t => t.Contains('.'));
|
||||
|
||||
|
||||
if (inPlanArray.Length > 0)
|
||||
{
|
||||
svExpression = svExpression.And(t => inPlanArray.Contains(t.SubjectVisit.VisitNum));
|
||||
}
|
||||
|
||||
|
||||
if (isSelectOutPlan)
|
||||
{
|
||||
svExpression = svExpression.Or(t => t.SubjectVisit.InPlan == false);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return svExpression;
|
||||
}
|
||||
|
||||
private Expression<Func<StudyMonitor, bool>> GetStudyMonitorSubjectVisitFilter(string[]? VisitPlanArray)
|
||||
{
|
||||
Expression<Func<StudyMonitor, bool>> svExpression = x => true;
|
||||
|
||||
bool isNeedVisitSearch = VisitPlanArray != null && VisitPlanArray?.Length > 0;
|
||||
|
||||
if (isNeedVisitSearch)
|
||||
{
|
||||
var inPlanArray = VisitPlanArray!.Where(t => !t.Contains('.')).Select(t => decimal.Parse(t)).ToArray();
|
||||
var isSelectOutPlan = VisitPlanArray!.Any(t => t.Contains('.'));
|
||||
|
||||
|
||||
if (inPlanArray.Length > 0)
|
||||
{
|
||||
svExpression = svExpression.And(t => inPlanArray.Contains(t.SubjectVisit.VisitNum));
|
||||
}
|
||||
|
||||
|
||||
if (isSelectOutPlan)
|
||||
{
|
||||
svExpression = svExpression.Or(t => t.SubjectVisit.InPlan == false);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return svExpression;
|
||||
}
|
||||
|
||||
|
||||
|
||||
[HttpPost]
|
||||
public async Task<PageOutput<UnionStudyViewModel>> GetDicomAndNoneDicomStudyList(StudyQuery studyQuery)
|
||||
{
|
||||
|
||||
var svExpression = GetDicomStudySubjectVisitFilter(studyQuery.VisitPlanArray);
|
||||
|
||||
var dicomStudyQuery = _repository.Where<DicomStudy>(t => t.TrialId == studyQuery.TrialId)
|
||||
.WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA, t => t.TrialSite.CRCUserList.Any(t => t.UserId == _userInfo.Id))
|
||||
//.WhereIf(!string.IsNullOrEmpty(studyQuery.VisitPlanInfo), studyQuery.VisitPlanInfo.Contains('.') ? t => t.SubjectVisit.VisitNum.ToString().Contains(".") : t => t.SubjectVisit.VisitNum == decimal.Parse(studyQuery.VisitPlanInfo))
|
||||
.WhereIf(studyQuery.VisitPlanArray != null && studyQuery.VisitPlanArray?.Length > 0, svExpression)
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(studyQuery.SubjectInfo), t => t.Subject.Code.Contains(studyQuery.SubjectInfo))
|
||||
.Select(t => new UnionStudyViewModel()
|
||||
{
|
||||
TrialId = t.TrialId,
|
||||
SiteId = t.SiteId,
|
||||
SubjectId = t.SubjectId,
|
||||
SubjectVisitId = t.SubjectVisitId,
|
||||
VisitName = t.SubjectVisit.VisitName,
|
||||
VisitNum = t.SubjectVisit.VisitNum,
|
||||
|
||||
IsDicom = true,
|
||||
|
||||
SubjectCode = t.Subject.Code,
|
||||
|
||||
Id = t.Id,
|
||||
|
||||
Bodypart = t.BodyPartExamined,
|
||||
|
||||
Modalities = t.Modalities,
|
||||
|
||||
Count = t.SeriesCount,
|
||||
|
||||
StudyCode = t.StudyCode,
|
||||
|
||||
//DicomStudyCode = t.StudyCode,
|
||||
//NoneDicomCode = 0,
|
||||
|
||||
StudyTime = t.StudyTime,
|
||||
|
||||
TrialSiteAliasName = t.TrialSite.TrialSiteAliasName,
|
||||
|
||||
TrialSiteCode = t.TrialSite.TrialSiteCode,
|
||||
|
||||
Uploader = t.Uploader.UserName,
|
||||
|
||||
UploadTime = t.CreateTime
|
||||
|
||||
});
|
||||
|
||||
|
||||
//.ProjectTo<UnionStudyViewDodel>(_mapper.ConfigurationProvider);
|
||||
var svExpression2 = GetNoneDicomStudySubjectVisitFilter(studyQuery.VisitPlanArray);
|
||||
|
||||
|
||||
var nodeDicomStudyQuery = _repository.Where<NoneDicomStudy>(t => t.TrialId == studyQuery.TrialId)
|
||||
.WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA, t => t.TrialSite.CRCUserList.Any(t => t.UserId == _userInfo.Id))
|
||||
//.WhereIf(!string.IsNullOrEmpty(studyQuery.VisitPlanInfo), studyQuery.VisitPlanInfo.Contains('.') ? t => t.SubjectVisit.VisitNum.ToString().Contains(".") : t => t.SubjectVisit.VisitNum == decimal.Parse(studyQuery.VisitPlanInfo))
|
||||
.WhereIf(studyQuery.VisitPlanArray != null && studyQuery.VisitPlanArray?.Length > 0, svExpression2)
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(studyQuery.SubjectInfo), t => t.Subject.Code.Contains(studyQuery.SubjectInfo))
|
||||
|
||||
.Select(t => new UnionStudyViewModel()
|
||||
{
|
||||
TrialId = t.TrialId,
|
||||
SiteId = t.SiteId,
|
||||
SubjectId = t.SubjectId,
|
||||
SubjectVisitId = t.SubjectVisitId,
|
||||
VisitName = t.SubjectVisit.VisitName,
|
||||
VisitNum = t.SubjectVisit.VisitNum,
|
||||
|
||||
IsDicom = false,
|
||||
|
||||
SubjectCode = t.Subject.Code,
|
||||
|
||||
Id = t.Id,
|
||||
|
||||
Bodypart = t.BodyPart,
|
||||
|
||||
Modalities = t.Modality,
|
||||
|
||||
Count = t.NoneDicomFileList.Count(),
|
||||
|
||||
StudyCode = t.StudyCode,
|
||||
|
||||
//NoneDicomCode = t.Code,
|
||||
//DicomStudyCode = string.Empty,
|
||||
|
||||
StudyTime = t.ImageDate,
|
||||
|
||||
TrialSiteAliasName = t.TrialSite.TrialSiteAliasName,
|
||||
|
||||
TrialSiteCode = t.TrialSite.TrialSiteCode,
|
||||
|
||||
Uploader = t.CreateUser.UserName,
|
||||
|
||||
UploadTime = t.CreateTime
|
||||
|
||||
});
|
||||
|
||||
//.ProjectTo<UnionStudyViewDodel>(_mapper.ConfigurationProvider);
|
||||
|
||||
|
||||
var unionQuery = dicomStudyQuery.Union(nodeDicomStudyQuery)
|
||||
.WhereIf(studyQuery.SubjectId != null, t => t.SubjectId == studyQuery.SubjectId)
|
||||
.WhereIf(studyQuery.SubjectVisitId != null, t => t.SubjectId == studyQuery.SubjectVisitId)
|
||||
.WhereIf(studyQuery.SiteId != null, t => t.SiteId == studyQuery.SiteId);
|
||||
|
||||
return await unionQuery.ToPagedListAsync(studyQuery.PageIndex, studyQuery.PageSize, studyQuery.SortField, studyQuery.Asc);
|
||||
}
|
||||
|
||||
|
||||
[HttpPost]
|
||||
public async Task<PageOutput<UnionStudyMonitorModel>> GetDicomAndNoneDicomStudyMonitorList(StudyQuery studyQuery)
|
||||
{
|
||||
var svExpression = GetStudyMonitorSubjectVisitFilter(studyQuery.VisitPlanArray);
|
||||
var StudyMonitorQuery = _repository.Where<StudyMonitor>(t => t.TrialId == studyQuery.TrialId)
|
||||
.WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA, t => t.TrialSite.CRCUserList.Any(t => t.UserId == _userInfo.Id))
|
||||
//.WhereIf(!string.IsNullOrEmpty(studyQuery.VisitPlanInfo), studyQuery.VisitPlanInfo.Contains('.') ? t => t.SubjectVisit.VisitNum.ToString().Contains(".") : t => t.SubjectVisit.VisitNum == decimal.Parse(studyQuery.VisitPlanInfo))
|
||||
.WhereIf(studyQuery.VisitPlanArray != null && studyQuery.VisitPlanArray?.Length > 0, svExpression)
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(studyQuery.SubjectInfo), t => t.Subject.Code.Contains(studyQuery.SubjectInfo))
|
||||
.WhereIf(studyQuery.SubjectId != null, t => t.SubjectId == studyQuery.SubjectId)
|
||||
.WhereIf(studyQuery.SubjectVisitId != null, t => t.SubjectId == studyQuery.SubjectVisitId)
|
||||
.WhereIf(studyQuery.SiteId != null, t => t.SiteId == studyQuery.SiteId)
|
||||
.Select(t => new UnionStudyMonitorModel()
|
||||
{
|
||||
TrialId = t.TrialId,
|
||||
SiteId = t.SiteId,
|
||||
SubjectId = t.SubjectId,
|
||||
SubjectVisitId = t.SubjectVisitId,
|
||||
VisitName = t.SubjectVisit.VisitName,
|
||||
VisitNum = t.SubjectVisit.VisitNum,
|
||||
|
||||
|
||||
|
||||
SubjectCode = t.Subject.Code,
|
||||
|
||||
|
||||
TrialSiteAliasName = t.TrialSite.TrialSiteAliasName,
|
||||
|
||||
TrialSiteCode = t.TrialSite.TrialSiteCode,
|
||||
|
||||
Uploader = t.Uploader.UserName,
|
||||
|
||||
UploadTime = t.CreateTime,
|
||||
|
||||
|
||||
IP = t.IP,
|
||||
FileCount = t.FileCount,
|
||||
FileSize = t.FileSize,
|
||||
UploadFinishedTime = t.UploadFinishedTime,
|
||||
UploadStartTime = t.UploadStartTime,
|
||||
|
||||
TotalMillisecondsInterval = t.TotalMillisecondsInterval,
|
||||
|
||||
IsDicomReUpload = t.IsDicomReUpload,
|
||||
StudyId = t.Id,
|
||||
IsDicom = t.IsDicom,
|
||||
|
||||
StudyCode = t.StudyCode
|
||||
|
||||
|
||||
});
|
||||
|
||||
return await StudyMonitorQuery.ToPagedListAsync(studyQuery.PageIndex, studyQuery.PageSize, string.IsNullOrEmpty(studyQuery.SortField) ? "UploadTime" : studyQuery.SortField, studyQuery.Asc);
|
||||
|
||||
|
||||
|
||||
#region 冗余查询
|
||||
//var dicomStudyQuery = _repository.Where<StudyMonitor>(t => t.TrialId == studyQuery.TrialId && t.IsDicom)
|
||||
// .WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator, t => t.TrialSite.CRCUserList.Any(t => t.UserId == _userInfo.Id))
|
||||
// .WhereIf(!string.IsNullOrEmpty(studyQuery.VisitPlanInfo), studyQuery.VisitPlanInfo.Contains('.') ? t => t.SubjectVisit.VisitNum.ToString().Contains(".") : t => t.SubjectVisit.VisitNum == decimal.Parse(studyQuery.VisitPlanInfo))
|
||||
// .WhereIf(!string.IsNullOrWhiteSpace(studyQuery.SubjectInfo), t => t.Subject.Code.Contains(studyQuery.SubjectInfo))
|
||||
// .Select(t => new UnionStudyMonitorModel()
|
||||
// {
|
||||
// TrialId = t.TrialId,
|
||||
// SiteId = t.SiteId,
|
||||
// SubjectId = t.SubjectId,
|
||||
// SubjectVisitId = t.SubjectVisitId,
|
||||
// VisitName = t.SubjectVisit.VisitName,
|
||||
// VisitNum = t.SubjectVisit.VisitNum,
|
||||
|
||||
|
||||
|
||||
// SubjectCode = t.Subject.Code,
|
||||
|
||||
|
||||
// TrialSiteAliasName = t.TrialSite.TrialSiteAliasName,
|
||||
|
||||
// TrialSiteCode = t.TrialSite.TrialSiteCode,
|
||||
|
||||
// Uploader = t.Uploader.FullName,
|
||||
|
||||
// UploadTime = t.CreateTime,
|
||||
|
||||
|
||||
// IP = t.IP,
|
||||
// FileCount = t.FileCount,
|
||||
// FileSize = t.FileSize,
|
||||
// UploadFinishedTime = t.UploadFinishedTime,
|
||||
// UploadStartTime = t.UploadStartTime,
|
||||
|
||||
// TotalMillisecondsInterval = t.TotalMillisecondsInterval,
|
||||
|
||||
// IsDicomReUpload = t.IsDicomReUpload,
|
||||
// StudyId = t.Id,
|
||||
// IsDicom = t.IsDicom,
|
||||
|
||||
// StudyCode = t.DicomStudy.StudyCode
|
||||
// //DicomStudyCode = t.DicomStudy.StudyCode,
|
||||
// //NoneDicomCode = 0,
|
||||
|
||||
// });
|
||||
|
||||
////.ProjectTo<UnionStudyViewDodel>(_mapper.ConfigurationProvider);
|
||||
|
||||
|
||||
|
||||
//var nodeDicomStudyQuery = _repository.Where<StudyMonitor>(t => t.TrialId == studyQuery.TrialId && t.IsDicom == false)
|
||||
// .WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator, t => t.TrialSite.CRCUserList.Any(t => t.UserId == _userInfo.Id))
|
||||
// .WhereIf(!string.IsNullOrEmpty(studyQuery.VisitPlanInfo), studyQuery.VisitPlanInfo.Contains('.') ? t => t.SubjectVisit.VisitNum.ToString().Contains(".") : t => t.SubjectVisit.VisitNum == decimal.Parse(studyQuery.VisitPlanInfo))
|
||||
// .WhereIf(!string.IsNullOrWhiteSpace(studyQuery.SubjectInfo), t => t.Subject.Code.Contains(studyQuery.SubjectInfo))
|
||||
|
||||
// .Select(t => new UnionStudyMonitorModel()
|
||||
// {
|
||||
|
||||
// TrialId = t.TrialId,
|
||||
// SiteId = t.SiteId,
|
||||
// SubjectId = t.SubjectId,
|
||||
// SubjectVisitId = t.SubjectVisitId,
|
||||
// VisitName = t.SubjectVisit.VisitName,
|
||||
// VisitNum = t.SubjectVisit.VisitNum,
|
||||
// SubjectCode = t.Subject.Code,
|
||||
// TrialSiteAliasName = t.TrialSite.TrialSiteAliasName,
|
||||
// TrialSiteCode = t.TrialSite.TrialSiteCode,
|
||||
// Uploader = t.Uploader.FullName,
|
||||
// UploadTime = t.CreateTime,
|
||||
|
||||
// IP = t.IP,
|
||||
// FileCount = t.FileCount,
|
||||
// FileSize = t.FileSize,
|
||||
// UploadFinishedTime = t.UploadFinishedTime,
|
||||
// UploadStartTime = t.UploadStartTime,
|
||||
|
||||
// TotalMillisecondsInterval = t.TotalMillisecondsInterval,
|
||||
|
||||
// IsDicomReUpload = t.IsDicomReUpload,
|
||||
// StudyId = t.Id,
|
||||
// IsDicom = t.IsDicom,
|
||||
|
||||
// StudyCode = t.NoneDicomStudy.StudyCode
|
||||
|
||||
// //DicomStudyCode = string.Empty,
|
||||
// //NoneDicomCode = t.NoneDicomStudy.Code,
|
||||
|
||||
// });
|
||||
|
||||
////.ProjectTo<UnionStudyViewDodel>(_mapper.ConfigurationProvider);
|
||||
|
||||
|
||||
//var unionQuery = dicomStudyQuery.Union(nodeDicomStudyQuery)
|
||||
// .WhereIf(studyQuery.SubjectId != null, t => t.SubjectId == studyQuery.SubjectId)
|
||||
// .WhereIf(studyQuery.SubjectVisitId != null, t => t.SubjectId == studyQuery.SubjectVisitId)
|
||||
// .WhereIf(studyQuery.SiteId != null, t => t.SiteId == studyQuery.SiteId);
|
||||
|
||||
//return await unionQuery.ToPagedListAsync(studyQuery.PageIndex, studyQuery.PageSize, string.IsNullOrEmpty(studyQuery.SortField) ? "UploadTime" : studyQuery.SortField, studyQuery.Asc);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary> 指定资源Id,渲染Dicom检查的Jpeg预览图像 </summary>
|
||||
/// <param name="studyId"> Dicom检查的Id </param>
|
||||
[HttpGet("{studyId:guid}")]
|
||||
public async Task<FileContentResult> Preview(Guid studyId)
|
||||
{
|
||||
string path = String.Empty;
|
||||
|
||||
DicomInstance dicomInstance = await _repository.FirstOrDefaultAsync<DicomInstance>(s => s.StudyId == studyId);
|
||||
|
||||
if (dicomInstance != null)
|
||||
{
|
||||
DicomStudy dicomStudy = await _repository.FirstOrDefaultAsync<DicomStudy>(s => s.Id == dicomInstance.StudyId);
|
||||
if (dicomStudy != null)
|
||||
{
|
||||
path = _dicomFileStoreHelper.GetInstanceFilePath(dicomStudy, dicomInstance.SeriesId, dicomInstance.Id.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
using (var sw = DicomRenderingHelper.RenderPreviewJpeg(path))
|
||||
{
|
||||
var bytes = new byte[sw.Length];
|
||||
sw.Read(bytes, 0, bytes.Length);
|
||||
sw.Close();
|
||||
return new FileContentResult(bytes, "image/jpeg");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取某个检查的关联检查列表(该受试者在这个想项目下的所有检查)
|
||||
/// 点击检查检查列表中的一个检查获取对应的序列列表(调用之前的接口:/series/list/,根据StudyId,获取访视的序列列表)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("{subjectVisitId:guid}")]
|
||||
[AllowAnonymous]
|
||||
public IResponseOutput<List<RelationStudyDTO>> GetAllRelationStudyList(Guid subjectVisitId)
|
||||
{
|
||||
#region 废弃
|
||||
//var studylist = _studyRepository.Where(u => u.SubjectVisitId == subjectVisitId && u.IsDeleted == false).Select(t => new { StudyId = t.Id, t.SubjectId, t.TrialId }).ToList();
|
||||
//var subjectId = studylist.FirstOrDefault().SubjectId;
|
||||
//var trialId = studylist.FirstOrDefault().TrialId;
|
||||
//var studyIds = studylist.Select(t => t.StudyId).ToList();
|
||||
|
||||
|
||||
//var query = from studyItem in _studyRepository.Where(u => u.SubjectId == subjectId
|
||||
// && u.TrialId == trialId && u.IsDeleted == false &&
|
||||
// !studyIds.Contains(u.Id)
|
||||
// /* && u.Status != (int)StudyStatus.Abandon*/)
|
||||
// join visitItem in _subjectVisitRepository.AsQueryable()
|
||||
// on studyItem.SubjectVisitId equals visitItem.Id
|
||||
// select new RelationStudyDTO
|
||||
// {
|
||||
// StudyId = studyItem.Id,
|
||||
// StudyCode = studyItem.StudyCode,
|
||||
// VisitName = visitItem.VisitName,
|
||||
// Modalities = studyItem.Modalities,
|
||||
// Description = studyItem.Description,
|
||||
// SeriesCount = studyItem.SeriesCount
|
||||
// };
|
||||
#endregion
|
||||
|
||||
var studyInfo = _repository.Where<DicomStudy>(u => u.SubjectVisitId == subjectVisitId).Select(t => new { t.SubjectId, t.TrialId }).FirstOrDefault().IfNullThrowException();
|
||||
|
||||
var query = _repository.Where<DicomStudy>(t => t.SubjectVisitId != subjectVisitId && t.TrialId == studyInfo.TrialId && t.SubjectId == studyInfo.SubjectId)
|
||||
.ProjectTo<RelationStudyDTO>(_mapper.ConfigurationProvider).ToList();
|
||||
|
||||
var list = query.OrderBy(u => u.VisitName).ThenBy(s => s.StudyCode).ToList();
|
||||
|
||||
return ResponseOutput.Ok(list);
|
||||
}
|
||||
|
||||
|
||||
/// <summary> 指定资源Id,获取Dicom检查信息 </summary>
|
||||
/// <param name="studyId"> Dicom检查的Id </param>
|
||||
[HttpGet, Route("{studyId:guid}")]
|
||||
[AllowAnonymous]
|
||||
public IResponseOutput<DicomStudyDTO> Item(Guid studyId)
|
||||
{
|
||||
return ResponseOutput.Ok(_mapper.Map<DicomStudyDTO>(_repository.Where<DicomStudy>().FirstOrDefault(s => s.Id == studyId)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 批量验证 检查是否可以上传 并告知原因
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
public IResponseOutput<List<VerifyStudyUploadResult>> VerifyStudyAllowUpload(VerifyUploadOrReupload verifyInfo)
|
||||
{
|
||||
var trialInfo = _repository.Where<Trial>().FirstOrDefault(t => t.Id == verifyInfo.TrialId).IfNullThrowException();
|
||||
|
||||
var result = new List<VerifyStudyUploadResult>();
|
||||
|
||||
var visitList = _repository.Where<SubjectVisit>(t => t.SubjectId == verifyInfo.SubjectId).Select(t => new { t.VisitNum, t.EarliestScanDate, t.LatestScanDate, t.Id }).ToList();
|
||||
|
||||
|
||||
verifyInfo.StudyInstanceUidList.ForEach(waitUploadItem =>
|
||||
{
|
||||
|
||||
if (trialInfo.IsVerifyVisitImageDate)
|
||||
{
|
||||
|
||||
//小于当前访视 最近的最晚拍片
|
||||
var before = visitList.Where(u => u.VisitNum < verifyInfo.VisitNum).Max(k => k.LatestScanDate);
|
||||
|
||||
if (before != null && waitUploadItem.StudyDate !=null && before > waitUploadItem.StudyDate)
|
||||
{
|
||||
result.Add(new VerifyStudyUploadResult() { ErrorMesseage = $"当前访视检查时间{waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")}不能早于前序访视检查时间{before?.ToString("yyyy-MM-dd")},请核对检查数据是否有误", StudyInstanceUid = waitUploadItem.StudyInstanceUid });
|
||||
return;
|
||||
}
|
||||
|
||||
//大于当前访视 最近的最早拍片日期
|
||||
var after = visitList.Where(u => u.VisitNum > verifyInfo.VisitNum).Min(k => k.EarliestScanDate);
|
||||
|
||||
if (after != null && waitUploadItem.StudyDate != null && after < waitUploadItem.StudyDate)
|
||||
{
|
||||
result.Add(new VerifyStudyUploadResult() { ErrorMesseage = $"当前访视检查时间{waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")}不能晚于该访视之后的检查时间{after?.ToString("yyyy-MM-dd")},请核对检查数据是否有误", StudyInstanceUid = waitUploadItem.StudyInstanceUid });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var temp = VerifyStudyUpload(waitUploadItem.StudyInstanceUid, verifyInfo.TrialId, verifyInfo.SubjectVisitId, verifyInfo.SubjectId);
|
||||
|
||||
result.Add(temp);
|
||||
});
|
||||
|
||||
return ResponseOutput.Ok(result);
|
||||
}
|
||||
|
||||
|
||||
private VerifyStudyUploadResult VerifyStudyUpload(string studyInstanceUid, Guid trialId, Guid currentSubjectVisitId, Guid SubjectId)
|
||||
{
|
||||
|
||||
var result = new VerifyStudyUploadResult();
|
||||
|
||||
if (_provider.Exists("StudyUid_" + studyInstanceUid))
|
||||
{
|
||||
result.AllowUpload = false;
|
||||
|
||||
result.AllowReUpload = false;
|
||||
result.StudyInstanceUid = studyInstanceUid;
|
||||
result.ErrorMesseage = "当前有人正在上传归档该检查!";
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (_repository.Where<Subject>(t => t.Id == SubjectId).Select(t => t.Status).FirstOrDefault() == SubjectStatus.EndOfVisit)
|
||||
{
|
||||
result.AllowUpload = false;
|
||||
|
||||
result.AllowReUpload = false;
|
||||
result.StudyInstanceUid = studyInstanceUid;
|
||||
result.ErrorMesseage = "受试者访视结束,不允许上传!";
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Guid expectStudyId = IdentifierHelper.CreateGuid(studyInstanceUid.Trim(), trialId.ToString());
|
||||
|
||||
|
||||
|
||||
var verifyStudyInfo = _repository.Where<DicomStudy>(t => t.TrialId == trialId && t.Id == expectStudyId).ProjectTo<VerifyStudyDto>(_mapper.ConfigurationProvider).FirstOrDefault();
|
||||
result.StudyInfo = verifyStudyInfo;
|
||||
|
||||
|
||||
//数据库不存在该检查 允许上传
|
||||
if (verifyStudyInfo == null)
|
||||
{
|
||||
result.AllowUpload = true;
|
||||
}
|
||||
//数据库该项目有该检查 看是否支持重传
|
||||
else
|
||||
{
|
||||
//是同一个受试者 支持重传
|
||||
if (verifyStudyInfo.SubjectId == SubjectId && verifyStudyInfo.SubjectVisitId == currentSubjectVisitId)
|
||||
{
|
||||
result.AllowReUpload = true;
|
||||
}
|
||||
//不是同一个受试者
|
||||
else
|
||||
{
|
||||
//有默认值,其实不用写,这里为了好理解
|
||||
result.AllowUpload = false;
|
||||
|
||||
result.AllowReUpload = false;
|
||||
|
||||
result.ErrorMesseage = $"此处不可以上传。当前影像检查已经上传给受试者{verifyStudyInfo.SubjectCode}的{verifyStudyInfo.VisitName}";
|
||||
}
|
||||
}
|
||||
result.StudyInstanceUid = studyInstanceUid;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -719,7 +719,7 @@ namespace IRaCIS.Core.Application.Image.QA
|
|||
[HttpPost, Route("{trialId:guid}/{subjectVisitId:guid}")]
|
||||
[TypeFilter(typeof(TrialResourceFilter))]
|
||||
[UnitOfWork]
|
||||
[Authorize(Policy = IRaCISPolicy.IQC)]
|
||||
[Authorize(Policy = IRaCISPolicy.CRC_IQC)]
|
||||
public async Task<IResponseOutput> DeleteStudyList(Guid[] ids, Guid subjectVisitId, Guid trialId)
|
||||
{
|
||||
|
||||
|
|
|
@ -9,10 +9,13 @@ namespace IRaCIS.Core.Application.Triggers
|
|||
public class SubjectVisitTrigger : IAfterSaveTrigger<NoneDicomStudy>, IAfterSaveTrigger<DicomStudy>, IAfterSaveTrigger<NoneDicomStudyFile>
|
||||
{
|
||||
private readonly IRepository<SubjectVisit> _subjectVisitRepository;
|
||||
private readonly IRepository _repository;
|
||||
|
||||
public SubjectVisitTrigger(IRepository<SubjectVisit> subjectVisitRepository)
|
||||
public SubjectVisitTrigger(IRepository<SubjectVisit> subjectVisitRepository,IRepository repository)
|
||||
{
|
||||
_subjectVisitRepository = subjectVisitRepository;
|
||||
|
||||
_repository = repository;
|
||||
}
|
||||
|
||||
//注意删除不能用扩展方法,必须用EF跟踪的实体 否则不能取到 SubjectVisitId
|
||||
|
@ -45,6 +48,15 @@ namespace IRaCIS.Core.Application.Triggers
|
|||
if (context.ChangeType == ChangeType.Added )
|
||||
{
|
||||
await UpdateSubjectVisitImageDateAsync(subjectVisitId);
|
||||
|
||||
var studyId = context.Entity.Id;
|
||||
//处理Modality
|
||||
var seriesModalityList = _repository.Where<DicomSeries>(t => t.StudyId == studyId).Select(u => u.Modality).Distinct();
|
||||
string ModaliyStr = string.Join('、', seriesModalityList.ToList());
|
||||
|
||||
|
||||
context.Entity.Modalities = ModaliyStr;
|
||||
|
||||
await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.Id == subjectVisitId, u => new SubjectVisit()
|
||||
{
|
||||
VisitExecuted = VisitExecutedEnum.Executed
|
||||
|
|
Loading…
Reference in New Issue