From 4aecfb3bed603da724637e941204461290ba4e63 Mon Sep 17 00:00:00 2001 From: hang <872297557@qq.com> Date: Fri, 19 Dec 2025 17:06:39 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=AF=BC=E8=A1=A8=E7=BB=93?= =?UTF-8?q?=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IRaCIS.Core.Application.xml | 2 +- .../TrialSiteUser/DTO/TrialStatViewModel.cs | 33 ++++++- .../Service/TrialSiteUser/TrialStatService.cs | 92 ++++++++++++++++--- 3 files changed, 110 insertions(+), 17 deletions(-) diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml index 2bbfe2ad7..731955b54 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -15707,7 +15707,7 @@ - 删除某个目录的文件 + 删除某个目录的文件 (包含单个文件,oss单个文件需要去除前缀/) diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialStatViewModel.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialStatViewModel.cs index 1244fe508..b0df38be2 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialStatViewModel.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialStatViewModel.cs @@ -91,17 +91,48 @@ namespace IRaCIS.Core.Application.ViewModel public Guid? TrialSiteId { get; set; } } + public class FirstPdInfo + { + public string SubjectCode { get; set; } + + public DateTime? EarliestScanDate { get; set; } + + public DateTime? BaseLineLatestScanDate { get; set; } + + + // 新增属性:天数差 + public double? DaysDiff + { + get + { + if (BaseLineLatestScanDate.HasValue && EarliestScanDate.HasValue) + { + return (EarliestScanDate.Value - BaseLineLatestScanDate.Value).TotalDays; + } + return null; + } + } + } + public class EfficacyEvaluationStatViewModel { public string? DictionaryCode { get; set; } + + public string Code { get; set; } public string OverallTumorEvaluation { get; set; } - public int SubjectCount { get; set; } + public int SubjectCount => SubjectCodeList.Count(); + + public List SubjectCodeList { get; set; } } public class EfficacyEvaluationExport { + public DateTime? EarliestScanDate { get; set; } + + public DateTime? LatestScanDate { get; set; } + public Guid Id { get; set; } diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialStatService.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialStatService.cs index b5b7b15db..3eb13abe8 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialStatService.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialStatService.cs @@ -113,18 +113,18 @@ public class TrialStatService( /// /// [HttpPost] - public async Task> GetTrialEfficacyEvaluationStatList(EfficacyEvaluationQuery inQuery) + public async Task>> GetTrialEfficacyEvaluationStatList(EfficacyEvaluationQuery inQuery) { var trialReadingCriterionId = inQuery.TrialReadingCriterionId; //每次查询必须是单标准的 - var criterion = await _readingQuestionCriterionTrialRepository.Where(t => t.Id == trialReadingCriterionId).Select(t => new { t.CriterionType, t.CriterionGroup, t.IsGlobalReading, t.IsArbitrationReading, t.IsOncologyReading, t.CriterionName, t.ArbitrationRule,t.TrialId }).FirstNotNullAsync(); + var criterion = await _readingQuestionCriterionTrialRepository.Where(t => t.Id == trialReadingCriterionId).Select(t => new { t.CriterionType, t.CriterionGroup, t.IsGlobalReading, t.IsArbitrationReading, t.IsOncologyReading, t.CriterionName, t.ArbitrationRule, t.TrialId }).FirstNotNullAsync(); if (criterion.CriterionGroup == CriterionGroup.Nontumorous) { - return new List(); + return ResponseOutput.Ok(new List()); } @@ -132,15 +132,18 @@ public class TrialStatService( if (criterion.CriterionType == CriterionType.RECIST1Point1 || criterion.CriterionType == CriterionType.RECIST1Pointt1_MB || criterion.CriterionType == CriterionType.IRECIST1Point1 || criterion.CriterionType == CriterionType.mRECISTHCC) { - questionType = QuestionType.Tumor; - + //iresist pfs 是icpd } - else if (criterion.CriterionType == CriterionType.Lugano2014 || criterion.CriterionType == CriterionType.Lugano2014WithoutPET) + else if (criterion.CriterionType == CriterionType.Lugano2014) { questionType = QuestionType.ImgOncology; } + else if (criterion.CriterionType == CriterionType.Lugano2014WithoutPET) + { + questionType = QuestionType.CTandMRI; + } else if (criterion.CriterionType == CriterionType.PCWG3) { @@ -164,6 +167,8 @@ public class TrialStatService( ReadingCategory = t.ReadingCategory, ArmEnum = t.ArmEnum, JudgeArmEnum = t.JudgeResultTask.ArmEnum, + LatestScanDate = t.SourceSubjectVisit.LatestScanDate, + EarliestScanDate = t.SourceSubjectVisit.EarliestScanDate, IsTrigerJudge = criterion.ArbitrationRule == ArbitrationRule.Visit ? t.JudgeVisitTaskId != null : (criterion.ArbitrationRule == ArbitrationRule.Reading ? @@ -176,7 +181,7 @@ public class TrialStatService( DictionaryCode = t.ReadingTaskQuestionAnswerList.Where(c => c.ReadingQuestionTrial.QuestionType == questionType).Select(t => t.ReadingQuestionTrial.DictionaryCode).FirstOrDefault(), //整体肿瘤评估答案 - OverallTumorEvaluation = t.ReadingTaskQuestionAnswerList.Where(c => c.ReadingQuestionTrial.QuestionType == questionType).FirstOrDefault()!.Answer + OverallTumorEvaluation = t.ReadingTaskQuestionAnswerList.Where(c => c.ReadingQuestionTrial.QuestionType == questionType).Select(t => t.IsGlobalChange ? t.GlobalChangeAnswer : t.Answer).FirstOrDefault() }); @@ -201,6 +206,24 @@ public class TrialStatService( //处理裁判标记 list = DealJudgeMark(criterion.ArbitrationRule, criterion.IsGlobalReading, list); + //基线(最晚拍片日期)-首次PD(所有触发PD的病灶的检查的最早拍片日期)的中位数,单位是天 + + // 构建字典:SubjectCode -> LatestScanDate + var baseLineDict = list.Where(t => t.VisitTaskNum == 0).GroupBy(t => t.SubjectCode) + .ToDictionary( + g => g.Key, + g => g.First().LatestScanDate // 如果同一个 SubjectCode 有多条记录,只取第一条 + ); + + //一定要两个人做完了,产生了裁判并且有结果的,否则就不算,并且排除基线 + list = list.Where(t => t.IsJudgeSelect == true && t.VisitTaskNum != 0 && t.ReadingCategory==ReadingCategory.Visit)//全局的答案已经放在对应访视上了 + .GroupBy(t => t.SubjectCode).Select(g => g.OrderByDescending(t => t.VisitTaskNum).First()).ToList(); + + + //总subject 数量 + var totalSubjectCount = list.Select(t => t.SubjectId).Distinct().Count(); + + //判断subject的逻辑需要确认,这么多次访视任务,有的符合,有的不符合,准则是什么? @@ -208,30 +231,69 @@ public class TrialStatService( { DictionaryCode = g.FirstOrDefault()?.DictionaryCode, OverallTumorEvaluation = g.Key, - SubjectCount = g.Select(t => t.SubjectId).Distinct().Count() + Code = g.Key, + SubjectCodeList = g.Select(t => t.SubjectCode).Distinct().ToList() }).ToList(); // 先把 resultList 转成内存字典 - var resultDict = resultList.ToDictionary(r => r.OverallTumorEvaluation, r => r.SubjectCount); + var resultDict = resultList.ToDictionary(r => r.OverallTumorEvaluation, r => r.SubjectCodeList); // 查询字典表,先把数据拉出来到内存,再合并 - var dicList = _dictionaryRepository + var translateList = _dictionaryRepository .Where(t => t.Parent.Code == dicName) .Select(t => new { - t.Code + t.Code, + t.Value, }) - .ToList() + .ToList() .Select(t => new EfficacyEvaluationStatViewModel { DictionaryCode = dicName, - OverallTumorEvaluation = t.Code, - SubjectCount = resultDict.ContainsKey(t.Code) ? resultDict[t.Code] : 0 + Code = t.Code, //方便找到首次PD的日期 + OverallTumorEvaluation = t.Value,//翻译后的值 + SubjectCodeList = resultDict.ContainsKey(t.Code) ? resultDict[t.Code] : new List() }) .ToList(); - return dicList; + // (cr +pr) /总人数 + + var crAddPr = translateList.Where(t => t.OverallTumorEvaluation == "PR" || t.OverallTumorEvaluation == "CR").Sum(t => t.SubjectCount); + + var orrPercent = totalSubjectCount > 0 + ? ((decimal)crAddPr / totalSubjectCount * 100).ToString("0.00") + "%" + : "0.00%"; + + var pdInfo = translateList + .WhereIf(criterion.CriterionType == CriterionType.IRECIST1Point1, t => t.OverallTumorEvaluation == "ICPD") + .WhereIf(criterion.CriterionType == CriterionType.IRECIST1Point1, t => t.OverallTumorEvaluation == "PD") + .FirstOrDefault(); + + var firstPdList = new List(); + if (pdInfo != null) + { + firstPdList = list.Where(t => t.OverallTumorEvaluation == pdInfo.Code).GroupBy(t => t.SubjectCode) + .Select(g => new FirstPdInfo + { + SubjectCode = g.Key, + EarliestScanDate = g.Where(t => t.OverallTumorEvaluation == pdInfo.Code).OrderBy(t => t.VisitTaskNum).First().EarliestScanDate + }) + .ToList(); + + foreach (var item in firstPdList) + { + if (baseLineDict.TryGetValue(item.SubjectCode, out var latestScanDate)) + { + item.BaseLineLatestScanDate = latestScanDate; + } + } + + + } + + + return ResponseOutput.Ok(translateList, new { PDList = firstPdList, ORR = orrPercent }); }