263 lines
12 KiB
C#
263 lines
12 KiB
C#
//--------------------------------------------------------------------
|
|
// 此代码由T4模板自动生成 byzhouhang 20210918
|
|
// 生成时间 2021-12-06 10:54:55
|
|
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
|
//--------------------------------------------------------------------
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.AspNetCore.Hosting;
|
|
using Microsoft.AspNetCore.Http;
|
|
using IRaCIS.Core.Domain.Share;
|
|
using SharpCompress.Archives;
|
|
using IRaCIS.Core.Application.Filter;
|
|
using IRaCIS.Core.Infra.EFCore;
|
|
|
|
namespace IRaCIS.Core.Application.Contracts
|
|
{
|
|
/// <summary>
|
|
/// NoneDicomStudyService
|
|
/// </summary>
|
|
[ApiExplorerSettings(GroupName = "Image")]
|
|
public class NoneDicomStudyService : BaseService, INoneDicomStudyService
|
|
{
|
|
private readonly IRepository<NoneDicomStudy> _noneDicomStudyRepository;
|
|
private readonly IRepository<NoneDicomStudyFile> _noneDicomStudyFileRepository;
|
|
|
|
public NoneDicomStudyService(IRepository<NoneDicomStudy> noneDicomStudyRepository,IRepository<NoneDicomStudyFile> noneDicomStudyFileRepository)
|
|
{
|
|
_noneDicomStudyRepository = noneDicomStudyRepository;
|
|
_noneDicomStudyFileRepository = noneDicomStudyFileRepository;
|
|
}
|
|
|
|
|
|
[HttpGet("{subjectVisitId:guid}")]
|
|
public async Task<List<NoneDicomStudyView>> GetNoneDicomStudyList(Guid subjectVisitId)
|
|
{
|
|
|
|
var noneDicomStudyQueryable = _noneDicomStudyRepository.Where(t => t.SubjectVisitId == subjectVisitId)
|
|
.ProjectTo<NoneDicomStudyView>(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken });
|
|
|
|
return await noneDicomStudyQueryable.ToListAsync();
|
|
}
|
|
|
|
[UnitOfWork]
|
|
[TypeFilter(typeof(TrialResourceFilter))]
|
|
public async Task<IResponseOutput> AddOrUpdateNoneDicomStudy(NoneDicomStudyAddOrEdit addOrEditNoneDicomStudy)
|
|
{
|
|
var entity = await _noneDicomStudyRepository.InsertOrUpdateAsync(addOrEditNoneDicomStudy, false);
|
|
|
|
if (_repository.Entry(entity).State == Microsoft.EntityFrameworkCore.EntityState.Added)
|
|
{
|
|
entity.Code = _noneDicomStudyRepository.Where(t => t.TrialId == addOrEditNoneDicomStudy.TrialId).Select(t => t.Code).DefaultIfEmpty().Max() + 1;
|
|
}
|
|
|
|
await _repository.SaveChangesAsync();
|
|
|
|
var svTime = _repository.Where<SubjectVisit>(t => t.Id == addOrEditNoneDicomStudy.SubjectVisitId).Select(t => new
|
|
{
|
|
DicomStudyMinStudyTime = t.StudyList.Min(t => (DateTime?)t.StudyTime),
|
|
DicomStudyMaxStudyTime = t.StudyList.Max(t => (DateTime?)t.StudyTime),
|
|
NoneDicomStudyMinStudyTime = t.NoneDicomStudyList.Min(t => (DateTime?)t.ImageDate),
|
|
NoneDicomStudyMaxStudyTime = t.NoneDicomStudyList.Max(t => (DateTime?)t.ImageDate)
|
|
}).FirstOrDefault().IfNullThrowException();
|
|
|
|
var minArray = new DateTime?[] { svTime.DicomStudyMinStudyTime, svTime.NoneDicomStudyMinStudyTime, addOrEditNoneDicomStudy.ImageDate };
|
|
var maxArray = new DateTime?[] { svTime.DicomStudyMaxStudyTime, svTime.NoneDicomStudyMaxStudyTime, addOrEditNoneDicomStudy.ImageDate };
|
|
|
|
await _repository.UpdateFromQueryAsync<SubjectVisit>(t => t.Id == addOrEditNoneDicomStudy.SubjectVisitId, u => new SubjectVisit()
|
|
{
|
|
VisitExecuted = VisitExecutedEnum.Executed,
|
|
|
|
EarliestScanDate = minArray.Min(),
|
|
|
|
LatestScanDate = maxArray.Max()
|
|
});
|
|
|
|
await _repository.SaveChangesAsync();
|
|
|
|
|
|
return ResponseOutput.Ok(entity.Id);
|
|
|
|
}
|
|
|
|
[TypeFilter(typeof(TrialResourceFilter))]
|
|
[HttpDelete("{noneDicomStudyId:guid}/{trialId:guid}")]
|
|
public async Task<IResponseOutput> DeleteNoneDicomStudy(Guid noneDicomStudyId)
|
|
{
|
|
var noneDicomStudy = await _noneDicomStudyRepository.FirstOrDefaultAsync(t => t.Id == noneDicomStudyId);
|
|
|
|
if (noneDicomStudy == null) return Null404NotFound(noneDicomStudy);
|
|
|
|
await _noneDicomStudyRepository.DeleteFromQueryAsync(t => t.Id == noneDicomStudyId);
|
|
await _noneDicomStudyFileRepository.DeleteFromQueryAsync(t => t.NoneDicomStudyId == noneDicomStudyId);
|
|
|
|
var svTime = await _repository.Where<SubjectVisit>(t => t.Id == noneDicomStudy.SubjectVisitId).Select(t => new
|
|
{
|
|
DicomStudyMinStudyTime = t.StudyList.Min(t => (DateTime?)t.StudyTime),
|
|
DicomStudyMaxStudyTime = t.StudyList.Max(t => (DateTime?)t.StudyTime),
|
|
NoneDicomStudyMinStudyTime = t.NoneDicomStudyList.Min(t => (DateTime?)t.ImageDate),
|
|
NoneDicomStudyMaxStudyTime = t.NoneDicomStudyList.Max(t => (DateTime?)t.ImageDate)
|
|
}).FirstOrDefaultAsync().IfNullThrowException();
|
|
|
|
var minArray = new DateTime?[] { svTime.DicomStudyMinStudyTime, svTime.NoneDicomStudyMinStudyTime };
|
|
var maxArray = new DateTime?[] { svTime.DicomStudyMaxStudyTime, svTime.NoneDicomStudyMaxStudyTime };
|
|
|
|
await _repository.UpdateFromQueryAsync<SubjectVisit>(t => t.Id == noneDicomStudy.SubjectVisitId, u => new SubjectVisit()
|
|
{
|
|
EarliestScanDate = minArray.Min(),
|
|
|
|
LatestScanDate = maxArray.Max()
|
|
});
|
|
return ResponseOutput.Ok();
|
|
}
|
|
|
|
|
|
[HttpDelete("{noneDicomStudyFileId:guid}")]
|
|
public async Task<IResponseOutput> DeleteNoneDicomStudyFile(Guid noneDicomStudyFileId)
|
|
{
|
|
var subjectVisitId = await _noneDicomStudyFileRepository.Where(t=>t.Id== noneDicomStudyFileId).Select(t => t.NoneDicomStudy.SubjectVisitId).FirstOrDefaultAsync();
|
|
|
|
var success = await _noneDicomStudyFileRepository.DeleteFromQueryAsync(t => t.Id == noneDicomStudyFileId);
|
|
|
|
//如果既没有 dicom数据 也没有非dicom 文件 那么提交状态变更回去
|
|
if (await _repository.CountAsync<DicomStudy>(t => t.SubjectVisitId == subjectVisitId) == 0 && await _repository.CountAsync<NoneDicomStudyFile>(t => t.NoneDicomStudy.SubjectVisitId == subjectVisitId) == 0)
|
|
{
|
|
await _repository.UpdateFromQueryAsync<SubjectVisit>(t => t.Id == subjectVisitId && t.SubmitState == SubmitStateEnum.ToSubmit, u => new SubjectVisit() { VisitExecuted = 0, SubmitState = SubmitStateEnum.None });
|
|
}
|
|
|
|
return ResponseOutput.Ok();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 非Dicom检查 文件列表
|
|
/// </summary>
|
|
/// <param name="noneDicomStudyId"></param>
|
|
/// <returns></returns>
|
|
[HttpGet("{noneDicomStudyId:guid}")]
|
|
public async Task<List<NoneDicomStudyFileView>> GetNoneDicomStudyFileList(Guid noneDicomStudyId)
|
|
{
|
|
return await _noneDicomStudyFileRepository.Where(t => t.NoneDicomStudyId == noneDicomStudyId)
|
|
.ProjectTo<NoneDicomStudyFileView>(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken }).ToListAsync();
|
|
}
|
|
|
|
[HttpGet("{subjectVisitId:guid}")]
|
|
public async Task<List<NoneDicomStudyFileView>> GetVisitNoneDicomStudyFileList(Guid subjectVisitId)
|
|
{
|
|
return await _repository.Where<NoneDicomStudyFile>(t => t.NoneDicomStudy.SubjectVisitId == subjectVisitId).ProjectTo<NoneDicomStudyFileView>(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken }).ToListAsync();
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 上传非Dicom 文件 支持压缩包
|
|
/// </summary>
|
|
/// <param name="formCollection"></param>
|
|
/// <param name="subjectVisitId"></param>
|
|
/// <param name="noneDicomStudyId"></param>
|
|
/// <param name="_hostEnvironment"></param>
|
|
/// <returns></returns>
|
|
//[DisableRequestSizeLimit]
|
|
[RequestSizeLimit(1_073_741_824)]
|
|
[HttpPost("{noneDicomStudyId:guid}/{subjectVisitId:guid}")]
|
|
public async Task<IResponseOutput> UploadNoneDicomFile(IFormCollection formCollection, Guid subjectVisitId, Guid noneDicomStudyId, [FromServices] IWebHostEnvironment _hostEnvironment)
|
|
{
|
|
var rootPath = Directory.GetParent(_hostEnvironment.ContentRootPath.TrimEnd('\\')).IfNullThrowException().FullName;
|
|
|
|
//上传根路径
|
|
var _fileStorePath = Path.Combine(rootPath, StaticData.TrialDataFolder);
|
|
|
|
var sv = await _repository.Where<SubjectVisit>(t => t.Id == subjectVisitId).Select(t => new { t.TrialId, t.SiteId, t.SubjectId }).FirstOrDefaultAsync().IfNullThrowConvertException();
|
|
|
|
string uploadFolderPath = Path.Combine(_fileStorePath, sv.TrialId.ToString(), sv.SiteId.ToString(), sv.SubjectId.ToString(), subjectVisitId.ToString(), StaticData.NoneDicomFolder);
|
|
|
|
if (!Directory.Exists(uploadFolderPath))
|
|
{
|
|
Directory.CreateDirectory(uploadFolderPath);
|
|
}
|
|
|
|
var startTime = DateTime.Now;
|
|
|
|
foreach (IFormFile file in formCollection.Files)
|
|
{
|
|
if (file.FileName.Contains(".Zip", StringComparison.OrdinalIgnoreCase) || file.FileName.Contains(".rar", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
var archive = ArchiveFactory.Open(file.OpenReadStream());
|
|
|
|
foreach (var entry in archive.Entries)
|
|
{
|
|
if (!entry.IsDirectory)
|
|
{
|
|
DealCompressFile(entry, sv, subjectVisitId, noneDicomStudyId, uploadFolderPath);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var trustedFileNameForFileStorage = GetStoreFileName(file.FileName);
|
|
var relativePath = $"/{StaticData.TrialDataFolder}/{sv.TrialId}/{sv.SiteId}/{sv.SubjectId}/{subjectVisitId}/{StaticData.NoneDicomFolder}/{trustedFileNameForFileStorage}";
|
|
|
|
var filePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
|
|
|
|
using (FileStream fs = System.IO.File.Create(filePath))
|
|
{
|
|
await file.CopyToAsync(fs);
|
|
await fs.FlushAsync();
|
|
}
|
|
|
|
await _noneDicomStudyFileRepository.AddAsync(new NoneDicomStudyFile() { FileName = file.FileName, Path = relativePath, NoneDicomStudyId = noneDicomStudyId });
|
|
|
|
}
|
|
}
|
|
|
|
// 上传非Dicom 后 将状态改为待提交 分为普通上传 和QC后重传 普通上传时才改为待提交
|
|
await _repository.UpdateFromQueryAsync<SubjectVisit>(t => t.Id == subjectVisitId && t.SubmitState == SubmitStateEnum.None, u => new SubjectVisit() { SubmitState = SubmitStateEnum.ToSubmit });
|
|
|
|
await _repository.AddAsync(new StudyMonitor()
|
|
{
|
|
FileCount = formCollection.Files.Count, FileSize = formCollection.Files.Sum(t => t.Length), IsDicom = false,
|
|
IsDicomReUpload = false, StudyId = noneDicomStudyId,
|
|
UploadStartTime = startTime, UploadFinishedTime = DateTime.Now, IP = _userInfo.IP,
|
|
TrialId = sv.TrialId,
|
|
SiteId = sv.SiteId,
|
|
SubjectId = sv.SubjectId,
|
|
SubjectVisitId = subjectVisitId,
|
|
});
|
|
|
|
await _repository.SaveChangesAsync();
|
|
|
|
return ResponseOutput.Ok(/*list*/);
|
|
}
|
|
|
|
private string GetStoreFileName(string fileName)
|
|
{
|
|
var realName = fileName;
|
|
|
|
var fileNameEX = Path.GetExtension(realName);
|
|
|
|
var trustedFileNameForFileStorage = Guid.NewGuid().ToString() + fileNameEX;
|
|
|
|
return trustedFileNameForFileStorage;
|
|
}
|
|
|
|
private async void DealCompressFile(IArchiveEntry entry, dynamic sv, Guid subjectVisitId, Guid noneDicomStudyId, string uploadFolderPath)
|
|
{
|
|
var trustedFileNameForFileStorage = GetStoreFileName(entry.Key);
|
|
|
|
var relativePath = $"/{StaticData.TrialDataFolder}/{sv.TrialId}/{sv.SiteId}/{sv.SubjectId}/{subjectVisitId}/{StaticData.NoneDicomFolder}/{trustedFileNameForFileStorage}";
|
|
|
|
var filePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
|
|
|
|
entry.WriteToFile(filePath);
|
|
|
|
var fileName = string.Empty;
|
|
|
|
if (entry.Key.Contains("\\"))
|
|
{
|
|
fileName = entry.Key.Split("\\").Last();
|
|
}
|
|
|
|
|
|
await _repository.AddAsync(new NoneDicomStudyFile() { FileName = fileName, Path = relativePath, NoneDicomStudyId = noneDicomStudyId });
|
|
}
|
|
|
|
}
|
|
}
|