using IRaCIS.Application.Interfaces; using IRaCIS.Core.Infra.EFCore; using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Application.Filter; using Microsoft.AspNetCore.Mvc; using IRaCIS.Core.Application.Service.WorkLoad.DTO; using Microsoft.AspNetCore.Authorization; using IRaCIS.Core.Application.Auth; using IRaCIS.Core.Application.Service.Reading.Dto; using MassTransit; using IRaCIS.Core.Application.Service.Reading; using IRaCIS.Core.Infra.EFCore.Common; using Panda.DynamicWebApi.Attributes; using AutoMapper; using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Infrastructure; using Newtonsoft.Json; using IRaCIS.Core.Application.Service; using IRaCIS.Core.Application.ViewModel; namespace IRaCIS.Application.Services { /// <summary> /// IR影像阅片 /// </summary> [ApiExplorerSettings(GroupName = "Reading")] public class ReadingImageTaskService : BaseService, IReadingImageTaskService { private readonly IRepository<NoneDicomStudy> _noneDicomStudyRepository; private readonly IRepository<VisitTask> _visitTaskRepository; private readonly IRepository<Trial> _trialRepository; private readonly IVisitTaskHelpeService _visitTaskHelpeService; private readonly IReadingClinicalDataService _readingClinicalDataService; private readonly IRepository<SubjectVisit> _subjectVisitRepository; private readonly IRepository<Subject> _subjectRepository; private readonly IRepository<ReadingGlobalTaskInfo> _readingGlobalTaskInfoRepository; private readonly IRepository<ReadingCriterionPage> _readingCriterionPageRepository; private readonly IRepository<ReadingJudgeInfo> _readingJudgeInfoRepository; private readonly IRepository<ReadModule> _readModuleRepository; private readonly IRepository<ReadingTaskQuestionAnswer> _readingTaskQuestionAnswerRepository; private readonly IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository; private readonly IRepository<ReadingQuestionTrial> _readingQuestionTrialRepository; public ReadingImageTaskService( IMapper mapper, IRepository<NoneDicomStudy> noneDicomStudyRepository, IRepository<VisitTask> visitTaskRepository, IRepository<Trial> TrialRepository, IVisitTaskHelpeService visitTaskHelpeService, IReadingClinicalDataService readingClinicalDataService, IRepository<SubjectVisit> subjectVisitRepository, IRepository<Subject> subjectRepository, IRepository<ReadingGlobalTaskInfo> readingGlobalTaskInfoRepository, IRepository<ReadingCriterionPage> readingCriterionPageRepository, IRepository<ReadingJudgeInfo> readingJudgeInfoRepository, IRepository<ReadModule> readModuleRepository, IRepository<ReadingTaskQuestionAnswer> readingTaskQuestionAnswerRepository, IRepository<ReadingQuestionCriterionTrial> readingQuestionCriterionTrialRepository, IRepository<ReadingQuestionTrial> readingQuestionTrialRepository ) { base._mapper = mapper; this._noneDicomStudyRepository = noneDicomStudyRepository; this._visitTaskRepository = visitTaskRepository; this._trialRepository = TrialRepository; this._visitTaskHelpeService = visitTaskHelpeService; this._readingClinicalDataService = readingClinicalDataService; this._subjectVisitRepository = subjectVisitRepository; this._subjectRepository = subjectRepository; this._readingGlobalTaskInfoRepository = readingGlobalTaskInfoRepository; this._readingCriterionPageRepository = readingCriterionPageRepository; this._readingJudgeInfoRepository = readingJudgeInfoRepository; this._readModuleRepository = readModuleRepository; this._readingTaskQuestionAnswerRepository = readingTaskQuestionAnswerRepository; this._readingQuestionCriterionTrialRepository = readingQuestionCriterionTrialRepository; this._readingQuestionTrialRepository = readingQuestionTrialRepository; } #region 全局阅片相关 /// <summary> /// 获取全局阅片历史记录 /// </summary> /// <param name="inDto"></param> /// <returns></returns> [HttpPost] public async Task<List<GetHistoryGlobalInfoOutDto>> GetHistoryGlobalInfo(GetHistoryGlobalInfoInDto inDto) { var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync(); List<GetHistoryGlobalInfoOutDto> result = await _visitTaskRepository.Where(x => x.SubjectId == taskInfo.SubjectId && x.ArmEnum == taskInfo.ArmEnum && x.ReadingCategory == ReadingCategory.Global && x.VisitTaskNum < taskInfo.VisitTaskNum) .OrderBy(x => x.VisitTaskNum) .Select(x => new GetHistoryGlobalInfoOutDto() { ReadingTaskState = x.ReadingTaskState, TaskName = x.TaskName, VisitTaskId = x.Id, }).ToListAsync(); return result; } /// <summary> /// 保存全局阅片结果 /// </summary> /// <param name="inDto"></param> /// <returns></returns> [HttpPost] public async Task<IResponseOutput> SaveGlobalReadingInfo(SaveGlobalReadingInfoInDto inDto) { await _readingGlobalTaskInfoRepository.BatchDeleteNoTrackingAsync(x => x.GlobalTaskId == inDto.GlobalTaskId); foreach(var item in inDto.QuestionList) { await _readingTaskQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x => x.VisitTaskId == item.VisitTaskId && x.ReadingQuestionTrialId == item.QuestionId, x => new ReadingTaskQuestionAnswer() { GlobalChangeAnswer = item.Answer }); } await _readingGlobalTaskInfoRepository.AddRangeAsync(inDto.QuestionList.Select(x => new ReadingGlobalTaskInfo() { Answer = x.Answer, QuestionId = x.QuestionId, SubjectId = inDto.SubjectId, GlobalTaskId = inDto.GlobalTaskId, TaskId = x.VisitTaskId, TrialId = inDto.TrialId, }).ToList()); var result = await _readingGlobalTaskInfoRepository.SaveChangesAsync(); return ResponseOutput.Ok(result); } /// <summary> /// 获取全局阅片信息 /// </summary> /// <param name="inDto"></param> /// <returns></returns> [HttpPost] public async Task<GetGlobalReadingInfoOutDto> GetGlobalReadingInfo(GetGlobalReadingInfoInDto inDto) { var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync(); if (taskInfo.ReadingCategory != ReadingCategory.Global) { throw new BusinessValidationFailedException("当前任务不是全局阅片任务"); } GetGlobalReadingInfoOutDto result = new GetGlobalReadingInfoOutDto() { GlobalTaskId = inDto.VisitTaskId, ReadingTaskState=taskInfo.ReadingTaskState }; result.TaskList = await _visitTaskRepository.Where(x => x.ReadingCategory == ReadingCategory.Visit && x.SubjectId == taskInfo.SubjectId && x.ArmEnum == taskInfo.ArmEnum&&x.IsAnalysisCreate== taskInfo.IsAnalysisCreate&&x.TaskState==TaskState.Effect && x.VisitTaskNum < taskInfo.VisitTaskNum) .OrderBy(x => x.VisitTaskNum).Select(x => new GlobalVisitInfo() { VisitName = x.SourceSubjectVisit.VisitName, VisitTaskId = x.Id, VisitNum=x.SourceSubjectVisit.VisitNum, VisitId = x.SourceSubjectVisitId.Value, BeforeQuestionList = x.ReadingTaskQuestionAnswerList.Where(y => y.ReadingQuestionTrial.IsJudgeQuestion).OrderBy(y => y.ReadingQuestionTrial.ShowOrder) .Select(y => new GlobalQuestionInfo() { QuestionId = y.ReadingQuestionTrialId, QuestionName = y.ReadingQuestionTrial.QuestionName, AnswerGroup=y.ReadingQuestionTrial.AnswerGroup, AnswerCombination=y.ReadingQuestionTrial.AnswerCombination, JudgeType=y.ReadingQuestionTrial.JudgeType, Type = y.ReadingQuestionTrial.Type, TypeValue = y.ReadingQuestionTrial.TypeValue, Answer = y.Answer }).ToList() }).ToListAsync(); var globalReadingQuestion = await _readingGlobalTaskInfoRepository.Where(x => x.GlobalTaskId == inDto.VisitTaskId).ToListAsync(); result.TaskList.ForEach(x => { x.AfterQuestionList = x.BeforeQuestionList.GroupJoin( globalReadingQuestion , l => new { a = l.QuestionId, b = x.VisitTaskId } , r => new { a = r.QuestionId, b = r.TaskId } , (l, r) => new { question = l, global = r }) .SelectMany(lr => lr.global.DefaultIfEmpty(), (lr, r) => new GlobalQuestionInfo { Answer = lr.global == null ? (inDto.UsingOriginalData?lr.question.Answer: string.Empty) : lr.global.Select(x => x.Answer).FirstOrDefault(), QuestionId = lr.question.QuestionId, QuestionName = lr.question.QuestionName, Type = lr.question.Type, AnswerGroup = lr.question.AnswerGroup, AnswerCombination = lr.question.AnswerCombination, JudgeType = lr.question.JudgeType, TypeValue = lr.question.TypeValue, }).ToList(); var reason = new GlobalQuestionInfo() { Answer = globalReadingQuestion.Where(y => y.TaskId == x.VisitTaskId && y.QuestionId == null).Select(x => x.Answer).FirstOrDefault() ?? String.Empty, QuestionName = "原因", Type = "input", }; x.AfterQuestionList.Add(reason); }); return result; } #endregion #region 获取下一个阅片任务 /// <summary> /// 获取下一个阅片任务 /// </summary> /// <param name="inDto"></param> /// <returns></returns> [HttpPost] public async Task<GetReadingTaskDto> GetNextTask(GetNextTaskInDto inDto) { GetReadingTaskDto? task = new GetReadingTaskDto(); if (inDto.VisistTaskId != null) { task = await _visitTaskRepository.Where(x => x.Id == inDto.VisistTaskId).Select(x => new GetReadingTaskDto() { VisitTaskId = x.Id, TaskBlindName = x.TaskBlindName, SubjectId = x.SubjectId, ReadingCategory = x.ReadingCategory, VisistId = x.SourceSubjectVisitId != null ? x.SourceSubjectVisitId.Value : x.ReadModule.SubjectVisitId, VisitNum = x.VisitTaskNum, }).FirstOrDefaultAsync(); } else if (inDto.SubjectId != null) { var subjectList = await _subjectRepository.Where(t => t.TrialId == inDto.TrialId) .Select(s => new SubjectTask() { SubjectId = s.Id, UnReadTaskCount = s.SubjectVisitTaskList.Count(t => t.ReadingTaskState != ReadingTaskState.HaveSigned && t.DoctorUserId == _userInfo.Id && t.TaskState == TaskState.Effect), }).OrderBy(x => x.SubjectId).ToListAsync(); subjectList = subjectList.Select((x, index) => new SubjectTask() { Index = index, SubjectId = x.SubjectId, UnReadTaskCount = x.UnReadTaskCount, }).ToList(); var subjectIndex = subjectList.Where(x => x.SubjectId == inDto.SubjectId).Select(x => x.Index).FirstOrDefault(); var newSubjectId = subjectList.Where(x => x.Index >= subjectIndex && x.UnReadTaskCount != 0).Select(x => x.SubjectId).FirstOrDefault(); var taskquery = _visitTaskRepository.Where(x => x.TrialId == inDto.TrialId && x.ReadingTaskState != ReadingTaskState.HaveSigned && x.SubjectId == newSubjectId && x.DoctorUserId == _userInfo.Id).Select(x => new GetReadingTaskDto() { VisitTaskId = x.Id, TaskBlindName = x.TaskBlindName, ReadingCategory = x.ReadingCategory, VisistId = x.SourceSubjectVisitId != null ? x.SourceSubjectVisitId.Value : x.ReadModule == null ? default(Guid) : x.ReadModule.SubjectVisitId, VisitNum = x.VisitTaskNum, }).OrderBy(x => x.VisitNum).ThenBy(x => x.ReadingCategory); task = await taskquery.FirstOrDefaultAsync(); if (task == null) { throw new BusinessValidationFailedException("任务都已经完成"); } task.SubjectId = inDto.SubjectId.Value; } else { task = await _visitTaskRepository.Where(x => x.TrialId == inDto.TrialId && x.ReadingTaskState != ReadingTaskState.HaveSigned && x.DoctorUserId == _userInfo.Id && x.TaskState == TaskState.Effect).Select(x => new GetReadingTaskDto() { VisitTaskId = x.Id, TaskBlindName = x.TaskBlindName, ReadingCategory = x.ReadingCategory, VisistId = x.SourceSubjectVisitId != null ? x.SourceSubjectVisitId.Value : x.ReadModule == null ? default(Guid) : x.ReadModule.SubjectVisitId, VisitNum = x.VisitTaskNum, SubjectId = x.SubjectId, SubjectCode = x.Subject.Code, }).FirstOrDefaultAsync(); if (task == null) { throw new BusinessValidationFailedException("任务都已经完成"); } } if (task.SubjectCode.IsNullOrEmpty()) { task.SubjectCode = await _subjectRepository.Where(x => x.Id == task.SubjectId).Select(x => x.Code).FirstOrDefaultAsync(); } await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => x.Id == task.VisitTaskId && x.FirstReadingTime == null, x => new VisitTask() { FirstReadingTime = DateTime.Now, }); await _visitTaskRepository.SaveChangesAsync(); return task; } #endregion #region 获取阅片非Dicom文件 /// <summary> /// 获取阅片非Dicom文件 /// </summary> /// <param name="inDto"></param> /// <returns></returns> [HttpPost] public async Task<(List<NoneDicomStudyView>, object)> GetReadingImageFile(GetReadingImgInDto inDto) { var task = await GetNextTask(new GetNextTaskInDto() { TrialId = inDto.TrialId, SubjectId = inDto.SubjectId, VisistTaskId = inDto.VisistTaskId, }); List<Guid> visitIds = new List<Guid>(); if (task.ReadingCategory == ReadingCategory.Visit) { visitIds.Add(task.VisistId); } else { // 阅片期取前面所有的图像 visitIds.AddRange(await _subjectVisitRepository.Where(x => x.VisitNum <= task.VisitNum && x.SubjectId == task.SubjectId).Select(x => x.Id).ToListAsync()); } List<NoneDicomStudyView> result = await _noneDicomStudyRepository.Where(t => visitIds.Contains(t.SubjectVisitId)) .ProjectTo<NoneDicomStudyView>(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken }).ToListAsync(); var trialInfo = await _trialRepository.Where(x => x.Id == inDto.TrialId).Select(x => new { x.IsReadingShowPreviousResults, x.IsReadingShowSubjectInfo, x.ClinicalInformationTransmissionEnum, }).FirstOrDefaultAsync(); #region 临床数据 #endregion bool isExistsClinicalData = false; if (trialInfo.ClinicalInformationTransmissionEnum == 1) { isExistsClinicalData = (await _readingClinicalDataService.GetClinicalDataList(new GetReadingOrTaskClinicalDataListInDto() { SubjectId = task.SubjectId, TrialId = inDto.TrialId, VisitTaskId = task.VisitTaskId, })).Count() > 0; } return (result, new { VisitTaskId = task.VisitTaskId, SubjectId = task.SubjectId, SubjectCode = task.SubjectCode, ReadingCategory = task.ReadingCategory, TaskBlindName = task.TaskBlindName, IsReadingShowPreviousResults = trialInfo.IsReadingShowPreviousResults, IsReadingShowSubjectInfo = trialInfo.IsReadingShowSubjectInfo, IsExistsClinicalData = isExistsClinicalData, }); } #endregion #region 获取项目已确认的标准 /// <summary> /// 获取项目已确认的标准 /// </summary> /// <param name="inDto"></param> /// <returns></returns> [HttpPost] public async Task<List<GetTrialConfirmCriterionListOutDto>> GetTrialConfirmCriterionList(GetConfirmCriterionInDto inDto) { var result = await _readingQuestionCriterionTrialRepository.Where(x => x.TrialId == inDto.TrialId && x.IsConfirm && x.IsCompleteConfig) .Select(x => new GetTrialConfirmCriterionListOutDto() { ReadingQuestionCriterionTrialId = x.Id, ReadingQuestionCriterionTrialName = x.CriterionName }).ToListAsync(); return result; } #endregion #region 配置裁判问题相关 /// <summary> /// 获取项目标准的裁判问题 /// </summary> /// <param name="inDto"></param> /// <returns></returns> [HttpPost] public async Task<(List<GetTrialCriterionJudgeQuestionListOutDto>, object)> GetTrialCriterionJudgeQuestionList(GetTrialCriterionJudgeQuestionListInDto inDto) { var trialCriterion = await _readingQuestionCriterionTrialRepository.Where(x => x.TrialId == inDto.TrialId && x.IsConfirm).FirstNotNullAsync(); var result = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == inDto.ReadingQuestionCriterionTrialId && x.IsJudgeQuestion) .WhereIf(trialCriterion.FormType == FormType.SinglePage, x => x.ReadingCriterionPageId == null) .WhereIf(trialCriterion.FormType == FormType.MultiplePage, x => x.ReadingCriterionPageId != null) .Select(x => new GetTrialCriterionJudgeQuestionListOutDto() { AnswerGroup = JsonConvert.DeserializeObject<List<string>>(x.AnswerGroup.IsNullOrEmpty() ? "[]" : x.AnswerGroup), AnswerCombination = JsonConvert.DeserializeObject<List<AnswerCombinationDto>>(x.AnswerCombination.IsNullOrEmpty() ? "[]" : x.AnswerCombination), QuestionName = x.QuestionName, PageName = x.ReadingCriterionPage.PageName, TypeValue = x.TypeValue, JudgeType = x.JudgeType, ReadingQuestionTrialId = x.Id }).ToListAsync(); var signTime = await _trialRepository.Where(x => x.Id == inDto.TrialId).Select(x => x.ReadingInfoSignTime).FirstOrDefaultAsync(); return (result, new { IsSign = signTime != null, }); } /// <summary> /// 设置裁判问题的答案分组 /// </summary> /// <param name="inDto"></param> /// <returns></returns> [HttpPost] public async Task<IResponseOutput> SetTrialCriterionJudgeQuestionAnswerGroup(SetTrialCriterionJudgeQuestionAnswerGroupInDto inDto) { await _readingQuestionTrialRepository.UpdatePartialFromQueryAsync(inDto.ReadingQuestionTrialId, x => new ReadingQuestionTrial() { AnswerGroup = JsonConvert.SerializeObject(inDto.AnswerGroup), AnswerCombination = JsonConvert.SerializeObject(inDto.AnswerCombination), JudgeType = inDto.JudgeType, }); var result = await _readingQuestionTrialRepository.SaveChangesAsync(); return ResponseOutput.Ok(result); } #endregion #region 获取项目的阅片问题 /// <summary> /// 获取项目的阅片问题 /// </summary> /// <remarks> /// SinglePage 单页 /// /// MultiPage 多页 /// /// PublicPage 公共 /// </remarks> /// <param name="inDto"></param> /// <returns></returns> [HttpPost] public async Task<(GetTrialReadingQuestionPageDto, object)> GetTrialReadingQuestion(GetTrialReadingQuestionInDto inDto) { var result = new GetTrialReadingQuestionPageDto(); var readingTaskState = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Select(x => x.ReadingTaskState).FirstOrDefaultAsync(); var query = from data in _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == inDto.ReadingQuestionCriterionTrialId) join page in _readingCriterionPageRepository.AsQueryable() on data.ReadingCriterionPageId ?? default(Guid) equals page.Id into pageTemp from leftpage in pageTemp.DefaultIfEmpty() join questionAnswer in _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId) on data.Id equals questionAnswer.ReadingQuestionTrialId into questionAnswerTemp from leftquestionAnswer in questionAnswerTemp.DefaultIfEmpty() select new GetTrialReadingQuestionOutDto() { ReadingQuestionTrialId = data.Id, ReadingQuestionCriterionTrialId = data.ReadingQuestionCriterionTrialId, TrialId = data.TrialId, Type = data.Type, ParentTriggerValue = data.ParentTriggerValue, GroupName = data.GroupName, QuestionName = data.QuestionName, IsRequired = data.IsRequired, ShowOrder = data.ShowOrder, ParentId = data.ParentId, TypeValue = data.TypeValue, Answer = leftquestionAnswer.Answer, ReadingCriterionPageId = data.ReadingCriterionPageId, PageName = leftpage.PageName, PageShowOrder = leftpage.ShowOrder, IsPublicPage = leftpage.IsPublicPage, }; var qusetionList = await query.OrderBy(x => x.ShowOrder).ToListAsync(); var formType = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inDto.ReadingQuestionCriterionTrialId).Select(x => x.FormType).FirstOrDefaultAsync(); var groupList = new List<GetTrialReadingQuestionOutDto>(); if (inDto.FormType != null) { formType = inDto.FormType.Value; } if (formType == FormType.MultiplePage) { qusetionList = qusetionList.Where(x => x.ReadingCriterionPageId != null).ToList(); var readingCriterionPageIds = qusetionList.OrderBy(x => x.PageShowOrder).Select(x => x.ReadingCriterionPageId).Distinct().ToList(); foreach (var item in readingCriterionPageIds) { var newPageQusetionList = qusetionList.Where(x => x.ReadingCriterionPageId == item).ToList(); var firstData = newPageQusetionList.FirstOrDefault(); var page = new GetTrialReadingQuestionOutDto() { PageName = firstData.PageName, IsPage = true, IsPublicPage = firstData.IsPublicPage, }; var pageGroupList = newPageQusetionList.Where(x => x.Type == "group" || (x.ParentId == null && x.GroupName.IsNullOrEmpty())).ToList(); pageGroupList.ForEach(x => { this.FindChildQuestion(x, newPageQusetionList); }); page.Childrens = pageGroupList.Where(x => !(x.Type == "group" && x.Childrens.Count() == 0)).ToList(); groupList.Add(page); } result.PublicPage = groupList.Where(x => x.IsPublicPage.Value).ToList(); result.MultiPage = groupList.Where(x => !x.IsPublicPage.Value).ToList(); } else { qusetionList = qusetionList.Where(x => x.ReadingCriterionPageId == null).ToList(); groupList = qusetionList.Where(x => x.Type == "group" || (x.ParentId == null && x.GroupName.IsNullOrEmpty())).ToList(); groupList.ForEach(x => { this.FindChildQuestion(x, qusetionList); }); groupList = groupList.Where(x => !(x.Type == "group" && x.Childrens.Count() == 0)).ToList(); result.SinglePage = groupList; } //List<GetTrialReadingQuestionOutDto> groupList = qusetionList.Where(x => x.ParentId == null).ToList(); //groupList.ForEach(x => //{ // this.FindChildQuestion(x, qusetionList); //}); return (result, new { readingTaskState = readingTaskState, FormType = formType }); ; } #endregion #region 获取阅片任务和答案 /// <summary> /// 获取阅片任务和答案 /// </summary> /// <returns></returns> private async Task<List<GetTrialReadingQuestionOutDto>> GetTaskAndAnswer(Guid visitTaskId) { var taskQuery = from questionAnswer in _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == visitTaskId) join trialQuestion in _readingQuestionTrialRepository.AsQueryable() on questionAnswer.ReadingQuestionTrialId equals trialQuestion.Id select new GetTrialReadingQuestionOutDto() { ReadingQuestionTrialId = trialQuestion.Id, ReadingQuestionCriterionTrialId = trialQuestion.ReadingQuestionCriterionTrialId, TrialId = trialQuestion.TrialId, Type = trialQuestion.Type, ParentTriggerValue = trialQuestion.ParentTriggerValue, GroupName = trialQuestion.GroupName, QuestionName = trialQuestion.QuestionName, IsRequired = trialQuestion.IsRequired, ShowOrder = trialQuestion.ShowOrder, ParentId = trialQuestion.ParentId, TypeValue = trialQuestion.TypeValue, Answer = questionAnswer.Answer }; var qusetionList = await taskQuery.OrderBy(x => x.ShowOrder).ToListAsync(); List<GetTrialReadingQuestionOutDto> groupList = qusetionList.Where(x => x.ParentId == null).ToList(); groupList.ForEach(x => { this.FindChildQuestion(x, qusetionList); }); return groupList; } #endregion #region 获取裁判阅片任务信息 /// <summary> /// 获取裁判阅片任务信息 /// </summary> /// <returns></returns> [HttpPost] public async Task<GetJudgeReadingInfoOutDto> GetJudgeReadingInfo(GetJudgeReadingInfo inDto) { var visitTask = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Select(x => new { x.ReadingTaskState, x.JudgeResultTaskId, x.JudgeResultRemark, x.JudgeResultImagePath, }).FirstOrDefaultAsync(); GetJudgeReadingInfoOutDto judgeInfo = new GetJudgeReadingInfoOutDto() { ReadingTaskState = visitTask.ReadingTaskState, JudgeResultTaskId = visitTask.JudgeResultTaskId, JudgeResultRemark = visitTask.JudgeResultRemark, JudgeResultImagePath = visitTask.JudgeResultImagePath, VisitTaskInfoList = new List<JudgeReadingInfoDto>() }; var visitIds = await _visitTaskRepository.Where(x => x.JudgeVisitTaskId == inDto.VisitTaskId).Select(x => new { x.Id, x.ArmEnum, }).ToListAsync(); foreach (var item in visitIds) { var taskReadingQuestionList = await this.GetTaskAndAnswer(item.Id); judgeInfo.VisitTaskInfoList.Add( new JudgeReadingInfoDto() { JudgeQuestionAnswerInfoList = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == item.Id && x.ReadingQuestionTrial.IsJudgeQuestion).Select(x => new JudgeQuestionAnswerInfo { Answer = x.Answer, QuestionName = x.ReadingQuestionTrial.QuestionName, }).ToListAsync(), VisitTaskId = item.Id, ArmEnum = item.ArmEnum, TaskReadingQuestionList = taskReadingQuestionList, }); } return judgeInfo; } #endregion #region 保存裁判问题 /// <summary> /// 保存裁判问题 /// </summary> /// <param name="inDto"></param> /// <returns></returns> [HttpPost] public async Task<IResponseOutput> SaveJudgeVisitTaskResult(SaveJudgeVisitTaskResult inDto) { await _visitTaskRepository.UpdatePartialFromQueryAsync(inDto.VisitTaskId, x => new VisitTask() { JudgeResultTaskId = inDto.JudgeResultTaskId, JudgeResultRemark = inDto.JudgeResultRemark, JudgeResultImagePath = inDto.JudgeResultImagePath, }); var result = await _visitTaskRepository.SaveChangesAsync(); return ResponseOutput.Ok(result); } #endregion #region 获取既往结果 /// <summary> /// 获取既往结果 /// </summary> /// <returns></returns> [HttpPost] public async Task<List<GetReadingPastResultListOutDto>> GetReadingPastResultList(GetReadingPastResultListInDto inDto) { var readingPastResultList = await _visitTaskRepository.Where(x => x.TrialId == inDto.TrialId && x.SubjectId == inDto.SubjectId && x.DoctorUserId == _userInfo.Id && x.Id != inDto.VisitTaskId && x.ReadingTaskState == ReadingTaskState.HaveSigned).ProjectTo<GetReadingPastResultListOutDto>(_mapper.ConfigurationProvider).ToListAsync(); return readingPastResultList; } #endregion #region 找子问题 /// <summary> /// 找子问题 /// </summary> /// <param name="trialReadingQuestion"></param> /// <param name="questionlists"></param> [NonDynamicMethod] public void FindChildQuestion(GetTrialReadingQuestionOutDto trialReadingQuestion, List<GetTrialReadingQuestionOutDto> questionlists) { trialReadingQuestion.Childrens = questionlists.Where(x => x.ParentId == trialReadingQuestion.ReadingQuestionTrialId || (trialReadingQuestion.Type == "group" && x.Type != "group" && x.ParentId == null && x.GroupName == trialReadingQuestion.GroupName)).ToList(); if (trialReadingQuestion.Childrens != null && trialReadingQuestion.Childrens.Count != 0) { trialReadingQuestion.Childrens.ForEach(x => { this.FindChildQuestion(x, questionlists); }); } } #endregion #region 保存任务问题 /// <summary> /// 保存任务问题 /// </summary> /// <param name="inDto"></param> /// <returns></returns> [HttpPost] public async Task<IResponseOutput> SaveVisitTaskQuestions(SubmitVisitTaskQuestionsInDto inDto) { var subjectId = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Select(x => x.SubjectId).FirstOrDefaultAsync(); await _readingTaskQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.ReadingQuestionCriterionTrialId == inDto.ReadingQuestionCriterionTrialId); List<ReadingTaskQuestionAnswer> readingTaskAnswerList = inDto.AnswerList.Select(x => new ReadingTaskQuestionAnswer() { Id = NewId.NextGuid(), SubjectId = subjectId, Answer = x.Answer, ReadingQuestionCriterionTrialId = inDto.ReadingQuestionCriterionTrialId, ReadingQuestionTrialId = x.ReadingQuestionTrialId, VisitTaskId = inDto.VisitTaskId, TrialId = inDto.TrialId }).ToList(); await _visitTaskRepository.UpdatePartialFromQueryAsync(x => x.Id == inDto.VisitTaskId, x => new VisitTask() { ReadingTaskState = ReadingTaskState.Reading, }); await _readingTaskQuestionAnswerRepository.AddRangeAsync(readingTaskAnswerList); var result = await _visitTaskRepository.SaveChangesAsync(); return ResponseOutput.Ok(result); } #endregion #region 提交问题 /// <summary> /// 提交访视阅片问题 /// </summary> /// <param name="inDto"></param> /// <returns></returns> [NonDynamicMethod] public async Task<IResponseOutput> SubmitVisitTaskQuestions(SubmitVisitTaskQuestionsInDto inDto) { await this.SaveVisitTaskQuestions(inDto); await this.SubmitTaskChangeState(inDto.VisitTaskId); return ResponseOutput.Ok(true); } /// <summary> /// 提交裁判问题 /// </summary> /// <param name="inDto"></param> /// <returns></returns> [NonDynamicMethod] public async Task<IResponseOutput> SubmitJudgeVisitTaskResult(SaveJudgeVisitTaskResult inDto) { await _visitTaskRepository.UpdatePartialFromQueryAsync(inDto.VisitTaskId, x => new VisitTask() { JudgeResultTaskId = inDto.JudgeResultTaskId, ReadingTaskState = ReadingTaskState.HaveSigned, JudgeResultRemark = inDto.JudgeResultRemark, SignTime = DateTime.Now, JudgeResultImagePath = inDto.JudgeResultImagePath, }); var result = await _visitTaskRepository.SaveChangesAsync(); return ResponseOutput.Ok(result); } /// <summary> /// 提交全局阅片结果 /// </summary> /// <param name="inDto"></param> /// <returns></returns> [NonDynamicMethod] public async Task<IResponseOutput> SubmitGlobalReadingInfo(SubmitGlobalReadingInfoInDto inDto) { //var result = await this.SaveGlobalReadingInfo(inDto); await this.SubmitTaskChangeState(inDto.GlobalTaskId); return ResponseOutput.Ok(true) ; } /// <summary> /// 签名提交任务修改状态 /// </summary> /// <param name="visitTaskId"></param> /// <returns></returns> private async Task SubmitTaskChangeState(Guid visitTaskId) { await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => x.Id == visitTaskId, x => new VisitTask() { ReadingTaskState = ReadingTaskState.HaveSigned, SignTime = DateTime.Now, }); // 触裁判任务 await this.TriggerJudgeQuestion(visitTaskId); // 添加阅片期任务 await this.AddReadingTask(visitTaskId); // 完成阅片修改状态 await this.FinishReadUpdateState(visitTaskId); } #endregion /// <summary> /// 完成阅片修改状态 /// </summary> /// <returns></returns> private async Task FinishReadUpdateState(Guid visitTaskId) { var taskInfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).FirstNotNullAsync(); if (!await _visitTaskRepository.AnyAsync(x => x.SourceSubjectVisitId == taskInfo.SourceSubjectVisitId && x.SouceReadModuleId == taskInfo.SouceReadModuleId && x.ReadingTaskState != ReadingTaskState.HaveSigned)) { if (taskInfo.SouceReadModuleId != null) { await _readModuleRepository.UpdatePartialFromQueryAsync(taskInfo.SouceReadModuleId.Value, x => new ReadModule { ReadingStatus = ReadingStatusEnum.ReadCompleted }); } else if (taskInfo.SourceSubjectVisitId != null) { await _subjectVisitRepository.UpdatePartialFromQueryAsync(taskInfo.SourceSubjectVisitId.Value, x => new SubjectVisit { ReadingStatus = ReadingStatusEnum.ReadCompleted }); } await _subjectVisitRepository.SaveChangesAsync(); } } /// <summary> /// 添加阅片期任务 /// </summary> /// <returns></returns> private async Task AddReadingTask(Guid visitTaskId) { // ****** 先生成阅片期 阅片期任务阅片完成之后生成肿瘤学的 如果没有阅片期 直接生成肿瘤学 *********//// #region 建立关系 // 访视阅完产生 全局 Dictionary<ModuleTypeEnum, ReadingCategory> typeChangeDic = new Dictionary<ModuleTypeEnum, ReadingCategory>(); typeChangeDic.Add(ModuleTypeEnum.InPlanSubjectVisit, ReadingCategory.Visit); typeChangeDic.Add(ModuleTypeEnum.OutPlanSubjectVisit, ReadingCategory.Visit); //typeChange.Add(ModuleTypeEnum.Read, ReadingCategory.ReadingPeriod); typeChangeDic.Add(ModuleTypeEnum.Global, ReadingCategory.Global); typeChangeDic.Add(ModuleTypeEnum.Referee, ReadingCategory.Judge); typeChangeDic.Add(ModuleTypeEnum.Oncology, ReadingCategory.Oncology); #endregion var taskInfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).FirstNotNullAsync(); List<ReadingGenerataTaskDTO> needReadList = new List<ReadingGenerataTaskDTO>(); if (!taskInfo.IsAnalysisCreate) { // 任务类型 switch (taskInfo.ReadingCategory) { case ReadingCategory.Visit: needReadList = await _readModuleRepository.Where(x => x.SubjectVisitId == taskInfo.SourceSubjectVisitId) .Select(x => new ReadingGenerataTaskDTO { IsUrgent = x.IsUrgent ?? false, SubjectId = x.SubjectId, VisitNum=x.VisitNum, ReadingName = x.ModuleName, ReadModuleId = x.Id, ReadingCategory = typeChangeDic[x.ModuleType], }).ToListAsync(); if (needReadList.Any(x => x.ReadingCategory == ReadingCategory.Global)) { needReadList = needReadList.Where(x => x.ReadingCategory != ReadingCategory.Oncology).ToList(); } //needReadList = needReadList.Where(x => _visitTaskRepository.Where(y => y.SouceReadModuleId == x.ReadModuleId).Count() == 0).ToList(); await _visitTaskHelpeService.AddTaskAsync(new GenerateTaskCommand() { OriginalVisitId= visitTaskId, ReadingCategory = GenerateTaskCategory.Global, TrialId = taskInfo.TrialId, ReadingGenerataTaskList = needReadList }) ; break; // 肿瘤学 case ReadingCategory.Global: var subjectId = await _readModuleRepository.Where(x => x.Id == taskInfo.SouceReadModuleId).Select(x => x.SubjectVisitId).FirstOrDefaultAsync(); needReadList=await _readModuleRepository.Where(x => x.SubjectVisitId == subjectId&&x.ModuleType==ModuleTypeEnum.Oncology) .Select(x => new ReadingGenerataTaskDTO { IsUrgent = x.IsUrgent ?? false, SubjectId = x.SubjectId, ReadingName = x.ModuleName, VisitNum = x.VisitNum, ReadModuleId = x.Id, ReadingCategory = typeChangeDic[x.ModuleType], }).ToListAsync(); if (taskInfo.JudgeVisitTaskId == null) { // 有裁判要等裁判完成之后才进行添加 await _visitTaskHelpeService.AddTaskAsync(new GenerateTaskCommand() { ReadingCategory = GenerateTaskCategory.Oncology, TrialId = taskInfo.TrialId, ReadingGenerataTaskList = needReadList }); } //needReadList = needReadList.Where(x => _visitTaskRepository.Where(y => y.SouceReadModuleId == x.ReadModuleId).Count() == 0).ToList(); break; } } } /// <summary> /// 全局阅片裁判触发 /// </summary> /// <param name="visitTaskId"></param> /// <returns></returns> private async Task GlobalTriggerJudgeQuestion(Guid visitTaskId) { List<Guid> visitTaskids = new List<Guid>(); var taskInfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).FirstNotNullAsync(); // 判断是否是一致性分析产生的 if (taskInfo.IsAnalysisCreate) { if (taskInfo.ConsistentAnalysisOriginalTaskId != null) { visitTaskids.Add(visitTaskId); visitTaskids.Add(taskInfo.ConsistentAnalysisOriginalTaskId.Value); } } else { visitTaskids = await _visitTaskRepository.Where(x => x.ReadingTaskState == ReadingTaskState.HaveSigned && x.ReadingCategory != ReadingCategory.Judge && x.ReReadingApplyState != ReReadingApplyState.Agree && x.SourceSubjectVisitId == taskInfo.SourceSubjectVisitId && x.SouceReadModuleId == taskInfo.SouceReadModuleId).Select(x => x.Id).ToListAsync(); } } /// <summary> /// 触发裁判任务(新) /// </summary> /// <param name="visitTaskId"></param> /// <returns></returns> private async Task TriggerJudgeQuestion(Guid visitTaskId) { List<Guid> visitTaskids = new List<Guid>(); var visitTask = await _visitTaskRepository.Where(x => x.Id == visitTaskId).AsNoTracking().FirstNotNullAsync(); // 判断是否是一致性核查产生 if (visitTask.IsAnalysisCreate&& visitTask.ConsistentAnalysisOriginalTaskId!=null) { visitTaskids.Add(visitTask.Id); visitTaskids.Add(visitTask.ConsistentAnalysisOriginalTaskId.Value); } else { // 这里是非一致性分析产生的 visitTaskids = await _visitTaskRepository.Where(x => x.ReadingTaskState == ReadingTaskState.HaveSigned && x.ReadingCategory != ReadingCategory.Judge &&x.IsAnalysisCreate==false && x.ReReadingApplyState != ReReadingApplyState.Agree && x.SourceSubjectVisitId == visitTask.SourceSubjectVisitId && x.SouceReadModuleId == visitTask.SouceReadModuleId).Select(x => x.Id).ToListAsync(); } var trialInfo = await _trialRepository.Where(x => x.Id == visitTask.TrialId).Select(x=> new { x.IsArbitrationReading, x.ArbitrationRule }).FirstNotNullAsync(); var noteEqual = false; // 判断项目是否设置了裁判 if (trialInfo.IsArbitrationReading ?? false) { // 判断数量是否为2 是否仲裁 if (visitTaskids.Count == 2) { switch (visitTask.ReadingCategory) { // 访视 case ReadingCategory.Visit: // 查找两个 访视的阅片答案 var query = from questionAnswet in _readingTaskQuestionAnswerRepository.Where(x => visitTaskids.Contains(x.VisitTaskId)) join question in _readingQuestionTrialRepository.Where(x => x.IsJudgeQuestion) on new { ReadingQuestionTrialId = questionAnswet.ReadingQuestionTrialId } equals new { ReadingQuestionTrialId = question.Id } select new TaskAnswerDto() { Answer = questionAnswet.Answer, AnswerGroup = question.AnswerGroup, AnswerCombination = question.AnswerCombination, JudgeType = question.JudgeType, QuestionId = question.Id, VisitTaskId = questionAnswet.VisitTaskId, }; var questionAnswerlist = await query.ToListAsync(); // 将答案进行分组 List<GroupTaskAnswerDto> groupTasks = questionAnswerlist.GroupBy(x => new { x.QuestionId, x.AnswerGroup, x.JudgeType, x.AnswerCombination }).Select(x => new GroupTaskAnswerDto { QuestionId = x.Key.QuestionId, AnswerGroup = x.Key.AnswerGroup, AnswerCombination = x.Key.AnswerCombination, JudgeType = x.Key.JudgeType, TaskAnswerList = x.Select(y => y.Answer).ToList(), }).ToList(); noteEqual = ComputeJudgeResult(groupTasks); break; case ReadingCategory.Global: var taskOneInfo = await this.GetGlobalReadingInfo(new GetGlobalReadingInfoInDto() { UsingOriginalData = true, VisitTaskId = visitTaskids[0] }); var taskTwoInfo = await this.GetGlobalReadingInfo(new GetGlobalReadingInfoInDto() { UsingOriginalData = true, VisitTaskId = visitTaskids[1] }); // 判断两个任务是否 if (taskOneInfo.TaskList.Count() != taskTwoInfo.TaskList.Count()) { noteEqual = true; } else { foreach (var item in taskOneInfo.TaskList) { GlobalVisitInfo twoItem = taskTwoInfo.TaskList.Where(x => x.VisitId == item.VisitId).FirstOrDefault(); if (twoItem == null) { noteEqual = true; break; } else { var newlist = item.AfterQuestionList.Where(x => x.QuestionId != null).ToList().Union( twoItem.AfterQuestionList.Where(x => x.QuestionId != null).ToList() ).ToList(); List<GroupTaskAnswerDto> globalGroupTasks = newlist.GroupBy(x => new { x.QuestionId, x.AnswerGroup, x.JudgeType, x.AnswerCombination }).Select(x => new GroupTaskAnswerDto { QuestionId = x.Key.QuestionId.Value, AnswerGroup = x.Key.AnswerGroup, AnswerCombination = x.Key.AnswerCombination, JudgeType = x.Key.JudgeType, TaskAnswerList = x.Select(y => y.Answer).ToList(), }).ToList(); noteEqual = noteEqual || ComputeJudgeResult(globalGroupTasks); } } } break; } } else { // 这里判断一致性分析产生的全局阅片 if (visitTask.ReadingCategory == ReadingCategory.Global && visitTask.IsAnalysisCreate) { var taskOneInfo = await this.GetGlobalReadingInfo(new GetGlobalReadingInfoInDto() { UsingOriginalData = true, VisitTaskId = visitTask.Id }); // 找到最后一个任务ID var lastTask = taskOneInfo.TaskList.Last(); if (lastTask == null) { noteEqual = true; } else { var query = from questionAnswet in _readingTaskQuestionAnswerRepository.Where(x => x.VisitTask.IsAnalysisCreate==false&& x.VisitTask.DoctorUserId==visitTask.DoctorUserId&& x.VisitTask.TaskState== TaskState.Effect&& (x.VisitTask.SourceSubjectVisitId??default(Guid))== lastTask.VisitId) join question in _readingQuestionTrialRepository.Where(x => x.IsJudgeQuestion) on new { ReadingQuestionTrialId = questionAnswet.ReadingQuestionTrialId } equals new { ReadingQuestionTrialId = question.Id } select new GlobalQuestionInfo() { Answer = questionAnswet.Answer, AnswerGroup = question.AnswerGroup, AnswerCombination = question.AnswerCombination, JudgeType = question.JudgeType, QuestionId = question.Id, }; var visitTaskQuestions =await query.ToListAsync(); var newlist = visitTaskQuestions.Where(x => x.QuestionId != null).ToList().Union( lastTask.AfterQuestionList.Where(x => x.QuestionId != null).ToList() ).ToList(); List<GroupTaskAnswerDto> globalGroupTasks = newlist.GroupBy(x => new { x.QuestionId, x.AnswerGroup, x.JudgeType, x.AnswerCombination }).Select(x => new GroupTaskAnswerDto { QuestionId = x.Key.QuestionId.Value, AnswerGroup = x.Key.AnswerGroup, AnswerCombination = x.Key.AnswerCombination, JudgeType = x.Key.JudgeType, TaskAnswerList = x.Select(y => y.Answer).ToList(), }).ToList(); noteEqual = noteEqual || ComputeJudgeResult(globalGroupTasks); } } } } if (noteEqual) { if (visitTask.IsAnalysisCreate) { await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => x.Id == visitTaskId, x => new VisitTask() { IsAnalysisDiffToOriginalData = true }); await _visitTaskRepository.SaveChangesAsync(); } else { if ((visitTask.SourceSubjectVisitId != null && trialInfo.ArbitrationRule == ArbitrationRule.Visit) || (visitTask.SouceReadModuleId != null && trialInfo.ArbitrationRule == ArbitrationRule.Reading)) { await this.SaveJudgeTask(new SaveJudgeTaskDto() { VisitTaskIds = visitTaskids, }); } } } else { if (visitTask.IsAnalysisCreate) { await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => x.Id == visitTaskId, x => new VisitTask() { IsAnalysisDiffToOriginalData = false }); await _visitTaskRepository.SaveChangesAsync(); } } } /// <summary> /// 计算返回的结果 为True表示不相等 /// </summary> /// <param name="groupTasks"></param> /// <returns></returns> private bool ComputeJudgeResult(List<GroupTaskAnswerDto> groupTasks) { var noteEqual = false; foreach (var item in groupTasks) { if (item.TaskAnswerList.Count() != 2) { noteEqual = true; break; } else { var taskAnswer1 = item.TaskAnswerList[0]; var taskAnswer2 = item.TaskAnswerList[1]; if (taskAnswer1 != taskAnswer2) { switch (item.JudgeType) { case JudgeTypeEnum.AnswerDisaffinity: noteEqual = true; break; case JudgeTypeEnum.AnswerGroup: var answerGroupList = JsonConvert.DeserializeObject<List<string>>(item.AnswerGroup).Select(x => new AnswerGroup() { GroupId = NewId.NextGuid(), GroupValue = x }).ToList(); var itemAnswerGroupsitem1 = answerGroupList.Where(x => x.GroupValue.Contains($"|{taskAnswer1}|")); var itemAnswerGroupsitem2 = answerGroupList.Where(x => x.GroupValue.Contains($"|{taskAnswer2}|")); var unionList = itemAnswerGroupsitem1.Intersect(itemAnswerGroupsitem2).ToList(); if (unionList.Count < 1) { noteEqual = true; } break; case JudgeTypeEnum.AnswerCombination: var answerCombinationList = JsonConvert.DeserializeObject<List<AnswerCombinationDto>>(item.AnswerCombination == string.Empty ? "[]" : item.AnswerCombination).ToList(); answerCombinationList.ForEach(x => { if (x.AnswerGroupA.Contains(taskAnswer1) && x.AnswerGroupB.Contains(taskAnswer2)) { noteEqual = true; } if (x.AnswerGroupB.Contains(taskAnswer1) && x.AnswerGroupA.Contains(taskAnswer2)) { noteEqual = true; } }); break; } } } } return noteEqual; } /// <summary> /// 添加裁判任务 /// </summary> /// <returns></returns> private async Task SaveJudgeTask(SaveJudgeTaskDto inDto) { var trialId = await _visitTaskRepository.Where(x => inDto.VisitTaskIds.Contains(x.Id)).Select(x => x.TrialId).FirstOrDefaultAsync(); await _visitTaskHelpeService.AddTaskAsync(new GenerateTaskCommand() { JudgeVisitTaskIdList= inDto.VisitTaskIds, ReadingCategory= GenerateTaskCategory.Judge, TrialId= trialId }); } } }