diff --git a/IRaCIS.Core.Application/Helper/OtherTool/DicomSortHelper.cs b/IRaCIS.Core.Application/Helper/OtherTool/DicomSortHelper.cs
index ee63f5c53..ab0d67063 100644
--- a/IRaCIS.Core.Application/Helper/OtherTool/DicomSortHelper.cs
+++ b/IRaCIS.Core.Application/Helper/OtherTool/DicomSortHelper.cs
@@ -129,7 +129,7 @@ public sealed class DicomMaskOptions
/// 灰度图像的遮挡像素值,默认 0。
/// 注意:这表示写入的原始像素值,不保证视觉上一定为黑色。
///
- public ushort GrayscaleMaskValue { get; init; } = 0;
+ //public ushort GrayscaleMaskValue { get; init; } = 0;
///
/// 彩色图像的遮挡值,默认 [0,0,0]。
@@ -147,6 +147,19 @@ public sealed class DicomMaskOptions
/// 是否更新 BurnedInAnnotation 为 NO。
///
public bool UpdateBurnedInAnnotationToNo { get; init; } = false;
+
+
+ ///
+ /// 是否启用自动灰度遮挡值。
+ /// true 时,根据 PhotometricInterpretation + BitsStored + PixelRepresentation 自动选择更合理的值。
+ ///
+ public bool AutoSelectGrayscaleMaskValue { get; init; } = true;
+
+ ///
+ /// 当 AutoSelectGrayscaleMaskValue=false 时,使用该值。
+ /// 当为 null 且 AutoSelectGrayscaleMaskValue=false 时,默认 0。
+ ///
+ public int? GrayscaleMaskValue { get; init; }
}
@@ -188,7 +201,7 @@ public static class DicomPixelMasker
ValidateDataset(originalDataset);
- var originalTransferSyntax = originalFile.FileMetaInfo.TransferSyntax;
+ var originalTs = originalFile.FileMetaInfo.TransferSyntax;
var originalPhotometric = originalDataset.GetSingleValueOrDefault(DicomTag.PhotometricInterpretation, string.Empty);
var rows = originalDataset.GetSingleValue(DicomTag.Rows);
@@ -198,36 +211,32 @@ public static class DicomPixelMasker
var samplesPerPixel = originalDataset.GetSingleValue(DicomTag.SamplesPerPixel);
var pixelRepresentation = originalDataset.GetSingleValueOrDefault(DicomTag.PixelRepresentation, (ushort)0);
var planarConfiguration = originalDataset.GetSingleValueOrDefault(DicomTag.PlanarConfiguration, (ushort)0);
- //log?.Invoke($"Rows={rows}, Cols={cols}, BitsAllocated={bitsAllocated}, BitsStored={bitsStored}, SamplesPerPixel={samplesPerPixel}, PixelRepresentation={pixelRepresentation}, PlanarConfiguration={planarConfiguration}");
+ Console.WriteLine($"Rows={rows}, Cols={cols}, BitsAllocated={bitsAllocated}, BitsStored={bitsStored}, SamplesPerPixel={samplesPerPixel}, PixelRepresentation={pixelRepresentation}, PlanarConfiguration={planarConfiguration}");
+ EnsureSupportedPhotometric(originalPhotometric, samplesPerPixel);
// 1. 转为工作用的未压缩 DICOM
var workingFile = await EnsureUncompressedAsync(originalFile, cancellationToken).ConfigureAwait(false);
- var workingDataset = workingFile.Dataset;
-
// 2. 修改像素
- MaskPixelDataInPlace(workingDataset, regionList, options);
-
+ MaskPixelDataInPlace(workingFile.Dataset, regionList, options);
// 3. 保持原 PhotometricInterpretation
if (!string.IsNullOrWhiteSpace(originalPhotometric))
{
- workingDataset.AddOrUpdate(DicomTag.PhotometricInterpretation, originalPhotometric);
+ workingFile.Dataset.AddOrUpdate(DicomTag.PhotometricInterpretation, originalPhotometric);
}
-
// 4. 可选更新 BurnedInAnnotation
if (options.UpdateBurnedInAnnotationToNo)
{
- workingDataset.AddOrUpdate(DicomTag.BurnedInAnnotation, "NO");
+ workingFile.Dataset.AddOrUpdate(DicomTag.BurnedInAnnotation, "NO");
}
-
- // 5. 转回原始 TransferSyntax
+ // 5. 编码回原始传输语法
var finalFile = await ReEncodeToOriginalTransferSyntaxAsync(
workingFile,
- originalTransferSyntax,
+ originalTs,
options.StrictKeepTransferSyntax,
cancellationToken).ConfigureAwait(false);
- finalFile.FileMetaInfo.TransferSyntax = originalTransferSyntax;
+ finalFile.FileMetaInfo.TransferSyntax = originalTs;
if (output.CanSeek)
output.SetLength(0);
@@ -236,6 +245,7 @@ public static class DicomPixelMasker
if (output.CanSeek)
output.Position = 0;
+
}
///
@@ -254,6 +264,37 @@ public static class DicomPixelMasker
_ = dataset.GetSingleValue(DicomTag.SamplesPerPixel);
}
+ private static void EnsureSupportedPhotometric(string photometric, int samplesPerPixel, Action? log = null)
+ {
+ if (samplesPerPixel == 1)
+ {
+ if (string.Equals(photometric, "MONOCHROME1", StringComparison.OrdinalIgnoreCase) ||
+ string.Equals(photometric, "MONOCHROME2", StringComparison.OrdinalIgnoreCase))
+ {
+ return;
+ }
+ throw new NotSupportedException($"Unsupported grayscale PhotometricInterpretation: {photometric}");
+ }
+ if (samplesPerPixel == 3)
+ {
+ if (string.Equals(photometric, "RGB", StringComparison.OrdinalIgnoreCase) ||
+ string.Equals(photometric, "YBR_FULL", StringComparison.OrdinalIgnoreCase))
+ {
+ return;
+ }
+ // 对 YBR_FULL_422 不建议直接按当前布局改
+ if (string.Equals(photometric, "YBR_FULL_422", StringComparison.OrdinalIgnoreCase) ||
+ string.Equals(photometric, "YBR_PARTIAL_422", StringComparison.OrdinalIgnoreCase) ||
+ string.Equals(photometric, "YBR_PARTIAL_420", StringComparison.OrdinalIgnoreCase))
+ {
+ throw new NotSupportedException(
+ $"PhotometricInterpretation={photometric} uses subsampling layout and is not safely supported by this pixel masking implementation.");
+ }
+ throw new NotSupportedException($"Unsupported color PhotometricInterpretation: {photometric}");
+ }
+ throw new NotSupportedException($"Unsupported SamplesPerPixel={samplesPerPixel}");
+ }
+
///
/// 转为工作用的未压缩 DICOM
///
@@ -288,59 +329,35 @@ public static class DicomPixelMasker
///
/// 转回原始 TransferSyntax
///
- ///
+ ///
///
///
///
///
///
private static async Task ReEncodeToOriginalTransferSyntaxAsync(
- DicomFile uncompressedFile,
- DicomTransferSyntax originalTransferSyntax,
- bool strictKeepTransferSyntax,
- CancellationToken cancellationToken)
+ DicomFile workingFile,
+ DicomTransferSyntax originalTransferSyntax,
+ bool strictKeepTransferSyntax,
+ CancellationToken cancellationToken)
{
- if (!originalTransferSyntax.IsEncapsulated)
- {
- if (uncompressedFile.FileMetaInfo.TransferSyntax == originalTransferSyntax)
- {
- return uncompressedFile;
- }
-
- try
- {
- var transcoder = new DicomTranscoder(
- uncompressedFile.FileMetaInfo.TransferSyntax,
- originalTransferSyntax);
-
- return await Task.Run(() => transcoder.Transcode(uncompressedFile), cancellationToken)
- .ConfigureAwait(false);
- }
- catch (Exception ex)
- {
- throw new InvalidOperationException(
- $"Failed to convert dataset back to original uncompressed TransferSyntax {originalTransferSyntax.UID.UID}.",
- ex);
- }
- }
-
+ if (workingFile.FileMetaInfo.TransferSyntax == originalTransferSyntax)
+ return workingFile;
try
{
- var currentTs = uncompressedFile.FileMetaInfo.TransferSyntax;
+ var currentTs = workingFile.FileMetaInfo.TransferSyntax;
var transcoder = new DicomTranscoder(currentTs, originalTransferSyntax);
- return await Task.Run(() => transcoder.Transcode(uncompressedFile), cancellationToken)
- .ConfigureAwait(false);
+ return await Task.Run(() => transcoder.Transcode(workingFile), cancellationToken).ConfigureAwait(false);
}
catch (Exception ex)
{
if (strictKeepTransferSyntax)
{
throw new InvalidOperationException(
- $"Failed to re-encode DICOM back to original compressed TransferSyntax {originalTransferSyntax.UID.UID}.",
+ $"Failed to re-encode DICOM back to original TransferSyntax {originalTransferSyntax.UID.UID}.",
ex);
}
-
- return uncompressedFile;
+ return workingFile;
}
}
@@ -351,77 +368,66 @@ public static class DicomPixelMasker
///
///
private static void MaskPixelDataInPlace(
- DicomDataset dataset,
- IReadOnlyList regions,
- DicomMaskOptions options)
+ DicomDataset dataset,
+ IReadOnlyList regions,
+ DicomMaskOptions options)
{
var rows = dataset.GetSingleValue(DicomTag.Rows);
var cols = dataset.GetSingleValue(DicomTag.Columns);
var bitsAllocated = dataset.GetSingleValue(DicomTag.BitsAllocated);
+ var bitsStored = dataset.GetSingleValueOrDefault(DicomTag.BitsStored, bitsAllocated);
var samplesPerPixel = dataset.GetSingleValue(DicomTag.SamplesPerPixel);
var pixelRepresentation = dataset.GetSingleValueOrDefault(DicomTag.PixelRepresentation, (ushort)0);
var photometric = dataset.GetSingleValueOrDefault(DicomTag.PhotometricInterpretation, string.Empty);
var planarConfiguration = dataset.GetSingleValueOrDefault(DicomTag.PlanarConfiguration, (ushort)0);
-
var pixelData = DicomPixelData.Create(dataset, false);
var frameCount = pixelData.NumberOfFrames;
-
var framesToProcess = ResolveFrames(frameCount, options.FrameIndices);
-
- var newFrames = new List(frameCount);
-
+ var replacementFrames = new List(frameCount);
for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)
{
var frame = pixelData.GetFrame(frameIndex);
- var data = frame.Data.ToArray();
-
+ var buffer = frame.Data;
+ var bytes = buffer.ToArray();
if (framesToProcess.Contains(frameIndex))
{
ApplyMaskToFrame(
- data,
- rows,
- cols,
- bitsAllocated,
- samplesPerPixel,
- pixelRepresentation,
- photometric,
- planarConfiguration,
- regions,
- options);
+ frameData: bytes,
+ rows: rows,
+ cols: cols,
+ bitsAllocated: bitsAllocated,
+ bitsStored: bitsStored,
+ samplesPerPixel: samplesPerPixel,
+ pixelRepresentation: pixelRepresentation,
+ photometric: photometric,
+ planarConfiguration: planarConfiguration,
+ regions: regions,
+ options: options);
}
-
- newFrames.Add(new MemoryByteBuffer(data));
+ replacementFrames.Add(new MemoryByteBuffer(bytes));
}
-
- ReplacePixelDataFrames(dataset, pixelData, newFrames);
+ ReplacePixelDataFrames(dataset, pixelData, replacementFrames);
}
private static HashSet ResolveFrames(int frameCount, IReadOnlyCollection? frameIndices)
{
if (frameIndices == null || frameIndices.Count == 0)
- {
return Enumerable.Range(0, frameCount).ToHashSet();
- }
-
var result = new HashSet();
- foreach (var i in frameIndices)
+ foreach (var index in frameIndices)
{
- if (i < 0 || i >= frameCount)
- throw new ArgumentOutOfRangeException(nameof(frameIndices), $"Frame index {i} out of range [0, {frameCount - 1}]");
-
- result.Add(i);
+ if (index < 0 || index >= frameCount)
+ throw new ArgumentOutOfRangeException(nameof(frameIndices), $"Frame index {index} out of range [0, {frameCount - 1}]");
+ result.Add(index);
}
-
return result;
}
-
private static void ReplacePixelDataFrames(
DicomDataset dataset,
DicomPixelData sourcePixelData,
IReadOnlyList frames)
{
dataset.Remove(DicomTag.PixelData);
-
var newPixelData = DicomPixelData.Create(dataset, true);
//newPixelData.BitsAllocated = sourcePixelData.BitsAllocated;
newPixelData.BitsStored = sourcePixelData.BitsStored;
@@ -432,7 +438,6 @@ public static class DicomPixelMasker
newPixelData.Height = sourcePixelData.Height;
newPixelData.Width = sourcePixelData.Width;
newPixelData.PhotometricInterpretation = sourcePixelData.PhotometricInterpretation;
-
foreach (var frame in frames)
{
newPixelData.AddFrame(frame);
@@ -440,63 +445,106 @@ public static class DicomPixelMasker
}
private static void ApplyMaskToFrame(
- byte[] frameData,
- int rows,
- int cols,
- int bitsAllocated,
- int samplesPerPixel,
- ushort pixelRepresentation,
- string photometric,
- ushort planarConfiguration,
- IReadOnlyList regions,
- DicomMaskOptions options)
+ byte[] frameData,
+ int rows,
+ int cols,
+ int bitsAllocated,
+ int bitsStored,
+ int samplesPerPixel,
+ ushort pixelRepresentation,
+ string photometric,
+ ushort planarConfiguration,
+ IReadOnlyList regions,
+ DicomMaskOptions options)
{
if (samplesPerPixel == 1)
{
if (bitsAllocated == 8)
{
- //8 位灰度
- ApplyMask_Grayscale8(frameData, rows, cols, regions, (byte)Math.Min(options.GrayscaleMaskValue, byte.MaxValue));
+ byte maskValue8 = ResolveGrayscaleMaskValue8(photometric, options);
+ ApplyMask_Grayscale8(frameData, rows, cols, regions, maskValue8);
return;
}
-
- // 16 位灰度
if (bitsAllocated == 16)
{
- ApplyMask_Grayscale16(frameData, rows, cols, regions, options.GrayscaleMaskValue);
+ ushort maskValue16 = ResolveGrayscaleMaskValue16(
+ photometric,
+ bitsStored,
+ pixelRepresentation,
+ options);
+ ApplyMask_Grayscale16(frameData, rows, cols, regions, maskValue16);
return;
}
-
- throw new NotSupportedException($"Unsupported grayscale BitsAllocated={bitsAllocated}, Photometric={photometric}.");
+ throw new NotSupportedException(
+ $"Unsupported grayscale image: BitsAllocated={bitsAllocated}, Photometric={photometric}");
}
-
- //RGB 彩图
if (samplesPerPixel == 3)
{
if (bitsAllocated != 8)
{
- throw new NotSupportedException($"Unsupported color image: SamplesPerPixel=3 but BitsAllocated={bitsAllocated}.");
+ throw new NotSupportedException(
+ $"Unsupported color image: SamplesPerPixel=3, BitsAllocated={bitsAllocated}, Photometric={photometric}");
}
-
if (planarConfiguration == 0)
{
ApplyMask_Color8_Interleaved(frameData, rows, cols, regions, options.ColorMaskValue);
return;
}
-
if (planarConfiguration == 1)
{
ApplyMask_Color8_Planar(frameData, rows, cols, regions, options.ColorMaskValue);
return;
}
-
- throw new NotSupportedException($"Unsupported PlanarConfiguration={planarConfiguration}, Photometric={photometric}.");
+ throw new NotSupportedException(
+ $"Unsupported PlanarConfiguration={planarConfiguration}, Photometric={photometric}");
}
-
throw new NotSupportedException(
- $"Unsupported image format: SamplesPerPixel={samplesPerPixel}, BitsAllocated={bitsAllocated}, PixelRepresentation={pixelRepresentation}, Photometric={photometric}.");
+ $"Unsupported format: SamplesPerPixel={samplesPerPixel}, BitsAllocated={bitsAllocated}, Photometric={photometric}");
+ }
+ private static byte ResolveGrayscaleMaskValue8(string photometric, DicomMaskOptions options)
+ {
+ if (!options.AutoSelectGrayscaleMaskValue)
+ {
+ var value = options.GrayscaleMaskValue ?? 0;
+ return (byte)Math.Clamp(value, byte.MinValue, byte.MaxValue);
+ }
+ if (string.Equals(photometric, "MONOCHROME1", StringComparison.OrdinalIgnoreCase))
+ return byte.MaxValue;
+ return byte.MinValue;
+ }
+ private static ushort ResolveGrayscaleMaskValue16(
+ string photometric,
+ int bitsStored,
+ ushort pixelRepresentation,
+ DicomMaskOptions options)
+ {
+ if (!options.AutoSelectGrayscaleMaskValue)
+ {
+ var value = options.GrayscaleMaskValue ?? 0;
+ return unchecked((ushort)value);
+ }
+ bool isSigned = pixelRepresentation == 1;
+ bool mono1 = string.Equals(photometric, "MONOCHROME1", StringComparison.OrdinalIgnoreCase);
+ bitsStored = Math.Clamp(bitsStored, 1, 16);
+ if (!isSigned)
+ {
+ ushort min = 0;
+ ushort max = bitsStored == 16
+ ? ushort.MaxValue
+ : (ushort)((1 << bitsStored) - 1);
+ return mono1 ? max : min;
+ }
+ else
+ {
+ // signed range based on BitsStored
+ // minSigned = -(1 << (bitsStored - 1))
+ // maxSigned = (1 << (bitsStored - 1)) - 1
+ int minSigned = -(1 << (bitsStored - 1));
+ int maxSigned = (1 << (bitsStored - 1)) - 1;
+ short selected = mono1 ? (short)maxSigned : (short)minSigned;
+ return unchecked((ushort)selected);
+ }
}
-
private static void ApplyMask_Grayscale8(
byte[] data,
int rows,
@@ -508,18 +556,16 @@ public static class DicomPixelMasker
{
var (left, top, right, bottom) = ClipRegion(region, cols, rows);
if (left >= right || top >= bottom) continue;
-
for (int y = top; y < bottom; y++)
{
- int rowOffset = y * cols;
+ int offset = y * cols;
for (int x = left; x < right; x++)
{
- data[rowOffset + x] = maskValue;
+ data[offset + x] = maskValue;
}
}
}
}
-
private static void ApplyMask_Grayscale16(
byte[] data,
int rows,
@@ -531,22 +577,19 @@ public static class DicomPixelMasker
{
var (left, top, right, bottom) = ClipRegion(region, cols, rows);
if (left >= right || top >= bottom) continue;
-
for (int y = top; y < bottom; y++)
{
- int rowOffset = y * cols;
+ int offset = y * cols;
for (int x = left; x < right; x++)
{
- int pixelIndex = rowOffset + x;
+ int pixelIndex = offset + x;
int byteIndex = pixelIndex * 2;
-
data[byteIndex] = (byte)(maskValue & 0xFF);
data[byteIndex + 1] = (byte)((maskValue >> 8) & 0xFF);
}
}
}
}
-
private static void ApplyMask_Color8_Interleaved(
byte[] data,
int rows,
@@ -556,23 +599,19 @@ public static class DicomPixelMasker
{
if (color == null || color.Length < 3)
throw new ArgumentException("ColorMaskValue must contain at least 3 bytes.");
-
byte c0 = color[0];
byte c1 = color[1];
byte c2 = color[2];
-
foreach (var region in regions)
{
var (left, top, right, bottom) = ClipRegion(region, cols, rows);
if (left >= right || top >= bottom) continue;
-
for (int y = top; y < bottom; y++)
{
for (int x = left; x < right; x++)
{
int pixelIndex = y * cols + x;
int byteIndex = pixelIndex * 3;
-
data[byteIndex] = c0;
data[byteIndex + 1] = c1;
data[byteIndex + 2] = c2;
@@ -580,7 +619,6 @@ public static class DicomPixelMasker
}
}
}
-
private static void ApplyMask_Color8_Planar(
byte[] data,
int rows,
@@ -590,18 +628,14 @@ public static class DicomPixelMasker
{
if (color == null || color.Length < 3)
throw new ArgumentException("ColorMaskValue must contain at least 3 bytes.");
-
int planeSize = rows * cols;
-
byte c0 = color[0];
byte c1 = color[1];
byte c2 = color[2];
-
foreach (var region in regions)
{
var (left, top, right, bottom) = ClipRegion(region, cols, rows);
if (left >= right || top >= bottom) continue;
-
for (int y = top; y < bottom; y++)
{
int rowOffset = y * cols;
@@ -615,8 +649,10 @@ public static class DicomPixelMasker
}
}
}
-
- private static (int left, int top, int right, int bottom) ClipRegion(MaskRegion region, int imageWidth, int imageHeight)
+ private static (int left, int top, int right, int bottom) ClipRegion(
+ MaskRegion region,
+ int imageWidth,
+ int imageHeight)
{
int left = Math.Max(0, region.X);
int top = Math.Max(0, region.Y);
diff --git a/IRaCIS.Core.Application/Helper/OtherTool/WeComNotifier.cs b/IRaCIS.Core.Application/Helper/OtherTool/WeComNotifier.cs
index 7af0b625c..b9f991f43 100644
--- a/IRaCIS.Core.Application/Helper/OtherTool/WeComNotifier.cs
+++ b/IRaCIS.Core.Application/Helper/OtherTool/WeComNotifier.cs
@@ -1,13 +1,14 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using IdentityModel;
using Newtonsoft.Json;
using RestSharp;
+using System;
+using System.Collections.Generic;
+using System.Linq;
using System.Net;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
using System.Threading.Tasks;
-using IdentityModel;
namespace IRaCIS.Core.Application.Helper.OtherTool;
@@ -31,6 +32,11 @@ public static class WeComNotifier
public static async Task SendAlertAsync(string webhook, WeComAlert alert)
{
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ await Task.CompletedTask;
+ }
+
try
{
var client = new RestClient();
diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
index d3dbc1581..5ca2defe6 100644
--- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
+++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
@@ -16157,12 +16157,6 @@
要处理的帧,null 或空表示全部帧。
-
-
- 灰度图像的遮挡像素值,默认 0。
- 注意:这表示写入的原始像素值,不保证视觉上一定为黑色。
-
-
彩色图像的遮挡值,默认 [0,0,0]。
@@ -16180,6 +16174,18 @@
是否更新 BurnedInAnnotation 为 NO。
+
+
+ 是否启用自动灰度遮挡值。
+ true 时,根据 PhotometricInterpretation + BitsStored + PixelRepresentation 自动选择更合理的值。
+
+
+
+
+ 当 AutoSelectGrayscaleMaskValue=false 时,使用该值。
+ 当为 null 且 AutoSelectGrayscaleMaskValue=false 时,默认 0。
+
+
验证dicom tag
@@ -16200,7 +16206,7 @@
转回原始 TransferSyntax
-
+
@@ -17206,17 +17212,17 @@
- ����
+ 质疑
- һ���Ժ˲�
+ 一致性核查
- ����
+ 复制
diff --git a/IRaCIS.Core.Application/TestService.cs b/IRaCIS.Core.Application/TestService.cs
index 119543e55..861ea57fb 100644
--- a/IRaCIS.Core.Application/TestService.cs
+++ b/IRaCIS.Core.Application/TestService.cs
@@ -137,10 +137,7 @@ namespace IRaCIS.Core.Application.Service
{
new MaskRegion(0, 0, 200, 200)
};
- var options = new DicomMaskOptions
- {
- StrictKeepTransferSyntax = true
- };
+
foreach (var inputPath in Directory.EnumerateFiles(sourceDir, "*.dcm", SearchOption.TopDirectoryOnly))
{
var relativePath = Path.GetRelativePath(sourceDir, inputPath);
@@ -152,7 +149,19 @@ namespace IRaCIS.Core.Application.Service
}
await using var input = File.OpenRead(inputPath);
await using var output = File.Create(outputPath);
- await DicomPixelMasker.MaskAsync(input, output, regions, options);
+
+ try
+ {
+ await DicomPixelMasker.MaskAsync(input, output, regions);
+
+ }
+ catch(Exception ex)
+ {
+ // 跳过该文件
+
+ Console.WriteLine($"error: {ex.Message}");
+ }
+
Console.WriteLine($"Done: {relativePath}");
}
diff --git a/IRaCIS.Core.Domain/Reading/ReadingCriterion/ReadingQuestionCriterionTrial.cs b/IRaCIS.Core.Domain/Reading/ReadingCriterion/ReadingQuestionCriterionTrial.cs
index d27815e83..ca3df7293 100644
--- a/IRaCIS.Core.Domain/Reading/ReadingCriterion/ReadingQuestionCriterionTrial.cs
+++ b/IRaCIS.Core.Domain/Reading/ReadingCriterion/ReadingQuestionCriterionTrial.cs
@@ -239,7 +239,6 @@ public enum ReadingOrder
}
-[ComplexType]
public class DefaultSegmentNameDto
{
public string SegmentationName { get; set; } =string.Empty;
diff --git a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs
index 700581332..7beb13475 100644
--- a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs
+++ b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs
@@ -104,10 +104,10 @@ public class IRaCISDBContext : DbContext
modelBuilder.Entity(entity =>
{
//默认SegmentName
- entity.OwnsOne(x => x.DefaultSegmentName, ownedNavigationBuilder =>
- {
- ownedNavigationBuilder.ToJson();
- });
+ entity.Property(e => e.DefaultSegmentName).HasConversion(
+ v => v == null ? null : JsonConvert.SerializeObject(v),
+ v => string.IsNullOrEmpty(v) ? new DefaultSegmentNameDto() : JsonConvert.DeserializeObject(v)
+ );
});
#region pgsql codefirst 配置 暂时屏蔽