EI-Image-Viewer-Api/IRaCIS.Core.Application/Service/ImageAndDoc/StudyListService.cs

425 lines
19 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Mvc;
using IRaCIS.Core.Application.Dicom;
using Microsoft.AspNetCore.Authorization;
using IRaCIS.Core.Application.Services;
using EasyCaching.Core;
namespace IRaCIS.Core.Application.Service.ImageAndDoc
{
[ApiExplorerSettings(GroupName = "Image")]
public class StudyService : BaseService
{
private readonly DicomFileStoreHelper _dicomFileStoreHelper;
private readonly IEasyCachingProvider _provider;
public StudyService(DicomFileStoreHelper dicomFileStoreHelper, IEasyCachingProvider provider)
{
_dicomFileStoreHelper = dicomFileStoreHelper;
_provider = provider;
}
[HttpPost]
public async Task<PageOutput<UnionStudyViewModel>> GetDicomAndNoneDicomStudyList(StudyQuery studyQuery)
{
var dicomStudyQuery = _repository.Where<DicomStudy>(t => t.TrialId == studyQuery.TrialId)
.WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator, t => t.TrialSite.CRCUserList.Any(t => t.UserId == _userInfo.Id))
.WhereIf(!string.IsNullOrEmpty(studyQuery.VisitPlanInfo), studyQuery.VisitPlanInfo.Contains('.') ? t => t.SubjectVisit.VisitNum.ToString().Contains(".") : t => t.SubjectVisit.VisitNum == decimal.Parse(studyQuery.VisitPlanInfo))
.WhereIf(!string.IsNullOrWhiteSpace(studyQuery.SubjectInfo), t => t.Subject.Code.Contains(studyQuery.SubjectInfo))
.Select(t => new UnionStudyViewModel()
{
TrialId = t.TrialId,
SiteId = t.SiteId,
SubjectId = t.SubjectId,
SubjectVisitId = t.SubjectVisitId,
VisitName = t.SubjectVisit.VisitName,
VisitNum = t.SubjectVisit.VisitNum,
IsDicom = true,
SubjectCode = t.Subject.Code,
Id = t.Id,
Bodypart = t.BodyPartExamined,
Modalities = t.Modalities,
Count = t.SeriesCount,
StudyCode = t.StudyCode,
//DicomStudyCode = t.StudyCode,
//NoneDicomCode = 0,
StudyTime = t.StudyTime,
TrialSiteAliasName = t.TrialSite.TrialSiteAliasName,
TrialSiteCode = t.TrialSite.TrialSiteCode,
Uploader = t.Uploader.LastName + " / " + t.Uploader.LastName,
UploadTime = t.CreateTime
});
//.ProjectTo<UnionStudyViewDodel>(_mapper.ConfigurationProvider);
var nodeDicomStudyQuery = _repository.Where<NoneDicomStudy>(t => t.TrialId == studyQuery.TrialId)
.WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator, t => t.TrialSite.CRCUserList.Any(t => t.UserId == _userInfo.Id))
.WhereIf(!string.IsNullOrEmpty(studyQuery.VisitPlanInfo), studyQuery.VisitPlanInfo.Contains('.') ? t => t.SubjectVisit.VisitNum.ToString().Contains(".") : t => t.SubjectVisit.VisitNum == decimal.Parse(studyQuery.VisitPlanInfo))
.WhereIf(!string.IsNullOrWhiteSpace(studyQuery.SubjectInfo), t => t.Subject.Code.Contains(studyQuery.SubjectInfo))
.Select(t => new UnionStudyViewModel()
{
TrialId = t.TrialId,
SiteId = t.SiteId,
SubjectId = t.SubjectId,
SubjectVisitId = t.SubjectVisitId,
VisitName = t.SubjectVisit.VisitName,
VisitNum = t.SubjectVisit.VisitNum,
IsDicom = false,
SubjectCode = t.Subject.Code,
Id = t.Id,
Bodypart = t.BodyPart,
Modalities = t.Modality,
Count = t.NoneDicomFileList.Count(),
StudyCode = t.StudyCode,
//NoneDicomCode = t.Code,
//DicomStudyCode = string.Empty,
StudyTime = t.ImageDate,
TrialSiteAliasName = t.TrialSite.TrialSiteAliasName,
TrialSiteCode = t.TrialSite.TrialSiteCode,
Uploader = t.CreateUser.LastName + " / " + t.CreateUser.LastName,
UploadTime = t.CreateTime
});
//.ProjectTo<UnionStudyViewDodel>(_mapper.ConfigurationProvider);
var unionQuery = dicomStudyQuery.Union(nodeDicomStudyQuery)
.WhereIf(studyQuery.SubjectId != null, t => t.SubjectId == studyQuery.SubjectId)
.WhereIf(studyQuery.SubjectVisitId != null, t => t.SubjectId == studyQuery.SubjectVisitId)
.WhereIf(studyQuery.SiteId != null, t => t.SiteId == studyQuery.SiteId);
return await unionQuery.ToPagedListAsync(studyQuery.PageIndex, studyQuery.PageSize, studyQuery.SortField, studyQuery.Asc);
}
[HttpPost]
public async Task<PageOutput<UnionStudyMonitorModel>> GetDicomAndNoneDicomStudyMonitorList(StudyQuery studyQuery)
{
var dicomStudyQuery = _repository.Where<StudyMonitor>(t => t.TrialId == studyQuery.TrialId && t.IsDicom)
.WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator, t => t.TrialSite.CRCUserList.Any(t => t.UserId == _userInfo.Id))
.WhereIf(!string.IsNullOrEmpty(studyQuery.VisitPlanInfo), studyQuery.VisitPlanInfo.Contains('.') ? t => t.SubjectVisit.VisitNum.ToString().Contains(".") : t => t.SubjectVisit.VisitNum == decimal.Parse(studyQuery.VisitPlanInfo))
.WhereIf(!string.IsNullOrWhiteSpace(studyQuery.SubjectInfo), t => t.Subject.Code.Contains(studyQuery.SubjectInfo))
.Select(t => new UnionStudyMonitorModel()
{
TrialId = t.TrialId,
SiteId = t.SiteId,
SubjectId = t.SubjectId,
SubjectVisitId = t.SubjectVisitId,
VisitName = t.SubjectVisit.VisitName,
VisitNum = t.SubjectVisit.VisitNum,
SubjectCode = t.Subject.Code,
TrialSiteAliasName = t.TrialSite.TrialSiteAliasName,
TrialSiteCode = t.TrialSite.TrialSiteCode,
Uploader = t.Uploader.LastName + " / " + t.Uploader.LastName,
UploadTime = t.CreateTime,
IP = t.IP,
FileCount = t.FileCount,
FileSize = t.FileSize,
UploadFinishedTime = t.UploadFinishedTime,
UploadStartTime = t.UploadStartTime,
IsDicomReUpload = t.IsDicomReUpload,
StudyId = t.Id,
IsDicom = t.IsDicom,
StudyCode = t.DicomStudy.StudyCode
//DicomStudyCode = t.DicomStudy.StudyCode,
//NoneDicomCode = 0,
});
//.ProjectTo<UnionStudyViewDodel>(_mapper.ConfigurationProvider);
var nodeDicomStudyQuery = _repository.Where<StudyMonitor>(t => t.TrialId == studyQuery.TrialId && t.IsDicom == false)
.WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator, t => t.TrialSite.CRCUserList.Any(t => t.UserId == _userInfo.Id))
.WhereIf(!string.IsNullOrEmpty(studyQuery.VisitPlanInfo), studyQuery.VisitPlanInfo.Contains('.') ? t => t.SubjectVisit.VisitNum.ToString().Contains(".") : t => t.SubjectVisit.VisitNum == decimal.Parse(studyQuery.VisitPlanInfo))
.WhereIf(!string.IsNullOrWhiteSpace(studyQuery.SubjectInfo), t => t.Subject.Code.Contains(studyQuery.SubjectInfo))
.Select(t => new UnionStudyMonitorModel()
{
TrialId = t.TrialId,
SiteId = t.SiteId,
SubjectId = t.SubjectId,
SubjectVisitId = t.SubjectVisitId,
VisitName = t.SubjectVisit.VisitName,
VisitNum = t.SubjectVisit.VisitNum,
SubjectCode = t.Subject.Code,
TrialSiteAliasName = t.TrialSite.TrialSiteAliasName,
TrialSiteCode = t.TrialSite.TrialSiteCode,
Uploader = t.Uploader.LastName + " / " + t.Uploader.LastName,
UploadTime = t.CreateTime,
IP = t.IP,
FileCount = t.FileCount,
FileSize = t.FileSize,
UploadFinishedTime = t.UploadFinishedTime,
UploadStartTime = t.UploadStartTime,
IsDicomReUpload = t.IsDicomReUpload,
StudyId = t.Id,
IsDicom = t.IsDicom,
StudyCode = t.NoneDicomStudy.StudyCode
//DicomStudyCode = string.Empty,
//NoneDicomCode = t.NoneDicomStudy.Code,
});
//.ProjectTo<UnionStudyViewDodel>(_mapper.ConfigurationProvider);
var unionQuery = dicomStudyQuery.Union(nodeDicomStudyQuery)
.WhereIf(studyQuery.SubjectId != null, t => t.SubjectId == studyQuery.SubjectId)
.WhereIf(studyQuery.SubjectVisitId != null, t => t.SubjectId == studyQuery.SubjectVisitId)
.WhereIf(studyQuery.SiteId != null, t => t.SiteId == studyQuery.SiteId);
return await unionQuery.ToPagedListAsync(studyQuery.PageIndex, studyQuery.PageSize, string.IsNullOrEmpty(studyQuery.SortField) ? "UploadTime" : studyQuery.SortField, studyQuery.Asc);
}
/// <summary> 指定资源Id渲染Dicom检查的Jpeg预览图像 </summary>
/// <param name="studyId"> Dicom检查的Id </param>
[HttpGet("{studyId:guid}")]
public async Task<FileContentResult> Preview(Guid studyId)
{
string path = String.Empty;
DicomInstance dicomInstance = await _repository.FirstOrDefaultAsync<DicomInstance>(s => s.StudyId == studyId);
if (dicomInstance != null)
{
DicomStudy dicomStudy = await _repository.FirstOrDefaultAsync<DicomStudy>(s => s.Id == dicomInstance.StudyId);
if (dicomStudy != null)
{
path = _dicomFileStoreHelper.GetInstanceFilePath(dicomStudy, dicomInstance.SeriesId, dicomInstance.Id.ToString());
}
}
using (var sw = DicomRenderingHelper.RenderPreviewJpeg(path))
{
var bytes = new byte[sw.Length];
sw.Read(bytes, 0, bytes.Length);
sw.Close();
return new FileContentResult(bytes, "image/jpeg");
}
}
/// <summary>
/// 获取某个检查的关联检查列表(该受试者在这个想项目下的所有检查)
/// 点击检查检查列表中的一个检查获取对应的序列列表(调用之前的接口:/series/list/根据StudyId获取访视的序列列表
/// </summary>
/// <returns></returns>
[HttpGet("{subjectVisitId:guid}")]
[AllowAnonymous]
public IResponseOutput<List<RelationStudyDTO>> GetAllRelationStudyList(Guid subjectVisitId)
{
#region 废弃
//var studylist = _studyRepository.Where(u => u.SubjectVisitId == subjectVisitId && u.IsDeleted == false).Select(t => new { StudyId = t.Id, t.SubjectId, t.TrialId }).ToList();
//var subjectId = studylist.FirstOrDefault().SubjectId;
//var trialId = studylist.FirstOrDefault().TrialId;
//var studyIds = studylist.Select(t => t.StudyId).ToList();
//var query = from studyItem in _studyRepository.Where(u => u.SubjectId == subjectId
// && u.TrialId == trialId && u.IsDeleted == false &&
// !studyIds.Contains(u.Id)
// /* && u.Status != (int)StudyStatus.Abandon*/)
// join visitItem in _subjectVisitRepository.AsQueryable()
// on studyItem.SubjectVisitId equals visitItem.Id
// select new RelationStudyDTO
// {
// StudyId = studyItem.Id,
// StudyCode = studyItem.StudyCode,
// VisitName = visitItem.VisitName,
// Modalities = studyItem.Modalities,
// Description = studyItem.Description,
// SeriesCount = studyItem.SeriesCount
// };
#endregion
var studyInfo = _repository.Where<DicomStudy>(u => u.SubjectVisitId == subjectVisitId).Select(t => new { t.SubjectId, t.TrialId }).FirstOrDefault().IfNullThrowException();
var query = _repository.Where<DicomStudy>(t => t.SubjectVisitId != subjectVisitId && t.TrialId == studyInfo.TrialId && t.SubjectId == studyInfo.SubjectId)
.ProjectTo<RelationStudyDTO>(_mapper.ConfigurationProvider).ToList();
var list = query.OrderBy(u => u.VisitName).ThenBy(s => s.StudyCode).ToList();
return ResponseOutput.Ok(list);
}
/// <summary> 指定资源Id获取Dicom检查信息 </summary>
/// <param name="studyId"> Dicom检查的Id </param>
[HttpGet, Route("{studyId:guid}")]
public IResponseOutput<DicomStudyDTO> Item(Guid studyId)
{
return ResponseOutput.Ok(_mapper.Map<DicomStudyDTO>(_repository.Where<DicomStudy>().FirstOrDefault(s => s.Id == studyId)));
}
/// <summary>
/// 批量验证 检查是否可以上传 并告知原因
/// </summary>
[HttpPost]
public IResponseOutput<List<VerifyStudyUploadResult>> VerifyStudyAllowUpload(VerifyUploadOrReupload verifyInfo)
{
var trialInfo = _repository.Where<Trial>().FirstOrDefault(t => t.Id == verifyInfo.TrialId).IfNullThrowException();
var result = new List<VerifyStudyUploadResult>();
var visitList = _repository.Where<SubjectVisit>(t => t.SubjectId == verifyInfo.SubjectId).Select(t => new { t.VisitNum, t.EarliestScanDate, t.LatestScanDate, t.Id }).ToList();
verifyInfo.StudyInstanceUidList.ForEach(waitUploadItem =>
{
if (trialInfo.IsVerifyVisitImageDate)
{
//小于当前访视 最近的最早拍片日期
var before = visitList.Where(u => u.VisitNum < verifyInfo.VisitNum).Max(k => k.EarliestScanDate);
if (before != null && before > waitUploadItem.StudyDate)
{
result.Add(new VerifyStudyUploadResult() { ErrorMesseage = "当前访视检查时间不能小于该访视之前检查的时间,请核对检查数据是否有误", StudyInstanceUid = waitUploadItem.StudyInstanceUid });
return;
}
//大于当前访视 最近的最晚拍片日期
var after = visitList.Where(u => u.VisitNum > verifyInfo.VisitNum).Min(k => k.LatestScanDate);
if (after != null && after < waitUploadItem.StudyDate)
{
result.Add(new VerifyStudyUploadResult() { ErrorMesseage = "当前访视检查时间不能大于该访视之后的检查时间,请核对检查数据是否有误", StudyInstanceUid = waitUploadItem.StudyInstanceUid });
return;
}
}
var temp = VerifyStudyUpload(waitUploadItem.StudyInstanceUid, verifyInfo.TrialId, verifyInfo.SubjectVisitId, verifyInfo.SubjectId);
result.Add(temp);
});
return ResponseOutput.Ok(result);
}
private VerifyStudyUploadResult VerifyStudyUpload(string studyInstanceUid, Guid trialId, Guid currentSubjectVisitId, Guid SubjectId)
{
var result = new VerifyStudyUploadResult();
if (_provider.Exists("StudyUid_" + studyInstanceUid))
{
result.AllowUpload = false;
result.AllowReUpload = false;
result.StudyInstanceUid = studyInstanceUid;
result.ErrorMesseage = "当前有人正在上传归档该检查!";
return result;
}
if (_repository.Where<Subject>(t => t.Id == SubjectId).Select(t => t.Status).FirstOrDefault() == SubjectStatus.EndOfVisit)
{
result.AllowUpload = false;
result.AllowReUpload = false;
result.StudyInstanceUid = studyInstanceUid;
result.ErrorMesseage = "受试者访视结束,不允许上传!";
return result;
}
Guid expectStudyId = IdentifierHelper.CreateGuid(studyInstanceUid.Trim(), trialId.ToString());
var verifyStudyInfo = _repository.Where<DicomStudy>(t => t.TrialId == trialId && t.Id == expectStudyId).ProjectTo<VerifyStudyDto>(_mapper.ConfigurationProvider).FirstOrDefault();
result.StudyInfo = verifyStudyInfo;
//数据库不存在该检查 允许上传
if (verifyStudyInfo == null)
{
result.AllowUpload = true;
}
//数据库该项目有该检查 看是否支持重传
else
{
//是同一个受试者 支持重传
if (verifyStudyInfo.SubjectId == SubjectId && verifyStudyInfo.SubjectVisitId == currentSubjectVisitId)
{
result.AllowReUpload = true;
}
//不是同一个受试者
else
{
//有默认值,其实不用写,这里为了好理解
result.AllowUpload = false;
result.AllowReUpload = false;
result.ErrorMesseage = $"{ verifyStudyInfo.StudyTime }: This DICOM images have been uploaded and allocate to the {verifyStudyInfo.VisitName} of the subject {verifyStudyInfo.SubjectCode} (Study ID: {verifyStudyInfo.StudyCode}), which cannot continue to upload and assign it to others.";
}
}
result.StudyInstanceUid = studyInstanceUid;
return result;
}
}
}