diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml index c292bb7f1..2488f0e40 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -1181,6 +1181,16 @@ 获取Sod的值 + + + 获取iSod的值 + + + + + 上一次访视Id + + 删除病灶获取起始病灶序号(RECIST1Point1 固定是1) @@ -1355,6 +1365,27 @@ + + + 与前一访视SOD相比变化量 + + + + + + + 获取iSOD + + + + + + + 与前一访视相比iSOD变化量 + + + + 修改与整个访视期间SOD最低点相比增加的值(mm) @@ -1405,6 +1436,13 @@ + + + 获取IRECIST靶病灶评估 + + + + diff --git a/IRaCIS.Core.Application/Service/Reading/Dto/ReadingImageTaskViewModel.cs b/IRaCIS.Core.Application/Service/Reading/Dto/ReadingImageTaskViewModel.cs index cb8db141f..3773a0b8c 100644 --- a/IRaCIS.Core.Application/Service/Reading/Dto/ReadingImageTaskViewModel.cs +++ b/IRaCIS.Core.Application/Service/Reading/Dto/ReadingImageTaskViewModel.cs @@ -268,6 +268,7 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto public DateTime? LatestScanDate { get; set; } + public TaskState TaskState { get; set; } public string TaskName { get; set; } public decimal VisitTaskNum { get; set; } diff --git a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs index 16a2fe9f6..143467c60 100644 --- a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs @@ -475,7 +475,7 @@ namespace IRaCIS.Application.Services var taskQuery = _visitTaskRepository.Where(x => x.TrialId == taskInfo.TrialId && x.SubjectId == taskInfo.SubjectId && - x.VisitTaskNum <= taskInfo.VisitTaskNum && + x.VisitTaskNum < taskInfo.VisitTaskNum && x.ArmEnum == taskInfo.ArmEnum && x.Id != inDto.VisitTaskId && x.DoctorUserId == taskInfo.DoctorUserId && diff --git a/IRaCIS.Core.Application/Service/ReadingCalculate/General/GeneralCalculateService.cs b/IRaCIS.Core.Application/Service/ReadingCalculate/General/GeneralCalculateService.cs index 691faa5e9..18d31f91c 100644 --- a/IRaCIS.Core.Application/Service/ReadingCalculate/General/GeneralCalculateService.cs +++ b/IRaCIS.Core.Application/Service/ReadingCalculate/General/GeneralCalculateService.cs @@ -151,25 +151,25 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate /// public async Task AddConvertedTaskFocus(Guid visitTaskId, Guid beforeConvertedTaskId) { - var originalTask = await _visitTaskRepository.Where(x => x.Id == beforeConvertedTaskId).Include(x => x.TrialReadingCriterion).FirstNotNullAsync(); + var originalTask = await _visitTaskRepository.Where(x => x.Id == visitTaskId).Include(x => x.TrialReadingCriterion).FirstNotNullAsync(); - var taskAnswer = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == visitTaskId && x.ReadingQuestionTrial.Type != "calculation").IgnoreAutoIncludes().AsNoTracking().ToListAsync(); + var taskAnswer = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == beforeConvertedTaskId && x.ReadingQuestionTrial.Type != "calculation").IgnoreAutoIncludes().AsNoTracking().ToListAsync(); taskAnswer.ForEach(x => { - x.VisitTaskId = beforeConvertedTaskId; + x.VisitTaskId = visitTaskId; x.Id = NewId.NextGuid(); }); - var tableRowAnswers = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == visitTaskId).AsNoTracking().ProjectTo(_mapper.ConfigurationProvider).IgnoreAutoIncludes().ToListAsync(); + var tableRowAnswers = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == beforeConvertedTaskId).AsNoTracking().ProjectTo(_mapper.ConfigurationProvider).IgnoreAutoIncludes().ToListAsync(); tableRowAnswers.ForEach(x => { - x.VisitTaskId = beforeConvertedTaskId; + x.VisitTaskId = visitTaskId; x.IsCurrentTaskAdd = false; - x.FristAddTaskId = beforeConvertedTaskId; + x.FristAddTaskId = visitTaskId; x.Id = NewId.NextGuid(); }); @@ -180,12 +180,12 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate }); - var tableAnswer = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == visitTaskId).IgnoreAutoIncludes().AsNoTracking().ToListAsync(); + var tableAnswer = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == beforeConvertedTaskId).IgnoreAutoIncludes().AsNoTracking().ToListAsync(); tableAnswer.ForEach(x => { x.Id = NewId.NextGuid(); - x.VisitTaskId = beforeConvertedTaskId; + x.VisitTaskId = visitTaskId; x.RowId = tableRowAnswers.Where(y => y.OriginalId == x.RowId).Select(x => x.Id).FirstOrDefault(); }); var addrowInfo = _mapper.Map>(tableRowAnswers); @@ -311,7 +311,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate BlindName = x.TaskBlindName, IsBaseLine = x.SourceSubjectVisit.IsBaseLine, VisitTaskId = x.Id, - + TaskState= x.TaskState, TaskName = x.TaskName, LatestScanDate= x.SourceSubjectVisit!=null?x.SourceSubjectVisit.LatestScanDate : null, VisitTaskNum = x.VisitTaskNum, @@ -320,7 +320,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate //CrterionDictionaryGroup = x.CrterionDictionaryGroup, IsCurrentTask = x.Id == visitTaskId, - }).ToListAsync(); + }).OrderBy(x=>x.VisitTaskNum).ThenByDescending(x=>x.TaskState).ToListAsync(); taskInfoList.ForEach(x => diff --git a/IRaCIS.Core.Application/Service/ReadingCalculate/IRECIST1Point1CalculateService.cs b/IRaCIS.Core.Application/Service/ReadingCalculate/IRECIST1Point1CalculateService.cs index 4ef0ef9d7..89badb0d7 100644 --- a/IRaCIS.Core.Application/Service/ReadingCalculate/IRECIST1Point1CalculateService.cs +++ b/IRaCIS.Core.Application/Service/ReadingCalculate/IRECIST1Point1CalculateService.cs @@ -66,7 +66,17 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate /// private decimal? sODData; + /// + /// 获取iSod的值 + /// + private decimal? iSODData; + private string nAString = "NA"; + + /// + /// 上一次访视Id + /// + public Guid? lastVisitTaskId; #endregion #region 删除病灶获取起始病灶序号 @@ -420,13 +430,13 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate //与基线访视相比SOD变化百分比 new ReadingCalculateData (){QuestionType=QuestionType.SODPercent,GetDecimalNullFun=GetSODPercent}, - //与整个访视期间SOD最低点相比增加的值(mm) //其他任务需要改 + //与整个访视期间SOD最低点相比增加的值(mm) new ReadingCalculateData (){QuestionType=QuestionType.LowestIncrease,GetDecimalNullFun=GetLowestIncrease,/*ChangeAllTaskFun=ChangeAllLowestIncrease*/}, - //与整个访视期间SOD最低点相比增加的百分比 //其他任务需要改 + //与整个访视期间SOD最低点相比增加的百分比 new ReadingCalculateData (){QuestionType=QuestionType.LowPercent,GetDecimalNullFun=GetLowPercent,/*ChangeAllTaskFun=ChangeAllLowPercent*/}, - //整个访视期间SOD最低点访视名称 //其他任务需要改 + //整个访视期间SOD最低点访视名称 new ReadingCalculateData (){QuestionType=QuestionType.LowVisit,GetStringFun=GetLowVisit,/*ChangeAllTaskFun=ChangeAllLowVisitName*/}, //是否存在非淋巴结靶病灶 @@ -438,6 +448,15 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate //被评估为NE的单个靶病灶 new ReadingCalculateData (){QuestionType=QuestionType.NETarget,GetStringFun=GetNETarget}, + // 与前一访视SOD相比变化量 + new ReadingCalculateData (){QuestionType=QuestionType.LastVisitSODChange,GetDecimalNullFun=GetLastTaskSODChange}, + + //新靶病灶直径之和(iSOD) + new ReadingCalculateData (){QuestionType=QuestionType.ISOD,GetDecimalNullFun=GetiSODData}, + + // 与前一访视相比iSOD变化量 + new ReadingCalculateData (){QuestionType=QuestionType.LastVisitiSODChange,GetDecimalNullFun=GetISODChange}, + //靶病灶评估 new ReadingCalculateData (){QuestionType=QuestionType.TargetLesion,GetStringFun=GetTargetLesionEvaluate}, @@ -739,15 +758,14 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate await _generalCalculateService.AddConvertedTaskFocus(taskinfo.Id, taskinfo.BeforeConvertedTaskId.Value); } else - { - var LastVisitTaskId = await _visitTaskRepository.Where(x => (x.ReadingCategory == ReadingCategory.Visit && + var LastVisitTaskId = 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) || (x.Id == taskinfo.BeforeConvertedTaskId) + && x.VisitTaskNum < taskinfo.VisitTaskNum && x.TaskState == TaskState.Effect ).OrderByDescending(x => x.VisitTaskNum).Select(x => x.Id).FirstOrDefaultAsync(); @@ -1182,6 +1200,96 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate } #endregion + #region 与前一访视SOD相比变化量 + /// + /// 与前一访视SOD相比变化量 + /// + /// + /// + public async Task GetLastTaskSODChange(ReadingCalculateDto inDto) + { + var lastTaskId = await this.GetLastVisitTaskId(inDto); + var lastSOD = (await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == lastTaskId && x.ReadingQuestionTrial.QuestionType == QuestionType.SOD).Select(x => x.Answer).FirstOrDefaultAsync()).IsNullOrEmptyReturn0(); + + var value = await GetSODData(inDto); + + if (value == null || inDto.IsBaseLine) + { + return null; + } + return value.NullChange0() - lastSOD; + } + #endregion + + #region 新靶病灶直径之和(iSOD) + + /// + /// 获取iSOD + /// + /// + /// + public async Task GetiSODData(ReadingCalculateDto inDto) + { + if (iSODData != null) + { + return iSODData.Value; + } + + var tableQuestion = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.NewTargetLesion).SelectMany(x => x.TableRowInfoList).ToList(); + + if (tableQuestion.Count() == 0) + { + return null; + } + + decimal result = 0; + + foreach (var item in tableQuestion) + { + if (item.TableQuestionList.Any(x => x.QuestionMark == QuestionMark.IsLymph && x.Answer.EqEnum(YesOrNoOrNa.Yes))) + { + // 淋巴结的短径 + result += (item.TableQuestionList.Where(x => x.QuestionMark == QuestionMark.ShortAxis).Select(x => x.Answer).FirstOrDefault()).IsNullOrEmptyReturn0(); + } + + if (item.TableQuestionList.Any(x => x.QuestionMark == QuestionMark.IsLymph && x.Answer.EqEnum(YesOrNoOrNa.No))) + { + // 非淋巴结的长径 + result += item.TableQuestionList.Where(x => x.QuestionMark == QuestionMark.MajorAxis).Select(x => x.Answer).FirstOrDefault().IsNullOrEmptyReturn0(); + } + } + + iSODData = result; + + return iSODData.Value; + + + + } + #endregion + + #region 与前一访视相比iSOD变化量 + + /// + /// 与前一访视相比iSOD变化量 + /// + /// + /// + public async Task GetISODChange(ReadingCalculateDto inDto) + { + + var lastTaskId = await this.GetLastVisitTaskId(inDto); + var lastiSOD = (await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == lastTaskId && x.ReadingQuestionTrial.QuestionType == QuestionType.ISOD).Select(x => x.Answer).FirstOrDefaultAsync()).IsNullOrEmptyReturn0(); + + var value = await GetiSODData(inDto); + + if (value == null || inDto.IsBaseLine) + { + return null; + } + return value.NullChange0() - lastiSOD; + } + #endregion #region 修改其他标准 @@ -1397,26 +1505,73 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate /// private async Task GetLastVisitTaskId(ReadingCalculateDto inDto) { - // 拿到这一个访视 - var thisNum = await _subjectVisitRepository.Where(x => x.Id == inDto.SubjectVisitId).Select(x => x.VisitNum).FirstOrDefaultAsync(); - // 先找到上一个访视 - var lastVisitId = await _subjectVisitRepository.Where(x => x.SubjectId == inDto.SubjectId && !x.IsLostVisit && x.VisitNum < thisNum).OrderByDescending(x => x.VisitNum).Select(x => x.Id).FirstOrDefaultAsync(); + if (lastVisitTaskId != null) + { + return lastVisitTaskId.Value; + } + else + { + var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).ProjectTo(_mapper.ConfigurationProvider).FirstNotNullAsync(); + var lastTaskId = 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).FirstOrDefaultAsync(); + lastVisitTaskId = lastTaskId; + return lastTaskId; + } + - // 找到访视任务Id - - var LastVisitTaskId = await _visitTaskRepository.Where(x => x.ReadingCategory == ReadingCategory.Visit && - x.TrialReadingCriterionId == inDto.TrialReadingCriterionId && - x.TaskState == TaskState.Effect && - x.IsAnalysisCreate == inDto.IsAnalysisCreate - && x.SourceSubjectVisitId == lastVisitId && x.ArmEnum==inDto.ArmEnum).Select(x => x.Id).FirstOrDefaultAsync(); - - return LastVisitTaskId; + + } #endregion #region 计算阅片问题 外层问题 + #region 获取IRECIST靶病灶评估 + + /// + /// 获取IRECIST靶病灶评估 + /// + /// + /// + public async Task GetIRECISTTargetLesionEvaluate(ReadingCalculateDto inDto) + { + //if(基线没有靶病灶) + //{ + // 靶病灶疗效为 ND + //}else if ((上一访视评估为iCPD && 本次访视满足RECIST1.1的PD条件)|| 上一访视评估为iUPD || 本次访视SOD增加不小于5mm) + //{ + // 靶病灶疗效为 ICPD + //} else if (本次访视满足RECIST1.1的PD条件 && (比整体访视期间最低点SOD增加≥20 % && 比整体访视期间最低点SOD绝对增加值≥5 mm)|| (前一访视评估为iCR && 当前访视至少有一个“存在”状态的靶病灶)) + + //{ + // 靶病灶疗效为 iUPD + //} else if (有任一靶病灶为NE状态) + // { + // 靶病灶疗效为 NE + //} + // else if (所有非淋巴结靶病灶消失,径线总和为0 mm && 所有淋巴结靶病灶的短径缩小到 < 10 mm) + //{ + // 靶病灶疗效为 iCR + //} else if (与基线期SOD相比减小≥30 %) + //{ + // 靶病灶疗效为 iPR + //} + //else + // { + // 靶病灶疗效为 iSD + //} + return string.Empty; + } + #endregion + + #region 获取靶病灶评估 /// /// 获取靶病灶评估 diff --git a/IRaCIS.Core.Domain.Share/Reading/ReadEnum.cs b/IRaCIS.Core.Domain.Share/Reading/ReadEnum.cs index aeb673415..efc847663 100644 --- a/IRaCIS.Core.Domain.Share/Reading/ReadEnum.cs +++ b/IRaCIS.Core.Domain.Share/Reading/ReadEnum.cs @@ -1199,11 +1199,48 @@ namespace IRaCIS.Core.Domain.Share /// DaysBetween = 22, + /// + /// 与前一访视SOD相比变化量 + /// + LastVisitSODChange = 23, + + /// + /// 新靶病灶直径之和(iSOD) + /// + ISOD = 24, + + /// + /// 与前一访视相比iSOD变化量 + /// + LastVisitiSODChange = 25, + + /// + /// 新靶病灶评估 + /// + NewTargetLesion = 26, + + /// + /// 新非靶病灶评估 + /// + NewNoTargetLesion = 27, + + /// + /// 其它既往新病灶评估 + /// + OtherNewTargetLesion = 28, + + /// + /// 触发iRECIST后新病灶评估 + /// + IRECISTNewTargetLesion = 29, + /// /// 新病灶评估 /// NewLesionEvaluation = 30, + + /// /// 是否脑转移 ///