撤销遮盖接口初步完成
continuous-integration/drone/push Build is passing Details

Test_IRC_Net10
hang 2026-04-21 10:37:01 +08:00
parent 8259e2fea3
commit 6bb3be17ee
8 changed files with 22198 additions and 11 deletions

View File

@ -1584,6 +1584,10 @@ public class OSSService(IOptionsMonitor<ObjectStoreServiceOptions> options,
/// <returns></returns> /// <returns></returns>
public async Task DeleteFromPrefix(string prefix, bool isCache = false) public async Task DeleteFromPrefix(string prefix, bool isCache = false)
{ {
if (prefix.StartsWith("/"))
{
prefix = prefix.TrimStart("/");
}
//打开了同步的,删除的时候,一起删除 //打开了同步的,删除的时候,一起删除
if (ObjectStoreServiceOptions.IsOpenStoreSync && ObjectStoreServiceOptions.SyncConfigList.Any(t => t.IsOpenSync)) if (ObjectStoreServiceOptions.IsOpenStoreSync && ObjectStoreServiceOptions.SyncConfigList.Any(t => t.IsOpenSync))

View File

@ -2967,10 +2967,17 @@
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.ImageAndDoc.StudyService.StudyMaskImage(IRaCIS.Core.Application.Contracts.StudyMaskImageCommand)"> <member name="M:IRaCIS.Core.Application.Service.ImageAndDoc.StudyService.StudyMaskImage(IRaCIS.Core.Application.Contracts.StudyMaskImageCommand)">
<summary> <summary>
标注遮盖影像 标注遮盖影像 路径后面加了.MaskImage 就是遮盖的新路径
</summary> </summary>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.ImageAndDoc.StudyService.StudyUndoMaskImage(IRaCIS.Core.Application.Contracts.StudyUndoMaskImageCommand)">
<summary>
撤销遮盖的影像,可以单张,也可以整个序列
</summary>
<param name="inCommand"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ImageAndDoc.StudyService.Preview(System.Guid)"> <member name="M:IRaCIS.Core.Application.Service.ImageAndDoc.StudyService.Preview(System.Guid)">
<summary> 指定资源Id渲染Dicom检查的Jpeg预览图像 </summary> <summary> 指定资源Id渲染Dicom检查的Jpeg预览图像 </summary>
<param name="studyId"> Dicom检查的Id </param> <param name="studyId"> Dicom检查的Id </param>
@ -17248,17 +17255,17 @@
</member> </member>
<member name="F:IRaCIS.Core.Application.ViewModel.AccessToDialogueEnum.Question"> <member name="F:IRaCIS.Core.Application.ViewModel.AccessToDialogueEnum.Question">
<summary> <summary>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> 质疑
</summary> </summary>
</member> </member>
<member name="F:IRaCIS.Core.Application.ViewModel.AccessToDialogueEnum.Consistency"> <member name="F:IRaCIS.Core.Application.ViewModel.AccessToDialogueEnum.Consistency">
<summary> <summary>
һ<EFBFBD><EFBFBD><EFBFBD>Ժ˲<EFBFBD> 一致性核查
</summary> </summary>
</member> </member>
<member name="T:IRaCIS.Core.Application.ViewModel.CopyFrontAuditConfigItemDto"> <member name="T:IRaCIS.Core.Application.ViewModel.CopyFrontAuditConfigItemDto">
<summary> <summary>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> 复制
</summary> </summary>
</member> </member>
<member name="T:IRaCIS.Core.Application.ViewModel.SystemNoticeView"> <member name="T:IRaCIS.Core.Application.ViewModel.SystemNoticeView">

View File

@ -1077,4 +1077,18 @@ namespace IRaCIS.Core.Application.Contracts
} }
public class StudyUndoMaskImageCommand
{
public Guid? SeriesId { get; set; }
public List<Guid>? InstanceIdList { get; set; }
}
public class InstanceIdPath
{
public Guid Id { get; set; }
public string Path { get; set; }
}
} }

View File

@ -7,6 +7,7 @@ using IRaCIS.Core.Infrastructure;
using Medallion.Threading; using Medallion.Threading;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using SkiaSharp;
using System.Drawing; using System.Drawing;
using ZiggyCreatures.Caching.Fusion; using ZiggyCreatures.Caching.Fusion;
@ -68,7 +69,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
/// <summary> /// <summary>
/// 标注遮盖影像 /// 标注遮盖影像 路径后面加了.MaskImage 就是遮盖的新路径
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public async Task<IResponseOutput> StudyMaskImage(StudyMaskImageCommand inCommand) public async Task<IResponseOutput> StudyMaskImage(StudyMaskImageCommand inCommand)
@ -78,20 +79,25 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
return ResponseOutput.NotOk("SeriesId and InstanceIdList can not both be null"); return ResponseOutput.NotOk("SeriesId and InstanceIdList can not both be null");
} }
var instancePathList = new List<string>();
var idPathList = new List<InstanceIdPath>();
if (inCommand.SeriesId == null && inCommand.InstanceIdList != null) if (inCommand.SeriesId == null && inCommand.InstanceIdList != null)
{ {
instancePathList = await _dicomInstanceRepository.Where(t => inCommand.InstanceIdList.Contains(t.Id)).Select(t => t.Path).ToListAsync(); idPathList = await _dicomInstanceRepository.Where(t => inCommand.InstanceIdList.Contains(t.Id)).Select(t => new InstanceIdPath { Id = t.Id, Path = t.Path }).ToListAsync();
} }
else else
{ {
instancePathList = await _dicomInstanceRepository.Where(t => t.SeriesId == inCommand.SeriesId).Select(t => t.Path).ToListAsync(); idPathList = await _dicomInstanceRepository.Where(t => t.SeriesId == inCommand.SeriesId).Select(t => new InstanceIdPath { Id = t.Id, Path = t.Path }).ToListAsync();
} }
foreach (var path in instancePathList) var errorPathList = new List<string>();
foreach (var item in idPathList)
{ {
var path = item.Path;
try try
{ {
var inputStream = await _oSSService.GetStreamFromOSSAsync(path); var inputStream = await _oSSService.GetStreamFromOSSAsync(path);
@ -99,21 +105,79 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
var outPutStream = await DicomPixelMasker.MaskAsync(inputStream, inCommand.MaskRegionList); var outPutStream = await DicomPixelMasker.MaskAsync(inputStream, inCommand.MaskRegionList);
var prefix = path.Substring(1, path.LastIndexOf('/') - 1); var prefix = path.Substring(1, path.LastIndexOf('/') - 1);
await _oSSService.UploadToOSSAsync(outPutStream, prefix, $"MaskImage_{Path.GetFileName(path)}");
var maskPath = $"{Path.GetFileName(path)}.MaskImage";
//清理缓存的里面的遮盖图,多次遮盖同一张图时,清除缓存很重要
await _oSSService.DeleteFromPrefix(maskPath, true);
await _oSSService.UploadToOSSAsync(outPutStream, prefix, maskPath);
await _dicomInstanceRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Id, u => new DicomInstance() { IsMasked = true });
} }
catch (Exception ex) catch (Exception ex)
{ {
errorPathList.Add(path);
Log.Logger.Error(ex, $"StudyMaskImage Error for InstanceIdList Path:{path} {ex.Message}"); Log.Logger.Error(ex, $"StudyMaskImage Error for InstanceIdList Path:{path} {ex.Message}");
} }
} }
await _dicomInstanceRepository.SaveChangesAsync();
return ResponseOutput.Ok(errorPathList);
}
/// <summary>
/// 撤销遮盖的影像,可以单张,也可以整个序列
/// </summary>
/// <param name="inCommand"></param>
/// <returns></returns>
public async Task<IResponseOutput> StudyUndoMaskImage(StudyUndoMaskImageCommand inCommand)
{
if (inCommand.SeriesId == null && inCommand.InstanceIdList == null)
{
return ResponseOutput.NotOk("SeriesId and InstanceIdList can not both be null");
}
var idPathList = new List<InstanceIdPath>();
if (inCommand.SeriesId == null && inCommand.InstanceIdList != null)
{
idPathList = await _dicomInstanceRepository.Where(t => inCommand.InstanceIdList.Contains(t.Id)).Select(t => new InstanceIdPath { Id = t.Id, Path = t.Path }).ToListAsync();
}
else
{
idPathList = await _dicomInstanceRepository.Where(t => t.SeriesId == inCommand.SeriesId).Select(t => new InstanceIdPath { Id = t.Id, Path = t.Path }).ToListAsync();
}
foreach (var item in idPathList)
{
if (item.Path.EndsWith(".MaskImage"))
{
var newPath = item.Path[..^10];
//await _oSSService.DeleteFromPrefix(newPath, true);
await _dicomInstanceRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Id, u => new DicomInstance() { Path = newPath, IsMasked = false });
}
}
await _dicomInstanceRepository.SaveChangesAsync();
return ResponseOutput.Ok(); return ResponseOutput.Ok();
} }
[TrialGlobalLimit("AfterStopCannNotOpt")] [TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task<IResponseOutput> PreArchiveDicomStudy(PreArchiveDicomStudyCommand preArchiveStudyCommand) public async Task<IResponseOutput> PreArchiveDicomStudy(PreArchiveDicomStudyCommand preArchiveStudyCommand)

View File

@ -82,6 +82,9 @@ public class DicomInstance : BaseFullDeleteAuditEntity, IEntitySeqId
public bool IsReading { get; set; } = true; public bool IsReading { get; set; } = true;
[Comment("是否已经影像遮盖")]
public bool IsMasked { get; set; } = false;
#region DIR 增加 #region DIR 增加

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,30 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace IRaCIS.Core.Infra.EFCore.Migrations
{
/// <inheritdoc />
public partial class addImageMask : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "IsMasked",
table: "DicomInstance",
type: "bit",
nullable: false,
defaultValue: false,
comment: "是否已经影像遮盖");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "IsMasked",
table: "DicomInstance");
}
}
}

View File

@ -1168,6 +1168,10 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
b.Property<bool>("IsEncapsulated") b.Property<bool>("IsEncapsulated")
.HasColumnType("bit"); .HasColumnType("bit");
b.Property<bool>("IsMasked")
.HasColumnType("bit")
.HasComment("是否已经影像遮盖");
b.Property<bool>("IsReading") b.Property<bool>("IsReading")
.HasColumnType("bit"); .HasColumnType("bit");