1813 lines
83 KiB
C#
1813 lines
83 KiB
C#
using DocumentFormat.OpenXml.EMMA;
|
||
using FellowOakDicom;
|
||
using IRaCIS.Core.Application.Contracts;
|
||
using IRaCIS.Core.Application.Contracts.Dicom.DTO;
|
||
using IRaCIS.Core.Application.Filter;
|
||
using IRaCIS.Core.Application.Helper;
|
||
using IRaCIS.Core.Application.Service.ImageAndDoc.DTO;
|
||
using IRaCIS.Core.Domain.Models;
|
||
using IRaCIS.Core.Domain.Share;
|
||
using IRaCIS.Core.Infrastructure;
|
||
using MassTransit;
|
||
using MassTransit.Initializers;
|
||
using Medallion.Threading;
|
||
using Microsoft.AspNetCore.Mvc;
|
||
using Newtonsoft.Json;
|
||
using NPOI.SS.Formula.Functions;
|
||
using System.Data;
|
||
using System.IO.Compression;
|
||
using System.Text;
|
||
using System.Web;
|
||
using ZiggyCreatures.Caching.Fusion;
|
||
|
||
namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
||
{
|
||
public interface IDownloadAndUploadService
|
||
{
|
||
Task PackageAndAnonymizImage(Guid trialId, Guid subjectVisitId, bool isDicom, bool isAnonymize = true);
|
||
|
||
Task<IResponseOutput> SubejctRandomReadingTaskNameDeal(Guid subjectId, Guid trialReadingCriterionId);
|
||
}
|
||
|
||
[ApiExplorerSettings(GroupName = "Trial")]
|
||
public class DownloadAndUploadService(IRepository<SystemAnonymization> _systemAnonymizationRepository,
|
||
IRepository<VisitTask> _visitTaskRepository,
|
||
IRepository<SubjectVisit> _subjectVisitRepository,
|
||
IOSSService _oSSService,
|
||
IRepository<Dictionary> _dictionaryRepository,
|
||
IRepository<Trial> _trialRepository,
|
||
IRepository<StudyMonitor> _studyMonitorRepository,
|
||
IRepository<TaskStudy> _taskStudyRepository,
|
||
IRepository<TaskSeries> _taskSeriesRepository,
|
||
IRepository<TaskInstance> _taskInstanceRepository,
|
||
IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository,
|
||
IRepository<NoneDicomStudy> _noneDicomStudyReposiotry,
|
||
IRepository<NoneDicomStudyFile> _noneDicomStudyFileReposiotry,
|
||
IDistributedLockProvider _distributedLockProvider,
|
||
IRepository<TrialImageDownload> _trialImageDownloadRepository,
|
||
IRepository<Subject> _subjectRepository,
|
||
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IFusionCache _fusionCache) : BaseService, IDownloadAndUploadService
|
||
{
|
||
|
||
|
||
/// <summary>
|
||
/// 受试者随机阅片,任务进行随机编号
|
||
/// 进入阅片任务前,随机挑选出该受试者的一个任务,然后给该任务一个编号,编号给的逻辑是:TimePoint Ran+ 已阅任务数量+1
|
||
/// 根据当前受试者该标准已阅任务数量(生效失效的任务都算,考虑重阅,最后编号不重复) 第一个就是TimePoint Ran1,后面依次随机挑选出来的阅片序号依次递增
|
||
/// </summary>
|
||
/// <param name="subjectId"></param>
|
||
/// <param name="trialReadingCriterionId"></param>
|
||
/// <returns></returns>
|
||
public async Task<IResponseOutput> SubejctRandomReadingTaskNameDeal(Guid subjectId, Guid trialReadingCriterionId)
|
||
{
|
||
//subject 随机阅片 或者无序 有上传 才处理任务编号
|
||
if (_visitTaskRepository.Any(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId &&
|
||
(t.TrialReadingCriterion.IsReadingTaskViewInOrder == ReadingOrder.SubjectRandom ||
|
||
(t.TrialReadingCriterion.IsReadingTaskViewInOrder == ReadingOrder.Random && t.TrialReadingCriterion.ImageUploadEnum != ReadingImageUpload.None))))
|
||
{
|
||
//找到 非一致性分析,未签名,状态正常的 并且任务名称是TimePoint的 任务
|
||
var needDealTaskList = await _visitTaskRepository.Where(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.IsAnalysisCreate == false && t.DoctorUserId == _userInfo.UserRoleId
|
||
&& t.ReadingTaskState != ReadingTaskState.HaveSigned && t.TaskBlindName == "Timepoint" && t.ReadingCategory == ReadingCategory.Visit
|
||
&& (t.TaskState == TaskState.Effect || t.TaskState == TaskState.Freeze), true).ToListAsync();
|
||
|
||
if (needDealTaskList.Count > 0)
|
||
{
|
||
//已完成的访视任务数量(包含重阅的)
|
||
var haveFinishedTaskCount = await _visitTaskRepository.CountAsync(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.IsAnalysisCreate == false && t.DoctorUserId == _userInfo.UserRoleId
|
||
&& t.ReadingTaskState == ReadingTaskState.HaveSigned && t.ReadingCategory == ReadingCategory.Visit);
|
||
|
||
//已经处理过的任务名称的数量
|
||
|
||
var haveDealedTaskList = await _visitTaskRepository.Where(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.IsAnalysisCreate == false && t.DoctorUserId == _userInfo.UserRoleId
|
||
&& t.ReadingTaskState != ReadingTaskState.HaveSigned && t.ReadingCategory == ReadingCategory.Visit && t.TaskBlindName != "Timepoint").Select(t => new { t.TaskBlindName, t.SourceSubjectVisitId, t.SouceReadModuleId }).ToListAsync();
|
||
|
||
|
||
//随机赋值编号 比如要处理5个任务,实例化一个包含1-5的数组,每次随机取出一个
|
||
List<int> availableNumbers = Enumerable.Range(haveDealedTaskList.Count + haveFinishedTaskCount + 1, needDealTaskList.Count).ToList();
|
||
Random rng = new Random();
|
||
foreach (var visitTask in needDealTaskList)
|
||
{
|
||
int randomIndex = rng.Next(availableNumbers.Count);
|
||
|
||
var findOldTask = haveDealedTaskList.Where(t => t.SourceSubjectVisitId == visitTask.SourceSubjectVisitId && t.SouceReadModuleId == visitTask.SouceReadModuleId).FirstOrDefault();
|
||
|
||
if (findOldTask != null)
|
||
{
|
||
visitTask.TaskBlindName = findOldTask.TaskBlindName;
|
||
}
|
||
else
|
||
{
|
||
visitTask.TaskBlindName = $"Timepoint Ran {availableNumbers[randomIndex]}";
|
||
}
|
||
|
||
availableNumbers.RemoveAt(randomIndex);
|
||
}
|
||
await _visitTaskRepository.SaveChangesAsync();
|
||
}
|
||
}
|
||
return ResponseOutput.Ok();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取该受试者任务上传列表(展示已上传情况)
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput<List<SubjectImageUploadDTO>>> GetSubjectImageUploadList(IRUploadStudyQuery inQuery)
|
||
{
|
||
|
||
//要根据标准阅片顺序,确定是否查询单个任务的,还是查询所有的
|
||
var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(t => t.Id == inQuery.TrialReadingCriterionId)
|
||
.Select(t => new { t.IsReadingTaskViewInOrder, t.Trial.Modalitys }).FirstNotNullAsync();
|
||
|
||
var subjectCode = string.Empty;
|
||
var subjectId = inQuery.SubjectId;
|
||
|
||
if (criterionInfo.IsReadingTaskViewInOrder == ReadingOrder.Random)
|
||
{
|
||
if (inQuery.VisitTaskId == null)
|
||
{
|
||
throw new Exception("无序阅片,前端参数传递错误");
|
||
}
|
||
//考虑到一致性分析,必须要这个编号进行过滤
|
||
var taskInfo = _visitTaskRepository.Where(t => t.Id == inQuery.VisitTaskId).Select(t => new
|
||
{
|
||
SubjectCode = t.IsAnalysisCreate ? t.BlindSubjectCode : t.Subject.Code,
|
||
SubjectId = t.SubjectId,
|
||
}).FirstOrDefault();
|
||
subjectId = taskInfo.SubjectId;
|
||
subjectCode = taskInfo.SubjectCode;
|
||
}
|
||
else
|
||
{
|
||
if (inQuery.SubjectId == null || inQuery.SubjectCode == null)
|
||
{
|
||
throw new Exception("有序阅片,前端参数传递错误");
|
||
}
|
||
|
||
//考虑到一致性分析,必须要这个编号进行过滤
|
||
subjectCode = inQuery.SubjectCode;
|
||
}
|
||
|
||
await SubejctRandomReadingTaskNameDeal((Guid)subjectId, inQuery.TrialReadingCriterionId);
|
||
|
||
|
||
|
||
var query = _visitTaskRepository.Where(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId && t.SourceSubjectVisitId != null
|
||
&& t.DoctorUserId == _userInfo.UserRoleId && t.TaskState == TaskState.Effect)
|
||
//满足 有序,或者随机只看到当前任务的dicom 非dicom检查
|
||
.WhereIf(criterionInfo.IsReadingTaskViewInOrder != ReadingOrder.SubjectRandom && inQuery.VisitTaskId != null, t => t.Id == inQuery.VisitTaskId)
|
||
.Select(u => new SubjectImageUploadDTO()
|
||
{
|
||
VisitTaskId = u.Id,
|
||
|
||
SubejctId = u.SubjectId,
|
||
|
||
TrialSiteId = u.Subject.TrialSiteId,
|
||
|
||
IsImageFilter = u.TrialReadingCriterion.IsImageFilter,
|
||
|
||
CriterionModalitys = u.TrialReadingCriterion.CriterionModalitys,
|
||
|
||
SubjectCode = u.IsAnalysisCreate == true ? u.BlindSubjectCode : u.Subject.Code,
|
||
TaskBlindName = u.TaskBlindName,
|
||
TaskName = u.TaskName,
|
||
ReadingTaskState = u.ReadingTaskState,
|
||
|
||
SourceSubjectVisitId = u.SourceSubjectVisitId,
|
||
|
||
OrginalStudyList = u.SourceSubjectVisit.StudyList
|
||
.Where(t => u.TrialReadingCriterion.IsImageFilter ? ("|" + u.TrialReadingCriterion.CriterionModalitys + "|").Contains("|" + t.ModalityForEdit + "|") : true)
|
||
.Select(t => new StudyBasicInfo()
|
||
{
|
||
Id = t.Id,
|
||
StudyInstanceUid = t.StudyInstanceUid,
|
||
ModalityForEdit = t.ModalityForEdit,
|
||
BodyPartExamined = t.BodyPartExamined,
|
||
BodyPartForEdit = t.BodyPartForEdit,
|
||
|
||
StudyCode = t.StudyCode,
|
||
StudyTime = t.StudyTime,
|
||
Description = t.Description,
|
||
InstanceCount = t.InstanceCount,
|
||
Modalities = t.Modalities,
|
||
SeriesCount = t.SeriesCount,
|
||
}).ToList(),
|
||
|
||
UploadStudyList = u.TaskStudyList.Select(t => new StudyBasicInfo()
|
||
{
|
||
Id = t.Id,
|
||
StudyInstanceUid = t.StudyInstanceUid,
|
||
ModalityForEdit = t.ModalityForEdit,
|
||
BodyPartExamined = t.BodyPartExamined,
|
||
BodyPartForEdit = t.BodyPartForEdit,
|
||
|
||
StudyCode = t.StudyCode,
|
||
StudyTime = t.StudyTime,
|
||
Description = t.Description,
|
||
InstanceCount = t.InstanceCount,
|
||
Modalities = t.Modalities,
|
||
SeriesCount = t.SeriesCount,
|
||
|
||
SopInstanceUidList = t.InstanceList.Select(t => t.SopInstanceUid).ToList(),
|
||
|
||
}).ToList()
|
||
})
|
||
;
|
||
//var test = await query.ToListAsync();
|
||
|
||
var list = await query.Where(t => t.SubjectCode == subjectCode).ToListAsync();
|
||
|
||
|
||
return ResponseOutput.Ok(list, new { TrialModality = criterionInfo.Modalitys });
|
||
}
|
||
|
||
private void SpecialArchiveStudyDeal(TaskStudy 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
|
||
}
|
||
|
||
|
||
[TrialGlobalLimit("AfterStopCannNotOpt")]
|
||
|
||
public async Task<IResponseOutput> PreArchiveDicomStudy(PriArchiveTaskStudyCommand preArchiveStudyCommand)
|
||
{
|
||
|
||
var studyMonitor = new StudyMonitor()
|
||
{
|
||
TrialId = preArchiveStudyCommand.TrialId,
|
||
SubjectId = preArchiveStudyCommand.SubjectId,
|
||
SubjectVisitId = preArchiveStudyCommand.SubjectVisitId,
|
||
IsSuccess = false,
|
||
UploadStartTime = DateTime.Now,
|
||
IsDicom = true,
|
||
IP = _userInfo.IP,
|
||
FileCount = preArchiveStudyCommand.FileCount,
|
||
};
|
||
|
||
|
||
var addEntity = await _studyMonitorRepository.AddAsync(studyMonitor, true);
|
||
|
||
return ResponseOutput.Ok(addEntity.Id);
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 在调用预归档前验证 这些检查是否可以全新上传还是已存在补充 目前前端允许 IsAllowUpload==true 全新、IsAllowReUpload==true 补充的study ,全部丢到后端,后端判断存在,就删除之前的检查,全新插入
|
||
/// </summary>
|
||
/// <param name="inCommand"></param>
|
||
/// <param name="_dicomStudyRepository"></param>
|
||
/// <returns></returns>
|
||
public async Task<List<TaskStudyArchiveConfirmResult>> VerifyIRStudyAllowUpload(TaskStudyAchivePreConfirmCommand inCommand, [FromServices] IRepository<DicomStudy> _dicomStudyRepository)
|
||
{
|
||
|
||
var currentUploadSubjectVisitId = inCommand.VisitTaskId == null ? null : _visitTaskRepository.Where(t => t.Id == inCommand.VisitTaskId).Select(t => t.SourceSubjectVisitId).FirstOrDefault();
|
||
|
||
//重阅任务排除
|
||
var notAllowedUidList1 = _taskStudyRepository.Where(t => t.TrialId == inCommand.TrialId && t.VisitTask.TaskState == TaskState.Effect && inCommand.StudyInstanceUidList.Contains(t.StudyInstanceUid)).Select(t => new
|
||
{
|
||
t.StudyInstanceUid,
|
||
t.SubjectId,
|
||
SubjectVisitId = t.VisitTask.SourceSubjectVisitId,
|
||
SubejectCode = t.VisitTask.IsAnalysisCreate ? t.VisitTask.BlindSubjectCode : t.Subject.Code,
|
||
VisitTaskId = (Guid?)t.VisitTaskId
|
||
}).ToList();
|
||
|
||
var notAllowedUidList2 = _dicomStudyRepository.Where(t => t.TrialId == inCommand.TrialId && inCommand.StudyInstanceUidList.Contains(t.StudyInstanceUid)).Select(t => new
|
||
{
|
||
t.StudyInstanceUid,
|
||
t.SubjectId,
|
||
SubjectVisitId = (Guid?)t.SubjectVisitId,
|
||
SubejectCode = t.Subject.Code,
|
||
VisitTaskId = (Guid?)null
|
||
}).ToList();
|
||
|
||
var notAllowedUidList = notAllowedUidList1.Union(notAllowedUidList2);
|
||
|
||
var result = new List<TaskStudyArchiveConfirmResult>();
|
||
|
||
foreach (var studyUid in inCommand.StudyInstanceUidList)
|
||
{
|
||
var findStudy = notAllowedUidList.Where(t => t.StudyInstanceUid == studyUid).FirstOrDefault();
|
||
if (findStudy != null)
|
||
{
|
||
|
||
//同一个subject 同一份影响
|
||
if (findStudy.SubejectCode == inCommand.SubjectCode && findStudy.SubjectId == inCommand.SubjectId)
|
||
{
|
||
//上传给后处理其他访视了
|
||
if (inCommand.VisitTaskId != null && findStudy.VisitTaskId != null && findStudy.VisitTaskId != inCommand.VisitTaskId && findStudy.SubjectVisitId != currentUploadSubjectVisitId)
|
||
{
|
||
result.Add(new TaskStudyArchiveConfirmResult() { StudyInstanceUid = studyUid, IsAllowReUpload = false, IsAllowUpload = false });
|
||
}
|
||
//在原始crc 里面上传了,并且不是当前访视
|
||
else if (inCommand.VisitTaskId != null && findStudy.VisitTaskId == null && findStudy.SubjectVisitId != currentUploadSubjectVisitId)
|
||
{
|
||
result.Add(new TaskStudyArchiveConfirmResult() { StudyInstanceUid = studyUid, IsAllowReUpload = false, IsAllowUpload = false });
|
||
}
|
||
else
|
||
{
|
||
result.Add(new TaskStudyArchiveConfirmResult() { StudyInstanceUid = studyUid, IsAllowReUpload = true });
|
||
}
|
||
}
|
||
else
|
||
{
|
||
result.Add(new TaskStudyArchiveConfirmResult() { StudyInstanceUid = studyUid, IsAllowReUpload = false, IsAllowUpload = false });
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//说明没上传 不用管
|
||
result.Add(new TaskStudyArchiveConfirmResult() { StudyInstanceUid = studyUid, IsAllowUpload = true });
|
||
}
|
||
}
|
||
|
||
return result;
|
||
|
||
}
|
||
|
||
|
||
[TrialGlobalLimit("AfterStopCannNotOpt")]
|
||
public async Task<IResponseOutput> AddOrUpdateArchiveTaskStudy(TaskArchiveStudyCommand incommand)
|
||
{
|
||
#region 获取该subject 已生成任务的访视的检查
|
||
|
||
//var queryStudy = _visitTaskRepository.Where(t => t.SubjectId == incommand.SubjectId && t.SourceSubjectVisitId != null && t.DoctorUserId == _userInfo.Id).Select(u => new
|
||
//{
|
||
// VisitTaskId = u.Id,
|
||
// SourceSubjectVisitId = u.SourceSubjectVisitId,
|
||
// OrginalStudyList = u.SourceSubjectVisit.StudyList.Select(t => new StudyBasicInfo()
|
||
// {
|
||
// Id = t.Id,
|
||
// StudyInstanceUid = t.StudyInstanceUid
|
||
// }).ToList(),
|
||
//});
|
||
|
||
//var studyList = await queryStudy.ToListAsync();
|
||
|
||
|
||
//var findOriginStudy = studyList.FirstOrDefault(c => c.OrginalStudyList.Any(t => t.StudyInstanceUid == incommand.Study.StudyInstanceUid));
|
||
|
||
//if (findOriginStudy == null)
|
||
//{
|
||
// return ResponseOutput.NotOk("该检查不属于该受试者,请核查");
|
||
//}
|
||
|
||
#endregion
|
||
|
||
//总数为0的检查不允许提交
|
||
if (incommand.Study.SeriesList.SelectMany(t => t.InstanceList).Count() == 0)
|
||
{
|
||
return ResponseOutput.NotOk("Study_InstanceCountZero");
|
||
}
|
||
|
||
var @uploadLock = _distributedLockProvider.CreateLock($"UploadTaskDicom");
|
||
|
||
using (await @uploadLock.AcquireAsync())
|
||
{
|
||
if (_fusionCache.GetOrDefault<Guid>(CacheKeys.TrialTaskStudyUidDBLock(incommand.TrialId, incommand.VisitTaskId, incommand.Study.StudyInstanceUid)) != Guid.Empty)
|
||
{
|
||
//---当前已有人正在上传和归档该检查!
|
||
return ResponseOutput.NotOk(I18n.T("UploadDownLoad_ArchiveInProgress"));
|
||
}
|
||
else
|
||
{
|
||
//在事务未完成前 防止前端重复提交
|
||
await _fusionCache.SetAsync(CacheKeys.TrialTaskStudyUidDBLock(incommand.TrialId, incommand.VisitTaskId, incommand.Study.StudyInstanceUid), _userInfo.UserRoleId, TimeSpan.FromMinutes(1));
|
||
}
|
||
}
|
||
|
||
var visiTaskId = incommand.VisitTaskId;
|
||
|
||
var modalitys = string.Empty;
|
||
|
||
try
|
||
{
|
||
var trialId = incommand.TrialId;
|
||
|
||
|
||
var studyMonitor = await _studyMonitorRepository.FirstOrDefaultAsync(t => t.Id == incommand.StudyMonitorId);
|
||
studyMonitor.UploadFinishedTime = DateTime.Now;
|
||
studyMonitor.ArchiveFinishedTime = DateTime.Now;
|
||
studyMonitor.FailedFileCount = incommand.FailedFileCount;
|
||
studyMonitor.IsSuccess = incommand.FailedFileCount == 0;
|
||
studyMonitor.RecordPath = incommand.RecordPath;
|
||
studyMonitor.FileSize = incommand.Study.SeriesList.SelectMany(t => t.InstanceList).Sum(t => t.FileSize);
|
||
|
||
var studyId = IdentifierHelper.CreateGuid(incommand.Study.StudyInstanceUid, incommand.TrialId.ToString());
|
||
var findStudy = await _taskStudyRepository.FirstOrDefaultAsync(t => t.Id == studyId);
|
||
|
||
|
||
studyMonitor.StudyId = studyId;
|
||
studyMonitor.StudyCode = findStudy?.StudyCode ?? "";
|
||
|
||
studyMonitor.IsDicomReUpload = findStudy != null;
|
||
|
||
//上传
|
||
if (studyMonitor.IsDicomReUpload == false)
|
||
{
|
||
|
||
|
||
var study = _mapper.Map<TaskStudy>(incommand.Study);
|
||
|
||
var @lock = _distributedLockProvider.CreateLock($"StudyCode");
|
||
|
||
using (await @lock.AcquireAsync())
|
||
{
|
||
//查询数据库获取最大的Code 没有记录则为0
|
||
var dbStudyCodeIntMax = _taskStudyRepository.Where(s => s.TrialId == trialId).Select(t => t.Code).DefaultIfEmpty().Max();
|
||
|
||
//获取缓存中的值 并发的时候,需要记录,已被占用的值 这样其他线程在此占用的最大的值上递增
|
||
var cacheMaxCodeInt = await _fusionCache.GetOrDefaultAsync<int>(CacheKeys.TrialStudyMaxCode(trialId));
|
||
|
||
int currentNextCodeInt = cacheMaxCodeInt > dbStudyCodeIntMax ? cacheMaxCodeInt + 1 : dbStudyCodeIntMax + 1;
|
||
study.Code = currentNextCodeInt;
|
||
|
||
study.StudyCode = AppSettings.GetCodeStr(currentNextCodeInt, nameof(TaskStudy));
|
||
|
||
await _fusionCache.SetAsync<int>(CacheKeys.TrialStudyMaxCode(trialId), study.Code, TimeSpan.FromMinutes(30));
|
||
|
||
}
|
||
|
||
|
||
study.Id = IdentifierHelper.CreateGuid(incommand.Study.StudyInstanceUid, incommand.TrialId.ToString(), visiTaskId.ToString());
|
||
study.TrialId = incommand.TrialId;
|
||
study.SubjectId = incommand.SubjectId;
|
||
study.VisitTaskId = visiTaskId;
|
||
//study.SubjectVisitId = incommand.SubjectVisitId;
|
||
|
||
|
||
//特殊处理逻辑
|
||
study.Modalities = string.Join("、", incommand.Study.SeriesList.Select(t => t.Modality).Distinct());
|
||
SpecialArchiveStudyDeal(study);
|
||
modalitys = study.Modalities;
|
||
|
||
await _taskStudyRepository.AddAsync(study);
|
||
|
||
|
||
studyMonitor.StudyCode = study.StudyCode;
|
||
|
||
|
||
foreach (var seriesItem in incommand.Study.SeriesList)
|
||
{
|
||
var series = _mapper.Map<TaskSeries>(seriesItem);
|
||
|
||
series.Id = IdentifierHelper.CreateGuid(seriesItem.StudyInstanceUid, seriesItem.SeriesInstanceUid, incommand.TrialId.ToString(), visiTaskId.ToString());
|
||
series.StudyId = study.Id;
|
||
|
||
series.TrialId = incommand.TrialId;
|
||
series.SubjectId = incommand.SubjectId;
|
||
//series.SubjectVisitId = incommand.SubjectVisitId;
|
||
series.VisitTaskId = visiTaskId;
|
||
|
||
//前端传递的数量不准,上传的时候,把失败的也加进来了,以实际数组的数字为准
|
||
series.InstanceCount = seriesItem.InstanceList.Count;
|
||
|
||
await _taskSeriesRepository.AddAsync(series);
|
||
|
||
foreach (var instanceItem in seriesItem.InstanceList)
|
||
{
|
||
var isntance = _mapper.Map<TaskInstance>(instanceItem);
|
||
|
||
Guid instanceId = IdentifierHelper.CreateGuid(study.StudyInstanceUid, series.SeriesInstanceUid, isntance.SopInstanceUid, study.TrialId.ToString(), visiTaskId.ToString());
|
||
|
||
isntance.Id = instanceId;
|
||
isntance.StudyId = study.Id;
|
||
isntance.SeriesId = series.Id;
|
||
|
||
isntance.TrialId = incommand.TrialId;
|
||
isntance.SubjectId = incommand.SubjectId;
|
||
//isntance.SubjectVisitId = incommand.SubjectVisitId;
|
||
isntance.VisitTaskId = visiTaskId;
|
||
|
||
await _taskInstanceRepository.AddAsync(isntance);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
|
||
|
||
|
||
//重传的时候也要赋值检查Id
|
||
studyMonitor.StudyId = findStudy.Id;
|
||
studyMonitor.StudyCode = findStudy.StudyCode;
|
||
|
||
//特殊处理逻辑
|
||
findStudy.Modalities = string.Join("、", incommand.Study.SeriesList.Select(t => t.Modality).Union(findStudy.Modalities.Split("、", StringSplitOptions.RemoveEmptyEntries)).Distinct());
|
||
SpecialArchiveStudyDeal(findStudy);
|
||
modalitys = findStudy.Modalities;
|
||
|
||
|
||
// 少了整个序列
|
||
|
||
//某个序列下少了instance
|
||
foreach (var seriesItem in incommand.Study.SeriesList)
|
||
{
|
||
var seriesId = IdentifierHelper.CreateGuid(seriesItem.StudyInstanceUid, seriesItem.SeriesInstanceUid, trialId.ToString(), visiTaskId.ToString());
|
||
|
||
TaskSeries dicomSeries = await _taskSeriesRepository.FirstOrDefaultAsync(t => t.Id == seriesId);
|
||
|
||
//判断重复
|
||
if (dicomSeries == null)
|
||
{
|
||
var series = _mapper.Map<TaskSeries>(seriesItem);
|
||
|
||
series.Id = seriesId;
|
||
series.StudyId = findStudy.Id;
|
||
|
||
series.TrialId = incommand.TrialId;
|
||
series.SubjectId = incommand.SubjectId;
|
||
series.VisitTaskId = visiTaskId;
|
||
//series.SubjectVisitId = incommand.SubjectVisitId;
|
||
|
||
|
||
dicomSeries = await _taskSeriesRepository.AddAsync(series);
|
||
|
||
//新的序列 那么 检查的序列数量+1
|
||
findStudy.SeriesCount += 1;
|
||
}
|
||
else
|
||
{
|
||
//该序列掉了instance
|
||
dicomSeries.InstanceCount += seriesItem.InstanceList.Count;
|
||
}
|
||
|
||
foreach (var instanceItem in seriesItem.InstanceList)
|
||
{
|
||
var insntance = _mapper.Map<TaskInstance>(instanceItem);
|
||
insntance.Id = IdentifierHelper.CreateGuid(insntance.StudyInstanceUid, insntance.SeriesInstanceUid, insntance.SopInstanceUid, trialId.ToString(), visiTaskId.ToString());
|
||
insntance.StudyId = findStudy.Id;
|
||
insntance.SeriesId = dicomSeries.Id;
|
||
|
||
insntance.TrialId = incommand.TrialId;
|
||
insntance.SubjectId = incommand.SubjectId;
|
||
insntance.VisitTaskId = visiTaskId;
|
||
|
||
await _taskInstanceRepository.AddAsync(insntance);
|
||
}
|
||
|
||
|
||
// 不管是新的序列 还是 该序列 掉了Instance 重传的时候 检查的instance 数量都会增加
|
||
findStudy.InstanceCount += seriesItem.InstanceList.Count;
|
||
|
||
}
|
||
|
||
|
||
}
|
||
|
||
var @lock2 = _distributedLockProvider.CreateLock($"StudyCommit");
|
||
|
||
using (await @lock2.AcquireAsync())
|
||
{
|
||
await _taskStudyRepository.SaveChangesAsync();
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
|
||
return ResponseOutput.NotOk(ex.Message);
|
||
}
|
||
finally
|
||
{
|
||
await _fusionCache.RemoveAsync(CacheKeys.TrialTaskStudyUidDBLock(incommand.TrialId, incommand.VisitTaskId, incommand.Study.StudyInstanceUid));
|
||
await _fusionCache.RemoveAsync(CacheKeys.TrialTaskStudyUidUploading(incommand.TrialId, incommand.VisitTaskId, incommand.Study.StudyInstanceUid));
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
return ResponseOutput.Ok(modalitys);
|
||
}
|
||
|
||
|
||
[HttpDelete]
|
||
public async Task<IResponseOutput> DeleteTaskStudy(Guid visitTaskId, bool isDicom, Guid? dicomStudyId, Guid? noneDicomStudyId)
|
||
{
|
||
if (isDicom)
|
||
{
|
||
if (dicomStudyId == null)
|
||
{
|
||
var deleteStudyPathList = await _taskInstanceRepository.Where(t => t.VisitTaskId == visitTaskId).GroupBy(t => t.StudyId).Select(g => g.First().Path).ToListAsync();
|
||
|
||
foreach (var fisrtPath in deleteStudyPathList)
|
||
{
|
||
var prefix = fisrtPath.Substring(1, fisrtPath.LastIndexOf('/') - 1);
|
||
await _oSSService.DeleteFromPrefix(prefix, true);
|
||
}
|
||
|
||
|
||
await _taskStudyRepository.DeleteFromQueryAsync(t => t.VisitTaskId == visitTaskId);
|
||
await _taskSeriesRepository.BatchDeleteNoTrackingAsync(t => t.VisitTaskId == visitTaskId);
|
||
await _taskInstanceRepository.BatchDeleteNoTrackingAsync(t => t.VisitTaskId == visitTaskId);
|
||
}
|
||
else
|
||
{
|
||
var fisrtPath = await _taskInstanceRepository.Where(t => t.VisitTaskId == visitTaskId && t.StudyId == dicomStudyId).Select(t => t.Path).FirstOrDefaultAsync();
|
||
var prefix = fisrtPath.Substring(1, fisrtPath.LastIndexOf('/') - 1);
|
||
await _oSSService.DeleteFromPrefix(prefix, true);
|
||
|
||
await _taskStudyRepository.DeleteFromQueryAsync(t => t.VisitTaskId == visitTaskId && t.Id == dicomStudyId);
|
||
await _taskSeriesRepository.BatchDeleteNoTrackingAsync(t => t.VisitTaskId == visitTaskId && t.Id == dicomStudyId);
|
||
await _taskInstanceRepository.BatchDeleteNoTrackingAsync(t => t.VisitTaskId == visitTaskId && t.Id == dicomStudyId);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
await _noneDicomStudyFileReposiotry.DeleteFromQueryAsync(t => t.VisitTaskId == visitTaskId && t.OriginNoneDicomStudyId == noneDicomStudyId);
|
||
}
|
||
|
||
await _noneDicomStudyFileReposiotry.SaveChangesAsync();
|
||
|
||
return ResponseOutput.Ok();
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// IR 上传任务 nonedicom 列表 后处理的数据UploadedFileCount不能排序 --new
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<List<TaskNoneDicomStudyDTO>> GetIRUploadTaskNoneDicomStudyList(IRUploadStudyQuery inQuery)
|
||
{
|
||
var subjectCode = inQuery.SubjectCode;
|
||
var subjectId = inQuery.SubjectId;
|
||
var doctorUserId = _userInfo.UserRoleId;
|
||
|
||
if (inQuery.VisitTaskId != null)
|
||
{
|
||
//考虑到一致性分析,必须要这个编号进行过滤
|
||
//医学审核查看下载按钮,这个时候需要知道医生
|
||
|
||
var taskInfo = await _visitTaskRepository.Where(t => t.Id == inQuery.VisitTaskId).Select(t => new
|
||
{
|
||
SubjectCode = t.IsAnalysisCreate ? t.BlindSubjectCode : t.Subject.Code,
|
||
SubjectId = t.SubjectId,
|
||
t.DoctorUserId,
|
||
t.IsAnalysisCreate
|
||
}).FirstNotNullAsync();
|
||
|
||
subjectId = taskInfo.SubjectId;
|
||
subjectCode = taskInfo.SubjectCode;
|
||
doctorUserId = (Guid)taskInfo.DoctorUserId!;
|
||
}
|
||
|
||
var info = await _readingQuestionCriterionTrialRepository.Where(t => t.Id == inQuery.TrialReadingCriterionId)
|
||
.Select(t => new { t.IsImageFilter, t.CriterionModalitys, t.IsReadingTaskViewInOrder }).FirstNotNullAsync();
|
||
|
||
var query = from u in _visitTaskRepository.Where(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId
|
||
&& t.SourceSubjectVisitId != null && t.DoctorUserId == doctorUserId && t.TaskState == TaskState.Effect)
|
||
//满足 有序,或者随机只看到当前任务的dicom 非dicom检查
|
||
.WhereIf(info.IsReadingTaskViewInOrder != ReadingOrder.SubjectRandom && inQuery.VisitTaskId != null, t => t.Id == inQuery.VisitTaskId)
|
||
join ns in _noneDicomStudyReposiotry.Where(t => t.SubjectId == subjectId).WhereIf(info.IsImageFilter, t => ("|" + info.CriterionModalitys + "|").Contains("|" + t.Modality + "|"))
|
||
on u.SourceSubjectVisitId equals ns.SubjectVisitId
|
||
|
||
select new TaskNoneDicomStudyDTO()
|
||
{
|
||
SubjectId = u.SubjectId,
|
||
SubjectCode = u.IsSelfAnalysis == true ? u.BlindSubjectCode : u.Subject.Code,
|
||
TaskBlindName = u.TaskBlindName,
|
||
TaskName = u.TaskName,
|
||
ReadingTaskState = u.ReadingTaskState,
|
||
SourceSubjectVisitId = u.SourceSubjectVisitId,
|
||
VisitTaskId = u.Id,
|
||
|
||
Id = ns.Id,
|
||
Description = ns.Description,
|
||
ImageDate = ns.ImageDate,
|
||
BodyPart = ns.BodyPart,
|
||
FileCount = ns.FileCount,
|
||
Modality = ns.Modality,
|
||
StudyCode = ns.StudyCode,
|
||
|
||
FileList = ns.NoneDicomFileList.Select(t => new NoneDicomFileInfo()
|
||
{
|
||
FileType = t.FileType,
|
||
FileName = t.FileName,
|
||
FileSize = t.FileSize,
|
||
Path = t.Path
|
||
}).ToList()
|
||
|
||
};
|
||
|
||
var list = await query.Where(t => t.SubjectCode == subjectCode).SortToListAsync(inQuery);
|
||
|
||
var noneDicomStudyTaskIdList = list.Select(t => t.VisitTaskId).ToList();
|
||
|
||
|
||
var taskNoneDicomStudyList = _visitTaskRepository.Where(t => noneDicomStudyTaskIdList.Contains(t.Id))
|
||
.SelectMany(t => t.TaskNoneDicomStudyFileList).Where(t => noneDicomStudyTaskIdList.Contains((Guid)t.VisitTaskId))
|
||
.Select(u => new NoneDicomFileInfo
|
||
{
|
||
OriginNoneDicomStudyId = u.OriginNoneDicomStudyId,
|
||
|
||
FileType = u.FileType,
|
||
FileName = u.FileName,
|
||
FileSize = u.FileSize,
|
||
Path = u.Path
|
||
})
|
||
.ToList();
|
||
|
||
foreach (var item in list)
|
||
{
|
||
item.UploadedFileCount = taskNoneDicomStudyList.Where(t => t.OriginNoneDicomStudyId == item.Id).Count();
|
||
item.UploadedFileList = taskNoneDicomStudyList.Where(t => t.OriginNoneDicomStudyId == item.Id).ToList();
|
||
}
|
||
|
||
return list;
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// IQC 获取CRC 上传到某一个访视的的检查信息 (原始影像信息 包含dicom 非dicom)
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput> GetCRCUploadedStudyInfo(CRCUploadedStudyQuqry inQuery)
|
||
{
|
||
var isQueryDicom = inQuery.DicomStudyIdList.Count > 0;
|
||
var isQueryNoneDicom = inQuery.NoneDicomStudyIdList.Count > 0;
|
||
|
||
var imageType = (isQueryDicom && isQueryNoneDicom) ? ImageType.DicomAndNoneDicom : (isQueryDicom ? ImageType.Dicom : ImageType.NoneDicom);
|
||
|
||
var query = from sv in _subjectVisitRepository.Where(t => t.Id == inQuery.SubjectVisitId)
|
||
|
||
|
||
select new
|
||
{
|
||
TrialId = sv.TrialId,
|
||
SubjectId = sv.SubjectId,
|
||
SubjectCode = sv.Subject.Code,
|
||
TrialSiteCode = sv.TrialSite.TrialSiteCode,
|
||
VisitName = sv.VisitName,
|
||
|
||
StudyList = sv.StudyList.Where(t => isQueryDicom ? inQuery.DicomStudyIdList.Contains(t.Id) : false)
|
||
|
||
.Select(u => new
|
||
{
|
||
u.PatientId,
|
||
u.StudyTime,
|
||
u.StudyCode,
|
||
|
||
SeriesList = u.SeriesList.Select(z => new
|
||
{
|
||
z.Modality,
|
||
|
||
InstanceList = z.DicomInstanceList.Select(k => new
|
||
{
|
||
k.Path,
|
||
k.FileSize
|
||
})
|
||
})
|
||
|
||
}).ToList(),
|
||
|
||
NoneDicomStudyList = sv.NoneDicomStudyList.Where(t => isQueryNoneDicom ? inQuery.NoneDicomStudyIdList.Contains(t.Id) : false)
|
||
|
||
.Select(nd => new
|
||
{
|
||
nd.Modality,
|
||
nd.StudyCode,
|
||
nd.ImageDate,
|
||
|
||
FileList = nd.NoneDicomFileList.Select(file => new
|
||
{
|
||
file.FileName,
|
||
file.Path,
|
||
file.FileType,
|
||
file.FileSize,
|
||
})
|
||
}).ToList()
|
||
};
|
||
|
||
var result = query.FirstOrDefault();
|
||
|
||
var preDownloadInfo = new TrialImageDownload()
|
||
{
|
||
Id = NewId.NextSequentialGuid(),
|
||
TrialId = result.TrialId,
|
||
SubjectId = result.SubjectId,
|
||
SubjectCode = result.SubjectCode,
|
||
TrialSiteCode = result.TrialSiteCode,
|
||
IP = _userInfo.IP,
|
||
DownloadStartTime = DateTime.Now,
|
||
IsSuccess = false,
|
||
ImageType = imageType,
|
||
VisitName = string.Join(" | ", result.VisitName),
|
||
NoneDicomStudyCount = result.NoneDicomStudyList.Count(),
|
||
DicomStudyCount = result.StudyList.Count(),
|
||
ImageCount = result.StudyList.Sum(s => s.SeriesList.Sum(s => s.InstanceList.Count())) + result.NoneDicomStudyList.Sum(s => s.FileList.Count()),
|
||
ImageSize = result.StudyList.Sum(t => t.SeriesList.Sum(s => s.InstanceList.Sum(i => i.FileSize))) + result.NoneDicomStudyList.Sum(t => t.FileList.Sum(s => s.FileSize))
|
||
?? 0
|
||
};
|
||
await _trialImageDownloadRepository.AddAsync(preDownloadInfo, true);
|
||
return ResponseOutput.Ok(result, preDownloadInfo.Id);
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// IR 阅片页面 和IR 任务列表页面下载 勾选下载列表(后端要考虑到一致性分析 subjectCode的问题)
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<List<SubjectCRCImageUploadedStudyDto>> GetSubjectImageDownloadSelectList(IRReadingDownloadQuery inQuery)
|
||
{
|
||
|
||
var doctorUserId = _userInfo.UserRoleId;
|
||
var isAnalysisCreate = false;
|
||
|
||
//要根据标准阅片顺序,确定是否查询单个任务的,还是查询所有的
|
||
var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(t => t.Id == inQuery.TrialReadingCriterionId)
|
||
.Select(t => new { t.IsReadingTaskViewInOrder }).FirstNotNullAsync();
|
||
|
||
var subjectCode = string.Empty;
|
||
var subjectId = inQuery.SubjectId;
|
||
|
||
if (criterionInfo.IsReadingTaskViewInOrder == ReadingOrder.Random)
|
||
{
|
||
if (inQuery.VisitTaskId == null)
|
||
{
|
||
throw new Exception("无序阅片,前端参数传递错误");
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
if (inQuery.SubjectId == null || inQuery.SubjectCode == null)
|
||
{
|
||
throw new Exception("有序阅片,前端参数传递错误");
|
||
}
|
||
|
||
//考虑到一致性分析,必须要这个编号进行过滤
|
||
subjectCode = inQuery.SubjectCode;
|
||
}
|
||
|
||
if (inQuery.VisitTaskId != null)
|
||
{
|
||
//考虑到一致性分析,必须要这个编号进行过滤
|
||
//医学审核查看下载按钮,这个时候需要知道医生
|
||
|
||
var taskInfo = await _visitTaskRepository.Where(t => t.Id == inQuery.VisitTaskId).Select(t => new
|
||
{
|
||
SubjectCode = t.IsAnalysisCreate ? t.BlindSubjectCode : t.Subject.Code,
|
||
SubjectId = t.SubjectId,
|
||
t.DoctorUserId,
|
||
t.IsAnalysisCreate
|
||
}).FirstNotNullAsync();
|
||
|
||
subjectId = taskInfo.SubjectId;
|
||
subjectCode = taskInfo.SubjectCode;
|
||
doctorUserId = (Guid)taskInfo.DoctorUserId!;
|
||
isAnalysisCreate = taskInfo.IsAnalysisCreate;
|
||
}
|
||
|
||
var query = _visitTaskRepository.Where(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId
|
||
&& t.SourceSubjectVisitId != null && t.DoctorUserId == doctorUserId)
|
||
//满足 有序,或者随机只看到当前任务的dicom 非dicom检查
|
||
.WhereIf(inQuery.VisitTaskId == null, t => t.TaskState == TaskState.Effect)//从待阅列表进入,要筛选出有效的,任务可能重阅了,也要看到该任务的的
|
||
.WhereIf(criterionInfo.IsReadingTaskViewInOrder != ReadingOrder.SubjectRandom && inQuery.VisitTaskId != null, t => t.Id == inQuery.VisitTaskId)
|
||
.ProjectTo<SubjectCRCImageUploadedDto>(_mapper.ConfigurationProvider);
|
||
|
||
//这里过滤是否是一致性分析的
|
||
var list = await query.Where(t => t.SubjectCode == subjectCode).ToListAsync();
|
||
|
||
foreach (var item in list)
|
||
{
|
||
if (item.IsImageFilter)
|
||
{
|
||
item.DicomStudyList = item.DicomStudyList.Where(t => ("|" + item.CriterionModalitys + "|").Contains("|" + t.ModalityForEdit + "|")).ToList();
|
||
item.NoneDicomStudyList = item.NoneDicomStudyList.Where(t => ("|" + item.CriterionModalitys + "|").Contains("|" + t.Modality + "|")).ToList();
|
||
}
|
||
}
|
||
|
||
|
||
#region 将任务级别转为检查级别
|
||
|
||
var result = new List<SubjectCRCImageUploadedStudyDto>();
|
||
|
||
var dicomStudyList = list.Where(item => item.DicomStudyList.Count > 0)
|
||
.Select(item => new SubjectCRCImageUploadedStudyDto
|
||
{
|
||
VisitTaskId = item.VisitTaskId,
|
||
SubjectId = item.SubjectId,
|
||
SubjectCode = item.SubjectCode,
|
||
TaskBlindName = item.TaskBlindName,
|
||
TaskName = item.TaskName,
|
||
IsImageFilter = item.IsImageFilter,
|
||
CriterionModalitys = item.CriterionModalitys,
|
||
SourceSubjectVisitId = item.SourceSubjectVisitId,
|
||
//取dicom
|
||
DicomStudyList = item.DicomStudyList,
|
||
}).ToList();
|
||
|
||
var noneStudyList = list.Where(item => item.NoneDicomStudyList.Count > 0)
|
||
.Select(item => new SubjectCRCImageUploadedStudyDto
|
||
{
|
||
VisitTaskId = item.VisitTaskId,
|
||
SubjectId = item.SubjectId,
|
||
SubjectCode = item.SubjectCode,
|
||
TaskBlindName = item.TaskBlindName,
|
||
TaskName = item.TaskName,
|
||
IsImageFilter = item.IsImageFilter,
|
||
CriterionModalitys = item.CriterionModalitys,
|
||
SourceSubjectVisitId = item.SourceSubjectVisitId,
|
||
//非dicom
|
||
NoneDicomStudyList = item.NoneDicomStudyList,
|
||
}).ToList();
|
||
|
||
|
||
result.AddRange(dicomStudyList);
|
||
result.AddRange(noneStudyList);
|
||
#endregion
|
||
|
||
|
||
return result;
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// IR 阅片页面获取下载检查的信息 会根据标准进行过滤检查,(后端要考虑到一致性分析 subjectCode的问题)
|
||
/// 检查在访视下面,所以需要传递下载的访视Id,另外下载访视下面那些检查,就把访视下的对应的检查Id 丢到数组里就好
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput> GetIRReadingDownloadStudyInfo(IRDownloadQuery inQuery)
|
||
{
|
||
var info = await _readingQuestionCriterionTrialRepository.Where(t => t.Id == inQuery.TrialReadingCriterionId)
|
||
.Select(t => new { t.IsImageFilter, t.CriterionModalitys, t.TrialId, t.IsReadingTaskViewInOrder }).FirstNotNullAsync();
|
||
|
||
var isQueryDicom = inQuery.DicomStudyIdList.Count > 0;
|
||
var isQueryNoneDicom = inQuery.NoneDicomStudyIdList.Count > 0;
|
||
|
||
var imageType = (isQueryDicom && isQueryNoneDicom) ? ImageType.DicomAndNoneDicom : (isQueryDicom ? ImageType.Dicom : ImageType.NoneDicom);
|
||
|
||
var taskIdList = inQuery.SubjectVisitTaskList.Select(t => t.TaskId).ToList();
|
||
|
||
var subjectVisitIdList = inQuery.SubjectVisitTaskList.Select(t => t.SubjectVisitId).ToList();
|
||
|
||
var trialSiteCode = _visitTaskRepository.Where(t => t.Id == taskIdList.FirstOrDefault()).Select(t => t.IsAnalysisCreate ? t.BlindTrialSiteCode : t.Subject.TrialSite.TrialSiteCode).FirstOrDefault() ?? string.Empty;
|
||
|
||
var query = from sv in _subjectRepository.Where(t => t.Id == inQuery.SubjectId).SelectMany(t => t.SubjectVisitList.Where(t => subjectVisitIdList.Contains(t.Id)))
|
||
//一致性分析,导致查询出来两条数据
|
||
join visitTask in _visitTaskRepository.Where(t => taskIdList.Contains(t.Id))
|
||
|
||
on sv.Id equals visitTask.SourceSubjectVisitId
|
||
select new
|
||
{
|
||
SubjectCode = inQuery.SubjectCode,
|
||
VisitName = sv.VisitName,
|
||
TaskBlindName = visitTask.TaskBlindName,
|
||
StudyList = sv.StudyList.Where(t => isQueryDicom ? inQuery.DicomStudyIdList.Contains(t.Id) : false)
|
||
.Where(t => info.IsImageFilter ? ("|" + info.CriterionModalitys + "|").Contains("|" + t.ModalityForEdit + "|") : true)
|
||
.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,
|
||
k.FileSize
|
||
})
|
||
})
|
||
|
||
}),
|
||
|
||
NoneDicomStudyList = sv.NoneDicomStudyList.Where(t => isQueryNoneDicom ? inQuery.NoneDicomStudyIdList.Contains(t.Id) : false)
|
||
.Where(t => info.IsImageFilter ? ("|" + info.CriterionModalitys + "|").Contains("|" + t.Modality + "|") : true)
|
||
.Select(nd => new
|
||
{
|
||
nd.Modality,
|
||
nd.StudyCode,
|
||
nd.ImageDate,
|
||
|
||
FileList = nd.NoneDicomFileList.Select(file => new
|
||
{
|
||
file.FileName,
|
||
file.Path,
|
||
file.FileType,
|
||
file.FileSize
|
||
})
|
||
})
|
||
};
|
||
|
||
|
||
|
||
var result = await query.ToListAsync();
|
||
|
||
|
||
|
||
var preDownloadInfo = new TrialImageDownload()
|
||
{
|
||
Id = NewId.NextSequentialGuid(),
|
||
TrialId = info.TrialId,
|
||
SubjectId = inQuery.SubjectId,
|
||
SubjectCode = inQuery.SubjectCode,
|
||
TrialSiteCode = trialSiteCode,
|
||
IP = _userInfo.IP,
|
||
DownloadStartTime = DateTime.Now,
|
||
IsSuccess = false,
|
||
ImageType = imageType,
|
||
VisitName = string.Join(" | ", result.Select(t => t.VisitName).OrderBy(t => t).ToList()),
|
||
NoneDicomStudyCount = result.Sum(t => t.NoneDicomStudyList.Count()),
|
||
DicomStudyCount = result.Sum(t => t.StudyList.Count()),
|
||
ImageCount = result.Sum(t => t.StudyList.Sum(s => s.SeriesList.Sum(s => s.InstancePathList.Count())) + t.NoneDicomStudyList.Sum(s => s.FileList.Count())),
|
||
ImageSize = result.Sum(t => t.StudyList.Sum(t => t.SeriesList.Sum(s => s.InstancePathList.Sum(i => i.FileSize))) + t.NoneDicomStudyList.Sum(t => t.FileList.Sum(s => s.FileSize))
|
||
) ?? 0
|
||
};
|
||
|
||
await _trialImageDownloadRepository.AddAsync(preDownloadInfo, true);
|
||
|
||
return ResponseOutput.Ok(result, new { PreDownloadId = preDownloadInfo.Id, info.IsReadingTaskViewInOrder });
|
||
}
|
||
|
||
/// <summary>
|
||
/// dicom 影像后处理预览接口
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput> GetTaskUploadedDicomStudyList(IRTaskUploadedDicomStudyQuery inQuery)
|
||
{
|
||
var info = await _visitTaskRepository.Where(t => t.Id == inQuery.VisitTaskId)
|
||
.Select(t => new { t.TrialReadingCriterion.IsImageFilter, t.TrialReadingCriterion.CriterionModalitys }).FirstNotNullAsync();
|
||
|
||
var query = _taskStudyRepository.Where(t => t.VisitTaskId == inQuery.VisitTaskId)
|
||
.Where(t => info.IsImageFilter ? ("|" + info.CriterionModalitys + "|").Contains("|" + t.ModalityForEdit + "|") : true)
|
||
.Select(t => new
|
||
{
|
||
StudyId = t.Id,
|
||
t.Modalities,
|
||
t.InstanceCount,
|
||
t.SeriesCount,
|
||
t.StudyCode,
|
||
SeriesList = t.SeriesList.OrderBy(s => s.SeriesNumber).ThenBy(s => s.SeriesTime).Select(u => new
|
||
{
|
||
u.SeriesTime,
|
||
u.InstanceCount,
|
||
u.ImageResizePath,
|
||
u.Modality,
|
||
u.Description,
|
||
u.SeriesInstanceUid,
|
||
u.SeriesNumber,
|
||
u.SliceThickness,
|
||
u.StudyInstanceUid,
|
||
|
||
IsExistMutiFrames = u.InstanceList.Any(t => t.NumberOfFrames > 1),
|
||
|
||
InstanceInfoList = u.InstanceList.OrderBy(t => t.InstanceNumber).Select(k =>
|
||
new InstanceBasicInfo()
|
||
{
|
||
Id = k.Id,
|
||
NumberOfFrames = k.NumberOfFrames,
|
||
HtmlPath = k.HtmlPath,
|
||
Path = k.Path,
|
||
InstanceNumber = k.InstanceNumber,
|
||
|
||
}).ToList()
|
||
})
|
||
});
|
||
var list = await query.ToListAsync();
|
||
|
||
return ResponseOutput.Ok(list);
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新后处理上传的检查modality
|
||
/// </summary>
|
||
/// <param name="taskStudyId"></param>
|
||
/// <param name="modality"></param>
|
||
/// <returns></returns>
|
||
[HttpPut]
|
||
public async Task<IResponseOutput> UpdateTaskStudyModality(Guid taskStudyId, string modality)
|
||
{
|
||
await _taskStudyRepository.UpdatePartialFromQueryAsync(t => t.Id == taskStudyId, u => new TaskStudy() { ModalityForEdit = modality }, true);
|
||
return ResponseOutput.Ok();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 影像下载成功回调
|
||
/// </summary>
|
||
/// <param name="trialImageDownloadId"></param>
|
||
/// <returns></returns>
|
||
public async Task<IResponseOutput> DownloadImageSuccess(Guid trialImageDownloadId)
|
||
{
|
||
await _trialImageDownloadRepository.UpdatePartialFromQueryAsync(t => t.Id == trialImageDownloadId, u => new TrialImageDownload()
|
||
{ DownloadEndTime = DateTime.Now, IsSuccess = true }, true);
|
||
return ResponseOutput.Ok();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 项目影像下载监控列表
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<PageOutput<TrialImageDownloadView>> GetTrialDownloadList(TrialIamgeDownQuery inQuery)
|
||
{
|
||
var query = _trialImageDownloadRepository.Where(t => t.TrialId == inQuery.TrialId)
|
||
.WhereIf(inQuery.SubjectCode.IsNotNullOrEmpty(), t => t.SubjectCode.Contains(inQuery.SubjectCode))
|
||
.WhereIf(inQuery.IP.IsNotNullOrEmpty(), t => t.IP.Contains(inQuery.IP))
|
||
.WhereIf(inQuery.Name.IsNotNullOrEmpty(), t => t.CreateUserRole.IdentityUser.UserName.Contains(inQuery.Name) || t.CreateUserRole.FullName.Contains(inQuery.Name))
|
||
.WhereIf(inQuery.ImageType != null, t => t.ImageType == inQuery.ImageType)
|
||
.WhereIf(inQuery.UserType != null, t => t.CreateUserRole.UserTypeEnum == inQuery.UserType)
|
||
.WhereIf(inQuery.IsSuccess != null, t => t.IsSuccess == inQuery.IsSuccess)
|
||
.WhereIf(inQuery.DownloadStartTime != null, t => t.DownloadStartTime >= inQuery.DownloadStartTime)
|
||
.WhereIf(inQuery.DownloadEndTime != null, t => t.DownloadEndTime <= inQuery.DownloadEndTime)
|
||
|
||
.ProjectTo<TrialImageDownloadView>(_mapper.ConfigurationProvider);
|
||
|
||
return await query.ToPagedListAsync(inQuery);
|
||
}
|
||
|
||
|
||
|
||
#region 影像汇总页面
|
||
[HttpPost]
|
||
public async Task<IResponseOutput<PageOutput<TrialVisitImageStatView>>> GetTrialVisitImageStatList(TrialVisitImageQuery inQuery)
|
||
{
|
||
var query = _subjectVisitRepository.Where(t => t.TrialId == inQuery.TrialId)
|
||
.WhereIf(inQuery.TrialSiteId != null, t => t.TrialSiteId == inQuery.TrialSiteId)
|
||
.WhereIf(inQuery.SubjectCode.IsNotNullOrEmpty(), t => t.Subject.Code.Contains(inQuery.SubjectCode))
|
||
.WhereIf(inQuery.BeginScanDate != null, t => t.LatestScanDate >= inQuery.BeginScanDate)
|
||
.WhereIf(inQuery.EndScanDate != null, t => t.LatestScanDate == inQuery.EndScanDate)
|
||
.Select(t => new TrialVisitImageStatView()
|
||
{
|
||
TrialId = t.TrialId,
|
||
SubjectVisitId = t.Id,
|
||
SubjectCode = t.Subject.Code,
|
||
TrialSiteCode = t.TrialSite.TrialSiteCode,
|
||
TrialSiteId = t.TrialSiteId,
|
||
VisitName = t.VisitName,
|
||
VisitNum = t.VisitNum,
|
||
EarliestScanDate = t.EarliestScanDate,
|
||
LatestScanDate = t.LatestScanDate,
|
||
|
||
IsHaveDicom = t.StudyList.Any(),
|
||
|
||
IsHaveNoneDicom = t.NoneDicomStudyList.Any(),
|
||
|
||
|
||
TotalStudyCount = t.StudyList.Count() + t.NoneDicomStudyList.Count(),
|
||
|
||
TotalImageCount = t.StudyList.Sum(t => t.InstanceCount) + t.NoneDicomStudyList.Sum(t => t.FileCount),
|
||
|
||
TotalImageSize = t.StudyList.SelectMany(t => t.InstanceList).Sum(t => t.FileSize) + t.NoneDicomStudyList.SelectMany(t => t.NoneDicomFileList).Sum(t => t.FileSize),
|
||
|
||
|
||
//DicomStudyCount = t.StudyList.Count(),
|
||
//NoneDicomStudyCount = t.NoneDicomStudyList.Count(),
|
||
|
||
//DicomImageCount = t.StudyList.Sum(t => t.InstanceCount),
|
||
//NoneDicomImageCount = t.NoneDicomStudyList.Sum(t => t.FileCount),
|
||
|
||
//DicomImageSize = t.StudyList.SelectMany(t => t.InstanceList).Sum(t => t.FileSize),
|
||
//NoneDicomImageSize = t.NoneDicomStudyList.SelectMany(t => t.NoneDicomFileList).Sum(t => t.FileSize)
|
||
});
|
||
|
||
|
||
var pagelist = await query.Where(t => t.TotalImageCount > 0).ToPagedListAsync(inQuery);
|
||
|
||
return ResponseOutput.Ok(pagelist);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取项目影像统计,有影像的subject 数量 访视数量
|
||
/// </summary>
|
||
/// <param name="trialId"></param>
|
||
/// <returns></returns>
|
||
public async Task<IResponseOutput<TrialImageStatInfo>> GetTrialVisitImageStatInfo(Guid trialId)
|
||
{
|
||
var subjectImageList = _subjectVisitRepository.Where(t => t.TrialId == trialId)
|
||
.Where(t => t.StudyList.Sum(t => t.InstanceCount) > 0 || t.NoneDicomStudyList.Sum(t => t.FileCount) > 0)
|
||
.GroupBy(t => t.SubjectId)
|
||
.Select(g => new
|
||
{
|
||
SubjectId = g.Key,
|
||
VisitCount = g.Count(),
|
||
ImageSize = g.SelectMany(t => t.NoneDicomStudyList).SelectMany(t => t.NoneDicomFileList).Sum(t => t.FileSize)
|
||
|
||
+ g.SelectMany(t => t.StudyList).SelectMany(t => t.InstanceList).Sum(t => t.FileSize)
|
||
})
|
||
.ToList();
|
||
|
||
var subjectCount = subjectImageList.Count;
|
||
|
||
var subjectVisitCount = subjectImageList.Sum(t => t.VisitCount);
|
||
|
||
var totalImageSize = subjectImageList.Sum(t => t.ImageSize);
|
||
|
||
return ResponseOutput.Ok(new TrialImageStatInfo { SubjectCount = subjectCount, SubjectVisitCount = subjectVisitCount, TotalImageSize = totalImageSize });
|
||
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 批量勾选访视 进行下载
|
||
/// </summary>
|
||
/// <param name="inCommand"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput> GetExportSubjectVisitImageList(TrialExportImageCommand inCommand)
|
||
{
|
||
|
||
if (inCommand.IsKeyImage)
|
||
{
|
||
var downloadInfo = _visitTaskRepository.Where(t => t.TrialId == inCommand.TrialId && t.ReadingCategory == ReadingCategory.Visit && t.ReadingTaskState == ReadingTaskState.HaveSigned && t.IsAnalysisCreate == false)
|
||
.Where(t => inCommand.SubjectVisitIdList.Contains((Guid)t.SourceSubjectVisitId))
|
||
.Select(t => new
|
||
{
|
||
t.Trial.ResearchProgramNo,
|
||
CriterionName = t.TrialReadingCriterion.CriterionName,
|
||
|
||
TrialSiteCode = t.Subject.TrialSite.TrialSiteCode,
|
||
SubjectCode = t.Subject.Code,
|
||
VisitName = (string?)t.SourceSubjectVisit.VisitName,
|
||
|
||
ArmEnum = t.ArmEnum,
|
||
|
||
QuestionMarkPictureList = t.ReadingTaskQuestionMarkList.Select(c => new { c.PicturePath, c.OtherPicturePath }).ToList(),
|
||
|
||
TableQuestionRowPictureList = t.LesionList.Select(c => new { c.PicturePath, c.OtherPicturePath }).ToList(),
|
||
|
||
|
||
IsJudgeSelect = t.JudgeResultTaskId == t.Id
|
||
|
||
|
||
}).ToList();
|
||
|
||
return ResponseOutput.Ok(downloadInfo);
|
||
}
|
||
else
|
||
{
|
||
|
||
var downloadInfo = _trialRepository.Where(t => t.Id == inCommand.TrialId).Select(t => new
|
||
{
|
||
t.ResearchProgramNo,
|
||
|
||
VisitList = t.SubjectVisitList.Where(t => inCommand.SubjectVisitIdList.Contains(t.Id)).Select(sv => new
|
||
{
|
||
TrialSiteCode = sv.TrialSite.TrialSiteCode,
|
||
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
|
||
})
|
||
})
|
||
|
||
}),
|
||
|
||
NoneDicomStudyList = sv.NoneDicomStudyList.Select(nd => new
|
||
{
|
||
nd.Modality,
|
||
nd.StudyCode,
|
||
nd.ImageDate,
|
||
|
||
FileList = nd.NoneDicomFileList.Select(file => new
|
||
{
|
||
file.FileName,
|
||
file.Path,
|
||
file.FileType
|
||
})
|
||
})
|
||
}).ToList()
|
||
|
||
}).FirstOrDefault();
|
||
|
||
|
||
return ResponseOutput.Ok(downloadInfo);
|
||
}
|
||
|
||
|
||
|
||
}
|
||
|
||
#endregion
|
||
|
||
|
||
|
||
|
||
#region 之前后端下载废弃
|
||
|
||
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 受试者级别所有的影像
|
||
/// 访视级别的影响 传递subjectVisitId
|
||
/// 标准Id是可选的 不同标准有些检查可能有过滤
|
||
/// </summary>
|
||
/// <param name="_subjectRepository"></param>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[Obsolete]
|
||
public async Task<IResponseOutput> GetSubejectOrVisitZipInfo([FromServices] IRepository<Subject> _subjectRepository, SubejctZipInfoQuery inQuery)
|
||
{
|
||
var isImageFilter = false;
|
||
|
||
var criterionModalitys = string.Empty;
|
||
|
||
if (inQuery.TrialReadingCriterionId != null)
|
||
{
|
||
var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(t => t.Id == inQuery.TrialReadingCriterionId).Select(t => new { t.IsImageFilter, t.CriterionModalitys }).FirstOrDefaultAsync();
|
||
|
||
if (criterionInfo != null)
|
||
{
|
||
isImageFilter = criterionInfo.IsImageFilter;
|
||
criterionModalitys = criterionInfo.CriterionModalitys;
|
||
}
|
||
|
||
}
|
||
|
||
if (inQuery.SubejectVisitId != null)
|
||
{
|
||
var query = from sv in _subjectVisitRepository.Where(t => t.Id == inQuery.SubejectVisitId)
|
||
|
||
|
||
select new
|
||
{
|
||
SubjectCode = sv.Subject.Code,
|
||
VisitName = sv.VisitName,
|
||
StudyList = sv.StudyList.AsQueryable().WhereIf(isImageFilter, t => ("|" + criterionModalitys + "|").Contains("|" + t.ModalityForEdit + "|"))
|
||
.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
|
||
})
|
||
})
|
||
|
||
}),
|
||
|
||
NoneDicomStudyList = sv.NoneDicomStudyList.AsQueryable().WhereIf(isImageFilter, t => ("|" + criterionModalitys + "|").Contains("|" + t.Modality + "|"))
|
||
.Select(nd => new
|
||
{
|
||
nd.Modality,
|
||
nd.StudyCode,
|
||
nd.ImageDate,
|
||
|
||
FileList = nd.NoneDicomFileList.Select(file => new
|
||
{
|
||
file.FileName,
|
||
file.Path,
|
||
file.FileType
|
||
})
|
||
})
|
||
};
|
||
|
||
var result = query.ToList();
|
||
|
||
return ResponseOutput.Ok(result);
|
||
}
|
||
else if (inQuery.SubejctId != null)
|
||
{
|
||
var query = from sv in _subjectRepository.Where(t => t.Id == inQuery.SubejctId).SelectMany(t => t.SubjectVisitList)
|
||
|
||
|
||
select new
|
||
{
|
||
SubjectCode = sv.Subject.Code,
|
||
VisitName = sv.VisitName,
|
||
StudyList = sv.StudyList.AsQueryable().WhereIf(isImageFilter, t => ("|" + criterionModalitys + "|").Contains("|" + t.ModalityForEdit + "|"))
|
||
.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
|
||
})
|
||
})
|
||
|
||
}),
|
||
|
||
NoneDicomStudyList = sv.NoneDicomStudyList.AsQueryable().WhereIf(isImageFilter, t => ("|" + criterionModalitys + "|").Contains("|" + t.Modality + "|"))
|
||
.Select(nd => new
|
||
{
|
||
nd.Modality,
|
||
nd.StudyCode,
|
||
nd.ImageDate,
|
||
|
||
FileList = nd.NoneDicomFileList.Select(file => new
|
||
{
|
||
file.FileName,
|
||
file.Path,
|
||
file.FileType
|
||
})
|
||
})
|
||
};
|
||
|
||
var result = query.ToList();
|
||
|
||
return ResponseOutput.Ok(result);
|
||
}
|
||
else
|
||
{
|
||
return ResponseOutput.NotOk("不允许 subjectId SubejectVisitId 都不传递");
|
||
}
|
||
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 后台任务调用,前端忽略该接口
|
||
/// </summary>
|
||
/// <param name="trialId"></param>
|
||
/// <param name="subjectVisitId"></param>
|
||
/// <param name="isDicom"></param>
|
||
/// <param name="isAnonymize"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
[Obsolete]
|
||
public async Task PackageAndAnonymizImage(Guid trialId, Guid subjectVisitId, bool isDicom, 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
|
||
})
|
||
})
|
||
|
||
}),
|
||
|
||
NoneDicomStudyList = sv.NoneDicomStudyList.Select(nd => new
|
||
{
|
||
nd.Modality,
|
||
nd.StudyCode,
|
||
nd.ImageDate,
|
||
|
||
FileList = nd.NoneDicomFileList.Select(file => new
|
||
{
|
||
file.FileName,
|
||
file.Path,
|
||
file.FileType
|
||
})
|
||
})
|
||
};
|
||
|
||
var info = query.FirstOrDefault();
|
||
|
||
if (info != null)
|
||
{
|
||
// 创建一个临时文件夹来存放文件
|
||
string tempFolderPath = Path.Combine(Directory.GetCurrentDirectory(), $"DownloadTemp_{NewId.NextGuid()}");
|
||
Directory.CreateDirectory(tempFolderPath);
|
||
|
||
//dicom 处理
|
||
|
||
if (isDicom)
|
||
{
|
||
// 遍历查询结果
|
||
foreach (var studyInfo in info.StudyList)
|
||
{
|
||
// 遍历 Series
|
||
foreach (var seriesInfo in studyInfo.SeriesList)
|
||
{
|
||
string studyDicomFolderPath = Path.Combine(tempFolderPath, "Dicom",/* $"{info.SubjectCode}_{info.VisitName}",*/ $"{studyInfo.StudyCode}_{studyInfo.StudyTime?.ToString("yyyy-MM-dd")}_{seriesInfo.Modality}");
|
||
|
||
// 创建 影像 文件夹
|
||
Directory.CreateDirectory(studyDicomFolderPath);
|
||
|
||
// 遍历 InstancePathList
|
||
foreach (var instanceInfo in seriesInfo.InstancePathList)
|
||
{
|
||
// 复制文件到相应的文件夹
|
||
string destinationPath = Path.Combine(studyDicomFolderPath, 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;
|
||
dataset.AddOrUpdate(DicomTag.StudyDate, string.Empty);
|
||
dataset.AddOrUpdate(DicomTag.StudyTime, string.Empty);
|
||
|
||
#region 前端已经匿名化,不需要做相关tag匿名化
|
||
//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
|
||
|
||
}
|
||
#endregion
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
var zipDicomPath = Path.Combine(Directory.GetCurrentDirectory(), $"{info.SubjectCode}_{info.VisitName}_ImageStudy_Dicom.zip");
|
||
ZipFile.CreateFromDirectory(Path.Combine(tempFolderPath, "Dicom"), zipDicomPath);
|
||
//上传到Oss
|
||
var relativeDicomPath = await _oSSService.UploadToOSSAsync(zipDicomPath, $"download_zip", false);
|
||
|
||
//await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.Id == subjectVisitId, u => new SubjectVisit() { PackState = PackState.Packed, VisitImageZipPath = relativeDicomPath });
|
||
|
||
|
||
File.Delete(zipDicomPath);
|
||
}
|
||
else
|
||
{
|
||
var relativeNoneDicomPath = string.Empty;
|
||
|
||
if (info.NoneDicomStudyList.Count() == 1 && info.NoneDicomStudyList.SelectMany(t => t.FileList).Count() == 1)
|
||
{
|
||
relativeNoneDicomPath = info.NoneDicomStudyList.First().FileList.First().Path;
|
||
}
|
||
else
|
||
{
|
||
//非dicom 处理
|
||
|
||
foreach (var noneDicomStudy in info.NoneDicomStudyList)
|
||
{
|
||
string studyNoneDicomFolderPath = Path.Combine(tempFolderPath, "NoneDicom", /*$"{info.SubjectCode}_{info.VisitName}",*/ $"{noneDicomStudy.StudyCode}_{noneDicomStudy.ImageDate.ToString("yyyy-MM-dd")}_{noneDicomStudy.Modality}");
|
||
|
||
Directory.CreateDirectory(studyNoneDicomFolderPath);
|
||
|
||
foreach (var file in noneDicomStudy.FileList)
|
||
{
|
||
string destinationPath = Path.Combine(studyNoneDicomFolderPath, Path.GetFileName(file.FileName));
|
||
|
||
//下载到当前目录
|
||
await _oSSService.DownLoadFromOSSAsync(HttpUtility.UrlDecode(file.Path), destinationPath);
|
||
}
|
||
}
|
||
|
||
var zipNoneDicomPath = Path.Combine(Directory.GetCurrentDirectory(), $"{info.SubjectCode}_{info.VisitName}_ImageStudy_NoneDicom.zip");
|
||
ZipFile.CreateFromDirectory(Path.Combine(tempFolderPath, "NoneDicom"), zipNoneDicomPath);
|
||
relativeNoneDicomPath = await _oSSService.UploadToOSSAsync(zipNoneDicomPath, $"download_zip", false);
|
||
|
||
File.Delete(zipNoneDicomPath);
|
||
}
|
||
|
||
//await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.Id == subjectVisitId, u => new SubjectVisit() { PackState = PackState.Packed, VisitNoDicomImageZipPath = relativeNoneDicomPath });
|
||
|
||
|
||
}
|
||
|
||
//清理文件夹
|
||
Directory.Delete(tempFolderPath, true);
|
||
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
//await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.Id == subjectVisitId, u => new SubjectVisit() { PackState = PackState.WaitPack });
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
}
|
||
#endregion
|
||
|
||
#region 按照任务为维度 展示上传的列表 废弃
|
||
/// <summary>
|
||
/// IR 影像上传任务列表 --old 20240903 界面调整,现在先废弃
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
[Obsolete]
|
||
public async Task<List<SubjectUploadTaskInfo>> GetIRUploadTaskList_Old(CRCUploadTaskQuery inQuery)
|
||
{
|
||
var query = _visitTaskRepository.Where(t => t.SubjectId == inQuery.SubjectId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId
|
||
&& t.SourceSubjectVisitId != null && t.DoctorUserId == _userInfo.UserRoleId && t.TaskState == TaskState.Effect)
|
||
.ProjectTo<SubjectUploadTaskInfo>(_mapper.ConfigurationProvider);
|
||
|
||
|
||
var list = await query.Where(t => t.SubjectCode == inQuery.SubjectCode).ToListAsync();
|
||
|
||
return list;
|
||
}
|
||
/// <summary>
|
||
/// IR 上传任务 dicom 列表 后处理的数据不能排序 --old 20240903 界面调整,现在先废弃
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
[Obsolete]
|
||
public async Task<List<IRUploadTaskDicomStudyDto>> GetIRUploadTaskDicomStudyList_Old(CRCUploadTaskStudyQuery inQuery)
|
||
{
|
||
var list = await _visitTaskRepository.Where(t => t.Id == inQuery.VisitTaskId)
|
||
.SelectMany(t => t.SourceSubjectVisit.StudyList)
|
||
.ProjectTo<IRUploadTaskDicomStudyDto>(_mapper.ConfigurationProvider).SortToListAsync(inQuery);
|
||
|
||
var taskDicomStudyList = _visitTaskRepository.Where(t => t.Id == inQuery.VisitTaskId)
|
||
.SelectMany(t => t.TaskStudyList)
|
||
.Select(u => new
|
||
{
|
||
u.Id,
|
||
u.SeriesCount,
|
||
u.InstanceCount,
|
||
SopInstanceList = u.InstanceList.Select(t => t.SopInstanceUid).ToList()
|
||
})
|
||
.ToList();
|
||
|
||
foreach (var item in list)
|
||
{
|
||
var find = taskDicomStudyList.FirstOrDefault(t => t.Id == item.Id);
|
||
|
||
if (find != null)
|
||
{
|
||
item.UploadedInstanceCount = find.InstanceCount;
|
||
item.UploadedSopInstanceUidList = find.SopInstanceList;
|
||
item.UploadedSeriesCount = find.SeriesCount;
|
||
}
|
||
}
|
||
|
||
return list;
|
||
}
|
||
|
||
/// <summary>
|
||
/// IR 上传任务 nonedicom 列表 后处理的数据不能排序 --old 20240903 界面调整,现在先废弃
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
[Obsolete]
|
||
public async Task<List<IRUploadTaskNoneDicomStudyDto>> GetIRUploadTaskNoneDicomStudyList_Old(CRCUploadTaskStudyQuery inQuery)
|
||
{
|
||
var list = await _visitTaskRepository.Where(t => t.Id == inQuery.VisitTaskId)
|
||
.SelectMany(t => t.SourceSubjectVisit.StudyList)
|
||
.ProjectTo<IRUploadTaskNoneDicomStudyDto>(_mapper.ConfigurationProvider).SortToListAsync(inQuery);
|
||
|
||
var taskNoneDicomStudyList = _visitTaskRepository.Where(t => t.Id == inQuery.VisitTaskId)
|
||
.SelectMany(t => t.TaskNoneDicomStudyFileList).Where(t => t.VisitTaskId == inQuery.VisitTaskId)
|
||
.Select(u => new
|
||
{
|
||
u.OriginNoneDicomStudyId,
|
||
})
|
||
.ToList();
|
||
|
||
foreach (var item in list)
|
||
{
|
||
item.UploadedFileCount = taskNoneDicomStudyList.Where(t => t.OriginNoneDicomStudyId == item.Id).Count();
|
||
}
|
||
|
||
return list;
|
||
|
||
}
|
||
#endregion
|
||
|
||
}
|
||
|
||
|
||
}
|