diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml index f9ea4747d..26e1bd3ed 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -549,20 +549,6 @@ - - - 项目影像后台下载,不打包 - - - - - - - 项目影像后台下载,不打包 - - - - 系统模板文档配置表 @@ -1067,6 +1053,27 @@ PublishLogService + + + 项目影像后台下载,不打包 + + + + + + + 项目影像后台下载,不打包 + + + + + + + 后端api swagger 下载项目影像 + + + + 医生文档关联关系维护 @@ -2047,6 +2054,14 @@ + + + 更新后处理上传的检查modality + + + + + 影像下载成功回调 @@ -2061,12 +2076,18 @@ - + - 更新后处理上传的检查modality + 获取项目影像统计,有影像的subject 数量 访视数量 - - + + + + + + 批量勾选访视 进行下载 + + @@ -16080,6 +16101,13 @@ 系统邮件配置表 + + + 批量更新邮件主题中英文 + + + + ISystemBasicDataService diff --git a/IRaCIS.Core.Application/Service/Common/DTO/EmailNoticeConfigViewModel.cs b/IRaCIS.Core.Application/Service/Common/DTO/EmailNoticeConfigViewModel.cs index c36c3cbac..a6ae722e9 100644 --- a/IRaCIS.Core.Application/Service/Common/DTO/EmailNoticeConfigViewModel.cs +++ b/IRaCIS.Core.Application/Service/Common/DTO/EmailNoticeConfigViewModel.cs @@ -143,6 +143,17 @@ namespace IRaCIS.Core.Application.Contracts } + public class BatchUpdateEmailTopicCommand + { + [NotDefault] + public Guid Id { get; set; } + + public string EmailTopic { get; set; } = string.Empty; + + public string EmailTopicCN { get; set; } = string.Empty; + } + + public class EmailNoticeConfigExportDto { public Guid? Id { get; set; } diff --git a/IRaCIS.Core.Application/Service/Common/EmailNoticeConfigService.cs b/IRaCIS.Core.Application/Service/Common/EmailNoticeConfigService.cs index 0096f4495..e6f856a0e 100644 --- a/IRaCIS.Core.Application/Service/Common/EmailNoticeConfigService.cs +++ b/IRaCIS.Core.Application/Service/Common/EmailNoticeConfigService.cs @@ -41,6 +41,44 @@ namespace IRaCIS.Core.Application.Contracts return await emailNoticeConfigQueryable.ToPagedListAsync(inQuery); } + /// + /// 批量更新邮件主题中英文 + /// + /// + /// + public async Task BatchUpdateEmail(List inCommandList) + { + var findIdList = inCommandList.Select(x => x.Id).ToList(); + + var regex = new Regex(@"\{\s*\d+\s*\}"); + + foreach (var inCommand in inCommandList) + { + if (regex.Matches($"{inCommand.EmailTopic}{inCommand.EmailTopicCN}") + .Any(t => t.Value.Contains(" "))) + { + //邮件模板占位符不允许有空格,请核查占位符的地方 + return ResponseOutput.NotOk(I18n.T("EmailNoticeConfig_ContainEmpty")); + } + } + + var list = _emailNoticeConfigrepository.Where(t => findIdList.Contains(t.Id), true).ToList(); + + foreach (var item in list) + { + var exist = inCommandList.FirstOrDefault(t => t.Id == item.Id); + if (exist != null) + { + item.EmailTopic = exist.EmailTopic; + item.EmailTopicCN = exist.EmailTopicCN; + } + } + + await _emailNoticeConfigrepository.SaveChangesAsync(); + + + return ResponseOutput.Ok(); + } public async Task AddOrUpdateEmailNoticeConfig(EmailNoticeConfigAddOrEdit addOrEditEmailNoticeConfig) { diff --git a/IRaCIS.Core.Application/Service/Common/BackDownloadService.cs b/IRaCIS.Core.Application/Service/Common/TrialImageDownloadService.cs similarity index 91% rename from IRaCIS.Core.Application/Service/Common/BackDownloadService.cs rename to IRaCIS.Core.Application/Service/Common/TrialImageDownloadService.cs index 05a2af38c..dfe3cf445 100644 --- a/IRaCIS.Core.Application/Service/Common/BackDownloadService.cs +++ b/IRaCIS.Core.Application/Service/Common/TrialImageDownloadService.cs @@ -22,20 +22,31 @@ namespace IRaCIS.Core.Application.Service /// /// /// - [AllowAnonymous] [ApiExplorerSettings(GroupName = "Common")] - public class BackDownloadService(IRepository _trialRepository, IOSSService _oSSService, IWebHostEnvironment _hostEnvironment) : BaseService + public class TrialImageDownloadService(IRepository _trialRepository, IOSSService _oSSService, IWebHostEnvironment _hostEnvironment) : BaseService { + + + + + + /// + /// 后端api swagger 下载项目影像 + /// + /// + /// + [HttpPost] + [AllowAnonymous] public async Task DownloadTrialImage(Guid trialId) { - + var subjectCodeList = new List() { "S040001", "S140001", "S190002" }; var downloadInfo = _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo, - VisitList = t.SubjectVisitList.Select(sv => new + VisitList = t.SubjectVisitList.Where(t=>subjectCodeList.Contains(t.Subject.Code)).Select(sv => new { TrialSiteCode = sv.TrialSite.TrialSiteCode, SubjectCode = sv.Subject.Code, diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs index ab5eff287..81af79674 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs @@ -546,6 +546,110 @@ namespace IRaCIS.Core.Application.Contracts } + public class TrialExportImageCommand + { + [NotDefault] + public Guid TrialId { get; set; } + + public List SubjectVisitIdList { get; set; } + + + public bool IsKeyImage { get; set; } + } + + + public class TrialVisitImageQuery : PageInput + { + [NotDefault] + public Guid TrialId { get; set; } + + + public Guid? TrialSiteId { get; set; } + + public string? SubjectCode { get; set; } + + public DateTime? BeginScanDate { get; set; } + public DateTime? EndScanDate { get; set; } + } + public class TrialVisitImageStatView + { + public Guid TrialId { get; set; } + + public Guid SubjectVisitId { get; set; } + + public Guid TrialSiteId { get; set; } + + public string TrialSiteCode { get; set; } + + public string SubjectCode { get; set; } + + public string VisitName { get; set; } + + public decimal VisitNum { get; set; } + + public DateTime? EarliestScanDate { get; set; } + public DateTime? LatestScanDate { get; set; } + + + + public int TotalStudyCount { get; set; } + + public int TotalImageCount { get; set; } + + public long? TotalImageSize { get; set; } + + public string TotalImageSizeStr => TotalImageSize.HasValue + ? $"{TotalImageSize.Value / 1024d / 1024d:F3} MB" + : "0.000 MB"; + + + #region 废弃,为了字段排序 + //public int TotalStudyCount => DicomStudyCount + NoneDicomStudyCount; + + //public int TotalImageCount => DicomImageCount + NoneDicomImageCount; + + //public long? TotalImageSize => DicomImageSize + NoneDicomImageSize; + + //public int DicomStudyCount { get; set; } + //public int DicomImageCount { get; set; } + //public long? DicomImageSize { get; set; } + + + //public int NoneDicomStudyCount { get; set; } + //public int NoneDicomImageCount { get; set; } + //public long? NoneDicomImageSize { get; set; } + + #endregion + + + } + + + public class TrialImageStatInfo + { + public int SubjectCount { get; set; } + + public int SubjectVisitCount { get; set; } + + public long? TotalImageSize { get; set; } + + + public string TotalImageSizeStr => TotalImageSize.HasValue + ? $"{TotalImageSize.Value / 1024d / 1024d:F3} MB" + : "0.000 MB"; + + + public string SubjectImageAVGSizeStr => TotalImageSize.HasValue + ? $"{TotalImageSize.Value / SubjectCount / 1024d / 1024d:F3} MB" + : "0.000 MB"; + + + public string SubjectVisitImageAVGSizeStr => TotalImageSize.HasValue + ? $"{TotalImageSize.Value / SubjectVisitCount / 1024d / 1024d:F3} MB" + : "0.000 MB"; + + + } public class TrialImageDownloadView { public Guid TrialId { get; set; } diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs index 494022bf3..b9175ac2b 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs @@ -1117,7 +1117,18 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc } - + /// + /// 更新后处理上传的检查modality + /// + /// + /// + /// + [HttpPut] + public async Task UpdateTaskStudyModality(Guid taskStudyId, string modality) + { + await _taskStudyRepository.UpdatePartialFromQueryAsync(t => t.Id == taskStudyId, u => new TaskStudy() { ModalityForEdit = modality }, true); + return ResponseOutput.Ok(); + } /// /// 影像下载成功回调 @@ -1154,19 +1165,174 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc return await query.ToPagedListAsync(inQuery); } - /// - /// 更新后处理上传的检查modality - /// - /// - /// - /// - [HttpPut] - public async Task UpdateTaskStudyModality(Guid taskStudyId, string modality) + + + #region 影像汇总页面 + + public async Task>> GetTrialVisitImageStatList(TrialVisitImageQuery inQuery) { - await _taskStudyRepository.UpdatePartialFromQueryAsync(t => t.Id == taskStudyId, u => new TaskStudy() { ModalityForEdit = modality }, true); - return ResponseOutput.Ok(); + var query = _subjectVisitRepository.Where(t => t.TrialId == inQuery.TrialId) + .WhereIf(inQuery.TrialSiteId != null, t => t.TrialSiteId == inQuery.TrialSiteId) + .WhereIf(inQuery.SubjectCode.IsNotNullOrEmpty(), t => t.Subject.Code.Contains(inQuery.SubjectCode)) + .WhereIf(inQuery.BeginScanDate != null, t => t.LatestScanDate >= inQuery.BeginScanDate) + .WhereIf(inQuery.EndScanDate != null, t => t.LatestScanDate == inQuery.EndScanDate) + .Select(t => new TrialVisitImageStatView() + { + TrialId = t.TrialId, + SubjectCode = t.Subject.Code, + TrialSiteCode = t.TrialSite.TrialSiteCode, + TrialSiteId = t.TrialSiteId, + VisitName = t.VisitName, + VisitNum = t.VisitNum, + EarliestScanDate = t.EarliestScanDate, + LatestScanDate = t.LatestScanDate, + + + TotalStudyCount = t.StudyList.Count() + t.NoneDicomStudyList.Count(), + + TotalImageCount = t.StudyList.Sum(t => t.InstanceCount) + t.NoneDicomStudyList.Sum(t => t.FileCount), + + TotalImageSize = t.StudyList.SelectMany(t => t.InstanceList).Sum(t => t.FileSize) + t.NoneDicomStudyList.SelectMany(t => t.NoneDicomFileList).Sum(t => t.FileSize), + + + //DicomStudyCount = t.StudyList.Count(), + //NoneDicomStudyCount = t.NoneDicomStudyList.Count(), + + //DicomImageCount = t.StudyList.Sum(t => t.InstanceCount), + //NoneDicomImageCount = t.NoneDicomStudyList.Sum(t => t.FileCount), + + //DicomImageSize = t.StudyList.SelectMany(t => t.InstanceList).Sum(t => t.FileSize), + //NoneDicomImageSize = t.NoneDicomStudyList.SelectMany(t => t.NoneDicomFileList).Sum(t => t.FileSize) + }); + + + var pagelist = await query.ToPagedListAsync(inQuery); + + return ResponseOutput.Ok(pagelist); } + /// + /// 获取项目影像统计,有影像的subject 数量 访视数量 + /// + /// + /// + public async Task GetTrialVisitImageStatInfo(Guid trialId) + { + var subjectImageList = _subjectVisitRepository.Where(t => t.TrialId == trialId) + .Where(t => t.StudyList.Sum(t => t.InstanceCount) > 0 || t.NoneDicomStudyList.Sum(t => t.FileCount) > 0) + .GroupBy(t => t.SubjectId) + .Select(g => new + { + SubjectId = g.Key, + VisitCount = g.Count(), + ImageSize = g.Sum(t => t.NoneDicomStudyList.SelectMany(t => t.NoneDicomFileList).Sum(t => t.FileSize) + + g.Sum(t => t.StudyList.SelectMany(t => t.InstanceList).Sum(t => t.FileSize))) + }) + .ToList(); + + var subjectCount = subjectImageList.Count; + + var subjectVisitCount = subjectImageList.Sum(t => t.VisitCount); + + var totalImageSize = subjectImageList.Sum(t => t.ImageSize); + + return ResponseOutput.Ok(new TrialImageStatInfo { SubjectCount = subjectCount, SubjectVisitCount = subjectVisitCount, TotalImageSize = totalImageSize }); + + + } + + /// + /// 批量勾选访视 进行下载 + /// + /// + /// + public async Task GetExportSubjectVisitImageList(TrialExportImageCommand inCommand) + { + + if (inCommand.IsKeyImage) + { + var downloadInfo = _visitTaskRepository.Where(t => t.TrialId == inCommand.TrialId && t.ReadingCategory == ReadingCategory.Visit && t.IsAnalysisCreate == false) + .Where(t => inCommand.SubjectVisitIdList.Contains((Guid)t.SourceSubjectVisitId)) + .Select(t => new + { + t.Trial.ResearchProgramNo, + CriterionName = t.TrialReadingCriterion.CriterionName, + + TrialSiteCode = t.Subject.TrialSite.TrialSiteCode, + SubjectCode = t.Subject.Code, + VisitName = (string?)t.SourceSubjectVisit.VisitName, + + QuestionMarkPictureList = t.ReadingTaskQuestionMarkList.SelectMany(c => new List() { c.PicturePath, c.OtherPicturePath }).ToList(), + + TableQuestionRowPictureList = t.LesionList.SelectMany(c => new List() { c.PicturePath, c.OtherPicturePath }).ToList(), + + + IsJudgeSelect = t.JudgeResultTaskId == t.Id + + + }).FirstOrDefault(); + + return ResponseOutput.Ok(downloadInfo); + } + else + { + + var downloadInfo = _trialRepository.Where(t => t.Id == inCommand.TrialId).Select(t => new + { + t.ResearchProgramNo, + + VisitList = t.SubjectVisitList.Where(t => inCommand.SubjectVisitIdList.Contains(t.Id)).Select(sv => new + { + TrialSiteCode = sv.TrialSite.TrialSiteCode, + SubjectCode = sv.Subject.Code, + VisitName = sv.VisitName, + StudyList = sv.StudyList.Select(u => new + { + u.PatientId, + u.StudyTime, + u.StudyCode, + + SeriesList = u.SeriesList.Select(z => new + { + z.Modality, + + InstancePathList = z.DicomInstanceList.Select(k => new + { + k.Path + }) + }) + + }), + + NoneDicomStudyList = sv.NoneDicomStudyList.Select(nd => new + { + nd.Modality, + nd.StudyCode, + nd.ImageDate, + + FileList = nd.NoneDicomFileList.Select(file => new + { + file.FileName, + file.Path, + file.FileType + }) + }) + }).ToList() + + }).FirstOrDefault(); + + + return ResponseOutput.Ok(downloadInfo); + } + + + + } + + #endregion + + + #region 之前后端下载废弃 diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialConfigDTO.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialConfigDTO.cs index 515383350..f20d86207 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialConfigDTO.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialConfigDTO.cs @@ -79,7 +79,7 @@ namespace IRaCIS.Core.Application.Contracts /// public List StudyNameList { get; set; } - + public List TrialObjectNameList { get; set; } @@ -1040,7 +1040,7 @@ namespace IRaCIS.Core.Application.Contracts public class TrialSPMConfigCommand { - public Guid Id { get; set; } + public Guid Id { get; set; } [Comment("SPM 参与中心调研")] public bool IsSPMJoinSiteSurvey { get; set; } @@ -1184,6 +1184,9 @@ namespace IRaCIS.Core.Application.Contracts public class TrialBodyPartView { + + public bool IsStudyUse { get; set; } + public string Code { get; set; } diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs index 27f6ec35d..b3c3b34ee 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs @@ -503,8 +503,9 @@ namespace IRaCIS.Core.Application && x.ReadingCriterionPageId == null) .ProjectTo(_mapper.ConfigurationProvider).OrderBy(x => x.ShowOrder).ToListAsync(); - return (result, new { - ReadingVersionEnum= trialCriterion.ReadingVersionEnum + return (result, new + { + ReadingVersionEnum = trialCriterion.ReadingVersionEnum }); } @@ -585,7 +586,7 @@ namespace IRaCIS.Core.Application await _readingQuestionCriterionTrialRepository.UpdatePartialFromQueryAsync(inDto.TrialReadingCriterionId, x => new ReadingQuestionCriterionTrial() { - ReadingToolList=inDto.ReadingToolList, + ReadingToolList = inDto.ReadingToolList, IsImageFilter = inDto.IsImageFilter, ImageDownloadEnum = inDto.ImageDownloadEnum, ImageUploadEnum = inDto.ImageUploadEnum, @@ -1334,7 +1335,35 @@ namespace IRaCIS.Core.Application /// public async Task>> GetTrialBodyPartList(Guid trialId) { - var list = await _trialRepository.Where(t => t.Id == trialId).SelectMany(t => t.TrialBodyPartList).Select(t => new TrialBodyPartView() { Code = t.Code, Name = _userInfo.IsEn_Us ? t.Name : t.NameCN, Id = t.Id, IsHandAdd = t.IsHandAdd }).OrderBy(t=>t.Name).ToListAsync(); + var list = await _trialRepository.Where(t => t.Id == trialId) + .SelectMany(t => t.TrialBodyPartList) + .Select(t => new TrialBodyPartView() { Code = t.Code, Name = _userInfo.IsEn_Us ? t.Name : t.NameCN, Id = t.Id, IsHandAdd = t.IsHandAdd }) + .OrderBy(t => t.Name).ToListAsync(); + + + var useBodyPart = _trialRepository.Where(t => t.Id == trialId).Select(t => new + { + DicomBodyPartList = t.StudyList.Where(t => t.BodyPartForEdit != "") + .Select(c => c.BodyPartForEdit) + .Distinct(), + NoneDicomBodyPartList = t.NoneDicomStudyList.Where(t => t.BodyPart != "") + .Select(c => c.BodyPart) + .Distinct(), + + }).FirstOrDefault(); + + foreach (var item in list) + { + var useBodyPartList = new List(); + if (useBodyPart != null) + { + useBodyPartList = useBodyPart.DicomBodyPartList.Union(useBodyPart.NoneDicomBodyPartList).Distinct().ToList(); + } + + item.IsStudyUse = useBodyPartList.Any(t => t == item.Name); + } + + return ResponseOutput.Ok(list); } @@ -1417,7 +1446,7 @@ namespace IRaCIS.Core.Application [HttpPost] public async Task UpdateTrialStudyNameList(UpdateTrialStudyNameListInDto inDto) { - + var trial = await _trialRepository.FirstOrDefaultAsync(x => x.Id == inDto.TrialId); diff --git a/IRaCIS.Core.Domain/Allocation/VisitTask.cs b/IRaCIS.Core.Domain/Allocation/VisitTask.cs index 10453517e..928bb0148 100644 --- a/IRaCIS.Core.Domain/Allocation/VisitTask.cs +++ b/IRaCIS.Core.Domain/Allocation/VisitTask.cs @@ -9,6 +9,11 @@ namespace IRaCIS.Core.Domain.Models; public class VisitTask : BaseFullAuditEntity { #region 导航属性 + + [JsonIgnore] + + public List ReadingTaskQuestionMarkList { get; set; } + [JsonIgnore] public List TaskStudyList { get; set; } diff --git a/IRaCIS.Core.Domain/Trial/Trial.cs b/IRaCIS.Core.Domain/Trial/Trial.cs index d685f71d5..6a1d2b951 100644 --- a/IRaCIS.Core.Domain/Trial/Trial.cs +++ b/IRaCIS.Core.Domain/Trial/Trial.cs @@ -48,6 +48,9 @@ public partial class Trial : BaseFullDeleteAuditEntity public List SubjectList { get; set; } = new List(); [JsonIgnore] public List SubjectVisitList { get; set; } = new List(); + + [JsonIgnore] + public List NoneDicomStudyList { get; set; } [JsonIgnore] public List StudyList { get; set; } = new List(); [JsonIgnore]