diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml index 4fd242949..cc50e8291 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -3170,6 +3170,109 @@ 阅片计算 + + + 获取SOD + + + 靶病灶径线之和(SOD) + 非淋巴结的长径 和淋巴结的短径 + + + + + + 非淋巴结靶病灶长径之和 + + + + + + + 与基线SOD相比变化量(mm) + + + + + + + 与整个访视期间最低点相比增加的百分比 + + + + + + + 与整个访视期间最低点相比增加的值(mm) + + + + 要更新之前的 + + + + + + 与整个访视期间最低点相比增加的百分比 + + + + 要更新之前的 + + + + + + 整个访视期间最低点访视名称 + + + + 要更新之前的 + + + + + + 是否存在非淋巴结靶病灶 + + + + + + + 是否存在淋巴结靶病灶且该病灶比上一访视短径增加5MM以上 + + + + + + + 被评估为NE的单个靶病灶 + + + + + + + 整体肿瘤评估 + + + + + + + 获取基线SOD + + + + + + + 获取访视任务信息 + + + + 阅片医学审核 @@ -3789,6 +3892,36 @@ 标准 病灶类型 + + + 阅片计算Dto + + + + + 答案 + + + + + 病灶类型 + + + + + 答案 + + + + + 问题Id + + + + + 问题标识 + + 类型 diff --git a/IRaCIS.Core.Application/Service/Reading/Dto/ReadingCalculateViewModel.cs b/IRaCIS.Core.Application/Service/Reading/Dto/ReadingCalculateViewModel.cs index f1d63b2c3..231a57382 100644 --- a/IRaCIS.Core.Application/Service/Reading/Dto/ReadingCalculateViewModel.cs +++ b/IRaCIS.Core.Application/Service/Reading/Dto/ReadingCalculateViewModel.cs @@ -7,8 +7,85 @@ using System; using IRaCIS.Core.Domain.Share; using System.Collections.Generic; namespace IRaCIS.Core.Application.ViewModel -{ - +{ + /// + /// 阅片计算Dto + /// + public class ReadingCalculateDto + { + + public Guid SubjectId { get; set; } + + public Guid VisitTaskId { get; set; } + + public List QuestionInfo { get; set; } = new List(); + + + } + + + + public class QuestionInfo + { + + public Guid QuestionId { get; set; } + + /// + /// 答案 + /// + public string Answer { get; set; } + + + /// + /// 病灶类型 + /// + public LesionType? LesionType { get; set; } + + public QuestionType? QuestionType { get; set; } + + + + public List TableRowInfoList = new List(); + + + } + + + public class TableRowInfo + { + public int RowIndex { get; set; } + + public List TableQuestionList { get; set; } = new List(); + } + + public class TableQuestionInfo + { + /// + /// 答案 + /// + public string Answer { get; set; } + + /// + /// 问题Id + /// + public Guid TableQuestionId { get; set; } + + + /// + /// 问题标识 + /// + public QuestionMark? QuestionMark { get; set; } + + } + + + + public class VisitTaskAnswerInfo + { + public string VisitName { get; set; } + + public decimal SOD { get; set; } + } } diff --git a/IRaCIS.Core.Application/Service/Reading/ReadingCalculateService.cs b/IRaCIS.Core.Application/Service/Reading/ReadingCalculateService.cs index 7e5304db6..a12cc6b84 100644 --- a/IRaCIS.Core.Application/Service/Reading/ReadingCalculateService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ReadingCalculateService.cs @@ -9,23 +9,317 @@ using Microsoft.AspNetCore.Mvc; using IRaCIS.Core.Application.Interfaces; using IRaCIS.Core.Application.ViewModel; using Panda.DynamicWebApi.Attributes; +using IRaCIS.Core.Domain.Share; namespace IRaCIS.Core.Application.Service -{ +{ /// /// 阅片计算 /// [NonDynamicWebApi] - [ ApiExplorerSettings(GroupName = "Reading")] + [ApiExplorerSettings(GroupName = "Reading")] public class ReadingCalculateService : BaseService, IReadingCalculateService { private readonly IRepository _readingTableQuestionAnswerRepository; + private readonly IRepository _visitTaskRepository; + private readonly IRepository _tumorAssessmentRepository; + private readonly IRepository _readingTaskQuestionAnswerRepository; - public ReadingCalculateService(IRepository readingTableQuestionAnswerRepository) + public ReadingCalculateService( + IRepository readingTableQuestionAnswerRepository, + IRepository visitTaskRepository, + IRepository tumorAssessmentRepository, + IRepository ReadingTaskQuestionAnswerRepository + ) { - _readingTableQuestionAnswerRepository = readingTableQuestionAnswerRepository; + this._readingTableQuestionAnswerRepository = readingTableQuestionAnswerRepository; + this._visitTaskRepository = visitTaskRepository; + this._tumorAssessmentRepository = tumorAssessmentRepository; + this._readingTaskQuestionAnswerRepository = ReadingTaskQuestionAnswerRepository; } - } -} + + #region 获取SOD + + /// + /// 获取SOD + /// + /// + /// 靶病灶径线之和(SOD) + /// 非淋巴结的长径 和淋巴结的短径 + /// + /// + public async Task GetSODData(ReadingCalculateDto inDto) + { + var tableQuestion = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.TargetLesion).SelectMany(x => x.TableRowInfoList).ToList(); + + decimal result = 0; + + foreach (var item in tableQuestion) + { + if (item.TableQuestionList.Any(x => x.QuestionMark == QuestionMark.IsLymph && x.Answer == "是")) + { + // 淋巴结的短径 + result += decimal.Parse(item.TableQuestionList.Where(x => x.QuestionMark == QuestionMark.ShortAxis).Select(x => x.Answer).FirstOrDefault() ?? "0"); + } + + if (item.TableQuestionList.Any(x => x.QuestionMark == QuestionMark.IsLymph && x.Answer == "否")) + { + // 非淋巴结的长径 + result += decimal.Parse(item.TableQuestionList.Where(x => x.QuestionMark == QuestionMark.MajorAxis).Select(x => x.Answer).FirstOrDefault() ?? "0"); + } + } + + + return result; + + + } + #endregion + + #region 非淋巴结靶病灶长径之和 + /// + /// 非淋巴结靶病灶长径之和 + /// + /// + /// + public async Task GetSumOfDiameter(ReadingCalculateDto inDto) + { + var tableQuestion = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.TargetLesion).SelectMany(x => x.TableRowInfoList).ToList(); + + decimal result = 0; + + foreach (var item in tableQuestion) + { + if (item.TableQuestionList.Any(x => x.QuestionMark == QuestionMark.IsLymph && x.Answer == "否")) + { + // 非淋巴结的长径 + result += decimal.Parse(item.TableQuestionList.Where(x => x.QuestionMark == QuestionMark.MajorAxis).Select(x => x.Answer).FirstOrDefault() ?? "0"); + } + } + + + return result; + } + #endregion + + #region 与基线SOD相比变化量(mm) + /// + /// 与基线SOD相比变化量(mm) + /// + /// + /// + public async Task GetSODChange(ReadingCalculateDto inDto) + { + return await GetSODData(inDto) - await GetBaseLineSOD(inDto); + } + #endregion + + #region 与整个访视期间最低点相比增加的百分比 + /// + /// 与整个访视期间最低点相比增加的百分比 + /// + /// + /// + public async Task GetSODPercent(ReadingCalculateDto inDto) + { + var thisSOD = await GetSODData(inDto); + var baseLineSOD = await GetBaseLineSOD(inDto); + + if (baseLineSOD == 0) + { + return 100; + } + else + { + return decimal.Round(thisSOD * 100 / baseLineSOD, 2); + } + } + #endregion + + #region 与整个访视期间最低点相比增加的值(mm) + /// + /// 与整个访视期间最低点相比增加的值(mm) + /// + /// + /// + /// 要更新之前的 + /// + /// + public async Task GetLowestIncrease(ReadingCalculateDto inDto) + { + var decimalAnswerList = await GetVisitTaskAnswerList(inDto); + var minSOD = decimalAnswerList.OrderBy(x => x.SOD).Select(x => x.SOD).FirstOrDefault(); + return await GetSODData(inDto) - minSOD; + } + #endregion + + #region 与整个访视期间最低点相比增加的百分比 + /// + /// 与整个访视期间最低点相比增加的百分比 + /// + /// + /// + /// 要更新之前的 + /// + /// + public async Task GetLowPercent(ReadingCalculateDto inDto) + { + var thisSOD = await GetSODData(inDto); + var decimalAnswerList = await GetVisitTaskAnswerList(inDto); + var minSOD = decimalAnswerList.OrderBy(x => x.SOD).Select(x => x.SOD).FirstOrDefault(); + + if (minSOD == 0) + { + return 100; + } + else + { + return decimal.Round(thisSOD * 100 / minSOD, 2); + } + + + } + #endregion + + #region 整个访视期间最低点访视名称 + /// + /// 整个访视期间最低点访视名称 + /// + /// + /// + /// 要更新之前的 + /// + /// + public async Task GetLowVisit(ReadingCalculateDto inDto) + { + var decimalAnswerList = await GetVisitTaskAnswerList(inDto); + return decimalAnswerList.OrderBy(x => x.SOD).Select(x => x.VisitName).FirstOrDefault() ?? string.Empty; + } + #endregion + + #region 是否存在非淋巴结靶病灶 + /// + /// 是否存在非淋巴结靶病灶 + /// + /// + /// + public async Task GetIsLymphTarget(ReadingCalculateDto inDto) + { + var tableQuestion = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.TargetLesion).SelectMany(x => x.TableRowInfoList).ToList(); + + foreach (var item in tableQuestion) + { + if (item.TableQuestionList.Any(x => x.QuestionMark == QuestionMark.IsLymph && x.Answer == "是")) + { + return "是"; + } + } + + return "否"; + } + #endregion + + #region 是否存在淋巴结靶病灶且该病灶比上一访视短径增加5MM以上 + /// + /// 是否存在淋巴结靶病灶且该病灶比上一访视短径增加5MM以上 + /// + /// + /// + public async Task GetIsAddFive(ReadingCalculateDto inDto) + { + return string.Empty; + } + #endregion + + #region 被评估为NE的单个靶病灶 + /// + /// 被评估为NE的单个靶病灶 + /// + /// + /// + public async Task GetNETarget(ReadingCalculateDto inDto) + { + var result = inDto.QuestionInfo.Any(x => x.QuestionType == QuestionType.TargetLesion && x.Answer == "NE"); + + return result ? "有" : "无"; + } + #endregion + + #region 整体肿瘤评估 + + /// + /// 整体肿瘤评估 + /// + /// + /// + public async Task GetTumor(ReadingCalculateDto inDto) + { + var targetLesion = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.TargetLesion).Select(x => x.Answer).FirstOrDefault(); + var noTargetLesion = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.NoTargetLesion).Select(x => x.Answer).FirstOrDefault(); + var newLesions = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.NewLesions).Select(x => x.Answer).FirstOrDefault(); + var result = await _tumorAssessmentRepository.Where(x => x.TargetLesion == targetLesion && x.NonTargetLesions == noTargetLesion && x.NewLesion == newLesions).Select(x => x.OverallEfficacy).FirstOrDefaultAsync(); + + return result ?? string.Empty; + + } + #endregion + + #region 通用方法 + + #region 获取基线SOD + /// + /// 获取基线SOD + /// + /// + /// + private async Task GetBaseLineSOD(ReadingCalculateDto inDto) + { + if (await _visitTaskRepository.AnyAsync(x => x.Id == inDto.VisitTaskId && x.SourceSubjectVisit.IsBaseLine)) + { + return 0; + } + + // 先找到基线的任务 + var baseLineTaskId = await _visitTaskRepository.Where(x => x.SubjectId == inDto.SubjectId && x.ReadingCategory == ReadingCategory.Visit + && x.SourceSubjectVisit.IsBaseLine && x.TaskState == TaskState.Effect) + .Select(x => x.Id).FirstOrDefaultAsync(); + + + var baseLineSOD = decimal.Parse(await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == baseLineTaskId && x.ReadingQuestionTrial.QuestionType == QuestionType.SOD).Select(x => x.Answer).FirstOrDefaultAsync() ?? "0"); + return baseLineSOD; + } + #endregion + + #region 获取访视任务信息 + /// + /// 获取访视任务信息 + /// + /// + /// + private async Task> GetVisitTaskAnswerList(ReadingCalculateDto inDto) + { + var answerList = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTask.ReadingCategory == ReadingCategory.Visit + && x.SubjectId == inDto.SubjectId && x.VisitTask.ReadingTaskState == ReadingTaskState.HaveSigned && x.VisitTask.TaskState == TaskState.Effect && x.ReadingQuestionTrial.QuestionType == QuestionType.SOD) + .Select(x => new + { + VisitName = x.VisitTask.SourceSubjectVisit.VisitName, + SOD = x.Answer + }).ToListAsync(); + + var decimalAnswerList = answerList.Select(x => new VisitTaskAnswerInfo + { + VisitName = x.VisitName, + SOD = decimal.Parse(x.SOD ?? "0"), + }).ToList(); + + return decimalAnswerList; + } + #endregion + + + #endregion + + } +}