//-------------------------------------------------------------------- // 此代码由T4模板自动生成 byzhouhang 20210918 // 生成时间 2021-12-06 10:54:55 // 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 //-------------------------------------------------------------------- using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Http; using IRaCIS.Core.Domain.Share; using SharpCompress.Archives; using IRaCIS.Core.Application.Filter; using IRaCIS.Core.Application.Service.Inspection.Interface; using Nito.AsyncEx; using IRaCIS.Application.Interfaces; using IRaCIS.Core.Infrastructure; using Microsoft.Extensions.Logging; using System.ComponentModel.DataAnnotations; using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.Service.Verify; using Microsoft.AspNetCore.Authorization; using IRaCIS.Core.Application.Auth; namespace IRaCIS.Core.Application.Contracts { /// /// NoneDicomStudyService /// [ApiExplorerSettings(GroupName = "Image")] public class NoneDicomStudyService : BaseService, INoneDicomStudyService { private readonly IRepository _noneDicomStudyRepository; private readonly IHttpContextAccessor _httpContext; private readonly IDictionaryService _dictionaryService; private readonly IInspectionService _inspectionService; private readonly IRepository _studyMonitorRepository; private readonly IRepository _noneDicomStudyFileRepository; private readonly IRepository _subjectVisitRepository; private readonly AsyncLock _mutex = new AsyncLock(); private readonly ILogger _logger; public NoneDicomStudyService(IRepository noneDicomStudyRepository, IHttpContextAccessor httpContext, IDictionaryService dictionaryService, IInspectionService inspectionService, IRepository studyMonitorRepository, IRepository noneDicomStudyFileRepository, IRepository subjectVisitRepository, ILogger logger) { _noneDicomStudyRepository = noneDicomStudyRepository; this._httpContext = httpContext; this._dictionaryService = dictionaryService; this._inspectionService = inspectionService; this._studyMonitorRepository = studyMonitorRepository; _noneDicomStudyFileRepository = noneDicomStudyFileRepository; this._subjectVisitRepository = subjectVisitRepository; _logger = logger; } [HttpGet] public async Task> GetNoneDicomStudyList( [FromQuery,NotDefault] Guid subjectVisitId,Guid? nonedicomStudyId) { var noneDicomStudyQueryable = _noneDicomStudyRepository.Where(t => t.SubjectVisitId == subjectVisitId).WhereIf(nonedicomStudyId!=null , t => t.Id== nonedicomStudyId) .ProjectTo(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken }); return await noneDicomStudyQueryable.ToListAsync(); } [UnitOfWork] [TypeFilter(typeof(TrialResourceFilter))] public async Task> AddOrUpdateNoneDicomStudy(NoneDicomStudyAddOrEdit addOrEditNoneDicomStudy) { await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, addOrEditNoneDicomStudy.SubjectVisitId); await QCCommonVerify.VerifyStudyImageDataAsync(_repository, addOrEditNoneDicomStudy.SubjectId, addOrEditNoneDicomStudy.SubjectVisitId, addOrEditNoneDicomStudy.ImageDate); NoneDicomStudy? optEntity = null; using (await _mutex.LockAsync()) { if (addOrEditNoneDicomStudy.Id == Guid.Empty || addOrEditNoneDicomStudy.Id == null) { //默认会是0 var code = await _noneDicomStudyRepository.Where(t => t.TrialId == addOrEditNoneDicomStudy.TrialId).Select(x => x.Code).DefaultIfEmpty().MaxAsync(); addOrEditNoneDicomStudy.Code = code + 1; optEntity = await _noneDicomStudyRepository.InsertFromDTOAsync(addOrEditNoneDicomStudy); optEntity.StudyCode = "NST" + optEntity.Code.ToString("D5"); } else { optEntity = await _noneDicomStudyRepository.UpdateFromDTOAsync(addOrEditNoneDicomStudy); } await _noneDicomStudyRepository.SaveChangesAsync(); } NoneDicomStudyAddReturnDto noneDicom = new NoneDicomStudyAddReturnDto() { StudyCode = optEntity.StudyCode, Id = optEntity.Id }; return ResponseOutput.Ok(noneDicom); } [TypeFilter(typeof(TrialResourceFilter))] [HttpDelete("{trialId:guid}/{subjectVisitId:guid}/{noneDicomStudyId:guid}")] public async Task DeleteNoneDicomStudy(Guid noneDicomStudyId, Guid subjectVisitId) { //提交了 但是IQC同意的时候 是可以删除的 | 普通提交后也不能删除 await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository,_userInfo, subjectVisitId); await _noneDicomStudyRepository.DeleteFromQueryAsync(noneDicomStudyId); await _noneDicomStudyFileRepository.DeleteFromQueryAsync(t => t.NoneDicomStudyId == noneDicomStudyId); //确认需求 不删除 //await _studyMonitorRepository.BatchDeleteNoTrackingAsync(t => t.StudyId == noneDicomStudyId); await _noneDicomStudyRepository.SaveChangesAsync(); return ResponseOutput.Ok(); } [HttpDelete("{trialId:guid}/{subjectVisitId:guid}/{noneDicomStudyFileId:guid}")] [TypeFilter(typeof(TrialResourceFilter))] public async Task DeleteNoneDicomStudyFile(Guid noneDicomStudyFileId, Guid subjectVisitId) { //提交了 但是IQC同意的时候 是可以删除的 | 普通提交后也不能删除 await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId); var success = await _noneDicomStudyFileRepository.DeleteFromQueryAsync(t => t.Id == noneDicomStudyFileId, true); return ResponseOutput.Ok(); } /// /// 非Dicom检查 文件列表 /// /// /// [HttpGet("{noneDicomStudyId:guid}")] public async Task> GetNoneDicomStudyFileList(Guid noneDicomStudyId) { return await _noneDicomStudyFileRepository.Where(t => t.NoneDicomStudyId == noneDicomStudyId) .ProjectTo(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken }).ToListAsync(); } [HttpGet("{subjectVisitId:guid}")] public async Task> GetVisitNoneDicomStudyFileList(Guid subjectVisitId) { return await _repository.Where(t => t.NoneDicomStudy.SubjectVisitId == subjectVisitId) .ProjectTo(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken }).ToListAsync(); } /// /// 上传非Dicom 文件 支持压缩包 /// /// /// /// /// //[DisableRequestSizeLimit] [RequestSizeLimit(1_073_741_824)] [HttpPost("{trialId:guid}/{subjectVisitId:guid}/{noneDicomStudyId:guid}")] [TypeFilter(typeof(TrialResourceFilter))] [Authorize(Policy = IRaCISPolicy.CRC)] public async Task UploadNoneDicomFile(IFormCollection formCollection, Guid subjectVisitId, Guid noneDicomStudyId) { await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId); var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment); //上传根路径 var _fileStorePath = Path.Combine(rootPath, StaticData.TrialDataFolder); var sv = (await _repository.Where(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, fileName) = FileStoreHelper.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 = fileName, Path = relativePath, NoneDicomStudyId = noneDicomStudyId }); } } // 上传非Dicom 后 将状态改为待提交 分为普通上传 和QC后重传 普通上传时才改为待提交 await _subjectVisitRepository.UpdatePartialFromQueryAsync(t => t.Id == subjectVisitId && t.SubmitState == SubmitStateEnum.None, u => new SubjectVisit() { SubmitState = SubmitStateEnum.ToSubmit }); var studyCode = await _noneDicomStudyRepository.Where(t => t.Id == noneDicomStudyId).Select(t => t.StudyCode).FirstOrDefaultAsync(); await _studyMonitorRepository.AddAsync(new StudyMonitor() { FileCount = formCollection.Files.Count, FileSize = formCollection.Files.Sum(t => t.Length), IsDicom = false, IsDicomReUpload = false, StudyId = noneDicomStudyId, StudyCode = studyCode, UploadStartTime = startTime, UploadFinishedTime = DateTime.Now, IP = _userInfo.IP, TrialId = sv.TrialId, SiteId = sv.SiteId, SubjectId = sv.SubjectId, SubjectVisitId = subjectVisitId, }); await _noneDicomStudyFileRepository.SaveChangesAsync(); return ResponseOutput.Ok(/*list*/); } private async void DealCompressFile(IArchiveEntry entry, dynamic sv, Guid subjectVisitId, Guid noneDicomStudyId, string uploadFolderPath) { var (trustedFileNameForFileStorage, fileName) = FileStoreHelper.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); await _noneDicomStudyFileRepository.AddAsync(new NoneDicomStudyFile() { FileName = fileName, Path = relativePath, NoneDicomStudyId = noneDicomStudyId }); } } }