diff --git a/IRC.Core.SCP/IRC.Core.SCP.csproj b/IRC.Core.SCP/IRC.Core.SCP.csproj index 084654c25..999a17361 100644 --- a/IRC.Core.SCP/IRC.Core.SCP.csproj +++ b/IRC.Core.SCP/IRC.Core.SCP.csproj @@ -19,7 +19,7 @@ - + true diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj b/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj index 2bdee0a79..790c4f8ed 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj @@ -41,11 +41,11 @@ - + - + @@ -53,7 +53,7 @@ - + @@ -62,9 +62,9 @@ - + - + diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml index 27914ff5e..09103feb3 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -957,16 +957,6 @@ - - - 一致性分析结果导出 7 8 分别是自身 和组件一致性 - - - - - - - 获取阅片标准可以导出的列表 @@ -1118,6 +1108,14 @@ + + + + 下载已经删除的影像 + + + + 医生文档关联关系维护 diff --git a/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs b/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs index 34331fd2a..614c90328 100644 --- a/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs +++ b/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs @@ -135,7 +135,7 @@ namespace IRaCIS.Core.Application.Service.Common QuestionAnswerList = g.Select(t => new QCQuestionAnswerExport() { Answer = t.Answer, QuestionName = t.QuesitonName, ShowOrder = t.ShowOrder, QuestionId = t.QuestionId }).OrderBy(t => t.ShowOrder).ToList() - }).OrderBy(t => t.TrialSiteCode).ThenBy(t => t.SubjectCode).ThenBy(t => t.VisitNum).ThenBy(t=>t.CurrentQCEnum).ThenBy(t=>t.AuditTime).ToList(); + }).OrderBy(t => t.TrialSiteCode).ThenBy(t => t.SubjectCode).ThenBy(t => t.VisitNum).ThenBy(t => t.CurrentQCEnum).ThenBy(t => t.AuditTime).ToList(); var exportInfo = (await _trialRepository.Where(t => t.Id == inQuery.TrialId).IgnoreQueryFilters().ProjectTo(_mapper.ConfigurationProvider).FirstOrDefaultAsync()).IfNullThrowException(); @@ -2311,263 +2311,8 @@ namespace IRaCIS.Core.Application.Service.Common #region 通用阅片结果导出 - /// - /// 一致性分析结果导出 7 8 分别是自身 和组件一致性 - /// - /// - /// - /// - /// - /// - [HttpPost] - public async Task GetAnalysisTaskList_Export(VisitTaskQuery inQuery, - [FromServices] IRepository _commonDocumentRepository, - [FromServices] IDictionaryService _dictionaryService, - [FromServices] IRepository _trialRepository) - { - //每次查询必须是单标准的 - var criterion = await _readingQuestionCriterionTrialRepository.Where(t => t.Id == inQuery.TrialReadingCriterionId).Select(t => new { t.CriterionType, t.CriterionName, t.ArbitrationRule }).FirstNotNullAsync(); - var query = _visitTaskRepository.Where(t => t.TrialId == inQuery.TrialId && t.TaskAllocationState == TaskAllocationState.Allocated && (t.TaskState == TaskState.Effect || t.TaskState == TaskState.Freeze)) - - //一致性分析 - .WhereIf(inQuery.ReadingExportType == ExportResult.DetailedTableOfIntraReaderAnalysisResults, t => t.IsSelfAnalysis == true || t.IsSelfAnalysis == null) - .WhereIf(inQuery.ReadingExportType == ExportResult.DetailedTableOfIntraReaderAnalysisResults, t => t.IsSelfAnalysis == null ? t.Subject.SubjectVisitTaskList.Any(u => u.IsSelfAnalysis == true && u.VisitTaskNum == t.VisitTaskNum && u.DoctorUserId == t.DoctorUserId && u.TrialReadingCriterionId == t.TrialReadingCriterionId) : true) - .WhereIf(inQuery.ReadingExportType == ExportResult.DetailedTableOfInterReaderAnalysisResults, t => t.IsSelfAnalysis == false || t.IsSelfAnalysis == null) - - //访视和全局查询已签名完成的,裁判可以是未签名,未完成的 - .Where(t => (t.ReadingTaskState == ReadingTaskState.HaveSigned && (t.ReadingCategory == ReadingCategory.Visit || t.ReadingCategory == ReadingCategory.Global)) || t.ReadingCategory == ReadingCategory.Judge) - .WhereIf(inQuery.TrialReadingCriterionId != null, t => t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId) - .WhereIf(inQuery.TrialSiteId != null, t => t.Subject.TrialSiteId == inQuery.TrialSiteId) - - .WhereIf(inQuery.IsUrgent != null, t => t.IsUrgent == inQuery.IsUrgent) - .WhereIf(inQuery.DoctorUserId != null, t => t.DoctorUserId == inQuery.DoctorUserId) - .WhereIf(inQuery.ReadingCategory != null, t => t.ReadingCategory == inQuery.ReadingCategory) - //.WhereIf(inQuery.ReadingTaskState != null, t => t.ReadingTaskState == inQuery.ReadingTaskState) - .WhereIf(inQuery.TaskAllocationState != null, t => t.TaskAllocationState == inQuery.TaskAllocationState) - .WhereIf(inQuery.ArmEnum != null, t => t.ArmEnum == inQuery.ArmEnum) - .WhereIf(!string.IsNullOrEmpty(inQuery.TrialSiteCode), t => (t.BlindTrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.IsAnalysisCreate) || (t.Subject.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.IsAnalysisCreate == false)) - .WhereIf(!string.IsNullOrEmpty(inQuery.TaskName), t => t.TaskName.Contains(inQuery.TaskName) || t.TaskBlindName.Contains(inQuery.TaskName)) - .WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => t.Subject.Code.Contains(inQuery.SubjectCode)) - .WhereIf(inQuery.BeginAllocateDate != null, t => t.AllocateTime > inQuery.BeginAllocateDate) - .WhereIf(inQuery.EndAllocateDate != null, t => t.AllocateTime < inQuery.EndAllocateDate); - - var list = await query.ProjectTo(_mapper.ConfigurationProvider, - new - { - readingExportType = inQuery.ReadingExportType, - criterionType = criterion.CriterionType, - trialReadingCriterionId = inQuery.TrialReadingCriterionId, - isEn_Us = _userInfo.IsEn_Us - }).ToListAsync(); - - list = list.OrderBy(t => t.SubjectCode).ThenBy(t => t.ArmEnum).ThenBy(t => t.VisitTaskNum).ToList(); - - - var exportInfo = (await _trialRepository.Where(t => t.Id == inQuery.TrialId).IgnoreQueryFilters().ProjectTo(_mapper.ConfigurationProvider).FirstOrDefaultAsync()).IfNullThrowException(); - exportInfo.CriterionName = criterion.CriterionName; - - #region 处理系统标准存在疾病和整体肿瘤合并 - - //如果是以合并后的找翻译字典,会少,所以必须放在前面 - var translateDicNameList = list.SelectMany(t => t.QuestionAnswerList).Where(t => t.TranslateDicName.IsNotNullOrEmpty()).Select(t => t.TranslateDicName).Distinct().ToList(); - - //针对1.1 整体肿瘤评估 有的两列要合并一列 - if (criterion.CriterionType == CriterionType.RECIST1Point1 || criterion.CriterionType == CriterionType.RECIST1Pointt1_MB || criterion.CriterionType == CriterionType.IRECIST1Point1) - { - foreach (var item in list) - { - //处理合并表头 - - var questionType = item.IsBaseline == true ? QuestionType.ExistDisease : QuestionType.Tumor; - - var findItem = item.QuestionAnswerList.Where(t => t.QuestionType == questionType).FirstOrDefault(); - - if (findItem != null) - { - findItem.QuestionName = _userInfo.IsEn_Us ? "Overall Response" : "整体肿瘤评估"; - } - - - if (item.IsBaseline == true) - { - item.QuestionAnswerList = item.QuestionAnswerList.Where(t => t.QuestionType != QuestionType.Tumor).ToList(); - } - else - { - item.QuestionAnswerList = item.QuestionAnswerList.Where(t => t.QuestionType != QuestionType.ExistDisease).ToList(); - } - } - } - else if (criterion.CriterionType == CriterionType.Lugano2014 || criterion.CriterionType == CriterionType.Lugano2014WithoutPET) - { - - foreach (var item in list) - { - //处理合并表头 - - var questionType = item.IsBaseline == true ? QuestionType.ExistDisease : QuestionType.ImgOncology; - - var findItem = item.QuestionAnswerList.Where(t => t.QuestionType == questionType).FirstOrDefault(); - - if (findItem != null) - { - findItem.QuestionName = _userInfo.IsEn_Us ? "Overall Response" : "整体肿瘤评估"; - } - - if (item.IsBaseline == true) - { - item.QuestionAnswerList = item.QuestionAnswerList.Where(t => t.QuestionType != QuestionType.ImgOncology).ToList(); - } - else - { - item.QuestionAnswerList = item.QuestionAnswerList.Where(t => t.QuestionType != QuestionType.ExistDisease).ToList(); - } - } - } - else if (criterion.CriterionType == CriterionType.PCWG3) - { - - } - else if (criterion.CriterionType == CriterionType.SelfDefine) - { - //自定义的又问题名称重复 所以统一加上组名 - - //有重复的就加,没有重复的就不加 - if (list.Any(t => t.QuestionAnswerList.Select(t => t.QuestionName).Count() != t.QuestionAnswerList.Select(t => t.QuestionName).Distinct().Count())) - { - foreach (var item in list) - { - foreach (var qs in item.QuestionAnswerList) - { - qs.QuestionName = qs.Group + "_" + qs.QuestionName; - } - } - } - - - } - - #endregion - - var export_Template = StaticData.Export.TrialSelfAnalysisList_Export; - - #region 自身一致性分析和组间一致性分析 - - if (inQuery.ReadingExportType == ExportResult.DetailedTableOfIntraReaderAnalysisResults) - { - //找到非一致性分析的任务 - var selfExportList = list.Where(t => t.IsSelfAnalysis == null).ToList(); - - //处理一致性分析结果是否和原始阅片是否一致 - foreach (var item in selfExportList) - { - //找到一致性分析的结果 - var selfAnalysisTask = list.Where(t => t.IsSelfAnalysis == true && t.SubjectCode == item.SubjectCode && t.VisitTaskNum == item.VisitTaskNum && t.TaskName == t.TaskName && t.UserName == item.UserName).FirstOrDefault(); - - //将自身一致性分析的字段 赋值到访视任务这个字段 - item.IsAnalysisDiffToOriginalData = selfAnalysisTask?.IsAnalysisDiffToOriginalData; - - //处理再次阅片人的结果 - if (selfAnalysisTask != null) - { - var cloneQuestionAnswerList = selfAnalysisTask.QuestionAnswerList.Clone(); - - foreach (var qItem in cloneQuestionAnswerList) - { - qItem.QuestionName = qItem.QuestionName + $"{(_userInfo.IsEn_Us ? "(Again)" : "(再次)")}"; - } - - item.QuestionAnswerList = item.QuestionAnswerList.Union(cloneQuestionAnswerList).ToList(); - } - } - - list = selfExportList; - } - else - { - export_Template = StaticData.Export.TrialGroupAnalysisList_Export; - - var newList = new List(); - - foreach (var group in list.GroupBy(t => new { t.SubjectCode, t.VisitTaskNum, t.TaskName }).OrderBy(g => g.Key.SubjectCode).ThenBy(g => g.Key.VisitTaskNum)) - { - var subjectVisitGroupList = group.ToList(); - - - //找到当前访视组间一致性分析的任务结果 - - var groupOtherTaskList = subjectVisitGroupList.Where(t => t.IsSelfAnalysis == false).ToList(); - - foreach (var subjectVisitTaskArm in subjectVisitGroupList.Where(t => t.IsSelfAnalysis == null).OrderBy(t => t.ArmEnum)) - { - foreach (var otherTask in groupOtherTaskList) - { - //非一致性分析任务 - var cloneObj = subjectVisitTaskArm.Clone(); - - var otherTaskQuestionAnserList = otherTask.QuestionAnswerList.Clone(); - - foreach (var qItem in otherTaskQuestionAnserList) - { - qItem.QuestionName = qItem.QuestionName + $"{(_userInfo.IsEn_Us ? "(Again)" : "(再次)")}"; - } - - //处理 再次阅片人,再次阅片人角色 两列 - var addQuestionList = new List(); - - addQuestionList.Add(new CommonQuesionInfo() { QuestionName = _userInfo.IsEn_Us ? "Reviwer(Again)" : "阅片人(再次)", QuestionValue = otherTask.UserName }); - addQuestionList.Add(new CommonQuesionInfo() { QuestionName = _userInfo.IsEn_Us ? "Reviwer Role(Again)" : "阅片人角色(再次)", QuestionValue = ((int)otherTask.ArmEnum).ToString(), TranslateDicName = "ArmEnum" }); - - - cloneObj.QuestionAnswerList = cloneObj.QuestionAnswerList.Union(addQuestionList).Union(otherTaskQuestionAnserList).ToList(); - - - cloneObj.IsGroupAnalysisDiffToOriginalData = cloneObj.ArmEnum == Arm.DoubleReadingArm1 ? otherTask.IsGroupDiffArm1 : otherTask.IsGroupDiffArm2; - - newList.Add(cloneObj); - } - } - } - translateDicNameList.Add("ArmEnum"); - - list = newList; - - } - - #endregion - - var columNameList = list.SelectMany(t => t.QuestionAnswerList).Where(t => t.QuestionName.IsNotNullOrEmpty()).Select(t => t.QuestionName).Distinct().ToList(); - - exportInfo.List = ExportExcelConverterDate.ConvertToClientTimeInObject(list.Where(t => t.ReadingCategory != ReadingCategory.Global).ToList(), _userInfo.TimeZoneId); - exportInfo.CurrentTime = ExportExcelConverterDate.DateTimeInternationalToString(DateTime.Now, _userInfo.TimeZoneId); - - var dynamicColumnConfig = new DynamicColumnConfig() - { - //可读的列表名行索引,不是{{}} 模板行索引 - AutoColumnTitleRowIndex = 2, - AutoColumnStartIndex = 5, - TempalteLastColumnIndex = 4, - DynamicItemDicName = "TranslateDicName", - DynamicItemValueName = "QuestionValue", - DynamicItemTitleName = "QuestionName", - DynamicListName = "QuestionAnswerList", - RemoveColunmIndexList = new List() { }, - ColumnIdNameList = columNameList.Select(t => new DynamicColumnConfig.ColumItem() { Id = Guid.Empty, Name = t }).ToList(), - TranslateDicNameList = translateDicNameList ?? new List() - }; - - - var (memoryStream, fileName) = await ExcelExportHelper.DataExport_NpoiTestAsync(export_Template, exportInfo, _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(AnalysisDynamicCommonExport), criterion.CriterionType, dynamicColumnConfig); - - return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") - { - FileDownloadName = $"{exportInfo.ResearchProgramNo}_{exportInfo.CriterionName}_{fileName}_{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx" - }; - - } - /// /// 获取阅片标准可以导出的列表 @@ -2898,7 +2643,8 @@ namespace IRaCIS.Core.Application.Service.Common { #region 外层问题处理 - if (criterion.CriterionType == CriterionType.RECIST1Point1 || criterion.CriterionType == CriterionType.RECIST1Pointt1_MB || criterion.CriterionType == CriterionType.IRECIST1Point1) + if (criterion.CriterionType == CriterionType.RECIST1Point1 || criterion.CriterionType == CriterionType.RECIST1Pointt1_MB + || criterion.CriterionType == CriterionType.IRECIST1Point1 || criterion.CriterionType == CriterionType.mRECISTHCC) { fistLeveLNameList = trialConfigQuestionList.Select(t => new DynamicColumnConfig.ColumItem() @@ -2941,7 +2687,8 @@ namespace IRaCIS.Core.Application.Service.Common var extralNameList = new List(); if (criterion.CriterionType == CriterionType.RECIST1Point1 || criterion.CriterionType == CriterionType.RECIST1Pointt1_MB - || criterion.CriterionType == CriterionType.IRECIST1Point1 || criterion.CriterionType == CriterionType.Lugano2014 || criterion.CriterionType == CriterionType.Lugano2014WithoutPET) + || criterion.CriterionType == CriterionType.IRECIST1Point1 || criterion.CriterionType == CriterionType.mRECISTHCC + || criterion.CriterionType == CriterionType.Lugano2014 || criterion.CriterionType == CriterionType.Lugano2014WithoutPET) { //if(inQuery.ReadingExportType == ExportResult.DetailedTableOfLesions) @@ -2982,7 +2729,8 @@ namespace IRaCIS.Core.Application.Service.Common var addLessionInfoList = new List(); if (criterion.CriterionType == CriterionType.RECIST1Point1 || criterion.CriterionType == CriterionType.RECIST1Pointt1_MB - || criterion.CriterionType == CriterionType.IRECIST1Point1 || criterion.CriterionType == CriterionType.Lugano2014 || criterion.CriterionType == CriterionType.Lugano2014WithoutPET) + || criterion.CriterionType == CriterionType.IRECIST1Point1 || criterion.CriterionType == CriterionType.mRECISTHCC + || criterion.CriterionType == CriterionType.Lugano2014 || criterion.CriterionType == CriterionType.Lugano2014WithoutPET) { //病灶编号 和病灶类型没有配置,但是需要有的 addLessionInfoList.Add(new CommonQuesionInfo() { QuestionName = _userInfo.IsEn_Us ? "Lesion ID" : "病灶编号", QuestionValue = lession.LessionCode }); @@ -3022,7 +2770,8 @@ namespace IRaCIS.Core.Application.Service.Common #endregion #region 不管是list 还是taskList 最终处理的数据都是list 处理好数据后合并 - if (criterion.CriterionType == CriterionType.RECIST1Point1 || criterion.CriterionType == CriterionType.RECIST1Pointt1_MB || criterion.CriterionType == CriterionType.IRECIST1Point1) + if (criterion.CriterionType == CriterionType.RECIST1Point1 || criterion.CriterionType == CriterionType.RECIST1Pointt1_MB + || criterion.CriterionType == CriterionType.IRECIST1Point1 || criterion.CriterionType == CriterionType.mRECISTHCC) { //针对1.1 整体肿瘤评估 有的两列要合并一列 foreach (var item in list) diff --git a/IRaCIS.Core.Application/Service/Common/TrialImageDownloadService.cs b/IRaCIS.Core.Application/Service/Common/TrialImageDownloadService.cs index d06a9d8f3..5b4d1ef88 100644 --- a/IRaCIS.Core.Application/Service/Common/TrialImageDownloadService.cs +++ b/IRaCIS.Core.Application/Service/Common/TrialImageDownloadService.cs @@ -1,22 +1,30 @@ using DocumentFormat.OpenXml.EMMA; +using DocumentFormat.OpenXml.Office2010.Excel; +using DocumentFormat.OpenXml.Office2013.Drawing.ChartStyle; using FellowOakDicom; using FellowOakDicom.Imaging; using FellowOakDicom.Imaging.Render; using FellowOakDicom.IO.Buffer; using IRaCIS.Core.Application.Helper; +using IRaCIS.Core.Application.ViewModel; +using IRaCIS.Core.Domain.Models; using MassTransit; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; +using MiniExcelLibs; using SharpCompress.Common; using System; using System.Collections.Generic; +using System.Data; +using System.Diagnostics; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Web; using static IRaCIS.Core.Domain.Share.StaticData; +using static Microsoft.EntityFrameworkCore.DbLoggerCategory; namespace IRaCIS.Core.Application.Service { @@ -243,11 +251,12 @@ namespace IRaCIS.Core.Application.Service /// [HttpGet] [AllowAnonymous] - public async Task DownloadAndUploadTrialData(Guid trialId, [FromServices] IRepository _instanceRepository, + public async Task DownloadAndUploadTrialData(Guid trialId, + [FromServices] IRepository _instanceRepository, [FromServices] IRepository _studyRepository, [FromServices] IRepository _seriesRepository) { - var list = await _instanceRepository.Where(t => t.TrialId == trialId && t.SubjectVisitId == Guid.Parse("01000000-0a00-0242-bd20-08dcce543ded" ) && t.DicomStudy.ModalityForEdit == "IVUS") + var list = await _instanceRepository.Where(t => t.TrialId == trialId && t.SubjectVisitId == Guid.Parse("01000000-0a00-0242-bd20-08dcce543ded") && t.DicomStudy.ModalityForEdit == "IVUS") .Select(t => new { t.SeriesId, t.StudyId, t.Id, t.Path }).ToListAsync(); int totalCount = list.Count; @@ -288,7 +297,7 @@ namespace IRaCIS.Core.Application.Service await _instanceRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Id, u => new DicomInstance() { - IsEncapsulated= syntax.IsEncapsulated, + IsEncapsulated = syntax.IsEncapsulated, TransferSytaxUID = dirInfo.TransferSytaxUID, SOPClassUID = dirInfo.SOPClassUID, MediaStorageSOPClassUID = dirInfo.MediaStorageSOPClassUID, @@ -334,6 +343,715 @@ namespace IRaCIS.Core.Application.Service return ResponseOutput.Ok(); } + + /// + /// 维护dir 需求新增的字段 + + /// + /// + /// + /// + /// + /// + public async Task TrialImageAddExtralField(Guid trialId, + [FromServices] IRepository _instanceRepository, + [FromServices] IRepository _studyRepository, + [FromServices] IRepository _seriesRepository) + { + // UPDATE DicomStudy + //SET DicomStudyDate = CONVERT(char(8), StudyTime, 112), --yyyyMMdd + // DicomStudyTime = REPLACE(CONVERT(char(8), StudyTime, 108), ':', ''); --HHmmss + // where DicomStudyDate = '' + + + //instance 找到传输语法为空的,然后分组 + var seriesList = _instanceRepository.Where(t => t.TrialId == trialId && t.TransferSytaxUID == "") + //按照序列 和 NumberOfFrames 分组 + .GroupBy(t => new { t.NumberOfFrames, t.SeriesId }) + // 每个分组 取数据最小的一条 + .Select(g => new { g.Key.SeriesId, g.Key.NumberOfFrames, g.OrderBy(t => t.FileSize).First().Path }).ToList(); + + foreach (var item in seriesList) + { + var stream = await _oSSService.GetStreamFromOSSAsync(item.Path); + + var dicomFile = DicomFile.Open(stream); + + var pixelData = DicomPixelData.Create(dicomFile.Dataset); + + //获取像素是否为封装形式 + var syntax = dicomFile.Dataset.InternalTransferSyntax; + + //读取需要维护的值 + var transferSyntaxUID = dicomFile.FileMetaInfo.GetSingleValueOrDefault(DicomTag.TransferSyntaxUID, string.Empty); + var mediaStorageSOPClassUID = dicomFile.FileMetaInfo.GetSingleValueOrDefault(DicomTag.MediaStorageSOPClassUID, string.Empty); + var mediaStorageSOPInstanceUID = dicomFile.FileMetaInfo.GetSingleValueOrDefault(DicomTag.MediaStorageSOPInstanceUID, string.Empty); + var sOPClassUID = dicomFile.Dataset.GetSingleValueOrDefault(DicomTag.SOPClassUID, string.Empty); + + //维护序列层级四个字段 后再用sql 维护study series 时间拆分 和 MediaStorageSOPInstanceUID + await _instanceRepository.BatchUpdateNoTrackingAsync(t => t.SeriesId == item.SeriesId, t => new DicomInstance() + { + IsEncapsulated = syntax.IsEncapsulated, + TransferSytaxUID = transferSyntaxUID, + MediaStorageSOPClassUID = mediaStorageSOPClassUID, + SOPClassUID = sOPClassUID, + }); + + } + + return ResponseOutput.Ok(); + + } + + + /// + /// 下载已经删除的影像 + /// + /// + /// + [HttpPost] + [AllowAnonymous] + public async Task DownloadDeleteTrialImage(Guid trialId) + { + trialId = Guid.Parse("01000000-ac13-0242-6397-08dcd2d2a091"); + + var downloadInfo = _trialRepository.Where(t => t.Id == trialId, ignoreQueryFilters: true).Select(t => new + { + t.ResearchProgramNo, + + VisitList = t.SubjectVisitList + .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, + z.SeriesNumber, + + InstancePathList = z.DicomInstanceList.Where(t => t.IsDeleted == true || t.DicomSerie.IsDeleted == true || t.IsReading == false || t.DicomSerie.IsReading == false).Select(k => new + { + k.Path, + k.FileSize + }).ToList() + }) + + }).ToList() + }).ToList() + + }).FirstOrDefault(); + + + var filesizes = downloadInfo.VisitList.SelectMany(t => t.StudyList).SelectMany(t => t.SeriesList).SelectMany(t => t.InstancePathList).Sum(t => t.FileSize); + var count2 = downloadInfo.VisitList.SelectMany(t => t.StudyList).SelectMany(t => t.SeriesList).SelectMany(t => t.InstancePathList).Count(); + + Console.WriteLine($"下载总数量:{count2},总大小{filesizes}"); + + if (downloadInfo != null) + { + var downloadJobs = new List<(string Path, Func Job)>(); + + var rootFolder = @"E:\DownloadImage"; + + //var rootFolder = FileStoreHelper.GetDonwnloadImageFolder(_hostEnvironment); + + // 获取无效字符(系统定义的) + string invalidChars = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars()); + + // 用正则表达式替换所有非法字符为下划线或空字符 + string pattern = $"[{Regex.Escape(invalidChars)}]"; + + var regexNo = Regex.Replace(downloadInfo.ResearchProgramNo, pattern, "_"); + + // 创建一个临时文件夹来存放文件 + string trialFolderPath = Path.Combine(rootFolder, $"{regexNo}_{NewId.NextGuid()}"); + Directory.CreateDirectory(trialFolderPath); + + foreach (var visitItem in downloadInfo.VisitList) + { + if (visitItem.StudyList.Count() == 0) + { + continue; + } + + #region 处理 中心,受试者dicom non-dicom 文件夹层级 + + //var siteFolderPath = Path.Combine(trialFolderPath, visitItem.TrialSiteCode); + //if (!Directory.Exists(siteFolderPath)) + //{ + // Directory.CreateDirectory(siteFolderPath); + //} + + #endregion + + + foreach (var studyInfo in visitItem.StudyList) + { + // 遍历 Series + foreach (var seriesInfo in studyInfo.SeriesList) + { + string studyDicomFolderPath = Path.Combine(trialFolderPath, $"{visitItem.SubjectCode}_{visitItem.VisitName}", $"{studyInfo.StudyCode}_{studyInfo.StudyTime?.ToString("yyyy-MM-dd")}", $"{seriesInfo.SeriesNumber}"); + + // 创建 影像 文件夹 + Directory.CreateDirectory(studyDicomFolderPath); + + // 遍历 InstancePathList + foreach (var instanceInfo in seriesInfo.InstancePathList) + { + // 复制文件到相应的文件夹 + string destinationPath = Path.Combine(studyDicomFolderPath, Path.GetFileName(instanceInfo.Path)); + + + //加入到下载任务里 + downloadJobs.Add((instanceInfo.Path, () => _oSSService.DownLoadFromOSSAsync(instanceInfo.Path, destinationPath))); + + //下载到当前目录 + //await _oSSService.DownLoadFromOSSAsync(instanceInfo.Path, destinationPath); + } + } + + + } + } + + #region 异步方式处理 + + int totalCount = downloadJobs.Count; + int downloadedCount = 0; + + // 在 trialFolderPath 下面放一个失败记录文件 + string failedLogPath = Path.Combine(trialFolderPath, "failed_downloads.txt"); + + // 确保文件存在(如果之前有就清空) + File.WriteAllText(failedLogPath, ""); + + foreach (var job in downloadJobs) + { + try + { + await job.Job(); + } + catch (Exception ex) + { + + + string errorMessage = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 下载失败: {job.Path}, 错误: {ex.Message}\r\n"; + + Console.WriteLine(errorMessage); + + await File.AppendAllTextAsync(failedLogPath, errorMessage); + } + + downloadedCount++; + + // 每处理50个,输出一次进度(或最后一个时也输出) + if (downloadedCount % 50 == 0 || downloadedCount == totalCount) + { + Console.WriteLine($"已下载 {downloadedCount} / {totalCount} 个文件,完成 {(downloadedCount * 100.0 / totalCount):F2}%"); + } + } + #endregion + + #region 多线程测试 + + //const int batchSize = 15; + //int totalCount = downloadJobs.Count; + //int downloadedCount = 0; + + //for (int i = 0; i < downloadJobs.Count; i += batchSize) + //{ + // var batch = downloadJobs.Skip(i).Take(batchSize).Select(job => job()); + + // await Task.WhenAll(batch); + + // downloadedCount += batch.Count(); + + // Console.WriteLine($"已下载 {downloadedCount} / {totalCount} 个文件,完成 {(downloadedCount * 100.0 / totalCount):F2}%"); + //} + #endregion + + } + + return ResponseOutput.Ok(); + + + } + + + [AllowAnonymous] + public async Task ReadDicomDataWriteDB([FromServices] IRepository _instanceRepository) + { + var testPath = @"E:\WXT001"; + var path = @"E:\WXT001"; + + var files = Directory.GetFiles(testPath, "*", SearchOption.AllDirectories) + // 只要没有后缀(Windows 显示类型是 .file) + .Where(f => string.IsNullOrEmpty(Path.GetExtension(f))) + .Where(f => Guid.TryParse(Path.GetFileNameWithoutExtension(f), out _)) + .ToList(); + + Console.WriteLine($"找到 {files.Count} 个 DICOM 文件"); + + int total = files.Count; + int processed = 0; + double lastPercent = 0; + + var options = new ParallelOptions { MaxDegreeOfParallelism = 12 }; + + // 输出文件路径 + var outputFile = Path.Combine(@"D:\dicomWrite", $"{Guid.NewGuid()}_dicom_info.txt"); + + var outputErrorFile = Path.Combine(@"D:\dicomWrite", $"{Guid.NewGuid()}_dicom_info_error.txt"); + + // 用并发安全的写法(锁保护) + var fileLock = new object(); + + foreach (var file in files) + { + try + { + var id = Guid.Parse(Path.GetFileNameWithoutExtension(file)); + var dicomFile = DicomFile.Open(file); + + var dataset = dicomFile.Dataset; + var fileMeta = dicomFile.FileMetaInfo; + var syntax = dataset.InternalTransferSyntax; + + + + //单位 设备 PatientId Visit 检查UId 帧数 + + var stationName = dataset.GetSingleValueOrDefault(DicomTag.StationName, string.Empty); + + var institutionName = dataset.GetSingleValueOrDefault(DicomTag.InstitutionName, string.Empty); + + var manufacturer = dataset.GetSingleValueOrDefault(DicomTag.Manufacturer, string.Empty); + + //PatientID TrialCode_SubjectCode + //var patientID = dataset.GetSingleValueOrDefault(DicomTag.PatientID, string.Empty); + + //SubjectCode + var clinicalTrialSubjectID = dataset.GetSingleValueOrDefault(DicomTag.ClinicalTrialSubjectID, string.Empty); + //访视visitNum + var clinicalTrialTimePointID = dataset.GetSingleValueOrDefault(DicomTag.ClinicalTrialTimePointID, string.Empty); + var studyInstanceUID = dataset.GetSingleValueOrDefault(DicomTag.StudyInstanceUID, string.Empty); + var seriesInstanceUID = dataset.GetSingleValueOrDefault(DicomTag.SeriesInstanceUID, string.Empty); + var sOPInstanceUID = dataset.GetSingleValueOrDefault(DicomTag.SOPInstanceUID, string.Empty); + + var numberOfFrames = dataset.GetSingleValueOrDefault(DicomTag.NumberOfFrames, 1); + + + // 传输语法 + var transferSyntaxUID = fileMeta.GetSingleValueOrDefault(DicomTag.TransferSyntaxUID, string.Empty); + var sOPClassUID = dataset.GetSingleValueOrDefault(DicomTag.SOPClassUID, string.Empty); + var mediaStorageSOPClassUID = fileMeta.GetSingleValueOrDefault(DicomTag.MediaStorageSOPClassUID, string.Empty); + + var mediaStorageSOPInstanceUID = fileMeta.GetSingleValueOrDefault(DicomTag.MediaStorageSOPInstanceUID, string.Empty); + + + // 拼接一行 CSV 格式 + var line = string.Join(",", + id, + stationName, + institutionName, + manufacturer, + clinicalTrialSubjectID, + clinicalTrialTimePointID, + studyInstanceUID, + seriesInstanceUID, + sOPInstanceUID, + numberOfFrames, + transferSyntaxUID, + sOPClassUID, + mediaStorageSOPClassUID, + mediaStorageSOPInstanceUID + + ); + + + await File.AppendAllTextAsync(outputFile, line + Environment.NewLine); + + await _instanceRepository.BatchUpdateNoTrackingAsync( + t => t.Id == id, + t => new DicomInstance + { + IsEncapsulated = syntax.IsEncapsulated, + TransferSytaxUID = transferSyntaxUID, + MediaStorageSOPClassUID = mediaStorageSOPClassUID, + SOPClassUID = sOPClassUID, + MediaStorageSOPInstanceUID = mediaStorageSOPInstanceUID + }, false); + } + catch (Exception ex) + { + var errorMsg = $"{DateTime.Now}❌ {file} 解析失败: {ex.Message}"; + Console.WriteLine(errorMsg); + + await File.AppendAllTextAsync(outputErrorFile, errorMsg + Environment.NewLine); + } + finally + { + var done = Interlocked.Increment(ref processed); + double percent = done * 100.0 / total; + + // 只在进度提升 >= 1% 时打印 + if (percent - lastPercent >= 5.0 || done == total) + { + lastPercent = percent; + Console.WriteLine($"{DateTime.Now} 进度: {done}/{total} ({percent:F2}%)"); + } + } + + } + + + + + + + return ResponseOutput.Ok(); + } + + #region 维护已经下载本地的数据 + + [AllowAnonymous] + public async Task ReadExcelData([FromServices] IRepository _instanceRepository) + { + var rows = await MiniExcel.QueryAsync(@"C:\Users\hang\Desktop\维护数据读取.xlsx"); + + rows = rows.Where(t => !string.IsNullOrEmpty(t.InstanceId.ToString())).ToList(); + + int total = rows.Count(); + int processed = 0; + double lastPercent = 0; + + var outputErrorFile = Path.Combine(@"D:\dicomWrite", $"{Guid.NewGuid()}_dicom_info_error.txt"); + + foreach (var item in rows) + { + + + try + { + await _instanceRepository.BatchUpdateNoTrackingAsync( + t => t.Id == item.InstanceId, + t => new DicomInstance + { + + IsEncapsulated = item.IsEncapsulated, + TransferSytaxUID = item.TransferSyntaxUID, + MediaStorageSOPClassUID = item.MediaStorageSOPClassUID, + SOPClassUID = item.SOPClassUID, + MediaStorageSOPInstanceUID = item.MediaStorageSOPInstanceUID + }, false); + } + catch (Exception ex) + { + + var errorMsg = $"{item.InstanceId} {DateTime.Now} 更新失败: {ex.Message}"; + Console.WriteLine(errorMsg); + + await File.AppendAllTextAsync(outputErrorFile, errorMsg + Environment.NewLine); + } + finally + { + processed++; + double percent = processed * 100.0 / total; + + // 每提升 5% 或完成时输出 + if (percent - lastPercent >= 2.0 || processed == total) + { + lastPercent = percent; + Console.WriteLine($"{DateTime.Now} 进度: {processed}/{total} ({percent:F2}%)"); + } + } + + } + + + + + return ResponseOutput.Ok(); + } + + public class DicomSOPInfo + { + public Guid InstanceId { get; set; } + + + public string TransferSyntaxUID { get; set; } + + public string SOPClassUID { get; set; } + + public string MediaStorageSOPClassUID { get; set; } + + public string MediaStorageSOPInstanceUID { get; set; } + + public bool IsEncapsulated => DicomTransferSyntax.Lookup(DicomUID.Parse(TransferSyntaxUID)).IsEncapsulated; + + + + } + + + [AllowAnonymous] + public async Task ReadExcelImageDataInstanceIsReading([FromServices] IRepository _instanceRepository, + [FromServices] IRepository _seriesRepository, + [FromServices] IRepository _studyRepository) + { + + var trialId = Guid.Parse("01000000-ac13-0242-6397-08dcd2d2a091"); + + var rows = await MiniExcel.QueryAsync(@"C:\Users\hang\Desktop\instanceReading.xlsx"); + + rows = rows.Where(t => !string.IsNullOrEmpty(t.SopInstanceUid) && t.SopInstanceUid.Length > 15).ToList(); + + var outputErrorFile = Path.Combine(@"D:\dicomWrite", $"{Guid.NewGuid()}_dicom_info_error.txt"); + + + //foreach (var batch in rows.Chunk(20)) + //{ + // var sopUids = batch.Select(x => x.SopInstanceUid).ToList(); + + // try + // { + // await _instanceRepository.BatchUpdateNoTrackingAsync( + // t => sopUids.Contains(t.SopInstanceUid) && t.TrialId == trialId, + // t => new DicomInstance + // { + // IsReading = true, + // IsDeleted = false + // }, false); + + + // await _seriesRepository.BatchUpdateNoTrackingAsync( + // t => t.DicomInstanceList.Any(t => sopUids.Contains(t.SopInstanceUid)) && t.TrialId == trialId, + // t => new DicomSeries + // { + // IsReading = true, + // IsDeleted = false + // }, false); + // } + // catch (Exception ex) + // { + // var errorMsg = $"{string.Join(",", sopUids)} {DateTime.Now} 批量更新失败: {ex.Message}"; + // Console.WriteLine(errorMsg); + // await File.AppendAllTextAsync(outputErrorFile, errorMsg + Environment.NewLine); + // } + //} + + //找到该项目的检查,实时统计数量,并且回更数据库 + + var studyList = _studyRepository.Where(t => t.TrialId == trialId && (t.SeriesCount != t.SeriesList.Count() || t.InstanceCount != t.InstanceList.Count())) + .Select(t => new + { + t.Id, + t.StudyCode, + DBSeriesCount = t.SeriesCount, + DBInstanceCount = t.InstanceCount, + + ActrualSeriesCount = t.SeriesList.Count(), + + ActrualInstanceCount = t.InstanceList.Count(), + + }).ToList(); + + + var seriesList = _seriesRepository.Where(t => t.TrialId == trialId && t.InstanceCount != t.DicomInstanceList.Count()) + .Select(t => new + { + SeriesId = t.Id, + t.DicomStudy.StudyCode, + DBInstanceCount = t.InstanceCount, + ActrualInstanceCount = t.DicomInstanceList.Count(), + + }).ToList(); + + + await File.AppendAllTextAsync(outputErrorFile, studyList.ToJsonStr() + Environment.NewLine); + + await File.AppendAllTextAsync(outputErrorFile, seriesList.ToJsonStr() + Environment.NewLine); + + return ResponseOutput.Ok(); + } + + public class DicomSOPInstanceInfo + { + public string SopInstanceUid { get; set; } + + + } + + #endregion + + + #region 通过Excel 读取未下载的,边下载边维护数据 + + [AllowAnonymous] + public async Task WriteNeedDealData([FromServices] IRepository _instanceRepository) + { + + #region 获取差集数据 + //var rows = await MiniExcel.QueryAsync(@"C:\Users\hang\Desktop\维护数据读取.xlsx"); + + //rows = rows.Where(t => !string.IsNullOrEmpty(t.InstanceId.ToString())).ToList(); + + //var allRows = await MiniExcel.QueryAsync(@"C:\Users\hang\Desktop\AllData.xlsx"); + + //allRows = allRows.Where(t => !string.IsNullOrEmpty(t.InstanceId.ToString())).ToList(); + + //var needDealRows = allRows.Where(t => !rows.Select(c => c.InstanceId).Contains(t.InstanceId)).ToList(); + + //var outputFile = Path.Combine(@"D:\dicomWrite", $"{Guid.NewGuid()}_dicom_info.txt"); + + //foreach (var item in needDealRows) + //{ + // var line = string.Join(",", item.InstanceId, item.Path); + + // await File.AppendAllTextAsync(outputFile, line + Environment.NewLine); + //} + + #endregion + + var folder = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment); + + var needDealRows = await MiniExcel.QueryAsync(Path.Combine(folder, "needDownload.xlsx")); + + needDealRows = needDealRows.Where(t => !string.IsNullOrEmpty(t.InstanceId.ToString())).ToList(); + + + + var outputFile = Path.Combine(folder, $"{Guid.NewGuid()}_dicom_info.txt"); + + var outputErrorFile = Path.Combine(folder, $"{Guid.NewGuid()}_dicom_info_error.txt"); + + int total = needDealRows.Count(); + + Console.WriteLine($"需要处理数量{total}"); + + int processed = 0; + double lastPercent = 0; + + foreach (var item in needDealRows) + { + + try + { + await using var stream = await _oSSService.GetStreamFromOSSAsync(item.Path); + + var dicomFile = DicomFile.Open(stream); + + var dataset = dicomFile.Dataset; + var fileMeta = dicomFile.FileMetaInfo; + + var pixelData = DicomPixelData.Create(dicomFile.Dataset); + + //获取像素是否为封装形式 + var syntax = dicomFile.Dataset.InternalTransferSyntax; + + var stationName = dataset.GetSingleValueOrDefault(DicomTag.StationName, string.Empty); + + var institutionName = dataset.GetSingleValueOrDefault(DicomTag.InstitutionName, string.Empty); + + var manufacturer = dataset.GetSingleValueOrDefault(DicomTag.Manufacturer, string.Empty); + + //PatientID TrialCode_SubjectCode + //var patientID = dataset.GetSingleValueOrDefault(DicomTag.PatientID, string.Empty); + + //SubjectCode + var clinicalTrialSubjectID = dataset.GetSingleValueOrDefault(DicomTag.ClinicalTrialSubjectID, string.Empty); + //访视visitNum + var clinicalTrialTimePointID = dataset.GetSingleValueOrDefault(DicomTag.ClinicalTrialTimePointID, string.Empty); + var studyInstanceUID = dataset.GetSingleValueOrDefault(DicomTag.StudyInstanceUID, string.Empty); + var seriesInstanceUID = dataset.GetSingleValueOrDefault(DicomTag.SeriesInstanceUID, string.Empty); + var sOPInstanceUID = dataset.GetSingleValueOrDefault(DicomTag.SOPInstanceUID, string.Empty); + + var numberOfFrames = dataset.GetSingleValueOrDefault(DicomTag.NumberOfFrames, 1); + + + // 传输语法 + var transferSyntaxUID = fileMeta.GetSingleValueOrDefault(DicomTag.TransferSyntaxUID, string.Empty); + var sOPClassUID = dataset.GetSingleValueOrDefault(DicomTag.SOPClassUID, string.Empty); + var mediaStorageSOPClassUID = fileMeta.GetSingleValueOrDefault(DicomTag.MediaStorageSOPClassUID, string.Empty); + + var mediaStorageSOPInstanceUID = fileMeta.GetSingleValueOrDefault(DicomTag.MediaStorageSOPInstanceUID, string.Empty); + + + var line = string.Join(",", + item.InstanceId, + stationName, + institutionName, + manufacturer, + clinicalTrialSubjectID, + clinicalTrialTimePointID, + studyInstanceUID, + seriesInstanceUID, + sOPInstanceUID, + numberOfFrames, + transferSyntaxUID, + sOPClassUID, + mediaStorageSOPClassUID, + mediaStorageSOPInstanceUID + + ); + + + await File.AppendAllTextAsync(outputFile, line + Environment.NewLine); + + //维护序列层级四个字段 后再用sql 维护study series 时间拆分 和 MediaStorageSOPInstanceUID + await _instanceRepository.BatchUpdateNoTrackingAsync( + t => t.Id == item.InstanceId, + t => new DicomInstance + { + IsEncapsulated = syntax.IsEncapsulated, + TransferSytaxUID = transferSyntaxUID, + MediaStorageSOPClassUID = mediaStorageSOPClassUID, + SOPClassUID = sOPClassUID, + MediaStorageSOPInstanceUID = mediaStorageSOPInstanceUID + }, false); + } + catch (Exception ex) + { + + var errorMsg = $"{DateTime.Now} ❌ 失败: {ex.Message} | InstanceId={item.InstanceId}, Path={item.Path}"; + + Console.WriteLine(errorMsg); + + await File.AppendAllTextAsync(outputErrorFile, errorMsg + Environment.NewLine); + } + finally + { + processed++; + double percent = processed * 100.0 / total; + + // 每提升 5% 或完成时输出 + if (percent - lastPercent >= 2.0 || processed == total) + { + lastPercent = percent; + Console.WriteLine($"{DateTime.Now} 进度: {processed}/{total} ({percent:F2}%)"); + } + } + + + } + + return ResponseOutput.Ok(); + } + + public class NeedDealInstanceInfo + { + public Guid InstanceId { get; set; } + + public string Path { get; set; } + } + #endregion } } \ No newline at end of file diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs index 21c9dd018..7e185716c 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs @@ -435,7 +435,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc 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 studyId = IdentifierHelper.CreateGuid(incommand.Study.StudyInstanceUid, incommand.TrialId.ToString(), visiTaskId.ToString()); var findStudy = await _taskStudyRepository.FirstOrDefaultAsync(t => t.Id == studyId); @@ -471,7 +471,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc } - study.Id = IdentifierHelper.CreateGuid(incommand.Study.StudyInstanceUid, incommand.TrialId.ToString(), visiTaskId.ToString()); + study.Id = studyId; study.TrialId = incommand.TrialId; study.SubjectId = incommand.SubjectId; study.VisitTaskId = visiTaskId; @@ -568,29 +568,41 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc //新的序列 那么 检查的序列数量+1 findStudy.SeriesCount += 1; } - else - { - //该序列掉了instance - dicomSeries.InstanceCount += seriesItem.InstanceList.Count; - } + //else + //{ + // //该序列掉了instance + // dicomSeries.InstanceCount += seriesItem.InstanceList.Count; + //} + + //找到该序列已经存在的instanceId + var existInstanceIdList = _taskInstanceRepository.Where(t => t.SeriesId == dicomSeries.Id).Select(t => t.Id).ToList(); foreach (var instanceItem in seriesItem.InstanceList) { var insntance = _mapper.Map(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; + var instanceId = IdentifierHelper.CreateGuid(insntance.StudyInstanceUid, insntance.SeriesInstanceUid, insntance.SopInstanceUid, trialId.ToString(), visiTaskId.ToString()); + + + if (!existInstanceIdList.Any(t => t == instanceId)) + { + insntance.Id = instanceId; + insntance.StudyId = findStudy.Id; + insntance.SeriesId = dicomSeries.Id; + + insntance.TrialId = incommand.TrialId; + insntance.SubjectId = incommand.SubjectId; + insntance.VisitTaskId = visiTaskId; + + await _taskInstanceRepository.AddAsync(insntance); + + dicomSeries.InstanceCount++; + findStudy.InstanceCount++; + } - await _taskInstanceRepository.AddAsync(insntance); } - - // 不管是新的序列 还是 该序列 掉了Instance 重传的时候 检查的instance 数量都会增加 - findStudy.InstanceCount += seriesItem.InstanceList.Count; + //findStudy.InstanceCount += seriesItem.InstanceList.Count; } diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialMaintenanceService.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialMaintenanceService.cs index ed7b3aca8..25b4ed629 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialMaintenanceService.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialMaintenanceService.cs @@ -211,6 +211,7 @@ namespace IRaCIS.Core.Application.Service //测试项目 可以加入 测试用户 或者内部正式用户 .WhereIf(trialType == TrialType.NoneOfficial, t => t.IdentityUser.IsTestUser == true || (t.IdentityUser.IsTestUser == false && t.IdentityUser.IsZhiZhun)) + .Where(t => t.IdentityUser.Status == UserStateEnum.Enable && t.IsUserRoleDisabled == false) .Where(t => userTypeEnums.Contains(t.UserTypeEnum)) .WhereIf(inQuery.UserTypeEnum != null, t => t.UserTypeEnum == inQuery.UserTypeEnum) .WhereIf(!string.IsNullOrWhiteSpace(inQuery.UserRealName), t => t.IdentityUser.FullName.Contains(inQuery.UserRealName)) diff --git a/IRaCIS.Core.Infra.EFCore/IRaCIS.Core.Infra.EFCore.csproj b/IRaCIS.Core.Infra.EFCore/IRaCIS.Core.Infra.EFCore.csproj index 12aa90fdc..d0b656afe 100644 --- a/IRaCIS.Core.Infra.EFCore/IRaCIS.Core.Infra.EFCore.csproj +++ b/IRaCIS.Core.Infra.EFCore/IRaCIS.Core.Infra.EFCore.csproj @@ -31,12 +31,12 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/IRaCIS.Core.Test/IRaCIS.Core.Test.csproj b/IRaCIS.Core.Test/IRaCIS.Core.Test.csproj index 01d324f8b..bb69e4176 100644 --- a/IRaCIS.Core.Test/IRaCIS.Core.Test.csproj +++ b/IRaCIS.Core.Test/IRaCIS.Core.Test.csproj @@ -50,10 +50,10 @@ - - + + - + all runtime; build; native; contentfiles; analyzers; buildtransitive