增加打包状态 crc列表增加字段,影像下载打包迁移
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
2933d100f7
commit
85439213b2
|
@ -96,8 +96,8 @@ namespace IRaCIS.Core.Application.Helper
|
|||
|
||||
public interface IOSSService
|
||||
{
|
||||
public Task<string> UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName);
|
||||
public Task<string> UploadToOSSAsync(string localFilePath, string oosFolderPath);
|
||||
public Task<string> UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName, bool isFileNameAddGuid = true);
|
||||
public Task<string> UploadToOSSAsync(string localFilePath, string oosFolderPath, bool isFileNameAddGuid = true);
|
||||
|
||||
public Task DownLoadFromOSSAsync(string ossRelativePath, string localFilePath);
|
||||
|
||||
|
@ -124,12 +124,12 @@ namespace IRaCIS.Core.Application.Helper
|
|||
/// <param name="fileStream"></param>
|
||||
/// <param name="oosFolderPath"></param>
|
||||
/// <param name="fileRealName"></param>
|
||||
/// <param name="isFileNameAddGuid"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<string> UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName)
|
||||
public async Task<string> UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName, bool isFileNameAddGuid = true)
|
||||
{
|
||||
|
||||
|
||||
var ossRelativePath = $"{oosFolderPath}/{Guid.NewGuid()}_{fileRealName}";
|
||||
var ossRelativePath = isFileNameAddGuid ? $"{oosFolderPath}/{Guid.NewGuid()}_{fileRealName}" : $"{oosFolderPath}/{fileRealName}";
|
||||
//var ossRelativePath = $"{oosFolderPath}/{Guid.NewGuid()}_{fileRealName}";
|
||||
//var ossRelativePath = oosFolderPath + "/" + fileRealName;
|
||||
|
||||
using (var memoryStream = new MemoryStream())
|
||||
|
@ -207,11 +207,12 @@ namespace IRaCIS.Core.Application.Helper
|
|||
/// <param name="oosFolderPath"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="BusinessValidationFailedException"></exception>
|
||||
public async Task<string> UploadToOSSAsync(string localFilePath, string oosFolderPath)
|
||||
public async Task<string> UploadToOSSAsync(string localFilePath, string oosFolderPath, bool isFileNameAddGuid = true)
|
||||
{
|
||||
var localFileName = Path.GetFileName(localFilePath);
|
||||
|
||||
var ossRelativePath = $"{oosFolderPath}/{Guid.NewGuid()}_{localFileName}";
|
||||
var ossRelativePath = isFileNameAddGuid ? $"{oosFolderPath}/{Guid.NewGuid()}_{localFileName}" : $"{oosFolderPath}/{localFileName}";
|
||||
|
||||
|
||||
//var ossRelativePath = oosFolderPath + "/" + localFileName;
|
||||
|
||||
|
@ -266,6 +267,7 @@ namespace IRaCIS.Core.Application.Helper
|
|||
|
||||
}
|
||||
|
||||
|
||||
public async Task DownLoadFromOSSAsync(string ossRelativePath, string localFilePath)
|
||||
{
|
||||
|
||||
|
|
|
@ -84,16 +84,17 @@
|
|||
<param name="type"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.Application.Helper.OSSService.UploadToOSSAsync(System.IO.Stream,System.String,System.String)">
|
||||
<member name="M:IRaCIS.Core.Application.Helper.OSSService.UploadToOSSAsync(System.IO.Stream,System.String,System.String,System.Boolean)">
|
||||
<summary>
|
||||
oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder
|
||||
</summary>
|
||||
<param name="fileStream"></param>
|
||||
<param name="oosFolderPath"></param>
|
||||
<param name="fileRealName"></param>
|
||||
<param name="isFileNameAddGuid"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.Application.Helper.OSSService.UploadToOSSAsync(System.String,System.String)">
|
||||
<member name="M:IRaCIS.Core.Application.Helper.OSSService.UploadToOSSAsync(System.String,System.String,System.Boolean)">
|
||||
<summary>
|
||||
oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder
|
||||
</summary>
|
||||
|
@ -852,6 +853,24 @@
|
|||
后台托管服务的方式运行
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.Application.Service.ImageAndDoc.DownloadAndUploadService.RequestPackageAndAnonymizImage(System.Guid,System.Guid,System.Boolean)">
|
||||
<summary>
|
||||
打包和匿名化影像 默认是匿名化打包,也可以不匿名化打包
|
||||
</summary>
|
||||
<param name="trialId"></param>
|
||||
<param name="subjectVisitId"></param>
|
||||
<param name="isAnonymize"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.Application.Service.ImageAndDoc.DownloadAndUploadService.PackageAndAnonymizImage(System.Guid,System.Guid,System.Boolean)">
|
||||
<summary>
|
||||
后台任务调用,前端忽略该接口
|
||||
</summary>
|
||||
<param name="trialId"></param>
|
||||
<param name="subjectVisitId"></param>
|
||||
<param name="isAnonymize"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.Application.Service.ImageAndDoc.StudyService.AddOrUpdateArchiveStudy(IRaCIS.Core.Application.Contracts.NewArchiveStudyCommand)">
|
||||
<summary>
|
||||
上传临床数据
|
||||
|
|
|
@ -0,0 +1,232 @@
|
|||
using FellowOakDicom;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using MassTransit;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
||||
{
|
||||
public interface IDownloadAndUploadService
|
||||
{
|
||||
Task PackageAndAnonymizImage(Guid trialId, Guid subjectVisitId, bool isAnonymize = true);
|
||||
}
|
||||
[ApiExplorerSettings(GroupName = "Trial")]
|
||||
public class DownloadAndUploadService : BaseService, IDownloadAndUploadService
|
||||
{
|
||||
|
||||
private readonly IRepository<SystemAnonymization> _systemAnonymizationRepository;
|
||||
private readonly IRepository<SubjectVisit> _subjectVisitRepository;
|
||||
private readonly IOSSService _oSSService;
|
||||
public DownloadAndUploadService(IRepository<SystemAnonymization> systemAnonymizationRepository, IRepository<SubjectVisit> subjectVisitRepository, IOSSService oSSService)
|
||||
{
|
||||
_systemAnonymizationRepository = systemAnonymizationRepository;
|
||||
|
||||
_subjectVisitRepository = subjectVisitRepository;
|
||||
|
||||
_oSSService = oSSService;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 打包和匿名化影像 默认是匿名化打包,也可以不匿名化打包
|
||||
/// </summary>
|
||||
/// <param name="trialId"></param>
|
||||
/// <param name="subjectVisitId"></param>
|
||||
/// <param name="isAnonymize"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
public async Task<IResponseOutput> RequestPackageAndAnonymizImage(Guid trialId, Guid subjectVisitId, bool isAnonymize = true)
|
||||
{
|
||||
var subjectVisit = await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId);
|
||||
|
||||
if (subjectVisit.PackState == PackState.WaitPack)
|
||||
{
|
||||
HangfireJobHelper.NotImmediatelyOnceOnlyJob<IDownloadAndUploadService>(t => t.PackageAndAnonymizImage(trialId, subjectVisitId, isAnonymize), TimeSpan.FromSeconds(1));
|
||||
|
||||
subjectVisit.PackState = PackState.Packing;
|
||||
|
||||
await _subjectVisitRepository.SaveChangesAsync();
|
||||
|
||||
}
|
||||
|
||||
return ResponseOutput.Ok(subjectVisit.VisitImageZipPath);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 后台任务调用,前端忽略该接口
|
||||
/// </summary>
|
||||
/// <param name="trialId"></param>
|
||||
/// <param name="subjectVisitId"></param>
|
||||
/// <param name="isAnonymize"></param>
|
||||
/// <returns></returns>
|
||||
public async Task PackageAndAnonymizImage(Guid trialId, Guid subjectVisitId, bool isAnonymize = true)
|
||||
{
|
||||
|
||||
var subjectVisit = await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId);
|
||||
|
||||
try
|
||||
{
|
||||
var addOrUpdateFixedFieldList = new List<SystemAnonymization>();
|
||||
|
||||
var ircFieldList = new List<SystemAnonymization>();
|
||||
|
||||
if (isAnonymize)
|
||||
{
|
||||
var systemAnonymizationList = _systemAnonymizationRepository.Where(t => t.IsEnable).ToList();
|
||||
|
||||
addOrUpdateFixedFieldList = systemAnonymizationList.Where(t => t.IsFixed).ToList();
|
||||
|
||||
ircFieldList = systemAnonymizationList.Where(t => t.IsFixed == false).ToList();
|
||||
}
|
||||
|
||||
var subjectAndVisitInfo = _subjectVisitRepository.Where(t => t.Id == subjectVisitId).Select(t => new { SubjectCode = t.Subject.Code, t.Trial.TrialCode, t.VisitNum }).FirstOrDefault();
|
||||
|
||||
var query = from sv in _subjectVisitRepository.Where(t => t.Id == subjectVisitId)
|
||||
|
||||
select new
|
||||
{
|
||||
SubjectCode = sv.Subject.Code,
|
||||
VisitName = sv.VisitName,
|
||||
StudyList = sv.StudyList.Select(u => new
|
||||
{
|
||||
u.PatientId,
|
||||
u.StudyTime,
|
||||
u.StudyCode,
|
||||
|
||||
SeriesList = u.SeriesList.Select(z => new
|
||||
{
|
||||
z.Modality,
|
||||
|
||||
InstancePathList = z.DicomInstanceList.Select(k => new
|
||||
{
|
||||
k.Path
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
};
|
||||
|
||||
var info = query.FirstOrDefault();
|
||||
|
||||
if (info != null)
|
||||
{
|
||||
// 创建一个临时文件夹来存放文件
|
||||
string tempFolderPath = Path.Combine(Directory.GetCurrentDirectory(), $"DownloadTemp_{NewId.NextGuid()}");
|
||||
Directory.CreateDirectory(tempFolderPath);
|
||||
|
||||
// 遍历查询结果
|
||||
foreach (var studyInfo in info.StudyList)
|
||||
{
|
||||
// 遍历 Series
|
||||
foreach (var seriesInfo in studyInfo.SeriesList)
|
||||
{
|
||||
string studyFolderPath = Path.Combine(tempFolderPath, $"{info.SubjectCode}_{info.VisitName}", $"{studyInfo.StudyCode}_{studyInfo.StudyTime?.ToString("yyyy-MM-dd")}_{seriesInfo.Modality}");
|
||||
|
||||
// 创建 影像 文件夹
|
||||
Directory.CreateDirectory(studyFolderPath);
|
||||
|
||||
// 遍历 InstancePathList
|
||||
foreach (var instanceInfo in seriesInfo.InstancePathList)
|
||||
{
|
||||
// 复制文件到相应的文件夹
|
||||
string destinationPath = Path.Combine(studyFolderPath, Path.GetFileName(instanceInfo.Path));
|
||||
|
||||
//下载到当前目录
|
||||
await _oSSService.DownLoadFromOSSAsync(instanceInfo.Path, destinationPath);
|
||||
|
||||
#region 匿名化逻辑
|
||||
|
||||
|
||||
if (isAnonymize)
|
||||
{
|
||||
DicomFile dicomFile = await DicomFile.OpenAsync(destinationPath, Encoding.Default);
|
||||
|
||||
DicomDataset dataset = dicomFile.Dataset;
|
||||
|
||||
foreach (var item in addOrUpdateFixedFieldList)
|
||||
{
|
||||
|
||||
var dicomTag = new DicomTag(Convert.ToUInt16(item.Group, 16), Convert.ToUInt16(item.Element, 16));
|
||||
|
||||
dataset.AddOrUpdate(dicomTag, item.ReplaceValue);
|
||||
}
|
||||
|
||||
foreach (var item in ircFieldList)
|
||||
{
|
||||
|
||||
var dicomTag = new DicomTag(Convert.ToUInt16(item.Group, 16), Convert.ToUInt16(item.Element, 16));
|
||||
|
||||
if (dicomTag == DicomTag.ClinicalTrialProtocolID)
|
||||
{
|
||||
dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.TrialCode);
|
||||
|
||||
}
|
||||
if (dicomTag == DicomTag.ClinicalTrialSiteID)
|
||||
{
|
||||
//dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.TrialSiteCode);
|
||||
|
||||
}
|
||||
if (dicomTag == DicomTag.ClinicalTrialSubjectID)
|
||||
{
|
||||
dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.SubjectCode);
|
||||
|
||||
}
|
||||
if (dicomTag == DicomTag.ClinicalTrialTimePointID)
|
||||
{
|
||||
dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.VisitNum.ToString());
|
||||
|
||||
}
|
||||
if (dicomTag == DicomTag.PatientID)
|
||||
{
|
||||
dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.TrialCode + "_" + subjectAndVisitInfo.SubjectCode);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var zipPath = Path.Combine(Directory.GetCurrentDirectory(), $"{info.SubjectCode}_{info.VisitName}_ImageStudy.zip");
|
||||
|
||||
ZipFile.CreateFromDirectory(tempFolderPath, zipPath);
|
||||
|
||||
//上传到Oss
|
||||
var relativePath = await _oSSService.UploadToOSSAsync(zipPath, $"download_zip", false);
|
||||
|
||||
|
||||
//subjectVisit.PackState = PackState.Packed;
|
||||
//subjectVisit.VisitImageZipPath = relativePath;
|
||||
//await _subjectVisitRepository.SaveChangesAsync();
|
||||
await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.Id == subjectVisitId, u => new SubjectVisit() { PackState = PackState.Packed, VisitImageZipPath = relativePath });
|
||||
|
||||
|
||||
//清理文件夹
|
||||
Directory.Delete(tempFolderPath, true);
|
||||
File.Delete(zipPath);
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.Id == subjectVisitId, u => new SubjectVisit() { PackState = PackState.WaitPack });
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1470,6 +1470,10 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
|
||||
public bool IsLostVisit { get; set; }
|
||||
|
||||
public string VisitImageZipPath { get; set; }
|
||||
|
||||
public PackState PackState { get; set; }
|
||||
|
||||
//public Guid? ClinicalDataSignUserId { get; set; }
|
||||
}
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ namespace IRaCIS.Core.Application.Image.QA
|
|||
/// <param name="visitSearchDTO"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<(PageOutput<QCCRCVisitViewModel>, TrialSubjectAndSVConfig)> GetCRCVisitList(CRCVisitSearchDTO visitSearchDTO)
|
||||
public async Task<IResponseOutput< PageOutput<QCCRCVisitViewModel>>> GetCRCVisitList(CRCVisitSearchDTO visitSearchDTO)
|
||||
{
|
||||
var svExpression = QCCommon.GetSubjectVisitFilter(visitSearchDTO.VisitPlanArray);
|
||||
|
||||
|
@ -83,7 +83,7 @@ namespace IRaCIS.Core.Application.Image.QA
|
|||
var config = await _repository.Where<Trial>(t => t.Id == visitSearchDTO.TrialId).ProjectTo<TrialSubjectAndSVConfig>(_mapper.ConfigurationProvider).FirstOrDefaultAsync().IfNullThrowException();
|
||||
config.IsHaveSubjectClinicalData = await _clinicalDataTrialSet.AnyAsync(x => x.TrialId == visitSearchDTO.TrialId && x.IsConfirm && (x.ClinicalDataLevel == ClinicalLevel.Subject ) && x.UploadRole == UploadRole.CRC);
|
||||
config.IsHaveVisitClinicalData = await _clinicalDataTrialSet.AnyAsync(x => x.TrialId == visitSearchDTO.TrialId && x.IsConfirm && (x.ClinicalDataLevel == ClinicalLevel.SubjectVisit) && x.UploadRole == UploadRole.CRC);
|
||||
return (pageList, config);
|
||||
return ResponseOutput.Ok (pageList, config);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -344,6 +344,7 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
{
|
||||
public string TrialModalitys { get; set;}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 项目ID
|
||||
/// </summary>
|
||||
|
@ -501,6 +502,11 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
|
||||
public string CriterionModalitys { get; set; }
|
||||
|
||||
public ReadingImageDownload? ImageDownloadEnum { get; set; }
|
||||
|
||||
public ReadingImageUpload? ImageUploadEnum { get; set; }
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class ReadingCriterionPageDto
|
||||
|
|
|
@ -240,6 +240,29 @@ namespace IRaCIS.Core.Domain.Models
|
|||
public List<SubjectCriteriaEvaluationVisitFilter> SubjectCriteriaEvaluationVisitFilterList { get; set; }
|
||||
public ReadingStatusEnum ReadingStatus { get; set; }
|
||||
|
||||
public string VisitImageZipPath { get; set; } = string.Empty;
|
||||
|
||||
public PackState PackState { get; set; }
|
||||
}
|
||||
/// <summary>
|
||||
/// 影像下载打包状态
|
||||
/// </summary>
|
||||
public enum PackState
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 待打包
|
||||
/// </summary>
|
||||
WaitPack = 0,
|
||||
|
||||
/// <summary>
|
||||
/// 打包中
|
||||
/// </summary>
|
||||
Packing = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 打包完成
|
||||
/// </summary>
|
||||
Packed = 2
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue