diff --git a/IRaCIS.Core.Application/Service/Reading/Dto/ReadingImageTaskViewModel.cs b/IRaCIS.Core.Application/Service/Reading/Dto/ReadingImageTaskViewModel.cs index 1d435bd13..1b9f72a09 100644 --- a/IRaCIS.Core.Application/Service/Reading/Dto/ReadingImageTaskViewModel.cs +++ b/IRaCIS.Core.Application/Service/Reading/Dto/ReadingImageTaskViewModel.cs @@ -2500,6 +2500,8 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto public Guid ReadingQuestionId { get; set; } public string QuestionName { get; set; } = string.Empty; public string Type { get; set; } = string.Empty; + + public ShowQuestion ShowQuestion { get; set; } public string TypeValue { get; set; } = string.Empty; public int ShowOrder { get; set; } public string Answer { get; set; } = string.Empty; @@ -2508,6 +2510,13 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto public ValueUnit? Unit { get; set; } public string? CustomUnit { get; set; } public ValueOfType? ValueType { get; set; } + public string ClassifyAlgorithms { get; set; } + + public ClassifyType? ClassifyType { get; set; } + + public Guid? ClassifyQuestionId { get; set; } + + public JudgeReadingQuestionType QuestionType { get; set; } = JudgeReadingQuestionType.Question; } diff --git a/IRaCIS.Core.Application/Service/Reading/Dto/ReadingQuestionViewModel.cs b/IRaCIS.Core.Application/Service/Reading/Dto/ReadingQuestionViewModel.cs index 6101cc51d..8f09ae0ec 100644 --- a/IRaCIS.Core.Application/Service/Reading/Dto/ReadingQuestionViewModel.cs +++ b/IRaCIS.Core.Application/Service/Reading/Dto/ReadingQuestionViewModel.cs @@ -29,6 +29,22 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto public List QuestionList { get; set; } = new List(); } + public class CopyTrialQuestionVisitJudgeRuleInDto + { + [NotDefault] + public Guid TrialReadingCriterionId { get; set; } + + /// + /// 来源访视 + /// + public decimal SourceVisitNum { get; set; } + + /// + /// 目标访视 + /// + public decimal TargetVisitNum { get; set; } + } + public class TrialQuestionVisitJudgeRuleItemDto { public Guid ReadingQuestionTrialId { get; set; } diff --git a/IRaCIS.Core.Application/Service/Reading/ReadingCriterion/ReadingCriterionService.cs b/IRaCIS.Core.Application/Service/Reading/ReadingCriterion/ReadingCriterionService.cs index 4b9eaa2c9..5ec42ce6d 100644 --- a/IRaCIS.Core.Application/Service/Reading/ReadingCriterion/ReadingCriterionService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ReadingCriterion/ReadingCriterionService.cs @@ -386,6 +386,36 @@ namespace IRaCIS.Core.Application.Service.RC [HttpPost] public async Task SetTrialJudgeRuleInfo(SetTrialJudgeRuleInfoInDto inDto) { + if (inDto.JudgeRuleEnum == JudgeRule.Consistent) + { + if (await _readingQuestionTrialRepository.AnyAsync(x => x.ReadingQuestionCriterionTrialId == inDto.TrialReadingCriterionId&& x.IsJudgeQuestion && x.LimitShow != LimitShow.AllShow)) + { + + + var questionList = await _readingQuestionTrialRepository + .Where(x => x.ReadingQuestionCriterionTrialId == inDto.TrialReadingCriterionId && x.IsJudgeQuestion && x.LimitShow != LimitShow.AllShow) + .OrderBy(x => x.ShowOrder) + .Select(x => new TrialQuestionVisitJudgeRuleItemDto + { + ReadingQuestionTrialId = x.Id, + QuestionName = x.QuestionName.LanguageName(x.QuestionEnName, _userInfo.IsEn_Us), + ShowOrder = x.ShowOrder, + Type = x.Type, + TypeValue = x.TypeValue, + QuestionGenre = x.QuestionGenre, + DictionaryCode = x.DictionaryCode, + Unit = x.Unit, + CustomUnit = x.CustomUnit, + }) + .ToListAsync(); + + var questionName=string.Join(",", questionList.Select(x => x.QuestionName)); + + + //---当前标准裁判规则为一致性,但存在非全部显示的裁判问题,操作失败 + throw new BusinessValidationFailedException(_localizer["JudgeCanNotLimitShow", questionName]); + } + } await _readingQuestionCriterionTrialRepository.UpdatePartialFromQueryAsync(x => x.Id == inDto.TrialReadingCriterionId, x => new ReadingQuestionCriterionTrial() { JudgeModeEnum = inDto.JudgeModeEnum, diff --git a/IRaCIS.Core.Application/Service/Reading/ReadingCriterion/ReadingQuestionService.cs b/IRaCIS.Core.Application/Service/Reading/ReadingCriterion/ReadingQuestionService.cs index 8c99a7088..e5c05b668 100644 --- a/IRaCIS.Core.Application/Service/Reading/ReadingCriterion/ReadingQuestionService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ReadingCriterion/ReadingQuestionService.cs @@ -36,12 +36,16 @@ namespace IRaCIS.Core.Application.Service IRepository _readingTaskQuestionAnswer, IRepository _previousPDFRepository, IRepository _readingQuestionVisitJudgeRuleRepository, + IRepository _visitStageRepository, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, IReadingQuestionService { #region 项目访视裁判规则 + + + /// /// 获取项目阅片标准各访视的裁判规则配置。 /// 未配置规则的访视问题也会返回,供前端直接进行配置。 @@ -50,8 +54,11 @@ namespace IRaCIS.Core.Application.Service public async Task> GetTrialQuestionVisitJudgeRule(GetTrialQuestionVisitJudgeRuleInDto inDto) { var questionList = await _readingQuestionTrialRepository - .Where(x=>!x.ExcludeShowVisitList.Contains(inDto.VisitNum)) .Where(x => x.ReadingQuestionCriterionTrialId == inDto.TrialReadingCriterionId && x.IsJudgeQuestion) + .Where(x => x.LimitShow == LimitShow.AllShow + || (x.LimitShow == LimitShow.BaseLineShow && inDto.VisitNum == 0) + || (x.LimitShow == LimitShow.FollowShow && inDto.VisitNum != 0) + || (x.LimitShow == LimitShow.ExcludeSomeVisits && !x.ExcludeShowVisitList.Contains(inDto.VisitNum))) .WhereIf(inDto.ReadingQuestionId != null, x => x.Id == inDto.ReadingQuestionId) .OrderBy(x => x.ShowOrder) .Select(x => new TrialQuestionVisitJudgeRuleItemDto @@ -128,6 +135,54 @@ namespace IRaCIS.Core.Application.Service return ResponseOutput.Result(await _readingQuestionVisitJudgeRuleRepository.SaveChangesAsync()); } + /// + /// 复制其他访视的项目阅片标准裁判规则配置。 + /// 目标访视不适用的问题保留其已有的不适用规则,不参与复制。 + /// + [HttpPost] + public async Task CopyTrialQuestionVisitJudgeRule(CopyTrialQuestionVisitJudgeRuleInDto inDto) + { + var targetQuestionIds = await _readingQuestionTrialRepository + .Where(x => x.ReadingQuestionCriterionTrialId == inDto.TrialReadingCriterionId && x.IsJudgeQuestion) + .Where(x => x.LimitShow == LimitShow.AllShow + || (x.LimitShow == LimitShow.BaseLineShow && inDto.TargetVisitNum == 0) + || (x.LimitShow == LimitShow.FollowShow && inDto.TargetVisitNum != 0) + || (x.LimitShow == LimitShow.ExcludeSomeVisits && !x.ExcludeShowVisitList.Contains(inDto.TargetVisitNum))) + .Select(x => x.Id) + .ToListAsync(); + + if (targetQuestionIds.Count == 0) + { + return ResponseOutput.Ok(); + } + + var sourceRules = await _readingQuestionVisitJudgeRuleRepository + .Where(x => x.VisitNum == inDto.SourceVisitNum && targetQuestionIds.Contains(x.ReadingQuestionId)) + .ToListAsync(); + + await _readingQuestionVisitJudgeRuleRepository.BatchDeleteNoTrackingAsync(x => + x.VisitNum == inDto.TargetVisitNum && targetQuestionIds.Contains(x.ReadingQuestionId)); + + var targetRules = sourceRules.Select(rule => new ReadingQuestionVisitJudgeRule + { + Id = NewId.NextGuid(), + ReadingQuestionId = rule.ReadingQuestionId, + VisitNum = inDto.TargetVisitNum, + AnswerGroup = rule.AnswerGroup, + AnswerCombination = rule.AnswerCombination, + JudgeType = rule.JudgeType, + JudgeDifferenceValue = rule.JudgeDifferenceValue, + JudgeDifferenceType = rule.JudgeDifferenceType, + }).ToList(); + + if (targetRules.Count > 0) + { + await _readingQuestionVisitJudgeRuleRepository.AddRangeAsync(targetRules); + } + + return ResponseOutput.Result(await _readingQuestionVisitJudgeRuleRepository.SaveChangesAsync()); + } + #endregion @@ -713,9 +768,61 @@ namespace IRaCIS.Core.Application.Service } var entity = await _readingQuestionTrialRepository.InsertOrUpdateAsync(indto, true); + await AddNAJudgeRule(entity); return ResponseOutput.Ok(entity.Id.ToString()); } + /// + /// 添加问题的不适用规则 + /// + /// + private async Task AddNAJudgeRule(ReadingQuestionTrial entity) + { + List visitNums = new List(); + if (entity.IsJudgeQuestion) + { + var visitStageNums = await _visitStageRepository + .Where(x => x.TrialId == entity.TrialId) + .Select(x => x.VisitNum) + .Distinct() + .ToListAsync(); + + switch (entity.LimitShow) + { + case LimitShow.BaseLineShow: + visitNums = visitStageNums.Where(x => x > 0).ToList(); + visitNums.Add(-1); + break; + case LimitShow.FollowShow: + visitNums.Add(0); + break; + case LimitShow.ExcludeSomeVisits: + visitNums = entity.ExcludeShowVisitList; + break; + } + } + + if (visitNums.Count==0) + { + return; + } + + + await _readingQuestionVisitJudgeRuleRepository.BatchDeleteNoTrackingAsync(x => + x.ReadingQuestionId == entity.Id && visitNums.Contains(x.VisitNum)); + + var rules = visitNums.Select(visitNum => new ReadingQuestionVisitJudgeRule + { + Id = NewId.NextGuid(), + ReadingQuestionId = entity.Id, + VisitNum = visitNum, + JudgeType = JudgeTypeEnum.None, + }).ToList(); + + await _readingQuestionVisitJudgeRuleRepository.AddRangeAsync(rules); + await _readingQuestionVisitJudgeRuleRepository.SaveChangesAsync(); + } + /// /// 获取项目问题(项目) /// diff --git a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingJudgeTaskService.cs b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingJudgeTaskService.cs index 36c25cd81..71f220b0a 100644 --- a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingJudgeTaskService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingJudgeTaskService.cs @@ -125,7 +125,7 @@ namespace IRaCIS.Core.Application.Service .Select(x => x.JudgeRuleEnum) .FirstNotNullAsync(); - var displayQuestions = await GetJudgeDisplayQuestions(r1Task.TrialReadingCriterionId, r1Task.VisitTaskNum, judgeRule); + var displayQuestions = await GetJudgeDisplayQuestions(r1Task.TrialReadingCriterionId, r1Task.VisitTaskNum, judgeRule, false); var judgeAnswers = displayQuestions .Select(x => new SingleVisitJudgeAnswerItemDto { @@ -175,7 +175,7 @@ namespace IRaCIS.Core.Application.Service { var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync(); var judgeRule = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == taskInfo.TrialReadingCriterionId).Select(x => x.JudgeRuleEnum).FirstNotNullAsync(); - var questionList = await GetJudgeDisplayQuestions(taskInfo.TrialReadingCriterionId, taskInfo.VisitTaskNum, judgeRule); + var questionList = await GetJudgeDisplayQuestions(taskInfo.TrialReadingCriterionId, taskInfo.VisitTaskNum, judgeRule, true); var questionIds = questionList.Select(x => x.Id).ToList(); var answers = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && questionIds.Contains(x.ReadingQuestionTrialId)).ToListAsync(); @@ -188,6 +188,7 @@ namespace IRaCIS.Core.Application.Service ReadingQuestionId = x.Id, QuestionName = x.QuestionName.LanguageName(x.QuestionEnName, _userInfo.IsEn_Us), Type = x.Type, + ShowQuestion = x.ShowQuestion, TypeValue = x.TypeValue, ShowOrder = x.ShowOrder, Answer = answers.FirstOrDefault(answer => answer.ReadingQuestionTrialId == x.Id)?.Answer ?? string.Empty, @@ -196,6 +197,11 @@ namespace IRaCIS.Core.Application.Service Unit = x.Unit, CustomUnit = x.CustomUnit, ValueType = x.ValueType, + + + ClassifyQuestionId = x.ClassifyQuestionId, + ClassifyAlgorithms = x.ClassifyAlgorithms, + ClassifyType = x.ClassifyType }).ToList(), }; } @@ -223,7 +229,7 @@ namespace IRaCIS.Core.Application.Service { var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync(); var judgeRule = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == taskInfo.TrialReadingCriterionId).Select(x => x.JudgeRuleEnum).FirstNotNullAsync(); - var displayQuestionIds = (await GetJudgeDisplayQuestions(taskInfo.TrialReadingCriterionId, taskInfo.VisitTaskNum, judgeRule)).Select(x => x.Id).ToList(); + var displayQuestionIds = (await GetJudgeDisplayQuestions(taskInfo.TrialReadingCriterionId, taskInfo.VisitTaskNum, judgeRule, true)).Select(x => x.Id).ToList(); var submittedQuestionIds = inDto.QuestionList.Select(x => x.ReadingQuestionId).ToList(); @@ -268,9 +274,10 @@ namespace IRaCIS.Core.Application.Service } - private async Task> GetJudgeDisplayQuestions(Guid trialReadingCriterionId, decimal visitNum, JudgeRule judgeRule) + private async Task> GetJudgeDisplayQuestions(Guid trialReadingCriterionId, decimal visitNum, JudgeRule judgeRule,bool isGetShowQuestion) { var questionList = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == trialReadingCriterionId && x.IsJudgeQuestion) + .WhereIf(!isGetShowQuestion,x=>x.ShowQuestion!= ShowQuestion.Hide) .WhereIf(visitNum == 0, x => x.LimitShow != LimitShow.FollowShow) .WhereIf(visitNum != 0, x => x.LimitShow != LimitShow.BaseLineShow) .Where(x=>x.LimitShow!=LimitShow.ExcludeSomeVisits||x.ExcludeShowVisitList.Contains(visitNum)) @@ -308,6 +315,7 @@ namespace IRaCIS.Core.Application.Service return questionList .Where(x => visitJudgeRules.FirstOrDefault(rule => rule.ReadingQuestionId == x.Id && rule.VisitNum == -1)?.JudgeType != JudgeTypeEnum.NotApplicable) + .OrderBy(x=>x.ShowOrder) .ToList(); } diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs index aab463e19..262d25d62 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs @@ -27,15 +27,16 @@ namespace IRaCIS.Core.Application IRepository _trialQCQuestionRepository, IRepository _readingQuestionCriterionTrialRepository, IRepository _readingQuestionTrialRepository, + IRepository _readingQuestionVisitJudgeRuleRepository, IRepository _trialCriterionDictionaryCode, IRepository _systemCriterionDictionaryCode, IRepository _readingQuestionCriterionSystemRepository, IRepository _clinicalDataTrialSetRepository, IRepository _readingCriterionPageRepository, - IRepository _systemCriterionKeyFileRepository, - IOSSService _oSSService, - - IRepository _trialCriterionKeyFileRepository, + IRepository _systemCriterionKeyFileRepository, + IOSSService _oSSService, + IRepository _visitStageRepository, + IRepository _trialCriterionKeyFileRepository, IOrganInfoService _iOrganInfoService, IRepository _trialBodyPartRepository, IRepository _readingCriterionDictionaryRepository, @@ -48,7 +49,7 @@ namespace IRaCIS.Core.Application IRepository _systemBasicDataRepository, IRepository _subjectVisitRepository, IRepository _enrollRepository, - IRepository _qcQuestionAnswerRepository, + IRepository _qcQuestionAnswerRepository, IRepository _trialStateChangeRepository, IRepository _readingTableQuestionTrialRepository, IRepository _dicomAERepository, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IFusionCache _fusionCache) : BaseService, ITrialConfigService @@ -105,6 +106,40 @@ namespace IRaCIS.Core.Application throw new BusinessValidationFailedException(_localizer["TrialConfig_JudgeTaskFail"]); } + if (trialCriterion.JudgeRuleEnum == JudgeRule.Difference) + { + var visitStageList = await _visitStageRepository.Where(x => x.TrialId == trialCriterion.TrialId).ToListAsync(); + + visitStageList.Add(new VisitStage() + { + VisitName = "Out of Plan", + VisitNum=-1, + }); + + + + var judgeCount = await _readingQuestionTrialRepository.CountAsync(x => x.ReadingQuestionCriterionTrialId == inDto.TrialReadingCriterionId && x.IsJudgeQuestion); + + var ruleList = await _readingQuestionVisitJudgeRuleRepository.Where(x => x.ReadingQuestionTrial.ReadingQuestionCriterionTrialId == inDto.TrialReadingCriterionId).ToListAsync(); + + var errorList = new List(); + + visitStageList.ForEach(x => + { + if (judgeCount != ruleList.Count(y => y.VisitNum == x.VisitNum)) + { + errorList.Add(x.VisitName); + } + + }); + + if (errorList.Count() > 0) + { + throw new BusinessValidationFailedException(_localizer["TrialConfig_VisitjudgeDeficiency", string.Join(",", errorList)]); + } + + + } return ResponseOutput.Ok(true); } diff --git a/IRaCIS.Core.Domain/Reading/ReadingCriterionQuestion/ReadingQuestionVisitJudgeRule.cs b/IRaCIS.Core.Domain/Reading/ReadingCriterionQuestion/ReadingQuestionVisitJudgeRule.cs index 67dcf892d..e44d8c6b1 100644 --- a/IRaCIS.Core.Domain/Reading/ReadingCriterionQuestion/ReadingQuestionVisitJudgeRule.cs +++ b/IRaCIS.Core.Domain/Reading/ReadingCriterionQuestion/ReadingQuestionVisitJudgeRule.cs @@ -21,7 +21,7 @@ public class ReadingQuestionVisitJudgeRule : BaseAddAuditEntity public Guid ReadingQuestionId { get; set; } /// - /// 访视Num + /// 访视Num (计划外是-1) /// public decimal VisitNum { get; set; }