diff --git a/IRaCIS.Core.Application/Helper/ExcelExportHelper.cs b/IRaCIS.Core.Application/Helper/ExcelExportHelper.cs index e1d1703b..66bb77e9 100644 --- a/IRaCIS.Core.Application/Helper/ExcelExportHelper.cs +++ b/IRaCIS.Core.Application/Helper/ExcelExportHelper.cs @@ -143,22 +143,32 @@ public static class ExcelExportHelper - public static async Task DataExport_NpoiTestAsync(string code, object data, IRepository _commonDocumentRepository, IWebHostEnvironment _hostEnvironment, IDictionaryService? _dictionaryService = null, Type? translateType = null, CriterionType? criterionType = null) + public static async Task<(MemoryStream,string)> DataExport_NpoiTestAsync(string code, object data, IRepository _commonDocumentRepository, IWebHostEnvironment _hostEnvironment, IDictionaryService? _dictionaryService = null, Type? translateType = null, CriterionType? criterionType = null) { //判断是否有字典翻译 if (_dictionaryService != null && translateType != null) { + + ////只标注单个的时候 + //var needTranslatePropertyList = translateType.GetProperties().Where(t => t.IsDefined(typeof(DictionaryTranslateAttribute), true)) + // .Select(c => new { c.Name, DicParentCode = ((DictionaryTranslateAttribute?)c.GetCustomAttributes(typeof(DictionaryTranslateAttribute), false)[0])?.DicParentCode }).ToList(); + + //一个值 对应不同的字典翻译 var needTranslatePropertyList = translateType.GetProperties().Where(t => t.IsDefined(typeof(DictionaryTranslateAttribute), true)) .SelectMany(c => - c.GetCustomAttributes(typeof(DictionaryTranslateAttribute), false).Select(f => (DictionaryTranslateAttribute?)f).Where(t => t.CriterionType == criterionType || t.CriterionType == null).Select(k => new { c.Name, k.DicParentCode }) + c.GetCustomAttributes(typeof(DictionaryTranslateAttribute), false).Select(f => (DictionaryTranslateAttribute?)f).Where(t => t.CriterionType == criterionType || t.CriterionType == null) + .Select(k => new { c.Name, k.DicParentCode, k.IsTranslateDenpendOtherProperty, k.DependPropertyName, k.DependPropertyValueStr }) ).ToList(); + + //字典表查询出所有需要翻译的数据 var translateDataList = await _dictionaryService.GetBasicDataSelect(needTranslatePropertyList.Select(t => t.DicParentCode).Distinct().ToArray()); + var dic = JsonConvert.DeserializeObject>(data.ToJsonNotIgnoreNull()); foreach (var key in dic.Keys) @@ -174,11 +184,30 @@ public static class ExcelExportHelper { var itemDic = JsonConvert.DeserializeObject>(item.ToJsonNotIgnoreNull()); + foreach (var needTranslateProperty in needTranslatePropertyList) { - var beforeValue = itemDic[needTranslateProperty.Name]?.ToString(); + //翻译的属性依赖其他属性 + if (needTranslateProperty.IsTranslateDenpendOtherProperty) + { + if (item[needTranslateProperty.DependPropertyName]?.ToString().ToLower() == needTranslateProperty.DependPropertyValueStr.ToLower()) + { + var beforeValue = itemDic[needTranslateProperty.Name]?.ToString(); + + itemDic[needTranslateProperty.Name] = translateDataList[needTranslateProperty.DicParentCode].Where(t => t.Code.ToLower() == beforeValue?.ToLower()).FirstOrDefault()?.ValueCN ?? String.Empty; + } + } + //普通翻译 或者某一标准翻译 + else + { + var beforeValue = itemDic[needTranslateProperty.Name]?.ToString(); + + + itemDic[needTranslateProperty.Name] = translateDataList[needTranslateProperty.DicParentCode].Where(t => t.Code.ToLower() == beforeValue?.ToLower()).FirstOrDefault()?.ValueCN ?? String.Empty; + } + + - itemDic[needTranslateProperty.Name] = translateDataList[needTranslateProperty.DicParentCode].Where(t => t.Code.ToLower() == beforeValue?.ToLower()).FirstOrDefault()?.ValueCN ?? String.Empty; } itemDic.Add("No", no++); @@ -197,12 +226,9 @@ public static class ExcelExportHelper } + var (physicalPath, fileName) = await FileStoreHelper.GetCommonDocPhysicalFilePathAsync(_hostEnvironment, _commonDocumentRepository, code); - - - var (physicalPath, fileNmae) = await FileStoreHelper.GetCommonDocPhysicalFilePathAsync(_hostEnvironment, _commonDocumentRepository, code); - - + //模板路径 var tplPath = physicalPath; @@ -220,9 +246,9 @@ public static class ExcelExportHelper memoryStream.Seek(0, SeekOrigin.Begin); - return memoryStream; + return (memoryStream, fileName); - //var wb = new HSSFWorkbook(memoryStream); + //var wb = new HSSFWorkbook(memoryStream); //var sheet = wb.GetSheetAt(0); diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml index 07ce6258..225dfc3f 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -469,6 +469,16 @@ + + + Subject 进展表 --new + + + + + + + 阅片期信息表 diff --git a/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs b/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs index 6732e954..fb92f044 100644 --- a/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs +++ b/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs @@ -1,14 +1,22 @@ using DocumentFormat.OpenXml.Office2010.ExcelAc; +using DocumentFormat.OpenXml.Spreadsheet; using IRaCIS.Application.Contracts; using IRaCIS.Application.Interfaces; using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Application.Service.Reading.Dto; using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Domain.Share; +using IRaCIS.Core.Infra.EFCore.Common; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using MiniExcelLibs; +using MiniExcelLibs.OpenXml; +using NPOI.HPSF; +using NPOI.HSSF.UserModel; +using NPOI.XSSF.UserModel; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -185,6 +193,149 @@ namespace IRaCIS.Core.Application.Service.Common } + + /// + /// Subject 进展表 --new + /// + /// + /// + /// + /// + /// + + [HttpPost] + public async Task GetSubjectProgress_Export(SubjectProgressQuery dto, + [FromServices] IRepository _commonDocumentRepository, + [FromServices] IDictionaryService _dictionaryService, + [FromServices] IRepository _trialRepository) + { + + + var query = from subject in _repository.Where(u => u.TrialId == dto.TrialId) + join trialReadingCriterion in _repository.Where(u => u.TrialId == dto.TrialId && u.IsConfirm && u.Id == dto.TrialReadingCriterionId) on subject.TrialId equals trialReadingCriterion.TrialId + + select new SubjectProgressDto() + { + TrialSiteCode = subject.TrialSite.TrialSiteCode, + SubjectCode = subject.Code, + SubjectStatus = subject.Status, + + + VisitList = subject.SubjectVisitList.Where(t => t.VisitExecuted != VisitExecutedEnum.Unavailable).Select(t => new SubjectProgressDto.MouduleProgress() + { + TaskName = t.VisitName, + VisitTaskNum = t.VisitNum, + Inplan = t.InPlan, + IsFinalVisit = t.IsFinalVisit, + IsLostVisit = t.IsLostVisit, + ReadingStatus = + t.VisitTaskList.Where(t => t.TaskState == TaskState.Effect && t.IsAnalysisCreate == false && t.ReadingCategory == ReadingCategory.Visit && t.ReadingTaskState == ReadingTaskState.HaveSigned).Count() == (int)trialReadingCriterion.ReadingType ? + ReadingStatusEnum.ReadCompleted : t.VisitTaskList.Where(t => t.TaskState == TaskState.Effect && t.IsAnalysisCreate == false && t.ReadingCategory == ReadingCategory.Visit && t.TaskAllocationState == TaskAllocationState.Allocated).Count() == (int)trialReadingCriterion.ReadingType ? ReadingStatusEnum.TaskAllocate : + t.ReadingStatus + }).ToList(), + + ModuleList = subject.ReadModuleList.Select(t => new SubjectProgressDto.MouduleProgress() + { + TaskName = t.ModuleName, + VisitTaskNum = t.ReadingSetType == ReadingSetType.ImageReading ? ReadingCommon.TaskNumDic[ReadingCategory.Global] : ReadingCommon.TaskNumDic[ReadingCategory.Oncology] + t.SubjectVisit.VisitNum, + ReadingSetType = t.ReadingSetType, + ReadingStatus = t.ModuleTaskList.Where(t => t.TaskState == TaskState.Effect && t.IsAnalysisCreate == false && (t.ReadingCategory == ReadingCategory.Oncology || t.ReadingCategory == ReadingCategory.Global) && t.ReadingTaskState == ReadingTaskState.HaveSigned).Count() == (int)trialReadingCriterion.ReadingType ? + ReadingStatusEnum.ReadCompleted : t.ModuleTaskList.Where(t => t.TaskState == TaskState.Effect && t.IsAnalysisCreate == false && (t.ReadingCategory == ReadingCategory.Oncology || t.ReadingCategory == ReadingCategory.Global) && t.TaskAllocationState == TaskAllocationState.Allocated).Count() == (int)trialReadingCriterion.ReadingType ? + ReadingStatusEnum.TaskAllocate : t.ReadingStatus + }).ToList() + + + } + ; + + + var list = query.ToList(); + //.ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); + + + + var exportInfo = (await _trialRepository.Where(t => t.Id == dto.TrialId).IgnoreQueryFilters().ProjectTo(_mapper.ConfigurationProvider).FirstOrDefaultAsync()).IfNullThrowException(); + + exportInfo.CriterionName = await _repository.Where(u => u.TrialId == dto.TrialId && u.IsConfirm && u.Id == dto.TrialReadingCriterionId).Select(t=>t.CriterionName).FirstOrDefaultAsync(); + + exportInfo.List = list; + + var (memoryStream, fileName) = await ExcelExportHelper.DataExport_NpoiTestAsync(StaticData.Export.TrialSubjectProgressList_Export, exportInfo, /*"", */_commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(SubjectProgressDto)); + + + // 使用NPOI 进行二次处理 + + var wb = new XSSFWorkbook(memoryStream); + + var sheet = wb.GetSheetAt(0); + + foreach (var subject in list) + { + var index = list.IndexOf(subject); + var row = sheet.GetRow(index + 4); + + + foreach (var item in subject.TotalList) + { + //从第五列开始动态写 + var visitIndex = subject.TotalList.IndexOf(item) + 4; + + var cell = row.CreateCell(visitIndex); + + if (item.IsLostVisit == true) + { + cell.CellStyle = sheet.GetRow(1).GetCell(6).CellStyle; + } + else + { + switch (item.ReadingStatus) + { + case ReadingStatusEnum.ImageNotSubmit: + + cell.CellStyle = sheet.GetRow(1).GetCell(1).CellStyle; + + break; + case ReadingStatusEnum.ImageQuality: + cell.CellStyle = sheet.GetRow(1).GetCell(2).CellStyle; + break; + case ReadingStatusEnum.ConsistencyCheck: + cell.CellStyle = sheet.GetRow(1).GetCell(3).CellStyle; + break; + case ReadingStatusEnum.TaskAllocate: + cell.CellStyle = sheet.GetRow(1).GetCell(4).CellStyle; + break; + case ReadingStatusEnum.ImageReading: + cell.CellStyle = sheet.GetRow(1).GetCell(5).CellStyle; + break; + case ReadingStatusEnum.ReadCompleted: + cell.CellStyle = sheet.GetRow(1).GetCell(6).CellStyle; + break; + + default: + break; + } + } + + + + cell.SetCellValue(item.TaskName); + } + } + + var memoryStream2 = new MemoryStream(); + wb.Write(memoryStream2); + memoryStream2.Seek(0, SeekOrigin.Begin); + + return new FileStreamResult(memoryStream2, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") + { + FileDownloadName = $"{fileName.Substring(startIndex: 0, fileName.LastIndexOf('.'))}_{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx" + }; + + } + + + + /// /// 阅片期信息表 /// @@ -643,14 +794,14 @@ namespace IRaCIS.Core.Application.Service.Common public string FileName { get; set; } - public ExportCatogory ExportCatogory { get;set; } + public ExportCatogory ExportCatogory { get; set; } } public enum ExportCatogory { - // 整体肿瘤评估 - OverallTumorEvaluation =1, + // 整体肿瘤评估 + OverallTumorEvaluation = 1, //肿瘤疗效评估 EvaluationOfTumorEfficacy = 2, @@ -674,12 +825,12 @@ namespace IRaCIS.Core.Application.Service.Common if (criterionType == CriterionType.RECIST1Pointt1) { - list.Add( new ExportDocumentDes() { Code= StaticData.Export.OverallTumorEvaluation_Export ,ExportCatogory=ExportCatogory.OverallTumorEvaluation} ); + list.Add(new ExportDocumentDes() { Code = StaticData.Export.OverallTumorEvaluation_Export, ExportCatogory = ExportCatogory.OverallTumorEvaluation }); list.Add(new ExportDocumentDes() { Code = StaticData.Export.RECIST1Point1EvaluationOfTumorEfficacy_Export, ExportCatogory = ExportCatogory.EvaluationOfTumorEfficacy }); - list.Add(new ExportDocumentDes() { Code = StaticData.Export.RECIST1Point1DetailedOfEvaluatedLesion_Export, ExportCatogory = ExportCatogory.DetailedOfEvaluatedLesion }); + list.Add(new ExportDocumentDes() { Code = StaticData.Export.RECIST1Point1DetailedOfEvaluatedLesion_Export, ExportCatogory = ExportCatogory.DetailedOfEvaluatedLesion }); } - var result = _repository.Where(t => list.Select(c=>c.Code).Contains(t.Code)).Select(c => new ExportDocumentDes() { Code = c.Code, FileName = c.Name }).ToList(); + var result = _repository.Where(t => list.Select(c => c.Code).Contains(t.Code)).Select(c => new ExportDocumentDes() { Code = c.Code, FileName = c.Name }).ToList(); foreach (var item in list) { diff --git a/IRaCIS.Core.Application/Service/QC/DTO/QCListViewModel.cs b/IRaCIS.Core.Application/Service/QC/DTO/QCListViewModel.cs index 9514c632..5c8e4c22 100644 --- a/IRaCIS.Core.Application/Service/QC/DTO/QCListViewModel.cs +++ b/IRaCIS.Core.Application/Service/QC/DTO/QCListViewModel.cs @@ -2,6 +2,7 @@ using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Domain.Share; +using MiniExcelLibs.Attributes; using Newtonsoft.Json; using System.ComponentModel.DataAnnotations; @@ -242,6 +243,7 @@ namespace IRaCIS.Core.Application.Contracts //public DateTime? SignDate { get; set; } //public bool IsUrgent { get; set; } + //[ExcelFormat("yyyy-MM-dd")] public DateTime? FirstGiveMedicineTime { get; set; } public DateTime? OutEnrollmentTime { get; set; } @@ -352,6 +354,58 @@ namespace IRaCIS.Core.Application.Contracts public Guid TrialId { get; set; } } + public class SubjectProgressQuery + { + [NotDefault] + public Guid TrialId { get; set; } + + [NotDefault] + public Guid TrialReadingCriterionId { get; set; } + } + + public class SubjectProgressDto + { + public string SubjectCode { get; set; } + + public string TrialSiteCode { get; set; } + + [DictionaryTranslateAttribute("Subject_Visit_Status")] + public SubjectStatus SubjectStatus { get; set; } + + + public List VisitList { get; set; } + + public List ModuleList { get; set; } + + + public List TotalList => VisitList.Union(ModuleList).OrderBy(t=>t.VisitTaskNum).ToList(); + + + public class MouduleProgress + { + public string TaskName { get; set; } + + public ReadingStatusEnum ReadingStatus { get; set; } + + + + + //最终任务 + public decimal VisitTaskNum { get; set; } + + //访视会有 + public bool? Inplan { get; set; } + + public bool? IsLostVisit { get; set; } + + public bool? IsFinalVisit { get; set; } + + //阅片期会有 + public ReadingSetType? ReadingSetType { get; set; } + } + + } + public class ReadPeriodExportDto { public string SubjectCode { get; set; } @@ -385,7 +439,7 @@ namespace IRaCIS.Core.Application.Contracts public string Modality { get; set; } = string.Empty; - + //[ExcelFormat("yyyy-MM-dd")] public DateTime? StudyTime { get; set; } public string SubjectCode { get; set; } = String.Empty; diff --git a/IRaCIS.Core.Application/Service/QC/_MapConfig.cs b/IRaCIS.Core.Application/Service/QC/_MapConfig.cs index 3b2961c5..590db948 100644 --- a/IRaCIS.Core.Application/Service/QC/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/QC/_MapConfig.cs @@ -5,6 +5,7 @@ using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Application.Contracts.DTO; using IRaCIS.Core.Application.MediatR.CommandAndQueries; using IRaCIS.Core.Domain.Share; +using static IRaCIS.Core.Application.Contracts.SubjectProgressDto; namespace IRaCIS.Core.Application.Service { @@ -68,6 +69,24 @@ namespace IRaCIS.Core.Application.Service .ForMember(d => d.CheckWaitReplyCount, u => u.MapFrom(s => s.SubjectVisitList.Count(t => t.CheckState == CheckStateEnum.CVIng && t.CheckChallengeState != CheckChanllengeTypeEnum.Closed && !t.CheckChallengeDialogList.Any(t => t.CreateUser.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator)))) ; + CreateMap() + .ForMember(d => d.TrialSiteCode, u => u.MapFrom(s => s.TrialSite.TrialSiteCode)) + .ForMember(d => d.SubjectCode, u => u.MapFrom(s => s.Code)) + .ForMember(d => d.SubjectStatus, u => u.MapFrom(s => s.Status)) + .ForMember(d => d.VisitList, u => u.MapFrom(s => s.SubjectVisitList.Where(t => t.VisitExecuted != VisitExecutedEnum.Unavailable) + )); + + //CreateMap () + // .ForMember(d => d.TaskName, u => u.MapFrom(s => s.VisitName)) + // .ForMember(d => d.VisitTaskNum, u => u.MapFrom(s => s.VisitNum)) + // .ForMember(d => d.Inplan, u => u.MapFrom(s => s.InPlan)) + // .ForMember(d => d.ReadingStatus, u => u.MapFrom(s => s.VisitTaskList + // .Count(t=>t.TaskState==TaskState.Effect && t.IsAnalysisCreate==false && t.ReadingCategory==ReadingCategory.Visit && t.ReadingTaskState==ReadingTaskState.HaveSigned)==s. s.ReadingStatus)) + + + + + CreateMap() .ForMember(d => d.TrialSiteCode, u => u.MapFrom(s => s.Subject.TrialSite.TrialSiteCode)) diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialViewModel.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialViewModel.cs index b99f04ef..6a9785e1 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialViewModel.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialViewModel.cs @@ -75,6 +75,8 @@ namespace IRaCIS.Application.Contracts public string ResearchProgramNo { get; set; } = string.Empty; + public string CriterionName { get; set;} = string.Empty; + } diff --git a/IRaCIS.Core.Domain.Share/Reading/ReadEnum.cs b/IRaCIS.Core.Domain.Share/Reading/ReadEnum.cs index 8f08aeb7..00384e05 100644 --- a/IRaCIS.Core.Domain.Share/Reading/ReadEnum.cs +++ b/IRaCIS.Core.Domain.Share/Reading/ReadEnum.cs @@ -1343,6 +1343,8 @@ namespace IRaCIS.Core.Domain.Share /// 阅片完成 /// ReadCompleted = 5, + + } diff --git a/IRaCIS.Core.Domain/Reading/ReadingPeriod/ReadModule.cs b/IRaCIS.Core.Domain/Reading/ReadingPeriod/ReadModule.cs index ff256076..fed6a88c 100644 --- a/IRaCIS.Core.Domain/Reading/ReadingPeriod/ReadModule.cs +++ b/IRaCIS.Core.Domain/Reading/ReadingPeriod/ReadModule.cs @@ -4,6 +4,7 @@ using System; using IRaCIS.Core.Domain.Share; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using System.Collections.Generic; namespace IRaCIS.Core.Domain.Models { @@ -18,10 +19,13 @@ namespace IRaCIS.Core.Domain.Models public ReadingQuestionCriterionTrial TrialReadingCriterion { get; set; } - /// - /// 受试者ID - /// - public Guid SubjectId { get; set; } + [JsonIgnore] + public List ModuleTaskList { get; set; } + + /// + /// 受试者ID + /// + public Guid SubjectId { get; set; } public Guid TrialReadingCriterionId { get; set; } @@ -122,7 +126,7 @@ namespace IRaCIS.Core.Domain.Models - public ReadingStatusEnum ReadingStatus { get; set; } + public ReadingStatusEnum ReadingStatus { get; set; } = ReadingStatusEnum.TaskAllocate; } diff --git a/IRaCIS.Core.Domain/Visit/SubjectVisit.cs b/IRaCIS.Core.Domain/Visit/SubjectVisit.cs index 5aae51bc..35b4139f 100644 --- a/IRaCIS.Core.Domain/Visit/SubjectVisit.cs +++ b/IRaCIS.Core.Domain/Visit/SubjectVisit.cs @@ -229,6 +229,12 @@ namespace IRaCIS.Core.Domain.Models [JsonIgnore] public List VisitTaskList { get; set; } = new List(); + + + [JsonIgnore] + + public List TrialReadingCriterionList { get; set; } + public ReadingStatusEnum ReadingStatus { get; set; } diff --git a/IRaCIS.Core.Domain/_Config/_StaticData.cs b/IRaCIS.Core.Domain/_Config/_StaticData.cs index fa3b327b..99e2e894 100644 --- a/IRaCIS.Core.Domain/_Config/_StaticData.cs +++ b/IRaCIS.Core.Domain/_Config/_StaticData.cs @@ -143,6 +143,8 @@ public static class StaticData public const string TrialSubjectList_Export = "TrialSubjectList_Export"; + public const string TrialSubjectProgressList_Export = "TrialSubjectProgressList_Export"; + public const string TrialSubjectReadingPeriodList_Export = "TrialSubjectReadingPeriodList_Export"; public const string TrialStudyList_Export = "TrialStudyList_Export";