From 36c354c8f08709b91b01819dea9352ee6cec5a72 Mon Sep 17 00:00:00 2001 From: hang <872297557@qq.com> Date: Wed, 11 Sep 2024 14:41:04 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=B8=8B=E8=BD=BD=E7=9B=91?= =?UTF-8?q?=E6=8E=A7=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IRaCIS.Core.Application.xml | 17 +++- .../ImageAndDoc/DTO/UnionStudyViewDodel.cs | 44 +++++++++ .../ImageAndDoc/DownloadAndUploadService.cs | 96 ++++++++++++++++--- .../Service/ImageAndDoc/_MapConfig.cs | 5 +- IRaCIS.Core.Domain/BaseModel/Entity.cs | 4 + .../Image/TrialImageDownload.cs | 50 ++++++++++ IRaCIS.Core.Domain/Management/User.cs | 3 +- .../Context/IRaCISDBContext.cs | 4 + .../EntityConfigration/StudyConfigration.cs | 42 -------- .../EntityConfigration/SubjectConfigration.cs | 13 ++- .../TrialUserConfigration.cs | 2 - .../VisitTaskConfigration.cs | 2 - .../Interceptor/AuditEntityInterceptor.cs | 13 ++- .../Extention/StringExtension.cs | 4 + 14 files changed, 227 insertions(+), 72 deletions(-) create mode 100644 IRaCIS.Core.Domain/Image/TrialImageDownload.cs delete mode 100644 IRaCIS.Core.Infra.EFCore/EntityConfigration/StudyConfigration.cs diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml index a9cf98e57..e6f523192 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -1031,13 +1031,12 @@ - + IR 阅片页面获取下载检查的信息 会根据标准进行过滤检查,(后端要考虑到一致性分析 subjectCode的问题) 检查在访视下面,所以需要传递下载的访视Id,另外下载访视下面那些检查,就把访视下的对应的检查Id 丢到数组里就好 - @@ -1047,6 +1046,20 @@ + + + 影像下载成功回调 + + + + + + + 项目影像下载监控列表 + + + + 打包和匿名化影像 默认是匿名化打包,也可以不匿名化打包 diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs index 7d82d7ec2..d02f7a345 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs @@ -1,4 +1,5 @@ using IRaCIS.Core.Application.Service.ImageAndDoc.DTO; +using IRaCIS.Core.Domain.Share; using Newtonsoft.Json; using System; using System.Collections.Generic; @@ -551,6 +552,49 @@ namespace IRaCIS.Core.Application.Contracts } + public class TrialImageDownloadView + { + public Guid TrialId { get; set; } + + public string SubjectCode { get; set; } + + public bool IsSuccess { get; set; } + + public DateTime DownloadStartTime { get; set; } + public DateTime? DownloadEndTime { get; set; } + + public string VisitName { get; set; } + + public ImageType ImageType { get; set; } + + public int NoneDicomStudyCount { get; set; } + + public int DicomStudyCount { get; set; } + + public int ImageCount { get; set; } + public long ImageSize { get; set; } + + + public string UserName { get; set; } + + public string UserFullName { get; set; } + public DateTime CreateTime { get; set; } + + } + + public class TrialIamgeDownQuery:PageInput + { + [NotDefault] + public Guid TrialId { get; set; } + + public string? SubjectCode { get; set; } + + public ImageType? ImageType { get; set; } + + public UserTypeEnum? UserType { get; set; } + + public bool? IsSuccess { get; set; } + } public class SubjectVisitTaskInfo { diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs index 41d195d93..94cb36c6b 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs @@ -49,7 +49,9 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc IRepository _readingQuestionCriterionTrialRepository, IRepository _noneDicomStudyReposiotry, IRepository _noneDicomStudyFileReposiotry, - IDistributedLockProvider _distributedLockProvider) : BaseService, IDownloadAndUploadService + IDistributedLockProvider _distributedLockProvider, + IRepository _trialImageDownloadRepository, + IRepository _subjectRepository) : BaseService, IDownloadAndUploadService { @@ -220,9 +222,6 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc } - - - [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] public async Task PreArchiveDicomStudy(PriArchiveTaskStudyCommand preArchiveStudyCommand) @@ -678,11 +677,14 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc var isQueryDicom = inQuery.DicomStudyIdList.Count > 0; var isQueryNoneDicom = inQuery.NoneDicomStudyIdList.Count > 0; + var imageType = (isQueryDicom && isQueryNoneDicom) ? ImageType.DicomAndNoneDicom : (isQueryDicom ? ImageType.Dicom : ImageType.NoneDicom); + var query = from sv in _subjectVisitRepository.Where(t => t.Id == inQuery.SubjectVisitId) select new { + TrialId = sv.TrialId, SubjectCode = sv.Subject.Code, VisitName = sv.VisitName, @@ -719,14 +721,31 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc { file.FileName, file.Path, - file.FileType + file.FileType, + file.FileSize, }) }).ToList() }; var result = query.FirstOrDefault(); - return ResponseOutput.Ok(result); + var preDownloadInfo = new TrialImageDownload() + { + Id = NewId.NextSequentialGuid(), + TrialId = result.TrialId, + SubjectCode = result.SubjectCode, + DownloadStartTime = DateTime.Now, + IsSuccess = false, + ImageType = imageType, + VisitName = string.Join(" | ", result.VisitName), + NoneDicomStudyCount = result.NoneDicomStudyList.Count(), + DicomStudyCount = result.StudyList.Count(), + ImageCount = result.StudyList.Sum(s => s.SeriesList.Sum(s => s.InstanceList.Count())) + result.NoneDicomStudyList.Sum(s => s.FileList.Count()), + ImageSize = result.StudyList.Sum(t => t.SeriesList.Sum(s => s.InstanceList.Sum(i => i.FileSize))) + result.NoneDicomStudyList.Sum(t => t.FileList.Sum(s => s.FileSize)) + ?? 0 + }; + + return ResponseOutput.Ok(result, preDownloadInfo.Id); } @@ -817,17 +836,18 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc /// 检查在访视下面,所以需要传递下载的访视Id,另外下载访视下面那些检查,就把访视下的对应的检查Id 丢到数组里就好 /// /// - /// /// [HttpPost] - public async Task GetIRReadingDownloadStudyInfo(IRDownloadQuery inQuery, [FromServices] IRepository _subjectRepository) + public async Task GetIRReadingDownloadStudyInfo(IRDownloadQuery inQuery) { var info = await _readingQuestionCriterionTrialRepository.Where(t => t.Id == inQuery.TrialReadingCriterionId) - .Select(t => new { t.IsImageFilter, t.CriterionModalitys }).FirstNotNullAsync(); + .Select(t => new { t.IsImageFilter, t.CriterionModalitys, t.TrialId }).FirstNotNullAsync(); var isQueryDicom = inQuery.DicomStudyIdList.Count > 0; var isQueryNoneDicom = inQuery.NoneDicomStudyIdList.Count > 0; + var imageType = (isQueryDicom && isQueryNoneDicom) ? ImageType.DicomAndNoneDicom : (isQueryDicom ? ImageType.Dicom : ImageType.NoneDicom); + var taskIdList = inQuery.SubjectVisitTaskList.Select(t => t.TaskId).ToList(); var subjectVisitIdList = inQuery.SubjectVisitTaskList.Select(t => t.SubjectVisitId).ToList(); @@ -856,7 +876,8 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc InstancePathList = z.DicomInstanceList.Select(k => new { - k.Path + k.Path, + k.FileSize }) }) @@ -874,7 +895,8 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc { file.FileName, file.Path, - file.FileType + file.FileType, + file.FileSize }) }) }; @@ -885,7 +907,24 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc - return ResponseOutput.Ok(result); + var preDownloadInfo = new TrialImageDownload() + { + Id = NewId.NextSequentialGuid(), + TrialId = info.TrialId, + SubjectCode = inQuery.SubjectCode, + DownloadStartTime = DateTime.Now, + IsSuccess = false, + ImageType = imageType, + VisitName = string.Join(" | ", result.Select(t => t.VisitName).OrderBy(t => t).ToList()), + NoneDicomStudyCount = result.Sum(t => t.NoneDicomStudyList.Count()), + DicomStudyCount = result.Sum(t => t.StudyList.Count()), + ImageCount = result.Sum(t => t.StudyList.Sum(s => s.SeriesList.Sum(s => s.InstancePathList.Count())) + t.NoneDicomStudyList.Sum(s => s.FileList.Count())), + ImageSize = result.Sum(t => t.StudyList.Sum(t => t.SeriesList.Sum(s => s.InstancePathList.Sum(i => i.FileSize))) + t.NoneDicomStudyList.Sum(t => t.FileList.Sum(s => s.FileSize)) + ) ?? 0 + }; + + await _trialImageDownloadRepository.AddAsync(preDownloadInfo); + return ResponseOutput.Ok(result, preDownloadInfo.Id); } /// @@ -937,6 +976,36 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc + /// + /// 影像下载成功回调 + /// + /// + /// + public async Task DownloadImageSuccess(Guid trialImageDownloadId) + { + await _trialImageDownloadRepository.UpdatePartialFromQueryAsync(t => t.Id == trialImageDownloadId, u => new TrialImageDownload() + { DownloadEndTime = DateTime.Now, IsSuccess = true }, true); + return ResponseOutput.Ok(); + } + + /// + /// 项目影像下载监控列表 + /// + /// + /// + [HttpPost] + public async Task> GetTrialDownloadList(TrialIamgeDownQuery inQuery) + { + var query = _trialImageDownloadRepository.Where(t => t.TrialId == inQuery.TrialId) + .WhereIf(inQuery.SubjectCode.IsNotNullOrEmpty(), t => t.SubjectCode.Contains(inQuery.SubjectCode)) + .WhereIf(inQuery.ImageType != null, t => t.ImageType == inQuery.ImageType) + .WhereIf(inQuery.UserType != null, t => t.CreateUser.UserTypeEnum == inQuery.UserType) + .WhereIf(inQuery.IsSuccess != null, t => t.IsSuccess == inQuery.IsSuccess) + .ProjectTo(_mapper.ConfigurationProvider); + + return await query.ToPagedListAsync(inQuery); + } + #region 之前后端下载废弃 /// @@ -1361,9 +1430,6 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc } #endregion - - - #region 按照任务为维度 展示上传的列表 废弃 /// /// IR 影像上传任务列表 --old 20240903 界面调整,现在先废弃 diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/_MapConfig.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/_MapConfig.cs index 78b0c12ea..3e902c646 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/_MapConfig.cs @@ -143,7 +143,10 @@ namespace IRaCIS.Core.Application.Service .ForMember(d => d.NoneDicomStudyList, u => u.MapFrom(s => s.SourceSubjectVisit.NoneDicomStudyList)) ; - + CreateMap() + .ForMember(d => d.UserFullName, u => u.MapFrom(s => s.CreateUser.FullName)) + .ForMember(d => d.UserName, u => u.MapFrom(s => s.CreateUser.UserName)); + } } diff --git a/IRaCIS.Core.Domain/BaseModel/Entity.cs b/IRaCIS.Core.Domain/BaseModel/Entity.cs index 26c0b0fc9..76ba5c65d 100644 --- a/IRaCIS.Core.Domain/BaseModel/Entity.cs +++ b/IRaCIS.Core.Domain/BaseModel/Entity.cs @@ -86,6 +86,10 @@ namespace IRaCIS.Core.Domain.Models public DateTime CreateTime { get; set; } public Guid UpdateUserId { get; set; } public DateTime UpdateTime { get; set; } + + //[ForeignKey("CreateUserId")] + //[JsonIgnore] + //public User CreateUser { get; set; } } diff --git a/IRaCIS.Core.Domain/Image/TrialImageDownload.cs b/IRaCIS.Core.Domain/Image/TrialImageDownload.cs new file mode 100644 index 000000000..bc9a18571 --- /dev/null +++ b/IRaCIS.Core.Domain/Image/TrialImageDownload.cs @@ -0,0 +1,50 @@ +using IRaCIS.Core.Domain.Models; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace IRaCIS.Core.Domain.Models +{ + [Table("TrialImageDownload")] + public class TrialImageDownload : BaseFullAuditEntity + { + #region 导航属性 + [JsonIgnore] + public Trial Trial { get; set; } + + [JsonIgnore] + public User CreateUser { get; set; } + #endregion + + public Guid TrialId { get; set; } + + public string SubjectCode { get; set; } + + public bool IsSuccess { get; set; } + + public DateTime DownloadStartTime { get; set; } + public DateTime? DownloadEndTime { get; set; } + + public string VisitName { get; set; } + + public ImageType ImageType { get; set; } + + public int NoneDicomStudyCount { get; set; } + + public int DicomStudyCount { get; set; } + + public int ImageCount { get; set; } + public long ImageSize { get; set; } + + } + + public enum ImageType + { + Dicom = 1, + NoneDicom = 2, + DicomAndNoneDicom = 3 + }; +} diff --git a/IRaCIS.Core.Domain/Management/User.cs b/IRaCIS.Core.Domain/Management/User.cs index c024f2824..a70f563e1 100644 --- a/IRaCIS.Core.Domain/Management/User.cs +++ b/IRaCIS.Core.Domain/Management/User.cs @@ -16,8 +16,7 @@ namespace IRaCIS.Core.Domain.Models [JsonIgnore] public List SystemDocConfirmedList { get; set; } - [JsonIgnore] - public List UserDoctors { get; set; } = new List(); + [JsonIgnore] public List UserTrials { get; set; } = new List(); diff --git a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs index d6673ef2e..bdf501aa4 100644 --- a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs +++ b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs @@ -527,6 +527,10 @@ namespace IRaCIS.Core.Infra.EFCore public virtual DbSet EnrollReadingCriterion { get; set; } #endregion + public virtual DbSet TrialImageDownload { get; set; } + + + } diff --git a/IRaCIS.Core.Infra.EFCore/EntityConfigration/StudyConfigration.cs b/IRaCIS.Core.Infra.EFCore/EntityConfigration/StudyConfigration.cs deleted file mode 100644 index 5fa1e61c3..000000000 --- a/IRaCIS.Core.Infra.EFCore/EntityConfigration/StudyConfigration.cs +++ /dev/null @@ -1,42 +0,0 @@ -using IRaCIS.Core.Domain.Models; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - - -namespace IRaCIS.Core.Infra.EFCore.EntityConfigration -{ - //public class StudyConfigration : IEntityTypeConfiguration - //{ - - // /// - // /// 一个外键,关联多个表 ReadingId - // /// - // /// - // public void Configure(EntityTypeBuilder builder) - // { - - // builder - // .HasMany(s => s.ReadingClinicalDataList) - // .WithOne(c => c.DicomStudy) - // .HasForeignKey(s => new { s.StudyId }) - // .HasPrincipalKey(c => new { c.Id }); - - - // builder - // .HasMany(s => s.ReadingConsistentClinicalDataList) - // .WithOne(c => c.DicomStudy) - // .HasForeignKey(s => new { s.StudyId }) - // .HasPrincipalKey(c => new { c.Id }); - - // } - //} - - //public class UserConfigration : IEntityTypeConfiguration - //{ - // public void Configure(EntityTypeBuilder builder) - // { - // //对于阅片人来讲,会有很多任务 - // builder.HasMany(t => t.VisitTaskList).WithOne(t => t.DoctorUser).HasForeignKey(t => t.DoctorUserId).IsRequired(false); - // } - //} -} diff --git a/IRaCIS.Core.Infra.EFCore/EntityConfigration/SubjectConfigration.cs b/IRaCIS.Core.Infra.EFCore/EntityConfigration/SubjectConfigration.cs index 1fb1584fd..1dff62f9b 100644 --- a/IRaCIS.Core.Infra.EFCore/EntityConfigration/SubjectConfigration.cs +++ b/IRaCIS.Core.Infra.EFCore/EntityConfigration/SubjectConfigration.cs @@ -9,7 +9,6 @@ namespace IRaCIS.Core.Infra.EFCore.EntityConfigration { public void Configure(EntityTypeBuilder builder) { - //不能同时配置一对多 和一对一 但是有时表要存储多的最新的 比如受试者 最新的访视 在这里要显示配置 builder.HasOne(s => s.LatestSubjectVisit).WithMany().HasForeignKey(t => t.LatestSubjectVisitId); builder.HasOne(s => s.FinalSubjectVisit).WithMany().HasForeignKey(t => t.FinalSubjectVisitId); @@ -20,10 +19,8 @@ namespace IRaCIS.Core.Infra.EFCore.EntityConfigration { public void Configure(EntityTypeBuilder builder) { - //自身同时存在一对多 和一对一的关系,配置一对多的就可以,一对一 不用配置,有点奇怪 builder.HasMany(t => t.ChildList).WithOne(t => t.Parent).HasForeignKey(d => d.ParentId); - } } @@ -46,4 +43,14 @@ namespace IRaCIS.Core.Infra.EFCore.EntityConfigration builder.HasMany(t => t.EarlierSubjectUserList).WithOne(t => t.ReplacedSubjectUser).HasForeignKey(t => t.ReplacedSubjectUserId); } } + + public class UserConfigration : IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + builder.HasMany(t => t.VisitTaskList).WithOne(t => t.DoctorUser).HasForeignKey(t => t.DoctorUserId); + + //builder.HasOne(t => t.Doctor).WithOne(t => t.User); + } + } } diff --git a/IRaCIS.Core.Infra.EFCore/EntityConfigration/TrialUserConfigration.cs b/IRaCIS.Core.Infra.EFCore/EntityConfigration/TrialUserConfigration.cs index c4f782f0c..98ccf65cd 100644 --- a/IRaCIS.Core.Infra.EFCore/EntityConfigration/TrialUserConfigration.cs +++ b/IRaCIS.Core.Infra.EFCore/EntityConfigration/TrialUserConfigration.cs @@ -5,8 +5,6 @@ using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace IRaCIS.Core.Infra.EFCore.EntityConfigration { - - public class SubjectCriteriaEvaluationConfigration : IEntityTypeConfiguration { diff --git a/IRaCIS.Core.Infra.EFCore/EntityConfigration/VisitTaskConfigration.cs b/IRaCIS.Core.Infra.EFCore/EntityConfigration/VisitTaskConfigration.cs index 0e15a0649..2f355ef5e 100644 --- a/IRaCIS.Core.Infra.EFCore/EntityConfigration/VisitTaskConfigration.cs +++ b/IRaCIS.Core.Infra.EFCore/EntityConfigration/VisitTaskConfigration.cs @@ -25,8 +25,6 @@ namespace IRaCIS.Core.Infra.EFCore.EntityConfigration //subject 删除了,但是任务没删除,导致的查询问题 builder.HasQueryFilter(b => b.Subject.IsDeleted == false); - //builder.HasOne(t => t.Subject).WithMany(s => s.SubjectVisitTaskList).HasForeignKey(t => t.SubjectId); - //builder.HasMany(t => t.TaskMedicalReviewList).WithOne(t => t.VisitTask).HasForeignKey(t => t.VisitTaskId); } } public class ReadingQuestionTrialConfigration : IEntityTypeConfiguration diff --git a/IRaCIS.Core.Infra.EFCore/Interceptor/AuditEntityInterceptor.cs b/IRaCIS.Core.Infra.EFCore/Interceptor/AuditEntityInterceptor.cs index 6f49c3b84..3ec49f294 100644 --- a/IRaCIS.Core.Infra.EFCore/Interceptor/AuditEntityInterceptor.cs +++ b/IRaCIS.Core.Infra.EFCore/Interceptor/AuditEntityInterceptor.cs @@ -96,8 +96,11 @@ public class AuditEntityInterceptor(IUserInfo _userInfo, ILogger 类型 public static bool IsNullOrEmpty(this IEnumerable enumerable)