From 998b92aa79ccb22250e3d6d7609f351dd74ca1e3 Mon Sep 17 00:00:00 2001
From: hang <872297557@qq.com>
Date: Mon, 27 Oct 2025 10:48:31 +0800
Subject: [PATCH] =?UTF-8?q?=E8=AF=84=E4=BC=B0=E7=BB=9F=E8=AE=A1=E5=88=9D?=
=?UTF-8?q?=E6=AD=A5=E5=A2=9E=E5=8A=A0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../IRaCIS.Core.Application.xml | 13 +
.../TrialSiteUser/DTO/TrialStatViewModel.cs | 36 +-
.../Service/TrialSiteUser/TrialStatService.cs | 316 +++++++++++++++++-
3 files changed, 341 insertions(+), 24 deletions(-)
diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
index e83e73b9c..bdba84e25 100644
--- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
+++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
@@ -9438,6 +9438,11 @@
融合的CTSeriesId
+
+
+ 比例
+
+
@@ -13675,6 +13680,14 @@
+
+
+ 修改比例修改答案
+
+
+
+
+
删除绑定关系
diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialStatViewModel.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialStatViewModel.cs
index e60d03b3b..1fcddc4d4 100644
--- a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialStatViewModel.cs
+++ b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialStatViewModel.cs
@@ -87,7 +87,7 @@ namespace IRaCIS.Core.Application.ViewModel
public class EfficacyEvaluationStatViewModel
{
- public int OverallTumorEvaluation { get; set; }
+ public string OverallTumorEvaluation { get; set; }
public int SubjectCount { get; set; }
}
@@ -135,26 +135,24 @@ namespace IRaCIS.Core.Application.ViewModel
public string JudgeNote { get; set; } = string.Empty;
- public string VisitNote { get; set; }
-
-
-
-
-
-
-
-
-
-
-
-
-
- public Guid? DoctorUserId { get; set; }
- public string UserName { get; set; }
- public List QuestionAnswerList { get; set; }
public List SubjectCriterionReadingPeriodVisitNumList { get; set; }
- public String TrialSiteCode { get; set; } = String.Empty;
+
+
+
+ public string OverallTumorEvaluation { get; set; }
+
+
+
+
+
+ //public string VisitNote { get; set; }
+
+ //public Guid? DoctorUserId { get; set; }
+ //public string UserName { get; set; }
+ //public List QuestionAnswerList { get; set; }
+
+ //public String TrialSiteCode { get; set; } = String.Empty;
}
}
diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialStatService.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialStatService.cs
index f92b862d3..b88e8fdb6 100644
--- a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialStatService.cs
+++ b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialStatService.cs
@@ -1,21 +1,26 @@
-using IRaCIS.Core.Application.ViewModel;
+using IRaCIS.Core.Application.Contracts;
+using IRaCIS.Core.Application.ViewModel;
+using IRaCIS.Core.Domain.Share;
+using IRaCIS.Core.Infra.EFCore.Common;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using static IRaCIS.Core.Application.Service.ExcelExportHelper;
namespace IRaCIS.Core.Application;
[ApiExplorerSettings(GroupName = "Trial")]
public class TrialStatService(
IRepository _trialRepository,
- IRepository _subjectVisitRepository,
+ IRepository _subjectVisitRepository,
IRepository _trialDocumentRepository,
IRepository _systemDocumentRepository,
IRepository _systemNoticeRepository,
- IRepository _visitTaskRepository,
+ IRepository _visitTaskRepository,
+ IRepository _readingQuestionCriterionTrialRepository,
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService
{
@@ -94,8 +99,38 @@ public class TrialStatService(
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 }).FirstNotNullAsync();
+
+
+ if (criterion.CriterionGroup == CriterionGroup.Nontumorous)
+ {
+ return new List();
+ }
+
+
+ var questionType = QuestionType.Tumor;
+ if (criterion.CriterionType == CriterionType.RECIST1Point1 || criterion.CriterionType == CriterionType.RECIST1Pointt1_MB
+ || criterion.CriterionType == CriterionType.IRECIST1Point1 || criterion.CriterionType == CriterionType.mRECISTHCC)
+ {
+
+ questionType = QuestionType.Tumor;
+
+ }
+ else if (criterion.CriterionType == CriterionType.Lugano2014 || criterion.CriterionType == CriterionType.Lugano2014WithoutPET)
+ {
+
+ questionType = QuestionType.ImgOncology;
+ }
+ else if (criterion.CriterionType == CriterionType.PCWG3)
+ {
+
+ }
+
var query = _visitTaskRepository
- .Where(t => t.TrialId == inQuery.TrialId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId && t.IsAnalysisCreate == false && (t.TaskState == TaskState.Effect || t.TaskState == TaskState.Freeze))
+ .Where(t => t.TrialId == inQuery.TrialId && t.TrialReadingCriterionId == trialReadingCriterionId && t.IsAnalysisCreate == false && (t.TaskState == TaskState.Effect || t.TaskState == TaskState.Freeze))
//访视和全局查询已签名完成的,裁判可以是未签名,未完成的
.Where(t => (t.ReadingTaskState == ReadingTaskState.HaveSigned && (t.ReadingCategory == ReadingCategory.Visit || t.ReadingCategory == ReadingCategory.Global)) || t.ReadingCategory == ReadingCategory.Judge)
@@ -109,12 +144,283 @@ public class TrialStatService(
TaskBlindName = t.TaskBlindName,
ReadingTaskState = t.ReadingTaskState,
ReadingCategory = t.ReadingCategory,
+ ArmEnum = t.ArmEnum,
+ JudgeArmEnum = t.JudgeResultTask.ArmEnum,
+ IsTrigerJudge = criterion.ArbitrationRule == ArbitrationRule.Visit ? t.JudgeVisitTaskId != null :
+ (criterion.ArbitrationRule == ArbitrationRule.Reading ?
+ t.Subject.SubjectVisitTaskList.Any(c => c.TaskState == TaskState.Effect && c.IsAnalysisCreate == false && c.ReadingCategory == ReadingCategory.Judge && c.TrialReadingCriterionId == trialReadingCriterionId
+ && t.VisitTaskNum < c.VisitTaskNum) :
+ false),
+ JudgeNote = t.ReadingCategory == ReadingCategory.Judge ? t.JudgeResultRemark : "",
+ SubjectCriterionReadingPeriodVisitNumList = t.Subject.ReadModuleList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId && t.ReadingSetType == ReadingSetType.ImageReading).Select(c => c.SubjectVisit.VisitNum).ToList(),
+ //整体肿瘤评估答案
+ OverallTumorEvaluation = t.ReadingTaskQuestionAnswerList.Where(c => c.ReadingQuestionTrial.QuestionType == questionType).FirstOrDefault()!.Answer
});
- return new List { };
+
+ var list = await query.ToListAsync();
+
+
+
+ if (criterion.IsArbitrationReading)
+ {
+ //找到只有一个人阅片的受试者 和访视
+ var exceptVisit = list.Where(t => t.ReadingCategory == ReadingCategory.Visit)
+ .GroupBy(t => new { t.SubjectCode, t.TaskName }).Where(g => g.Count() == 1).Select(g => new { g.Key.SubjectCode, g.Key.TaskName }).ToList();
+
+ list = list.Where(t => !exceptVisit.Any(ev => ev.SubjectCode == t.SubjectCode && ev.TaskName == t.TaskName)).ToList();
+ }
+
+
+ list = list.OrderBy(t => t.SubjectCode).ThenBy(t => t.ArmEnum).ThenBy(t => t.VisitTaskNum).ToList();
+
+ //处理裁判标记
+ list = DealJudgeMark(criterion.ArbitrationRule, criterion.IsGlobalReading, list);
+
+
+ //判断subject的逻辑需要确认,这么多次访视任务,有的符合,有的不符合,准则是什么?
+ return list.GroupBy(t => t.OverallTumorEvaluation).Select(g => new EfficacyEvaluationStatViewModel()
+ {
+ OverallTumorEvaluation = g.Key,
+ SubjectCount = g.Select(t => t.SubjectId).Distinct().Count()
+ }).ToList();
+
}
+
+
+ public List DealJudgeMark(ArbitrationRule arbitrationRule, bool isGlobalReading, IEnumerable list) where T : EfficacyEvaluationExport
+ {
+ //处理访视任务的裁判标记
+ var resultExceptJudgeList = list.Where(t => t.ReadingCategory != ReadingCategory.Judge).ToList();
+
+ var judegeList = list.Where(t => t.ReadingCategory == ReadingCategory.Judge).ToList();
+
+ if (arbitrationRule == ArbitrationRule.Visit)
+ {
+
+ foreach (var item in resultExceptJudgeList)
+ {
+ var findJudge = judegeList.FirstOrDefault(t => t.SubjectCode == item.SubjectCode
+ && (t.VisitTaskNum - ReadingCommon.TaskNumDic[ReadingCategory.Judge]) == item.VisitTaskNum);
+
+ if (findJudge != null)
+ {
+ if (findJudge.ReadingTaskState == ReadingTaskState.HaveSigned)
+ {
+ item.IsJudgeSelect = findJudge.JudgeArmEnum == item.ArmEnum ? true : false;
+
+ item.JudgeNote = findJudge.JudgeArmEnum == item.ArmEnum ? findJudge.JudgeNote : string.Empty;
+ }
+ else
+ {
+ //默认也是null 其实不用赋值
+ item.IsJudgeSelect = null;
+ }
+ }
+ else
+ {
+
+ //两个人都做了
+ if (resultExceptJudgeList.Where(t => t.VisitTaskNum == item.VisitTaskNum && t.SubjectCode == item.SubjectCode).Select(t => t.ArmEnum).Distinct().Count() == 2)
+ {
+ //如果没有产生裁判,默认选择R1
+ if (item.ArmEnum == Arm.DoubleReadingArm1)
+ {
+ item.IsJudgeSelect = true;
+ }
+ else
+ {
+ item.IsJudgeSelect = false;
+ }
+ }
+ else
+ {
+ item.IsJudgeSelect = null;
+ item.IsTrigerJudge = null;
+ }
+
+
+
+ }
+ }
+
+ }
+ else if (arbitrationRule == ArbitrationRule.Reading)
+ {
+ //处理访视裁判标记
+ foreach (var visitItem in resultExceptJudgeList.Where(t => t.ReadingCategory == ReadingCategory.Visit))
+ {
+ ////默认设置为false 只处理为true 和 空的情况
+ //visitItem.IsJudgeSelect = false;
+
+ var subjectJudgeList = judegeList.Where(t => t.SubjectCode == visitItem.SubjectCode).ToList();
+
+ //阅片期访视号
+ var subjectReadingPeriondVisitNumList = resultExceptJudgeList.Where(t => t.SubjectCode == visitItem.SubjectCode).FirstOrDefault()?.SubjectCriterionReadingPeriodVisitNumList;
+
+ //两个人完成最大得任务号(访视+全局)
+ var subjectMaxFinishedTaskNum = resultExceptJudgeList.Where(t => t.SubjectCode == visitItem.SubjectCode)
+ .GroupBy(t => t.VisitTaskNum).Where(g => g.Count() == 2).Select(g => g.Key).DefaultIfEmpty().Max();
+
+ var addReadingPeriodNum = isGlobalReading ? ReadingCommon.TaskNumDic[ReadingCategory.Global] : 0;
+
+ var finishedGlobalCount = 0;
+
+ //没有配置阅片期
+ if (subjectReadingPeriondVisitNumList == null)
+ {
+ finishedGlobalCount = 0;
+ }
+ else
+ {
+ //已完成的全局数量
+ finishedGlobalCount = resultExceptJudgeList.Where(t => t.SubjectCode == visitItem.SubjectCode && subjectReadingPeriondVisitNumList.Any(c => (c + addReadingPeriodNum) == t.VisitTaskNum)
+ /*&& t.ReadingCategory == ReadingCategory.Global*/)
+ .Select(t => new { t.VisitTaskNum, t.ArmEnum }).Distinct()
+ .GroupBy(t => t.VisitTaskNum).Where(g => g.Count() == 2).Select(g => g.Key).Count();
+ }
+
+
+ visitItem.IsJudgeSelect = null;
+ visitItem.IsTrigerJudge = null;
+
+ if (finishedGlobalCount != 0)
+ {
+ //最大的全局是否产生裁判
+
+ var subjectMaxFinishedGlobalTaskNum = resultExceptJudgeList.Where(t => t.SubjectCode == visitItem.SubjectCode && subjectReadingPeriondVisitNumList.Any(c => (c + addReadingPeriodNum) == t.VisitTaskNum)
+ /*&& t.ReadingCategory == ReadingCategory.Global*/)
+ .Select(t => new { t.VisitTaskNum, t.ArmEnum }).Distinct()
+ .GroupBy(t => t.VisitTaskNum).Where(g => g.Count() == 2).Select(g => g.Key).DefaultIfEmpty().Max();
+
+ //最大的完成的全局是否产生裁判
+ if (subjectJudgeList.Any(t => t.VisitTaskNum == (subjectMaxFinishedGlobalTaskNum + ReadingCommon.TaskNumDic[ReadingCategory.Judge])))
+ {
+
+ var maxJudge = subjectJudgeList.FirstOrDefault(t => t.VisitTaskNum == (subjectMaxFinishedGlobalTaskNum + ReadingCommon.TaskNumDic[ReadingCategory.Judge]));
+
+ //最大裁判完成了
+ if (maxJudge.ReadingTaskState == ReadingTaskState.HaveSigned)
+ {
+ if (visitItem.VisitTaskNum < maxJudge.VisitTaskNum)
+ {
+ //触发裁判
+ visitItem.IsTrigerJudge = true;
+
+ if (visitItem.ArmEnum == maxJudge.JudgeArmEnum)
+ {
+ visitItem.IsJudgeSelect = true;
+ visitItem.JudgeNote = maxJudge.JudgeNote;
+ }
+ //裁判没选择的人设置为false
+ else
+ {
+ visitItem.IsJudgeSelect = false;
+ }
+ }
+ else
+ {
+ //后续访视 未知 默认都是null
+
+ }
+ }
+ else
+ {
+ //找到当前未阅最大裁判之前的已完成的最大裁判任务
+ var maxFinishedJudge = subjectJudgeList.Where(t => t.ReadingTaskState == ReadingTaskState.HaveSigned).OrderByDescending(t => t.VisitTaskNum).FirstOrDefault();
+
+ if (maxFinishedJudge == null)
+ {
+ // 为空 裁判选择标记默认就是null 不用处理
+
+ if (visitItem.VisitTaskNum < maxJudge.VisitTaskNum)
+ {
+ visitItem.IsTrigerJudge = true;
+ }
+
+ }
+ else
+ {
+ if (visitItem.VisitTaskNum < maxFinishedJudge.VisitTaskNum)
+ {
+ visitItem.IsTrigerJudge = true;
+
+ if (visitItem.ArmEnum == maxFinishedJudge.JudgeArmEnum)
+ {
+ visitItem.IsJudgeSelect = true;
+ visitItem.JudgeNote = maxFinishedJudge.JudgeNote;
+ }
+ //裁判没选择的人设置为false
+ else
+ {
+ visitItem.IsJudgeSelect = false;
+ }
+ }
+ else if (visitItem.VisitTaskNum > maxFinishedJudge.VisitTaskNum && visitItem.VisitTaskNum < maxJudge.VisitTaskNum)
+ {
+ //完成裁判 和未完成裁判之间的 裁判选择标记默认是null
+
+ visitItem.IsTrigerJudge = true;
+ }
+ else
+ {
+ //在未完成全局裁判之后的访视 未知 默认都是null
+
+
+ }
+
+ }
+
+ }
+
+
+ }
+ else
+ {
+ //最大的完成的全局未产生裁判
+
+ if (visitItem.VisitTaskNum <= subjectMaxFinishedGlobalTaskNum)
+ {
+ visitItem.IsTrigerJudge = false;
+
+ if (visitItem.ArmEnum == Arm.DoubleReadingArm1)
+ {
+ visitItem.IsJudgeSelect = true;
+
+ }
+ else
+ {
+ visitItem.IsJudgeSelect = false;
+ }
+ }
+ else
+ {
+ //未产生裁判的全局之后的访视 两个标记都是null (后续可能还有全局,但是全局两个人没做完)
+ }
+
+
+ }
+
+
+ }
+
+
+
+ }
+ }
+ else
+ {
+ foreach (var visitItem in resultExceptJudgeList.Where(t => t.ReadingCategory == ReadingCategory.Visit))
+ {
+ visitItem.IsJudgeSelect = null;
+ visitItem.IsTrigerJudge = null;
+ }
+
+ }
+ return resultExceptJudgeList;
+ }
}
\ No newline at end of file