diff --git a/IRaCIS.Core.API/Controllers/ExtraController.cs b/IRaCIS.Core.API/Controllers/ExtraController.cs index ca49c5e0b..5d43d4a61 100644 --- a/IRaCIS.Core.API/Controllers/ExtraController.cs +++ b/IRaCIS.Core.API/Controllers/ExtraController.cs @@ -208,7 +208,7 @@ namespace IRaCIS.Api.Controllers [HttpGet("user/GenerateSTS")] - public IResponseOutput GenerateSTS(IOptionsMonitor options ) + public IResponseOutput GenerateSTS([FromServices]IOptionsMonitor options ) { var ossOptions = options.CurrentValue; diff --git a/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs b/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs index 7b48775da..b0a275fb5 100644 --- a/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs +++ b/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs @@ -268,7 +268,7 @@ namespace IRaCIS.Core.API.Controllers [DisableFormValueModelBinding] [DisableRequestSizeLimit] [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] - public async Task ArchiveStudyNew(/*[FromForm] ArchiveStudyCommand archiveStudyCommand,*/ Guid trialId, Guid subjectVisitId, string studyInstanceUid, Guid? abandonStudyId,Guid studyMonitorId, + public async Task ArchiveStudyNew(/*[FromForm] ArchiveStudyCommand archiveStudyCommand,*/ Guid trialId, Guid subjectVisitId, string studyInstanceUid, Guid? abandonStudyId, Guid studyMonitorId, [FromServices] ILogger _logger, [FromServices] IEasyCachingProvider _provider, [FromServices] IStudyService _studyService, @@ -302,9 +302,9 @@ namespace IRaCIS.Core.API.Controllers { _provider.Set($"StudyUid_{trialId}_{archiveStudyCommand.StudyInstanceUid}", _userInfo.Id, TimeSpan.FromMinutes(30)); } - - - + + + //if (_provider.Exists($"StudyUid_{trialId}_{archiveStudyCommand.StudyInstanceUid}")) //{ // //---当前已有人正在上传和归档该检查! @@ -407,7 +407,7 @@ namespace IRaCIS.Core.API.Controllers studyMonitor.IsSuccess = true; } - + } catch (Exception e) { @@ -424,7 +424,7 @@ namespace IRaCIS.Core.API.Controllers studyMonitor.StudyCode = archiveResult.ArchivedDicomStudies.FirstOrDefault()?.StudyCode; studyMonitor.ArchiveFinishedTime = DateTime.Now; - await _studyMonitorRepository.SaveChangesAsync(); + await _studyMonitorRepository.SaveChangesAsync(); } @@ -528,7 +528,7 @@ namespace IRaCIS.Core.API.Controllers if (!fileName.EndsWith(".xlsx") && !fileName.EndsWith(".csv") && !fileName.EndsWith(".xls")) { - //---支持.xlsx、.xls、.csv格式的文件上传。 + //---支持.xlsx、.xls、.csv格式的文件上传。 throw new BusinessValidationFailedException(StaticData.International("UploadDownLoad_SupportedFormats")); } @@ -686,11 +686,11 @@ namespace IRaCIS.Core.API.Controllers var dt = DateTime.Now; - etcCheckList = etcCheckList.Where(t => !(t.Modality == string.Empty || t.SiteCode == string.Empty || t.SubjectCode == string.Empty || t.VisitName == string.Empty || t.StudyDate == string.Empty ||! DateTime.TryParse(t.StudyDate, out dt))).ToList(); + etcCheckList = etcCheckList.Where(t => !(t.Modality == string.Empty || t.SiteCode == string.Empty || t.SubjectCode == string.Empty || t.VisitName == string.Empty || t.StudyDate == string.Empty || !DateTime.TryParse(t.StudyDate, out dt))).ToList(); if (etcCheckList.Count == 0) { - //---请保证上传数据符合模板文件中的样式,且存在有效数据。 + //---请保证上传数据符合模板文件中的样式,且存在有效数据。 return ResponseOutput.NotOk(StaticData.International("UploadDownLoad_InvalidData")); } @@ -709,6 +709,38 @@ namespace IRaCIS.Core.API.Controllers #region 医生文件上传下载 + + #region DTO + public class DoctorDownloadInfo + { + public Guid Id { get; set; } + public string Name { get; set; } + public string ReviewerCode { get; set; } + + public List FileList { get; set; } + } + public class DownloadFileInfo + { + public string FileName { get; set; } + + public string Path { get; set; } + } + + public class GetDoctorPathCommand + { + public int Language { get; set; } + + public List DoctorIdList { get; set; } + } + + public class GetDoctoreAttachPathCommand + { + public Guid DoctorId { get; set; } + public List AttachmentIdList { get; set; } + } + #endregion + + /// 医生文件上传下载 [ApiExplorerSettings(GroupName = "Common")] [ApiController] @@ -723,55 +755,98 @@ namespace IRaCIS.Core.API.Controllers private readonly IFileService _fileService; - public FileController(IMapper mapper, IUserInfo userInfo, IWebHostEnvironment hostEnvironment, IFileService fileService) { _fileService = fileService; _hostEnvironment = hostEnvironment; - _mapper = mapper; _userInfo = userInfo; } /// - /// 上传文件[FileUpload] + /// New 医生首页 多选 获取多个医生信息+文件路径列表 医生压缩包名称 doctorCode + "_" + doctorName _(时间戳或者随机的Guid) /// - /// 附件类型 - /// 医生Id - /// 返回文件信息 - [HttpPost, Route("file/UploadFile/{attachmentType}/{doctorId}")] - [DisableFormValueModelBinding] - [DisableRequestSizeLimit] - public async Task UploadOrdinaryFile(string attachmentType, Guid doctorId) + /// + [HttpPost, Route("file/GetOfficialResume")] + public async Task>> GetOfficialResume(GetDoctorPathCommand command, + [FromServices] IRepository _attachmentrepository) { - return await SingleFileUploadAsync((fileName) => FileStoreHelper.GetDoctorOrdinaryFilePath(_hostEnvironment, fileName, doctorId, attachmentType)); + var list = await _attachmentrepository.Where(t => command.DoctorIdList.Contains(t.DoctorId) && command.Language==t.Language).GroupBy(t => new { Name = t.Doctor.FirstName + "_" + t.Doctor.LastName, ReviewerCode = t.Doctor.ReviewerCode, t.DoctorId }) + .Select(g => new DoctorDownloadInfo() + { + Id = g.Key.DoctorId, + Name = g.Key.Name, + ReviewerCode = g.Key.ReviewerCode, + FileList = g.Select(t => new DownloadFileInfo() { FileName = t.FileName, Path = t.Path }).ToList() + }).ToListAsync(); + + return ResponseOutput.Ok(list); } - /// - /// 上传文件( 不是医生个人的文件)[FileUpload] - /// 例如:阅片章程等 + /// New 项目入组 获取医生简历 /// - /// 文件类型 + /// + /// + /// /// - - [HttpPost, Route("file/UploadNonDoctorFile/{type}")] - [DisableFormValueModelBinding] - [DisableRequestSizeLimit] - public async Task UploadNonDoctorFile(string type) + [HttpPost,Route("file/GetTrialDoctorOfficialResume")] + public async Task>> GetTrialDoctorOfficialResume(GetDoctorPathCommand command, + [FromServices] IDoctorService _doctorService, + [FromServices] IRepository _attachmentrepository) { - return await SingleFileUploadAsync((fileName) => FileStoreHelper.GetNonDoctorFilePath(_hostEnvironment, fileName, type)); + + var list = await _attachmentrepository.Where(t => command.DoctorIdList.Contains(t.DoctorId) && command.Language == t.Language && t.IsOfficial && t.Type.Equals("Resume")).GroupBy(t => new { Name = t.Doctor.FirstName + "_" + t.Doctor.LastName, ReviewerCode = t.Doctor.ReviewerCode, t.DoctorId }) + .Select(g => new DoctorDownloadInfo() + { + Id = g.Key.DoctorId, + Name = g.Key.Name, + ReviewerCode = g.Key.ReviewerCode, + FileList = g.Select(t => new DownloadFileInfo() { FileName = t.FileName, Path = t.Path }).ToList() + }).ToListAsync(); + + return ResponseOutput.Ok(list); + } + /// + /// new 医生详情 下载指定简历 + /// + /// + /// + /// + /// + [HttpPost, Route("file/GetDoctorAttachment")] + public async Task> GetDoctorAttachment(GetDoctoreAttachPathCommand command, + [FromServices] IDoctorService _doctorService, + [FromServices] IRepository _attachmentrepository) + { + + var find = await _attachmentrepository.Where(t => command.DoctorId==t.DoctorId && command.AttachmentIdList.Contains(t.Id)).GroupBy(t => new { Name = t.Doctor.FirstName + "_" + t.Doctor.LastName, ReviewerCode = t.Doctor.ReviewerCode, t.DoctorId }) + .Select(g => new DoctorDownloadInfo() + { + Id = g.Key.DoctorId, + Name = g.Key.Name, + ReviewerCode = g.Key.ReviewerCode, + FileList = g.Select(t => new DownloadFileInfo() { FileName = t.FileName, Path = t.Path }).ToList() + }).FirstOrDefaultAsync(); + + return ResponseOutput.Ok(find); + + } + + + + #region 废弃 /// /// 下载多个医生的所有附件 /// /// /// - + [Obsolete] [HttpPost, Route("file/downloadDoctorAttachments")] public async Task> DownloadAttachment(Guid[] doctorIds) { @@ -786,24 +861,6 @@ namespace IRaCIS.Core.API.Controllers }); } - /// - /// 下载医生官方简历 - /// - /// - /// - /// - [HttpPost, Route("file/downloadOfficialCV/{language}")] - public async Task> DownloadOfficialResume(int language, Guid[] doctorIds) - { - - var path = await _fileService.CreateDoctorsAllAttachmentZip(doctorIds); - return ResponseOutput.Ok(new UploadFileInfoDTO - { - FilePath = await _fileService.CreateOfficialResumeZip(language, doctorIds), - FullFilePath = path + "?access_token=" + HttpContext.Request.Headers["Authorization"].ToString().Substring(7) - }); - } - /// /// 下载指定医生的指定附件 /// @@ -811,6 +868,7 @@ namespace IRaCIS.Core.API.Controllers /// 要下载的附件Id /// [HttpPost, Route("file/downloadByAttachmentId/{doctorId}")] + [Obsolete] public async Task> DownloadAttachmentById(Guid doctorId, Guid[] attachmentIds) { var path = await _fileService.CreateZipPackageByAttachment(doctorId, attachmentIds); @@ -822,15 +880,47 @@ namespace IRaCIS.Core.API.Controllers } + /// + /// 下载医生官方简历 首页 区分 中文和英文 + /// + /// + /// + /// + [HttpPost, Route("file/downloadOfficialCV/{language}")] + [Obsolete] + public async Task> DownloadOfficialResume(int language, Guid[] doctorIds) + { + + var path = await _fileService.CreateDoctorsAllAttachmentZip(doctorIds); + return ResponseOutput.Ok(new UploadFileInfoDTO + { + FilePath = await _fileService.CreateOfficialResumeZip(language, doctorIds), + FullFilePath = path + "?access_token=" + HttpContext.Request.Headers["Authorization"].ToString().Substring(7) + }); + } + + + + + /// + /// 入组 项目下载简历 + /// + /// + /// + /// + /// [HttpPost, Route("enroll/downloadResume/{trialId:guid}/{language}")] [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] [AllowAnonymous] + [Obsolete] public async Task> DownloadResume(int language, Guid trialId, Guid[] doctorIdArray) { var zipPath = await _fileService.CreateOfficialResumeZip(language, doctorIdArray); return ResponseOutput.Ok(zipPath); } + #endregion + } #endregion @@ -856,7 +946,18 @@ namespace IRaCIS.Core.API.Controllers _userInfo = userInfo; } + /// 通用文件下载 + [AllowAnonymous] + [HttpGet("CommonDocument/DownloadCommonDoc")] + public async Task DownloadCommonFile(string code, [FromServices] IRepository _commonDocumentRepository) + { + var (filePath, fileName) = await FileStoreHelper.GetCommonDocPhysicalFilePathAsync(_hostEnvironment, _commonDocumentRepository, code); + new FileExtensionContentTypeProvider().Mappings.TryGetValue(Path.GetExtension(filePath), out var contentType); + + return File(System.IO.File.OpenRead(filePath), contentType ?? "application/octet-stream", fileName); + + } /// /// 上传通用文档 比如一致性核查的 比如导出的excel 模板 diff --git a/IRaCIS.Core.API/IRaCIS.Core.API.xml b/IRaCIS.Core.API/IRaCIS.Core.API.xml index 96f6f9d06..5198124a0 100644 --- a/IRaCIS.Core.API/IRaCIS.Core.API.xml +++ b/IRaCIS.Core.API/IRaCIS.Core.API.xml @@ -285,20 +285,28 @@ 医生文件上传下载 - + - 上传文件[FileUpload] + New 医生首页 多选 获取多个医生信息+文件路径列表 医生压缩包名称 doctorCode + "_" + doctorName _(时间戳或者随机的Guid) - 附件类型 - 医生Id - 返回文件信息 + - + - 上传文件( 不是医生个人的文件)[FileUpload] - 例如:阅片章程等 + New 项目入组 获取医生简历 - 文件类型 + + + + + + + + new 医生详情 下载指定简历 + + + + @@ -308,14 +316,6 @@ - - - 下载医生官方简历 - - - - - 下载指定医生的指定附件 @@ -324,6 +324,26 @@ 要下载的附件Id + + + 下载医生官方简历 首页 区分 中文和英文 + + + + + + + + 入组 项目下载简历 + + + + + + + + 通用文件下载 + 上传通用文档 比如一致性核查的 比如导出的excel 模板 diff --git a/IRaCIS.Core.Application/Helper/OSSService.cs b/IRaCIS.Core.Application/Helper/OSSService.cs index 1fba59176..ff0a024fa 100644 --- a/IRaCIS.Core.Application/Helper/OSSService.cs +++ b/IRaCIS.Core.Application/Helper/OSSService.cs @@ -51,17 +51,19 @@ namespace IRaCIS.Core.Application.Helper { var ossOptions = options.CurrentValue; - _OSSConfig = new AliyunOssOptions() - { - RegionId = ossOptions.RegionId, - AccessKeyId = ossOptions.AccessKeyId, - AccessKeySecret = ossOptions.AccessKeySecret, - EndPoint = ossOptions.EndPoint, - BucketName = ossOptions.BucketName, - RoleArn = ossOptions.RoleArn, - Region = ossOptions.Region, - ViewEndpoint = ossOptions.ViewEndpoint - }; + _OSSConfig= ossOptions; + + //_OSSConfig = new AliyunOssOptions() + //{ + // RegionId = ossOptions.RegionId, + // AccessKeyId = ossOptions.AccessKeyId, + // AccessKeySecret = ossOptions.AccessKeySecret, + // EndPoint = ossOptions.EndPoint, + // BucketName = ossOptions.BucketName, + // RoleArn = ossOptions.RoleArn, + // Region = ossOptions.Region, + // ViewEndpoint = ossOptions.ViewEndpoint + //}; _ossClient = new OssClient(_OSSConfig.EndPoint, _OSSConfig.AccessKeyId, _OSSConfig.AccessKeySecret); diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml index 9724e186a..4650ad18a 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -1918,6 +1918,14 @@ + + + 获取脾脏状态 + + + + + 获取脾脏评估 @@ -1946,6 +1954,20 @@ + + + 骨髓中是否存在局灶性 FDG亲和病灶的证据 + + + + + + + 获取肝脏评估 + + + + SuvMax所在病灶 @@ -4791,6 +4813,11 @@ Path + + + 分组分类 + + 问题分类 @@ -6576,6 +6603,11 @@ 问题分类 + + + 分组分类 + + 单位 @@ -6654,6 +6686,11 @@ 问题分类 + + + 分组分类 + + 数据来源 @@ -7002,6 +7039,11 @@ 问题分类 + + + 分组分类 + + 单位 @@ -7062,6 +7104,11 @@ 问题分类 + + + 分组分类 + + 备注 @@ -7417,6 +7464,11 @@ 问题分类 + + + 分组分类 + + 限制编辑 @@ -7747,6 +7799,11 @@ 问题分类 + + + 分组分类 + + 数据来源 @@ -8571,6 +8628,59 @@ + + + 项目列表 + + + + + + + 任务列表 第一层级 + + + + + + + 检查列表 第二层级 + + + + + + 修改任务上的 影像上传状态 + + + + + + + 通过任务Id 获取检查模态下拉框 + + + + + + 通过选择的序列Id 数组,获取下面的Instance 路径 + + + + + + + + 归档接口 -new 一份 序列层级增加了一个参数VisitTaskId 用于绑定从TomTec拉取来的序列(两个人公用的影像,不应该绑定) + + + + + + + + + 项目外部人员 录入流程相关 @@ -13108,7 +13218,7 @@ - + 获取阅片外层问题 diff --git a/IRaCIS.Core.Application/Service/Common/FileService.cs b/IRaCIS.Core.Application/Service/Common/FileService.cs index ecbce02cd..01f6323b3 100644 --- a/IRaCIS.Core.Application/Service/Common/FileService.cs +++ b/IRaCIS.Core.Application/Service/Common/FileService.cs @@ -98,7 +98,8 @@ namespace IRaCIS.Application.Services /// public async Task CreateDoctorsAllAttachmentZip(Guid[] doctorIds) { - //准备下载文件的临时路径 + #region 老版本 存储在服务器 + //准备下载文件的临时路径 var guidStr = Guid.NewGuid().ToString(); //string uploadFolderPath = HostingEnvironment.MapPath("/UploadFile/"); string uploadFolderPath = Path.Combine(FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment), "UploadFile"); @@ -134,6 +135,8 @@ namespace IRaCIS.Application.Services string targetPath = Path.Combine(uploadFolderPath, target + ".zip"); ZipHelper.CreateZip(tempSavePath, targetPath); return Path.Combine("/IRaCISData/UploadFile/", target + ".zip"); + #endregion + } diff --git a/IRaCIS.Core.Application/Service/Document/_MapConfig.cs b/IRaCIS.Core.Application/Service/Document/_MapConfig.cs index 1116a7bf1..f01322122 100644 --- a/IRaCIS.Core.Application/Service/Document/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/Document/_MapConfig.cs @@ -52,7 +52,9 @@ namespace IRaCIS.Core.Application.Service CreateMap(); + CreateMap(); + CreateMap() diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/DicomSeriesModel.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/DicomSeriesModel.cs index e9a16ca10..a9062fd24 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/DicomSeriesModel.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/DicomSeriesModel.cs @@ -41,7 +41,7 @@ public string WindowCenter { get; set; } = string.Empty; public string WindowWidth { get; set; } = string.Empty; - public string IamgeResizePath { get; set; } + public string ImageResizePath { get; set; } } public class DicomSeriesWithLabelDTO : DicomSeriesDTO diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs index 42c9c3a71..ab1beb6eb 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs @@ -173,6 +173,8 @@ namespace IRaCIS.Core.Application.Contracts public string[]? VisitPlanArray { get; set; } + public Guid? VisitTaskId { get; set; } + } @@ -280,10 +282,10 @@ namespace IRaCIS.Core.Application.Contracts public string AcquisitionNumber { get; set; } = string.Empty; public string TriggerTime { get; set; } = string.Empty; - public string IamgeResizePath { get; set; }=string.Empty; + public string ImageResizePath { get; set; }=string.Empty; public List InstanceList { get; set; } - + public Guid? VisitTaskId { get; set; } } diff --git a/IRaCIS.Core.Application/Service/Reading/Dto/ReadingCalculateViewModel.cs b/IRaCIS.Core.Application/Service/Reading/Dto/ReadingCalculateViewModel.cs index a8c54a077..dab5f2a05 100644 --- a/IRaCIS.Core.Application/Service/Reading/Dto/ReadingCalculateViewModel.cs +++ b/IRaCIS.Core.Application/Service/Reading/Dto/ReadingCalculateViewModel.cs @@ -50,6 +50,8 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto public bool IsChangeOtherTask { get; set; } + + public ComputationTrigger ComputationTrigger { get; set; } } public class TargetLesionCalculateDto @@ -218,7 +220,9 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto public Guid SubjectVisitId { get; set; } - public Arm ArmEnum { get; set; } + public Arm ArmEnum { get; set; } + + public ComputationTrigger ComputationTrigger { get; set; } = ComputationTrigger.Lesion; /// /// 是否修改其他任务 @@ -348,6 +352,9 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto { public QuestionType QuestionType { get; set; } + + public ComputationTrigger? ComputationTrigger { get; set; } + public Func> GetDecimalFun { get; set; } public Func> GetIntFun { get; set; } diff --git a/IRaCIS.Core.Application/Service/Reading/Dto/ReadingImageTaskViewModel.cs b/IRaCIS.Core.Application/Service/Reading/Dto/ReadingImageTaskViewModel.cs index 257dbc73f..ddaf82d92 100644 --- a/IRaCIS.Core.Application/Service/Reading/Dto/ReadingImageTaskViewModel.cs +++ b/IRaCIS.Core.Application/Service/Reading/Dto/ReadingImageTaskViewModel.cs @@ -507,6 +507,11 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto public Guid TrialId { get; set; } + /// + /// 分组分类 + /// + public List? GroupClassifyList { get; set; } + /// /// 问题分类 /// @@ -1275,6 +1280,8 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto public string SubjectCode { get; set; } + public bool IsExistsClinicalData { get; set; } + public ReadingTaskState ReadingTaskState { get; set; } public decimal VisitTaskNum { get; set; } @@ -1923,7 +1930,7 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto public int? NumberOfFrames { get; set; } - public string? FromMark { get; set; } + public string? FromMark { get; set; } public string? ReportMark { get; set; } diff --git a/IRaCIS.Core.Application/Service/Reading/Dto/ReadingQuestionViewModel.cs b/IRaCIS.Core.Application/Service/Reading/Dto/ReadingQuestionViewModel.cs index 37b96be24..4983fb326 100644 --- a/IRaCIS.Core.Application/Service/Reading/Dto/ReadingQuestionViewModel.cs +++ b/IRaCIS.Core.Application/Service/Reading/Dto/ReadingQuestionViewModel.cs @@ -341,6 +341,11 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto /// public QuestionClassify? QuestionClassify { get; set; } + /// + /// 分组分类 + /// + public GroupClassify? GroupClassify { get; set; } + /// /// 单位 /// @@ -450,6 +455,11 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto /// public QuestionClassify? QuestionClassify { get; set; } + /// + /// 分组分类 + /// + public GroupClassify? GroupClassify { get; set; } + /// /// 数据来源 /// @@ -999,6 +1009,11 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto /// public QuestionClassify? QuestionClassify { get; set; } + /// + /// 分组分类 + /// + public GroupClassify? GroupClassify { get; set; } + /// /// 单位 /// @@ -1068,6 +1083,11 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto /// public QuestionClassify? QuestionClassify { get; set; } + /// + /// 分组分类 + /// + public GroupClassify? GroupClassify { get; set; } + public List ParentTriggerValueList { get; set; } = new List(); public List RelevanceValueList { get; set; } = new List(); @@ -1593,6 +1613,11 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto /// public QuestionClassify? QuestionClassify { get; set; } + /// + /// 分组分类 + /// + public GroupClassify? GroupClassify { get; set; } + /// /// 限制编辑 /// @@ -1957,6 +1982,11 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto /// public QuestionClassify? QuestionClassify { get; set; } + /// + /// 分组分类 + /// + public GroupClassify? GroupClassify { get; set; } + /// /// 数据来源 /// diff --git a/IRaCIS.Core.Application/Service/Reading/Interface/IReadingImageTaskService.cs b/IRaCIS.Core.Application/Service/Reading/Interface/IReadingImageTaskService.cs index 99d4cc7de..6cba1b928 100644 --- a/IRaCIS.Core.Application/Service/Reading/Interface/IReadingImageTaskService.cs +++ b/IRaCIS.Core.Application/Service/Reading/Interface/IReadingImageTaskService.cs @@ -23,7 +23,7 @@ namespace IRaCIS.Core.Application.Contracts Task GetGlobalReadingInfo(GetGlobalReadingInfoInDto inDto); - Task> GetReadingQuestion(Guid trialReadingCriterionId, Guid? visitTaskId,QuestionClassify? questionClassify); + Task> GetReadingQuestion(Guid trialReadingCriterionId, Guid? visitTaskId,QuestionClassify? questionClassify, List? groupClassifyList); Task GetReadingTableQuestion(GetReadingTableQuestionOrAnswerInDto inDto); diff --git a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs index df466c762..da06e0a23 100644 --- a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs @@ -549,6 +549,22 @@ namespace IRaCIS.Application.Services result = result.Where(x => x.VisitTaskId == inDto.VisitTaskId).ToList(); } + foreach (var item in result) + { + var clinicalDataList = await _readingClinicalDataService.GetClinicalDataList(new GetReadingOrTaskClinicalDataListInDto() + { + + SubjectId = taskInfo.SubjectId, + TrialId = taskInfo.TrialId, + VisitTaskId = item.VisitTaskId, + }); + + item.IsExistsClinicalData = clinicalDataList.Count() > 0; + } + + + + return (result, new { ReadingTaskState = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Select(x => x.ReadingTaskState).FirstOrDefaultAsync() @@ -704,7 +720,7 @@ namespace IRaCIS.Application.Services { //await AddDefaultValueToTask(inDto.VisitTaskId); var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync(); - var result = await GetReadingQuestion(taskInfo.TrialReadingCriterionId, taskInfo.Id, inDto.QuestionClassify); + var result = await GetReadingQuestion(taskInfo.TrialReadingCriterionId, taskInfo.Id, inDto.QuestionClassify,inDto.GroupClassifyList); @@ -722,7 +738,7 @@ namespace IRaCIS.Application.Services /// /// [NonDynamicMethod] - public async Task> GetReadingQuestion(Guid trialReadingCriterionId, Guid? visitTaskId, QuestionClassify? questionClassify) + public async Task> GetReadingQuestion(Guid trialReadingCriterionId, Guid? visitTaskId, QuestionClassify? questionClassify, List? groupClassifyList) { @@ -776,7 +792,9 @@ namespace IRaCIS.Application.Services //排除表格问题 同时排除组问题 var groupids = questions.Where(x => x.Type != ReadingQestionType.Group).Select(x => x.GroupId).ToList(); - var result = questions.Where(x => x.Type == ReadingQestionType.Group && groupids.Contains(x.Id)).ToList(); + var result = questions.Where(x => x.Type == ReadingQestionType.Group && groupids.Contains(x.Id)) + .WhereIf(groupClassifyList!=null,x=>x.GroupClassify!=null&& groupClassifyList.Contains(x.GroupClassify.Value)) + .ToList(); foreach (var item in result) { @@ -1562,7 +1580,9 @@ namespace IRaCIS.Application.Services x.FirstAddTaskId, }).ToListAsync(); - await _readingTaskQuestionMarkRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId); + + var markquestionId = inDto.Answers.Select(y => y.Id).ToList(); + await _readingTaskQuestionMarkRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId&& markquestionId.Contains(x.QuestionId)); var datetime = DateTime.Now; var markList = _mapper.Map, List>(inDto.QuestionMarkInfoList); @@ -1741,6 +1761,7 @@ namespace IRaCIS.Application.Services { IsChangeOtherTask = false, VisitTaskId = inDto.VisitTaskId, + ComputationTrigger=ComputationTrigger.Lesion, }); return ResponseOutput.Ok(true); } @@ -1767,7 +1788,7 @@ namespace IRaCIS.Application.Services } } var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Include(x => x.TrialReadingCriterion).FirstNotNullAsync(); - + inDto.BlindName = taskinfo.TaskBlindName; switch (taskinfo.TrialReadingCriterion.CriterionType) { // 对于非靶病灶,如果状态选择为显著增大,请验证: @@ -2071,7 +2092,11 @@ namespace IRaCIS.Application.Services rowInfo.FristAddTaskId = inDto.RowId == null ? inDto.VisitTaskId : rowInfo.FristAddTaskId; if (inDto.RowId == null) { - + rowInfo.FromMark = inDto.FromMark ?? string.Empty; + rowInfo.ReportMark = inDto.ReportMark ?? string.Empty; + rowInfo.MarkTool = inDto.MarkTool ?? string.Empty; + rowInfo.PicturePath = inDto.PicturePath ?? string.Empty; + rowInfo.MeasureData = inDto.MeasureData ?? string.Empty; //await _readingTableAnswerRowInfoRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.RowIndex == inDto.RowIndex && x.QuestionId == inDto.QuestionId); List answerList = inDto.AnswerList.Select(x => new ReadingTableQuestionAnswer() @@ -2137,6 +2162,7 @@ namespace IRaCIS.Application.Services { IsChangeOtherTask = false, VisitTaskId = inDto.VisitTaskId, + ComputationTrigger = ComputationTrigger.Lesion, }); diff --git a/IRaCIS.Core.Application/Service/ReadingCalculate/General/ReadingCalculateService.cs b/IRaCIS.Core.Application/Service/ReadingCalculate/General/ReadingCalculateService.cs index ff966babf..49509412d 100644 --- a/IRaCIS.Core.Application/Service/ReadingCalculate/General/ReadingCalculateService.cs +++ b/IRaCIS.Core.Application/Service/ReadingCalculate/General/ReadingCalculateService.cs @@ -196,7 +196,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate { await service.CalculateTask(new CalculateTaskInDto() { - + ComputationTrigger= ComputationTrigger.Report, VisitTaskId = inDto.VisitTaskId }); } diff --git a/IRaCIS.Core.Application/Service/ReadingCalculate/LuganoCalculateService.cs b/IRaCIS.Core.Application/Service/ReadingCalculate/LuganoCalculateService.cs index 5e816b314..dde4e18be 100644 --- a/IRaCIS.Core.Application/Service/ReadingCalculate/LuganoCalculateService.cs +++ b/IRaCIS.Core.Application/Service/ReadingCalculate/LuganoCalculateService.cs @@ -400,7 +400,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate if (lowPddTaskid != null && lowPddTaskid != default(Guid)) { - var lowPPDAnswerList = await _readingTableQuestionAnswerRepository.Where(x => visitTaskIds.Contains(x.VisitTaskId) + var lowPPDAnswerList = await _readingTableQuestionAnswerRepository.Where(x =>x.VisitTaskId== lowPddTaskid && x.QuestionId == inDto.QuestionId && x.RowIndex == inDto.RowIndex).Include(x => x.ReadingTableQuestionTrial) .Select(x => new @@ -429,6 +429,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate { ReadingCalculateDto readingData = await _generalCalculateService.GetReadingCalculateDto(inDto.VisitTaskId); readingData.IsChangeOtherTask = inDto.IsChangeOtherTask; + readingData.ComputationTrigger = inDto.ComputationTrigger; await ReadingCalculate(readingData); } @@ -493,16 +494,22 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate new ReadingCalculateData (){QuestionType=QuestionType.NoTargetLesion,GetStringFun=GetNoTargetLesionEvaluate}, //新病灶评估 - new ReadingCalculateData (){QuestionType=QuestionType.NewLesions,GetStringFun=GetNewLesionEvaluate}, + new ReadingCalculateData (){QuestionType=QuestionType.NewLesionEvaluation,GetStringFun=GetNewLesionEvaluate}, + + //获取肝脏评估 + new ReadingCalculateData (){QuestionType=QuestionType.LiverAssessment,GetStringFun=GetLiverAssessment}, + + // 骨髓中是否存在局灶性 FDG亲和病灶的证据 + new ReadingCalculateData (){QuestionType=QuestionType.EvidenceFocalFDG,GetStringFun=GetEvidenceFocalFDG,ComputationTrigger=ComputationTrigger.Lesion}, //CT/MRI new ReadingCalculateData (){QuestionType=QuestionType.CTandMRI,GetStringFun=CTMRIEvaluation}, // PET 5PS评分 - new ReadingCalculateData (){QuestionType=QuestionType.PET5PS,GetStringFun=GetPET5PS}, + new ReadingCalculateData (){QuestionType=QuestionType.PET5PS,GetStringFun=GetPET5PS,ComputationTrigger=ComputationTrigger.Lesion}, //与基线相比摄取值变化 - new ReadingCalculateData (){QuestionType=QuestionType.UptakeChange,GetStringFun=GetUptakeChange}, + new ReadingCalculateData (){QuestionType=QuestionType.UptakeChange,GetStringFun=GetUptakeChange,ComputationTrigger=ComputationTrigger.Lesion}, // FDG-PET 评估结果 new ReadingCalculateData (){QuestionType=QuestionType.FDGPET,GetStringFun=GetFDGPETOverallAssessment}, @@ -517,6 +524,10 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate // SUVmax所在病灶 new ReadingCalculateData (){QuestionType=QuestionType.SUVmaxLesion,GetStringFun=GetSuvMaxFocus}, + + + + ////靶病灶径线之和(SOD) //new ReadingCalculateData (){QuestionType=QuestionType.SOD,GetDecimalNullFun=GetSODData}, @@ -599,6 +610,8 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate calculateList = calculateList.Where(x => calculateType.Contains(x.QuestionType)).ToList(); } + + calculateList = calculateList.Where(x => x.ComputationTrigger == null || x.ComputationTrigger == inDto.ComputationTrigger).ToList(); var typeNAList = new List { QuestionType.SODChange, @@ -1619,7 +1632,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate var presentSpd = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.SPD).Select(x => x.Answer).FirstOrDefault().IsNullOrEmptyReturn0(); if (baseLineSpd != 0) { - return (presentSpd - baseLineSpd) / baseLineSpd; + return (presentSpd - baseLineSpd)*100 / baseLineSpd; } else { @@ -1704,35 +1717,82 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate } #endregion - #region 获取脾脏评估 + #region 获取脾脏状态 /// - /// 获取脾脏评估 + /// 获取脾脏状态 /// - /// + /// + /// /// - public async Task GetSplenicEvaluation(ReadingCalculateDto inDto) + [HttpPost] + public async Task GetSplenicState(Guid visitTaskId,decimal spleenLength) { + + var taskinfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).FirstNotNullAsync(); + ReadingCalculateDto inDto = await _generalCalculateService.GetReadingCalculateDto(visitTaskId); + if (inDto.IsBaseLine) { - return SpleenAssessment.Stabilization.GetEnumInt(); + if (spleenLength <= 130) + { + return SpleenAssessment.Normal.GetEnumInt(); + } + else + { + return SpleenAssessment.Swelling.GetEnumInt(); + } + } + if (spleenLength == 0) + { + return SpleenAssessment.NotEvaluable.GetEnumInt(); + } + + #region 最低 + var visitTaskIds = await _visitTaskRepository.Where(x => x.ReadingCategory == ReadingCategory.Visit && + x.TrialReadingCriterionId == taskinfo.TrialReadingCriterionId && + x.IsAnalysisCreate == taskinfo.IsAnalysisCreate && + x.DoctorUserId == taskinfo.DoctorUserId && + x.IsSelfAnalysis == taskinfo.IsSelfAnalysis && + x.SubjectId == taskinfo.SubjectId && x.ReadingTaskState == ReadingTaskState.HaveSigned && x.ArmEnum == taskinfo.ArmEnum + && x.VisitTaskNum < taskinfo.VisitTaskNum && x.TaskState == TaskState.Effect + ).OrderByDescending(x => x.VisitTaskNum).Select(x => x.Id).ToListAsync(); + + var questionId = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == taskinfo.TrialReadingCriterionId && x.QuestionType == QuestionType.SpleenLength).Select(x => x.Id).FirstNotNullAsync(); + var answerList = await _readingTaskQuestionAnswerRepository.Where(x => visitTaskIds.Contains(x.VisitTaskId) + && x.ReadingQuestionTrialId == questionId ) + .Select(x => new + { + x.Answer, + x.VisitTaskId, + }).ToListAsync(); + + var lowSpleenLength = answerList.Select(x => new + { + Answer = x.Answer.IsNullOrEmptyReturn0(), + x.VisitTaskId + }).OrderBy(x => x.Answer).Select(x=>x.Answer).FirstOrDefault(); + #endregion + var result = SpleenAssessment.Stabilization; - var presentSpd = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.SpleenLength).Select(x => x.Answer).FirstOrDefault().IsNullOrEmptyReturn0(); + var presentSpd = spleenLength; var baseLineSpleenLength = await GetBaseLineSpleenLength(inDto); var baseLineTaskId = await GetBaseLineTaskId(inDto); - var baseLineState= await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == baseLineTaskId && x.ReadingQuestionTrial.QuestionType == QuestionType.SplenicStatus).Select(x => x.Answer).FirstOrDefaultAsync(); + var baseLineState = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == baseLineTaskId && x.ReadingQuestionTrial.QuestionType == QuestionType.SplenicStatus).Select(x => x.Answer).FirstOrDefaultAsync(); var differenceValue = presentSpd - baseLineSpleenLength; + + var differenceLowValue = presentSpd - lowSpleenLength; decimal percentage = 0; if (baseLineSpleenLength != 0) { - percentage = differenceValue*100 / baseLineSpleenLength; + percentage = differenceValue * 100 / (baseLineSpleenLength-130); } // 1、基线 垂直径> 130 mm @@ -1753,7 +1813,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate //2、当前访视的前面访视中 存在垂直径≤130mm //3、与最低点相比脾脏垂直径的增加值≥20 mm //4、当前垂直径 > 130 mm - else if (baseLineSpleenLength > 130 && presentSpd <= 130 && differenceValue >= 20 && presentSpd > 130) + else if (baseLineSpleenLength > 130 && lowSpleenLength <= 130 && differenceLowValue >= 20 && presentSpd > 130) { result = SpleenAssessment.Increase; } @@ -1764,18 +1824,96 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate } //1、基线期 状态为“肿大” //与基线相比脾肿大增加的百分比 > 50% - else if (baseLineState.EqEnum(SpleenState.Swelling) && percentage > 50) + else if (baseLineState.EqEnum(SpleenAssessment.Swelling) && percentage > 50) { result = SpleenAssessment.Remission; } else { - result = SpleenAssessment.Remission; + result = SpleenAssessment.Stabilization; } return result.GetEnumInt(); } #endregion + #region 获取脾脏评估 + + /// + /// 获取脾脏评估 + /// + /// + /// + public async Task GetSplenicEvaluation(ReadingCalculateDto inDto) + { + + return inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.SplenicStatus).Select(x => x.Answer).FirstIsNullReturnEmpty(); + + //if (inDto.IsBaseLine) + //{ + // return SpleenAssessment.Stabilization.GetEnumInt(); + //} + + //var result = SpleenAssessment.Stabilization; + + + //var presentSpd = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.SpleenLength).Select(x => x.Answer).FirstOrDefault().IsNullOrEmptyReturn0(); + //var baseLineSpleenLength = await GetBaseLineSpleenLength(inDto); + + //var baseLineTaskId = await GetBaseLineTaskId(inDto); + //var baseLineState = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == baseLineTaskId && x.ReadingQuestionTrial.QuestionType == QuestionType.SplenicStatus).Select(x => x.Answer).FirstOrDefaultAsync(); + + + //var differenceValue = presentSpd - baseLineSpleenLength; + //decimal percentage = 0; + //if (baseLineSpleenLength != 0) + //{ + // percentage = differenceValue * 100 / baseLineSpleenLength; + //} + + //// 1、基线 垂直径> 130 mm + ////2、与基线相比脾垂直径变化值≥10 mm + ////与基线相比脾肿大增加的百分比 > 50% + //if (baseLineSpleenLength > 130 && differenceValue >= 10 && percentage > 50) + //{ + // result = SpleenAssessment.Increase; + //} + ////1、基线垂直径≤130mm + ////2、与基线相比脾垂直径变化值≥20 mm + ////当前垂直径 > 130 mm + //else if (baseLineSpleenLength <= 130 && differenceValue >= 20 && presentSpd > 130) + //{ + // result = SpleenAssessment.Increase; + //} + ////1、基线 垂直径> 130 mm + ////2、当前访视的前面访视中 存在垂直径≤130mm + ////3、与最低点相比脾脏垂直径的增加值≥20 mm + ////4、当前垂直径 > 130 mm + //else if (baseLineSpleenLength > 130 && presentSpd <= 130 && differenceValue >= 20 && presentSpd > 130) + //{ + // result = SpleenAssessment.Increase; + //} + //// 基线垂直径≤130mm + //else if (baseLineSpleenLength <= 130) + //{ + // result = SpleenAssessment.Normal; + //} + ////1、基线期 状态为“肿大” + ////与基线相比脾肿大增加的百分比 > 50% + //else if (baseLineState.EqEnum(SpleenState.Swelling) && percentage > 50) + //{ + // result = SpleenAssessment.Remission; + //} + //else + //{ + // result = SpleenAssessment.Remission; + //} + //return result.GetEnumInt(); + + + } + #endregion + + #region PET 5PS /// @@ -1785,10 +1923,18 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate /// public async Task GetPET5PS(ReadingCalculateDto inDto) { - if (inDto.IsBaseLine) + //if (inDto.IsBaseLine) + //{ + // return SpleenAssessment.Stabilization.GetEnumInt(); + //} + + if (inDto.QuestionInfo.Any(x => x.QuestionType == QuestionType.ExistPET && x.Answer == ReadingYesOrNo.No.GetEnumInt())) { - return SpleenAssessment.Stabilization.GetEnumInt(); + return PET5PSScore.NE.GetEnumInt(); } + + + PET5PSScore result = PET5PSScore.X; // 最大Suvmax @@ -1850,6 +1996,11 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate return SUVChangeVSBaseline.NotEvaluable.GetEnumInt(); } + if (inDto.QuestionInfo.Any(x => x.QuestionType == QuestionType.ExistPET && x.Answer == ReadingYesOrNo.No.GetEnumInt())) + { + return SUVChangeVSBaseline.NotEvaluable.GetEnumInt(); + } + var result = SUVChangeVSBaseline.NotEvaluable; var baseLineTaskId = await GetBaseLineTaskId(inDto); @@ -1929,7 +2080,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate new CalculationDto(){ Column1=ReadingCommon.EnumToString(new List() { PET5PSScore.Five,PET5PSScore.Four, }), Column2=ReadingCommon.EnumToString(new List() { SUVChangeVSBaseline.Increase }), - Column3=ReadingCommon.EnumToString(new List() { FDGAffinityFociInBM.NE, FDGAffinityFociInBM.YesHaveNew, FDGAffinityFociInBM.YesHaveNew, FDGAffinityFociInBM.No}), + Column3=ReadingCommon.EnumToString(new List() { FDGAffinityFociInBM.NE, FDGAffinityFociInBM.YesHaveNew, FDGAffinityFociInBM.YesSustain, FDGAffinityFociInBM.No}), Column4=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.PMD }), }, @@ -1953,7 +2104,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate new CalculationDto(){ Column1=ReadingCommon.EnumToString(new List() { PET5PSScore.Five,PET5PSScore.Four }), Column2=ReadingCommon.EnumToString(new List() { SUVChangeVSBaseline.Decrease }), - Column3=ReadingCommon.EnumToString(new List() { FDGAffinityFociInBM.YesSustain}), + Column3=ReadingCommon.EnumToString(new List() { FDGAffinityFociInBM.No, FDGAffinityFociInBM.YesSustain}), Column4=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.PMR }), }, @@ -1961,7 +2112,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate new CalculationDto(){ Column1=ReadingCommon.EnumToString(new List() { PET5PSScore.Five,PET5PSScore.Four }), Column2=ReadingCommon.EnumToString(new List() { SUVChangeVSBaseline.DidNotChange }), - Column3=ReadingCommon.EnumToString(new List() { FDGAffinityFociInBM.YesSustain}), + Column3=ReadingCommon.EnumToString(new List() { FDGAffinityFociInBM.No, FDGAffinityFociInBM.YesSustain}), Column4=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.NMR }), }, }; @@ -1976,6 +2127,37 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate return resultdata ?? string.Empty; } + #endregion + #region 骨髓中是否存在局灶性 FDG亲和病灶的证据 + + /// + /// 骨髓中是否存在局灶性 FDG亲和病灶的证据 + /// + /// + /// + public async Task GetEvidenceFocalFDG(ReadingCalculateDto inDto) + { + if (inDto.QuestionInfo.Any(x => x.QuestionType == QuestionType.ExistPET && x.Answer == ReadingYesOrNo.No.GetEnumInt())) + { + return FDGAffinityFociInBM.NE.GetEnumInt(); + } + else + { + return inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.EvidenceFocalFDG).Select(x => x.Answer).FirstOrDefault(); + } + } + #endregion + + #region 肝脏评估 + /// + /// 获取肝脏评估 + /// + /// + /// + public async Task GetLiverAssessment(ReadingCalculateDto inDto) + { + return inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.LiverState).Select(x => x.Answer).FirstIsNullReturnEmpty(); + } #endregion #region SuvMax所在病灶 @@ -2071,18 +2253,18 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate List data = new List() { - //ND NE NE ND + //ND NE NE/NA ND new CalculationDto(){ Column1=ReadingCommon.EnumToString(new List() { CTMRIOverallAssessment.ND }), Column2=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.NE }), - Column3=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.NE}), + Column3=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.NE, FDGPETOverallAssessment.NA}), Column4=ReadingCommon.EnumToString(new List() { ImagingOverallAssessment_Lugano.ND }), }, - //ND/PD/CR/NE/PR/SD PMD PMD/CMR/PMR/NMR/NE PMD/PD + //ND/PD/CR/NE/PR/SD PMD PMD/CMR/PMR/NMR/NE/NA PMD/PD new CalculationDto(){ Column1=ReadingCommon.EnumToString(new List() { CTMRIOverallAssessment.ND, CTMRIOverallAssessment.PD,CTMRIOverallAssessment.CR,CTMRIOverallAssessment.NE,CTMRIOverallAssessment.PR,CTMRIOverallAssessment.SD}), Column2=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.PMD, }), - Column3=ReadingCommon.EnumToString(new List() {FDGPETOverallAssessment.PMD, FDGPETOverallAssessment.CMR,FDGPETOverallAssessment.PMR, FDGPETOverallAssessment.NMR, FDGPETOverallAssessment.NE }), + Column3=ReadingCommon.EnumToString(new List() {FDGPETOverallAssessment.PMD, FDGPETOverallAssessment.CMR,FDGPETOverallAssessment.PMR, FDGPETOverallAssessment.NMR, FDGPETOverallAssessment.NE, FDGPETOverallAssessment.NA }), Column4=ReadingCommon.EnumToString(new List() { ImagingOverallAssessment_Lugano.PMDPD }), }, //ND/PD/CR/NE/PR/SD PMD/CMR/PMR/NMR/NE PMD PMD/PD @@ -2092,25 +2274,59 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate Column3=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.PMD, }), Column4=ReadingCommon.EnumToString(new List() { ImagingOverallAssessment_Lugano.PMDPD }), }, - //PD NE CMR/PMR/NMR/NE PMD/PD + //PD NE CMR/PMR/NMR/NE/NA PMD/PD new CalculationDto(){ Column1=ReadingCommon.EnumToString(new List() { CTMRIOverallAssessment.PD}), Column2=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.NE, }), - Column3=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.CMR,FDGPETOverallAssessment.PMR, FDGPETOverallAssessment.NMR, FDGPETOverallAssessment.NE }), + Column3=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.CMR,FDGPETOverallAssessment.PMR, FDGPETOverallAssessment.NMR, FDGPETOverallAssessment.NE, FDGPETOverallAssessment.NA }), Column4=ReadingCommon.EnumToString(new List() { ImagingOverallAssessment_Lugano.PMDPD }), }, - //ND/PD/CR/NE/PR/SD PMR PMD/CMR/PMR/NMR/NE PMR/PR + //NE NE NE/NA NE + new CalculationDto(){ + Column1=ReadingCommon.EnumToString(new List() { CTMRIOverallAssessment.NE }), + Column2=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.NE }), + Column3=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.NE, FDGPETOverallAssessment.NA }), + Column4=ReadingCommon.EnumToString(new List() { ImagingOverallAssessment_Lugano.NE }), + }, + + //CR、PR、SD、NE、ND、PD CMR CMR/PMR/NMR/PMD/NE/NA CMR/CR + new CalculationDto(){ + Column1=ReadingCommon.EnumToString(new List() { CTMRIOverallAssessment.CR,CTMRIOverallAssessment.PR,CTMRIOverallAssessment.SD,CTMRIOverallAssessment.NE,CTMRIOverallAssessment.ND,CTMRIOverallAssessment.PD }), + Column2=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.CMR }), + Column3=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.CMR, FDGPETOverallAssessment.PMR, FDGPETOverallAssessment.NMR, FDGPETOverallAssessment.PMD, FDGPETOverallAssessment.NE, FDGPETOverallAssessment.NA}), + Column4=ReadingCommon.EnumToString(new List() { ImagingOverallAssessment_Lugano.CMRCR }), + }, + //CR NE NE/NA CMR/CR + new CalculationDto(){ + Column1=ReadingCommon.EnumToString(new List() { CTMRIOverallAssessment.CR }), + Column2=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.NE }), + Column3=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.NE, FDGPETOverallAssessment.NA,}), + Column4=ReadingCommon.EnumToString(new List() { ImagingOverallAssessment_Lugano.CMRCR }), + }, + + //CR、PR、SD、NE、ND CMR NE/NA CMR/CR + new CalculationDto(){ + Column1=ReadingCommon.EnumToString(new List() { CTMRIOverallAssessment.CR,CTMRIOverallAssessment.PR,CTMRIOverallAssessment.SD,CTMRIOverallAssessment.NE,CTMRIOverallAssessment.ND }), + Column2=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.CMR }), + Column3=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.NE, FDGPETOverallAssessment.NA,}), + Column4=ReadingCommon.EnumToString(new List() { ImagingOverallAssessment_Lugano.CMRCR }), + }, + + + + + //ND/PD/CR/NE/PR/SD PMR PMD/CMR/PMR/NMR/NE PMR/PR new CalculationDto(){ Column1=ReadingCommon.EnumToString(new List() { CTMRIOverallAssessment.ND, CTMRIOverallAssessment.PD,CTMRIOverallAssessment.CR,CTMRIOverallAssessment.NE,CTMRIOverallAssessment.PR,CTMRIOverallAssessment.SD }), Column2=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.PMR }), - Column3=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.PMD, FDGPETOverallAssessment.CMR,FDGPETOverallAssessment.PMR, FDGPETOverallAssessment.NMR, FDGPETOverallAssessment.NE }), + Column3=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.PMD, FDGPETOverallAssessment.CMR,FDGPETOverallAssessment.PMR, FDGPETOverallAssessment.NMR, FDGPETOverallAssessment.NE,FDGPETOverallAssessment.NA, }), Column4=ReadingCommon.EnumToString(new List() { ImagingOverallAssessment_Lugano.PMRPR }), }, //PR NE NE PMR/PR new CalculationDto(){ Column1=ReadingCommon.EnumToString(new List() { CTMRIOverallAssessment.PR }), Column2=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.NE }), - Column3=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.NE}), + Column3=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.NE, FDGPETOverallAssessment.NA,}), Column4=ReadingCommon.EnumToString(new List() { ImagingOverallAssessment_Lugano.PMRPR }), }, //CR/PR/SD/NE/ND NE PMR PMR/PR @@ -2124,7 +2340,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate new CalculationDto(){ Column1=ReadingCommon.EnumToString(new List() { CTMRIOverallAssessment.ND,CTMRIOverallAssessment.PD,CTMRIOverallAssessment.CR,CTMRIOverallAssessment.NE,CTMRIOverallAssessment.PR,CTMRIOverallAssessment.SD }), Column2=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.NMR }), - Column3=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.PMD, FDGPETOverallAssessment.CMR, FDGPETOverallAssessment.PMR, FDGPETOverallAssessment.NMR, FDGPETOverallAssessment.NE}), + Column3=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.PMD, FDGPETOverallAssessment.CMR, FDGPETOverallAssessment.PMR, FDGPETOverallAssessment.NMR, FDGPETOverallAssessment.NE, FDGPETOverallAssessment.NA,}), Column4=ReadingCommon.EnumToString(new List() { ImagingOverallAssessment_Lugano.NMRSD }), }, //CR/PR/SD/ND/NE NE NMR NMR/SD @@ -2138,7 +2354,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate new CalculationDto(){ Column1=ReadingCommon.EnumToString(new List() { CTMRIOverallAssessment.SD }), Column2=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.NE }), - Column3=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.NE}), + Column3=ReadingCommon.EnumToString(new List() { FDGPETOverallAssessment.NE, FDGPETOverallAssessment.NA,}), Column4=ReadingCommon.EnumToString(new List() { ImagingOverallAssessment_Lugano.NMRSD }), }, }; @@ -2204,11 +2420,14 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate /// public async Task GetTargetLesionEvaluate(ReadingCalculateDto inDto) { + + + var rowInfo = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.TargetLesion).SelectMany(x => x.TableRowInfoList).ToList(); - //if (inDto.IsBaseLine) - //{ - // return TargetAssessment.NA.GetEnumInt(); - //} + if (inDto.IsBaseLine) + { + return TargetAssessment.NA.GetEnumInt(); + } var tableQuestions = rowInfo.SelectMany(x => x.TableQuestionList).ToList(); TargetAssessment result = TargetAssessment.SD; @@ -2273,10 +2492,13 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate { result = TargetAssessment.PD; } - //在排除PD后,有任一靶病灶为NE状态 - else if (tableQuestions.Any(x => x.QuestionMark == QuestionMark.State && x.Answer.EqEnum(TargetState.UnableEvaluate))) + //当前访视没有任何一个状态为“疾病进展”的靶病灶; + //当前访视存在至少一个状态为“不可评估”的靶病灶。 + else if ( + !tableQuestions.Any(x => x.QuestionMark == QuestionMark.State && x.Answer.EqEnum(TargetState.DiseaseProgression))&& + tableQuestions.Any(x => x.QuestionMark == QuestionMark.State && x.Answer.EqEnum(TargetState.UnableEvaluate))) { - result = TargetAssessment.PD; + result = TargetAssessment.NE; } //1、基线非淋巴结靶病灶不存在,或者当前访视非淋巴结靶病灶全部消失; //并且 2.当前访视淋巴结靶病灶的状态全部变为“消失”。 @@ -2308,10 +2530,10 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate NoTargetAssessment result = NoTargetAssessment.PD; - //if (inDto.IsBaseLine) - //{ - // return NoTargetAssessment.NA.GetEnumInt(); - //} + if (inDto.IsBaseLine) + { + return NoTargetAssessment.NA.GetEnumInt(); + } var tableRows = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.NonTargetLesions).SelectMany(x => x.TableRowInfoList).ToList(); @@ -2409,14 +2631,18 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate /// public async Task CTMRIEvaluation(ReadingCalculateDto inDto) { + if (inDto.IsBaseLine) + { + return CTMRIOverallAssessment.NA.GetEnumInt(); + } // 靶病灶评估 var targetEvaluation = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.TargetLesion).Select(x => x.Answer).FirstOrDefault(); // 非靶病灶评估 - var noTargetEvaluation = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.NETarget).Select(x => x.Answer).FirstOrDefault(); + var noTargetEvaluation = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.NoTargetLesion).Select(x => x.Answer).FirstOrDefault(); // 存在新病灶 - var existsNewTarget = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.NewTargetLesion).Select(x => x.Answer).FirstOrDefault(); + var existsNewTarget = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.NewLesionEvaluation).Select(x => x.Answer).FirstOrDefault(); // 肝脏评估 var liverEvaluation = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.LiverAssessment).Select(x => x.Answer).FirstOrDefault(); @@ -2430,7 +2656,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate new CalculationDto(){ Column1=ReadingCommon.EnumToString(new List() { TargetAssessment.ND }), Column2=ReadingCommon.EnumToString(new List() { NoTargetAssessment.ND }), - Column3=ReadingCommon.EnumToString(new List() { NewLesionAssessment.No,NewLesionAssessment.Suspected }), + Column3=ReadingCommon.EnumToString(new List() { NewLesionAssessment.No, NewLesionAssessment.Suspected }), Column4=ReadingCommon.EnumToString(new List() { LiverAssessment.Normal }), Column5=ReadingCommon.EnumToString(new List() { SpleenAssessment.Normal }), Column6=ReadingCommon.EnumToString(new List() { CTMRIOverallAssessment.ND }), @@ -2454,14 +2680,14 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate Column5=ReadingCommon.EnumToString(new List() { }), Column6=ReadingCommon.EnumToString(new List() { CTMRIOverallAssessment.PD }), }, - //PD 任一结果 是 任一结果 任一结果 PD + //任一结果 任一结果 是 任一结果 任一结果 PD new CalculationDto(){ - Column1=ReadingCommon.EnumToString(new List() { TargetAssessment.PD }), + Column1=ReadingCommon.EnumToString(new List() { }), Column2=ReadingCommon.EnumToString(new List() { }), Column3=ReadingCommon.EnumToString(new List() { NewLesionAssessment.Yes }), Column4=ReadingCommon.EnumToString(new List() { }), Column5=ReadingCommon.EnumToString(new List() { }), - Column6=ReadingCommon.EnumToString(new List() { CTMRIOverallAssessment.ND }), + Column6=ReadingCommon.EnumToString(new List() { CTMRIOverallAssessment.PD }), }, //任一结果 任一结果 任一结果 显著增大 任一结果 PD new CalculationDto(){ @@ -2470,7 +2696,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate Column3=ReadingCommon.EnumToString(new List() { }), Column4=ReadingCommon.EnumToString(new List() { LiverAssessment.Increase }), Column5=ReadingCommon.EnumToString(new List() { }), - Column6=ReadingCommon.EnumToString(new List() { CTMRIOverallAssessment.ND }), + Column6=ReadingCommon.EnumToString(new List() { CTMRIOverallAssessment.PD }), }, //任一结果 任一结果 任一结果 任一结果 显著增大 PD new CalculationDto(){ @@ -2479,7 +2705,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate Column3=ReadingCommon.EnumToString(new List() {}), Column4=ReadingCommon.EnumToString(new List() { }), Column5=ReadingCommon.EnumToString(new List() { SpleenAssessment.Increase }), - Column6=ReadingCommon.EnumToString(new List() { CTMRIOverallAssessment.ND }), + Column6=ReadingCommon.EnumToString(new List() { CTMRIOverallAssessment.PD }), }, //CR CR/ND 否 正常 正常 CR new CalculationDto(){ @@ -2499,9 +2725,9 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate Column5=ReadingCommon.EnumToString(new List() { SpleenAssessment.Normal }), Column6=ReadingCommon.EnumToString(new List() { CTMRIOverallAssessment.CR }), }, - //NE 非PD 否/疑似/无法评估 显著增大 显著增大 NE + //NE 非PD 否/疑似/无法评估 非显著增大 非显著增大 NE new CalculationDto(){ - NotEq=new List(){ 2}, + NotEq=new List(){ 2,4,5}, Column1=ReadingCommon.EnumToString(new List() { TargetAssessment.NE }), Column2=ReadingCommon.EnumToString(new List() { NoTargetAssessment.PD }), Column3=ReadingCommon.EnumToString(new List() { NewLesionAssessment.No,NewLesionAssessment.Suspected, NewLesionAssessment.NE}), @@ -2531,7 +2757,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate }, //ND ND 否/疑似 无法评估 正常/稳定/无法评估/部分缓解(非显著增大) NE new CalculationDto(){ - NotEq=new List(){ 4}, + NotEq=new List(){ 5}, Column1=ReadingCommon.EnumToString(new List() { TargetAssessment.ND }), Column2=ReadingCommon.EnumToString(new List() { NoTargetAssessment.ND }), Column3=ReadingCommon.EnumToString(new List() { NewLesionAssessment.No,NewLesionAssessment.Suspected }), @@ -2598,6 +2824,14 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate }, }; + var index= data.FindIndex(x => + (x.NotEq.Contains(1) ? !x.Column1.Contains(targetEvaluation) : x.Column1.Contains(targetEvaluation) || x.Column1.Count() == 0) && + (x.NotEq.Contains(2) ? !x.Column2.Contains(noTargetEvaluation) : x.Column2.Contains(noTargetEvaluation) || x.Column2.Count() == 0) && + (x.NotEq.Contains(3) ? !x.Column3.Contains(existsNewTarget) : x.Column3.Contains(existsNewTarget) || x.Column3.Count() == 0) && + (x.NotEq.Contains(4) ? !x.Column4.Contains(liverEvaluation) : x.Column4.Contains(liverEvaluation) || x.Column4.Count() == 0) && + (x.NotEq.Contains(5) ? !x.Column5.Contains(spleenEvaluation) : x.Column5.Contains(spleenEvaluation) || x.Column5.Count() == 0)) + ; + Console.WriteLine(index); var result = data.Where(x => (x.NotEq.Contains(1) ? !x.Column1.Contains(targetEvaluation) : x.Column1.Contains(targetEvaluation) || x.Column1.Count() == 0) && (x.NotEq.Contains(2) ? !x.Column2.Contains(noTargetEvaluation) : x.Column2.Contains(noTargetEvaluation) || x.Column2.Count() == 0) && diff --git a/IRaCIS.Core.Application/Service/Third-partyProject/DTO/UltrasonicDicomViewModel.cs b/IRaCIS.Core.Application/Service/Third-partyProject/DTO/UltrasonicDicomViewModel.cs new file mode 100644 index 000000000..25bf021ee --- /dev/null +++ b/IRaCIS.Core.Application/Service/Third-partyProject/DTO/UltrasonicDicomViewModel.cs @@ -0,0 +1,130 @@ +using IRaCIS.Core.Application.Contracts; +using IRaCIS.Core.Domain.Share; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace IRaCIS.Core.Application.Service.Third_partyProject.DTO +{ + + public class TrialListDTO_UltrasonicDicom: TrialBaseInfoDto + { + public DateTime CreateTime { get; set; } + + public string Sponsor { get; set; } + public string TrialStatusStr { get; set; } + } + + public class VisitTaskQuery_UltrasonicDicom : PageInput + { + [NotDefault] + public Guid TrialId { get; set; } + + public Guid? SiteId { get; set; } + + public Guid? SubjectId { get; set; } + + public string SubjectCode { get; set; } = String.Empty; + + public bool? IsUrgent { get; set; } + + public string TaskName { get; set; } = String.Empty; + + public Guid? DoctorUserId { get; set; } + + public string? TaskCode { get; set; } + + public String? TrialSiteCode { get; set; } + + public Arm? ArmEnum { get; set; } + + public Guid? TrialReadingCriterionId { get; set; } + + + + } + public class VisitTaskDTO_UltrasonicDicom + { + public Guid Id { get;set; } + public Guid SubjectId { get; set; } + public String TrialSiteCode { get; set; } = String.Empty; + public string SubjectCode { get; set; } = String.Empty; + public string UserName { get; set; } + public string FullName { get; set; } + public Arm ArmEnum { get; set; } + public Guid? DoctorUserId { get; set; } + public string TaskCode { get; set; } + public string TaskName { get; set; } + public string TaskBlindName { get; set; } + + public decimal VisitTaskNum { get; set; } + + public int ImageStudyState { get; set; } + + public Guid TrialReadingCriterionId { get; set; } + public string TrialReadingCriterionName { get; set; } + } + + public class UpdateTaskImageStateCommand + { + [NotDefault] + public Guid VisitTaskId { get; set; } + public int ImageStudyState { get; set; } + } + + + public class StudyDTO_UltrasonicDicom : UnionStudyViewModel + { + + } + + public class StudySeriesModality + { + public Guid StudyId { get; set; } + + public int SeriesCount { get; set; } + + public string StudyCode { get; set; } + + + public List ModalitySeriesList => SeriesModalityList.GroupBy(t=>t.Modality).Select(g=>new ModalitySeriesIdList() { Modality= g.Key,SeriesIdList=g.Select(t=>t.SeriesId).ToList() }).ToList(); + + public List SeriesModalityList { get; set; } + + } + + public class StudySeriesModalitySelectDTO + { + public Guid StudyId { get; set; } + + public List SeriesIdList { get; set; } + } + + + public class ModalitySeriesIdList + { + public string Modality { get; set; } + + public List SeriesIdList { get; set; } + } + public class SeriesModality + { + public Guid SeriesId { get; set; } + + public string Modality { get; set; } + } + + public class InstancePathDTO + { + public string StudyInstanceUid { get; set; } + public string SopInstanceUid { get; set; } + public string StudyCode { get; set; } + public string InstancePath { get; set; } + } + + + +} diff --git a/IRaCIS.Core.Application/Service/Third-partyProject/UltrasonicDicomService.cs b/IRaCIS.Core.Application/Service/Third-partyProject/UltrasonicDicomService.cs new file mode 100644 index 000000000..7e52257fb --- /dev/null +++ b/IRaCIS.Core.Application/Service/Third-partyProject/UltrasonicDicomService.cs @@ -0,0 +1,443 @@ +using EasyCaching.Core; +using IRaCIS.Application.Contracts; +using IRaCIS.Core.Application.Contracts; +using IRaCIS.Core.Application.Filter; +using IRaCIS.Core.Application.Service.Third_partyProject.DTO; +using IRaCIS.Core.Application.ViewModel; +using IRaCIS.Core.Domain.Share; +using IRaCIS.Core.Infrastructure; +using Medallion.Threading; +using Microsoft.AspNetCore.Mvc; +using OfficeOpenXml.FormulaParsing.Utilities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace IRaCIS.Core.Application.Service.Third_partyProject +{ + + [ApiExplorerSettings(GroupName = "Trial")] + public class UltrasonicDicomService : BaseService + { + public readonly IRepository _trialRepository; + public readonly IRepository _studyRepository; + private readonly IRepository _dictionaryRepository; + public readonly IRepository _visitTaskRepository; + + + public UltrasonicDicomService(IRepository trialRepository, IRepository studyRepository, IRepository visitTaskRepository, IRepository dictionaryRepository) + { + _trialRepository = trialRepository; + _studyRepository = studyRepository; + _visitTaskRepository = visitTaskRepository; + _dictionaryRepository = dictionaryRepository; + } + + + /// + /// 项目列表 + /// + /// + /// + [HttpPost] + public async Task>> GetTrialList(TrialToBeDoneQuery inQuery) + { + + var isPM = _userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.APM; + var isCRC = _userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator; + var isIQC = _userInfo.UserTypeEnumInt == (int)UserTypeEnum.IQC; + var isMIM = _userInfo.UserTypeEnumInt == (int)UserTypeEnum.MIM; + var isSPMOrCPM = _userInfo.UserTypeEnumInt == (int)UserTypeEnum.SPM || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CPM; + + + var query = _trialRepository.AsQueryable().IgnoreQueryFilters() + + .WhereIf(inQuery.SponsorId != null, o => o.SponsorId == inQuery.SponsorId) + .WhereIf(!string.IsNullOrEmpty(inQuery.Code), o => o.TrialCode.Contains(inQuery.Code)) + .WhereIf(!string.IsNullOrEmpty(inQuery.ResearchProgramNo), o => o.ResearchProgramNo.Contains(inQuery.ResearchProgramNo)) + .WhereIf(!string.IsNullOrWhiteSpace(inQuery.ExperimentName), o => o.ExperimentName.Contains(inQuery.ExperimentName)) + .WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin, t => t.TrialUserList.Any(t => t.UserId == _userInfo.Id && t.IsDeleted == false) && t.IsDeleted == false) + .Select(t => new TrialListDTO_UltrasonicDicom() + { + TrialId = t.Id, + ResearchProgramNo = t.ResearchProgramNo, + ExperimentName = t.ExperimentName, + TrialCode = t.TrialCode, + CreateTime = t.CreateTime, + Sponsor = _userInfo.IsEn_Us ? t.Sponsor.SponsorName : t.Sponsor.SponsorNameCN, + TrialStatusStr = t.TrialStatusStr + }); + + var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrWhiteSpace(inQuery.SortField) ? nameof(TrialListDTO_UltrasonicDicom.CreateTime) : inQuery.SortField, inQuery.Asc); + + return ResponseOutput.Ok(result); + } + + + /// + /// 任务列表 第一层级 + /// + /// + /// + [HttpPost] + public async Task> GetVisitTaskList(VisitTaskQuery_UltrasonicDicom queryVisitTask) + { + var visitTaskQueryable = _visitTaskRepository.Where(t => t.TrialId == queryVisitTask.TrialId && t.IsAnalysisCreate == false && t.TaskState == TaskState.Effect && t.SourceSubjectVisitId != null) + + .WhereIf(queryVisitTask.SiteId != null, t => t.Subject.SiteId == queryVisitTask.SiteId) + .WhereIf(queryVisitTask.SubjectId != null, t => t.SubjectId == queryVisitTask.SubjectId) + .WhereIf(queryVisitTask.IsUrgent != null, t => t.IsUrgent == queryVisitTask.IsUrgent) + .WhereIf(queryVisitTask.DoctorUserId != null, t => t.DoctorUserId == queryVisitTask.DoctorUserId) + .WhereIf(queryVisitTask.TrialReadingCriterionId != null, t => t.TrialReadingCriterionId == queryVisitTask.TrialReadingCriterionId) + .WhereIf(!string.IsNullOrEmpty(queryVisitTask.TrialSiteCode), t => (t.BlindTrialSiteCode.Contains(queryVisitTask.TrialSiteCode!) && t.IsAnalysisCreate) || (t.Subject.TrialSite.TrialSiteCode.Contains(queryVisitTask.TrialSiteCode!) && t.IsAnalysisCreate == false)) + .WhereIf(!string.IsNullOrEmpty(queryVisitTask.TaskName), t => t.TaskName.Contains(queryVisitTask.TaskName) || t.TaskBlindName.Contains(queryVisitTask.TaskName)) + .WhereIf(!string.IsNullOrEmpty(queryVisitTask.SubjectCode), t => (t.Subject.Code.Contains(queryVisitTask.SubjectCode) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(queryVisitTask.SubjectCode) && t.IsAnalysisCreate)) + + .ProjectTo(_mapper.ConfigurationProvider); + + var defalutSortArray = new string[] { nameof(VisitTask.SubjectId), nameof(VisitTask.VisitTaskNum) }; + + var pageList = await visitTaskQueryable.ToPagedListAsync(queryVisitTask.PageIndex, queryVisitTask.PageSize, queryVisitTask.SortField, queryVisitTask.Asc, string.IsNullOrWhiteSpace(queryVisitTask.SortField), defalutSortArray); + + return pageList; + } + + /// + /// 检查列表 第二层级 + /// + /// + [HttpGet] + public async Task> GetDicomAndNoneDicomStudyList(Guid visiTaskId, [FromServices] IRepository _visitTaskRepository) + { + + var query = from dicomStudy in _visitTaskRepository.Where(t => t.Id == visiTaskId).Select(t => t.SourceSubjectVisit).SelectMany(t => t.StudyList) + select new StudyDTO_UltrasonicDicom() + { + TrialId = dicomStudy.TrialId, + SiteId = dicomStudy.SiteId, + SubjectId = dicomStudy.SubjectId, + SubjectVisitId = dicomStudy.SubjectVisitId, + VisitName = dicomStudy.SubjectVisit.VisitName, + VisitNum = dicomStudy.SubjectVisit.VisitNum, + IsDicom = true, + SubjectCode = dicomStudy.Subject.Code, + + Id = dicomStudy.Id, + + Bodypart = dicomStudy.BodyPartExamined, + + Modalities = dicomStudy.Modalities, + + Count = dicomStudy.SeriesCount, + + StudyCode = dicomStudy.StudyCode, + + StudyTime = dicomStudy.StudyTime, + + TrialSiteAliasName = dicomStudy.TrialSite.TrialSiteAliasName, + + TrialSiteCode = dicomStudy.TrialSite.TrialSiteCode, + + Uploader = dicomStudy.Uploader.UserName, + + UploadTime = dicomStudy.CreateTime + }; + + + + + + return await query.ToListAsync(); + } + + /// + /// 修改任务上的 影像上传状态 + /// + /// + /// + [HttpPut] + public async Task UpdateTaskImageState(UpdateTaskImageStateCommand command) + { + await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => t.Id == command.VisitTaskId, u => new VisitTask() { ImageStudyState = command.ImageStudyState }); + + return ResponseOutput.Ok(); + } + + /// + /// 通过任务Id 获取检查模态下拉框 + /// + /// + public async Task> GetStudyModalityList(Guid visiTaskId) + { + + var list = await _visitTaskRepository.Where(t => t.Id == visiTaskId).Select(t => t.SourceSubjectVisit).SelectMany(t => t.StudyList).Select(t => new StudySeriesModality + { + StudyId = t.Id, + SeriesCount = t.SeriesCount, + StudyCode = t.StudyCode, + SeriesModalityList = t.SeriesList.Select(t => new SeriesModality { SeriesId = t.Id, Modality = t.Modality }).ToList() + + }).ToListAsync(); + + return list; + } + + /// + /// 通过选择的序列Id 数组,获取下面的Instance 路径 + /// + /// + /// + /// + [HttpPost] + public async Task> GetStudyModalityOSSPath(List seriesIdList, [FromServices] IRepository _dicomSeriesRepository) + { + return await _dicomSeriesRepository.Where(t => seriesIdList.Contains(t.Id)).SelectMany(t => t.DicomInstanceList).Select(t => new InstancePathDTO() {InstancePath= t.Path,StudyCode=t.DicomStudy.StudyCode , SopInstanceUid = t.SopInstanceUid, StudyInstanceUid = t.StudyInstanceUid} ).ToListAsync(); + } + + + /// + /// 归档接口 -new 一份 序列层级增加了一个参数VisitTaskId 用于绑定从TomTec拉取来的序列(两个人公用的影像,不应该绑定) + /// + /// + /// + /// + /// + /// + /// + /// + + [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] + public async Task AddOrUpdateArchiveStudy(NewArchiveStudyCommand incommand, + [FromServices] IRepository _studyMonitorRepository, + [FromServices] IDistributedLockProvider _distributedLockProvider, + [FromServices] IEasyCachingProvider _provider, + [FromServices] IRepository _dicomSeriesRepository, + [FromServices] IRepository _dicomInstanceRepository) + { + try + { + var trialId = incommand.TrialId; + + var studyMonitor = await _studyMonitorRepository.FirstOrDefaultAsync(t => t.Id == incommand.StudyMonitorId); + studyMonitor.UploadFinishedTime = DateTime.Now; + studyMonitor.ArchiveFinishedTime = DateTime.Now; + studyMonitor.FailedFileCount = incommand.FailedFileCount; + studyMonitor.IsSuccess = true; + + //上传 + if (studyMonitor.IsDicomReUpload == false) + { + var study = _mapper.Map(incommand.Study); + + var @lock = _distributedLockProvider.CreateLock($"StudyCode"); + + using (await @lock.AcquireAsync()) + { + //查询数据库获取最大的Code 没有记录则为0 + var dbStudyCodeIntMax = _studyRepository.Where(s => s.TrialId == trialId).Select(t => t.Code).DefaultIfEmpty().Max(); + + //获取缓存中的值 并发的时候,需要记录,已被占用的值 这样其他线程在此占用的最大的值上递增 + var cacheMaxCodeInt = _provider.Get($"{trialId}_{StaticData.CacheKey.StudyMaxCode}").Value; + + int currentNextCodeInt = cacheMaxCodeInt > dbStudyCodeIntMax ? cacheMaxCodeInt + 1 : dbStudyCodeIntMax + 1; + + study.Code = currentNextCodeInt; + study.StudyCode = AppSettings.GetCodeStr(currentNextCodeInt, nameof(DicomStudy)); + + _provider.Set($"{trialId}_{StaticData.CacheKey.StudyMaxCode}", study.Code, TimeSpan.FromMinutes(30)); + + } + + + study.Id = IdentifierHelper.CreateGuid(incommand.Study.StudyInstanceUid, incommand.TrialId.ToString()); + study.TrialId = incommand.TrialId; + study.SiteId = incommand.SiteId; + study.SubjectId = incommand.SubjectId; + study.SubjectVisitId = incommand.SubjectVisitId; + + + //特殊处理逻辑 + study.Modalities = string.Join("、", incommand.Study.SeriesList.Select(t => t.Modality).Distinct()); + SpecialArchiveStudyDeal(study); + + await _studyRepository.AddAsync(study); + + + studyMonitor.StudyId = study.Id; + studyMonitor.StudyCode = study.StudyCode; + + + foreach (var seriesItem in incommand.Study.SeriesList) + { + var series = _mapper.Map(seriesItem); + + series.Id = IdentifierHelper.CreateGuid(seriesItem.StudyInstanceUid, seriesItem.SeriesInstanceUid, incommand.TrialId.ToString()); + series.StudyId = study.Id; + + series.TrialId = incommand.TrialId; + series.SiteId = incommand.SiteId; + series.SubjectId = incommand.SubjectId; + series.SubjectVisitId = incommand.SubjectVisitId; + + await _dicomSeriesRepository.AddAsync(series); + + foreach (var instanceItem in seriesItem.InstanceList) + { + var isntance = _mapper.Map(instanceItem); + + Guid instanceId = IdentifierHelper.CreateGuid(study.StudyInstanceUid, series.SeriesInstanceUid, isntance.SopInstanceUid, study.TrialId.ToString()); + + isntance.Id = instanceId; + isntance.StudyId = study.Id; + isntance.SeriesId = series.Id; + + isntance.TrialId = incommand.TrialId; + isntance.SiteId = incommand.SiteId; + isntance.SubjectId = incommand.SubjectId; + isntance.SubjectVisitId = incommand.SubjectVisitId; + + await _dicomInstanceRepository.AddAsync(isntance); + } + } + + + + + } + else + { + + var studyId = IdentifierHelper.CreateGuid(incommand.Study.StudyInstanceUid, incommand.TrialId.ToString()); ; + + var study = await _studyRepository.FirstOrDefaultAsync(t => t.Id == studyId); + + + //特殊处理逻辑 + study.Modalities = string.Join("、", incommand.Study.SeriesList.Select(t => t.Modality).Union(study.Modalities.Split("、", StringSplitOptions.RemoveEmptyEntries)).Distinct()); + SpecialArchiveStudyDeal(study); + + + + // 少了整个序列 + + //某个序列下少了instance + foreach (var seriesItem in incommand.Study.SeriesList) + { + var seriesId = IdentifierHelper.CreateGuid(seriesItem.StudyInstanceUid, seriesItem.SeriesInstanceUid, trialId.ToString()); + + DicomSeries dicomSeries = await _dicomSeriesRepository.FirstOrDefaultAsync(t => t.Id == seriesId); + + //判断重复 + if (dicomSeries == null) + { + var series = _mapper.Map(seriesItem); + + series.Id = seriesId; + series.StudyId = study.Id; + + series.TrialId = incommand.TrialId; + series.SiteId = incommand.SiteId; + series.SubjectId = incommand.SubjectId; + series.SubjectVisitId = incommand.SubjectVisitId; + + + dicomSeries = await _dicomSeriesRepository.AddAsync(series); + + //新的序列 那么 检查的序列数量+1 + study.SeriesCount += 1; + } + else + { + //该序列掉了instance + dicomSeries.InstanceCount += seriesItem.InstanceList.Count; + } + + foreach (var instanceItem in seriesItem.InstanceList) + { + var insntance = _mapper.Map(instanceItem); + insntance.Id = IdentifierHelper.CreateGuid(insntance.StudyInstanceUid, insntance.SeriesInstanceUid, insntance.SopInstanceUid, trialId.ToString()); + insntance.StudyId = study.Id; + insntance.SeriesId = dicomSeries.Id; + + insntance.TrialId = incommand.TrialId; + insntance.SiteId = incommand.SiteId; + insntance.SubjectId = incommand.SubjectId; + insntance.SubjectVisitId = incommand.SubjectVisitId; + + await _dicomInstanceRepository.AddAsync(insntance); + } + + + // 不管是新的序列 还是 该序列 掉了Instance 重传的时候 检查的instance 数量都会增加 + study.InstanceCount += seriesItem.InstanceList.Count; + + } + + + } + + var @lock2 = _distributedLockProvider.CreateLock($"StudyCommit"); + + using (await @lock2.AcquireAsync()) + { + await _dicomInstanceRepository.SaveChangesAsync(); + } + } + catch (Exception ex) + { + + return ResponseOutput.NotOk(ex.Message); + } + finally + { + _provider.Remove($"StudyUid_{incommand.TrialId}_{incommand.Study.StudyInstanceUid}"); + } + + + + + + + + return ResponseOutput.Ok(); + } + + private void SpecialArchiveStudyDeal(DicomStudy study) + { + #region 特殊逻辑 + + + if (study.PatientBirthDate.Length == 8) + { + study.PatientBirthDate = $"{study.PatientBirthDate[0]}{study.PatientBirthDate[1]}{study.PatientBirthDate[2]}{study.PatientBirthDate[3]}-{study.PatientBirthDate[4]}{study.PatientBirthDate[5]}-{study.PatientBirthDate[6]}{study.PatientBirthDate[7]}"; + } + + var dicModalityList = _dictionaryRepository.Where(t => t.Code == "Modality").SelectMany(t => t.ChildList.Select(c => c.Value)).ToList(); + + + var modality = study.Modalities; + + var modalityForEdit = dicModalityList.Contains(modality) ? modality : String.Empty; + + if (modality == "MR") + { + modalityForEdit = "MRI"; + } + + if (modality == "PT") + { + modalityForEdit = "PET"; + } + if (modality == "PT、CT") + { + modalityForEdit = "PET-CT"; + } + + study.ModalityForEdit = modalityForEdit; + #endregion + } + } +} diff --git a/IRaCIS.Core.Application/Service/Third-partyProject/_MapConfig.cs b/IRaCIS.Core.Application/Service/Third-partyProject/_MapConfig.cs new file mode 100644 index 000000000..900ca913f --- /dev/null +++ b/IRaCIS.Core.Application/Service/Third-partyProject/_MapConfig.cs @@ -0,0 +1,29 @@ +using AutoMapper; +using AutoMapper.EquivalencyExpression; +using DocumentFormat.OpenXml.Spreadsheet; +using IRaCIS.Application.Contracts; +using IRaCIS.Core.Application.Contracts; +using IRaCIS.Core.Application.Contracts.DTO; +using IRaCIS.Core.Application.Service.Third_partyProject.DTO; +using IRaCIS.Core.Application.ViewModel; +using IRaCIS.Core.Domain.Models; +using IRaCIS.Core.Domain.Share; + +namespace IRaCIS.Core.Application.Service +{ + public class UltrasonicDicomConfig : Profile + { + public UltrasonicDicomConfig() + { + + CreateMap() + .ForMember(o => o.TrialSiteCode, t => t.MapFrom(u => u.Subject.TrialSite.TrialSiteCode)) + .ForMember(o => o.SubjectCode, t => t.MapFrom(u => u.Subject.Code)) + .ForMember(o => o.UserName, t => t.MapFrom(u => u.DoctorUser.UserName)) + .ForMember(o => o.FullName, t => t.MapFrom(u => u.DoctorUser.FullName)) + .ForMember(o => o.TrialReadingCriterionName, t => t.MapFrom(u => u.TrialReadingCriterion.CriterionName)) + ; + } + } + +} diff --git a/IRaCIS.Core.Application/Service/Visit/SubjectVisitService.cs b/IRaCIS.Core.Application/Service/Visit/SubjectVisitService.cs index 2c7f9e564..695454728 100644 --- a/IRaCIS.Core.Application/Service/Visit/SubjectVisitService.cs +++ b/IRaCIS.Core.Application/Service/Visit/SubjectVisitService.cs @@ -267,8 +267,7 @@ namespace IRaCIS.Core.Application.Services foreach (var t in studyList) { t.SeriesList = await _repository.Where(s => s.StudyId == t.StudyId) - .WhereIf(isReading == 1, s => s.IsReading).OrderBy(s => s.SeriesNumber). - ThenBy(s => s.SeriesTime) + .WhereIf(isReading == 1, s => s.IsReading).OrderBy(s => s.SeriesNumber).ThenBy(s => s.SeriesTime) .ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); diff --git a/IRaCIS.Core.Domain.Share/Reading/ReadEnum.cs b/IRaCIS.Core.Domain.Share/Reading/ReadEnum.cs index f8e93eb38..2fccb06c7 100644 --- a/IRaCIS.Core.Domain.Share/Reading/ReadEnum.cs +++ b/IRaCIS.Core.Domain.Share/Reading/ReadEnum.cs @@ -67,6 +67,18 @@ namespace IRaCIS.Core.Domain.Share } + /// + /// 分组分类 + /// + public enum GroupClassify + { + /// + /// 质量问题 + /// + QualityProblem = 1, + + } + /// /// 临床表格问题标识 /// @@ -832,7 +844,7 @@ namespace IRaCIS.Core.Domain.Share Normal = 1, /// - /// 缓解 + /// 部分缓解 /// Remission = 2, @@ -854,10 +866,11 @@ namespace IRaCIS.Core.Domain.Share /// /// 肿大 /// - Swelling = 5, + Swelling = 6, } + /// /// 是(1)或否(0) /// @@ -893,38 +906,12 @@ namespace IRaCIS.Core.Domain.Share /// /// 稳定 /// - Stabilization = 2, + Tumefaction = 2, /// - /// 显著增大 + /// 稳定 /// - Increase = 3, - - /// - /// 无法评估 - /// - NotEvaluable = 4, - - } - /// - /// 脾脏状态 - /// - public enum SpleenState - { - /// - /// 正常 - /// - Normal = 1, - - /// - /// 肿大 - /// - Swelling = 2, - - /// - /// 部分缓解稳定 - /// - PartialRemission = 3, + Stabilization = 3, /// /// 显著增大 @@ -936,6 +923,47 @@ namespace IRaCIS.Core.Domain.Share /// NotEvaluable = 5, + } + /// + /// 脾脏状态 + /// + public enum SpleenState + { + /// + /// NA + /// + NA = -1, + + /// + /// 正常 + /// + Normal = 1, + + /// + /// 部分缓解 + /// + Remission = 2, + + /// + /// 稳定 + /// + Stabilization = 3, + + /// + /// 显著增大 + /// + Increase = 4, + + /// + /// 无法评估 + /// + NotEvaluable = 5, + + /// + /// 肿大 + /// + Swelling = 6, + } /// @@ -2219,12 +2247,10 @@ public enum SUVChangeVSBaseline - - - /// - /// PET 5PS 评分 - /// - public enum PET5PSScore +/// +/// PET 5PS 评分 +/// +public enum PET5PSScore { /// /// 5分 @@ -2244,7 +2270,7 @@ public enum SUVChangeVSBaseline /// /// 2分 /// - Two = 5, + Two = 2, /// /// 1分 @@ -2263,6 +2289,22 @@ public enum SUVChangeVSBaseline } + /// + /// 计算触发 + /// + public enum ComputationTrigger + { + /// + /// 病灶 + /// + Lesion=0, + + /// + /// 报告 + /// + Report=1, + } + /// /// 新靶病灶评估 /// diff --git a/IRaCIS.Core.Domain/Allocation/VisitTask.cs b/IRaCIS.Core.Domain/Allocation/VisitTask.cs index 73daba8ce..bbc4b3fa8 100644 --- a/IRaCIS.Core.Domain/Allocation/VisitTask.cs +++ b/IRaCIS.Core.Domain/Allocation/VisitTask.cs @@ -426,5 +426,8 @@ namespace IRaCIS.Core.Domain.Models } } + + public int ImageStudyState { get; set; } + } } diff --git a/IRaCIS.Core.Domain/Dcotor/Attachment.cs b/IRaCIS.Core.Domain/Dcotor/Attachment.cs index bf61dd5ee..1a97bfb64 100644 --- a/IRaCIS.Core.Domain/Dcotor/Attachment.cs +++ b/IRaCIS.Core.Domain/Dcotor/Attachment.cs @@ -16,7 +16,11 @@ namespace IRaCIS.Core.Domain.Models [Table("Attachment")] public partial class Attachment : Entity, IAuditAdd { - public Guid? DoctorId { get; set; } + + [JsonIgnore] + public Doctor Doctor { get; set; } + + public Guid DoctorId { get; set; } public string Type { get; set; } public bool IsOfficial { get; set; } = false; public string Path { get; set; } = string.Empty; diff --git a/IRaCIS.Core.Domain/Image/DicomInstance.cs b/IRaCIS.Core.Domain/Image/DicomInstance.cs index a05f3bbf0..bce1777cf 100644 --- a/IRaCIS.Core.Domain/Image/DicomInstance.cs +++ b/IRaCIS.Core.Domain/Image/DicomInstance.cs @@ -11,6 +11,10 @@ namespace IRaCIS.Core.Domain.Models [ForeignKey("SeriesId")] public DicomSeries DicomSerie { get; set; } + [JsonIgnore] + [ForeignKey("StudyId")] + public DicomStudy DicomStudy { get; set; } + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public Guid SeqId { get; set; } diff --git a/IRaCIS.Core.Domain/Image/DicomSeries.cs b/IRaCIS.Core.Domain/Image/DicomSeries.cs index 46820e012..d59070e40 100644 --- a/IRaCIS.Core.Domain/Image/DicomSeries.cs +++ b/IRaCIS.Core.Domain/Image/DicomSeries.cs @@ -61,7 +61,9 @@ namespace IRaCIS.Core.Domain.Models public bool IsDeleted {get;set;} public bool IsReading { get; set; } = true; - public string IamgeResizePath { get; set; }=string.Empty; + public string ImageResizePath { get; set; }=string.Empty; + + public Guid? VisitTaskId { get; set; } } } diff --git a/IRaCIS.Core.Domain/Reading/ReadingCriterionQuestion/ReadingQuestionSystem.cs b/IRaCIS.Core.Domain/Reading/ReadingCriterionQuestion/ReadingQuestionSystem.cs index 764d72254..1b7e453c3 100644 --- a/IRaCIS.Core.Domain/Reading/ReadingCriterionQuestion/ReadingQuestionSystem.cs +++ b/IRaCIS.Core.Domain/Reading/ReadingCriterionQuestion/ReadingQuestionSystem.cs @@ -203,10 +203,15 @@ namespace IRaCIS.Core.Domain.Models /// public string? FileType { get; set; } - /// - /// 问题分类 - /// - public QuestionClassify? QuestionClassify { get; set; } + /// + /// 分组分类 + /// + public GroupClassify? GroupClassify { get; set; } + + /// + /// 问题分类 + /// + public QuestionClassify? QuestionClassify { get; set; } [JsonIgnore] [ForeignKey("GroupId")] diff --git a/IRaCIS.Core.Domain/Reading/ReadingCriterionQuestion/ReadingQuestionTrial.cs b/IRaCIS.Core.Domain/Reading/ReadingCriterionQuestion/ReadingQuestionTrial.cs index 959790ed5..0ffbd778d 100644 --- a/IRaCIS.Core.Domain/Reading/ReadingCriterionQuestion/ReadingQuestionTrial.cs +++ b/IRaCIS.Core.Domain/Reading/ReadingCriterionQuestion/ReadingQuestionTrial.cs @@ -271,6 +271,13 @@ namespace IRaCIS.Core.Domain.Models /// public Guid? GroupId { get; set; } + + /// + /// 分组分类 + /// + public GroupClassify? GroupClassify { get; set; } + + /// /// 问题分类 /// diff --git a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs index 068df0e6d..af07c7462 100644 --- a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs +++ b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs @@ -589,6 +589,12 @@ namespace IRaCIS.Core.Infra.EFCore throw new DBSaveFailedException("SQL 事务失败,请检查环境。"); } + catch (Exception ex) + { + _logger.LogError(ex.InnerException is null ? ex.Message : ex.InnerException?.Message); + + throw new DBSaveFailedException("数据保存异常。"); + } }