185 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C#
		
	
	
			
		
		
	
	
			185 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C#
		
	
	
using IRaCIS.Core.Application.Contracts.Dicom.DTO;
 | 
						||
using IRaCIS.Core.Application.Helper;
 | 
						||
using IRaCIS.Core.Infrastructure.Extention;
 | 
						||
using Microsoft.AspNetCore.Authorization;
 | 
						||
using Microsoft.AspNetCore.Hosting;
 | 
						||
using Microsoft.AspNetCore.Mvc;
 | 
						||
 | 
						||
namespace IRaCIS.Core.Application.Services
 | 
						||
{
 | 
						||
    [ApiExplorerSettings(GroupName = "Image")]
 | 
						||
    [AllowAnonymous]
 | 
						||
    public class SeriesService(IRepository<DicomSeries> _seriesRepository,
 | 
						||
        IRepository<DicomInstance> _instanceRepository,
 | 
						||
        IRepository<SCPSeries> _scpSeriesRepository,
 | 
						||
        IRepository<SCPInstance> _scpInstanceRepository,
 | 
						||
        IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IWebHostEnvironment _hostEnvironment) : BaseService
 | 
						||
    {
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
        //医生读片那一块有耦合,关键序列   这里暂时留存
 | 
						||
        /// <summary> 指定资源Id,获取Dicom检查所属序列信息列表 </summary>
 | 
						||
        /// <param name="studyId"> Dicom检查的Id </param>
 | 
						||
        /// <param name="isReading"></param>
 | 
						||
        [HttpGet, Route("{studyId:guid}")]
 | 
						||
        public async Task<IResponseOutput<List<DicomSeriesDTO>>> List(Guid studyId, bool? isReading, bool? isPacs)
 | 
						||
        {
 | 
						||
            if (isPacs == true)
 | 
						||
            {
 | 
						||
                var seriesList = await _scpSeriesRepository.Where(s => s.StudyId == studyId).IgnoreQueryFilters()
 | 
						||
                   .OrderBy(s => s.SeriesNumber).ThenBy(s => s.SeriesTime).ThenBy(s => s.CreateTime)
 | 
						||
                 .ProjectTo<DicomSeriesDTO>(_mapper.ConfigurationProvider).ToListAsync();
 | 
						||
 | 
						||
                var instanceList = await _scpInstanceRepository.Where(s => s.StudyId == studyId).IgnoreQueryFilters()
 | 
						||
                     .OrderBy(t => t.SeriesId).ThenBy(t => t.InstanceNumber)
 | 
						||
                     .ThenBy(s => s.InstanceTime).ThenBy(s => s.CreateTime)
 | 
						||
                    .Select(t => new { t.SeriesId, t.Id, t.Path, t.NumberOfFrames, t.InstanceNumber, t.FileSize }).ToListAsync();//.GroupBy(u => u.SeriesId);
 | 
						||
 | 
						||
 | 
						||
                foreach (var series in seriesList)
 | 
						||
                {
 | 
						||
 | 
						||
                    series.InstanceInfoList = instanceList.Where(t => t.SeriesId == series.Id).OrderBy(t => t.InstanceNumber).Select(k =>
 | 
						||
                       new InstanceBasicInfo()
 | 
						||
                       {
 | 
						||
                           Id = k.Id,
 | 
						||
                           NumberOfFrames = k.NumberOfFrames,
 | 
						||
                           HtmlPath = string.Empty,
 | 
						||
                           Path = k.Path,
 | 
						||
                           InstanceNumber = k.InstanceNumber,
 | 
						||
                           IsReading = true,
 | 
						||
                           IsDeleted = false,
 | 
						||
                           FileSize = k.FileSize
 | 
						||
 | 
						||
                       }).ToList();
 | 
						||
 | 
						||
                    series.InstanceCount = series.InstanceInfoList.Count;
 | 
						||
                }
 | 
						||
 | 
						||
                return ResponseOutput.Ok(seriesList);
 | 
						||
 | 
						||
            }
 | 
						||
            else
 | 
						||
            {
 | 
						||
                //质控的时候,要标记序列,和instance 删除  ,所以要返回全部,但是 质控通过后,pm 进去看的时候要看过滤后的
 | 
						||
 | 
						||
                var qcAuditState = await _seriesRepository.Where(s => s.StudyId == studyId).Select(t => t.DicomStudy.SubjectVisit.AuditState).FirstOrDefaultAsync();
 | 
						||
 | 
						||
                //质控通过以后,预览过滤删除的   质控之前的不过滤
 | 
						||
                var isQCFinished = qcAuditState == AuditStateEnum.QCPassed;
 | 
						||
 | 
						||
                //断点
 | 
						||
                var seriesList = await _seriesRepository.Where(s => s.StudyId == studyId).IgnoreQueryFilters()
 | 
						||
                    .WhereIf(isQCFinished, t => t.IsDeleted == false)
 | 
						||
                    .WhereIf(isReading == true, t => t.IsReading == true)
 | 
						||
                    .OrderBy(s => s.SeriesNumber).ThenBy(s => s.SeriesTime).ThenBy(s => s.CreateTime)
 | 
						||
                  .ProjectTo<DicomSeriesDTO>(_mapper.ConfigurationProvider).ToListAsync();
 | 
						||
 | 
						||
                var instanceList = await _instanceRepository.Where(s => s.StudyId == studyId).IgnoreQueryFilters()
 | 
						||
                     .WhereIf(isQCFinished, t => t.IsDeleted == false)
 | 
						||
                     .WhereIf(isReading == true, t => t.IsReading == true)
 | 
						||
                     .OrderBy(t => t.SeriesId).ThenBy(t => t.InstanceNumber)
 | 
						||
                     .ThenBy(s => s.InstanceTime).ThenBy(s => s.CreateTime)
 | 
						||
                    .Select(t => new { t.SeriesId, t.Id, t.Path, t.NumberOfFrames, t.InstanceNumber, t.HtmlPath, t.IsReading, t.IsDeleted, t.FileSize }).ToListAsync();//.GroupBy(u => u.SeriesId);
 | 
						||
 | 
						||
 | 
						||
                foreach (var series in seriesList)
 | 
						||
                {
 | 
						||
 | 
						||
                    series.InstanceInfoList = instanceList.Where(t => t.SeriesId == series.Id).OrderBy(t => t.InstanceNumber).Select(k =>
 | 
						||
                       new InstanceBasicInfo()
 | 
						||
                       {
 | 
						||
                           Id = k.Id,
 | 
						||
                           NumberOfFrames = k.NumberOfFrames,
 | 
						||
                           HtmlPath = k.HtmlPath,
 | 
						||
                           Path = k.Path,
 | 
						||
                           InstanceNumber = k.InstanceNumber,
 | 
						||
                           IsReading = k.IsReading,
 | 
						||
                           IsDeleted = k.IsDeleted,
 | 
						||
                           FileSize = k.FileSize
 | 
						||
 | 
						||
                       }).ToList();
 | 
						||
 | 
						||
                    series.InstanceCount = series.InstanceInfoList.Count;
 | 
						||
                }
 | 
						||
 | 
						||
                return ResponseOutput.Ok(seriesList);
 | 
						||
 | 
						||
            }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
        /// <summary> 指定资源Id,渲染Dicom序列的Jpeg预览图像 </summary>
 | 
						||
        /// <param name="seriesId"> Dicom序列的Id </param>
 | 
						||
        [HttpGet, Route("{seriesId:guid}")]
 | 
						||
        [AllowAnonymous]
 | 
						||
        public async Task<FileContentResult> Preview(Guid seriesId)
 | 
						||
        {
 | 
						||
            string path = string.Empty;
 | 
						||
 | 
						||
            path = (await _instanceRepository.Where(s => s.SeriesId == seriesId).Select(t => t.Path).FirstOrDefaultAsync()).IfNullThrowException();
 | 
						||
 | 
						||
            #region 切换磁盘存储之前
 | 
						||
            //var physicalPath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, path);
 | 
						||
 | 
						||
            #endregion
 | 
						||
 | 
						||
            #region 切换磁盘存储后
 | 
						||
 | 
						||
            var physicalPath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, path);
 | 
						||
 | 
						||
            //不存在,去其他路径找
 | 
						||
            if (!File.Exists(physicalPath))
 | 
						||
            {
 | 
						||
                //找到所有磁盘
 | 
						||
                var drives = DriveInfo.GetDrives()
 | 
						||
                         .Where(d => d.DriveType == DriveType.Fixed && d.IsReady)
 | 
						||
                         //剩余空间最多的
 | 
						||
                         .OrderByDescending(d => d.AvailableFreeSpace)
 | 
						||
 | 
						||
                         //存储空间相同,则按照按照总空间从大到小排序
 | 
						||
                         .ThenByDescending(d => d.TotalSize - d.TotalFreeSpace)
 | 
						||
                         .Select(d => d.RootDirectory.FullName)
 | 
						||
                         .ToList();
 | 
						||
 | 
						||
 | 
						||
                foreach (var drive in drives)
 | 
						||
                {
 | 
						||
                    physicalPath = Path.Combine(drive, _hostEnvironment.EnvironmentName, path.Trim('/'));
 | 
						||
 | 
						||
                    if (File.Exists(physicalPath))
 | 
						||
                    {
 | 
						||
                        break;
 | 
						||
                    }
 | 
						||
                }
 | 
						||
            }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
            #endregion
 | 
						||
 | 
						||
 | 
						||
 | 
						||
            using (var sw = ImageHelper.RenderPreviewJpeg(physicalPath))
 | 
						||
            {
 | 
						||
                var bytes = new byte[sw.Length];
 | 
						||
                sw.Read(bytes, 0, bytes.Length);
 | 
						||
                sw.Close();
 | 
						||
                return new FileContentResult(bytes, "image/jpeg");
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
    }
 | 
						||
} |