Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing

This commit is contained in:
2026-01-27 15:18:51 +08:00
51 changed files with 55375 additions and 1242 deletions
+1
View File
@@ -194,6 +194,7 @@ app.MapControllers();
Log.Logger = new LoggerConfiguration() Log.Logger = new LoggerConfiguration()
//.MinimumLevel.Information() //.MinimumLevel.Information()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning) .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.MinimumLevel.Override("ZiggyCreatures.Caching.Fusion", LogEventLevel.Warning)
.WriteTo.Console() .WriteTo.Console()
.WriteTo.File($"{AppContext.BaseDirectory}Serilogs/.log", rollingInterval: RollingInterval.Day) .WriteTo.File($"{AppContext.BaseDirectory}Serilogs/.log", rollingInterval: RollingInterval.Day)
.CreateLogger(); .CreateLogger();
+349 -297
View File
@@ -1,28 +1,29 @@
using FellowOakDicom.Network; using FellowOakDicom;
using FellowOakDicom; using FellowOakDicom.Imaging;
using FellowOakDicom.IO.Buffer;
using FellowOakDicom.Network;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Infrastructure.Extention;
using IRaCIS.Core.SCP.Service;
using Medallion.Threading;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Serilog;
using SharpCompress.Common;
using SixLabors.ImageSharp.Formats.Jpeg;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging; using ZiggyCreatures.Caching.Fusion;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using IRaCIS.Core.SCP.Service;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Infra.EFCore;
using Medallion.Threading;
using IRaCIS.Core.Domain.Share;
using Serilog;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
using Microsoft.Extensions.Options;
using System.Data;
using FellowOakDicom.Imaging;
using SharpCompress.Common;
using SixLabors.ImageSharp.Formats.Jpeg;
using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Infrastructure.Extention;
using FellowOakDicom.IO.Buffer;
namespace IRaCIS.Core.SCP.Service namespace IRaCIS.Core.SCP.Service
{ {
@@ -120,7 +121,7 @@ namespace IRaCIS.Core.SCP.Service
var _trialSiteDicomAERepository = _serviceProvider.GetService<IRepository<TrialSiteDicomAE>>(); var _trialSiteDicomAERepository = _serviceProvider.GetService<IRepository<TrialSiteDicomAE>>();
var findTrialSiteAE = _trialSiteDicomAERepository.Where(t => t.CallingAE == association.CallingAE && t.TrialId==_trialId).FirstOrDefault(); var findTrialSiteAE = _trialSiteDicomAERepository.Where(t => t.CallingAE == association.CallingAE && t.TrialId == _trialId).FirstOrDefault();
if (findTrialSiteAE != null) if (findTrialSiteAE != null)
{ {
@@ -328,6 +329,11 @@ namespace IRaCIS.Core.SCP.Service
var _seriesRepository = _serviceProvider.GetService<IRepository<SCPSeries>>(); var _seriesRepository = _serviceProvider.GetService<IRepository<SCPSeries>>();
var _distributedLockProvider = _serviceProvider.GetService<IDistributedLockProvider>(); var _distributedLockProvider = _serviceProvider.GetService<IDistributedLockProvider>();
var _fusionCache = _serviceProvider.GetService<IFusionCache>();
var _trialSiteRepository = _serviceProvider.GetService<IRepository<TrialSite>>();
var _systemAnonymizationRepository = _serviceProvider.GetService<IRepository<SystemAnonymization>>();
var storeRelativePath = string.Empty; var storeRelativePath = string.Empty;
var ossFolderPath = $"{_trialId}/Image/PACS/{_trialSiteId}/{studyInstanceUid}"; var ossFolderPath = $"{_trialId}/Image/PACS/{_trialSiteId}/{studyInstanceUid}";
@@ -336,337 +342,383 @@ namespace IRaCIS.Core.SCP.Service
long fileSize = 0; long fileSize = 0;
try try
{ {
using (MemoryStream ms = new MemoryStream()) // 直接拿 Dataset(已经完整)
var dataset = request.Dataset;
#region
var anonymizeList = await _fusionCache.GetOrSetAsync(CacheKeys.SystemAnonymization, _ => CacheHelper.GetSystemAnonymizationListAsync(_systemAnonymizationRepository), TimeSpan.FromDays(7));
var trialSiteInfo = await _fusionCache.GetOrSetAsync(CacheKeys.TrialSiteInfo(_trialSiteId), _ => CacheHelper.GetTrialSiteInfo(_trialSiteId, _trialSiteRepository), TimeSpan.FromMinutes(2));
var fixedFiledList = anonymizeList.Where(t => t.IsFixed).ToList();
var ircFiledList = anonymizeList.Where(t => t.IsFixed == false).ToList();
foreach (var item in fixedFiledList)
{ {
await request.File.SaveAsync(ms);
#region 1便 var dicomTag = new DicomTag(Convert.ToUInt16(item.Group, 16), Convert.ToUInt16(item.Element, 16));
// 回到开头,读取 dicom dataset.AddOrUpdate(dicomTag, item.ReplaceValue);
ms.Position = 0; }
var dicomFile = DicomFile.Open(ms);
var numberOfFrames = dicomFile.Dataset.GetSingleValueOrDefault(DicomTag.NumberOfFrames, 1); foreach (var item in ircFiledList)
{
//多帧处理逻辑 var dicomTag = new DicomTag(Convert.ToUInt16(item.Group, 16), Convert.ToUInt16(item.Element, 16));
if (numberOfFrames > 1)
if (dicomTag == DicomTag.ClinicalTrialProtocolID)
{ {
//一定要有像素数据才处理 dataset.AddOrUpdate(DicomTag.ClinicalTrialProtocolID, trialSiteInfo.TrialCode);
var pixelData = DicomPixelData.Create(dicomFile.Dataset);
if (pixelData != null) }
{ if (dicomTag == DicomTag.ClinicalTrialSiteID)
try {
{ dataset.AddOrUpdate(DicomTag.ClinicalTrialSiteID, trialSiteInfo.TrialSiteCode);
Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE} 开始处理多帧instanceId:{instanceId}");
var syntax = pixelData.Syntax;
// 每个 fragment 固定大小 (64KB 示例,可以自己调整)
int fragmentSize = 20 * 1024;
var frag = dicomFile.Dataset.GetDicomItem<DicomOtherByteFragment>(DicomTag.PixelData);
int fragmentCount = frag?.Fragments?.Count() ?? 0;
var originOffsetTable = frag?.OffsetTable; //有可能没有表,需要自己重建
var bot = new List<uint>();
uint botOffset = 0;
//需要拆成固定片段的
if (syntax.IsEncapsulated && fragmentCount == pixelData.NumberOfFrames && numberOfFrames > 1)
{
var newFragments = new DicomOtherByteFragment(DicomTag.PixelData);
#region test
//var newDicomFile = dicomFile.Clone();
//var newDataset = newDicomFile.Dataset;
//var dstPd = DicomPixelData.Create(newDataset, true);
//for (int i = 0; i < pixelData.NumberOfFrames; i++)
//{
// var frame = pixelData.GetFrame(i);
// dstPd.AddFrame(frame);
// var data = frame.Data;
// int offset = 0;
// while (offset < data.Length)
// {
// int size = Math.Min(fragmentSize, data.Length - offset);
// var buffer = new byte[size];
// Buffer.BlockCopy(data, offset, buffer, 0, size);
// newFragments.Fragments.Add(new MemoryByteBuffer(buffer));
// offset += size;
// }
//}
//var newOffsetTable = newDataset.GetDicomItem<DicomOtherByteFragment>(DicomTag.PixelData).OffsetTable;
//newFragments.OffsetTable.AddRange(newOffsetTable.ToArray());
#endregion
#region test fo-dicom auto bot
//var newDicomFile = dicomFile.Clone();
//var newDataset = newDicomFile.Dataset;
//var dstPd = DicomPixelData.Create(newDataset, true);
//for (int i = 0; i < pixelData.NumberOfFrames; i++)
//{
// var frame = pixelData.GetFrame(i);
// dstPd.AddFrame(frame);
//}
//var newOffsetTable = newDataset.GetDicomItem<DicomOtherByteFragment>(DicomTag.PixelData).OffsetTable;
//Console.WriteLine(newOffsetTable.ToJsonStr());
#endregion
#region 使
for (int n = 0; n < pixelData.NumberOfFrames; n++)
{
var frameData = pixelData.GetFrame(n); // 获取完整一帧
var data = frameData.Data;
int offset = 0;
bot.Add(botOffset);
botOffset += (uint)data.Length;
while (offset < data.Length)
{
botOffset += 8;
int size = Math.Min(fragmentSize, data.Length - offset);
var buffer = new byte[size];
Buffer.BlockCopy(data, offset, buffer, 0, size);
newFragments.Fragments.Add(new MemoryByteBuffer(buffer));
offset += size;
}
}
//保留原始偏移表
if (originOffsetTable.Count == pixelData.NumberOfFrames)
{
newFragments.OffsetTable.AddRange(originOffsetTable.ToArray());
}
else
{
newFragments.OffsetTable.AddRange(bot.ToArray());
//Console.WriteLine(bot.ToJsonStr());
}
#endregion
dicomFile.Dataset.AddOrUpdate(newFragments);
// 重新保存 dicom 到流
ms.SetLength(0);
dicomFile.Save(ms);
}
//传递过来的就是拆分的,但是是没有偏移表的,我需要自己创建偏移表,不然生成缩略图失败
else if (syntax.IsEncapsulated && fragmentCount > pixelData.NumberOfFrames && originOffsetTable.Count == 0)
{
uint offset = 0;
bot.Add(offset);
var fistSize = frag.Fragments.FirstOrDefault()?.Size ?? 0;
//和上一个大小不一样
var isDiffrentBefore = false;
uint count = 0;
// 假设你知道每帧对应的 fragment 数量
foreach (var frameFragments in frag.Fragments)
{
count++;
if (frameFragments.Size == fistSize)
{
isDiffrentBefore = false;
// 累加这一帧所有 fragment 的大小
offset += (uint)frameFragments.Size;
continue;
}
else
{
offset += (uint)frameFragments.Size;
isDiffrentBefore = true;
}
if (isDiffrentBefore)
{
//每个Fragment 也占用字节
offset += 8 * count;
bot.Add(offset);
count = 0;
}
}
bot.RemoveAt(bot.Count - 1);
// 设置到新的 PixelData
frag.OffsetTable.AddRange(bot.ToArray());
// 重新保存 DICOM 到流
ms.SetLength(0);
dicomFile.Save(ms);
}
}
catch (Exception mutiEx)
{
Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE} 处理多帧失败,上传原始文件:{mutiEx.ToString()}");
}
}
} }
if (dicomTag == DicomTag.ClinicalTrialSubjectID)
{
dataset.AddOrUpdate(DicomTag.ClinicalTrialSubjectID, "");
}
if (dicomTag == DicomTag.ClinicalTrialTimePointID)
{
dataset.AddOrUpdate(DicomTag.ClinicalTrialTimePointID, "");
}
if (dicomTag == DicomTag.PatientID)
{
var pid = dataset.GetSingleValueOrDefault(DicomTag.PatientID, string.Empty);
dataset.AddOrUpdate(DicomTag.PatientID, trialSiteInfo.TrialCode + "-" + pid);
}
}
#endregion
// 构造 DicomFile(不用 Open
var dicomFile = new DicomFile(dataset);
#region 1便
var numberOfFrames = dicomFile.Dataset.GetSingleValueOrDefault(DicomTag.NumberOfFrames, 1);
//多帧处理逻辑
if (numberOfFrames > 1)
{
//一定要有像素数据才处理
var pixelData = DicomPixelData.Create(dicomFile.Dataset);
#endregion if (pixelData != null)
#region
//// --- 保存到本地文件测试 ---
//var localPath = @"D:\TestDicom.dcm";
//using (var fs = new FileStream(localPath, FileMode.Create, FileAccess.Write))
//{
// ms.CopyTo(fs);
//}
//return new DicomCStoreResponse(request, DicomStatus.Success);
#endregion
ms.Position = 0;
//irc 从路径最后一截取Guid
storeRelativePath = await ossService.UploadToOSSAsync(ms, ossFolderPath, instanceId.ToString(), false);
fileSize = ms.Length;
var @lock = _distributedLockProvider.CreateLock($"{studyInstanceUid}");
using (await @lock.AcquireAsync())
{ {
try try
{ {
var scpStudyId = await dicomArchiveService.ArchiveDicomFileAsync(dicomFile, _trialId, _trialSiteId, storeRelativePath, Association.CallingAE, Association.CalledAE, fileSize);
Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE} 开始处理多帧instanceId:{instanceId}");
var syntax = pixelData.Syntax;
// 每个 fragment 固定大小 (64KB 示例,可以自己调整)
int fragmentSize = 20 * 1024;
var series = await _seriesRepository.FirstOrDefaultAsync(t => t.Id == seriesId);
//没有缩略图 var frag = dicomFile.Dataset.GetDicomItem<DicomOtherByteFragment>(DicomTag.PixelData);
if (series != null && string.IsNullOrEmpty(series.ImageResizePath))
int fragmentCount = frag?.Fragments?.Count() ?? 0;
var originOffsetTable = frag?.OffsetTable; //有可能没有表,需要自己重建
var bot = new List<uint>();
uint botOffset = 0;
//需要拆成固定片段的
if (syntax.IsEncapsulated && fragmentCount == pixelData.NumberOfFrames && numberOfFrames > 1)
{ {
// 生成缩略图
using (var memoryStream = new MemoryStream())
var newFragments = new DicomOtherByteFragment(DicomTag.PixelData);
#region test
//var newDicomFile = dicomFile.Clone();
//var newDataset = newDicomFile.Dataset;
//var dstPd = DicomPixelData.Create(newDataset, true);
//for (int i = 0; i < pixelData.NumberOfFrames; i++)
//{
// var frame = pixelData.GetFrame(i);
// dstPd.AddFrame(frame);
// var data = frame.Data;
// int offset = 0;
// while (offset < data.Length)
// {
// int size = Math.Min(fragmentSize, data.Length - offset);
// var buffer = new byte[size];
// Buffer.BlockCopy(data, offset, buffer, 0, size);
// newFragments.Fragments.Add(new MemoryByteBuffer(buffer));
// offset += size;
// }
//}
//var newOffsetTable = newDataset.GetDicomItem<DicomOtherByteFragment>(DicomTag.PixelData).OffsetTable;
//newFragments.OffsetTable.AddRange(newOffsetTable.ToArray());
#endregion
#region test fo-dicom auto bot
//var newDicomFile = dicomFile.Clone();
//var newDataset = newDicomFile.Dataset;
//var dstPd = DicomPixelData.Create(newDataset, true);
//for (int i = 0; i < pixelData.NumberOfFrames; i++)
//{
// var frame = pixelData.GetFrame(i);
// dstPd.AddFrame(frame);
//}
//var newOffsetTable = newDataset.GetDicomItem<DicomOtherByteFragment>(DicomTag.PixelData).OffsetTable;
//Console.WriteLine(newOffsetTable.ToJsonStr());
#endregion
#region 使
for (int n = 0; n < pixelData.NumberOfFrames; n++)
{ {
DicomImage image = new DicomImage(dicomFile.Dataset); var frameData = pixelData.GetFrame(n); // 获取完整一帧
var data = frameData.Data;
int offset = 0;
var sharpimage = image.RenderImage().AsSharpImage(); bot.Add(botOffset);
sharpimage.Save(memoryStream, new JpegEncoder());
// 上传缩略图到 OSS botOffset += (uint)data.Length;
var seriesPath = await ossService.UploadToOSSAsync(memoryStream, ossFolderPath, $"{seriesId.ToString()}_{instanceId.ToString()}.preview.jpg", false);
series.ImageResizePath = seriesPath; while (offset < data.Length)
{
botOffset += 8;
int size = Math.Min(fragmentSize, data.Length - offset);
var buffer = new byte[size];
Buffer.BlockCopy(data, offset, buffer, 0, size);
newFragments.Fragments.Add(new MemoryByteBuffer(buffer));
offset += size;
}
}
//保留原始偏移表
if (originOffsetTable.Count == pixelData.NumberOfFrames)
{
newFragments.OffsetTable.AddRange(originOffsetTable.ToArray());
} }
else
{
newFragments.OffsetTable.AddRange(bot.ToArray());
//Console.WriteLine(bot.ToJsonStr());
}
#endregion
dicomFile.Dataset.AddOrUpdate(newFragments);
} }
//传递过来的就是拆分的,但是是没有偏移表的,我需要自己创建偏移表,不然生成缩略图失败
else if (syntax.IsEncapsulated && fragmentCount > pixelData.NumberOfFrames && originOffsetTable.Count == 0)
await _seriesRepository.SaveChangesAsync();
if (_ImageUploadList.Any(t => t.StudyInstanceUid == studyInstanceUid))
{ {
var find = _ImageUploadList.FirstOrDefault(t => t.StudyInstanceUid.Equals(studyInstanceUid));
find.SuccessImageCount++;
if (!find.PatientNameList.Any(t => t == patientIdStr) && patientIdStr.IsNotNullOrEmpty()) uint offset = 0;
bot.Add(offset);
var fistSize = frag.Fragments.FirstOrDefault()?.Size ?? 0;
//和上一个大小不一样
var isDiffrentBefore = false;
uint count = 0;
// 假设你知道每帧对应的 fragment 数量
foreach (var frameFragments in frag.Fragments)
{ {
find.PatientNameList.Add(patientIdStr); count++;
if (frameFragments.Size == fistSize)
{
isDiffrentBefore = false;
// 累加这一帧所有 fragment 的大小
offset += (uint)frameFragments.Size;
continue;
}
else
{
offset += (uint)frameFragments.Size;
isDiffrentBefore = true;
}
if (isDiffrentBefore)
{
//每个Fragment 也占用字节
offset += 8 * count;
bot.Add(offset);
count = 0;
}
} }
//首次 (默认是Guid 空,数据库归档出了Id) bot.RemoveAt(bot.Count - 1);
if (find.SCPStudyId != scpStudyId) // 设置到新的 PixelData
{ frag.OffsetTable.AddRange(bot.ToArray());
find.SCPStudyId = scpStudyId;
}
} }
//监控信息设置
_upload.FileCount++;
_upload.FileSize = _upload.FileSize + fileSize;
} }
catch (Exception ex) catch (Exception mutiEx)
{
Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE} 处理多帧失败,上传原始文件:{mutiEx.ToString()}");
}
}
}
#endregion
#region
//// --- 保存到本地文件测试 ---
//var localPath = @"D:\TestDicom.dcm";
//using (var fs = new FileStream(localPath, FileMode.Create, FileAccess.Write))
//{
// ms.CopyTo(fs);
//}
//return new DicomCStoreResponse(request, DicomStatus.Success);
#endregion
// 直接写入内存
await using var ms = new MemoryStream();
await dicomFile.SaveAsync(ms);
ms.Position = 0;
//irc 从路径最后一截取Guid
storeRelativePath = await ossService.UploadToOSSAsync(ms, ossFolderPath, instanceId.ToString(), false);
fileSize = ms.Length;
var @lock = _distributedLockProvider.CreateLock($"{studyInstanceUid}");
using (await @lock.AcquireAsync())
{
try
{
var scpStudyId = await dicomArchiveService.ArchiveDicomFileAsync(dicomFile, _trialId, _trialSiteId, storeRelativePath, Association.CallingAE, Association.CalledAE, fileSize);
var series = await _seriesRepository.FirstOrDefaultAsync(t => t.Id == seriesId);
//没有缩略图
if (series != null && string.IsNullOrEmpty(series.ImageResizePath))
{ {
Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE} 传输处理异常:{ex.ToString()}"); // 生成缩略图
using (var memoryStream = new MemoryStream())
if (_ImageUploadList.Any(t => t.StudyInstanceUid == studyInstanceUid))
{ {
var find = _ImageUploadList.FirstOrDefault(t => t.StudyInstanceUid.Equals(studyInstanceUid)); DicomImage image = new DicomImage(dicomFile.Dataset);
find.FailedImageCount++; var sharpimage = image.RenderImage().AsSharpImage();
sharpimage.Save(memoryStream, new JpegEncoder());
// 上传缩略图到 OSS
var seriesPath = await ossService.UploadToOSSAsync(memoryStream, ossFolderPath, $"{seriesId.ToString()}_{instanceId.ToString()}.preview.jpg", false);
series.ImageResizePath = seriesPath;
} }
}
await _seriesRepository.SaveChangesAsync();
if (_ImageUploadList.Any(t => t.StudyInstanceUid == studyInstanceUid))
{
var find = _ImageUploadList.FirstOrDefault(t => t.StudyInstanceUid.Equals(studyInstanceUid));
find.SuccessImageCount++;
if (!find.PatientNameList.Any(t => t == patientIdStr) && patientIdStr.IsNotNullOrEmpty())
{
find.PatientNameList.Add(patientIdStr);
}
//首次 (默认是Guid 空,数据库归档出了Id)
if (find.SCPStudyId != scpStudyId)
{
find.SCPStudyId = scpStudyId;
}
}
//监控信息设置
_upload.FileCount++;
_upload.FileSize = _upload.FileSize + fileSize;
}
catch (Exception ex)
{
Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE} 传输处理异常:{ex.ToString()}");
if (_ImageUploadList.Any(t => t.StudyInstanceUid == studyInstanceUid))
{
var find = _ImageUploadList.FirstOrDefault(t => t.StudyInstanceUid.Equals(studyInstanceUid));
find.FailedImageCount++;
} }
} }
} }
Log.Logger.Information($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE} {request.SOPInstanceUID} 上传完成 "); Log.Logger.Information($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE} {request.SOPInstanceUID} 上传完成 ");
+2 -65
View File
@@ -22,11 +22,7 @@ namespace IRaCIS.Core.SCP.Service
public class DicomArchiveService(IRepository<SCPPatient> _patientRepository, public class DicomArchiveService(IRepository<SCPPatient> _patientRepository,
IRepository<SCPStudy> _studyRepository, IRepository<SCPStudy> _studyRepository,
IRepository<SCPSeries> _seriesRepository, IRepository<SCPSeries> _seriesRepository,
IRepository<SCPInstance> _instanceRepository, IRepository<SCPInstance> _instanceRepository
IDistributedLockProvider _distributedLockProvider,
IRepository<SystemAnonymization> _systemAnonymizationRepository,
IRepository<TrialSite> _trialSiteRepository,
IFusionCache _fusionCache
) : BaseService, IDicomArchiveService ) : BaseService, IDicomArchiveService
{ {
@@ -45,66 +41,6 @@ namespace IRaCIS.Core.SCP.Service
var dataset = dicomFile.Dataset; var dataset = dicomFile.Dataset;
#region
var anonymizeList = await _fusionCache.GetOrSetAsync(CacheKeys.SystemAnonymization, _ => CacheHelper.GetSystemAnonymizationListAsync(_systemAnonymizationRepository), TimeSpan.FromDays(7));
var trialSiteInfo = await _fusionCache.GetOrSetAsync(CacheKeys.TrialSiteInfo(trialSiteId), _ => CacheHelper.GetTrialSiteInfo(trialSiteId, _trialSiteRepository), TimeSpan.FromMinutes(2));
var fixedFiledList = anonymizeList.Where(t => t.IsFixed).ToList();
var ircFiledList = anonymizeList.Where(t => t.IsFixed == false).ToList();
foreach (var item in fixedFiledList)
{
var dicomTag = new DicomTag(Convert.ToUInt16(item.Group, 16), Convert.ToUInt16(item.Element, 16));
dataset.AddOrUpdate(dicomTag, item.ReplaceValue);
}
foreach (var item in ircFiledList)
{
var dicomTag = new DicomTag(Convert.ToUInt16(item.Group, 16), Convert.ToUInt16(item.Element, 16));
if (dicomTag == DicomTag.ClinicalTrialProtocolID)
{
dataset.AddOrUpdate(dicomTag, trialSiteInfo.TrialCode);
}
if (dicomTag == DicomTag.ClinicalTrialSiteID)
{
dataset.AddOrUpdate(dicomTag, trialSiteInfo.TrialSiteCode);
}
if (dicomTag == DicomTag.ClinicalTrialSubjectID)
{
dataset.AddOrUpdate(dicomTag, "");
}
if (dicomTag == DicomTag.ClinicalTrialTimePointID)
{
dataset.AddOrUpdate(dicomTag, "");
}
if (dicomTag == DicomTag.PatientID)
{
var pid = dataset.GetSingleValueOrDefault(DicomTag.PatientID, string.Empty);
dataset.AddOrUpdate(dicomTag, trialSiteInfo.TrialCode + "_" + pid);
}
}
#endregion
string studyInstanceUid = dataset.GetString(DicomTag.StudyInstanceUID); string studyInstanceUid = dataset.GetString(DicomTag.StudyInstanceUID);
string seriesInstanceUid = dataset.GetString(DicomTag.SeriesInstanceUID); string seriesInstanceUid = dataset.GetString(DicomTag.SeriesInstanceUID);
string sopInstanceUid = dataset.GetString(DicomTag.SOPInstanceUID); string sopInstanceUid = dataset.GetString(DicomTag.SOPInstanceUID);
@@ -293,6 +229,7 @@ namespace IRaCIS.Core.SCP.Service
findStudy.DicomStudyTime = dataset.GetSingleValueOrDefault(DicomTag.StudyTime, string.Empty); findStudy.DicomStudyTime = dataset.GetSingleValueOrDefault(DicomTag.StudyTime, string.Empty);
findStudy.CalledAE = calledAE; findStudy.CalledAE = calledAE;
findStudy.CallingAE = callingAE; findStudy.CallingAE = callingAE;
findStudy.PatientIdStr = patientIdStr;
findStudy.PatientName = dataset.GetSingleValueOrDefault(DicomTag.PatientName, string.Empty); findStudy.PatientName = dataset.GetSingleValueOrDefault(DicomTag.PatientName, string.Empty);
findStudy.PatientSex = dataset.GetSingleValueOrDefault(DicomTag.PatientSex, string.Empty); findStudy.PatientSex = dataset.GetSingleValueOrDefault(DicomTag.PatientSex, string.Empty);
findStudy.PatientAge = dataset.GetSingleValueOrDefault(DicomTag.PatientAge, string.Empty); findStudy.PatientAge = dataset.GetSingleValueOrDefault(DicomTag.PatientAge, string.Empty);
+6
View File
@@ -96,6 +96,12 @@ builder.Services.AddJsonLocalization(options => options.ResourcesPath = "Resourc
// 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim() // 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim()
builder.Services.AddControllers(options => builder.Services.AddControllers(options =>
{ {
// 关键配置:禁用不可空引用类型的自动 Required 验证
options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true;
// 插到最前,抢在默认绑定器之前
//options.ModelBinderProviders.Insert(0, new SpecificNullableBinderProvider());
options.Filters.Add<ModelActionFilter>(); options.Filters.Add<ModelActionFilter>();
options.Filters.Add<ProjectExceptionFilter>(); options.Filters.Add<ProjectExceptionFilter>();
options.Filters.Add<UnitOfWorkFilter>(); options.Filters.Add<UnitOfWorkFilter>();
@@ -71,29 +71,27 @@ namespace IRaCIS.Core.API
DateTime dateTime; DateTime dateTime;
if (reader.ValueType == typeof(DateTime) || reader.ValueType == typeof(DateTime?)) // 2. 检查目标类型是否可空
bool isNullable = objectType == typeof(DateTime?);
var canConvert = DateTime.TryParse(reader.Value?.ToString(), out dateTime);
if (isNullable == false && canConvert == false)
{ {
DateTime? nullableDateTime = reader.Value as DateTime?;
throw new JsonSerializationException($"Could not convert string to DateTime: {reader.Value} Path {reader.Path}");
if (nullableDateTime != null && nullableDateTime.HasValue)
{
dateTime = nullableDateTime.Value;
}
else
{
return null;
}
} }
else else
{ {
if (DateTime.TryParse((string)reader.Value, out dateTime) == false) if (canConvert == false)
{ {
return null; return null;
} }
} }
////如果前端传递带时区的,那么转换会报错,需要DateTimeKind.Unspecified
//dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Unspecified);
// 将客户端时间转换为服务器时区的时间 // 将客户端时间转换为服务器时区的时间
var serverZoneTime = TimeZoneInfo.ConvertTime(dateTime, _clientTimeZone, TimeZoneInfo.Local); var serverZoneTime = TimeZoneInfo.ConvertTime(dateTime, _clientTimeZone, TimeZoneInfo.Local);
@@ -113,7 +111,10 @@ namespace IRaCIS.Core.API
//第一个参数默认使用系统本地时区 也就是应用服务器的时区 //第一个参数默认使用系统本地时区 也就是应用服务器的时区
DateTime clientZoneTime = TimeZoneInfo.ConvertTime(nullableDateTime.Value, _clientTimeZone); DateTime clientZoneTime = TimeZoneInfo.ConvertTime(nullableDateTime.Value, _clientTimeZone);
//writer.WriteValue(clientZoneTime);
//// 最简单的方式:创建 DateTimeOffset
//DateTimeOffset dateTimeOffset = new DateTimeOffset(clientZoneTime, _clientTimeZone.GetUtcOffset(clientZoneTime));
//writer.WriteValue(dateTimeOffset.ToString("yyyy-MM-dd HH:mm:sszzz"));
writer.WriteValue(clientZoneTime.ToString(_dateFormat)); writer.WriteValue(clientZoneTime.ToString(_dateFormat));
} }
@@ -3,8 +3,10 @@ using Newtonsoft.Json;
using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Serialization;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Reflection.Metadata;
namespace IRaCIS.Core.API namespace IRaCIS.Core.API
{ {
@@ -51,34 +53,90 @@ namespace IRaCIS.Core.API
} }
public class NullToEmptyStringValueProvider : IValueProvider public class NullToEmptyStringValueProvider : IValueProvider
{ {
PropertyInfo _MemberInfo; PropertyInfo _memberInfo;
private readonly bool _isNullable;
public NullToEmptyStringValueProvider(PropertyInfo memberInfo) public NullToEmptyStringValueProvider(PropertyInfo memberInfo)
{ {
_MemberInfo = memberInfo; _memberInfo = memberInfo;
} }
// DTO → JSON 返回前端的时候 处理null 变为"" 方便前端判断
public object GetValue(object target) public object GetValue(object target)
{ {
object result = _MemberInfo.GetValue(target); var result = _memberInfo.GetValue(target);
if (_MemberInfo.PropertyType == typeof(string) && result == null) result = ""; // 检查类型是否为string或string?
else if (_MemberInfo.PropertyType == typeof(String[]) && result == null) result = new string[] { }; if (_memberInfo.PropertyType == typeof(string) && result == null)
//else if (_MemberInfo.PropertyType == typeof(Nullable<Int32>) && result == null) result = 0; {
//else if (_MemberInfo.PropertyType == typeof(Nullable<Decimal>) && result == null) result = 0.00M;
#region string string? null ""
//// 如果是string?类型,返回null 可以做到,但是得反射,因为 string string? 是编译层区分的
//var isNullable1 = _memberInfo.CustomAttributes
// .Any(a => a.AttributeType.Name == "NullableAttribute");
////var isNullable2 = _memberInfo.CustomAttributes
//// .Any(a => a.AttributeType.FullName == "System.Runtime.CompilerServices.NullableAttribute");
//if (isNullable1)
//{
// return result;
//}
#endregion
// 如果是string类型,返回空字符串
return string.Empty;
}
return result; return result;
} }
//影响 模型绑定时接收前端的值,同时影响 正常 JSON 序列化
public void SetValue(object target, object value) public void SetValue(object target, object value)
{ {
if (_MemberInfo.PropertyType == typeof(string)) _memberInfo.SetValue(target, value);
{
//去掉前后空格 #region string null
_MemberInfo.SetValue(target, value == null ? string.Empty : value.ToString() == string.Empty ? value : value/*.ToString().Trim()*/);
//if (_memberInfo.PropertyType == typeof(string))
//{
// _memberInfo.SetValue(target, value == null ? string.Empty : value);
//}
//else
//{
// _memberInfo.SetValue(target, value);
//}
#endregion
#region string string?
//////接收模型的时候 定义的明明是string 但是上面也有该属性,判断不准的 比如阅片跟踪列表查询
//var isNullable1 = _memberInfo.CustomAttributes.Any(a => a.AttributeType.Name == "NullableAttribute");
////不影响 string? 传递null 变为""
//if (_memberInfo.PropertyType == typeof(string) && isNullable1 == false)
//{
// //如果不处理 前段传递null string不会接收,说前段没传递会验证报错
// _memberInfo.SetValue(target, value == null ? string.Empty : value);
//}
//else
//{
// _memberInfo.SetValue(target, value);
//}
#endregion
}
else
{
_MemberInfo.SetValue(target, value);
}
} }
} }
+2 -2
View File
@@ -57,8 +57,8 @@
// 模板类型 1 Elevate 2 Extensive // 模板类型 1 Elevate 2 Extensive
"TemplateType": 2, "TemplateType": 2,
//MFA免验证发送天数
"UserMFAVerifyDays": 1 "UserMFAVerifyMinutes": 1440
}, },
"SystemEmailSendConfig": { "SystemEmailSendConfig": {
"Port": 465, "Port": 465,
+1 -1
View File
@@ -56,7 +56,7 @@
// 模板类型 1 Elevate 2 Extensive // 模板类型 1 Elevate 2 Extensive
"TemplateType": 2, "TemplateType": 2,
//MFA免验证发送天数 //MFA免验证发送天数
"UserMFAVerifyDays": 1 "UserMFAVerifyMinutes": 1440
}, },
"SystemEmailSendConfig": { "SystemEmailSendConfig": {
+2 -2
View File
@@ -59,8 +59,8 @@
"TemplateType": 1, "TemplateType": 1,
"OpenTrialRelationDelete": false, "OpenTrialRelationDelete": false,
//MFA免验证发送天数 //MFA免验证
"UserMFAVerifyDays": 1 "UserMFAVerifyMinutes": 1440
}, },
+2 -1
View File
@@ -69,7 +69,8 @@
"TemplateType": 1, "TemplateType": 1,
"OpenLoginMFA": true, "OpenLoginMFA": true,
//MFA免验证发送天数 //MFA免验证发送天数
"UserMFAVerifyDays": 1 "UserMFAVerifyMinutes": 1440
}, },
"SystemEmailSendConfig": { "SystemEmailSendConfig": {
+1 -1
View File
@@ -68,7 +68,7 @@
// 模板类型 1 Elevate 2 Extensive // 模板类型 1 Elevate 2 Extensive
"TemplateType": 1, "TemplateType": 1,
//MFA免验证发送天数 //MFA免验证发送天数
"UserMFAVerifyDays": 1 "UserMFAVerifyMinutes": 1440
}, },
"SystemEmailSendConfig": { "SystemEmailSendConfig": {
+1 -1
View File
@@ -75,7 +75,7 @@
// 模板类型 1 Elevate 2 Extensive // 模板类型 1 Elevate 2 Extensive
"TemplateType": 2, "TemplateType": 2,
//MFA免验证发送天数 //MFA免验证发送天数
"UserMFAVerifyDays": 1 "UserMFAVerifyMinutes": 1440
}, },
"SystemEmailSendConfig": { "SystemEmailSendConfig": {
@@ -1,7 +1,11 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.Reflection;
namespace IRaCIS.Core.Application.Filter; namespace IRaCIS.Core.Application.Filter;
@@ -28,3 +32,7 @@ public class ModelActionFilter(IStringLocalizer _localizer) : ActionFilterAttrib
} }
} }
} }
@@ -46,7 +46,7 @@ public class ProjectExceptionFilter(ILogger<ProjectExceptionFilter> _logger, ISt
else else
{ {
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (exception.InnerException is null ? (exception.Message) context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (exception.InnerException is null ? (exception.Message)
: (exception.InnerException?.Message )), ApiResponseCodeEnum.ProgramException)); : (exception.Message + "Inner ExceptionMsg:" + exception.InnerException?.Message)), ApiResponseCodeEnum.ProgramException));
} }
@@ -64,6 +64,8 @@ public static class CacheKeys
//每个用户 每个浏览器独立时间 //每个用户 每个浏览器独立时间
public static string UserMFAVerifyPass(Guid userId,string browserFingerprint) => $"UserMFAVerifyPass:{userId}:{browserFingerprint}"; public static string UserMFAVerifyPass(Guid userId,string browserFingerprint) => $"UserMFAVerifyPass:{userId}:{browserFingerprint}";
public static string UserMFATag(Guid userId) => $"UserMFAVerifyPass:{userId}";
} }
public static class CacheHelper public static class CacheHelper
@@ -1,4 +1,5 @@
using FellowOakDicom; using DocumentFormat.OpenXml.Office.CustomUI;
using FellowOakDicom;
using FellowOakDicom.Media; using FellowOakDicom.Media;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -57,6 +58,7 @@ namespace IRaCIS.Core.Application.Helper
var mappings = new List<string>(); var mappings = new List<string>();
int index = 1; int index = 1;
var studyUid=list.FirstOrDefault()?.StudyInstanceUid;
var dicomDir = new DicomDirectory(); var dicomDir = new DicomDirectory();
@@ -128,7 +130,9 @@ namespace IRaCIS.Core.Application.Helper
// 重置流位置 // 重置流位置
memoryStream.Position = 0; memoryStream.Position = 0;
await _oSSService.UploadToOSSAsync(memoryStream, ossFolder, "DICOMDIR", false); var relativePath= await _oSSService.UploadToOSSAsync(memoryStream, ossFolder, "DICOMDIR", true);
dic.Add($"{studyUid}_DICOMDIR" , relativePath.Split('/').Last());
} }
//清理临时文件 //清理临时文件
@@ -18,6 +18,7 @@ using NPOI.HSSF.UserModel;
using NPOI.SS.Formula.Functions; using NPOI.SS.Formula.Functions;
using NPOI.SS.UserModel; using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel; using NPOI.XSSF.UserModel;
using SharpCompress.Common;
using System.Collections; using System.Collections;
using System.Globalization; using System.Globalization;
using Xceed.Document.NET; using Xceed.Document.NET;
@@ -870,17 +871,16 @@ public static class ExcelExportHelper
//模板路径 //模板路径
var tplPath = physicalPath; var tplPath = physicalPath;
#region sheet
// 打开模板文件
var templateFile = new FileStream(tplPath, FileMode.Open, FileAccess.Read);
// 获取文件流 // 获取文件流
var templateStream = new MemoryStream(); var templateStream = new MemoryStream();
templateFile.CopyTo(templateStream);
templateStream.Seek(0, SeekOrigin.Begin);
var workbook = new XSSFWorkbook(templateStream); #region sheet
// 打开模板文件
var templateFileStream = new FileStream(tplPath, FileMode.Open, FileAccess.Read);
var workbook = new XSSFWorkbook(templateFileStream);
int sheetCount = workbook.NumberOfSheets; int sheetCount = workbook.NumberOfSheets;
@@ -985,14 +985,8 @@ public static class ExcelExportHelper
} }
} }
using (var memoryStream2 = new MemoryStream()) workbook.Write(templateStream, leaveOpen: true);
{ templateStream.Position = 0;
workbook.Write(memoryStream2, true);
memoryStream2.Seek(0, SeekOrigin.Begin);
templateStream = memoryStream2;
}
} }
@@ -1099,6 +1093,63 @@ public static class ExcelExportHelper
//模板路径 //模板路径
var tplPath = physicalPath; var tplPath = physicalPath;
var templateStream = new MemoryStream();
#region npoi
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
if (isEn_US)
{
// 打开模板文件
using var templateFileStream = new FileStream(tplPath, FileMode.Open, FileAccess.Read);
using var workbook = new XSSFWorkbook(templateFileStream);
int sheetCount = workbook.NumberOfSheets;
int removeRowIndex = 1; // 要删除的行(0-based
for (int i = 0; i < sheetCount; i++)
{
var sheet = workbook.GetSheetAt(i);
// 2 删除行
var row = sheet.GetRow(removeRowIndex);
if (row != null)
{
sheet.RemoveRow(row);
}
// 3 上移后续行
if (removeRowIndex < sheet.LastRowNum)
{
sheet.ShiftRows(
removeRowIndex + 1,
sheet.LastRowNum,
-1,
true, // copyRowHeight
false // resetOriginalRowHeight
);
}
}
workbook.Write(templateStream, leaveOpen: true);
templateStream.Position = 0;
}
else
{
using (var fs = new FileStream(tplPath, FileMode.Open, FileAccess.Read))
{
fs.CopyTo(templateStream);
}
templateStream.Position = 0;
}
#endregion
var memoryStream = new MemoryStream(); var memoryStream = new MemoryStream();
@@ -1107,7 +1158,7 @@ public static class ExcelExportHelper
IgnoreTemplateParameterMissing = true, IgnoreTemplateParameterMissing = true,
}; };
await MiniExcel.SaveAsByTemplateAsync(memoryStream, tplPath, data, config); await MiniExcel.SaveAsByTemplateAsync(memoryStream, templateStream.ToArray(), data, config);
memoryStream.Seek(0, SeekOrigin.Begin); memoryStream.Seek(0, SeekOrigin.Begin);
+49 -28
View File
@@ -160,7 +160,7 @@ public interface IOSSService
public Task DeleteFromPrefix(string prefix, bool isCache = false); public Task DeleteFromPrefix(string prefix, bool isCache = false);
public Task DeleteObjects(List<string> objectKeys); public Task DeleteObjects(List<string> objectKeys, bool isCache = false);
List<string> GetRootFolderNames(); List<string> GetRootFolderNames();
@@ -249,7 +249,7 @@ public class OSSService : IOSSService
LifeCycleExpiration = LifeCycleExpiration =
{ {
Days = 30 Days = 30 //最后一次修改时间
}, },
StorageClass = StorageClass.Archive StorageClass = StorageClass.Archive
} }
@@ -302,8 +302,8 @@ public class OSSService : IOSSService
//提供awsEndPoint(域名)进行访问配置 //提供awsEndPoint(域名)进行访问配置
var clientConfig = new AmazonS3Config var clientConfig = new AmazonS3Config
{ {
RegionEndpoint = RegionEndpoint.USEast1, RegionEndpoint = RegionEndpoint.GetBySystemName(awsConfig.Region)
UseHttp = true, //,UseHttp = true,
}; };
var amazonS3Client = new AmazonS3Client(credentials, clientConfig); var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
@@ -333,15 +333,15 @@ public class OSSService : IOSSService
Transitions = new List<LifecycleTransition> Transitions = new List<LifecycleTransition>
{ {
// 1天后转为低频访问 (Standard-IA) // 1天后转为低频访问 (Standard-IA)
new LifecycleTransition //new LifecycleTransition
{ //{
Days = 1, // Days = 1, //Days' in Transition action must be greater than or equal to 30 for storageClass 'STANDARD_IA'"
StorageClass = S3StorageClass.StandardInfrequentAccess // 对应S3 Standard-IA // StorageClass = S3StorageClass.StandardInfrequentAccess // 对应S3 Standard-IA
}, //},
// 30天后转为归档 (Glacier Instant Retrieval) // 30天后转为归档 (Glacier Instant Retrieval)
new LifecycleTransition new LifecycleTransition
{ {
Days = 30, Days = 30, //创建时间
StorageClass = S3StorageClass.GlacierInstantRetrieval // 对应归档(即时检索) StorageClass = S3StorageClass.GlacierInstantRetrieval // 对应归档(即时检索)
} }
// 如果需要更深的归档,可以继续添加: // 如果需要更深的归档,可以继续添加:
@@ -765,8 +765,8 @@ public class OSSService : IOSSService
//提供awsEndPoint(域名)进行访问配置 //提供awsEndPoint(域名)进行访问配置
var clientConfig = new AmazonS3Config var clientConfig = new AmazonS3Config
{ {
RegionEndpoint = RegionEndpoint.USEast1, RegionEndpoint = RegionEndpoint.GetBySystemName(awsConfig.Region)
UseHttp = true, //,UseHttp = true,
}; };
var amazonS3Client = new AmazonS3Client(credentials, clientConfig); var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
@@ -891,8 +891,8 @@ public class OSSService : IOSSService
//提供awsEndPoint(域名)进行访问配置 //提供awsEndPoint(域名)进行访问配置
var clientConfig = new AmazonS3Config var clientConfig = new AmazonS3Config
{ {
RegionEndpoint = RegionEndpoint.USEast1, RegionEndpoint = RegionEndpoint.GetBySystemName(awsConfig.Region)
UseHttp = true, //,UseHttp = true,
}; };
var amazonS3Client = new AmazonS3Client(credentials, clientConfig); var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
@@ -966,8 +966,8 @@ public class OSSService : IOSSService
//提供awsEndPoint(域名)进行访问配置 //提供awsEndPoint(域名)进行访问配置
var clientConfig = new AmazonS3Config var clientConfig = new AmazonS3Config
{ {
RegionEndpoint = RegionEndpoint.USEast1, RegionEndpoint = RegionEndpoint.GetBySystemName(awsConfig.Region)
UseHttp = true, //,UseHttp = true,
}; };
var amazonS3Client = new AmazonS3Client(credentials, clientConfig); var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
@@ -1172,8 +1172,8 @@ public class OSSService : IOSSService
//提供awsEndPoint(域名)进行访问配置 //提供awsEndPoint(域名)进行访问配置
var clientConfig = new AmazonS3Config var clientConfig = new AmazonS3Config
{ {
RegionEndpoint = RegionEndpoint.USEast1, RegionEndpoint = RegionEndpoint.GetBySystemName(awsConfig.Region)
UseHttp = true, //,UseHttp = true,
}; };
var amazonS3Client = new AmazonS3Client(credentials, clientConfig); var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
@@ -1546,8 +1546,8 @@ public class OSSService : IOSSService
//提供awsEndPoint(域名)进行访问配置 //提供awsEndPoint(域名)进行访问配置
var clientConfig = new AmazonS3Config var clientConfig = new AmazonS3Config
{ {
RegionEndpoint = RegionEndpoint.USEast1, RegionEndpoint = RegionEndpoint.GetBySystemName(awsConfig.Region)
UseHttp = true, //,UseHttp = true,
}; };
var amazonS3Client = new AmazonS3Client(credentials, clientConfig); var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
@@ -1561,7 +1561,7 @@ public class OSSService : IOSSService
var listObjectsResponse = await amazonS3Client.ListObjectsV2Async(listObjectsRequest); var listObjectsResponse = await amazonS3Client.ListObjectsV2Async(listObjectsRequest);
if (listObjectsResponse.S3Objects.Count > 0) if (listObjectsResponse.S3Objects?.Count > 0)
{ {
// 准备删除请求 // 准备删除请求
var deleteObjectsRequest = new Amazon.S3.Model.DeleteObjectsRequest var deleteObjectsRequest = new Amazon.S3.Model.DeleteObjectsRequest
@@ -1591,7 +1591,7 @@ public class OSSService : IOSSService
} }
} }
public async Task DeleteObjects(List<string> objectKeys) public async Task DeleteObjects(List<string> objectKeys, bool isCache = false)
{ {
GetObjectStoreTempToken(); GetObjectStoreTempToken();
@@ -1601,9 +1601,23 @@ public class OSSService : IOSSService
var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken); var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
var bucketName = string.Empty;
if (isCache)
{
Uri uri = new Uri(aliConfig.ViewEndpoint);
string host = uri.Host; // 获取 "zy-irc-test-dev-cache.oss-cn-shanghai.aliyuncs.com"
string[] parts = host.Split('.');
bucketName = parts[0];
}
else
{
bucketName = aliConfig.BucketName;
}
if (objectKeys.Count > 0) if (objectKeys.Count > 0)
{ {
var result = _ossClient.DeleteObjects(new Aliyun.OSS.DeleteObjectsRequest(aliConfig.BucketName, objectKeys, false)); var result = _ossClient.DeleteObjects(new Aliyun.OSS.DeleteObjectsRequest(bucketName, objectKeys, false));
} }
} }
@@ -1639,8 +1653,8 @@ public class OSSService : IOSSService
//提供awsEndPoint(域名)进行访问配置 //提供awsEndPoint(域名)进行访问配置
var clientConfig = new AmazonS3Config var clientConfig = new AmazonS3Config
{ {
RegionEndpoint = RegionEndpoint.USEast1, RegionEndpoint = RegionEndpoint.GetBySystemName(awsConfig.Region)
UseHttp = true, //,UseHttp = true,
}; };
var amazonS3Client = new AmazonS3Client(credentials, clientConfig); var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
@@ -1714,8 +1728,8 @@ public class OSSService : IOSSService
//提供awsEndPoint(域名)进行访问配置 //提供awsEndPoint(域名)进行访问配置
var clientConfig = new AmazonS3Config var clientConfig = new AmazonS3Config
{ {
RegionEndpoint = RegionEndpoint.USEast1, RegionEndpoint = RegionEndpoint.GetBySystemName(awsConfig.Region)
UseHttp = true, //,UseHttp = true,
}; };
var request = new Amazon.S3.Model.GetObjectMetadataRequest var request = new Amazon.S3.Model.GetObjectMetadataRequest
@@ -1799,9 +1813,16 @@ public class OSSService : IOSSService
{ {
var awsOptions = ObjectStoreServiceOptions.AWS; var awsOptions = ObjectStoreServiceOptions.AWS;
// 创建 STS 客户端(考虑使用 RegionEndpoint
var stsConfig = new AmazonSecurityTokenServiceConfig
{
RegionEndpoint = RegionEndpoint.GetBySystemName(awsOptions.Region)
};
//aws 临时凭证 //aws 临时凭证
// 创建 STS 客户端 // 创建 STS 客户端
var stsClient = new AmazonSecurityTokenServiceClient(awsOptions.AccessKeyId, awsOptions.SecretAccessKey); var stsClient = new AmazonSecurityTokenServiceClient(awsOptions.AccessKeyId, awsOptions.SecretAccessKey, stsConfig);
// 使用 AssumeRole 请求临时凭证 // 使用 AssumeRole 请求临时凭证
var assumeRoleRequest = new AssumeRoleRequest var assumeRoleRequest = new AssumeRoleRequest
@@ -19195,6 +19195,13 @@
<param name="tpCode"></param> <param name="tpCode"></param>
<param name="key"></param> <param name="key"></param>
</member> </member>
<member name="M:IRaCIS.Core.Application.Services.SeriesService.UpdateImageResizePath(IRaCIS.Core.Application.Contracts.Dicom.DTO.UpdateImageResizeDTO)">
<summary>
更新缩略图路径
</summary>
<param name="dto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Services.SeriesService.List(System.Guid,System.Nullable{System.Boolean},System.Nullable{System.Boolean})"> <member name="M:IRaCIS.Core.Application.Services.SeriesService.List(System.Guid,System.Nullable{System.Boolean},System.Nullable{System.Boolean})">
<summary> 指定资源Id,获取Dicom检查所属序列信息列表 </summary> <summary> 指定资源Id,获取Dicom检查所属序列信息列表 </summary>
<param name="studyId"> Dicom检查的Id </param> <param name="studyId"> Dicom检查的Id </param>
@@ -17,6 +17,7 @@ using MassTransit;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.Linq;
using System.Linq.Dynamic.Core; using System.Linq.Dynamic.Core;
using Subject = IRaCIS.Core.Domain.Models.Subject; using Subject = IRaCIS.Core.Domain.Models.Subject;
@@ -1172,7 +1173,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
var visitQuery = _visitTaskRepository.Where(x => x.TrialId == trialId && x.DoctorUserId == _userInfo.UserRoleId && x.TaskState == TaskState.Effect) var visitQuery = _visitTaskRepository.Where(x => x.TrialId == trialId && x.DoctorUserId == _userInfo.UserRoleId && x.TaskState == TaskState.Effect)
.WhereIf(inQuery.SubjectId != null, x => x.SubjectId == inQuery.SubjectId) .WhereIf(inQuery.SubjectId != null, x => x.SubjectId == inQuery.SubjectId)
.WhereIf(!string.IsNullOrEmpty(subjectCode), t => (t.Subject.Code.Contains(subjectCode!) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(subjectCode!) && t.IsAnalysisCreate)) .WhereIf(!string.IsNullOrEmpty(subjectCode), t => (t.Subject.Code.Contains(subjectCode!) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(subjectCode!) && t.IsAnalysisCreate))
.WhereIf(critrion.CriterionType == CriterionType.OCT, t => t.ReadingCategory == ReadingCategory.Visit ? t.SourceSubjectVisit.NoneDicomStudyList.Where(t=>t.Modality=="OCT").SelectMany(t => t.ImageLabelNoneDicomFileList).Any() : true) .WhereIf(critrion.CriterionType == CriterionType.OCT, t => t.ReadingCategory == ReadingCategory.Visit ? t.SourceSubjectVisit.NoneDicomStudyList.Where(t => t.Modality == "OCT").SelectMany(t => t.ImageLabelNoneDicomFileList).Any() : true)
.WhereIf(critrion.CriterionType == CriterionType.IVUS, t => t.ReadingCategory == ReadingCategory.Visit ? t.SourceSubjectVisit.NoneDicomStudyList.Where(t => t.Modality == "IVUS").SelectMany(t => t.ImageLabelNoneDicomFileList).Any() : true); .WhereIf(critrion.CriterionType == CriterionType.IVUS, t => t.ReadingCategory == ReadingCategory.Visit ? t.SourceSubjectVisit.NoneDicomStudyList.Where(t => t.Modality == "IVUS").SelectMany(t => t.ImageLabelNoneDicomFileList).Any() : true);
var visitGroupQuery = visitQuery.GroupBy(x => new { x.SubjectId, x.Subject.Code, x.BlindSubjectCode }); var visitGroupQuery = visitQuery.GroupBy(x => new { x.SubjectId, x.Subject.Code, x.BlindSubjectCode });
@@ -2292,12 +2293,12 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
foreach (var item in readingTableAnswerRowInfoList) foreach (var item in readingTableAnswerRowInfoList)
{ {
if (item.SplitRowId!=null&&lesionRelationship.ContainsKey(item.SplitRowId.Value)) if (item.SplitRowId != null && lesionRelationship.ContainsKey(item.SplitRowId.Value))
{ {
item.SplitRowId = lesionRelationship[item.SplitRowId.Value]; item.SplitRowId = lesionRelationship[item.SplitRowId.Value];
} }
if (item.MergeRowId!=null&&lesionRelationship.ContainsKey(item.MergeRowId.Value)) if (item.MergeRowId != null && lesionRelationship.ContainsKey(item.MergeRowId.Value))
{ {
item.MergeRowId = lesionRelationship[item.MergeRowId.Value]; item.MergeRowId = lesionRelationship[item.MergeRowId.Value];
} }
@@ -2402,6 +2403,10 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
//另一个阅片人的任务根据任务进度自动进入PM退回或PM申请重阅 //另一个阅片人的任务根据任务进度自动进入PM退回或PM申请重阅
filterExpression = filterExpression.And(t => t.VisitTaskNum >= task.VisitTaskNum); filterExpression = filterExpression.And(t => t.VisitTaskNum >= task.VisitTaskNum);
//退回只影响有序的后续所有的,无序的当前访视
filterExpression = filterExpression.And(t => (t.TrialReadingCriterion.IsReadingTaskViewInOrder == ReadingOrder.InOrder) ||
(t.TrialReadingCriterion.IsReadingTaskViewInOrder != ReadingOrder.InOrder && t.SourceSubjectVisitId == task.SourceSubjectVisitId));
var influenceTaskList = await _visitTaskRepository.Where(filterExpression, true).ToListAsync(); var influenceTaskList = await _visitTaskRepository.Where(filterExpression, true).ToListAsync();
@@ -2559,9 +2564,12 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
//删除序列数据 //删除序列数据
await _subjectCriteriaEvaluationVisitStudyFilterRepository.BatchDeleteNoTrackingAsync(t => t.TrialReadingCriterion.CriterionType == CriterionType.RECIST1Pointt1_MB && t.SubjectVisit.SubjectId == task.SubjectId && t.SubjectVisitId == task.SourceSubjectVisitId); await _subjectCriteriaEvaluationVisitStudyFilterRepository.BatchDeleteNoTrackingAsync(t => t.TrialReadingCriterion.CriterionType == CriterionType.RECIST1Pointt1_MB && t.SubjectVisit.SubjectId == task.SubjectId && t.SubjectVisitId == task.SourceSubjectVisitId);
otherVisitIdList = otherVisitIdList.Where(t => t != task.SourceSubjectVisitId.Value).ToList();
} }
//BM后续访视 ,筛选状态不变,任务生成状态重置(实际该访视任务状态 可能是重阅重置了或者失效了,需要后续生成,或者取消分配了,需要后续重新分配) //BM后续访视 ,筛选状态不变,任务生成状态重置(实际该访视任务状态 可能是重阅重置了或者失效了,需要后续生成,或者取消分配了,需要后续重新分配)
await _subjectCriteriaEvaluationVisitFilterRepository.UpdatePartialFromQueryAsync(t => t.TrialReadingCriterion.CriterionType == CriterionType.RECIST1Pointt1_MB && t.SubjectVisit.SubjectId == task.SubjectId && otherVisitIdList.Contains(t.SubjectVisitId), await _subjectCriteriaEvaluationVisitFilterRepository.UpdatePartialFromQueryAsync(t => t.TrialReadingCriterion.CriterionType == CriterionType.RECIST1Pointt1_MB && t.SubjectVisit.SubjectId == task.SubjectId && otherVisitIdList.Contains(t.SubjectVisitId),
t => new SubjectCriteriaEvaluationVisitFilter() t => new SubjectCriteriaEvaluationVisitFilter()
@@ -2723,6 +2731,13 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
//默认影响的都是该标准的任务 //默认影响的都是该标准的任务
filterExpression = filterExpression.And(t => t.TrialReadingCriterionId == filterObj.TrialReadingCriterionId); filterExpression = filterExpression.And(t => t.TrialReadingCriterionId == filterObj.TrialReadingCriterionId);
} }
//退回只影响有序的后续所有的,无序的当前访视
if (isReReading == false)
{
filterExpression = filterExpression.And(t => (t.TrialReadingCriterion.IsReadingTaskViewInOrder == ReadingOrder.InOrder) ||
(t.TrialReadingCriterion.IsReadingTaskViewInOrder != ReadingOrder.InOrder && t.SourceSubjectVisitId == filterObj.SourceSubjectVisitId));
}
} }
@@ -603,16 +603,21 @@ public class Tumor_CDISC_ExportService(IRepository<ReadingQuestionCriterionTrial
var tu = CreatNewTUExport(task, lesion, visitIndexNoDic, translateDataList, isEn_Us); var tu = CreatNewTUExport(task, lesion, visitIndexNoDic, translateDataList, isEn_Us);
if (lesion.OrganInfoId.HasValue)
if (!tuList.Any(t => t.SubjectCode == task.SubjectCode && t.ARM_TumorNo == $"{task.ArmEnumStr}_{lesion.LessionCode}"))
{ {
tu.BodyPart = _userInfo.IsEn_Us ? trialOrganDic[lesion.OrganInfoId.Value].PartEN : trialOrganDic[lesion.OrganInfoId.Value].Part;
if (lesion.OrganInfoId.HasValue)
{
tu.BodyPart = _userInfo.IsEn_Us ? trialOrganDic[lesion.OrganInfoId.Value].PartEN : trialOrganDic[lesion.OrganInfoId.Value].Part;
}
Fill_Resisit_Lugano_TUExport(tu, lesion);
tuList.Add(tu);
} }
Fill_Resisit_Lugano_TUExport(tu, lesion);
tuList.Add(tu);
#endregion #endregion
@@ -92,6 +92,10 @@ namespace IRaCIS.Core.Application.Contracts
public class UnionDocumentWithConfirmInfoView : UnionDocumentView public class UnionDocumentWithConfirmInfoView : UnionDocumentView
{ {
public DocUserSignType SysDocUserSignType { get; set; }
public bool IsConfirmIdentityUserInner { get; set; }
public Guid TrialId { get; set; } public Guid TrialId { get; set; }
public bool IsNeedSendEmial { get; set; } public bool IsNeedSendEmial { get; set; }
@@ -30,6 +30,7 @@ namespace IRaCIS.Core.Application.ViewModel
public new List<UserTypeEnum> CopyUserTypeList => TrialEmailNoticeUserList.Where(t => t.EmailUserType == EmailUserType.Copy).Select(t => t.UserType).ToList(); public new List<UserTypeEnum> CopyUserTypeList => TrialEmailNoticeUserList.Where(t => t.EmailUserType == EmailUserType.Copy).Select(t => t.UserType).ToList();
public List<CriterionType>? SysCriterionTypeList { get; set; } public List<CriterionType>? SysCriterionTypeList { get; set; }
} }
@@ -127,7 +128,7 @@ namespace IRaCIS.Core.Application.ViewModel
{ {
public Guid SubjectId { get; set; } public Guid SubjectId { get; set; }
public Guid TrialReadingCriterionId { get; set; } public CriterionType CriterionType { get; set; }
public EmailBusinessScenario BusinessScenarioEnum { get; set; } public EmailBusinessScenario BusinessScenarioEnum { get; set; }
} }
@@ -19,6 +19,8 @@ namespace IRaCIS.Core.Application.Contracts
Task<IResponseOutput> UserConfirm(UserConfirmCommand userConfirmCommand); Task<IResponseOutput> UserConfirm(UserConfirmCommand userConfirmCommand);
Task<List<TrialUserDto>> GetTrialUserSelect(Guid trialId); Task<List<TrialUserDto>> GetTrialUserSelect(Guid trialId);
Task<IResponseOutput<PageOutput<UnionDocumentWithConfirmInfoView>>> GetSysDocumentConfirmList(SystemDocQuery inQuery);
//Task<PageOutput<DocumentUnionWithUserStatView>> GetTrialSystemDocumentList(DocumentTrialUnionQuery querySystemDocument); //Task<PageOutput<DocumentUnionWithUserStatView>> GetTrialSystemDocumentList(DocumentTrialUnionQuery querySystemDocument);
//List<TrialUserUnionDocumentView> GetTrialUserDocumentList(Guid trialId); //List<TrialUserUnionDocumentView> GetTrialUserDocumentList(Guid trialId);
@@ -208,6 +208,7 @@ namespace IRaCIS.Core.Application.Services
await _systemDocumentRepository.BatchUpdateNoTrackingAsync(x => inDto.Ids.Contains(x.Id), x => new SystemDocument() await _systemDocumentRepository.BatchUpdateNoTrackingAsync(x => inDto.Ids.Contains(x.Id), x => new SystemDocument()
{ {
IsPublish = true, IsPublish = true,
PublishDate= DateTime.Now,
IsDeleted = false, IsDeleted = false,
}); });
@@ -301,6 +302,7 @@ namespace IRaCIS.Core.Application.Services
{ {
AttachmentCount=sysDoc.SystemDocumentAttachmentList.Where(z=>!z.OffLine).Count(), AttachmentCount=sysDoc.SystemDocumentAttachmentList.Where(z=>!z.OffLine).Count(),
IsSystemDoc = true, IsSystemDoc = true,
IsPublish=sysDoc.IsPublish,
CurrentStaffTrainDays=sysDoc.CurrentStaffTrainDays, CurrentStaffTrainDays=sysDoc.CurrentStaffTrainDays,
NewStaffTrainDays = sysDoc.NewStaffTrainDays, NewStaffTrainDays = sysDoc.NewStaffTrainDays,
Id = sysDoc.Id, Id = sysDoc.Id,
@@ -326,6 +328,7 @@ namespace IRaCIS.Core.Application.Services
//UserTypeShortName = user.UserTypeRole.UserTypeShortName //UserTypeShortName = user.UserTypeRole.UserTypeShortName
}; };
var list = await query var list = await query
//过滤掉删除的,并且没有签名的 //过滤掉删除的,并且没有签名的
.Where(t => !(t.IsDeleted == true && t.ConfirmTime == null)) .Where(t => !(t.IsDeleted == true && t.ConfirmTime == null))
@@ -101,8 +101,9 @@ namespace IRaCIS.Core.Application.Services
await _trialDocumentRepository.UpdatePartialFromQueryAsync(x => inDto.Ids.Contains(x.Id), x => new TrialDocument() await _trialDocumentRepository.UpdatePartialFromQueryAsync(x => inDto.Ids.Contains(x.Id), x => new TrialDocument()
{ {
IsPublish = true, IsPublish = true,
PublishDate = DateTime.Now,
IsDeleted = false, IsDeleted = false,
},false,true); }, false, true);
await _trialDocumentRepository.SaveChangesAsync(); await _trialDocumentRepository.SaveChangesAsync();
Console.WriteLine("开始 发布项目文档"); Console.WriteLine("开始 发布项目文档");
@@ -150,7 +151,7 @@ namespace IRaCIS.Core.Application.Services
{ {
// 从新作用域解析服务 // 从新作用域解析服务
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>(); var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
await mediator.Publish(new ImageQCRecurringEvent { TrialId= Guid.Parse("08de2254-5d7d-581a-0242-0a0001000000") }); await mediator.Publish(new ImageQCRecurringEvent { TrialId = Guid.Parse("08de2254-5d7d-581a-0242-0a0001000000") });
} }
}); });
return ResponseOutput.Result(true); return ResponseOutput.Result(true);
@@ -171,7 +172,7 @@ namespace IRaCIS.Core.Application.Services
.WhereIf(inQuery.UserTypeId != null, t => t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == inQuery.UserTypeId)) .WhereIf(inQuery.UserTypeId != null, t => t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == inQuery.UserTypeId))
.WhereIf(inQuery.IsDeleted != null, t => t.IsDeleted == inQuery.IsDeleted) .WhereIf(inQuery.IsDeleted != null, t => t.IsDeleted == inQuery.IsDeleted)
.WhereIf(inQuery.IsPublish != null, t => t.IsPublish == inQuery.IsPublish) .WhereIf(inQuery.IsPublish != null, t => t.IsPublish == inQuery.IsPublish)
.WhereIf(!string.IsNullOrEmpty(inQuery.FileTypeCode), t => t.FileType.Code== inQuery.FileTypeCode) .WhereIf(!string.IsNullOrEmpty(inQuery.FileTypeCode), t => t.FileType.Code == inQuery.FileTypeCode)
.ProjectTo<TrialDocumentView>(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken, isEn_Us = _userInfo.IsEn_Us }); .ProjectTo<TrialDocumentView>(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken, isEn_Us = _userInfo.IsEn_Us });
return await trialDocumentQueryable.ToPagedListAsync(inQuery); return await trialDocumentQueryable.ToPagedListAsync(inQuery);
@@ -180,7 +181,7 @@ namespace IRaCIS.Core.Application.Services
[HttpPost] [HttpPost]
public async Task<PageOutput<TrialSignDocView>> GetTrialSignDocumentList(TrialDocQuery inQuery) public async Task<PageOutput<TrialSignDocView>> GetTrialSignDocumentList(TrialDocQuery inQuery)
{ {
var trialDocQueryable = from trialDoc in _trialDocumentRepository.Where(t=>t.IsPublish) var trialDocQueryable = from trialDoc in _trialDocumentRepository.Where(t => t.IsPublish)
.WhereIf(inQuery.TrialId != null, t => t.TrialId == inQuery.TrialId) .WhereIf(inQuery.TrialId != null, t => t.TrialId == inQuery.TrialId)
.Where(t => t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == _userInfo.UserTypeId)) .Where(t => t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == _userInfo.UserTypeId))
@@ -353,7 +354,7 @@ namespace IRaCIS.Core.Application.Services
#region #region
var systemDocQuery = var systemDocQuery =
from sysDoc in _systemDocumentRepository.Where(t=>t.IsPublish).Where(t => t.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == _userInfo.UserTypeId)) from sysDoc in _systemDocumentRepository.Where(t => t.IsPublish).Where(t => t.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == _userInfo.UserTypeId))
//外部人员 只签署 外部需要签署的 //外部人员 只签署 外部需要签署的
.WhereIf(isInternal == false, t => t.DocUserSignType == DocUserSignType.InnerAndOuter) .WhereIf(isInternal == false, t => t.DocUserSignType == DocUserSignType.InnerAndOuter)
from trialUser in _trialIdentityUserRepository.AsQueryable(false) from trialUser in _trialIdentityUserRepository.AsQueryable(false)
@@ -392,7 +393,7 @@ namespace IRaCIS.Core.Application.Services
//项目文档查询 //项目文档查询
var trialDocQuery = var trialDocQuery =
from trialDoc in _trialDocumentRepository.Where(t=>t.IsPublish).Where(t => t.TrialId == inQuery.TrialId).Where(t => t.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == _userInfo.UserTypeId)) from trialDoc in _trialDocumentRepository.Where(t => t.IsPublish).Where(t => t.TrialId == inQuery.TrialId).Where(t => t.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == _userInfo.UserTypeId))
from trialUser in _trialIdentityUserRepository.AsQueryable(false).Where(t => t.TrialId == inQuery.TrialId && t.IdentityUserId == _userInfo.IdentityUserId from trialUser in _trialIdentityUserRepository.AsQueryable(false).Where(t => t.TrialId == inQuery.TrialId && t.IdentityUserId == _userInfo.IdentityUserId
&& t.TrialUserRoleList.Any(t => trialDoc.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == t.UserRole.UserTypeId))) && t.TrialUserRoleList.Any(t => trialDoc.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == t.UserRole.UserTypeId)))
@@ -582,7 +583,7 @@ namespace IRaCIS.Core.Application.Services
#endregion #endregion
var needSignTrialDocCount = await _trialDocumentRepository.AsQueryable(true).Where(t=>t.IsPublish) var needSignTrialDocCount = await _trialDocumentRepository.AsQueryable(true).Where(t => t.IsPublish)
.Where(t => t.TrialId == inQuery.TrialId && t.Trial.TrialStatusStr != StaticData.TrialState.TrialStopped) .Where(t => t.TrialId == inQuery.TrialId && t.Trial.TrialStatusStr != StaticData.TrialState.TrialStopped)
.Where(t => t.Trial.TrialIdentityUserList.Any(t => t.IdentityUserId == _userInfo.IdentityUserId && t.TrialUserRoleList.Any(t => t.UserRole.UserTypeId == _userInfo.UserTypeId))) .Where(t => t.Trial.TrialIdentityUserList.Any(t => t.IdentityUserId == _userInfo.IdentityUserId && t.TrialUserRoleList.Any(t => t.UserRole.UserTypeId == _userInfo.UserTypeId)))
.Where(t => t.IsDeleted == false && !t.TrialDocConfirmedUserList.Any(t => t.ConfirmUserId == _userInfo.IdentityUserId && t.ConfirmTime != null) && t.NeedConfirmedUserTypeList.Any(u => u.NeedConfirmUserTypeId == _userInfo.UserTypeId)) .Where(t => t.IsDeleted == false && !t.TrialDocConfirmedUserList.Any(t => t.ConfirmUserId == _userInfo.IdentityUserId && t.ConfirmTime != null) && t.NeedConfirmedUserTypeList.Any(u => u.NeedConfirmUserTypeId == _userInfo.UserTypeId))
@@ -713,7 +714,8 @@ namespace IRaCIS.Core.Application.Services
.WhereIf(inQuery.BeginCreateTime != null, t => t.CreateTime >= inQuery.BeginCreateTime) .WhereIf(inQuery.BeginCreateTime != null, t => t.CreateTime >= inQuery.BeginCreateTime)
.WhereIf(inQuery.EndCreateTime != null, t => t.CreateTime <= inQuery.EndCreateTime) .WhereIf(inQuery.EndCreateTime != null, t => t.CreateTime <= inQuery.EndCreateTime)
.WhereIf(!string.IsNullOrEmpty(inQuery.UserName), t => t.UserName.Contains(inQuery.UserName)) .WhereIf(!string.IsNullOrEmpty(inQuery.UserName), t => t.UserName.Contains(inQuery.UserName))
.WhereIf(inQuery.IsDeleted != null, t => t.IsDeleted == inQuery.IsDeleted); .WhereIf(inQuery.IsDeleted != null, t => t.IsDeleted == inQuery.IsDeleted)
.WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.EA, t => t.ConfirmTime != null);
var result = await unionQuery.ToPagedListAsync(inQuery); var result = await unionQuery.ToPagedListAsync(inQuery);
@@ -945,15 +947,18 @@ namespace IRaCIS.Core.Application.Services
var isEA = _userInfo.UserTypeEnumInt == (int)UserTypeEnum.EA; var isEA = _userInfo.UserTypeEnumInt == (int)UserTypeEnum.EA;
//EA 但是没有在进行的培训记录查看权限,那么返回空数据 //EA 但是没有在进行的培训记录查看权限,那么返回空数据
if (isEA && !_auditRecordRepository.Any(t => t.IsViewTrainingRecord && t.AuditState == AuditState.Ongoing && t.AuditRecordIdentityUserList.Any(c=>c.IdentityUserId==_userInfo.IdentityUserId))) if (isEA && !_auditRecordRepository.Any(t => t.IsViewTrainingRecord && t.AuditState == AuditState.Ongoing && t.AuditRecordIdentityUserList.Any(c => c.IdentityUserId == _userInfo.IdentityUserId)))
{ {
return ResponseOutput.Ok(new PageOutput<UnionDocumentWithConfirmInfoView>()); return ResponseOutput.Ok(new PageOutput<UnionDocumentWithConfirmInfoView>());
} }
var systemDocQuery = var systemDocQuery =
from sysDoc in _systemDocumentRepository.AsQueryable(false) from sysDoc in _systemDocumentRepository.Where(t => t.IsPublish)
.Where(t => inQuery.UserTypeId != null ? t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == inQuery.UserTypeId) : true) .Where(t => inQuery.UserTypeId != null ? t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == inQuery.UserTypeId) : true)
from identityUser in _identityUserRepository.AsQueryable(false).Where(t => t.Status == UserStateEnum.Enable && t.UserRoleList.Where(t => t.IsUserRoleDisabled == false).Any(t => sysDoc.NeedConfirmedUserTypeList.AsQueryable().Any(c => c.NeedConfirmUserTypeId == t.UserTypeId))) from identityUser in _identityUserRepository.AsQueryable(false)
.Where(t => t.Status == UserStateEnum.Enable && t.UserRoleList.Where(t => t.IsUserRoleDisabled == false).Any(t => sysDoc.NeedConfirmedUserTypeList.AsQueryable().Any(c => c.NeedConfirmUserTypeId == t.UserTypeId)))
.Where(t => inQuery.UserId != null ? t.Id == inQuery.UserId : true) .Where(t => inQuery.UserId != null ? t.Id == inQuery.UserId : true)
.Where(t => inQuery.UserTypeId != null ? t.UserRoleList.Any(t => t.UserTypeId == inQuery.UserTypeId && t.IsUserRoleDisabled == false) : true) .Where(t => inQuery.UserTypeId != null ? t.UserRoleList.Any(t => t.UserTypeId == inQuery.UserTypeId && t.IsUserRoleDisabled == false) : true)
.Where(t => isEA ? t.IsZhiZhun == true : true) //EA 只能查看内部人员文档 .Where(t => isEA ? t.IsZhiZhun == true : true) //EA 只能查看内部人员文档
@@ -962,6 +967,9 @@ namespace IRaCIS.Core.Application.Services
select new UnionDocumentWithConfirmInfoView() select new UnionDocumentWithConfirmInfoView()
{ {
IsSystemDoc = true, IsSystemDoc = true,
SysDocUserSignType = sysDoc.DocUserSignType,
IsConfirmIdentityUserInner = identityUser.IsZhiZhun,
IsPublish=sysDoc.IsPublish,
Id = sysDoc.Id, Id = sysDoc.Id,
CreateTime = sysDoc.CreateTime, CreateTime = sysDoc.CreateTime,
IsDeleted = sysDoc.IsDeleted, IsDeleted = sysDoc.IsDeleted,
@@ -993,14 +1001,16 @@ namespace IRaCIS.Core.Application.Services
}; };
var unionQuery = systemDocQuery.IgnoreQueryFilters().Where(t => !(t.IsDeleted == true && t.ConfirmTime == null)) var unionQuery = systemDocQuery.IgnoreQueryFilters().Where(t => !(t.IsDeleted == true && t.ConfirmTime == null))
//外部人员 只签署 外部需要签署的
.Where(t => t.IsConfirmIdentityUserInner == false ? t.SysDocUserSignType == DocUserSignType.InnerAndOuter : true)
.WhereIf(!string.IsNullOrEmpty(inQuery.Name), t => t.Name.Contains(inQuery.Name)) .WhereIf(!string.IsNullOrEmpty(inQuery.Name), t => t.Name.Contains(inQuery.Name))
.WhereIf(inQuery.FileTypeId != null, t => t.FileTypeId == inQuery.FileTypeId) .WhereIf(inQuery.FileTypeId != null, t => t.FileTypeId == inQuery.FileTypeId)
.WhereIf(inQuery.IsConfirmed == true, t => t.ConfirmTime != null) .WhereIf(inQuery.IsConfirmed == true, t => t.ConfirmTime != null)
.WhereIf(inQuery.IsConfirmed == false, t => t.ConfirmTime == null) .WhereIf(inQuery.IsConfirmed == false, t => t.ConfirmTime == null)
.WhereIf(inQuery.StartConfirmTime != null, t => t.ConfirmTime >= inQuery.StartConfirmTime.Value) .WhereIf(inQuery.StartConfirmTime != null, t => t.ConfirmTime >= inQuery.StartConfirmTime.Value)
.WhereIf(inQuery.EndConfirmTime != null, t => t.ConfirmTime <= inQuery.EndConfirmTime.Value) .WhereIf(inQuery.EndConfirmTime != null, t => t.ConfirmTime <= inQuery.EndConfirmTime.Value)
.WhereIf(inQuery.BeginCreateTime != null, t => t.CreateTime >= inQuery.BeginCreateTime) .WhereIf(inQuery.BeginCreateTime != null, t => t.CreateTime >= inQuery.BeginCreateTime)
.WhereIf(inQuery.EndCreateTime != null, t => t.CreateTime <= inQuery.EndCreateTime) .WhereIf(inQuery.EndCreateTime != null, t => t.CreateTime <= inQuery.EndCreateTime)
.WhereIf(!string.IsNullOrEmpty(inQuery.UserName), t => t.UserName.Contains(inQuery.UserName)) .WhereIf(!string.IsNullOrEmpty(inQuery.UserName), t => t.UserName.Contains(inQuery.UserName))
.WhereIf(inQuery.IsDeleted != null, t => t.IsDeleted == inQuery.IsDeleted) .WhereIf(inQuery.IsDeleted != null, t => t.IsDeleted == inQuery.IsDeleted)
.WhereIf(isInternal == false, t => t.ConfirmTime != null); //不是内部的人,看有签名时间的 .WhereIf(isInternal == false, t => t.ConfirmTime != null); //不是内部的人,看有签名时间的
@@ -773,10 +773,12 @@ namespace IRaCIS.Core.Application.Service
{ {
var subjectId = generateEmailCommand.SubjectId; var subjectId = generateEmailCommand.SubjectId;
var businessScenarioEnum = generateEmailCommand.BusinessScenarioEnum; var businessScenarioEnum = generateEmailCommand.BusinessScenarioEnum;
var trialReadingCriterionId = generateEmailCommand.TrialReadingCriterionId; var criterionType = generateEmailCommand.CriterionType;
var trialConfig = await _subjectRepository.Where(t => t.Id == subjectId).Select(t => new { t.Trial.IsEnrollementQualificationConfirm, t.Trial.IsPDProgressView }).FirstNotNullAsync();
var trialConfig = await _subjectRepository.Where(t => t.Id == subjectId).Select(t => new { t.Trial.IsEnrollementQualificationConfirm, t.Trial.IsPDProgressView, t.TrialId }).FirstNotNullAsync();
var trialReadingCriterionId = _readingQuestionCriterionTrialRepository.Where(t => t.CriterionType == criterionType && t.TrialId == trialConfig.TrialId).Select(t => t.Id).FirstOrDefault();
//找到入组确认 或者Pd 进展 已生成任务的 访视 //找到入组确认 或者Pd 进展 已生成任务的 访视
var subjectVisitList = await _subjectVisitRepository.Where(t => t.SubjectId == subjectId & t.CheckState == CheckStateEnum.CVPassed && (t.IsEnrollmentConfirm == true || t.PDState == PDStateEnum.PDProgress)).ToListAsync(); var subjectVisitList = await _subjectVisitRepository.Where(t => t.SubjectId == subjectId & t.CheckState == CheckStateEnum.CVPassed && (t.IsEnrollmentConfirm == true || t.PDState == PDStateEnum.PDProgress)).ToListAsync();
@@ -1671,10 +1673,10 @@ x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.LesionNumber && x.Readi
{ {
//await SyncSystemEmainCofigDocListAsync(inQuery.TrialId); //await SyncSystemEmainCofigDocListAsync(inQuery.TrialId);
var trialConfig = _trialRepository.Where(t => t.Id == inQuery.TrialId).Select(t => new { t.IsEnrollementQualificationConfirm, t.IsPDProgressView }).First(); var trialConfig = _trialRepository.Where(t => t.Id == inQuery.TrialId).Select(t => new { t.IsEnrollementQualificationConfirm, t.IsPDProgressView, TrialCriterionTypeList = t.TrialReadingCriterionList.Where(t => t.IsSigned).Select(t => t.CriterionType).ToList() }).First();
var trialEmailNoticeConfigQueryable = _trialEmailNoticeConfigRepository.Where(t => t.TrialId == inQuery.TrialId) var trialEmailNoticeConfigQueryable = _trialEmailNoticeConfigRepository.Where(t => t.TrialId == inQuery.TrialId)
.WhereIf(inQuery.EmailTopic.IsNotNullOrEmpty(), t => t.EmailTopic.Contains(inQuery.EmailTopic)||t.EmailTopicCN.Contains(inQuery.EmailTopic)) .WhereIf(inQuery.EmailTopic.IsNotNullOrEmpty(), t => t.EmailTopic.Contains(inQuery.EmailTopic) || t.EmailTopicCN.Contains(inQuery.EmailTopic))
.WhereIf(inQuery.IsDistinguishCriteria == false, t => t.IsDistinguishCriteria == false) .WhereIf(inQuery.IsDistinguishCriteria == false, t => t.IsDistinguishCriteria == false)
.WhereIf(inQuery.IsDistinguishCriteria == true, t => t.IsDistinguishCriteria == true) .WhereIf(inQuery.IsDistinguishCriteria == true, t => t.IsDistinguishCriteria == true)
.WhereIf(inQuery.CriterionTypeEnum != null, t => t.CriterionTypeList.Any(c => c == inQuery.CriterionTypeEnum)) .WhereIf(inQuery.CriterionTypeEnum != null, t => t.CriterionTypeList.Any(c => c == inQuery.CriterionTypeEnum))
@@ -1692,6 +1694,7 @@ x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.LesionNumber && x.Readi
var orderQuery = inQuery.Asc ? trialEmailNoticeConfigQueryable.OrderBy(sortField) : trialEmailNoticeConfigQueryable.OrderBy(sortField + " desc"); var orderQuery = inQuery.Asc ? trialEmailNoticeConfigQueryable.OrderBy(sortField) : trialEmailNoticeConfigQueryable.OrderBy(sortField + " desc");
var list = await orderQuery.ToListAsync(); var list = await orderQuery.ToListAsync();
return ResponseOutput.Ok(list, trialConfig); return ResponseOutput.Ok(list, trialConfig);
} }
@@ -117,4 +117,10 @@ namespace IRaCIS.Core.Application.Contracts.Dicom.DTO
public bool HasLabel { get; set; } = false; public bool HasLabel { get; set; } = false;
public bool KeySeries { get; set; } = false; public bool KeySeries { get; set; } = false;
} }
public class UpdateImageResizeDTO
{
public Guid SeriesId { get; set; }
public string ImageResizePath { get; set; }
}
} }
@@ -134,6 +134,8 @@ namespace IRaCIS.Core.Application.Contracts
public string Bodypart { get; set; } = string.Empty; public string Bodypart { get; set; } = string.Empty;
public string BodyPartForEditOther { get; set; } = string.Empty;
public DateTime? StudyTime { get; set; } public DateTime? StudyTime { get; set; }
@@ -1185,6 +1185,9 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
foreach (var item in list.GroupBy(t => new { t.StudyInstanceUid, t.DicomStudyId })) foreach (var item in list.GroupBy(t => new { t.StudyInstanceUid, t.DicomStudyId }))
{ {
var studyUid = item.Key.StudyInstanceUid;
var ossFolder = $"{pathInfo.TrialId}/Image/{pathInfo.SubjectId}/{pathInfo.VisitId}/{item.Key.StudyInstanceUid}"; var ossFolder = $"{pathInfo.TrialId}/Image/{pathInfo.SubjectId}/{pathInfo.VisitId}/{item.Key.StudyInstanceUid}";
var isSucess = await SafeBussinessHelper.RunAsync(async () => await DicomDIRHelper.GenerateStudyDIRAndUploadAsync(item.ToList(), dirDic, ossFolder, _oSSService)); var isSucess = await SafeBussinessHelper.RunAsync(async () => await DicomDIRHelper.GenerateStudyDIRAndUploadAsync(item.ToList(), dirDic, ossFolder, _oSSService));
@@ -1192,7 +1195,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
if (isSucess) if (isSucess)
{ {
await _dicomStudyRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Key.DicomStudyId, u => new DicomStudy() { StudyDIRPath = $"/{ossFolder}/DICOMDIR" }); await _dicomStudyRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Key.DicomStudyId, u => new DicomStudy() { StudyDIRPath = $"/{ossFolder}/{dirDic[$"{studyUid}_DICOMDIR"]}" });
} }
} }
@@ -1625,6 +1628,8 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
var ossFolder = $"{pathInfo.TrialId}/Image/{pathInfo.SubjectId}/{visitId}/{item.Key.StudyInstanceUid}"; var ossFolder = $"{pathInfo.TrialId}/Image/{pathInfo.SubjectId}/{visitId}/{item.Key.StudyInstanceUid}";
var studyUid = item.Key.StudyInstanceUid;
var isSucess = await SafeBussinessHelper.RunAsync(async () => await DicomDIRHelper.GenerateStudyDIRAndUploadAsync(item.ToList(), dirDic, ossFolder, _oSSService)); var isSucess = await SafeBussinessHelper.RunAsync(async () => await DicomDIRHelper.GenerateStudyDIRAndUploadAsync(item.ToList(), dirDic, ossFolder, _oSSService));
@@ -1632,11 +1637,11 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
{ {
if (isTaskStudy) if (isTaskStudy)
{ {
await _taskStudyRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Key.DicomStudyId, u => new TaskStudy() { StudyDIRPath = $"/{ossFolder}/DICOMDIR" }); await _taskStudyRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Key.DicomStudyId, u => new TaskStudy() { StudyDIRPath = $"/{ossFolder}/{dirDic[$"{studyUid}_DICOMDIR"]}" });
} }
else else
{ {
await _dicomStudyRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Key.DicomStudyId, u => new DicomStudy() { StudyDIRPath = $"/{ossFolder}/DICOMDIR" }); await _dicomStudyRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Key.DicomStudyId, u => new DicomStudy() { StudyDIRPath = $"/{ossFolder}/{dirDic[$"{studyUid}_DICOMDIR"]}" });
} }
} }
@@ -2303,6 +2308,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
var subjectId = item.First().SubjectId; var subjectId = item.First().SubjectId;
var studyUid = item.Key.StudyInstanceUid;
var ossFolder = $"{inCommand.TrialId}/Image/{subjectId}/{visitId}/{item.Key.StudyInstanceUid}"; var ossFolder = $"{inCommand.TrialId}/Image/{subjectId}/{visitId}/{item.Key.StudyInstanceUid}";
@@ -2310,7 +2316,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
if (isSucess) if (isSucess)
{ {
await _dicomStudyRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Key.DicomStudyId, u => new DicomStudy() { StudyDIRPath = $"/{ossFolder}/DICOMDIR" }); await _dicomStudyRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Key.DicomStudyId, u => new DicomStudy() { StudyDIRPath = $"/{ossFolder}/{dirDic[$"{studyUid}_DICOMDIR"]}" });
} }
} }
} }
@@ -17,7 +17,18 @@ namespace IRaCIS.Core.Application.Services
{ {
/// <summary>
/// 更新缩略图路径
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> UpdateImageResizePath(UpdateImageResizeDTO dto)
{
await _seriesRepository.UpdatePartialFromQueryAsync(t => t.Id == dto.SeriesId, u => new DicomSeries() { ImageResizePath = dto.ImageResizePath }, true);
return ResponseOutput.Ok();
}
//医生读片那一块有耦合,关键序列 这里暂时留存 //医生读片那一块有耦合,关键序列 这里暂时留存
/// <summary> 指定资源Id,获取Dicom检查所属序列信息列表 </summary> /// <summary> 指定资源Id,获取Dicom检查所属序列信息列表 </summary>
@@ -382,7 +382,8 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
Id = t.Id, Id = t.Id,
Bodypart = t.BodyPartExamined, Bodypart = t.BodyPartForEdit,
BodyPartForEditOther = t.BodyPartForEditOther,
Modalities = t.Modalities, Modalities = t.Modalities,
@@ -433,6 +434,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
Id = t.Id, Id = t.Id,
Bodypart = t.BodyPart, Bodypart = t.BodyPart,
BodyPartForEditOther=t.BodyPartForEditOther,
Modalities = t.Modality, Modalities = t.Modality,
@@ -308,6 +308,8 @@ namespace IRaCIS.Core.Application.Service
await _fusionCache.RemoveAsync(CacheKeys.UserLoginError(userName)); await _fusionCache.RemoveAsync(CacheKeys.UserLoginError(userName));
await _fusionCache.RemoveByTagAsync(CacheKeys.UserMFATag(identityUserId));
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionIdentityUserId = _userInfo.IdentityUserId, ActionUserName = _userInfo.UserName, TargetIdentityUserId = identityUserId, OptType = UserOptType.ResetPassword }, true); await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionIdentityUserId = _userInfo.IdentityUserId, ActionUserName = _userInfo.UserName, TargetIdentityUserId = identityUserId, OptType = UserOptType.ResetPassword }, true);
return ResponseOutput.Ok(); return ResponseOutput.Ok();
@@ -316,7 +318,7 @@ namespace IRaCIS.Core.Application.Service
/// <summary> /// <summary>
/// 重置密码发邮件 (未登陆修改) /// 重置密码发邮件 (未登陆修改-忘记密码
/// </summary> /// </summary>
/// <param name="email"></param> /// <param name="email"></param>
/// <returns></returns> /// <returns></returns>
@@ -357,6 +359,8 @@ namespace IRaCIS.Core.Application.Service
await _mailVerificationService.AnolymousSendEmailForResetAccount(email, verificationCode); await _mailVerificationService.AnolymousSendEmailForResetAccount(email, verificationCode);
await _fusionCache.RemoveByTagAsync(CacheKeys.UserMFATag(existUser.Id));
return ResponseOutput.Ok(); return ResponseOutput.Ok();
} }
@@ -438,6 +442,10 @@ namespace IRaCIS.Core.Application.Service
await _mailVerificationService.AfterUserModifyPasswordSendEmailAsync(identityUserId); await _mailVerificationService.AfterUserModifyPasswordSendEmailAsync(identityUserId);
var find = await _identityUserRepository.FindAsync(identityUserId);
await _fusionCache.RemoveAsync(CacheKeys.UserLoginError(find.UserName));
return ResponseOutput.Ok(); return ResponseOutput.Ok();
} }
@@ -485,6 +493,8 @@ namespace IRaCIS.Core.Application.Service
await _mailVerificationService.AfterUserModifyPasswordSendEmailAsync(_userInfo.IdentityUserId); await _mailVerificationService.AfterUserModifyPasswordSendEmailAsync(_userInfo.IdentityUserId);
await _fusionCache.RemoveByTagAsync(CacheKeys.UserMFATag(_userInfo.IdentityUserId));
return ResponseOutput.Result(success); return ResponseOutput.Result(success);
@@ -861,8 +871,9 @@ namespace IRaCIS.Core.Application.Service
if (isRemember) if (isRemember)
{ {
await _fusionCache.SetAsync(CacheKeys.UserMFAVerifyPass(identityUserId, _userInfo.BrowserFingerprint), _userInfo.BrowserFingerprint, TimeSpan.FromMinutes(_serviceVerifyConfigConfig.UserMFAVerifyMinutes)); await _fusionCache.SetAsync(CacheKeys.UserMFAVerifyPass(identityUserId, _userInfo.BrowserFingerprint), _userInfo.BrowserFingerprint,
TimeSpan.FromMinutes(_serviceVerifyConfigConfig.UserMFAVerifyMinutes), new[] { CacheKeys.UserMFATag(identityUserId) });
Log.Logger.Warning($"MFA登录记录:{_userInfo.UserName} 浏览器标识: {_userInfo.BrowserFingerprint} 设置缓存分钟{_serviceVerifyConfigConfig.UserMFAVerifyMinutes}");
} }
@@ -1066,7 +1077,7 @@ namespace IRaCIS.Core.Application.Service
//异地登录 //异地登录
loginUser.LoginState = 2; loginUser.LoginState = 2;
await _fusionCache.RemoveByTagAsync(CacheKeys.UserMFATag(loginUser.IdentityUserId));
} }
} }
} }
@@ -1176,15 +1187,20 @@ namespace IRaCIS.Core.Application.Service
if (_verifyConfig.CurrentValue.OpenLoginMFA) if (_verifyConfig.CurrentValue.OpenLoginMFA)
{ {
if ((await _fusionCache.GetOrDefaultAsync(CacheKeys.UserMFAVerifyPass(identityUserId, _userInfo.BrowserFingerprint), "")) == _userInfo.BrowserFingerprint) if ((await _fusionCache.GetOrDefaultAsync(CacheKeys.UserMFAVerifyPass(identityUserId, _userInfo.BrowserFingerprint), "")) == _userInfo.BrowserFingerprint)
{ {
userLoginReturnModel.IsMFA = false; userLoginReturnModel.IsMFA = false;
Log.Logger.Warning($"MFA登录:{userName} 浏览器标识: {_userInfo.BrowserFingerprint},判断缓存里存在 ");
} }
else else
{ {
//MFA 发送邮件 //MFA 发送邮件
userLoginReturnModel.IsMFA = true; userLoginReturnModel.IsMFA = true;
Log.Logger.Warning($"MFA登录:{userName} 浏览器标识: {_userInfo.BrowserFingerprint} 判断缓存已经不存在");
} }
var email = userLoginReturnModel.BasicInfo.EMail; var email = userLoginReturnModel.BasicInfo.EMail;
@@ -20,6 +20,8 @@ namespace IRaCIS.Core.Application.Contracts
public bool IsDeleted { get; set; } public bool IsDeleted { get; set; }
public bool IsBeMark { get; set; }
public DateTime? MarkTime { get; set; } public DateTime? MarkTime { get; set; }
} }
@@ -983,6 +983,8 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
/// </summary> /// </summary>
public ImageMark? ImageMarkEnum { get; set; } public ImageMark? ImageMarkEnum { get; set; }
public string QuestionGroupName { get; set; }
/// <summary> /// <summary>
/// 影像工具 /// 影像工具
/// </summary> /// </summary>
@@ -485,13 +485,16 @@ namespace IRaCIS.Core.Application.Service
List<NoneDicomStudyView> result = await noneDicomStudyQueryable.OrderBy(x => x.ImageDate).ThenBy(x => x.CreateTime).ToListAsync(); List<NoneDicomStudyView> result = await noneDicomStudyQueryable.OrderBy(x => x.ImageDate).ThenBy(x => x.CreateTime).ToListAsync();
// 获取非DIOCM标记
var nonoDicomStudyFileIds = await _readingNoneDicomMarkRepository.Where(x => x.VisitTaskId == inDto.VisistTaskId).ToListAsync(); var nonoDicomStudyFileIds = await _readingNoneDicomMarkRepository.Where(x => x.VisitTaskId == inDto.VisistTaskId).ToListAsync();
var markFileId = nonoDicomStudyFileIds.Select(x => x.NoneDicomFileId).ToList();
if (nonoDicomStudyFileIds.Count > 0 && taskinfo.ReadingTaskState == ReadingTaskState.HaveSigned) if (nonoDicomStudyFileIds.Count > 0 && taskinfo.ReadingTaskState == ReadingTaskState.HaveSigned)
{ {
var studyId = nonoDicomStudyFileIds.Select(x => x.StudyId).FirstOrDefault(); var studyId = nonoDicomStudyFileIds.Select(x => x.StudyId).FirstOrDefault();
var noneDicomids = nonoDicomStudyFileIds.Select(x => x.NoneDicomFileId).ToList(); var noneDicomids = nonoDicomStudyFileIds.Select(x => x.NoneDicomFileId).ToList();
var noneDicomStudyViewMark = new NoneDicomStudyView() { Id = Guid.NewGuid() }; var noneDicomStudyViewMark = new NoneDicomStudyView() { Id = Guid.NewGuid() };
noneDicomStudyViewMark.IsCriticalSequence = true; noneDicomStudyViewMark.IsCriticalSequence = true;
noneDicomStudyViewMark.NoneDicomStudyFileList = await _noneDicomStudyFileRepository.Where(x => noneDicomids.Contains(x.Id)).ProjectTo<NoneDicomStudyFileView>(_mapper.ConfigurationProvider).ToListAsync(); noneDicomStudyViewMark.NoneDicomStudyFileList = await _noneDicomStudyFileRepository.Where(x => noneDicomids.Contains(x.Id)).ProjectTo<NoneDicomStudyFileView>(_mapper.ConfigurationProvider).ToListAsync();
@@ -506,6 +509,14 @@ namespace IRaCIS.Core.Application.Service
} }
foreach (var item in result)
{
foreach (var item1 in item.NoneDicomStudyFileList)
{
item1.IsBeMark= markFileId.Contains(item1.Id);
}
}
var trialInfo = await _trialRepository.Where(x => x.Id == inDto.TrialId).Select(x => new var trialInfo = await _trialRepository.Where(x => x.Id == inDto.TrialId).Select(x => new
{ {
@@ -374,7 +374,7 @@ namespace IRaCIS.Core.Application.Service
CreateMap<AddOrUpdateReadingQuestionTrialInDto, ReadingQuestionTrial>() CreateMap<AddOrUpdateReadingQuestionTrialInDto, ReadingQuestionTrial>()
.ForMember(dest => dest.CreateUserRole, opt => opt.Ignore()); .ForMember(dest => dest.CreateUserRole, opt => opt.Ignore());
CreateMap<ReadingQuestionTrial, ReadingQuestionTrialView>() CreateMap<ReadingQuestionTrial, ReadingQuestionTrialView>()
.ForMember(d => d.QuestionGroupName, u => u.MapFrom(s => s.GroupInfo == null ? s.GroupName : s.GroupInfo.GroupName))
.ForMember(d => d.GroupName, u => u.MapFrom(s => s.GroupInfo == null ? s.GroupName : s.GroupInfo.GroupName)) .ForMember(d => d.GroupName, u => u.MapFrom(s => s.GroupInfo == null ? s.GroupName : s.GroupInfo.GroupName))
.ForMember(d => d.GroupEnName, u => u.MapFrom(s => s.GroupInfo == null ? s.GroupEnName : s.GroupInfo.GroupEnName)) .ForMember(d => d.GroupEnName, u => u.MapFrom(s => s.GroupInfo == null ? s.GroupEnName : s.GroupInfo.GroupEnName))
.ForMember(d => d.ParentQuestionName, u => u.MapFrom(s => s.ParentReadingQuestionTrial == null ? string.Empty : s.ParentReadingQuestionTrial.QuestionName)) .ForMember(d => d.ParentQuestionName, u => u.MapFrom(s => s.ParentReadingQuestionTrial == null ? string.Empty : s.ParentReadingQuestionTrial.QuestionName))
@@ -338,6 +338,7 @@ namespace IRaCIS.Core.Application.Service
trial.DeclarationTypes = $"|{string.Join('|', updateModel.DeclarationTypeEnumList.Select(x => ((int)x).ToString()).ToList())}|"; trial.DeclarationTypes = $"|{string.Join('|', updateModel.DeclarationTypeEnumList.Select(x => ((int)x).ToString()).ToList())}|";
trial.AttendedReviewerTypes = $"|{string.Join('|', updateModel.AttendedReviewerTypeEnumList.Select(x => ((int)x).ToString()).ToList())}|"; trial.AttendedReviewerTypes = $"|{string.Join('|', updateModel.AttendedReviewerTypeEnumList.Select(x => ((int)x).ToString()).ToList())}|";
trial.EmailFromName = $"{_systemEmailConfig.FromName}-{trial.TrialCode}";
trial.UpdateTime = DateTime.Now; trial.UpdateTime = DateTime.Now;
+75 -2
View File
@@ -12,6 +12,7 @@ using IRaCIS.Core.Domain;
using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore; using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Infra.EFCore.Context;
using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Infrastructure.Encryption; using IRaCIS.Core.Infrastructure.Encryption;
using IRaCIS.Core.Infrastructure.NewtonsoftJson; using IRaCIS.Core.Infrastructure.NewtonsoftJson;
@@ -38,6 +39,7 @@ using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
@@ -75,14 +77,85 @@ namespace IRaCIS.Core.Application.Service
{ {
public static int IntValue = 100; public static int IntValue = 100;
public class ModelVerifyCommand
{
public int? IntNUllValue { get; set; }
public int IntValue { get; set; }
public string StringValue { get; set; }
public string? StringNUllValue { get; set; }
public string StringBackDefaultValue { get; set; } = string.Empty;
public Guid GuidValue { get; set; } = NewId.NextSequentialGuid();
public Guid? GuidNUllValue { get; set; }
[NotDefault]
public Guid GuidValueNotDefault { get; set; }
public bool BoolValue { get; set; }
public bool? BoolNUllValue { get; set; }
public DateTime DateTimeValue { get; set; }
public DateTime? DateTimeNUllValue { get; set; }
}
//创建一个模型验证的方法
[AllowAnonymous]
[HttpPost]
public async Task<IResponseOutput> PostModelVerify(ModelVerifyCommand modelVerify)
{
return ResponseOutput.Ok(modelVerify);
}
[AllowAnonymous]
public async Task<IResponseOutput> CreatNewDBStruct()
{
var factory = new IRaCISDBContextFactory();
using var db = factory.CreateDbContext(Array.Empty<string>());
// ⚠️ 临时用,确认是测试库
// db.Database.EnsureDeleted();
db.Database.EnsureCreated();
Console.WriteLine("数据库结构已创建完成");
return ResponseOutput.Ok();
}
[AllowAnonymous]
public async Task<IResponseOutput> DeleteCacheDIR()
{
var list = _dicomStudyRepository.Where(t => t.StudyDIRPath != "").Select(t => t.StudyDIRPath).ToList();
await _IOSSService.DeleteObjects(list.Select(t => t.TrimStart('/')).ToList(), true);
return ResponseOutput.Ok();
}
[AllowAnonymous] [AllowAnonymous]
public async Task<IResponseOutput> TestOSS(StorageClass storageClass) public async Task<IResponseOutput> TestOSS(StorageClass storageClass)
{ {
if (storageClass == StorageClass.IA || storageClass == StorageClass.Archive || storageClass == StorageClass.ColdArchive || storageClass == StorageClass.DeepColdArchive) if (storageClass == StorageClass.IA || storageClass == StorageClass.Archive || storageClass == StorageClass.ColdArchive || storageClass == StorageClass.DeepColdArchive)
{ {
//await _IOSSService.SetImmediateArchiveRule($"Test-Archive/Archive{(int)storageClass}/"); await _IOSSService.SetImmediateArchiveRule($"Test-Archive/Archive{(int)storageClass}/");
await _IOSSService.RestoreFilesByPrefixAsync($"Test-Archive/Archive{(int)storageClass}/"); //await _IOSSService.RestoreFilesByPrefixAsync($"Test-Archive/Archive{(int)storageClass}/");
} }
@@ -46,6 +46,11 @@ public class SystemDocument : BaseFullDeleteAuditEntity
public bool IsPublish { get; set; } = true; public bool IsPublish { get; set; } = true;
/// <summary>
/// 发布时间
/// </summary>
public DateTime? PublishDate { get; set; }
} }
@@ -50,6 +50,11 @@ public class TrialDocument : BaseFullDeleteAuditEntity
/// </summary> /// </summary>
public bool IsPublish { get; set; } = true; public bool IsPublish { get; set; } = true;
/// <summary>
/// 发布时间
/// </summary>
public DateTime? PublishDate { get; set; }
} }
[Comment("项目签署文档附件")] [Comment("项目签署文档附件")]
+1 -1
View File
@@ -259,7 +259,7 @@ public partial class Trial : BaseFullDeleteAuditEntity
/// 图像格式 /// 图像格式
/// </summary> /// </summary>
[StringLength(2000)] [StringLength(2000)]
public List<string> ImageFormatList { get; set; } = new List<string>() {"jpg","jpeg","png","bmp","pdf","zip" }; public List<string> ImageFormatList { get; set; } = new List<string>() {"jpg","jpeg","png","bmp","pdf","zip","mp4" };
#endregion #endregion
#region #region
@@ -53,3 +53,6 @@
5、以下命令将生成一个从指定 from 迁移到指定 to 迁移的 SQL 脚本。 5、以下命令将生成一个从指定 from 迁移到指定 to 迁移的 SQL 脚本。
dotnet ef migrations script from to -p IRaCIS.Core.Infra.EFCore dotnet ef migrations script from to -p IRaCIS.Core.Infra.EFCore
6、查看迁移列表
dotnet ef migrations list -p IRaCIS.Core.Infra.EFCore
@@ -6,6 +6,7 @@ using IRaCIS.Core.Infrastructure.Extention;
using Microsoft.EntityFrameworkCore.Metadata.Conventions; using Microsoft.EntityFrameworkCore.Metadata.Conventions;
using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Microsoft.VisualBasic;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.ComponentModel; using System.ComponentModel;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
@@ -60,8 +61,13 @@ public class IRaCISDBContext : DbContext
//针对字符串使用默认的长度配置为200,如果标注了StringLength 其他长度,就是标注的长度,如果标注了MaxLength 那么就是nvarcharMax //针对字符串使用默认的长度配置为200,如果标注了StringLength 其他长度,就是标注的长度,如果标注了MaxLength 那么就是nvarcharMax
configurationBuilder.Conventions.Add(_ => new DefaultStringLengthConvention(400)); configurationBuilder.Conventions.Add(_ => new DefaultStringLengthConvention(400));
//configurationBuilder.Conventions.Add(_ => new RemoveForeignKeyConvention());
//控制外键索引生成与否
//https://learn.microsoft.com/zh-cn/ef/core/modeling/relationships/conventions?utm_source=chatgpt.com //https://learn.microsoft.com/zh-cn/ef/core/modeling/relationships/conventions?utm_source=chatgpt.com
//configurationBuilder.Conventions.Remove(typeof(ForeignKeyIndexConvention)); configurationBuilder.Conventions.Remove(typeof(ForeignKeyIndexConvention));
} }
protected override void OnModelCreating(ModelBuilder modelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder)
@@ -116,6 +122,7 @@ public class IRaCISDBContext : DbContext
#region decimal #region decimal
foreach (var entityType in modelBuilder.Model.GetEntityTypes()) foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{ {
foreach (var property in entityType.GetProperties()) foreach (var property in entityType.GetProperties())
@@ -142,6 +149,12 @@ public class IRaCISDBContext : DbContext
} }
} }
//用户名区分大小写
modelBuilder.Entity<IdentityUser>(entity =>
{
entity.Property(e => e.UserName)
.UseCollation("Chinese_PRC_CS_AS");
});
#endregion #endregion
//遍历实体模型手动配置 //遍历实体模型手动配置
@@ -160,6 +173,26 @@ public class IRaCISDBContext : DbContext
foreach (var entityType in modelBuilder.Model.GetEntityTypes()) foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{ {
#region Id -> Id非聚集CreateTime聚集索引便
// 1 所有 Entity:Id 为主键(非聚集)
if (typeof(Entity).IsAssignableFrom(entityType.ClrType))
{
modelBuilder.Entity(entityType.ClrType)
.HasKey(nameof(Entity.Id))
.IsClustered(false);
}
// 2 所有 IAuditAddCreateTime 为聚集索引
if (typeof(IAuditAdd).IsAssignableFrom(entityType.ClrType))
{
modelBuilder.Entity(entityType.ClrType)
.HasIndex(nameof(IAuditAdd.CreateTime))
.IsClustered();
}
#endregion
// 软删除配置 // 软删除配置
if (typeof(ISoftDelete).IsAssignableFrom(entityType.ClrType)) if (typeof(ISoftDelete).IsAssignableFrom(entityType.ClrType))
{ {
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,39 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace IRaCIS.Core.Infra.EFCore.Migrations
{
/// <inheritdoc />
public partial class PublishDate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<DateTime>(
name: "PublishDate",
table: "TrialDocument",
type: "datetime2",
nullable: true);
migrationBuilder.AddColumn<DateTime>(
name: "PublishDate",
table: "SystemDocument",
type: "datetime2",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "PublishDate",
table: "TrialDocument");
migrationBuilder.DropColumn(
name: "PublishDate",
table: "SystemDocument");
}
}
}
File diff suppressed because it is too large Load Diff
@@ -119,7 +119,10 @@ namespace IRaCIS.Core.Infra.EFCore
/// <summary>EntityState.Detached的实体 修改 部分字段</summary> /// <summary>EntityState.Detached的实体 修改 部分字段</summary>
public static void EntityModifyPartialFiled<T>(this IRaCISDBContext _dbContext, T waitModifyEntity, Expression<Func<T, T>> updateFactory) where T : Entity public static void EntityModifyPartialFiled<T>(this IRaCISDBContext _dbContext, T waitModifyEntity, Expression<Func<T, T>> updateFactory) where T : Entity
{ {
var entityEntry = _dbContext.Entry(waitModifyEntity); //解决重复跟踪问题
var tracked = _dbContext.ChangeTracker.Entries<T>().FirstOrDefault(e => e.Entity.Id.Equals(waitModifyEntity.Id));
var entityEntry = tracked?? _dbContext.Entry(waitModifyEntity);
//entityEntry.State = EntityState.Detached; //entityEntry.State = EntityState.Detached;
var list = ((MemberInitExpression)updateFactory.Body).Bindings.Select(mb => mb.Member.Name) var list = ((MemberInitExpression)updateFactory.Body).Bindings.Select(mb => mb.Member.Name)
@@ -134,7 +137,7 @@ namespace IRaCIS.Core.Infra.EFCore
foreach (PropertyInfo prop in list) foreach (PropertyInfo prop in list)
{ {
_dbContext.Entry(waitModifyEntity).Property(prop.Name).IsModified = true; entityEntry.Property(prop.Name).IsModified = true;
object value = prop.GetValue(applyObj); object value = prop.GetValue(applyObj);
prop.SetValue(waitModifyEntity, value); prop.SetValue(waitModifyEntity, value);
+12 -55
View File
@@ -48,29 +48,6 @@ steps:
commands: commands:
- cd /opt/1panel/xc-deploy/Test_IRC/devops-build-publish;sh test-irc-update-or-create-stack.sh v${DRONE_BUILD_NUMBER} - cd /opt/1panel/xc-deploy/Test_IRC/devops-build-publish;sh test-irc-update-or-create-stack.sh v${DRONE_BUILD_NUMBER}
trigger:
branch:
- Test_IRC_Net8
---
kind: pipeline
type: ssh
name: ssh-linux-test-irc-scp-publish
platform:
os: Linux
arch: 386
clone:
disable: true
server:
host: 106.14.89.110
user: root
password:
from_secret: test_ssh_pwd
steps:
- name: publish-test-irc-scp - name: publish-test-irc-scp
commands: commands:
- cd /opt/1panel/xc-deploy/Test_IRC_SCP/devops-build-publish;sh pull-build-test-irc-scp-image.sh v${DRONE_BUILD_NUMBER} - cd /opt/1panel/xc-deploy/Test_IRC_SCP/devops-build-publish;sh pull-build-test-irc-scp-image.sh v${DRONE_BUILD_NUMBER}
@@ -78,7 +55,9 @@ steps:
trigger: trigger:
branch: branch:
- Test_IRC_Net8—_SCP_Disable - Test_IRC_Net8
--- ---
kind: pipeline kind: pipeline
@@ -111,37 +90,7 @@ trigger:
--- ---
kind: pipeline kind: pipeline
type: ssh type: ssh
name: ssh-linux-test-scp-publish name: ssh-linux-test-hir
platform:
os: Linux
arch: 386
clone:
disable: true #禁用默认克隆
server:
host: 106.14.89.110
user: root
password:
from_secret: test_ssh_pwd
steps:
- name: publish-test-hir-scp
commands:
- cd /opt/1panel/xc-deploy/Test_HIR_SCP/devops-build-publish;sh pull-build-test-hir-scp-image.sh v${DRONE_BUILD_NUMBER}
- cd /opt/1panel/xc-deploy/Test_HIR_SCP ;sh update-image-if-need-then-pull-aliyun.sh v${DRONE_BUILD_NUMBER}
trigger:
branch:
- Test_HIR
---
kind: pipeline
type: ssh
name: ssh-linux-test-hir-publish
platform: platform:
os: Linux os: Linux
@@ -161,8 +110,16 @@ steps:
commands: commands:
- cd /opt/1panel/xc-deploy/Test_HIR/devops-build-publish;sh pull-build-test-hir-image.sh v${DRONE_BUILD_NUMBER} - cd /opt/1panel/xc-deploy/Test_HIR/devops-build-publish;sh pull-build-test-hir-image.sh v${DRONE_BUILD_NUMBER}
- cd /opt/1panel/xc-deploy/Test_HIR ; sh update-image-if-need-then-pull-aliyun.sh v${DRONE_BUILD_NUMBER} - cd /opt/1panel/xc-deploy/Test_HIR ; sh update-image-if-need-then-pull-aliyun.sh v${DRONE_BUILD_NUMBER}
- name: publish-test-hir-scp
commands:
- cd /opt/1panel/xc-deploy/Test_HIR_SCP/devops-build-publish;sh pull-build-test-hir-scp-image.sh v${DRONE_BUILD_NUMBER}
- cd /opt/1panel/xc-deploy/Test_HIR_SCP ;sh update-image-if-need-then-pull-aliyun.sh v${DRONE_BUILD_NUMBER}
trigger: trigger:
branch: branch:
- Test_HIR - Test_HIR