Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is pending
Details
continuous-integration/drone/push Build is pending
Details
commit
53149bf8a0
|
@ -19,7 +19,7 @@
|
||||||
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.2.1" />
|
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.2.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.10" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.10" />
|
||||||
<PackageReference Include="AutoMapper" Version="13.0.1" />
|
<PackageReference Include="AutoMapper" Version="13.0.1" />
|
||||||
<PackageReference Include="Minio" Version="6.0.4" />
|
<PackageReference Include="Minio" Version="6.0.3" />
|
||||||
<PackageReference Include="My.Extensions.Localization.Json" Version="3.3.0">
|
<PackageReference Include="My.Extensions.Localization.Json" Version="3.3.0">
|
||||||
<TreatAsUsed>true</TreatAsUsed>
|
<TreatAsUsed>true</TreatAsUsed>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|
|
@ -41,11 +41,11 @@
|
||||||
<PackageReference Include="FreeSpire.Doc" Version="12.2.0" />
|
<PackageReference Include="FreeSpire.Doc" Version="12.2.0" />
|
||||||
<PackageReference Include="ExcelDataReader" Version="3.7.0" />
|
<PackageReference Include="ExcelDataReader" Version="3.7.0" />
|
||||||
<PackageReference Include="ExcelDataReader.DataSet" Version="3.7.0" />
|
<PackageReference Include="ExcelDataReader.DataSet" Version="3.7.0" />
|
||||||
<PackageReference Include="DistributedLock.Redis" Version="1.0.3" />
|
<PackageReference Include="DistributedLock.Redis" Version="1.1.0" />
|
||||||
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.6" />
|
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.6" />
|
||||||
<PackageReference Include="fo-dicom" Version="5.2.2" />
|
<PackageReference Include="fo-dicom" Version="5.2.2" />
|
||||||
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.2.2" />
|
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.2.2" />
|
||||||
<PackageReference Include="fo-dicom.Codecs" Version="5.16.3" />
|
<PackageReference Include="fo-dicom.Codecs" Version="5.16.4" />
|
||||||
<PackageReference Include="IP2Region.Net" Version="2.0.2" />
|
<PackageReference Include="IP2Region.Net" Version="2.0.2" />
|
||||||
<PackageReference Include="MailKit" Version="4.11.0" />
|
<PackageReference Include="MailKit" Version="4.11.0" />
|
||||||
<PackageReference Include="Masa.Contrib.Service.MinimalAPIs" Version="1.0.0" />
|
<PackageReference Include="Masa.Contrib.Service.MinimalAPIs" Version="1.0.0" />
|
||||||
|
@ -53,7 +53,7 @@
|
||||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.10" />
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.10" />
|
||||||
<PackageReference Include="MimeKit" Version="4.11.0" />
|
<PackageReference Include="MimeKit" Version="4.11.0" />
|
||||||
<PackageReference Include="MiniExcel" Version="1.41.2" />
|
<PackageReference Include="MiniExcel" Version="1.41.2" />
|
||||||
<PackageReference Include="Minio" Version="6.0.5" />
|
<PackageReference Include="Minio" Version="6.0.3" />
|
||||||
<PackageReference Include="MiniWord" Version="0.9.2" />
|
<PackageReference Include="MiniWord" Version="0.9.2" />
|
||||||
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
|
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
|
||||||
<PackageReference Include="My.Extensions.Localization.Json" Version="3.3.0">
|
<PackageReference Include="My.Extensions.Localization.Json" Version="3.3.0">
|
||||||
|
@ -62,9 +62,9 @@
|
||||||
<PackageReference Include="NPOI" Version="2.7.4" />
|
<PackageReference Include="NPOI" Version="2.7.4" />
|
||||||
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" />
|
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" />
|
||||||
<PackageReference Include="RestSharp" Version="112.1.0" />
|
<PackageReference Include="RestSharp" Version="112.1.0" />
|
||||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.10" />
|
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.11" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.2" />
|
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.2" />
|
||||||
<PackageReference Include="ZiggyCreatures.FusionCache" Version="2.3.0" />
|
<PackageReference Include="ZiggyCreatures.FusionCache" Version="2.4.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -957,16 +957,6 @@
|
||||||
<param name="_dictionaryService"></param>
|
<param name="_dictionaryService"></param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:IRaCIS.Core.Application.Service.Common.ExcelExportService.GetAnalysisTaskList_Export(IRaCIS.Core.Application.ViewModel.VisitTaskQuery,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.CommonDocument},IRaCIS.Application.Interfaces.IDictionaryService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial})">
|
|
||||||
<summary>
|
|
||||||
一致性分析结果导出 7 8 分别是自身 和组件一致性
|
|
||||||
</summary>
|
|
||||||
<param name="inQuery"></param>
|
|
||||||
<param name="_commonDocumentRepository"></param>
|
|
||||||
<param name="_dictionaryService"></param>
|
|
||||||
<param name="_trialRepository"></param>
|
|
||||||
<returns></returns>
|
|
||||||
</member>
|
|
||||||
<member name="M:IRaCIS.Core.Application.Service.Common.ExcelExportService.GetTrialReadingCriterionCanExportDocumentList(System.Guid)">
|
<member name="M:IRaCIS.Core.Application.Service.Common.ExcelExportService.GetTrialReadingCriterionCanExportDocumentList(System.Guid)">
|
||||||
<summary>
|
<summary>
|
||||||
获取阅片标准可以导出的列表
|
获取阅片标准可以导出的列表
|
||||||
|
@ -1118,6 +1108,14 @@
|
||||||
<param name="trialId"></param>
|
<param name="trialId"></param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
|
<!-- Badly formed XML comment ignored for member "M:IRaCIS.Core.Application.Service.TrialImageDownloadService.TrialImageAddExtralField(System.Guid,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomInstance},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomSeries})" -->
|
||||||
|
<member name="M:IRaCIS.Core.Application.Service.TrialImageDownloadService.DownloadDeleteTrialImage(System.Guid)">
|
||||||
|
<summary>
|
||||||
|
下载已经删除的影像
|
||||||
|
</summary>
|
||||||
|
<param name="trialId"></param>
|
||||||
|
<returns></returns>
|
||||||
|
</member>
|
||||||
<member name="T:IRaCIS.Core.Application.Service.AttachmentService">
|
<member name="T:IRaCIS.Core.Application.Service.AttachmentService">
|
||||||
<summary>
|
<summary>
|
||||||
医生文档关联关系维护
|
医生文档关联关系维护
|
||||||
|
|
|
@ -2311,263 +2311,8 @@ namespace IRaCIS.Core.Application.Service.Common
|
||||||
|
|
||||||
#region 通用阅片结果导出
|
#region 通用阅片结果导出
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 一致性分析结果导出 7 8 分别是自身 和组件一致性
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="inQuery"></param>
|
|
||||||
/// <param name="_commonDocumentRepository"></param>
|
|
||||||
/// <param name="_dictionaryService"></param>
|
|
||||||
/// <param name="_trialRepository"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[HttpPost]
|
|
||||||
public async Task<IActionResult> GetAnalysisTaskList_Export(VisitTaskQuery inQuery,
|
|
||||||
[FromServices] IRepository<CommonDocument> _commonDocumentRepository,
|
|
||||||
[FromServices] IDictionaryService _dictionaryService,
|
|
||||||
[FromServices] IRepository<Trial> _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<AnalysisDynamicCommonExport>(_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<ExcelExportInfo>(_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<AnalysisDynamicCommonExport>();
|
|
||||||
|
|
||||||
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<CommonQuesionInfo>();
|
|
||||||
|
|
||||||
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<int>() { },
|
|
||||||
ColumnIdNameList = columNameList.Select(t => new DynamicColumnConfig.ColumItem() { Id = Guid.Empty, Name = t }).ToList(),
|
|
||||||
TranslateDicNameList = translateDicNameList ?? new List<string>()
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
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"
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取阅片标准可以导出的列表
|
/// 获取阅片标准可以导出的列表
|
||||||
|
@ -2898,7 +2643,8 @@ namespace IRaCIS.Core.Application.Service.Common
|
||||||
{
|
{
|
||||||
#region 外层问题处理
|
#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()
|
fistLeveLNameList = trialConfigQuestionList.Select(t => new DynamicColumnConfig.ColumItem()
|
||||||
|
@ -2941,7 +2687,8 @@ namespace IRaCIS.Core.Application.Service.Common
|
||||||
var extralNameList = new List<DynamicColumnConfig.ColumItem>();
|
var extralNameList = new List<DynamicColumnConfig.ColumItem>();
|
||||||
|
|
||||||
if (criterion.CriterionType == CriterionType.RECIST1Point1 || criterion.CriterionType == CriterionType.RECIST1Pointt1_MB
|
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)
|
//if(inQuery.ReadingExportType == ExportResult.DetailedTableOfLesions)
|
||||||
|
@ -2982,7 +2729,8 @@ namespace IRaCIS.Core.Application.Service.Common
|
||||||
var addLessionInfoList = new List<CommonQuesionInfo>();
|
var addLessionInfoList = new List<CommonQuesionInfo>();
|
||||||
|
|
||||||
if (criterion.CriterionType == CriterionType.RECIST1Point1 || criterion.CriterionType == CriterionType.RECIST1Pointt1_MB
|
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 });
|
addLessionInfoList.Add(new CommonQuesionInfo() { QuestionName = _userInfo.IsEn_Us ? "Lesion ID" : "病灶编号", QuestionValue = lession.LessionCode });
|
||||||
|
@ -3022,7 +2770,8 @@ namespace IRaCIS.Core.Application.Service.Common
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 不管是list 还是taskList 最终处理的数据都是list 处理好数据后合并
|
#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 整体肿瘤评估 有的两列要合并一列
|
//针对1.1 整体肿瘤评估 有的两列要合并一列
|
||||||
foreach (var item in list)
|
foreach (var item in list)
|
||||||
|
|
|
@ -1,22 +1,30 @@
|
||||||
using DocumentFormat.OpenXml.EMMA;
|
using DocumentFormat.OpenXml.EMMA;
|
||||||
|
using DocumentFormat.OpenXml.Office2010.Excel;
|
||||||
|
using DocumentFormat.OpenXml.Office2013.Drawing.ChartStyle;
|
||||||
using FellowOakDicom;
|
using FellowOakDicom;
|
||||||
using FellowOakDicom.Imaging;
|
using FellowOakDicom.Imaging;
|
||||||
using FellowOakDicom.Imaging.Render;
|
using FellowOakDicom.Imaging.Render;
|
||||||
using FellowOakDicom.IO.Buffer;
|
using FellowOakDicom.IO.Buffer;
|
||||||
using IRaCIS.Core.Application.Helper;
|
using IRaCIS.Core.Application.Helper;
|
||||||
|
using IRaCIS.Core.Application.ViewModel;
|
||||||
|
using IRaCIS.Core.Domain.Models;
|
||||||
using MassTransit;
|
using MassTransit;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using MiniExcelLibs;
|
||||||
using SharpCompress.Common;
|
using SharpCompress.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using static IRaCIS.Core.Domain.Share.StaticData;
|
using static IRaCIS.Core.Domain.Share.StaticData;
|
||||||
|
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Service
|
namespace IRaCIS.Core.Application.Service
|
||||||
{
|
{
|
||||||
|
@ -243,7 +251,8 @@ namespace IRaCIS.Core.Application.Service
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
public async Task<IResponseOutput> DownloadAndUploadTrialData(Guid trialId, [FromServices] IRepository<DicomInstance> _instanceRepository,
|
public async Task<IResponseOutput> DownloadAndUploadTrialData(Guid trialId,
|
||||||
|
[FromServices] IRepository<DicomInstance> _instanceRepository,
|
||||||
[FromServices] IRepository<DicomStudy> _studyRepository,
|
[FromServices] IRepository<DicomStudy> _studyRepository,
|
||||||
[FromServices] IRepository<DicomSeries> _seriesRepository)
|
[FromServices] IRepository<DicomSeries> _seriesRepository)
|
||||||
{
|
{
|
||||||
|
@ -334,6 +343,715 @@ namespace IRaCIS.Core.Application.Service
|
||||||
return ResponseOutput.Ok();
|
return ResponseOutput.Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 维护dir 需求新增的字段
|
||||||
|
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="trialId"></param>
|
||||||
|
/// <param name="_instanceRepository"></param>
|
||||||
|
/// <param name="_studyRepository"></param>
|
||||||
|
/// <param name="_seriesRepository"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<IResponseOutput> TrialImageAddExtralField(Guid trialId,
|
||||||
|
[FromServices] IRepository<DicomInstance> _instanceRepository,
|
||||||
|
[FromServices] IRepository<DicomStudy> _studyRepository,
|
||||||
|
[FromServices] IRepository<DicomSeries> _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();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 下载已经删除的影像
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="trialId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost]
|
||||||
|
[AllowAnonymous]
|
||||||
|
public async Task<IResponseOutput> 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<Task> 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<IResponseOutput> ReadDicomDataWriteDB([FromServices] IRepository<DicomInstance> _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<IResponseOutput> ReadExcelData([FromServices] IRepository<DicomInstance> _instanceRepository)
|
||||||
|
{
|
||||||
|
var rows = await MiniExcel.QueryAsync<DicomSOPInfo>(@"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<IResponseOutput> ReadExcelImageDataInstanceIsReading([FromServices] IRepository<DicomInstance> _instanceRepository,
|
||||||
|
[FromServices] IRepository<DicomSeries> _seriesRepository,
|
||||||
|
[FromServices] IRepository<DicomStudy> _studyRepository)
|
||||||
|
{
|
||||||
|
|
||||||
|
var trialId = Guid.Parse("01000000-ac13-0242-6397-08dcd2d2a091");
|
||||||
|
|
||||||
|
var rows = await MiniExcel.QueryAsync<DicomSOPInstanceInfo>(@"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<IResponseOutput> WriteNeedDealData([FromServices] IRepository<DicomInstance> _instanceRepository)
|
||||||
|
{
|
||||||
|
|
||||||
|
#region 获取差集数据
|
||||||
|
//var rows = await MiniExcel.QueryAsync<DicomSOPInfo>(@"C:\Users\hang\Desktop\维护数据读取.xlsx");
|
||||||
|
|
||||||
|
//rows = rows.Where(t => !string.IsNullOrEmpty(t.InstanceId.ToString())).ToList();
|
||||||
|
|
||||||
|
//var allRows = await MiniExcel.QueryAsync<NeedDealInstanceInfo>(@"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<NeedDealInstanceInfo>(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
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -435,7 +435,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
||||||
studyMonitor.RecordPath = incommand.RecordPath;
|
studyMonitor.RecordPath = incommand.RecordPath;
|
||||||
studyMonitor.FileSize = incommand.Study.SeriesList.SelectMany(t => t.InstanceList).Sum(t => t.FileSize);
|
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);
|
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.TrialId = incommand.TrialId;
|
||||||
study.SubjectId = incommand.SubjectId;
|
study.SubjectId = incommand.SubjectId;
|
||||||
study.VisitTaskId = visiTaskId;
|
study.VisitTaskId = visiTaskId;
|
||||||
|
@ -568,16 +568,25 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
||||||
//新的序列 那么 检查的序列数量+1
|
//新的序列 那么 检查的序列数量+1
|
||||||
findStudy.SeriesCount += 1;
|
findStudy.SeriesCount += 1;
|
||||||
}
|
}
|
||||||
else
|
//else
|
||||||
{
|
//{
|
||||||
//该序列掉了instance
|
// //该序列掉了instance
|
||||||
dicomSeries.InstanceCount += seriesItem.InstanceList.Count;
|
// 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)
|
foreach (var instanceItem in seriesItem.InstanceList)
|
||||||
{
|
{
|
||||||
var insntance = _mapper.Map<TaskInstance>(instanceItem);
|
var insntance = _mapper.Map<TaskInstance>(instanceItem);
|
||||||
insntance.Id = IdentifierHelper.CreateGuid(insntance.StudyInstanceUid, insntance.SeriesInstanceUid, insntance.SopInstanceUid, trialId.ToString(), visiTaskId.ToString());
|
|
||||||
|
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.StudyId = findStudy.Id;
|
||||||
insntance.SeriesId = dicomSeries.Id;
|
insntance.SeriesId = dicomSeries.Id;
|
||||||
|
|
||||||
|
@ -586,11 +595,14 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
||||||
insntance.VisitTaskId = visiTaskId;
|
insntance.VisitTaskId = visiTaskId;
|
||||||
|
|
||||||
await _taskInstanceRepository.AddAsync(insntance);
|
await _taskInstanceRepository.AddAsync(insntance);
|
||||||
|
|
||||||
|
dicomSeries.InstanceCount++;
|
||||||
|
findStudy.InstanceCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
// 不管是新的序列 还是 该序列 掉了Instance 重传的时候 检查的instance 数量都会增加
|
// 不管是新的序列 还是 该序列 掉了Instance 重传的时候 检查的instance 数量都会增加
|
||||||
findStudy.InstanceCount += seriesItem.InstanceList.Count;
|
//findStudy.InstanceCount += seriesItem.InstanceList.Count;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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))
|
.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))
|
.Where(t => userTypeEnums.Contains(t.UserTypeEnum))
|
||||||
.WhereIf(inQuery.UserTypeEnum != null, t => t.UserTypeEnum == inQuery.UserTypeEnum)
|
.WhereIf(inQuery.UserTypeEnum != null, t => t.UserTypeEnum == inQuery.UserTypeEnum)
|
||||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.UserRealName), t => t.IdentityUser.FullName.Contains(inQuery.UserRealName))
|
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.UserRealName), t => t.IdentityUser.FullName.Contains(inQuery.UserRealName))
|
||||||
|
|
|
@ -31,12 +31,12 @@
|
||||||
<PackageReference Include="Hangfire.Core" Version="1.8.18" />
|
<PackageReference Include="Hangfire.Core" Version="1.8.18" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="8.0.10" />
|
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="8.0.10" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.1" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.15" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.19" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.15">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.19">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.10">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.19">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|
|
@ -50,10 +50,10 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Fluid.Core" Version="2.21.0" />
|
<PackageReference Include="Fluid.Core" Version="2.21.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.15" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.19" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="8.0.15" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="8.0.19" />
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.11" />
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.11" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.15">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.19">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|
Loading…
Reference in New Issue