Files
irc-netcore-api/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs
T
he 35e6a47f2d
continuous-integration/drone/push Build is passing
获取问题修改
2026-08-18 09:24:57 +08:00

4474 lines
210 KiB
C#

using DocumentFormat.OpenXml;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.Helper.OtherTool;
using IRaCIS.Core.Application.Interfaces;
using IRaCIS.Core.Application.Service.ImageAndDoc;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Application.Service.ReadingCalculate.Interface;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Infra.EFCore.Common;
using IRaCIS.Core.Infrastructure;
using MassTransit;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Panda.DynamicWebApi.Attributes;
namespace IRaCIS.Core.Application.Service
{
/// <summary>
/// IR影像阅片
/// </summary>
[ApiExplorerSettings(GroupName = "Reading")]
public partial class ReadingImageTaskService(
IRepository<NoneDicomStudy> _noneDicomStudyRepository,
IRepository<VisitTask> _visitTaskRepository,
IRepository<VisitStage> _visitStageRepository,
IRepository<Trial> _trialRepository,
IRepository<TaskInstance> _taskInstanceRepository,
IRepository<NoneDicomStudyFile> _noneDicomStudyFileRepository,
IRepository<ReadingNoneDicomMark> _readingNoneDicomMarkRepository,
IRepository<ReadingNoneDicomMarkBinding> _readingNoneDicomMarkBindingRepository,
IRepository<UserLog> _userLogRepository,
IRepository<ReadingTableQuestionAnswer> _readingTableQuestionAnswerRepository,
IRepository<ReadingOncologyTaskInfo> _readingOncologyTaskInfoRepository,
IRepository<Segmentation> _segmentationRepository,
IRepository<SegmentBinding> _segmentBindingRepository,
IVisitTaskHelpeService _visitTaskHelpeService,
IVisitTaskService _visitTaskService,
IReadingClinicalDataService _readingClinicalDataService,
IReadingCalculateService _readingCalculateService,
IRepository<SubjectVisit> _subjectVisitRepository,
IRepository<Subject> _subjectRepository,
IRepository<UserFeedBack> _userFeedBackRepository,
IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig,
IRepository<ReadingGlobalTaskInfo> _readingGlobalTaskInfoRepository,
IRepository<ReadingCriterionPage> _readingCriterionPageRepository,
IRepository<ReadingTaskRelation> _readingTaskRelationRepository,
IRepository<ReadingJudgeInfo> _readingJudgeInfoRepository,
IRepository<ReadModule> _readModuleRepository,
IRepository<DicomInstance> _dicomInstanceRepository,
IRepository<OrganInfo> _organInfoRepository,
IRepository<TrialUserRole> _trialUserRoleRepository,
IRepository<EmailNoticeUserType> _emailNoticeUserTypeRepository,
IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
IRepository<OrganTrialInfo> _organTrialInfoRepository,
IRepository<TrialDocument> _trialDocumentRepository,
ILuganoCalculateService _luganoCalculateService,
ILuganoWithoutPETCalculateService _LuganoWithoutPETCalculateService,
//IRepository<ReadingCustomTag> _readingCustomTagRepository,
IRepository<ReadingTaskQuestionMark> _readingTaskQuestionMarkRepository,
IRepository<ReadingTrialCriterionDictionary> _readingTrialCriterionDictionaryRepository,
IRepository<ReadingTableAnswerRowInfo> _readingTableAnswerRowInfoRepository,
IRepository<ReadingTableQuestionSystem> _readingTableQuestionSystemRepository,
IRepository<ReadingTableQuestionTrial> _readingTableQuestionTrialRepository,
IRepository<ReadingTaskQuestionAnswer> _readingTaskQuestionAnswerRepository,
IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository,
IRepository<ReadingQuestionVisitJudgeRule> _readingQuestionVisitJudgeRuleRepository,
IRepository<ReadingQuestionSystem> _readingQuestionSystem,
IRepository<CriterionKeyFileRead> _criterionKeyFileReadRepository,
IRepository<TrialCriterionKeyFile> _trialCriterionKeyFileRepository,
IRepository<NoneDicomStudyFile> _noneDicomStudyFileSystem,
IGeneralCalculateService _generalCalculateService,
IRepository<ReadingQuestionTrial> _readingQuestionTrialRepository,
IRepository<TaskStudy> _taskStudyRepository,
IConfiguration _config,
IDownloadAndUploadService _downloadAndUploadService,
ITrialEmailNoticeConfigService _trialEmailNoticeConfigService,
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig,
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IFusionCache _fusionCache) : BaseService, IReadingImageTaskService
{
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
/// <summary>
/// 获取报告图表数据
/// </summary>
/// <param name=""></param>
/// <returns></returns>
[HttpPost]
public async Task<GetReportsChartDataOutDto> GetReportsChartData(GetReportsChartDataInDto inDto)
{
return await _readingCalculateService.GetReportsChartData(inDto);
}
/// <summary>
/// 获取图表数据汇总
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<GetReportsChartSummaryOutDto> GetReportsChartSummary(GetReportsChartSummaryInDto inDto)
{
return await _readingCalculateService.GetReportsChartSummary(inDto);
}
/// <summary>
/// 设置已阅读关键文件
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> SetReadKeyFile(SetReadKeyFileInDto inDto)
{
await _criterionKeyFileReadRepository.AddAsync(new CriterionKeyFileRead()
{
IdentityUserId=_userInfo.IdentityUserId,
TrialCriterionId= inDto.TrialCriterionId,
});
await _criterionKeyFileReadRepository.SaveChangesAsync();
return ResponseOutput.Ok();
}
#region 计算
/// <summary>
/// 获取阅片的计算数据
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<object> GetReadingCalculationData(GetReadingCalculationDataInDto inDto)
{
return await _readingCalculateService.GetReadingCalculationData(inDto);
}
#endregion
/// <summary>
/// 查看检查部位
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<bool> ViewStudyPart(ViewStudyPartInDto inDto)
{
await _visitTaskRepository.UpdatePartialFromQueryAsync(x => x.Id == inDto.VisitTaskId, x => new VisitTask()
{
IsViewStudyPart = true,
});
return await _visitTaskRepository.SaveChangesAsync();
}
/// <summary>
/// 删除单个表格问题标记
/// </summary>
/// <param name="inDto"></param>
/// <param name="param"></param>
/// <returns></returns>
[HttpPost]
[Route("/DeleteSingleTableQuestionMark/{param}")]
public async Task<bool> DeleteSingleTableQuestionMark(DeleteSingleTableQuestionMarkInDto inDto, string param)
{
var mark = await _readingTaskQuestionMarkRepository.Where(x => x.Id == inDto.Id).FirstNotNullAsync();
var taskid = mark.VisitTaskId;
await _readingTableQuestionAnswerRepository.DeleteFromQueryAsync(x => x.RowId == mark.RowId && x.TableQuestionId == mark.TableQuestionId);
await _readingTaskQuestionMarkRepository.UpdatePartialFromQueryAsync(x => x.Id == inDto.Id, x => new ReadingTaskQuestionMark()
{
InstanceId = null,
SeriesId = null,
StudyId = null,
MarkTool = string.Empty,
// PicturePath = string.Empty, 稽查需要显示截图
NumberOfFrames = null,
MeasureData = string.Empty,
OrderMarkName = string.Empty,
OtherInstanceId = null,
OtherSeriesId = null,
OtherStudyId = null,
OtherMarkTool = string.Empty,
OtherPicturePath = string.Empty,
OtherNumberOfFrames = null,
OtherMeasureData = string.Empty,
});
var result = await _readingTaskQuestionMarkRepository.SaveChangesAsync();
await _readingCalculateService.CalculateTask(new CalculateTaskInDto()
{
IsChangeOtherTask = false,
VisitTaskId = taskid,
ComputationTrigger = (ComputationTrigger)int.Parse(param),
});
return result;
}
/// <summary>
/// 删除表格问题标记
/// </summary>
/// <param name="inDto"></param>
/// <param name="param"></param>
/// <returns></returns>
[HttpPost]
[Route("/DeleteTableQuestionMark/{param}")]
public async Task<bool> DeleteTableQuestionMark(DeleteTableQuestionMarkInDto inDto, string param)
{
await _readingTaskQuestionMarkRepository.UpdatePartialFromQueryAsync(x => x.RowId == inDto.RowId, x => new ReadingTaskQuestionMark()
{
InstanceId = null,
SeriesId = null,
StudyId = null,
MarkTool = string.Empty,
// PicturePath = string.Empty, 稽查需要显示截图
NumberOfFrames = null,
MeasureData = string.Empty,
OrderMarkName = string.Empty,
OtherInstanceId = null,
OtherSeriesId = null,
OtherStudyId = null,
OtherMarkTool = string.Empty,
OtherPicturePath = string.Empty,
OtherNumberOfFrames = null,
OtherMeasureData = string.Empty,
});
return await _readingTaskQuestionMarkRepository.SaveChangesAsync();
}
/// <summary>
/// 保存表格问题标记
/// </summary>
/// <param name="inDto"></param>
/// <param name="param"></param>
/// <returns></returns>
[HttpPost]
[Route("/SaveTableQuestionMark/{param}")]
public async Task<SaveTableQuestionMarkInDto> SaveTableQuestionMark(SaveTableQuestionMarkInDto inDto, string param)
{
inDto.FristAddTaskId = await _readingTaskQuestionMarkRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.TableQuestionId == inDto.TableQuestionId && x.RowId == inDto.RowId).Select(x => x.FristAddTaskId).FirstOrDefaultAsync();
inDto.FristAddTaskId = inDto.FristAddTaskId == null ? inDto.VisitTaskId : inDto.FristAddTaskId;
if (param == "-10")
{
var existingMark = await _readingTaskQuestionMarkRepository.AnyAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.MeasureData != string.Empty && x.RowId == inDto.RowId && x.TableQuestionId == inDto.TableQuestionId);
if (!existingMark && inDto.MeasureData!=string.Empty)
{
_userInfo.AuditIdentification = "AddMark";
}
else if (existingMark&& inDto.MeasureData != string.Empty)
{
_userInfo.AuditIdentification = "UpdateMark";
}
else
{
_userInfo.AuditIdentification = "DeleteMark";
}
}
var visitTaskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();
await _readingTableQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.QuestionId == inDto.QuestionId && x.RowId == inDto.RowId.Value && x.TableQuestionId == inDto.TableQuestionId);
await _readingTableQuestionAnswerRepository.AddAsync(new ReadingTableQuestionAnswer()
{
Answer = inDto.Answer,
QuestionId = inDto.QuestionId,
TableQuestionId = inDto.TableQuestionId,
VisitTaskId = inDto.VisitTaskId,
TrialId = visitTaskInfo.TrialId,
RowIndex = inDto.RowIndex,
RowId = inDto.RowId.Value,
});
var originalMarkInfo = await _readingTaskQuestionMarkRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.QuestionId == inDto.QuestionId && x.RowId == inDto.RowId.Value && x.TableQuestionId == inDto.TableQuestionId).FirstOrDefaultAsync();
if (originalMarkInfo == null)
{
if (inDto.MeasureData != string.Empty)
{
// 这里还有可能是绑定历史标记
if (inDto.MarkId != null)
{
await _readingTaskQuestionMarkRepository.BatchDeleteNoTrackingAsync(x => x.MarkId == inDto.MarkId && x.QuestionId == null);
}
var readingTaskQuestionMark = _mapper.Map<ReadingTaskQuestionMark>(inDto);
await _readingTaskQuestionMarkRepository.AddAsync(readingTaskQuestionMark);
}
}
else
{
// 如果MeasureData为空,且没有其他任务有该标记,则删除该标记
if (inDto.MeasureData == string.Empty)
{
if (await _readingTaskQuestionMarkRepository.AnyAsync(x => x.MarkId == originalMarkInfo.MarkId && x.Id != originalMarkInfo.Id))
{
await _readingTaskQuestionMarkRepository.DeleteAsync(originalMarkInfo);
}
else
{
await _readingTaskQuestionMarkRepository.UpdatePartialFromQueryAsync(x => x.Id == originalMarkInfo.Id, x => new ReadingTaskQuestionMark()
{
QuestionId=null,
TableQuestionId=null,
RowId=null,
RowIndex=null,
});
}
}
else
{
await _readingTaskQuestionMarkRepository.UpdatePartialFromQueryAsync(x => x.Id == originalMarkInfo.Id, x => new ReadingTaskQuestionMark()
{
InstanceId = inDto.InstanceId,
SeriesId = inDto.SeriesId,
StudyId = inDto.StudyId,
MarkTool = inDto.MarkTool,
PicturePath = inDto.PicturePath,
NumberOfFrames = inDto.NumberOfFrames,
MeasureData = inDto.MeasureData,
OrderMarkName = inDto.OrderMarkName,
OtherInstanceId = inDto.OtherInstanceId,
OtherSeriesId = inDto.OtherSeriesId,
OtherStudyId = inDto.OtherStudyId,
OtherMarkTool = inDto.OtherMarkTool,
OtherPicturePath = inDto.OtherPicturePath,
OtherNumberOfFrames = inDto.OtherNumberOfFrames,
OtherMeasureData = inDto.OtherMeasureData,
});
}
}
await _readingTaskQuestionMarkRepository.SaveChangesAsync();
await _readingCalculateService.CalculateTask(new CalculateTaskInDto()
{
IsChangeOtherTask = false,
VisitTaskId = inDto.VisitTaskId,
ComputationTrigger = (ComputationTrigger)int.Parse(param),
});
return inDto;
}
/// <summary>
/// 获取既往病灶的OtherPicture
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<List<GetPreviousOtherPicturePathOutDto>> GetPreviousOtherPicturePath(GetPreviousOtherPicturePathInDto inDto)
{
List<GetPreviousOtherPicturePathOutDto> result = new List<GetPreviousOtherPicturePathOutDto>() { };
if (inDto.RowId != null)
{
var rowinfo = await _readingTableAnswerRowInfoRepository.Where(x => x.Id == inDto.RowId).FirstNotNullAsync();
var taskInfoList = await _generalCalculateService.GetReadingReportTaskList(rowinfo.VisitTaskId);
var visitTaskIds = taskInfoList.Where(x => x.VisitTaskId != rowinfo.VisitTaskId).Select(x => x.VisitTaskId).ToList();
result = await _readingTableAnswerRowInfoRepository.Where(x => x.QuestionId == rowinfo.QuestionId && x.RowIndex == rowinfo.RowIndex && visitTaskIds.Contains(x.VisitTaskId))
.OrderBy(x => x.VisitTask.VisitTaskNum).Select(x => new GetPreviousOtherPicturePathOutDto()
{
VisitTaskId = x.VisitTaskId,
PicturePath = x.OtherPicturePath,
TaskBlindName = x.VisitTask.TaskBlindName
}).ToListAsync();
}
else if (inDto.VisitTaskId != null && inDto.QuestionType != null)
{
var taskInfoList = await _generalCalculateService.GetReadingReportTaskList(inDto.VisitTaskId.Value);
var visitTaskIds = taskInfoList.Where(x => x.VisitTaskId != inDto.VisitTaskId.Value).Select(x => x.VisitTaskId).ToList();
result = await _readingTaskQuestionMarkRepository.Where(x => x.ReadingQuestionTrial.QuestionType == inDto.QuestionType && visitTaskIds.Contains(x.VisitTaskId))
.OrderBy(x => x.VisitTask.VisitTaskNum).Select(x => new GetPreviousOtherPicturePathOutDto()
{
VisitTaskId = x.VisitTaskId,
PicturePath = x.OtherPicturePath,
TaskBlindName = x.VisitTask.TaskBlindName
}).ToListAsync();
}
return result.Where(x => x.PicturePath != string.Empty && x.PicturePath != null).ToList();
}
/// <summary>
/// 提交自定义标记
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> SubmitCustomTag(ReadingCustomTagDto inDto)
{
if (inDto.Id == null&&inDto.MarkId!=null)
{
var oldMark = await _readingTaskQuestionMarkRepository.Where(x => x.MarkId == inDto.MarkId && x.QuestionId == null).FirstOrDefaultAsync();
if( oldMark != null)
{
inDto.Id = oldMark.Id;
}
}
var entity = await _readingTaskQuestionMarkRepository.InsertOrUpdateAsync(inDto, true);
return ResponseOutput.Ok(entity.Id.ToString());
}
/// <summary>
/// 删除自定义标记
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpPost("{id:guid}")]
public async Task<IResponseOutput> DeleteCustomTag(Guid id)
{
if (await _readingTaskQuestionMarkRepository.AnyAsync(t => (t.Id == id || t.MarkId == id) && t.QuestionId != null))
{
throw new BusinessValidationFailedException(_localizer["ReadingCustomTag_CannotDelete"]);
}
var success = await _readingTaskQuestionMarkRepository.DeleteFromQueryAsync(t => t.Id == id||t.MarkId==id, true);
return ResponseOutput.Ok();
}
/// <summary>
/// 获取自定义标记
/// </summary>
/// <param name="inQuery"></param>
/// <returns></returns>
[HttpPost]
public async Task<List<ReadingCustomTagDto>> GetCustomTag(GetCustomTagInDto inQuery)
{
var result = await _readingTaskQuestionMarkRepository.Where(x => x.VisitTaskId == inQuery.VisitTaskId).ProjectTo<ReadingCustomTagDto>(_mapper.ConfigurationProvider).ToListAsync();
return result;
}
/// <summary>
/// 获取标记信息
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<List<MarkListInfo>> GetMarkList(GetMarkListInDto inDto)
{
var questionMarkList = await _readingTaskQuestionMarkRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId&&x.InstanceId!=null)
.Select(x => new MarkListInfo() {
MeasureData = x.MeasureData,
PicturePath = x.PicturePath,
InstanceId = x.InstanceId,
SeriesId = x.SeriesId,
StudyId = x.StudyId,
MarkName= x.OrderMarkName,
SopInstanceUid = x.Instance.SopInstanceUid,
StudyInstanceUid = x.Instance.StudyInstanceUid,
NumberOfFrames= x.Instance.NumberOfFrames,
}).ToListAsync();
var rowMarkList=await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.InstanceId != null)
.Select(x => new MarkListInfo()
{
MeasureData = x.MeasureData,
PicturePath = x.PicturePath,
InstanceId = x.InstanceId,
SeriesId = x.SeriesId,
StudyId = x.StudyId,
MarkName = x.RowMark,
SopInstanceUid = x.Instance.SopInstanceUid,
StudyInstanceUid = x.Instance.StudyInstanceUid,
NumberOfFrames = x.Instance.NumberOfFrames,
}).ToListAsync();
return questionMarkList.Union(rowMarkList).OrderBy(x=>x.MarkName).ToList();
}
/// <summary>
/// 获取非DICOM标记信息
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<List<NoneDicomMarkInfo>> GetNoneDicomMarkList(GetMarkListInDto inDto)
{
var markList = await _readingNoneDicomMarkRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).Include(x => x.NoneDicomStudyFile)
.Select(x => new NoneDicomMarkInfo()
{
StudyId = x.StudyId,
NoneDicomFileId = x.NoneDicomFileId,
Path = x.Path,
PicturePath = x.PicturePath,
MeasureData = x.MeasureData,
MarkTool = x.MarkTool,
MarkName = x.OrderMarkName,
FileName = x.NoneDicomStudyFile==null? string.Empty: x.NoneDicomStudyFile.FileName,
MarkId = x.MarkId,
}).ToListAsync();
return markList.OrderBy(x => x.MarkName).ToList();
}
/// <summary>
/// 获取手册
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<List<GetManualListOutDto>> GetManualList(GetManualListInDto inDto)
{
UserTypeEnum userType = (UserTypeEnum)_userInfo.UserTypeEnumInt;
List<UserTypeEnum> canViewUserType = new List<UserTypeEnum>()
{
UserTypeEnum.IndependentReviewer,
UserTypeEnum.IQC,
};
return await _trialDocumentRepository.Where(x => x.TrialId == inDto.TrialId
&& x.IsPublish
//&& x.TrialDocConfirmedUserList.Any(y => y.ConfirmUserId == _userInfo.UserRoleId && y.ConfirmTime != null)
&& x.NeedConfirmedUserTypeList.Any(y => y.NeedConfirmUserTypeId == _userInfo.UserTypeId))
.WhereIf(userType == UserTypeEnum.IndependentReviewer, t => t.FileType.Code == "2" || t.FileType.Code == "6")
.WhereIf(userType == UserTypeEnum.IQC, t => t.FileType.Code == "4" || t.FileType.Code == "5")
.WhereIf(!canViewUserType.Contains(userType), t => false)
.Select(x => new GetManualListOutDto()
{
Id = x.Id,
Name = x.Name,
Path = x.Path
}).ToListAsync();
}
/// <summary>
/// 获取任务附加问题
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<(List<TrialAdditionaQuestion>, bool)> GetTaskAdditionalQuestion(GetTaskAdditionalQuestionInDto inDto)
{
var answerList = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).IgnoreAutoIncludes().ToListAsync();
var taskInfo = await _visitTaskRepository.Where(x => inDto.VisitTaskId == x.Id).FirstNotNullAsync();
var result = await _readingQuestionTrialRepository.Where(x => x.IsAdditional && x.ReadingQuestionCriterionTrialId == taskInfo.TrialReadingCriterionId).IgnoreAutoIncludes().IgnoreQueryFilters().ProjectTo<TrialAdditionaQuestion>(_mapper.ConfigurationProvider).OrderBy(x => x.ShowOrder).ToListAsync();
result.ForEach(x =>
{
var answer = answerList.Where(y => y.ReadingQuestionTrialId == x.Id).FirstOrDefault();
if (answer != null)
{
x.Answer = answer.Answer;
}
});
var resultData = result.Where(x => x.Type == "group").ToList();
resultData.ForEach(x =>
{
x.Childrens = result.Where(y => y.GroupId == x.Id).ToList();
});
return (resultData, true);
}
/// <summary>
/// 提交附加问题
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<bool> SubmitTaskAdditionalQuestion(SubmitTaskAdditionalQuestionInDto inDto)
{
var taskInfo = await _visitTaskRepository.Where(x => inDto.VisitTaskId == x.Id).FirstNotNullAsync();
var questionids = inDto.AnswerList.Select(x => x.QuestionId).ToList();
await _readingTaskQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId && questionids.Contains(x.ReadingQuestionTrialId));
await _readingTaskQuestionAnswerRepository.AddRangeAsync(inDto.AnswerList.Select(x => new ReadingTaskQuestionAnswer()
{
VisitTaskId = inDto.VisitTaskId,
ReadingQuestionCriterionTrialId = taskInfo.TrialReadingCriterionId,
Answer = x.Answer,
ReadingQuestionTrialId = x.QuestionId,
TrialId = taskInfo.TrialId,
SubjectId = taskInfo.SubjectId
}).ToList());
return await _readingTaskQuestionAnswerRepository.SaveChangesAsync();
}
/// <summary>
/// 维护任务关系
/// </summary>
/// <returns></returns>
public async Task MaintainTaskRelated()
{
List<ReadingTaskRelation> relations = new List<ReadingTaskRelation>();
var visitList = await _visitTaskRepository.Where(x => x.PastResultTaskIds != "[]" && x.RelatedVisitTaskIds != "[]").Select(x => new
{
x.Id,
x.RelatedVisitTaskIds,
x.PastResultTaskIds
}).ToListAsync();
List<Guid> relatedIds = new List<Guid>();
List<Guid> PastResultds = new List<Guid>();
foreach (var item in visitList)
{
try
{
PastResultds = JsonConvert.DeserializeObject<List<Guid>>(item.PastResultTaskIds) ?? new List<Guid>();
}
catch (Exception)
{
PastResultds = new List<Guid>();
}
try
{
relatedIds = JsonConvert.DeserializeObject<List<Guid>>(item.RelatedVisitTaskIds) ?? new List<Guid>();
}
catch (Exception)
{
relatedIds = new List<Guid>();
}
relations.AddRange(PastResultds.Select(x => new ReadingTaskRelation()
{
RelevanceTaskId = x,
TaskId = item.Id,
RelevanceType = RelevanceType.PastResult,
}));
relations.AddRange(relatedIds.Select(x => new ReadingTaskRelation()
{
RelevanceTaskId = x,
TaskId = item.Id,
RelevanceType = RelevanceType.Related,
}));
await _readingTaskRelationRepository.BatchDeleteNoTrackingAsync(x => x.TaskId == item.Id);
}
await _readingTaskRelationRepository.AddRangeAsync(relations);
await _readingTaskRelationRepository.SaveChangesAsync();
}
/// <summary>
/// 修改计算问题
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
[TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task ChangeCalculationAnswer(ChangeCalculationAnswerInDto inDto)
{
var visitTask = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();
var questionAnswerList = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).ToListAsync();
var tableQuestionAnswerList = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).ToListAsync();
var rowInfoList = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).ToListAsync();
foreach (var item in inDto.QuestionAnswer)
{
if (questionAnswerList.Any(x => x.ReadingQuestionTrialId == item.QuestionId))
{
await _readingTaskQuestionAnswerRepository.UpdatePartialFromQueryAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.ReadingQuestionTrialId == item.QuestionId, x => new ReadingTaskQuestionAnswer()
{
Answer = item.Answer,
});
}
else
{
await _readingTaskQuestionAnswerRepository.AddAsync(new ReadingTaskQuestionAnswer()
{
Answer = item.Answer,
ReadingQuestionCriterionTrialId = visitTask.TrialReadingCriterionId,
ReadingQuestionTrialId = item.QuestionId,
SubjectId = visitTask.SubjectId,
VisitTaskId = inDto.VisitTaskId,
TrialId = visitTask.TrialId
});
}
}
foreach (var item in inDto.TableQuestionAnswer.Where(x => x.RowId != null))
{
if (tableQuestionAnswerList.Any(x => x.QuestionId == item.QuestionId && x.RowId == item.RowId && x.TableQuestionId == item.TableQuestionId))
{
await _readingTableQuestionAnswerRepository.UpdatePartialFromQueryAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.RowId == item.RowId && x.TableQuestionId == item.TableQuestionId, x => new ReadingTableQuestionAnswer()
{
Answer = item.Answer,
});
}
else
{
var rowInfo = rowInfoList.Where(x => x.Id == item.RowId).FirstOrDefault() ?? new ReadingTableAnswerRowInfo();
await _readingTableQuestionAnswerRepository.AddAsync(new ReadingTableQuestionAnswer()
{
Answer = item.Answer,
QuestionId = item.QuestionId,
TableQuestionId = item.TableQuestionId,
RowIndex = rowInfo.RowIndex,
RowId = rowInfo.Id,
VisitTaskId = inDto.VisitTaskId,
TrialId = visitTask.TrialId
});
}
}
await _readingTableQuestionAnswerRepository.SaveChangesAsync();
}
/// <summary>
/// 阅读临床数据
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
[TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task ReadClinicalData(ReadClinicalDataInDto inDto)
{
await _visitTaskRepository.UpdatePartialFromQueryAsync(inDto.VisitTaskId, x => new VisitTask
{
IsReadClinicalData = true
});
await _visitTaskRepository.SaveChangesAsync();
}
/// <summary>
/// 添加默认值到任务里面
/// </summary>
/// <returns></returns>
[NonDynamicMethod]
public async Task AddDefaultValueToTask(Guid visitTaskId)
{
var visitTaskInfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).FirstNotNullAsync();
var questions = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == visitTaskInfo.TrialReadingCriterionId).ToListAsync();
questions = questions.Where(x => !x.DefaultValue.IsNullOrEmpty()).ToList();
var taskAnswerIds = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == visitTaskId).Select(x => x.ReadingQuestionTrialId).ToListAsync();
questions = questions.Where(x => !taskAnswerIds.Contains(x.Id)).ToList();
List<ReadingTaskQuestionAnswer> questionAnswers = questions.Select(x => new ReadingTaskQuestionAnswer()
{
Answer = x.DefaultValue,
Id = NewId.NextGuid(),
ReadingQuestionCriterionTrialId = visitTaskInfo.TrialReadingCriterionId,
ReadingQuestionTrialId = x.Id,
SubjectId = visitTaskInfo.SubjectId,
TrialId = visitTaskInfo.TrialId,
VisitTaskId = visitTaskId,
}).ToList();
await _readingTaskQuestionAnswerRepository.AddRangeAsync(questionAnswers);
await _readingTaskQuestionAnswerRepository.SaveChangesAsync();
}
#region 阅片页面 关联信息查询 以及基本验证
/// <summary>
/// 根据任务ID获取ReadingTool
/// </summary>
/// <param name="indto"></param>
/// <returns></returns>
[HttpPost]
public async Task<GetReadingToolOutDto> GetReadingTool(GetReadingToolInDto indto)
{
var visitTaskInfo = await _visitTaskRepository.Where(x => x.Id == indto.VisitTaskId).FirstNotNullAsync();
var criterionTrialInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == visitTaskInfo.TrialReadingCriterionId).FirstNotNullAsync();
GetReadingToolOutDto result = new GetReadingToolOutDto()
{
TrialReadingCriterionId = visitTaskInfo.TrialReadingCriterionId,
ReadingTool = criterionTrialInfo.ReadingTool,
CriterionType = criterionTrialInfo.CriterionType,
};
return result;
}
/// <summary>
/// 获取关联的阅片任务
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<(List<GetRelatedVisitTaskOutDto>, object)> GetRelatedVisitTask(GetRelatedVisitTaskInDto inDto)
{
var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Include(x => x.TrialReadingCriterion).FirstNotNullAsync();
var baselineVisitId = await _subjectVisitRepository.Where(x => x.SubjectId == taskInfo.SubjectId && x.IsBaseLine && !x.IsLostVisit).Select(x => x.Id).FirstNotNullAsync();
var taskQuery = _visitTaskRepository.Where(x =>
(x.TrialId == taskInfo.TrialId &&
x.SubjectId == taskInfo.SubjectId &&
x.ArmEnum == taskInfo.ArmEnum &&
x.DoctorUserId == taskInfo.DoctorUserId &&
x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId &&
x.TaskState == TaskState.Effect &&
x.IsAnalysisCreate == taskInfo.IsAnalysisCreate &&
x.ReadingCategory == ReadingCategory.Visit) || x.Id == inDto.VisitTaskId)
.WhereIf(taskInfo.TrialReadingCriterion.IsReadingTaskViewInOrder != ReadingOrder.SubjectRandom, x => (x.VisitTaskNum <= taskInfo.VisitTaskNum && x.ReadingTaskState == ReadingTaskState.HaveSigned) || x.Id == inDto.VisitTaskId);
if (taskInfo.ReadingTaskState == ReadingTaskState.HaveSigned)
{
taskQuery = _visitTaskRepository.Where(x => taskInfo.RelatedVisitTaskIdList.Contains(x.Id) || x.Id == taskInfo.Id);
}
var result = await taskQuery.Include(x => x.Subject).OrderBy(x => x.VisitTaskNum).ThenBy(x => x.TaskState)
.Select(x => new GetRelatedVisitTaskOutDto()
{
TaskBlindName = x.TaskBlindName,
TaskName = x.TaskName,
ReadingTaskState = x.ReadingTaskState,
VisitId = x.SourceSubjectVisitId,
SubjectCode = x.Subject.Code,
VisitTaskId = x.Id,
VisitTaskNum = x.VisitTaskNum,
IsBaseLineTask = x.SourceSubjectVisitId == baselineVisitId,
IsCurrentTask = x.Id == inDto.VisitTaskId,
IsConvertedTask = x.IsConvertedTask,
IsFirstChangeTask = x.BeforeConvertedTaskId != null,
IsExistUnprocessedFeedback = x.UserFeedBackList.Any(y => y.State == 0),
}).ToListAsync();
switch (taskInfo.TrialReadingCriterion.IsReadingTaskViewInOrder)
{
case ReadingOrder.InOrder:
/// 有序不做处理
break;
case ReadingOrder.Random:
result = result.Where(x => x.VisitTaskId == inDto.VisitTaskId).ToList();
break;
case ReadingOrder.SubjectRandom:
// 受试者随机 当前任务为第一个 其他的 随机
var self = result.Where(x => x.VisitTaskId == inDto.VisitTaskId).FirstOrDefault();
Random random = new Random();
var otherList = result.Where(x => x.VisitTaskId != inDto.VisitTaskId).OrderBy(x => random.Next()).ToList();
var newList = new List<GetRelatedVisitTaskOutDto>() { };
newList.AddRange(otherList);
newList.Add(self);
result = newList;
break;
}
var visitaskIds = result.Select(x => x.VisitTaskId).ToList();
var otherStudys = await _readingTableAnswerRowInfoRepository.Where(x => visitaskIds.Contains(x.VisitTaskId))
.Where(x => x.CTSeriesId != null && x.PTSeriesId != null)
.Select(x => new
{
x.OtherStudyId,
x.CTSeriesId,
x.PTSeriesId,
x.VisitTaskId,
x.UpdateTime
}).ToListAsync();
foreach (var item in result)
{
var clinicalDataList = await _readingClinicalDataService.GetClinicalDataList(new GetReadingOrTaskClinicalDataListInDto()
{
SubjectId = taskInfo.SubjectId,
TrialId = taskInfo.TrialId,
VisitTaskId = item.VisitTaskId,
});
item.IsExistsClinicalData = clinicalDataList.Count > 0;
var otherStudy = otherStudys.Where(x => x.VisitTaskId == item.VisitTaskId).OrderByDescending(x => x.UpdateTime).FirstOrDefault();
if (otherStudy != null)
{
item.PTSeriesId = otherStudy.PTSeriesId;
item.CTSeriesId = otherStudy.CTSeriesId;
item.OtherStudyId = otherStudy.OtherStudyId;
}
}
return (result, new
{
ReadingTaskState = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Select(x => x.ReadingTaskState).FirstOrDefaultAsync()
});
}
/// <summary>
/// 获取既往任务名称和编号
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<List<GetReadingPastResultListOutDto>> GetReadingPastResultList(GetReadingPastResultListInDto inDto)
{
var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();
var taskQuery = _visitTaskRepository.Where(x =>
x.TrialId == taskInfo.TrialId &&
x.SubjectId == taskInfo.SubjectId &&
x.VisitTaskNum < taskInfo.VisitTaskNum &&
x.ArmEnum == taskInfo.ArmEnum &&
x.Id != inDto.VisitTaskId &&
x.DoctorUserId == taskInfo.DoctorUserId &&
x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId &&
x.ReadingTaskState == ReadingTaskState.HaveSigned &&
x.TaskState == TaskState.Effect &&
x.IsSelfAnalysis == taskInfo.IsSelfAnalysis &&
x.IsAnalysisCreate == taskInfo.IsAnalysisCreate &&
x.ReadingCategory == taskInfo.ReadingCategory
);
if (taskInfo.ReadingTaskState == ReadingTaskState.HaveSigned)
{
taskQuery = _visitTaskRepository.Where(x => taskInfo.PastResultTaskIdList.Contains(x.Id));
}
var readingPastResultList = await taskQuery.OrderBy(x => x.VisitTaskNum).ThenBy(x => x.TaskState).Select(x => new GetReadingPastResultListOutDto()
{
VisitTaskId = x.Id,
TaskBlindName = x.TaskBlindName,
TaskName = x.TaskName,
ReadModuleVisitId = x.ReadModule != null ? x.ReadModule.SubjectVisitId : null,
VisitName = x.SourceSubjectVisit != null ? x.SourceSubjectVisit.VisitName : x.ReadModule == null ? string.Empty : x.ReadModule.SubjectVisit.VisitName,
VisitBlindName = x.TaskBlindName,
VisitTaskNum = x.VisitTaskNum,
JudgeResultArm = x.JudgeResultTask == null ? null : x.JudgeResultTask.ArmEnum,
}).ToListAsync();
foreach (var item in readingPastResultList)
{
if (item.ReadModuleVisitId != null)
{
item.VisitBlindName = (await _visitTaskRepository.Where(x => x.SourceSubjectVisitId == item.ReadModuleVisitId && x.IsSelfAnalysis == taskInfo.IsSelfAnalysis &&
x.IsAnalysisCreate == taskInfo.IsAnalysisCreate).Select(x => x.TaskBlindName).FirstOrDefaultAsync()) ?? string.Empty;
}
}
return readingPastResultList;
}
/// <summary>
/// 获取阅片的受试者信息
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<GetReadingSubjectInfoOutDto> GetReadingSubjectInfo(GetReadingSubjectInfoInDto inDto)
{
var visitTask = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();
var subjectCode = await _subjectRepository.Where(x => x.Id == visitTask.SubjectId).Select(x => x.Code).FirstOrDefaultAsync();
var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == visitTask.TrialReadingCriterionId).Select(x => new
{
x.IsReadingShowPreviousResults,
x.IsReadingShowSubjectInfo
}).FirstNotNullAsync();
var trialInfo = await _trialRepository.Where(x => x.Id == visitTask.TrialId).Select(x => new
{
x.ClinicalInformationTransmissionEnum,
}).FirstOrDefaultAsync();
return new GetReadingSubjectInfoOutDto()
{
VisitTaskId = visitTask.Id,
SubjectId = visitTask.SubjectId,
SubjectCode = visitTask.BlindSubjectCode.IsNullOrEmpty() ? subjectCode ?? string.Empty : visitTask.BlindSubjectCode,
ReadingCategory = visitTask.ReadingCategory,
TaskBlindName = visitTask.TaskBlindName,
IsReadingShowPreviousResults = criterionInfo.IsReadingShowPreviousResults,
IsReadingShowSubjectInfo = criterionInfo.IsReadingShowSubjectInfo,
};
}
/// <summary>
/// 验证是否为基线访视任务
/// </summary>
/// <param name="visitTaskId"></param>
/// <returns></returns>
/// <exception cref="BusinessValidationFailedException"></exception>
private async Task VerifyIsBaseLineTask(Guid visitTaskId)
{
var taskinfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).FirstNotNullAsync();
if (taskinfo.ReadingCategory != ReadingCategory.Visit)
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_NotVisit"]);
}
if (await _subjectVisitRepository.AnyAsync(x => x.Id == taskinfo.SourceSubjectVisitId && x.IsBaseLine))
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_CantSplit"]);
}
}
/// <summary>
/// 验证任务是否签名
/// </summary>
/// <param name="visitTaskid"></param>
/// <returns></returns>
/// <exception cref="BusinessValidationFailedException"></exception>
private async Task VerifyTaskIsSign(Guid visitTaskid)
{
var taskInfo = await _visitTaskRepository.Where(x => x.Id == visitTaskid).FirstNotNullAsync();
if (await _visitTaskRepository.AnyAsync(x => x.Id == visitTaskid && x.ReadingTaskState == ReadingTaskState.HaveSigned))
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_BeSigned"]);
}
if (await _visitTaskRepository.AnyAsync(x => x.Id == visitTaskid && x.TaskState != TaskState.Effect))
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_Beinvalid"]);
}
if (await _visitTaskRepository.AnyAsync(x => x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId
&& x.IsAnalysisCreate && taskInfo.IsAnalysisCreate
&& x.SubjectId == taskInfo.SubjectId && x.TaskState == TaskState.Effect &&
((x.ReReadingApplyState == ReReadingApplyState.DocotorHaveApplyed && x.DoctorUserId == taskInfo.DoctorUserId) || x.ReReadingApplyState == ReReadingApplyState.TrialGroupHaveApplyed)
))
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_PresenceReview"]);
}
}
#endregion
#region 访视任务 - Dicom 阅片 表格问题相关查询
/// <summary>
/// 获取DIcom阅片问题答案
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<(List<DicomReadingQuestionAnswer>, object)> GetDicomReadingQuestionAnswer(GetDicomReadingQuestionAnswerInDto inDto)
{
//await AddDefaultValueToTask(inDto.VisitTaskId);
var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();
var result = await GetReadingQuestion(taskInfo.TrialReadingCriterionId, taskInfo.Id, inDto.QuestionClassify, inDto.GroupClassifyList);
return (result, new
{
QuestionMarkInfoList = await _readingTaskQuestionMarkRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).ProjectTo<QuestionMarkInfo>(_mapper.ConfigurationProvider).ToListAsync(),
ReadingTaskState = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Select(x => x.ReadingTaskState).FirstOrDefaultAsync()
});
}
/// <summary>
/// 获取阅片外层问题
/// </summary>
/// <param name="trialReadingCriterionId"></param>
/// <param name="visitTaskId"></param>
/// <param name="questionClassify"></param>
/// <param name="groupClassifyList"></param>
/// <returns></returns>
[NonDynamicMethod]
public async Task<List<DicomReadingQuestionAnswer>> GetReadingQuestion(Guid trialReadingCriterionId, Guid? visitTaskId, QuestionClassify? questionClassify, List<GroupClassify>? groupClassifyList)
{
var criterionIdInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == trialReadingCriterionId).FirstNotNullAsync();
var groupIds = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == trialReadingCriterionId && (x.Type == ReadingQestionType.Table || x.Type == ReadingQestionType.BasicTable)).Select(x => x.GroupId).Distinct().ToListAsync();
var questionIds = await _readingQuestionTrialRepository
.Where(x => x.IsShowInDicom)
.Where(x => groupIds.Contains(x.GroupId)).Select(x => x.Id).ToListAsync();
//排除表格问题 以及在表格问题分组的外层问题
var questions = await _readingQuestionTrialRepository
.Where(x => !questionIds.Contains(x.Id))
.WhereIf(questionClassify != null, x => x.QuestionClassify == questionClassify)
.Where(x => x.IsShowInDicom && x.ReadingQuestionCriterionTrialId == trialReadingCriterionId && x.Type != ReadingQestionType.Table && x.Type != ReadingQestionType.BasicTable)
.ProjectTo<DicomReadingQuestionAnswer>(_mapper.ConfigurationProvider, new
{
isEn_Us = _userInfo.IsEn_Us
}).OrderBy(x => x.ShowOrder).ToListAsync();
var answers = new List<ReadingTaskQuestionAnswer>();
var lastTaskAnswer = new List<ReadingTaskQuestionAnswer>();
if (visitTaskId != null)
{
answers = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == visitTaskId).ToListAsync();
var taskInfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).FirstNotNullAsync();
var laskTaskId = await _visitTaskRepository.Where(x =>
(x.SubjectId == taskInfo.SubjectId && x.TaskState == TaskState.Effect
&& x.IsAnalysisCreate == taskInfo.IsAnalysisCreate
&& x.DoctorUserId == taskInfo.DoctorUserId
&& x.IsSelfAnalysis == taskInfo.IsSelfAnalysis
&& x.VisitTaskNum < taskInfo.VisitTaskNum
&& x.ArmEnum == taskInfo.ArmEnum
&& x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId
&& x.ReadingCategory == ReadingCategory.Visit) || x.Id == taskInfo.BeforeConvertedTaskId
).OrderByDescending(x => x.VisitTaskNum).Select(x => x.Id).FirstOrDefaultAsync();
if (criterionIdInfo.IsReadingTaskViewInOrder != ReadingOrder.InOrder)
{
// 无序的话 不要查
laskTaskId = Guid.NewGuid();
}
lastTaskAnswer = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == laskTaskId).ToListAsync();
var taskinfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).ProjectTo<VisitTaskDto>(_mapper.ConfigurationProvider).FirstNotNullAsync();
if (taskInfo.VisitTaskNum == 0)
{
questions = questions.Where(x => (x.LimitShow == LimitShow.AllShow || x.LimitShow == LimitShow.BaseLineShow) || (x.LimitShow == LimitShow.ExcludeSomeVisits && !x.ExcludeShowVisitList.Contains(taskInfo.VisitTaskNum))).ToList();
}
else
{
questions = questions.Where(x => (x.LimitShow == LimitShow.AllShow || x.LimitShow == LimitShow.FollowShow) || (x.LimitShow == LimitShow.ExcludeSomeVisits && !x.ExcludeShowVisitList.Contains(taskInfo.VisitTaskNum))).ToList();
}
questions.ForEach(x =>
{
x.CrterionDictionaryGroup = ReadingCommon.GetCrterionDictionaryGroup(taskinfo.IsConvertedTask);
});
if (taskinfo.IsConvertedTask && taskinfo.BeforeConvertedTaskId != null)
{
questions.ForEach(x =>
{
x.IsFirstChangeTask = true;
});
}
}
else
{
var crterionDictionaryGroup = new List<CrterionDictionaryGroup>() { CrterionDictionaryGroup.General, CrterionDictionaryGroup.BeforeConvert };
questions.ForEach(x =>
{
x.CrterionDictionaryGroup = crterionDictionaryGroup;
});
}
//排除表格问题 同时排除组问题
var groupids = questions.Where(x => x.Type != ReadingQestionType.Group).Select(x => x.GroupId).ToList();
var result = questions.Where(x => x.Type == ReadingQestionType.Group && groupids.Contains(x.Id))
.WhereIf(groupClassifyList != null, x => x.GroupClassify != null && groupClassifyList != null && groupClassifyList.Contains(x.GroupClassify.Value))
.ToList();
foreach (var item in result)
{
GetDicomReadingAnswer(item, questions, answers, lastTaskAnswer);
}
return result;
}
private void GetDicomReadingAnswer(DicomReadingQuestionAnswer item, List<DicomReadingQuestionAnswer> questions, List<ReadingTaskQuestionAnswer> answers, List<ReadingTaskQuestionAnswer> lastTaskAnswers)
{
var answer = answers.Where(x => x.ReadingQuestionTrialId == item.Id).Select(x => x.Answer).FirstIsNullReturnEmpty();
item.Answer = answer.IsNullOrEmpty() ? item.DefaultValue : answer;
var lastTaskAnswer = lastTaskAnswers.Where(x => x.ReadingQuestionTrialId == item.Id).Select(x => x.Answer).FirstIsNullReturnEmpty();
item.LastTaskAnswer = lastTaskAnswer.IsNullOrEmpty() ? item.DefaultValue : lastTaskAnswer;
item.Childrens = questions.Where(x => x.ParentId == item.Id || (x.GroupId == item.Id && x.ParentId == null)).ToList();
if (item.Childrens != null && item.Childrens.Count > 0)
{
foreach (var question in item.Childrens)
{
GetDicomReadingAnswer(question, questions, answers, lastTaskAnswers);
}
}
}
/// <summary>
/// 获取阅片报告
/// </summary>
/// <param name="indto"></param>
/// <returns></returns>
[HttpPost]
public async Task<GetReadingReportEvaluationOutDto> GetReadingReportEvaluation(GetReadingReportEvaluationInDto indto)
{
return await _readingCalculateService.GetReadingReportEvaluation(indto);
}
/// <summary>
/// 获取表格答案行信息
/// </summary>
/// <param name="inDto"></param>
/// <remarks>
/// (QuestionId) 可为空
/// </remarks>
/// <returns></returns>
[HttpGet]
public async Task<List<GetTableAnswerRowInfoOutDto>> GetTableAnswerRowInfoList(GetTableAnswerRowInfoInDto inDto)
{
var result = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId)
.WhereIf(inDto.QuestionId != null, x => x.QuestionId == inDto.QuestionId)
.ProjectTo<GetTableAnswerRowInfoOutDto>(_mapper.ConfigurationProvider).OrderBy(x => x.ShowOrder).ThenBy(x => x.RowIndex)
.ToListAsync();
//var tableQuestionMarkList = await _readingTaskQuestionMarkRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).ToListAsync();
//result.ForEach(x =>
//{
// x.TableQuestionMarkList = tableQuestionMarkList.Where(y => y.RowId == x.RowId).ToList();
//});
var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).ProjectTo<VisitTaskDto>(_mapper.ConfigurationProvider).FirstNotNullAsync();
if (taskInfo.IsConvertedTask && taskInfo.BeforeConvertedTaskId != null)
{
result.ForEach(x =>
{
x.IsFirstChangeTask = true;
});
}
result.ForEach(x =>
{
x.OrderMarkName = x.OrderMark + x.RowIndexNum.GetLesionMark();
});
var questionMark = await _readingTaskQuestionMarkRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).ProjectTo<GetTableAnswerRowInfoOutDto>(_mapper.ConfigurationProvider).ToListAsync();
questionMark.ForEach(x =>
{
x.IsFirstChangeTask = x.VisitTaskId == inDto.VisitTaskId;
});
result.AddRange(questionMark);
result = result.OrderBy(x => x.ShowOrder).ThenBy(x => x.RowIndex).ThenBy(x => x.OrderMarkName).ToList();
return result;
}
/// <summary>
/// 获取表格问题及答案(2022-08-26)
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<(GetReadingQuestionAndAnswerOutDto, object)> GetReadingQuestionAndAnswer(GetReadingQuestionAndAnswerInDto inDto)
{
//await AddDefaultValueToTask(inDto.VisitTaskId);
var result = new GetReadingQuestionAndAnswerOutDto();
var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();
var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == taskinfo.TrialReadingCriterionId).FirstNotNullAsync();
result.ReadingTaskState = taskinfo.ReadingTaskState;
var baseLineVisitId = await _subjectVisitRepository.Where(x => x.SubjectId == taskinfo.SubjectId && x.IsBaseLine).Select(x => x.Id).FirstOrDefaultAsync();
result.IsBaseLineTask = taskinfo.SourceSubjectVisitId == baseLineVisitId;
var visitTaskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();
var tableAnswers = await _readingTableQuestionAnswerRepository
.ProjectTo<ReadingTableQuestionAnswerInfo>(_mapper.ConfigurationProvider)
.Where(x => x.VisitTaskId == inDto.VisitTaskId).ToListAsync();
var tableAnsweRowInfos = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).ProjectTo<TableAnsweRowInfo>(_mapper.ConfigurationProvider).ToListAsync();
var organIds = tableAnsweRowInfos.Where(x => x.OrganInfoId != null).Select(x => x.OrganInfoId).Distinct().ToList();
var organList = await _organInfoRepository.Where(x => organIds.Contains(x.Id)).ToListAsync();
var questionPage = await GetReadingTableQuestion(
new GetReadingTableQuestionOrAnswerInDto()
{
TrialReadingCriterionId = taskinfo.TrialReadingCriterionId,
TaskId = inDto.VisitTaskId,
TableAnswers = tableAnswers,
TableAnsweRowInfos = tableAnsweRowInfos,
OrganInfos = organList,
QuestionClassify = inDto.QuestionClassify,
}
);
result.SinglePage = questionPage.SinglePage;
result.MultiPage = questionPage.MultiPage;
result.PublicPage = questionPage.PublicPage;
result.BlindName = visitTaskInfo.TaskBlindName;
result.TaskNum = visitTaskInfo.VisitTaskNum;
result.QuestionMarkInfoList = await _readingTaskQuestionMarkRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).ProjectTo<QuestionMarkInfo>(_mapper.ConfigurationProvider)
.ToListAsync();
var spleenLength = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.ReadingQuestionTrial.QuestionType == QuestionType.SpleenLength).Select(x => x.Answer).FirstOrDefaultAsync();
return (result, new
{
readingTaskState = visitTaskInfo.ReadingTaskState,
FormType = criterionInfo.FormType,
TaskNum = visitTaskInfo.VisitTaskNum,
SpleenLength = spleenLength,
}); ;
}
/// <summary>
/// 获取单个表格问题及答案 过滤问题
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> GetFilterTableQuestion(GetFilterTableQuestionInDto inDto)
{
var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();
var tableAnswers = await _readingTableQuestionAnswerRepository
.ProjectTo<ReadingTableQuestionAnswerInfo>(_mapper.ConfigurationProvider)
.Where(x => x.VisitTaskId == inDto.VisitTaskId).ToListAsync();
var tableAnsweRowInfos = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).ProjectTo<TableAnsweRowInfo>(_mapper.ConfigurationProvider).ToListAsync();
var organIds = tableAnsweRowInfos.Where(x => x.OrganInfoId != null).Select(x => x.OrganInfoId).Distinct().ToList();
var organList = await _organInfoRepository.Where(x => organIds.Contains(x.Id)).ToListAsync();
var questionPage = await GetReadingTableQuestion(
new GetReadingTableQuestionOrAnswerInDto()
{
TrialReadingCriterionId = taskinfo.TrialReadingCriterionId,
TaskId = inDto.VisitTaskId,
TableAnswers = tableAnswers,
TableAnsweRowInfos = tableAnsweRowInfos,
OrganInfos = organList,
QuestionClassify = inDto.QuestionClassify,
});
var result = questionPage.SinglePage.SelectMany(x => x.Childrens).Where(x => x.Id == inDto.QuestionId).FirstOrDefault();
return ResponseOutput.Ok(result);
}
/// <summary>
/// 获取自定义问题以及答案
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<(GetReadingTableQuestionOutDto, object)> GetCustomTableQuestionAnswer(GetCustomTableQuestionAnswerInDto inDto)
{
//await _readingCalculateService.AddTaskLesionAnswerFromLastTask(new AddTaskLesionAnswerFromLastTaskInDto() {
//VisitTaskId=inDto.VisitTaskId
//});
var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Include(x => x.SourceSubjectVisit).FirstNotNullAsync();
var tableAnswers = await _readingTableQuestionAnswerRepository
.ProjectTo<ReadingTableQuestionAnswerInfo>(_mapper.ConfigurationProvider)
.Where(x => x.VisitTaskId == inDto.VisitTaskId).ToListAsync();
var tableAnsweRowInfos = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).ProjectTo<TableAnsweRowInfo>(_mapper.ConfigurationProvider).ToListAsync();
var organIds = tableAnsweRowInfos.Where(x => x.OrganInfoId != null).Select(x => x.OrganInfoId).Distinct().ToList();
var organList = await _organInfoRepository.Where(x => organIds.Contains(x.Id)).ToListAsync();
var tableQuestionMarkList=new List<QuestionMarkInfo>();
if (inDto.IsDicomReading)
{
// 删除病灶不删除病灶标记 所以查询question的时候 已经删除的病灶对应的标记的信息要排除
var rowids = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).Select(x => x.Id).ToListAsync();
List<Guid?> rowidnull = rowids.Select(x => (Guid?)x).ToList();
tableQuestionMarkList = await _readingTaskQuestionMarkRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.QuestionId != null
).ProjectTo<QuestionMarkInfo>(_mapper.ConfigurationProvider).ToListAsync();
}
else
{
var markList = await _readingNoneDicomMarkRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId
).ProjectTo<QuestionMarkInfo>(_mapper.ConfigurationProvider).ToListAsync();
var bingList= await _readingNoneDicomMarkBindingRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId)
.ProjectTo<QuestionMarkInfo>(_mapper.ConfigurationProvider).ToListAsync();
tableQuestionMarkList = markList
.GroupJoin(
bingList,
l => l.MarkId,
r => r.MarkId,
(l, rs) => rs.DefaultIfEmpty()
.Select(r =>
{
var info = l.Clone();
info.QuestionId = r?.QuestionId;
info.TableQuestionId = r?.TableQuestionId;
info.RowId = r?.RowId;
return info;
}))
.SelectMany(g => g).ToList();
tableQuestionMarkList = tableQuestionMarkList.Where(x => x.QuestionId != null).ToList();
}
var isHaveBindingQuestion=(await _readingQuestionTrialRepository.AnyAsync(x=>x.ReadingQuestionCriterionTrialId==taskInfo.TrialReadingCriterionId&&x.ImageToolAttribute!=string.Empty))
|| (await _readingTableQuestionTrialRepository.AnyAsync(x=>x.ReadingQuestionTrial.ReadingQuestionCriterionTrialId == taskInfo.TrialReadingCriterionId && x.ImageToolAttribute != string.Empty));
return (await GetReadingTableQuestion(
new GetReadingTableQuestionOrAnswerInDto()
{
TrialReadingCriterionId = taskInfo.TrialReadingCriterionId,
TaskId = taskInfo.Id,
TableAnswers = tableAnswers,
TableAnsweRowInfos = tableAnsweRowInfos,
IsGetallQuestion = true,
OrganInfos = organList,
QuestionClassify = inDto.QuestionClassify,
}
), new
{
IsHaveBindingQuestion= isHaveBindingQuestion,
IsBaseline = taskInfo.SourceSubjectVisit != null && taskInfo.SourceSubjectVisit.IsBaseLine,
ReadingTaskState = taskInfo.ReadingTaskState,
QuestionMarkInfoList = tableQuestionMarkList,
});
}
/// <summary>
/// 获取表格问题及答案 只返回表格问题(任务和标准)
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[NonDynamicMethod]
public async Task<GetReadingTableQuestionOutDto> GetReadingTableQuestion(GetReadingTableQuestionOrAnswerInDto inDto)
{
var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inDto.TrialReadingCriterionId).FirstNotNullAsync();
var tableQuestionMarkList = await _readingTaskQuestionMarkRepository.Where(x => x.VisitTaskId == inDto.TaskId).ProjectTo<TableQuestionMark>(_mapper.ConfigurationProvider).ToListAsync();
var qusetionList = await _readingQuestionTrialRepository
.Where(x => x.IsShowInDicom)
.WhereIf(inDto.QuestionClassify != null, x => x.QuestionClassify == inDto.QuestionClassify)
.Where(x => x.ReadingQuestionCriterionTrialId == inDto.TrialReadingCriterionId).ProjectTo<TrialReadQuestionData>(_mapper.ConfigurationProvider, new
{
isEn_Us = _userInfo.IsEn_Us
}).OrderBy(x => x.ShowOrder).ToListAsync();
var taskInfo = new VisitTaskDto();
if (inDto.TaskId != null)
{
taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.TaskId).ProjectTo<VisitTaskDto>(_mapper.ConfigurationProvider).FirstNotNullAsync();
if (taskInfo.VisitTaskNum == 0)
{
qusetionList = qusetionList.Where(x => (x.LimitShow == LimitShow.AllShow || x.LimitShow == LimitShow.BaseLineShow) || (x.LimitShow == LimitShow.ExcludeSomeVisits&&!x.ExcludeShowVisitList.Contains(taskInfo.VisitTaskNum))).ToList();
}
else
{
qusetionList = qusetionList.Where(x => (x.LimitShow == LimitShow.AllShow || x.LimitShow == LimitShow.FollowShow) || (x.LimitShow == LimitShow.ExcludeSomeVisits && !x.ExcludeShowVisitList.Contains(taskInfo.VisitTaskNum))).ToList();
}
qusetionList.ForEach(x =>
{
x.CrterionDictionaryGroup = ReadingCommon.GetCrterionDictionaryGroup(taskInfo.IsConvertedTask);
});
}
else
{
qusetionList.ForEach(x =>
{
x.CrterionDictionaryGroup = new List<CrterionDictionaryGroup>() { CrterionDictionaryGroup.General, CrterionDictionaryGroup.BeforeConvert };
});
}
//是否是预览
if (inDto.IsGetPreview == false)
{
switch (criterionInfo.ReadingTool)
{
case ReadingTool.Dicom:
// 是否获取所有问题
if (inDto.IsGetallQuestion)
{
qusetionList = qusetionList.Where(x => x.IsShowInDicom).OrderBy(x => x.ShowOrder).ToList();
}
else
{
List<string> types = new List<string>()
{
ReadingQestionType.Table,
ReadingQestionType.BasicTable,
ReadingQestionType.Group,
};
qusetionList = qusetionList.Where(x => x.IsShowInDicom || types.Contains(x.Type)).OrderBy(x => x.ShowOrder).ToList();
if (inDto.TaskId != null)
{
if (taskInfo.IsConvertedTask)
{
qusetionList = qusetionList.Where(x => x.ConvertShowType == ConvertShowType.All || x.ConvertShowType == ConvertShowType.AfterShow).OrderBy(x => x.ShowOrder).ToList();
}
else
{
qusetionList = qusetionList.Where(x => x.ConvertShowType == ConvertShowType.All || x.ConvertShowType == ConvertShowType.BeforeShow).OrderBy(x => x.ShowOrder).ToList();
}
}
var usedGuropIds = qusetionList.Where(x => x.Type == ReadingQestionType.Table || x.Type == ReadingQestionType.BasicTable).Select(x => x.GroupId).ToList();
qusetionList = qusetionList.Where(x => usedGuropIds.Contains(x.Id) || usedGuropIds.Contains(x.GroupId)).ToList();
}
break;
case ReadingTool.NoDicom:
qusetionList = qusetionList.Where(x => x.IsShowInDicom).OrderBy(x => x.ShowOrder).ToList();
break;
}
}
var answers = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.TaskId).ToListAsync();
qusetionList.ForEach(x =>
{
var answer = answers.Where(y => y.ReadingQuestionTrialId == x.Id).Select(x => x.Answer).FirstOrDefault() ?? string.Empty;
x.Answer = answer.IsNullOrEmpty() ? x.DefaultValue : answer;
});
#endregion
var groupList = new List<TrialReadQuestionData>();
var qusetionIds = qusetionList.Select(x => x.Id).ToList();
var tableQuestionList = await _readingTableQuestionTrialRepository
.WhereIf(inDto.QuestionClassify != null, x => x.QuestionClassify == inDto.QuestionClassify)
.Where(x => qusetionIds.Contains(x.ReadingQuestionId))
.ProjectTo<TableQuestionTrial>(_mapper.ConfigurationProvider, new
{
isEn_Us = _userInfo.IsEn_Us
})
.OrderBy(x => x.ShowOrder).ToListAsync();
var result = new GetReadingTableQuestionOutDto();
List<ReadingTableQuestionAnswer> baseLineTableAnswer = new List<ReadingTableQuestionAnswer>();
List<ReadingTableQuestionAnswer> lastTaskTableAnswer = new List<ReadingTableQuestionAnswer>();
bool isFirstChangeTask = false;
if (inDto.TaskId != null)
{
taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.TaskId).ProjectTo<VisitTaskDto>(_mapper.ConfigurationProvider).FirstNotNullAsync();
// 取基线
var baseLineVisitId = await _subjectVisitRepository.Where(x => x.SubjectId == taskInfo.SubjectId && x.IsBaseLine).Select(x => x.Id).FirstNotNullAsync();
var baselineTaskId = await _visitTaskRepository.Where(x => x.SourceSubjectVisitId == baseLineVisitId
&& x.ArmEnum == taskInfo.ArmEnum
&& x.DoctorUserId == taskInfo.DoctorUserId
&& x.IsAnalysisCreate == taskInfo.IsAnalysisCreate
&& x.TaskState == TaskState.Effect
&& x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId
).Select(x => x.Id).FirstNotNullAsync();
baseLineTableAnswer = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == baselineTaskId).Include(x => x.ReadingTableQuestionTrial).ToListAsync();
var laskTaskId = await _visitTaskRepository.Where(x =>
(x.SubjectId == taskInfo.SubjectId && x.TaskState == TaskState.Effect
&& x.IsAnalysisCreate == taskInfo.IsAnalysisCreate
&& x.DoctorUserId == taskInfo.DoctorUserId
&& x.IsSelfAnalysis == taskInfo.IsSelfAnalysis
&& x.VisitTaskNum < taskInfo.VisitTaskNum
&& x.ArmEnum == taskInfo.ArmEnum
&& x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId
&& x.ReadingCategory == ReadingCategory.Visit) || x.Id == taskInfo.BeforeConvertedTaskId
).OrderByDescending(x => x.VisitTaskNum).Select(x => x.Id).FirstOrDefaultAsync();
if (criterionInfo.IsReadingTaskViewInOrder != ReadingOrder.InOrder)
{
// 无序的话 不要查
laskTaskId = Guid.NewGuid();
}
lastTaskTableAnswer = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == laskTaskId).Include(x=>x.ReadingQuestionTrial).Include(x => x.ReadingTableQuestionTrial).ToListAsync();
if (taskInfo.BeforeConvertedTaskId != null)
{
isFirstChangeTask = true;
}
}
if (criterionInfo.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 TrialReadQuestionData()
{
PageName = firstData!.PageName,
IsPage = true,
IsPublicPage = firstData.IsPublicPage,
};
var pageGroupList = newPageQusetionList.Where(x => x.Type == ReadingQestionType.Group).ToList();
pageGroupList.ForEach(x =>
{
FindChildQuestion(x, newPageQusetionList, tableQuestionList, inDto.TableAnswers, inDto.TableAnsweRowInfos, inDto.OrganInfos, baseLineTableAnswer, isFirstChangeTask, lastTaskTableAnswer, tableQuestionMarkList, inDto.TaskId);
});
page.Childrens = pageGroupList.Where(x => !(x.Type == ReadingQestionType.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 == ReadingQestionType.Group).ToList();
groupList.ForEach(x =>
{
FindChildQuestion(x, qusetionList, tableQuestionList, inDto.TableAnswers, inDto.TableAnsweRowInfos, inDto.OrganInfos, baseLineTableAnswer, isFirstChangeTask, lastTaskTableAnswer, tableQuestionMarkList, inDto.TaskId);
});
groupList = groupList.Where(x => !(x.Type == ReadingQestionType.Group && x.Childrens.Count == 0)).ToList();
result.SinglePage = groupList;
}
return result;
}
/// <summary>
/// 获取子元素
/// </summary>
/// <param name="item"></param>
/// <param name="questionlists"></param>
/// <param name="tableQuestionLists"></param>
/// <param name="tableAnswers"></param>
/// <param name="tableAnsweRowInfos"></param>
/// <param name="organInfos"></param>
/// <param name="baseLineTableAnswer"></param>
/// <param name="isFirstChangeTask"></param>
/// <param name="lastTaskTableAnswer"></param>
/// <param name="TaskId"></param>
private async void FindChildQuestion(TrialReadQuestionData item, List<TrialReadQuestionData> questionlists, List<TableQuestionTrial> tableQuestionLists, List<ReadingTableQuestionAnswerInfo> tableAnswers, List<TableAnsweRowInfo> tableAnsweRowInfos, List<OrganInfo> organInfos, List<ReadingTableQuestionAnswer> baseLineTableAnswer, bool isFirstChangeTask, List<ReadingTableQuestionAnswer> lastTaskTableAnswer, List<TableQuestionMark> TableQuestionMarkList, Guid? TaskId)
{
item.Childrens = questionlists.Where(x => x.ParentId == item.Id || (x.GroupId == item.Id && x.ParentId == null)).ToList();
item.TableQuestions = new TrialReadTableQuestion();
item.TableQuestions.Questions = tableQuestionLists.Where(x => x.ReadingQuestionId == item.Id).OrderBy(x => x.ShowOrder).ToList();
item.TableQuestions.Questions.ForEach(x =>
{
x.RelationQuestions = _mapper.Map<List<GetTrialReadingQuestionOutDto>>(tableQuestionLists.Where(z => (z.DependParentId ?? default(Guid)) == x.Id));
x.RelationQuestions.ForEach(y =>
{
y.Childrens = new List<GetTrialReadingQuestionOutDto>();
y.GroupName = string.Empty;
y.ImageCount = 0;
y.ParentId = item.Id;
y.LesionType = item.LesionType;
y.RelationQuestions = new List<GetTrialReadingQuestionOutDto>();
});
});
var thisAnswer = tableAnswers.Where(x => x.QuestionId == item.Id).ToList();
var orders = thisAnswer.Select(x => x.RowIndex).Distinct().OrderBy(x => x).ToList();
item.TableQuestions.Answers = new List<Dictionary<string, string>>();
var needChangeType = new List<QuestionMark?>() {
QuestionMark.Organ,
QuestionMark.Location,
QuestionMark.Part,
};
foreach (var x in orders)
{
Dictionary<string, string> answers = new Dictionary<string, string>();
var rowInfo = tableAnsweRowInfos.FirstOrDefault(y => y.RowIndex == x && y.QuestionId == item.Id);
if (rowInfo == null)
{
continue;
}
var rowAnswer = thisAnswer.Where(y => y.RowId == rowInfo.Id).OrderBy(y => y.ShowOrder).ToList();
var organInfo = organInfos.Where(x => x.Id == rowInfo.OrganInfoId).FirstOrDefault();
rowAnswer.ForEach(z =>
{
if (organInfo != null && needChangeType.Contains(z.QuestionMark))
{
if (_userInfo.IsEn_Us)
{
switch (z.QuestionMark)
{
case QuestionMark.Organ:
answers.Add(z.TableQuestionId.ToString(), organInfo.TULOCEN);
break;
case QuestionMark.Location:
if (organInfo.IsCanEditPosition)
{
answers.Add(z.TableQuestionId.ToString(), z.Answer);
}
else
{
answers.Add(z.TableQuestionId.ToString(), organInfo.TULATEN);
}
break;
case QuestionMark.Part:
answers.Add(z.TableQuestionId.ToString(), organInfo.PartEN);
break;
}
}
else
{
switch (z.QuestionMark)
{
case QuestionMark.Organ:
answers.Add(z.TableQuestionId.ToString(), organInfo.TULOC);
break;
case QuestionMark.Location:
if (organInfo.IsCanEditPosition)
{
answers.Add(z.TableQuestionId.ToString(), z.Answer);
}
else
{
answers.Add(z.TableQuestionId.ToString(), organInfo.TULAT);
}
break;
case QuestionMark.Part:
answers.Add(z.TableQuestionId.ToString(), organInfo.Part);
break;
}
}
}
else
{
answers.Add(z.TableQuestionId.ToString(), z.Answer);
}
});
answers.Add("LesionType", rowInfo.LesionType.GetEnumNullInt());
answers.Add("BlindName", rowInfo.BlindName);
answers.Add("IsFirstChangeTask", isFirstChangeTask.ToString());
answers.Add("FromMark", rowInfo.FromMark);
answers.Add("IsDicomReading", rowInfo.IsDicomReading.ToString());
answers.Add("MeasureData", rowInfo == null ? string.Empty : rowInfo.MeasureData);
answers.Add("OtherMeasureData", rowInfo == null || rowInfo.OtherMeasureData == null ? string.Empty : rowInfo.OtherMeasureData.ToString());
answers.Add("OtherStudyId", rowInfo == null || rowInfo.OtherStudyId == null ? string.Empty : rowInfo.OtherStudyId.ToString());
answers.Add("OtherSeriesId", rowInfo == null || rowInfo.OtherSeriesId == null ? string.Empty : rowInfo.OtherSeriesId.ToString());
answers.Add("OtherInstanceId", rowInfo == null || rowInfo.OtherInstanceId == null ? string.Empty : rowInfo.OtherInstanceId.ToString());
answers.Add("OtherPicturePath", rowInfo == null || rowInfo.OtherPicturePath == null ? string.Empty : rowInfo.OtherPicturePath.ToString());
answers.Add("OtherNumberOfFrames", rowInfo == null || rowInfo.OtherNumberOfFrames == null ? string.Empty : rowInfo.OtherNumberOfFrames.ToString());
answers.Add("OtherMarkTool", rowInfo == null || rowInfo.OtherMarkTool == null ? string.Empty : rowInfo.OtherMarkTool.ToString());
answers.Add("RowIndex", x.ToString());
JsonSerializerSettings settings = new JsonSerializerSettings
{
FloatParseHandling = FloatParseHandling.Double,
};
answers.Add("TableQuestionMarkList", rowInfo == null ? "[]" : JsonConvert.SerializeObject(TableQuestionMarkList.Where(x => x.RowId == rowInfo.Id).ToList(), settings));
answers.Add("RowId", rowInfo == null ? string.Empty : rowInfo.Id.ToString());
answers.Add("MarkTool", rowInfo.MarkTool);
answers.Add("StudyId", rowInfo.StudyId.ToString());
answers.Add("OrganInfoId", rowInfo.OrganInfoId.ToString());
answers.Add("IsFristAdd", (rowInfo.FristAddTaskId == TaskId).ToString());
answers.Add("IsCanEditPosition", rowInfo.IsCanEditPosition.ToString());
answers.Add("InstanceId", rowInfo == null ? string.Empty : rowInfo.InstanceId.ToString());
answers.Add("PTSeriesId", rowInfo == null ? string.Empty : rowInfo.PTSeriesId.ToString());
answers.Add("CTSeriesId", rowInfo == null ? string.Empty : rowInfo.CTSeriesId.ToString());
answers.Add("SeriesId", rowInfo == null ? string.Empty : rowInfo.SeriesId.ToString());
answers.Add("IsCurrentTaskAdd", rowInfo == null ? false.ToString() : rowInfo.IsCurrentTaskAdd.ToString());
answers.Add("SplitRowId", rowInfo == null ? string.Empty : rowInfo.SplitRowId==null?string.Empty: rowInfo.SplitRowId.ToString());
answers.Add("MergeRowId", rowInfo == null ? string.Empty : rowInfo.MergeRowId == null ? string.Empty : rowInfo.MergeRowId.ToString());
answers.Add("SplitOrMergeLesionName", rowInfo == null ? string.Empty : rowInfo.SplitName.IsNullOrEmpty() ? rowInfo.MergeName : rowInfo.SplitName);
answers.Add("SplitOrMergeType", rowInfo == null ? string.Empty : rowInfo.SplitOrMergeType == null ? string.Empty : ((int)rowInfo.SplitOrMergeType).ToString());
switch (item.CriterionType)
{
case CriterionType.PCWG3:
answers.Add("LastTaskState", lastTaskTableAnswer.Where(n => n.ReadingQuestionTrial.OrderMark == item.OrderMark && n.ReadingTableQuestionTrial.QuestionMark == QuestionMark.State && n.RowIndex == x).Select(n => n.Answer).FirstOrDefault() ?? string.Empty);
break;
default:
answers.Add("LastTaskState", lastTaskTableAnswer.Where(n => n.QuestionId == item.Id && n.ReadingTableQuestionTrial.QuestionMark == QuestionMark.State && n.RowIndex == x).Select(n => n.Answer).FirstOrDefault() ?? string.Empty);
break;
}
answers.Add("LastTaskMajorAxis", lastTaskTableAnswer.Where(n => n.QuestionId == item.Id && n.ReadingTableQuestionTrial.QuestionMark == QuestionMark.MajorAxis && n.RowIndex == x).Select(n => n.Answer).FirstOrDefault() ?? string.Empty);
answers.Add("LastTaskShortAxis", lastTaskTableAnswer.Where(n => n.QuestionId == item.Id && n.ReadingTableQuestionTrial.QuestionMark == QuestionMark.ShortAxis && n.RowIndex == x).Select(n => n.Answer).FirstOrDefault() ?? string.Empty);
answers.Add("BaseLineMajorAxis", baseLineTableAnswer.Where(n => n.QuestionId == item.Id && n.ReadingTableQuestionTrial.QuestionMark == QuestionMark.MajorAxis && n.RowIndex == x).Select(n => n.Answer).FirstOrDefault() ?? string.Empty);
answers.Add("BaseLineShortAxis", baseLineTableAnswer.Where(n => n.QuestionId == item.Id && n.ReadingTableQuestionTrial.QuestionMark == QuestionMark.ShortAxis && n.RowIndex == x).Select(n => n.Answer).FirstOrDefault() ?? string.Empty);
if (rowInfo.LesionType == LesionType.BaselineLesions)
{
answers.Add("BaseLineLesionNumber", baseLineTableAnswer.Where(n => n.ReadingTableQuestionTrial.QuestionMark == QuestionMark.LesionNumber && n.RowIndex == rowInfo.RowIndex).Select(x => x.Answer).FirstIsNullReturnEmpty());
}
item.TableQuestions.Answers.Add(answers);
};
if (item.Childrens != null && item.Childrens.Count != 0)
{
item.Childrens.ForEach(x =>
{
FindChildQuestion(x, questionlists, tableQuestionLists, tableAnswers, tableAnsweRowInfos, organInfos, baseLineTableAnswer, isFirstChangeTask, lastTaskTableAnswer, TableQuestionMarkList, TaskId);
});
}
}
#region 访视任务 - Dicom 阅片 表格问题 病灶的拆分与合并
/// <summary>
/// 拆分病灶 分裂病灶
/// </summary>
/// <returns></returns>
[HttpPost]
[TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task SplitLesion(SplitLesionInDto inDto)
{
await VerifyTaskIsSign(inDto.VisitTaskId);
await VerifyIsBaseLineTask(inDto.VisitTaskId);
var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Include(x => x.TrialReadingCriterion).FirstNotNullAsync();
var rowAnswer = await _readingTableAnswerRowInfoRepository.Where(x => x.Id == inDto.RowId).AsNoTracking().FirstNotNullAsync();
var tableAnswers = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.RowIndex == rowAnswer.RowIndex && x.QuestionId == inDto.QuestionId).Include(x => x.ReadingTableQuestionTrial).ProjectTo<TableQuestionAnswerInfo>(_mapper.ConfigurationProvider).ToListAsync();
var maxRowIndex = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.QuestionId == inDto.QuestionId && x.RowIndex < Math.Floor(rowAnswer.RowIndex + 1)).OrderByDescending(x => x.RowIndex).Select(x => x.RowIndex).FirstOrDefaultAsync();
var newRowIndex = maxRowIndex + (decimal)0.01;
rowAnswer.RowIndex = newRowIndex;
rowAnswer.MergeRowId = null;
rowAnswer.FristAddTaskId = inDto.VisitTaskId;
rowAnswer.SplitOrMergeType = SplitOrMergeType.Split;
rowAnswer.FromMark = string.Empty;
rowAnswer.ReportMark = string.Empty;
rowAnswer.SplitRowId = rowAnswer.Id;
rowAnswer.Id = NewId.NextGuid();
rowAnswer.InstanceId = null;
rowAnswer.SeriesId = null;
rowAnswer.IsCurrentTaskAdd = true;
rowAnswer.MeasureData = string.Empty;
rowAnswer.OtherMeasureData = null;
List<QuestionMark?> needSaveMark = new List<QuestionMark?>()
{
QuestionMark.Organ,
QuestionMark.Location,
QuestionMark.Part,
QuestionMark.IsLymph,
};
List<QuestionMark?> needSetNa = new List<QuestionMark?>() { };
switch (taskInfo.TrialReadingCriterion.CriterionType)
{
case CriterionType.Lugano2014:
case CriterionType.Lugano2014WithoutPET:
needSetNa = new List<QuestionMark?>()
{
QuestionMark.LowPPDAddPercent,
QuestionMark.NadirPPD,
/// <summary>
/// PPD最低点所在访视
/// </summary>
QuestionMark.LowPPDVisit ,
/// <summary>
/// PPD最低点LDi
/// </summary>
QuestionMark.LowPPDLDi,
/// <summary>
/// PPD最低点SDi
/// </summary>
QuestionMark.LowPPDSDi,
/// <summary>
/// 相比最低点PPD增加百分比
/// </summary>
QuestionMark.LowPPDAddPercent,
/// <summary>
/// 相比PPD最低点LDi增加值
/// </summary>
QuestionMark.LowPPDLDiAdded,
/// <summary>
/// 相比PPD最低点SDi增加值
/// </summary>
QuestionMark.LowPPDSDiAdded,
};
break;
case CriterionType.mRECISTHCC:
needSaveMark = new List<QuestionMark?>()
{
QuestionMark.Organ,
QuestionMark.Location,
QuestionMark.Part,
QuestionMark.IsLymph,
QuestionMark.TypicalIntrahepaticLesion,
};
break;
}
tableAnswers.ForEach(x =>
{
x.Id = NewId.NextGuid();
x.RowIndex = newRowIndex;
x.VisitTaskId = inDto.VisitTaskId;
x.RowId = rowAnswer.Id;
var answer = string.Empty;
if (needSaveMark.Contains(x.QuestionMark))
{
answer = x.Answer;
}
if (needSetNa.Contains(x.QuestionMark))
{
answer = "NA";
}
x.Answer = answer;
});
await _readingTableAnswerRowInfoRepository.AddAsync(rowAnswer);
await _readingTableQuestionAnswerRepository.AddRangeAsync(_mapper.Map<List<ReadingTableQuestionAnswer>>(tableAnswers));
await _readingTableAnswerRowInfoRepository.UpdatePartialFromQueryAsync(x => x.Id == inDto.RowId, x => new ReadingTableAnswerRowInfo()
{
SplitOrMergeType = SplitOrMergeType.SplitMain
});
await _readingTableAnswerRowInfoRepository.SaveChangesAsync();
}
/// <summary>
/// 合并病灶 融合
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> MergeLesion(MergeLesionInDto inDto)
{
await VerifyTaskIsSign(inDto.VisitTaskId);
await VerifyIsBaseLineTask(inDto.VisitTaskId);
var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Include(x => x.TrialReadingCriterion).FirstNotNullAsync();
var mergeRow = await _readingTableAnswerRowInfoRepository.Where(x => x.Id == inDto.MergeMainRowId).Include(x => x.ReadingQuestionTrial).FirstNotNullAsync();
var mark = mergeRow.ReadingQuestionTrial.OrderMark + mergeRow.RowIndex.GetLesionMark();
await _readingTableQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x => inDto.MergeRowIdList.Contains(x.RowId) && x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.State, x => new ReadingTableQuestionAnswer()
{
Answer = TargetState.Loss.GetEnumInt(),
});
var isLymph = ReadingYesOrNo.Yes.GetEnumInt();
foreach (var item in inDto.MergeRowIdList)
{
switch (taskinfo.TrialReadingCriterion.CriterionType)
{
case CriterionType.Lugano2014:
case CriterionType.Lugano2014WithoutPET:
await _readingTableQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x => x.RowId == item &&
(x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.MajorAxis || x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.ShortAxis), x => new ReadingTableQuestionAnswer()
{
Answer = "0",
});
break;
default:
//淋巴结的长短经 为0 非淋巴的 长径0 短径为空
if (await _readingTableQuestionAnswerRepository.AnyAsync(x => x.RowId == item && x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.IsLymph && x.Answer == isLymph))
{
await _readingTableQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x => x.RowId == item &&
(x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.MajorAxis || x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.ShortAxis), x => new ReadingTableQuestionAnswer()
{
Answer = "0",
});
}
else
{
await _readingTableQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x => x.RowId == item &&
x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.ShortAxis, x => new ReadingTableQuestionAnswer()
{
Answer = string.Empty,
});
await _readingTableQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x => x.RowId == item &&
x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.MajorAxis, x => new ReadingTableQuestionAnswer()
{
Answer = "0",
});
}
break;
}
}
await _readingTableAnswerRowInfoRepository.UpdatePartialFromQueryAsync(x => inDto.MergeRowIdList.Contains(x.Id), x => new ReadingTableAnswerRowInfo()
{
MergeRowId = inDto.MergeMainRowId,
SplitOrMergeType = SplitOrMergeType.Merge,
});
await _readingTableAnswerRowInfoRepository.BatchUpdateNoTrackingAsync(x=>x.Id== inDto.MergeMainRowId, x => new ReadingTableAnswerRowInfo()
{
SplitOrMergeType = SplitOrMergeType.MergeMain,
});
await _readingTableAnswerRowInfoRepository.SaveChangesAsync();
await _readingCalculateService.CalculateTask(new CalculateTaskInDto()
{
IsChangeOtherTask = false,
VisitTaskId = inDto.VisitTaskId,
ComputationTrigger = ComputationTrigger.MergeLesion,
});
// 保存完了计算疾病进展
switch (taskinfo.TrialReadingCriterion.CriterionType)
{
case CriterionType.Lugano2014:
await _luganoCalculateService.CalculateMergeTargetLesionStatus(new CalculateTargetLesionStatusInDto()
{
QuestionId = inDto.QuestionId,
VisitTaskId = inDto.VisitTaskId,
RowNumber = mergeRow.RowIndex,
});
break;
case CriterionType.Lugano2014WithoutPET:
await _LuganoWithoutPETCalculateService.CalculateMergeTargetLesionStatus(new CalculateTargetLesionStatusInDto()
{
QuestionId = inDto.QuestionId,
VisitTaskId = inDto.VisitTaskId,
RowNumber = mergeRow.RowIndex,
});
break;
}
return ResponseOutput.Ok();
}
/// <summary>
/// 获取可合并的病灶
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<List<GetCanMergeLesionOutDto>> GetCanMergeLesion(GetCanMergeLesionInDto inDto)
{
var rowinfo = await _readingTableAnswerRowInfoRepository.Where(x => x.Id == inDto.RowId).Include(x => x.ReadingQuestionTrial).FirstNotNullAsync();
var taskInfo = await _visitTaskRepository.Where(x => x.Id == rowinfo.VisitTaskId).Include(x => x.TrialReadingCriterion).FirstNotNullAsync();
// 需要排除的状态
var needFilterState = new List<string>();
var query = _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == rowinfo.VisitTaskId && x.QuestionId == rowinfo.QuestionId && x.Id != rowinfo.Id)
.Where(x => x.SplitOrMergeType != SplitOrMergeType.Split && x.SplitOrMergeType != SplitOrMergeType.SplitMain
&& x.SplitOrMergeType != SplitOrMergeType.Merge && x.SplitOrMergeType != SplitOrMergeType.MergeMain
&& x.SplitOrMergeType != SplitOrMergeType.Merged);
switch (taskInfo.TrialReadingCriterion.CriterionType)
{
case CriterionType.Lugano2014:
case CriterionType.Lugano2014WithoutPET:
// (无法评估 或者 状态为消失的非靶病灶) 并且不能是无法评估的病灶
query = query.Where(x =>
(x.MeasureData == string.Empty ||
(x.LesionAnswerList.Any(y => y.ReadingTableQuestionTrial.QuestionMark == QuestionMark.State && y.Answer == TargetState.Loss.GetEnumInt()) &&
x.LesionAnswerList.Any(y => y.ReadingTableQuestionTrial.QuestionMark == QuestionMark.IsLymph && y.Answer == ReadingYesOrNo.No.GetEnumInt())
)) && !x.LesionAnswerList.Any(y => y.ReadingTableQuestionTrial.QuestionMark == QuestionMark.State && y.Answer == TargetState.UnableEvaluate.GetEnumInt())
);
break;
default:
query = query.Where(x => !x.LesionAnswerList.Any(y => y.ReadingTableQuestionTrial.QuestionMark == QuestionMark.State&&y.Answer!=string.Empty));
break;
}
var result = await query
.Select(x => new GetCanMergeLesionOutDto()
{
RowId = x.Id,
RowIndex = x.RowIndex,
OrderMarkName = x.ReadingQuestionTrial.OrderMark + x.RowIndex.GetLesionMark(),
OrganInfoId = x.OrganInfoId
}).OrderBy(x => x.RowIndex).ToListAsync();
var organIds = result.Where(x => x.OrganInfoId != null).Select(x => x.OrganInfoId).Distinct().ToList();
var organList = await _organInfoRepository.Where(x => organIds.Contains(x.Id)).ToListAsync();
result.ForEach(x =>
{
if (_userInfo.IsEn_Us)
{
x.Part = organList.Where(y => y.Id == x.OrganInfoId).Select(y => y.PartEN).FirstIsNullReturnEmpty();
}
else
{
x.Part = organList.Where(y => y.Id == x.OrganInfoId).Select(y => y.Part).FirstIsNullReturnEmpty();
}
});
return result;
}
#endregion
#region 访视任务 - Dicom 阅片 提交、修改
/// <summary>
/// 保存影像质量
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
[TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task<IResponseOutput> SaveImageQuality(ChangeDicomReadingQuestionAnswerInDto inDto)
{
inDto.UpdateMark = true;
return await ChangeDicomReadingQuestionAnswer(inDto);
}
/// <summary>
/// 保存任务问题 带动态稽查参数
/// </summary>
/// <param name="inDto"></param>
/// <param name="param">请求类型</param>
/// <returns></returns>
[Route("/SaveTaskQuestion/{param}")]
[HttpPost]
public async Task<IResponseOutput> SaveTaskQuestion(ChangeDicomReadingQuestionAnswerInDto inDto, string param)
{
inDto.param= param;
List<MarkAuditInfo> markAuditInfos = new List<MarkAuditInfo>() {
// 自定义
new MarkAuditInfo (){Param="-10",IsGeneralMark=true },
// 保存脾尖
new MarkAuditInfo (){Param="4",IsGeneralMark=true },
// 保存脾底
new MarkAuditInfo (){Param="5",IsGeneralMark=true },
// 测量纵膈血池
new MarkAuditInfo (){Param="3",IsGeneralMark=false },
// 测量肝脏血池
new MarkAuditInfo (){Param="2",IsGeneralMark=false }
};
var markInfo= markAuditInfos.Where(x => x.Param == param).FirstOrDefault();
// 当 param == -10 时,为自定义标准 需要区分 绑定 更改 标记
if (markInfo!=null)
{
if (markInfo.IsGeneralMark)
{
// 自定义这边 移除标记 还是会传过来 不过 MeasureData 为空字符串
inDto.QuestionMarkInfoList = inDto.QuestionMarkInfoList.Where(x => x.MeasureData.IsNotNullOrEmpty()).ToList();
var questionMarkList = inDto.QuestionMarkInfoList.Select(x => x.QuestionId).ToList();
var existsMark = await _readingTaskQuestionMarkRepository.AnyAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.MeasureData != string.Empty && questionMarkList.Contains(x.QuestionId));
if (!existsMark && inDto.QuestionMarkInfoList.Count(x => x.MeasureData.IsNotNullOrEmpty()) > 0)
{
_userInfo.AuditIdentification = "AddMark";
}
else if (existsMark && inDto.QuestionMarkInfoList.Count(x => x.MeasureData.IsNotNullOrEmpty()) > 0)
{
_userInfo.AuditIdentification = "UpdateMark";
}
else
{
_userInfo.AuditIdentification = "DeleteMark";
}
}
else
{
inDto.QuestionMarkInfoList = inDto.QuestionMarkInfoList.Where(x => x.OtherMeasureData.IsNotNullOrEmpty()).ToList();
var questionMarkList = inDto.QuestionMarkInfoList.Select(x => x.QuestionId).ToList();
var existsMark = await _readingTaskQuestionMarkRepository.AnyAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.OtherMeasureData != string.Empty && questionMarkList.Contains(x.QuestionId));
if (!existsMark && inDto.QuestionMarkInfoList.Count(x => x.OtherMeasureData.IsNotNullOrEmpty()) > 0)
{
_userInfo.AuditIdentification = "AddMark";
}
else if (existsMark && inDto.QuestionMarkInfoList.Count(x => x.OtherMeasureData.IsNotNullOrEmpty()) > 0)
{
_userInfo.AuditIdentification = "UpdateMark";
}
else
{
_userInfo.AuditIdentification = "DeleteMark";
}
}
}
var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Include(x => x.TrialReadingCriterion).FirstNotNullAsync();
try
{
param = param == string.Empty ? "0" : param;
inDto.ComputationTrigger = (ComputationTrigger)int.Parse(param);
}
catch (Exception)
{
}
var result = await SaveImageQuality(inDto);
// 自动计算
await _readingCalculateService.CalculateTask(new CalculateTaskInDto()
{
IsChangeOtherTask = false,
VisitTaskId = inDto.VisitTaskId,
ComputationTrigger = inDto.ComputationTrigger,
});
return result;
}
///// <summary>
///// 保存ECRF
///// </summary>
///// <param name="inDto"></param>
///// <returns></returns>
//[HttpPost]
//public async Task<IResponseOutput> SaveImageQuality(ChangeDicomReadingQuestionAnswerInDto inDto)
//{
// return await ChangeDicomReadingQuestionAnswer(inDto);
//}
/// <summary>
/// 修改肿瘤学评估结果
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
[TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task<IResponseOutput> ChangeDicomReadingQuestionAnswer(ChangeDicomReadingQuestionAnswerInDto inDto)
{
await VerifyTaskIsSign(inDto.VisitTaskId);
var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Include(x=>x.TrialReadingCriterion).FirstNotNullAsync();
var tumorQuestionId = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == taskInfo.TrialReadingCriterionId && x.QuestionType == QuestionType.Tumor).Select(x => x.Id).FirstOrDefaultAsync();
var tumorAnswer = inDto.Answers.Where(x => x.Id == tumorQuestionId).FirstOrDefault();
if (tumorAnswer != null)
{
var isConvertedTask = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Select(x => x.IsConvertedTask).FirstOrDefaultAsync();
var reportVerify = await _readingCalculateService.GetReportVerify(new GetReportVerifyInDto()
{
BeforeConvertedTaskId = taskInfo.BeforeConvertedTaskId,
IsConvertTask = isConvertedTask,
VisitTaskId = inDto.VisitTaskId
});
if (tumorAnswer.Answer == reportVerify.TumorEvaluate)
{
await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => x.Id == inDto.VisitTaskId, x => new VisitTask()
{
IsChangeTumorEvaluate = false
});
}
else
{
await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => x.Id == inDto.VisitTaskId, x => new VisitTask()
{
IsChangeTumorEvaluate = true
});
}
}
var criterionId = taskInfo.TrialReadingCriterionId;
var questionIds = inDto.Answers.Select(x => x.Id).ToList();
await _readingTaskQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId && questionIds.Contains(x.ReadingQuestionTrialId));
var needAddAnswer = inDto.Answers.Select(x => new ReadingTaskQuestionAnswer()
{
Answer = x.Answer,
SubjectId = taskInfo.SubjectId,
ReadingQuestionCriterionTrialId = criterionId,
ReadingQuestionTrialId = x.Id,
TrialId = taskInfo.TrialId,
VisitTaskId = inDto.VisitTaskId,
}).ToList();
await _readingTaskQuestionAnswerRepository.AddRangeAsync(needAddAnswer);
if (inDto.UpdateMark)
{
var questionList = inDto.Answers.Select(x => x.Id as Guid?).ToList();
var questionMarkList = await _readingTaskQuestionMarkRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId&& questionList.Contains(x.QuestionId)).Select(x => new
{
x.QuestionId,
x.FristAddTaskId,
}).ToListAsync();
var markquestionId = inDto.QuestionMarkInfoList.Select(y => (Guid?)y.QuestionId).ToList();
List<Guid?> needDeleteMarkQuestonIds = inDto.Answers.Where(x => x.Answer == string.Empty).Select(x => (Guid?)x.Id).ToList();
var needDeleteMarkQuestionIds = questionList.Except(markquestionId).ToList();
switch (taskInfo.TrialReadingCriterion.CriterionType)
{
case CriterionType.SelfDefine:
// 先找到需要删除的
foreach (var item in needDeleteMarkQuestionIds)
{
// 对于要删除的标记不能删除 要与问题解绑
// 但是对于一个标记绑定多个问题的情况 相当于是要删除掉这条信息
var questionMark=await _readingTaskQuestionMarkRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.QuestionId == item).FirstOrDefaultAsync();
if (questionMark != null)
{
if (questionMark.MarkId == null)
{
await _readingTaskQuestionMarkRepository.DeleteAsync(questionMark);
}
else
{
if (await _readingTaskQuestionMarkRepository.AnyAsync(x => x.MarkId == questionMark.MarkId && x.Id != questionMark.Id))
{
await _readingTaskQuestionMarkRepository.DeleteAsync(questionMark);
}
else
{
await _readingTaskQuestionMarkRepository.UpdatePartialFromQueryAsync(x => x.Id == questionMark.Id, x => new ReadingTaskQuestionMark()
{
QuestionId = null,
});
}
}
}
}
// 新增或者修改的标记
var otherMark = inDto.QuestionMarkInfoList.Where(x => !needDeleteMarkQuestionIds.Contains(x.QuestionId)).Select(x => x.QuestionId).ToList();
await addOrEditmark(inDto.QuestionMarkInfoList.Where(x => otherMark.Contains(x.QuestionId)).ToList());
break;
case CriterionType.Lugano2014:
case CriterionType.Lugano2014WithoutPET:
// 先找到需要删除的
foreach (var item in needDeleteMarkQuestionIds)
{
// 对于要删除的标记不能删除 要与问题解绑
// 但是对于一个标记绑定多个问题的情况 相当于是要删除掉这条信息
var questionMark = await _readingTaskQuestionMarkRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.QuestionId == item).FirstOrDefaultAsync();
if (questionMark != null)
{
await _readingTaskQuestionMarkRepository.DeleteAsync(questionMark);
}
}
await addOrEditmark(inDto.QuestionMarkInfoList);
break;
default:
await addOrEditmark(inDto.QuestionMarkInfoList);
break;
}
async Task addOrEditmark(List<QuestionMarkInfo> addOrUpdatemarkList)
{
#region 老的代码
//var markids = addOrUpdatemarkList.Select(x => x.MarkId).Where(x => x != null).Distinct().ToList();
//var markQuestionIds = addOrUpdatemarkList.Select(y => (Guid?)y.QuestionId).ToList();
//// 绑定的历史标记的话 相当于要把历史标记改为现在的标记 先删再添加 得到的结果一样
//await _readingTaskQuestionMarkRepository.BatchDeleteNoTrackingAsync(x => markids.Contains(x.MarkId) && x.QuestionId == null);
//// 这里还不能直接删除 因为可能该问题绑定的原标记为a 现在新绑定的标记要为b 那么就需要把原标记a的绑定关系删除
//var oldMark = await _readingTaskQuestionMarkRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && markQuestionIds.Contains(x.QuestionId) && x.MarkId != null).ToListAsync();
//// 这里稽查又要记录为新增 只能把原标记记录为先删除再添加 不然稽查又对不上
//List<ReadingTaskQuestionMark> oldAddMark = new List<ReadingTaskQuestionMark>();
//foreach (var item in oldMark)
//{
// if (addOrUpdatemarkList.Any(x => x.QuestionId == item.QuestionId && x.MarkId != item.MarkId))
// {
// var olditem = item.Clone();
// olditem.QuestionId = null;
// olditem.TableQuestionId = null;
// olditem.RowId = null;
// olditem.RowIndex = null;
// oldAddMark.Add(olditem);
// }
//}
//await _readingTaskQuestionMarkRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId && markQuestionIds.Contains(x.QuestionId));
//var datetime = DateTime.Now;
//var markList = _mapper.Map<List<QuestionMarkInfo>, List<ReadingTaskQuestionMark>>(addOrUpdatemarkList);
//markList.ForEach(x =>
//{
// x.Id = NewId.NextGuid();
// x.VisitTaskId = inDto.VisitTaskId;
// x.CreateTime = datetime;
// x.FristAddTaskId = questionMarkList.Where(y => y.QuestionId == x.QuestionId).Select(x => x.FristAddTaskId).FirstOrDefault() ?? inDto.VisitTaskId;
//});
//// 原来移除关系的 已经删除 这里要添加 为什么要先删再加 因为稽查需要记录 稽查的记录方式为Add
//oldAddMark.AddRange(markList);
//await _readingTaskQuestionMarkRepository.AddRangeAsync(oldAddMark);
#endregion
foreach (var item in addOrUpdatemarkList)
{
var oldMark = await _readingTaskQuestionMarkRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.QuestionId == item.QuestionId).FirstOrDefaultAsync();
if (oldMark != null)
{
// 这种情况要先移除原来标记的绑定关系
if (oldMark.MarkId != item.MarkId)
{
await _readingTaskQuestionMarkRepository.UpdatePartialFromQueryAsync(x => x.Id == oldMark.Id, x => new ReadingTaskQuestionMark()
{
QuestionId = null,
TableQuestionId = null,
RowId = null,
RowIndex = null,
});
var newMark = _mapper.Map<QuestionMarkInfo, ReadingTaskQuestionMark>(item);
newMark.Id = NewId.NextGuid();
newMark.VisitTaskId = inDto.VisitTaskId;
newMark.FristAddTaskId = inDto.VisitTaskId;
await _readingTaskQuestionMarkRepository.AddAsync(newMark);
}
else
{
// 这种情况直接更新
await _readingTaskQuestionMarkRepository.UpdatePartialFromQueryAsync(x => x.Id == oldMark.Id, x => new ReadingTaskQuestionMark()
{
MeasureData = item.MeasureData ?? string.Empty,
OtherMeasureData = item.OtherMeasureData ?? string.Empty,
PicturePath = item.PicturePath ?? string.Empty,
OtherPicturePath = item.OtherPicturePath ?? string.Empty,
MarkTool = item.MarkTool ?? string.Empty,
});
}
}
else
{
// 这种情况可能是绑定历史的标记
if (item.MarkId != null && (await _readingTaskQuestionMarkRepository.AnyAsync(x => x.VisitTaskId == inDto.VisitTaskId&& x.QuestionId == null && x.MarkId == item.MarkId)))
{
var oldMarkItem = await _readingTaskQuestionMarkRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.MarkId == item.MarkId && x.QuestionId == null).FirstOrDefaultAsync();
await _readingTaskQuestionMarkRepository.UpdatePartialFromQueryAsync(x => x.Id == oldMarkItem.Id, x => new ReadingTaskQuestionMark()
{
QuestionId = item.QuestionId,
TableQuestionId = item.TableQuestionId,
RowId = item.RowId,
MeasureData = item.MeasureData ?? string.Empty,
OtherMeasureData = item.OtherMeasureData ?? string.Empty,
PicturePath = item.PicturePath ?? string.Empty,
OtherPicturePath = item.OtherPicturePath ?? string.Empty,
MarkTool = item.MarkTool ?? string.Empty,
});
}
else
{
var newMark = _mapper.Map<QuestionMarkInfo, ReadingTaskQuestionMark>(item);
newMark.Id = NewId.NextGuid();
newMark.VisitTaskId = inDto.VisitTaskId;
newMark.FristAddTaskId = inDto.VisitTaskId;
await _readingTaskQuestionMarkRepository.AddAsync(newMark);
}
}
}
}
}
await _readingTaskQuestionAnswerRepository.SaveChangesAsync();
return ResponseOutput.Ok(true);
}
/// <summary>
/// 删除表格行数据
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
[TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task<IResponseOutput> DeleteReadingRowAnswer(DeleteReadingRowAnswerInDto inDto)
{
await VerifyTaskIsSign(inDto.VisitTaskId);
var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Include(x => x.TrialReadingCriterion).FirstNotNullAsync();
var deleteRowInfo = await _readingTableAnswerRowInfoRepository.Where(x => x.Id == inDto.RowId).FirstOrDefaultAsync();
if (deleteRowInfo == null)
{
return ResponseOutput.Ok(true);
}
inDto.QuestionId = deleteRowInfo.QuestionId;
if (await _readingTableAnswerRowInfoRepository.AnyAsync(x => x.SplitRowId == deleteRowInfo.Id && x.MergeRowId == deleteRowInfo.Id))
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_DeleteError"]);
}
var index = await _readingCalculateService.GetDeleteLesionStatrIndex(inDto);
await _readingTableQuestionAnswerRepository.UpdatePartialFromQueryAsync(x => x.RowId == inDto.RowId, x => new ReadingTableQuestionAnswer()
{
IsDeleted = true
});
if (!(await _readingTableAnswerRowInfoRepository.AnyAsync(x => x.SplitRowId == deleteRowInfo.SplitRowId && x.Id != deleteRowInfo.Id)))
{
await _readingTableAnswerRowInfoRepository.BatchUpdateNoTrackingAsync(x => x.Id == deleteRowInfo.SplitRowId, x => new ReadingTableAnswerRowInfo()
{
SplitOrMergeType = null,
});
}
await _readingTableAnswerRowInfoRepository.UpdatePartialFromQueryAsync(x => x.Id == inDto.RowId, x => new ReadingTableAnswerRowInfo()
{
IsDeleted = true
});
await _readingTableAnswerRowInfoRepository.SaveChangesAsync();
if (inDto.IsNeedSort)
{
var rowInfoList = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.QuestionId == inDto.QuestionId, true).Include(x => x.ReadingQuestionTrial).OrderBy(x => x.RowIndex).ToListAsync();
var answerlist = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.QuestionId == inDto.QuestionId, true).ToListAsync();
foreach (var item in rowInfoList.Where(x => x.RowIndex % 1 == 0))
{
string measureDataStr = string.Empty;
if (item.MeasureData != null && item.MeasureData != string.Empty)
{
dynamic measureData = JObject.Parse(item.MeasureData);
measureData.data.remark = item.ReadingQuestionTrial.OrderMark + ((decimal)index).GetLesionMark();
measureDataStr = JsonConvert.SerializeObject(measureData);
}
string? otherMeasureDataStr = null;
if (item.OtherMeasureData != null && item.OtherMeasureData != string.Empty)
{
dynamic otherMeasureData = JObject.Parse(item.OtherMeasureData);
otherMeasureData.data.remark = item.ReadingQuestionTrial.OrderMark + ((decimal)index).GetLesionMark();
otherMeasureDataStr = JsonConvert.SerializeObject(otherMeasureData);
}
foreach (var answerItem in answerlist.Where(x => x.RowIndex == item.RowIndex))
{
answerItem.RowIndex = index;
}
foreach (var rowAnswerItem in rowInfoList.Where(x => x.RowIndex == item.RowIndex))
{
rowAnswerItem.RowIndex = index;
rowAnswerItem.MeasureData = measureDataStr;
rowAnswerItem.OtherMeasureData = otherMeasureDataStr;
}
//await _readingTableQuestionAnswerRepository.UpdatePartialFromQueryAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.RowIndex == item.RowIndex && x.QuestionId == inDto.QuestionId, x => new ReadingTableQuestionAnswer()
//{
// RowIndex = index
//});
//await _readingTableAnswerRowInfoRepository.UpdatePartialFromQueryAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.RowIndex == item.RowIndex && x.QuestionId == inDto.QuestionId, x => new ReadingTableAnswerRowInfo()
//{
// RowIndex = index,
// MeasureData = measureDataStr,
//});
var spiltList = rowInfoList.Where(x => x.RowIndex % 1 != 0 && x.RowIndex > item.RowIndex && x.RowIndex < Math.Floor(item.RowIndex + 1)).OrderBy(x => x.RowIndex).ToList();
decimal spiltindex = 0.01M;
foreach (var spiltitem in spiltList)
{
string spiltmeasureDataStr = string.Empty;
if (spiltitem.MeasureData != null && spiltitem.MeasureData != string.Empty)
{
dynamic spiltmeasureData = JObject.Parse(spiltitem.MeasureData);
spiltmeasureData.data.remark = item.ReadingQuestionTrial.OrderMark + ((decimal)index + spiltindex).GetLesionMark();
spiltmeasureDataStr = JsonConvert.SerializeObject(spiltmeasureData);
}
string? spiltOtherMeasureDataStr = null;
if (item.OtherMeasureData != null && item.OtherMeasureData != string.Empty)
{
dynamic otherMeasureData = JObject.Parse(item.OtherMeasureData);
otherMeasureData.data.remark = item.ReadingQuestionTrial.OrderMark + ((decimal)index).GetLesionMark();
spiltOtherMeasureDataStr = JsonConvert.SerializeObject(otherMeasureData);
}
foreach (var answerItem in answerlist.Where(x => x.RowIndex == spiltitem.RowIndex))
{
answerItem.RowIndex = index + spiltindex;
}
foreach (var rowAnswerItem in rowInfoList.Where(x => x.RowIndex == spiltitem.RowIndex))
{
rowAnswerItem.RowIndex = index + spiltindex;
rowAnswerItem.MeasureData = spiltmeasureDataStr;
rowAnswerItem.OtherMeasureData = spiltOtherMeasureDataStr;
}
//await _readingTableQuestionAnswerRepository.UpdatePartialFromQueryAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.RowIndex == spiltitem.RowIndex && x.QuestionId == inDto.QuestionId, x => new ReadingTableQuestionAnswer()
//{
// RowIndex = index + spiltindex
//});
//await _readingTableAnswerRowInfoRepository.UpdatePartialFromQueryAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.RowIndex == spiltitem.RowIndex && x.QuestionId == inDto.QuestionId, x => new ReadingTableAnswerRowInfo()
//{
// RowIndex = index + spiltindex,
// MeasureData = spiltmeasureDataStr,
//});
spiltindex += 0.01M;
}
index++;
}
await _readingTableAnswerRowInfoRepository.SaveChangesAsync();
}
// 自动计算
await _readingCalculateService.CalculateTask(new CalculateTaskInDto()
{
IsChangeOtherTask = false,
VisitTaskId = inDto.VisitTaskId,
ComputationTrigger = ComputationTrigger.RemoveLesion,
});
switch (taskinfo.TrialReadingCriterion.CriterionType)
{
case CriterionType.Lugano2014:
if (deleteRowInfo.RowIndex % 1 != 0)
{
await _luganoCalculateService.CalculateTargetLesionStatus(new CalculateTargetLesionStatusInDto()
{
QuestionId = inDto.QuestionId,
VisitTaskId = inDto.VisitTaskId,
RowNumber = deleteRowInfo.RowIndex
});
}
break;
case CriterionType.Lugano2014WithoutPET:
if (deleteRowInfo.RowIndex % 1 != 0)
{
await _LuganoWithoutPETCalculateService.CalculateTargetLesionStatus(new CalculateTargetLesionStatusInDto()
{
QuestionId = inDto.QuestionId,
VisitTaskId = inDto.VisitTaskId,
RowNumber = deleteRowInfo.RowIndex
});
}
break;
}
return ResponseOutput.Ok(true);
}
/// <summary>
/// 提交表格行信息
/// </summary>
/// <param name="inDto"></param>
/// <param name="param"></param>
/// <returns></returns>
[HttpPost]
[Route("/SubmitTaskRowInfo/{param}")]
public async Task<SubmitTableQuestionOutDto> SubmitTaskRowInfo(SubmitTableQuestionInDto inDto, string param)
{
inDto.ComputationTrigger = (ComputationTrigger)int.Parse(param);
return await SubmitTableQuestion(inDto);
}
/// <summary>
/// 提交表格问题答案 提交病灶 保存病灶
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
[TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task<SubmitTableQuestionOutDto> SubmitTableQuestion(SubmitTableQuestionInDto inDto)
{
SubmitTableQuestionOutDto result = new SubmitTableQuestionOutDto();
await VerifyTaskIsSign(inDto.VisitTaskId);
if (inDto.InstanceId != null && inDto.IsDicomReading)
{
if ((!(await _dicomInstanceRepository.AnyAsync(x => x.Id == inDto.InstanceId && x.SeriesId == inDto.SeriesId))) && (!(await _taskInstanceRepository.AnyAsync(x => x.Id == inDto.InstanceId && x.SeriesId == inDto.SeriesId))))
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_Idnotcorrespond"]);
}
}
var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Include(x => x.TrialReadingCriterion).Include(x => x.SourceSubjectVisit).FirstNotNullAsync();
inDto.BlindName = taskinfo.TaskBlindName;
var questionInfo = await _readingQuestionTrialRepository.Where(x => x.Id == inDto.QuestionId).FirstNotNullAsync();
switch (taskinfo.TrialReadingCriterion.CriterionType)
{
// 对于非靶病灶,如果状态选择为显著增大,请验证:
// 1) 对于非淋巴结病灶,验证当前访视该病灶的长径 > 上一访视该病灶的长径。
// 约束条件:两次访视该病灶的长径有测量值。
// 提示语:当前访视该非淋巴结病灶的长径小于上一访视的值,不能设置为显著增大。
// 2) 对于淋巴结病灶,验证当前访视该病灶的短径 > 上一访视该病灶的短径。
// 约束条件:两次访视该病灶的短径有测量值。
// 提示语:当前访视该淋巴结病灶的短径小于上一访视的值,不能设置为显著增大。
case CriterionType.RECIST1Point1:
var lastTaskinfo = await _visitTaskRepository
.Where(x => x.IsAnalysisCreate == taskinfo.IsAnalysisCreate &&
x.SubjectId == taskinfo.SubjectId &&
x.ReadingCategory == taskinfo.ReadingCategory &&
x.DoctorUserId == taskinfo.DoctorUserId &&
x.ArmEnum == taskinfo.ArmEnum &&
x.TrialReadingCriterionId == taskinfo.TrialReadingCriterionId &&
x.ReadingTaskState == ReadingTaskState.HaveSigned &&
x.TaskState == TaskState.Effect &&
x.IsSelfAnalysis == taskinfo.IsSelfAnalysis &&
x.VisitTaskNum < taskinfo.VisitTaskNum
).OrderByDescending(x => x.VisitTaskNum).FirstOrDefaultAsync();
if (lastTaskinfo != null)
{
var tablequestionList = await _readingTableQuestionTrialRepository.Where(x => x.TrialCriterionId == taskinfo.TrialReadingCriterionId && x.ReadingQuestionTrial.LesionType == LesionType.NonTargetLesions).ToListAsync();
// 判断表格问题是否为空
if (tablequestionList.Count > 0)
{
// 找到状态值
var stateQuestion = tablequestionList.Where(x => x.QuestionMark == QuestionMark.State).FirstOrDefault();
if (stateQuestion != null)
{
// 判断是否为非靶病灶
if (inDto.QuestionId == tablequestionList[0].ReadingQuestionId && inDto.AnswerList.Any(x => x.TableQuestionId == stateQuestion.Id && x.Answer.EqEnum(NoTargetState.Increase)))
{
var lymphQuestion = tablequestionList.Where(x => x.QuestionMark == QuestionMark.IsLymph).FirstOrDefault();
if (lymphQuestion != null)
{
// 判断是否是淋巴结
if (inDto.AnswerList.Any(x => x.TableQuestionId == lymphQuestion.Id && x.Answer.EqEnum(YesOrNoOrNa.Yes)))
{
var shortAxisQuestion = tablequestionList.Where(x => x.QuestionMark == QuestionMark.ShortAxis).FirstOrDefault();
if (shortAxisQuestion != null)
{
var lastAnswer = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == lastTaskinfo.Id && x.TableQuestionId == shortAxisQuestion.Id
&& x.RowIndex == inDto.RowIndex
).Select(x => x.Answer).FirstOrDefaultAsync();
var thisAnswer = inDto.AnswerList.Where(x => x.TableQuestionId == shortAxisQuestion.Id).Select(x => x.Answer).FirstOrDefault();
if (!lastAnswer.IsNullOrEmpty() && !thisAnswer.IsNullOrEmpty())
{
var lastvalue = 0m;
var thisvalue = 0m;
try
{
lastvalue = decimal.Parse(lastAnswer);
thisvalue = decimal.Parse(thisAnswer);
}
catch (Exception)
{
}
if (lastvalue >= thisvalue)
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_IsLymphNotbigger"]);
}
}
}
}
else
{
var majorAxisQuestion = tablequestionList.Where(x => x.QuestionMark == QuestionMark.MajorAxis).FirstOrDefault();
if (majorAxisQuestion != null)
{
var lastAnswer = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == lastTaskinfo.Id && x.TableQuestionId == majorAxisQuestion.Id
&& x.RowIndex == inDto.RowIndex
).Select(x => x.Answer).FirstOrDefaultAsync();
var thisAnswer = inDto.AnswerList.Where(x => x.TableQuestionId == majorAxisQuestion.Id).Select(x => x.Answer).FirstOrDefault();
if (!lastAnswer.IsNullOrEmpty() && !thisAnswer.IsNullOrEmpty())
{
var lastvalue = 0m;
var thisvalue = 0m;
try
{
lastvalue = decimal.Parse(lastAnswer);
thisvalue = decimal.Parse(thisAnswer);
}
catch (Exception)
{
}
if (lastvalue >= thisvalue)
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_NotLymphNotbigger"]);
}
}
}
}
}
}
}
}
}
break;
case CriterionType.Lugano2014:
case CriterionType.Lugano2014WithoutPET:
var targetTablequestionList = await _readingTableQuestionTrialRepository.Where(x => x.TrialCriterionId == taskinfo.TrialReadingCriterionId && x.ReadingQuestionTrial.LesionType == LesionType.TargetLesion).ToListAsync();
var targetlymphQuestion = targetTablequestionList.Where(x => x.QuestionMark == QuestionMark.IsLymph).FirstOrDefault();
// 判断是否存在淋巴结问题
if (targetlymphQuestion != null && taskinfo.SourceSubjectVisit.VisitNum == 0)
{
// 判断是否为淋巴结
if (inDto.QuestionId == targetTablequestionList[0].ReadingQuestionId && inDto.AnswerList.Any(x => x.TableQuestionId == targetlymphQuestion.Id && x.Answer.EqEnum(ReadingYesOrNo.No)))
{
if (await _readingTableQuestionAnswerRepository.CountAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.TableQuestionId == targetlymphQuestion.Id && x.Answer == ReadingYesOrNo.No.GetEnumInt() && x.RowId != inDto.RowId) >= 2)
{
// 靶病灶只能添加两个非淋巴结病灶
throw new BusinessValidationFailedException(_localizer["ReadingImage_LuganoMaxTowNoTarget"]);
}
}
}
break;
case CriterionType.mRECISTHCC:
//var orginInfo=await _organTrialInfoRepository.Where(x =>x.TrialCriterionId== taskinfo.TrialReadingCriterionId&& x.OrganInfoId == inDto.OrganInfoId).FirstOrDefaultAsync();
//if (orginInfo != null && orginInfo.TULOCEN == "Liver")
//{
// var otherorganCount=await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.QuestionId == inDto.QuestionId && x.Id!=inDto.Id&&x.OrganInfo.TULOCEN == "Liver").CountAsync();
// if (otherorganCount >=2)
// {
// throw new BusinessValidationFailedException(_localizer["ReadingImageTask_HCCOrganRepeat"]);
// }
//}
// 如果当前添加 是 非靶病灶 并且 典型肝内病灶为 是 时 如果 靶病灶的典型肝内病灶 为是的 数量<2 给提示
// 验证去掉
//if (questionInfo.LesionType == LesionType.NonTargetLesions)
//{
// // 非靶病灶
// var tablequestionList = await _readingTableQuestionTrialRepository.Where(x => x.TrialCriterionId == taskinfo.TrialReadingCriterionId && x.ReadingQuestionId == inDto.QuestionId).ToListAsync();
// // 判断表格问题是否为空
// var tableQuestion = tablequestionList.Where(x => x.QuestionMark == QuestionMark.TypicalIntrahepaticLesion).FirstOrDefault();
// if (tableQuestion != null)
// {
// if (inDto.AnswerList.Where(x => x.TableQuestionId == tableQuestion.Id).Select(x => x.Answer).FirstOrDefault().EqEnum(ReadingYesOrNo.Yes))
// {
// var yesString = ((int)(object)ReadingYesOrNo.Yes).ToString();
// var targetList = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.ReadingQuestionTrial.LesionType == LesionType.TargetLesion
// && x.LesionAnswerList.Any(y => y.Answer == yesString && y.ReadingTableQuestionTrial.QuestionMark == QuestionMark.TypicalIntrahepaticLesion)
// ).ToListAsync();
// if (targetList.Count() < 2)
// {
// throw new BusinessValidationFailedException(_localizer["ReadingImageTask_PriorityTarget"]);
// }
// }
// }
//}
break;
}
var criterionId = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Select(x => x.TrialReadingCriterionId).FirstOrDefaultAsync();
var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == criterionId).FirstNotNullAsync();
var tableQuestionIds = inDto.AnswerList.Select(x => x.TableQuestionId).ToList();
var tableAnswerList = await _readingTableQuestionAnswerRepository.Where(x => x.RowId == inDto.RowId).ToListAsync();
var tableQuestionIdGroup = tableQuestionIds.GroupBy(x => new { TableQuestionId = x }).Select(x => new TableQuestionData
{
TableQuestionId = x.Key.TableQuestionId,
Count = x.Count()
}).ToList();
if (tableQuestionIdGroup.Any(x => x.Count > 1))
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_Twice"]);
}
if (inDto.RowIndex % 1 == 0)
{
if (questionInfo.MaxQuestionCount != null && questionInfo.MaxQuestionCount != 0 && inDto.RowId == null)
{
if (questionInfo.MaxQuestionCount <
(
(await _readingTableAnswerRowInfoRepository.Where(x => ((x.RowIndex % 1) == 0) && x.VisitTaskId == inDto.VisitTaskId
&& x.QuestionId == inDto.QuestionId
).CountAsync()) + 1))
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_MaxQuestion", _userInfo.IsEn_Us ? questionInfo.QuestionEnName : questionInfo.QuestionName, questionInfo.MaxQuestionCount]);
}
}
var tableQuestions = await _readingTableQuestionTrialRepository.Where(x => tableQuestionIds.Contains(x.Id) && x.MaxRowCount != null && x.MaxRowCount != 0).ToListAsync();
List<QuestionMark?> questionMarks = new List<QuestionMark?>()
{
QuestionMark.Part,
QuestionMark.Organ,
};
string msg = string.Empty;
foreach (var item in tableQuestions)
{
var answer = inDto.AnswerList.Where(x => x.TableQuestionId == item.Id).Select(x => x.Answer).FirstOrDefault();
if (!answer.IsNullOrEmpty())
{
Dictionary<CriterionType, string> errorMsgDic = new Dictionary<CriterionType, string>()
{
{CriterionType.RECIST1Point1, _localizer["ReadingImage_Maxlesion", item.MaxRowCount!.Value]},
{CriterionType.PCWG3, _localizer["ReadingImage_PCWGMaximum", item.MaxRowCount.Value]},
};
var rowCount = 0;
if ((item.QuestionMark == QuestionMark.Part || item.QuestionMark == QuestionMark.Organ) && inDto.OrganInfoId != null)
{
var organIds = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.QuestionId == inDto.QuestionId && ((x.RowIndex % 1) == 0) && x.OrganInfoId != null && x.RowIndex != inDto.RowIndex).Select(x => x.OrganInfoId).ToListAsync();
organIds.Add(inDto.OrganInfoId);
var orginInfos = await _organInfoRepository.Where(x => organIds.Contains(x.Id)).ToListAsync();
List<OrganInfo?> orginInfoList = new List<OrganInfo?>();
foreach (var organId in organIds)
{
orginInfoList.Add(orginInfos.Where(x => x.Id == organId).FirstOrDefault());
}
var currentOrginInfo = orginInfos.Where(x => x.Id == inDto.OrganInfoId).FirstOrDefault() ?? new OrganInfo();
if (item.QuestionMark == QuestionMark.Part)
{
rowCount = orginInfoList.Where(x => x.Part == currentOrginInfo.Part).Count();
}
else
{
rowCount = orginInfoList.Where(x => x.TULOC == currentOrginInfo.TULOC).Count();
}
if (rowCount > item.MaxRowCount.Value)
{
if (rowCount > item.MaxRowCount.Value)
{
try
{
msg = errorMsgDic[criterionInfo.CriterionType];
}
catch (Exception)
{
msg = _localizer["ReadingImage_Maximum", item.QuestionName.LanguageName(item.QuestionEnName, _userInfo.IsEn_Us), item.MaxRowCount.Value, item.MaxRowCount.Value];
}
throw new BusinessValidationFailedException(msg);
}
}
}
else
{
rowCount = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.TableQuestionId == item.Id && ((x.RowIndex % 1) == 0) && x.Answer == answer && x.RowIndex != inDto.RowIndex).CountAsync();
if (rowCount > item.MaxRowCount.Value - 1)
{
try
{
msg = errorMsgDic[criterionInfo.CriterionType];
}
catch (Exception)
{
msg = _localizer["ReadingImage_Maximum", item.QuestionName.LanguageName(item.QuestionEnName, _userInfo.IsEn_Us), item.MaxRowCount.Value, rowCount];
}
throw new BusinessValidationFailedException(msg);
}
}
}
}
}
var isCurrentTaskAddList = await _readingTableAnswerRowInfoRepository.Where(x => x.Id == (inDto.RowId ?? default(Guid))).Select(x => x.IsCurrentTaskAdd).ToListAsync();
bool isCurrentTaskAdd = true;
if (isCurrentTaskAddList.Count > 0)
{
isCurrentTaskAdd = isCurrentTaskAddList[0];
}
ReadingTableAnswerRowInfo? rowInfo = await _readingTableAnswerRowInfoRepository.Where(x => x.Id == (inDto.RowId ?? default(Guid))).IgnoreAutoIncludes().FirstOrDefaultAsync();
rowInfo = rowInfo == null ? new ReadingTableAnswerRowInfo() : rowInfo;
//await _readingTableQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => x.RowId == (inDto.RowId ?? default(Guid)));
//await _readingTableAnswerRowInfoRepository.BatchDeleteNoTrackingAsync(x => x.Id == (inDto.RowId ?? default(Guid)));
_mapper.Map(inDto, rowInfo);
rowInfo.IdentityRowId = rowInfo.IdentityRowId == null ? NewId.NextGuid() : rowInfo.IdentityRowId;
rowInfo.Id = inDto.RowId == null ? NewId.NextGuid() : inDto.RowId.Value;
result.RowId = rowInfo.Id;
rowInfo.IsCurrentTaskAdd = isCurrentTaskAdd;
rowInfo.FristAddTaskId = inDto.RowId == null ? inDto.VisitTaskId : rowInfo.FristAddTaskId;
if (inDto.RowId == null)
{
rowInfo.FromMark = inDto.FromMark ?? string.Empty;
rowInfo.ReportMark = inDto.ReportMark ?? string.Empty;
rowInfo.MarkTool = inDto.MarkTool ?? string.Empty;
rowInfo.PicturePath = inDto.PicturePath ?? string.Empty;
rowInfo.MeasureData = inDto.MeasureData ?? string.Empty;
//await _readingTableAnswerRowInfoRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.RowIndex == inDto.RowIndex && x.QuestionId == inDto.QuestionId);
List<ReadingTableQuestionAnswer> answerList = inDto.AnswerList.Select(x => new ReadingTableQuestionAnswer()
{
Answer = x.Answer,
Id = NewId.NextGuid(),
TrialId = inDto.TrialId,
QuestionId = inDto.QuestionId,
TableQuestionId = x.TableQuestionId,
RowIndex = inDto.RowIndex,
RowId = rowInfo.Id,
VisitTaskId = inDto.VisitTaskId
}).ToList();
await _readingTableAnswerRowInfoRepository.AddAsync(rowInfo);
await _readingTableQuestionAnswerRepository.AddRangeAsync(answerList);
}
else
{
inDto.UpdateTime = DateTime.Now;
await _readingTableAnswerRowInfoRepository.UpdateFromDTOAsync(inDto);
foreach (var item in inDto.AnswerList)
{
if (tableAnswerList.Any(x => x.TableQuestionId == item.TableQuestionId))
{
await _readingTableQuestionAnswerRepository.UpdatePartialFromQueryAsync(x => x.RowId == inDto.RowId && x.TableQuestionId == item.TableQuestionId, x => new ReadingTableQuestionAnswer()
{
Answer = item.Answer
});
}
else
{
await _readingTableQuestionAnswerRepository.AddAsync(new ReadingTableQuestionAnswer()
{
Answer = item.Answer,
QuestionId = inDto.QuestionId,
TableQuestionId = item.TableQuestionId,
RowId = inDto.RowId.Value,
TrialId = taskinfo.TrialId,
RowIndex = rowInfo.RowIndex,
VisitTaskId = inDto.VisitTaskId,
});
}
}
}
await _readingTableAnswerRowInfoRepository.SaveChangesAsync();
await _readingCalculateService.CalculateTask(new CalculateTaskInDto()
{
IsChangeOtherTask = false,
VisitTaskId = inDto.VisitTaskId,
ComputationTrigger = inDto.ComputationTrigger,
});
// 保存完了计算疾病进展
switch (taskinfo.TrialReadingCriterion.CriterionType)
{
case CriterionType.Lugano2014:
if (inDto.RowIndex % 1 != 0)
{
await _luganoCalculateService.CalculateTargetLesionStatus(new CalculateTargetLesionStatusInDto()
{
QuestionId = inDto.QuestionId,
VisitTaskId = inDto.VisitTaskId,
RowNumber = inDto.RowIndex
});
}
break;
case CriterionType.Lugano2014WithoutPET:
if (inDto.RowIndex % 1 != 0)
{
await _LuganoWithoutPETCalculateService.CalculateTargetLesionStatus(new CalculateTargetLesionStatusInDto()
{
QuestionId = inDto.QuestionId,
VisitTaskId = inDto.VisitTaskId,
RowNumber = inDto.RowIndex
});
}
break;
}
return result;
}
/// <summary>
/// 提交Dicom阅片信息
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task<IResponseOutput> SubmitDicomVisitTask(SubmitDicomVisitTaskInDto inDto)
{
await VerifyTaskIsSign(inDto.VisitTaskId);
//// 修改编号
//var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();
//// 获取标准表格外层问题
//var questionList = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == taskInfo.TrialReadingCriterionId && x.LesionType != null && x.ReadingTableQuestionTrialList.Any(x => x.QuestionMark == QuestionMark.AutoId))
// .SelectMany(x => x.ReadingTableQuestionTrialList).Where(x => x.QuestionMark == QuestionMark.AutoId).Select(x => new
// {
// x.ReadingQuestionId,
// TableQuestionId = x.Id,
// }).ToListAsync();
//var questionIds = questionList.Select(x => x.ReadingQuestionId).ToList();
//var questionMarkList = await _readingQuestionTrialRepository.Where(x => questionIds.Contains(x.Id)).Select(x => new
//{
// QuestionId = x.Id,
// x.OrderMark,
//}).ToListAsync();
//var rowInfo = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && questionIds.Contains(x.QuestionId)).ToListAsync();
//List<ReadingTableQuestionAnswer> questionAnswerList = new List<ReadingTableQuestionAnswer>();
//foreach (var item in questionList)
//{
// await _readingTableQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => x.QuestionId == item.ReadingQuestionId
// && x.TableQuestionId == item.TableQuestionId && x.VisitTaskId == inDto.VisitTaskId);
// var orderMark = questionMarkList.Where(x => x.QuestionId == item.ReadingQuestionId).Select(x => x.OrderMark).FirstOrDefault();
// foreach (var row in rowInfo.Where(x => x.QuestionId == item.ReadingQuestionId))
// {
// questionAnswerList.Add(new ReadingTableQuestionAnswer()
// {
// Answer = orderMark + row.RowIndex.GetLesionMark(),
// Id = NewId.NextGuid(),
// QuestionId = item.ReadingQuestionId,
// RowId = row.Id,
// RowIndex = row.RowIndex,
// TableQuestionId = item.TableQuestionId,
// TrialId = taskInfo.TrialId,
// VisitTaskId = taskInfo.Id,
// });
// }
//}
//await _readingTableQuestionAnswerRepository.AddRangeAsync(questionAnswerList);
//await _readingTableQuestionAnswerRepository.SaveChangesAsync();
await SubmitTaskChangeState(inDto.VisitTaskId);
return ResponseOutput.Ok(true);
}
#endregion
#region Dicom dicom 公用
/// <summary>
/// 验证默认问题是否回答
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
/// <exception cref="BusinessValidationFailedException"></exception>
[HttpPost]
public async Task<IResponseOutput> VerifyDefaultQuestionBeAnswer(VerifyVisitTaskQuestionsInDto inDto)
{
var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Include(x => x.TrialReadingCriterion).Include(x => x.SourceSubjectVisit).FirstNotNullAsync();
var criterion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == taskInfo.TrialReadingCriterionId).FirstNotNullAsync();
var readingQuestionList = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == taskInfo.TrialReadingCriterionId && x.Type != "group")
.WhereIf(taskInfo.SourceSubjectVisit.IsBaseLine, x => ((x.IsRequired == IsRequired.Required && x.ShowQuestion == ShowQuestion.Show) && (x.LimitEdit == LimitEdit.None || x.LimitEdit == LimitEdit.OnlyBaseLine)))
.WhereIf(!taskInfo.SourceSubjectVisit.IsBaseLine, x => ((x.IsRequired == IsRequired.Required && x.ShowQuestion == ShowQuestion.Show) && (x.LimitEdit == LimitEdit.None || x.LimitEdit == LimitEdit.OnlyVisit)))
.WhereIf(taskInfo.TrialReadingCriterion.CriterionType == CriterionType.PCWG3, x => x.QuestionType != QuestionType.SiteVisitForTumorEvaluation)
.ToListAsync();
// 排除访视
readingQuestionList = readingQuestionList.Where(x => !(x.LimitShow == LimitShow.ExcludeSomeVisits && x.ExcludeShowVisitList.Contains(taskInfo.VisitTaskNum))).ToList();
var answerQuestionIds = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.Answer != string.Empty).Select(x => x.ReadingQuestionTrialId).ToListAsync();
readingQuestionList = readingQuestionList.Where(x => !answerQuestionIds.Contains(x.Id)).ToList();
if (readingQuestionList.Count > 0)
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_RequiredQuestion", string.Join(',', readingQuestionList.Select(x => x.QuestionName.LanguageName(x.QuestionEnName, _userInfo.IsEn_Us)))]);
}
return ResponseOutput.Ok(true);
}
/// <summary>
/// 验证访视提交
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> VerifyVisitTaskQuestions(VerifyVisitTaskQuestionsInDto inDto)
{
// 验证一个问题不能有多个答案
bool hasDuplicate = await _readingTaskQuestionAnswerRepository
.Where(x => x.VisitTaskId == inDto.VisitTaskId)
.GroupBy(x => x.ReadingQuestionTrialId)
.AnyAsync(g => g.Count() > 1);
if (hasDuplicate)
{
try
{
_ = SendWeComNotifier(inDto.VisitTaskId, "阅片问题答案有重复");
_ = SendAbnormalEmail(inDto.VisitTaskId, EmailBusinessScenario.RepeatedVisitAnswers);
}
catch (Exception)
{
}
throw new BusinessValidationFailedException(_localizer["ReadingImage_VisitAnswerRepeated"]);
}
//验证后处理影像必须传
if (_visitTaskRepository.Any(t => t.Id == inDto.VisitTaskId && t.TrialReadingCriterion.ImageUploadEnum != ReadingImageUpload.None))
{
// 校验当前访视存在上传的非dicom文件就可以提交了
if (!_taskStudyRepository.Any(t => t.VisitTaskId == inDto.VisitTaskId) && !_noneDicomStudyFileRepository.Any(t=>t.VisitTaskId==inDto.VisitTaskId) )
{
return ResponseOutput.NotOk(_localizer["ReadingImage_BackImageNotExist"]);
}
}
if (await _segmentationRepository.AnyAsync(x => !x.IsSaved && x.VisitTaskId == inDto.VisitTaskId))
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_SegmentationNeedSave"]);
}
await VerifyTaskIsSign(inDto.VisitTaskId);
await VerifyDefaultQuestionBeAnswer(inDto);
// 转化后的任务不应该有新病灶
var isConvertedTask = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Select(x => x.IsConvertedTask).FirstNotNullAsync();
if (isConvertedTask && (await _readingTableAnswerRowInfoRepository.AnyAsync(x => x.ReadingQuestionTrial.LesionType == LesionType.NewLesions && x.VisitTaskId == inDto.VisitTaskId)))
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_NotNewFocus"]);
}
var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();
var isBaseline = await _subjectVisitRepository.Where(x => x.Id == taskInfo.SourceSubjectVisitId).Select(x => x.IsBaseLine).FirstOrDefaultAsync();
var readingQuestionList = await _readingQuestionTrialRepository.Where(x => !x.ExcludeShowVisitList.Contains(taskInfo.VisitTaskNum) &&x.ReadingQuestionCriterionTrialId == taskInfo.TrialReadingCriterionId && x.Type != "group"
&& (x.IsJudgeQuestion || (x.IsRequired == IsRequired.Required && x.ShowQuestion == ShowQuestion.Show))
).ToListAsync();
if (isBaseline)
{
readingQuestionList = readingQuestionList.Where(x => x.LimitEdit != LimitEdit.OnlyVisit).ToList();
}
else
{
readingQuestionList = readingQuestionList.Where(x => x.LimitEdit != LimitEdit.OnlyBaseLine).ToList();
}
var answerQuestionIds = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).Select(x => x.ReadingQuestionTrialId).ToListAsync();
readingQuestionList = readingQuestionList.Where(x => !answerQuestionIds.Contains(x.Id)).ToList();
if (readingQuestionList.Count > 0)
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_RequiredQuestion", string.Join(',', readingQuestionList.Select(x => x.QuestionName.LanguageName(x.QuestionEnName, _userInfo.IsEn_Us)))]);
}
// 各个标准不同
await _readingCalculateService.VerifyVisitTaskQuestions(inDto);
var clinicalDataList = await _readingClinicalDataService.GetClinicalDataList(new GetReadingOrTaskClinicalDataListInDto()
{
SubjectId = taskInfo.SubjectId,
TrialId = taskInfo.TrialId,
VisitTaskId = taskInfo.Id,
});
var isBaseLine = false;
if (taskInfo.SourceSubjectVisitId != null)
{
isBaseLine = await _subjectVisitRepository.Where(x => x.Id == taskInfo.SourceSubjectVisitId).Select(x => x.IsBaseLine).FirstOrDefaultAsync();
}
var isNeedReadClinicalData = false;
if (isBaseLine)
{
isNeedReadClinicalData = clinicalDataList.Count > 0;
}
else
{
isNeedReadClinicalData = clinicalDataList.Where(x => x.ClinicalDataLevel != ClinicalLevel.Subject).Count() > 0;
}
if (isNeedReadClinicalData && !taskInfo.IsReadClinicalData)
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_ClinicalRead"]);
}
return ResponseOutput.Ok(true);
}
/// <summary>
/// 清除跳过阅片的缓存
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<bool> ClearSkipReadingCache()
{
await _fusionCache.RemoveAsync(CacheKeys.SkipReadingCacheKey(_userInfo.UserRoleId));
return true;
}
/// <summary>
/// 设置跳过阅片的缓存
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<bool> SetSkipReadingCache(SetSkipReadingCacheInDto inDto)
{
var clearSkipReadingCache = await _fusionCache.GetOrDefaultAsync<string>(CacheKeys.SkipReadingCacheKey(_userInfo.UserRoleId));
if (clearSkipReadingCache == null || clearSkipReadingCache == string.Empty)
{
List<Guid> cacheIds = new List<Guid>();
cacheIds.Add(inDto.VisitTaskId);
await _fusionCache.SetAsync<string>(CacheKeys.SkipReadingCacheKey(_userInfo.UserRoleId), JsonConvert.SerializeObject(cacheIds), TimeSpan.FromHours(24));
}
else
{
List<Guid>? cacheIds = JsonConvert.DeserializeObject<List<Guid>>(clearSkipReadingCache);
cacheIds.Add(inDto.VisitTaskId);
await _fusionCache.SetAsync<string>(CacheKeys.SkipReadingCacheKey(_userInfo.UserRoleId), JsonConvert.SerializeObject(cacheIds), TimeSpan.FromHours(24));
}
return true;
}
/// <summary>
/// 获取下一个阅片任务
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<GetReadingTaskDto> GetNextTask(GetNextTaskInDto inDto)
{
if (inDto.VisitTaskId == null)
{
await VerifyReadingRestTime();
}
GetReadingTaskDto? task = new GetReadingTaskDto();
var trialReadingCriterionId = inDto.TrialReadingCriterionId;
if (trialReadingCriterionId == null && inDto.VisitTaskId == null)
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_IDMust"]);
}
if (inDto.SubjectCode.IsNotNullOrEmpty() && inDto.SubjectId != null)
{
if (! (await _visitTaskRepository.AnyAsync(x => x.TrialReadingCriterionId == inDto.TrialReadingCriterionId
&& x.SubjectId == inDto.SubjectId && (x.BlindSubjectCode == inDto.SubjectCode || x.Subject.Code == inDto.SubjectCode))))
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_SubjectCodeError"]);
}
}
#region 跳过阅片
var clearSkipReadingCache = await _fusionCache.GetOrDefaultAsync<string>(CacheKeys.SkipReadingCacheKey(_userInfo.UserRoleId));
List<Guid> cacheSkipIds = new List<Guid>();
if (clearSkipReadingCache != null && clearSkipReadingCache != string.Empty)
{
cacheSkipIds = JsonConvert.DeserializeObject<List<Guid>>(clearSkipReadingCache);
}
#endregion
var trialReadingCriterion = await _readingQuestionCriterionTrialRepository.FindAsync(trialReadingCriterionId ?? Guid.Empty);
if (inDto.VisitTaskId != null)
{
task = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Select(x => new GetReadingTaskDto()
{
VisitTaskId = x.Id,
TaskBlindName = x.TaskBlindName,
SubjectId = x.SubjectId,
ReadingCategory = x.ReadingCategory,
ArmEnum = x.ArmEnum,
VisistId = x.SourceSubjectVisitId != null ? x.SourceSubjectVisitId.Value : default(Guid),
VisitNum = x.VisitTaskNum,
TrialReadingCriterionId = x.TrialReadingCriterionId,
}).FirstNotNullAsync();
trialReadingCriterionId = task.TrialReadingCriterionId;
}
else if (inDto.SubjectId != null && trialReadingCriterion.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
{
var subjectTaskList = (await _visitTaskService.GetSubjectReadingIQueryable(new GetReadingIQueryableInDto()
{
TrialId = inDto.TrialId,
TrialReadingCriterionId = trialReadingCriterionId!.Value,
PageIndex = 1,
PageSize = 99999,
})).CurrentPageData;
var index = 0;
subjectTaskList.ForEach(x =>
{
x.Index = index;
index++;
});
var subjectIndex = subjectTaskList.Where(x => x.SubjectId == inDto.SubjectId && x.SubjectCode == inDto.SubjectCode).Select(x => x.Index).FirstOrDefault();
var currentSubject = subjectTaskList.Where(x => x.Index >= subjectIndex && !x.ExistReadingApply)
// 排除跳过的
.Where(x => x.UnReadCanReadTaskList.Select(y => y.Id).Intersect(cacheSkipIds).Count() == 0)
.OrderBy(x => x.Index).FirstOrDefault();
if (currentSubject == null)
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_TaskFinish"], ApiResponseCodeEnum.CloseCurrentWindows);
}
task = currentSubject.UnReadCanReadTaskList
.Select(x => new GetReadingTaskDto()
{
ReadingCategory = x.ReadingCategory,
SubjectCode = currentSubject.SubjectCode,
SubjectId = currentSubject.SubjectId,
TaskBlindName = x.TaskBlindName,
VisitNum = x.VisitNum,
ArmEnum = x.ArmEnum,
VisistId = x.VisistId ?? default(Guid),
VisitTaskId = x.Id,
TrialReadingCriterionId = x.TrialReadingCriterionId,
}).FirstOrDefault();
}
else if (inDto.SubjectId != null && trialReadingCriterion.IsReadingTaskViewInOrder == ReadingOrder.SubjectRandom)
{
var subjectTaskList = (await _visitTaskService.GetSubjectReadingIQueryable(new GetReadingIQueryableInDto()
{
TrialId = inDto.TrialId,
SubjectId = inDto.SubjectId,
TrialReadingCriterionId = trialReadingCriterionId!.Value,
SubjectCode = inDto.SubjectCode,
PageIndex = 1,
PageSize = 99999,
})).CurrentPageData;
if (subjectTaskList.Count() == 0)
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_TaskFinish"], ApiResponseCodeEnum.CloseCurrentWindows);
}
var taskList = subjectTaskList.FirstOrDefault()!.UnReadCanReadTaskList;
// 排除跳过的
List<Guid> remainingItems = taskList.Select(x => x.Id).Except(cacheSkipIds).ToList();
//受试者随机固定排序
taskList = taskList.Where(x => remainingItems.Contains(x.Id)).OrderBy(t => t.TaskBlindName).ToList();
// 当前受试者没有就找其他受试者
if (taskList.Count() == 0)
{
var allsubjectTaskList = (await _visitTaskService.GetSubjectReadingIQueryable(new GetReadingIQueryableInDto()
{
TrialId = inDto.TrialId,
TrialReadingCriterionId = trialReadingCriterionId!.Value,
PageIndex = 1,
PageSize = 99999,
})).CurrentPageData;
foreach (var item in allsubjectTaskList)
{
var canReadList = item.UnReadCanReadTaskList.Where(x => remainingItems.Contains(x.Id)).OrderBy(t => t.TaskBlindName).ToList();
if (canReadList.Count() > 0)
{
taskList = canReadList;
break;
}
}
}
if (taskList.Count() == 0)
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_TaskFinish"], ApiResponseCodeEnum.CloseCurrentWindows);
}
#region 随机废弃
//Random random = new Random();
////返回的范围是 0- taskList.Count-1
//int randomIndex = random.Next(taskList.Count);
//var visitTaskId = taskList[randomIndex].Id;
#endregion
var visitTaskId = taskList[0].Id;
task = await _visitTaskRepository.Where(x => x.Id == visitTaskId).Select(x => new GetReadingTaskDto()
{
VisitTaskId = x.Id,
ArmEnum = x.ArmEnum,
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,
TrialReadingCriterionId = x.TrialReadingCriterionId,
}).FirstOrDefaultAsync();
}
else
{
var query = _visitTaskRepository.Where(x => x.TrialId == inDto.TrialId && x.TrialReadingCriterionId == trialReadingCriterionId && x.ReadingTaskState != ReadingTaskState.HaveSigned && x.DoctorUserId == _userInfo.UserRoleId
&& x.TrialReadingCriterionId == trialReadingCriterionId
&& x.TaskState == TaskState.Effect)
.Where(x => !cacheSkipIds.Contains(x.Id));
//如果是随机阅片
Random random = new Random();
var skipcount = 0;
var minRandomOrder = query.Where(t => t.RandomOrder != null).Select(t => t.RandomOrder).MinOrDefault();
//以随机序号优先,阅片中优先先给IR
if (minRandomOrder != null)
{
query = query.Where(x => x.RandomOrder == minRandomOrder);
skipcount = 0;
}
else
{
//没有随机序号的,那么就按照阅片中最新的时间给
var maxReadingTime = query.MaxOrDefault(x => x.FirstReadingTime);
if (maxReadingTime != null)
{
query = query.Where(x => x.FirstReadingTime == maxReadingTime);
skipcount = 0;
}
}
var count = await query.CountAsync();
if (count >= 2)
{
skipcount = random.Next(0, count - 1);
}
if (count == 0)
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_TaskFinish"], ApiResponseCodeEnum.CloseCurrentWindows);
}
task = await query
.Select(x => new GetReadingTaskDto()
{
VisitTaskId = x.Id,
ArmEnum = x.ArmEnum,
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,
TrialReadingCriterionId = x.TrialReadingCriterionId,
}).Skip(skipcount).FirstOrDefaultAsync();
}
if (task == null)
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_TaskFinish"], ApiResponseCodeEnum.CloseCurrentWindows);
}
else
{
//触发任务随机编号
await _downloadAndUploadService.SubejctRandomReadingTaskNameDeal(task.SubjectId, task.TrialReadingCriterionId);
task.TaskBlindName = await _visitTaskRepository.Where(t => t.Id == task.VisitTaskId).Select(t => t.TaskBlindName).FirstOrDefaultAsync() ?? "";
}
if (task.SubjectCode.IsNullOrEmpty())
{
task.SubjectCode = await _subjectRepository.Where(x => x.Id == task.SubjectId).Select(x => x.Code).FirstNotNullAsync();
}
await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => x.Id == task.VisitTaskId && x.TaskState == TaskState.Effect && x.ReadingTaskState != ReadingTaskState.HaveSigned, x => new VisitTask()
{
FirstReadingTime = DateTime.Now,
});
await _visitTaskRepository.SaveChangesAsync();
var visitTaskInfo = await _visitTaskRepository.Where(x => x.Id == task.VisitTaskId).ProjectTo<VisitTaskDto>(_mapper.ConfigurationProvider).FirstNotNullAsync();
task.SubjectCode = visitTaskInfo.BlindSubjectCode.IsNullOrEmpty() ? task.SubjectCode : visitTaskInfo.BlindSubjectCode;
var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == visitTaskInfo.TrialReadingCriterionId).Select(x => new
{
x.IsReadingShowPreviousResults,
x.IsReadingShowSubjectInfo,
x.DigitPlaces,
x.ReadingVersionEnum,
x.CriterionType,
x.IseCRFShowInDicomReading,
x.IsReadingTaskViewInOrder,
x.ReadingToolList,
x.CircleRadius,
x.DefaultSegmentName,
x.JudgeGenerateEnum,
x.JudgeModeEnum,
x.JudgeRuleEnum,
x.ArbitrationRule,
}).FirstNotNullAsync();
task.IsReadingShowPreviousResults = criterionInfo.IsReadingShowPreviousResults;
task.IsReadingShowSubjectInfo = criterionInfo.IsReadingShowSubjectInfo;
task.IsReadingTaskViewInOrder = criterionInfo.IsReadingTaskViewInOrder;
var isBaseLine = false;
if (visitTaskInfo.SourceSubjectVisitId != null)
{
task.IsExistsNoDicomFile = await _noneDicomStudyRepository.AnyAsync(x => x.SubjectVisitId == visitTaskInfo.SourceSubjectVisitId && x.FileCount > 0);
isBaseLine = await _subjectVisitRepository.Where(x => x.Id == visitTaskInfo.SourceSubjectVisitId).Select(x => x.IsBaseLine).FirstOrDefaultAsync();
}
var clinicalDataList = await _readingClinicalDataService.GetClinicalDataList(new GetReadingOrTaskClinicalDataListInDto()
{
SubjectId = task.SubjectId,
TrialId = inDto.TrialId,
VisitTaskId = task.VisitTaskId,
});
task.IsExistsClinicalData = clinicalDataList.Count > 0;
task.IsReadClinicalData = visitTaskInfo.IsReadClinicalData;
if (isBaseLine)
{
task.IsNeedReadClinicalData = clinicalDataList.Count > 0;
}
else
{
task.IsNeedReadClinicalData = clinicalDataList.Where(x => x.ClinicalDataLevel != ClinicalLevel.Subject).Count() > 0;
}
if (visitTaskInfo.ReadingTaskState == ReadingTaskState.WaitReading)
{
await _readingCalculateService.AddTaskLesionAnswerFromLastTask(new AddTaskLesionAnswerFromLastTaskInDto()
{
VisitTaskId = task.VisitTaskId
});
}
var trialInfo = await _trialRepository.Where(x => x.Id == visitTaskInfo.TrialId).FirstNotNullAsync();
// 如果已经签名 就不需要再读了
task.CircleRadius = criterionInfo.CircleRadius;
task.DefaultSegmentName = criterionInfo.DefaultSegmentName;
task.IsNeedReadClinicalData = visitTaskInfo.ReadingTaskState == ReadingTaskState.HaveSigned ? false : task.IsNeedReadClinicalData;
task.DigitPlaces = criterionInfo.DigitPlaces;
task.CriterionType = criterionInfo.CriterionType;
task.IseCRFShowInDicomReading = criterionInfo.IseCRFShowInDicomReading;
task.IsFirstChangeTask = visitTaskInfo.IsConvertedTask && visitTaskInfo.BeforeConvertedTaskId != null;
task.IsConvertedTask = visitTaskInfo.IsConvertedTask;
var blindSubjectCode = await _visitTaskRepository.Where(x => x.Id == task.VisitTaskId).Select(x => x.BlindSubjectCode).FirstNotNullAsync();
task.SubjectCode = blindSubjectCode.IsNullOrEmpty() ? task.SubjectCode : blindSubjectCode;
task.ExistsManual = (await GetManualList(new GetManualListInDto() { TrialId = visitTaskInfo.TrialId })).Count > 0;
task.ReadingTaskState = visitTaskInfo.ReadingTaskState;
task.IsShowStudyName = trialInfo.IsShowStudyName;
task.IsBaseLine = isBaseLine;
task.ReadingVersionEnum = criterionInfo.ReadingVersionEnum;
task.ReadingToolList = criterionInfo.ReadingToolList;
task.IsExistUnprocessedFeedback = await _userFeedBackRepository.AnyAsync(x => x.VisitTaskId == task.VisitTaskId && x.State == 0);
task.IsViewStudyPart = visitTaskInfo.ReadingCategory == ReadingCategory.Judge || visitTaskInfo.IsViewStudyPart;
task.IsReadKeyFile = await _criterionKeyFileReadRepository.AnyAsync(x => x.IdentityUserId == _userInfo.IdentityUserId && x.TrialCriterionId == task.TrialReadingCriterionId);
task.IsHaveKeyFile = await _trialCriterionKeyFileRepository.AnyAsync(x => x.TrialCriterionId == task.TrialReadingCriterionId);
task.JudgeModeEnum = criterionInfo.JudgeModeEnum;
task.JudgeRuleEnum = criterionInfo.JudgeRuleEnum;
task.ArbitrationRule = criterionInfo.ArbitrationRule;
// 添加默认答案
if (inDto.VisitTaskId == null && visitTaskInfo.ReadingTaskState != ReadingTaskState.HaveSigned)
{
await AddDefaultValueToTask(task.VisitTaskId);
}
return task;
}
/// <summary>
/// 重置阅片任务
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<ResetReadingTaskOutDto> ResetReadingTask(ResetReadingTaskInDto inDto)
{
await VerifyTaskIsSign(inDto.VisitTaskId);
var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();
if (taskinfo.ReadingCategory != ReadingCategory.Visit)
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_CannotReset"]);
}
await _readingTableAnswerRowInfoRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId);
await _readingTaskQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId);
await _readingTableQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId);
await _readingTaskQuestionMarkRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId);
await _readingNoneDicomMarkRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId);
await _readingNoneDicomMarkBindingRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId);
await _segmentBindingRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId);
await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => x.Id == inDto.VisitTaskId, x => new VisitTask()
{
ReadingTaskState = ReadingTaskState.WaitReading
});
await _visitTaskRepository.SaveChangesAsync();
_userInfo.IsNotNeedInspection = true;
await AddDefaultValueToTask(inDto.VisitTaskId);
await _readingCalculateService.AddTaskLesionAnswerFromLastTask(new AddTaskLesionAnswerFromLastTaskInDto()
{
VisitTaskId = inDto.VisitTaskId
});
return new ResetReadingTaskOutDto() { };
}
/// <summary>
/// 验证阅片休息时间
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<bool> VerifyReadingRestTime()
{
var userTypeEnum = (UserTypeEnum)_userInfo.UserTypeEnumInt;
if (userTypeEnum != UserTypeEnum.IndependentReviewer)
{
return true;
}
var startReadingTimeKey = _userInfo.UserRoleId.ToString() + "StartReadingTime";
var startRestTimeKey = _userInfo.UserRoleId.ToString() + "StartRestTime";
int readingMinute = _verifyConfig.CurrentValue.ContinuousReadingTimeMin; // 为60整数
int restMinute = _verifyConfig.CurrentValue.ReadingRestTimeMin; //
var startReadingTime = await _fusionCache.GetOrDefaultAsync<string>(CacheKeys.StartReadingTimeKey(_userInfo.UserRoleId));
var startRestTime = await _fusionCache.GetOrDefaultAsync<string>(CacheKeys.StartRestTime(_userInfo.UserRoleId));
if (startReadingTime == null && startRestTime == null)
{
await _fusionCache.SetAsync<string>(CacheKeys.StartReadingTimeKey(_userInfo.UserRoleId), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromHours(48));
}
else if (startRestTime != null)
{
var cacheStartRestTime = DateTime.Parse(startRestTime!.ToString());
int timespanMin = (DateTime.Now - cacheStartRestTime).Minutes;
if (timespanMin <= restMinute)
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_NeedRest", 2, 10]);
}
else
{
// 休息时间>10分钟 删除休息时间的缓存 记录开始阅片时间
await _fusionCache.RemoveAsync(CacheKeys.StartRestTime(_userInfo.UserRoleId));
await _fusionCache.SetAsync<string>(CacheKeys.StartReadingTimeKey(_userInfo.UserRoleId), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromHours(48));
}
}
// 如果开始阅片时间 不为空
else if (startReadingTime != null)
{
#region 两小时
var cacheDate = DateTime.Parse(startReadingTime!.ToString());
int timespanMin = (DateTime.Now - cacheDate).Minutes;
if (timespanMin > readingMinute)
{
await _fusionCache.RemoveAsync(CacheKeys.StartReadingTimeKey(_userInfo.UserRoleId));
await _fusionCache.SetAsync<string>(CacheKeys.StartRestTime(_userInfo.UserRoleId), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromHours(48));
throw new BusinessValidationFailedException(_localizer["ReadingImage_NeedRest", readingMinute / 60m, restMinute]);
}
#endregion
}
return true;
}
/// <summary>
/// 重置阅片时间 登录和解锁调用
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<bool> ResetReadingRestTime(Guid? userRoleId)
{
var roleId = (userRoleId != null && userRoleId != Guid.Empty) ? (Guid)userRoleId : _userInfo.UserRoleId;
//int readingMinute = 120; // 为60整数
int restMinute = 10; //
var startReadingTime = await _fusionCache.GetOrDefaultAsync<string>(CacheKeys.StartReadingTimeKey(roleId));
var startRestTime = await _fusionCache.GetOrDefaultAsync<string>(CacheKeys.StartRestTime(roleId));
if (startRestTime != null)
{
var cacheStartRestTime = DateTime.Parse(startRestTime!.ToString());
int timespanMin = (DateTime.Now - cacheStartRestTime).Minutes;
if (timespanMin > restMinute)
{
await _fusionCache.RemoveAsync(CacheKeys.StartRestTime(roleId));
}
}
else if (startReadingTime != null)
{
await _fusionCache.SetAsync<string>(CacheKeys.StartReadingTimeKey(roleId), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromHours(48));
}
//前端屏幕解锁才调用
if (userRoleId == null)
{
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionIdentityUserId = _userInfo.IdentityUserId, OptType = UserOptType.WebUnlock }, true);
}
return true;
}
/// <summary>
/// 签名提交任务修改状态
/// </summary>
/// <param name="visitTaskId"></param>
/// <returns></returns>
private async Task SubmitTaskChangeState(Guid visitTaskId)
{
await VerifyTaskIsSign(visitTaskId);
var taskInfo=await _visitTaskRepository.Where(x => x.Id == visitTaskId).Include(x=>x.TrialReadingCriterion).FirstNotNullAsync();
// 如果是PCGW标准 则把中间答案赋值给正式答案
if (taskInfo.TrialReadingCriterion.CriterionType == CriterionType.PCWG3)
{
var answerList = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTask.TaskState==TaskState.Effect&& x.VisitTask.SubjectId == taskInfo.SubjectId && x.VisitTask.ArmEnum == taskInfo.ArmEnum && x.PCWGInterimAnswer != null).ToListAsync();
foreach (var item in answerList)
{
await _readingTaskQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x=>x.Id==item.Id, x => new ReadingTaskQuestionAnswer()
{
//这里已经筛选过 不为null了
Answer = item.PCWGInterimAnswer,
PCWGInterimAnswer = null,
});
}
}
await _visitTaskRepository.UpdatePartialFromQueryAsync(visitTaskId, x => new VisitTask()
{
ReadingTaskState = ReadingTaskState.HaveSigned,
SignTime = DateTime.Now,
});
await _visitTaskRepository.SaveChangesAsync();
bool isConverted = false;
var taskinfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).Include(x => x.TrialReadingCriterion).FirstNotNullAsync();
var isConvertedTask = await _visitTaskRepository.Where(x => x.Id == visitTaskId).Select(x => x.IsConvertedTask).FirstNotNullAsync();
switch (taskinfo.TrialReadingCriterion.CriterionType)
{
case CriterionType.IRECIST1Point1:
if (!isConvertedTask &&
(await _readingTaskQuestionAnswerRepository.AnyAsync(x => x.VisitTaskId == visitTaskId
&& x.ReadingQuestionTrial.QuestionType == QuestionType.Tumor && x.Answer == (((int)OverallAssessment.PD)).ToString()))
)
{
isConverted = true;
}
break;
}
// 创建任务关联关系
await CreateTaskRelated(visitTaskId);
// 是否触发转变任务
if (isConverted)
{
await _visitTaskHelpeService.AddConvertedTask(visitTaskId);
}
else
{
// 触裁判任务
await TriggerJudgeQuestion(visitTaskId);
// 添加阅片期任务
await AddReadingTask(visitTaskId);
// 完成阅片修改状态
//await FinishReadUpdateState(visitTaskId);
await _visitTaskRepository.SaveChangesAsync();
await SafeMailHelper.Run(async () => await _trialEmailNoticeConfigService.BaseBusinessScenarioSendEmailAsync(visitTaskId));
}
}
/// <summary>
/// 签名时创建任务关联
/// </summary>
/// <returns></returns>
private async Task CreateTaskRelated(Guid visitTaskId)
{
var taskInfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).FirstNotNullAsync();
// 判断是否有序阅片
var isReadingTaskViewInOrder = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == taskInfo.TrialReadingCriterionId).Select(x => x.IsReadingTaskViewInOrder).FirstNotNullAsync();
// 判断任务类型
// 关联访视Id
List<Guid> relatedVisitTaskIdList = new List<Guid>();
// 既往任务Id
List<Guid> pastResultTaskIdList = new List<Guid>();
// 冻结任务Id
List<Guid> reportRelatedTaskIdList = new List<Guid>();
if (isReadingTaskViewInOrder == ReadingOrder.InOrder)
{
pastResultTaskIdList = await _visitTaskRepository.Where(x =>
x.TrialId == taskInfo.TrialId &&
x.SubjectId == taskInfo.SubjectId &&
x.VisitTaskNum < taskInfo.VisitTaskNum &&
x.ArmEnum == taskInfo.ArmEnum &&
x.DoctorUserId == taskInfo.DoctorUserId &&
x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId &&
x.ReadingTaskState == ReadingTaskState.HaveSigned &&
x.TaskState == TaskState.Effect &&
x.IsSelfAnalysis == taskInfo.IsSelfAnalysis &&
x.IsAnalysisCreate == taskInfo.IsAnalysisCreate &&
x.ReadingCategory == taskInfo.ReadingCategory &&
x.Id != taskInfo.Id
).OrderBy(x => x.VisitTaskNum).ThenBy(x => x.TaskState).Select(x => x.Id).ToListAsync();
reportRelatedTaskIdList = await _visitTaskRepository.Where(x =>
x.TrialId == taskInfo.TrialId &&
x.SubjectId == taskInfo.SubjectId &&
x.VisitTaskNum <= taskInfo.VisitTaskNum &&
x.ArmEnum == taskInfo.ArmEnum &&
x.DoctorUserId == taskInfo.DoctorUserId &&
x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId &&
x.ReadingTaskState == ReadingTaskState.HaveSigned &&
(x.TaskState == TaskState.Effect || x.TaskState == TaskState.Freeze) &&
x.IsSelfAnalysis == taskInfo.IsSelfAnalysis &&
x.IsAnalysisCreate == taskInfo.IsAnalysisCreate &&
x.ReadingCategory == taskInfo.ReadingCategory &&
x.Id != taskInfo.Id
).OrderBy(x => x.VisitTaskNum).ThenBy(x => x.TaskState).Select(x => x.Id).ToListAsync();
switch (taskInfo.ReadingCategory)
{
case ReadingCategory.Visit:
case ReadingCategory.Global:
relatedVisitTaskIdList = await _visitTaskRepository.Where(x =>
x.TrialId == taskInfo.TrialId &&
x.SubjectId == taskInfo.SubjectId &&
x.ReadingCategory == ReadingCategory.Visit &&
x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId &&
x.ReadingTaskState == ReadingTaskState.HaveSigned &&
x.IsAnalysisCreate == taskInfo.IsAnalysisCreate &&
x.ArmEnum == taskInfo.ArmEnum &&
x.IsSelfAnalysis == taskInfo.IsSelfAnalysis &&
x.DoctorUserId == taskInfo.DoctorUserId &&
x.TaskState == TaskState.Effect && x.VisitTaskNum <= taskInfo.VisitTaskNum).Select(x => x.Id).ToListAsync();
break;
case ReadingCategory.Oncology:
// 肿瘤学这里很特殊 因为没有裁判的时候 可能取R1可能取R2 为了和之前阅片的时候保持统一
// 所以在保存肿瘤学答案的时候就存起来 现在签名的时候 创建关系
relatedVisitTaskIdList = await _visitTaskRepository.Where(x => x.Id == visitTaskId).Select(x => x.RelatedVisitTaskIdList).FirstNotNullAsync();
break;
}
}
else
{
if (taskInfo.ReadingCategory == ReadingCategory.Visit)
{
switch (isReadingTaskViewInOrder)
{
case ReadingOrder.SubjectRandom:
relatedVisitTaskIdList = await _visitTaskRepository.Where(x =>
x.TrialId == taskInfo.TrialId &&
x.SubjectId == taskInfo.SubjectId &&
x.ReadingCategory == ReadingCategory.Visit &&
x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId &&
//x.ReadingTaskState == ReadingTaskState.HaveSigned &&
x.IsAnalysisCreate == taskInfo.IsAnalysisCreate &&
x.ArmEnum == taskInfo.ArmEnum &&
x.IsSelfAnalysis == taskInfo.IsSelfAnalysis &&
x.BlindSubjectCode == taskInfo.BlindSubjectCode &&
x.DoctorUserId == taskInfo.DoctorUserId &&
x.TaskState == TaskState.Effect && x.Id != taskInfo.Id).Select(x => x.Id).ToListAsync();
break;
default:
relatedVisitTaskIdList.Add(taskInfo.Id);
break;
}
}
}
await _visitTaskRepository.UpdatePartialFromQueryAsync(taskInfo.Id, x => new VisitTask()
{
ReportRelatedTaskIds = JsonConvert.SerializeObject(reportRelatedTaskIdList),
PastResultTaskIds = JsonConvert.SerializeObject(pastResultTaskIdList),
RelatedVisitTaskIds = JsonConvert.SerializeObject(relatedVisitTaskIdList),
});
await _readingTaskRelationRepository.AddRangeAsync(pastResultTaskIdList.Select(x => new ReadingTaskRelation()
{
RelevanceTaskId = x,
TaskId = visitTaskId,
RelevanceType = RelevanceType.PastResult,
}));
await _readingTaskRelationRepository.AddRangeAsync(relatedVisitTaskIdList.Select(x => new ReadingTaskRelation()
{
RelevanceTaskId = x,
TaskId = visitTaskId,
RelevanceType = RelevanceType.Related,
}));
await _readingTaskRelationRepository.AddRangeAsync(reportRelatedTaskIdList.Select(x => new ReadingTaskRelation()
{
RelevanceTaskId = x,
TaskId = visitTaskId,
RelevanceType = RelevanceType.ReportResult,
}));
await _visitTaskRepository.SaveChangesAsync();
}
/// <summary>
/// 阅片期 -全局和肿瘤学任务的生成
/// </summary>
/// <returns></returns>
[HttpPost]
[TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task AddReadingTask(Guid visitTaskId, Guid? trialId = null)
{
// ****** 先生成阅片期 阅片期任务阅片完成之后生成肿瘤学的 如果没有阅片期 直接生成肿瘤学 *********////
#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).Include(x => x.TrialReadingCriterion).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 &&
x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId)
.Select(x => new ReadingGenerataTaskDTO
{
IsUrgent = x.IsUrgent ?? false,
SubjectId = x.SubjectId,
VisitNum = x.SubjectVisit.VisitNum,
ReadingName = x.ModuleName,
ReadModuleId = x.Id,
ReadingCategory = typeChangeDic[x.ModuleType],
}).ToListAsync();
if (needReadList.Any(x => x.ReadingCategory == ReadingCategory.Global) && taskInfo.TrialReadingCriterion.IsGlobalReading)
{
needReadList = needReadList.Where(x => x.ReadingCategory != ReadingCategory.Oncology).ToList();
await _visitTaskHelpeService.AddTaskAsync(new GenerateTaskCommand()
{
OriginalVisitId = visitTaskId,
ReadingCategory = GenerateTaskCategory.Global,
TrialId = taskInfo.TrialId,
ReadingGenerataTaskList = needReadList
});
}
else if (needReadList.Any(x => x.ReadingCategory == ReadingCategory.Oncology))
{
// 添加肿瘤学
if (await _visitTaskRepository.AnyAsync(x => x.Id == visitTaskId && x.JudgeVisitTaskId == null))
{
await AddOncologyTask(needReadList.Where(x => x.ReadingCategory == ReadingCategory.Oncology).First().ReadModuleId);
}
}
//needReadList = needReadList.Where(x => _visitTaskRepository.Where(y => y.SouceReadModuleId == x.ReadModuleId).Count() == 0).ToList();
break;
// 肿瘤学
case ReadingCategory.Global:
var subjectVisitId = await _readModuleRepository.Where(x => x.Id == taskInfo.SouceReadModuleId).Select(x => x.SubjectVisitId).FirstOrDefaultAsync();
var oncologyReadId = await _readModuleRepository.Where(x => x.SubjectVisitId == subjectVisitId && x.ModuleType == ModuleTypeEnum.Oncology
&& x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId
).Select(x => x.Id).FirstOrDefaultAsync();
if (await _visitTaskRepository.AnyAsync(x => x.Id == visitTaskId && x.JudgeVisitTaskId == null))
{
await AddOncologyTask(oncologyReadId);
}
break;
}
}
}
#endregion
}
}