Files
irc-netcore-api/IRaCIS.Core.Application/TestService.cs
T
2026-08-07 14:56:35 +08:00

2352 lines
86 KiB
C#
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Aliyun.OSS;
using ClosedXML.Excel;
using FellowOakDicom;
using FellowOakDicom.Imaging;
using FellowOakDicom.IO.Buffer;
using IRaCIS.Application.Contracts;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Infra.EFCore.Context;
using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Infrastructure.Encryption;
using IRaCIS.Core.Infrastructure.NewtonsoftJson;
using MassTransit;
using Medallion.Threading;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MiniExcelLibs;
using Newtonsoft.Json;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Processing;
using System.ComponentModel.DataAnnotations;
using System.Linq.Dynamic.Core;
using System.Runtime.InteropServices;
using System.Text;
namespace IRaCIS.Core.Application.Service
{
[ApiExplorerSettings(GroupName = "Institution")]
public class TestService(IRepository<Dictionary> _dicRepository,
IRepository<Trial> _trialRepository,
IOptionsMonitor<SystemEmailSendConfig> _systemEmailConfig,
IOptionsMonitor<ServiceVerifyConfigOption> _basicConfig,
IRepository<SystemDocument> _systemDocumentRepository,
IRepository<TrialClinicalDataSetCriterion> _trialClinicalDataSetCriterionRepository,
IRepository<DicomInstance> _dicomInstanceRepository,
IRepository<Internationalization> _internationalizationRepository,
IRepository<SystemDocConfirmedIdentityUser> _systemDocConfirmedUserRepository,
IRepository<DicomStudy> _dicomStudyRepository,
IRepository<ClinicalDataTrialSet> _clinicalDataTrialSetRepository,
IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository,
IRepository<VisitTask> _visitTaskRepository,
IRepository<DicomSeries> _dicomSeriesRepository,
IRepository<UserRole> _userRoleRepository,
IRepository<TrialBodyPart> _trialBodyPartRepository,
IRepository<SubjectVisit> _subjectVisitRepository,
IOSSService _IOSSService,
IDistributedLockProvider _distributedLockProvider,
ILogger<TestService> _logger, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService
{
public static int IntValue = 100;
private readonly Random random = new();
static string ReplaceText(string text, Dictionary<string, string> replaceRules)
{
foreach (var rule in replaceRules)
{
text = text.Replace(rule.Key, rule.Value, StringComparison.OrdinalIgnoreCase);
}
return text;
}
public async Task<IResponseOutput> ExcelReplaceKeyWord()
{
string folderPath = @"C:\Users\PC\Downloads\SystemData(1)\SystemData\DataTemplate";
var replaceRules = new Dictionary<string, string>
{
["受试者"] = "试验参与者",
["Subject"] = "Participant"
};
foreach (var file in Directory.GetFiles(folderPath, "*.xlsx", SearchOption.AllDirectories))
{
Console.WriteLine($"处理文件:{file}");
using var workbook = new XLWorkbook(file);
bool changed = false;
foreach (var ws in workbook.Worksheets.ToList())
{
#region Sheet名称
var originalName = ws.Name;
string newSheetName = ReplaceText(originalName, replaceRules);
if (newSheetName != ws.Name)
{
ws.Name = newSheetName;
changed = true;
Console.WriteLine($"Sheet重命名:{originalName}->{newSheetName}");
}
#endregion
#region 单元格内容
var usedCells = ws.CellsUsed();
foreach (var cell in usedCells)
{
if (cell.IsEmpty())
{
continue;
}
string value = cell.GetString();
if (value.Contains("{{") || (value.Contains("}}")))
{
continue;
}
string newValue = ReplaceText(value, replaceRules);
if (value != newValue)
{
cell.Value = newValue;
changed = true;
Console.WriteLine($"单元格内容替换:{value}->{newValue}");
}
}
#endregion
#region 公式(可选)
//foreach (var cell in ws.CellsUsed(c => c.HasFormula))
//{
// var formula = cell.FormulaA1;
// var newFormula = ReplaceText(formula, replaceRules);
// if (formula != newFormula)
// {
// cell.FormulaA1 = newFormula;
// changed = true;
// }
//}
#endregion
}
if (changed)
{
workbook.Save();
Console.WriteLine($"已保存:{file}");
}
// 文件名替换
var fileName = Path.GetFileName(file);
var newFileName = ReplaceText(fileName, replaceRules);
if (fileName != newFileName)
{
var newPath = Path.Combine(
Path.GetDirectoryName(file)!,
newFileName);
File.Move(file, newPath, true);
Console.WriteLine($"文件重命名:{fileName} -> {newFileName}");
}
}
return ResponseOutput.Ok();
}
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; }
}
/// <summary>
/// 维护中心调研设备默认配置
/// </summary>
/// <param name="modelVerify"></param>
/// <returns></returns>
[AllowAnonymous]
[HttpPost]
public async Task<IResponseOutput> SiteSuveryEquipment()
{
//默认配置
var trialExtalConfig = new TrialExtraConfig()
{
EquipmentControlFieldList = new List<SiteSurveyEquipmentField> {
new SiteSurveyEquipmentField() { FiledName = "EquipmentTypeEnum", ShowOrder = 0, IsView = true },
new SiteSurveyEquipmentField() { FiledName = "OtherEquipmentType", ShowOrder = 1, IsView = true },
new SiteSurveyEquipmentField() { FiledName = "Parameters", ShowOrder = 2, IsView = true },
new SiteSurveyEquipmentField() { FiledName = "ManufacturerType", ShowOrder = 3, IsView = true },
new SiteSurveyEquipmentField() { FiledName = "ManufacturerName", ShowOrder = 4, IsView = true },
new SiteSurveyEquipmentField() { FiledName = "ScannerType", ShowOrder = 5, IsView = true },
new SiteSurveyEquipmentField() { FiledName = "Note", ShowOrder = 6, IsView = true },
}
};
var fixedFields = new List<string>() { "IsRoutineMRIPDEE", "MRIPDFFScanTime", "MRIPDFFLeadTime", "MRIPDFFOther", "IsAuthorizeRadiologistsParticipate", "AssignFixedTechnologists", "ISStrictManualBurnFlag", "NotStrictManualBurnFlagReason" };
//已有配置处理
var list = _trialRepository.Where(t => t.TrialExtraConfigJsonStr != "").Select(t => new { t.Id, t.TrialExtraConfigJsonStr }).ToList();
foreach (var item in list)
{
var extralConfig = JsonConvert.DeserializeObject<TrialExtraConfig>(item.TrialExtraConfigJsonStr);
//额外配置的中心调研,
if (extralConfig.ModifyFiledList.Count > 0)
{
extralConfig.EquipmentControlFieldList = trialExtalConfig.EquipmentControlFieldList.Where(t => t.ShowOrder != 2).ToList();
}
else
{
extralConfig.EquipmentControlFieldList = trialExtalConfig.EquipmentControlFieldList;
}
if (extralConfig.NotShowFieldList.Count == 0)
{
extralConfig.NotShowFieldList.AddRange(fixedFields);
extralConfig.NotShowFieldList = extralConfig.NotShowFieldList.Distinct().ToList();
}
else
{
//判断固定数组中是否有任意一个元素存在于 NotShowFieldList 中
if (!fixedFields.Any(t => extralConfig.NotShowFieldList.Any(c => c == t)))
{
extralConfig.NotShowFieldList.AddRange(fixedFields);
}
}
var jsonInfo = extralConfig.ToJsonStr();
await _trialRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Id, u => new Trial() { TrialExtraConfigJsonStr = jsonInfo });
}
//默认配置更新
var info = trialExtalConfig.ToJsonStr();
var idQuery = _trialRepository.Where(t => t.TrialExtraConfigJsonStr == "").Select(t => t.Id);
await _trialRepository.BatchUpdateNoTrackingAsync(t => idQuery.Contains(t.Id), u => new Trial() { TrialExtraConfigJsonStr = info });
return ResponseOutput.Ok();
}
/// <summary>
/// 访视数据模型
/// </summary>
public class SubjectVisitExcel
{
public string SubjectCode { get; set; }
public Guid? SubjectVisitId { get; set; }
public decimal VisitNum { get; set; }
public string VisitName { get; set; }
public string R1 { get; set; }
public string R1阅片状态 { get; set; }
public string R2 { get; set; }
public string R2阅片状态 { get; set; }
}
[AllowAnonymous]
public async Task<IResponseOutput> ExtralUndownloadImages(Guid trialId)
{
var newVisits = MiniExcel.Query<SubjectVisitExcel>(@"C:\Users\PC\Desktop\New.xlsx").ToList();
var oldVisits = MiniExcel.Query<SubjectVisitExcel>(@"C:\Users\PC\Desktop\Old.xlsx").ToList();
var downloadVisit = new List<SubjectVisitExcel>();
foreach (var item in newVisits)
{
if (oldVisits.Any(t => t.VisitNum == item.VisitNum && t.SubjectCode.Trim() == item.SubjectCode.Trim()))
{
continue;
}
else
{
downloadVisit.Add(item);
}
}
string exportPath = @$"C:\Users\PC\Desktop\newDownload.xlsx";
MiniExcel.SaveAs(exportPath, downloadVisit);
#region 数据库查询
// var downloadInfo = _trialRepository.Where(t => t.Id == trialId).Select(t => new
// {
// t.ResearchProgramNo,
// t.TrialCode,
// VisitList = t.SubjectVisitList.Where(t => t.VisitTaskList.Any(t => t.TaskState == TaskState.Effect && t.ReadingCategory == ReadingCategory.Visit && t.ReadingTaskState != ReadingTaskState.HaveSigned && t.SourceSubjectVisitId != null && t.DoctorUserId != null))
// //.Where(t=>subjectCodeList.Contains(t.Subject.Code))
// .Select(sv => new
// {
// SubjectVisitId = sv.Id,
// TrialSiteCode = sv.TrialSite.TrialSiteCode,
// SubjectCode = sv.Subject.Code,
// VisitName = sv.VisitName,
// VisitNum = sv.VisitNum,
// StudyList = sv.StudyList.Select(u => new
// {
// StudyId = u.Id,
// u.PatientId,
// u.StudyTime,
// u.StudyCode,
// u.StudyInstanceUid,
// u.StudyDIRPath,
// SeriesList = u.SeriesList.Where(t => t.IsReading).Select(z => new
// {
// z.Modality,
// InstancePathList = z.DicomInstanceList.Where(t => t.IsReading).Select(k => new
// {
// InstanceId = k.Id,
// k.Path,
// k.IsEncapsulated,
// k.NumberOfFrames,
// }).ToList()
// })
// }).ToList(),
// NoneDicomStudyList = sv.NoneDicomStudyList.Where(t => t.IsReading).Select(nd => new
// {
// nd.Modality,
// nd.StudyCode,
// nd.ImageDate,
// FileList = nd.NoneDicomFileList.Where(t => t.IsReading).Select(file => new
// {
// file.FileName,
// file.Path,
// file.FileType
// }).ToList()
// }).ToList()
// }).OrderBy(t => t.SubjectCode).ThenBy(t => t.VisitNum).ToList()
// }).FirstOrDefault();
// var acturalDownList = downloadInfo.VisitList.Where(t => !oldVisits.Any(old => old.VisitNum == t.VisitNum && old.SubjectCode == t.SubjectCode &&
//old.VisitName.Trim().ToLower() == t.VisitName.Trim().ToLower())).ToList();
// var diffList = downloadVisit.Where(t => !acturalDownList.Any(old => old.SubjectCode.Trim() == t.SubjectCode.Trim() &&
//old.VisitName.Trim().ToLower() == t.VisitName.Trim().ToLower())).ToList();
// string diffPath = @$"C:\Users\PC\Desktop\diff.xlsx";
// MiniExcel.SaveAs(diffPath, diffList);
#endregion
return ResponseOutput.Ok(downloadVisit);
}
//创建一个模型验证的方法
[AllowAnonymous]
[HttpPost("{email}")]
public async Task<IResponseOutput> PostModelVerify(/*ModelVerifyCommand modelVerify,*/ Guid subjectVisitId)
{
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == subjectVisitId).Include(x => x.Subject).Include(x => x.CurrentActionUser).FirstNotNullAsync();
var subjectVisit2 = await (_subjectVisitRepository.Where(x => x.Id == subjectVisitId).Include(x => x.Subject).Include(x => x.CurrentActionUser)).FirstNotNullAsync();
var webhook = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=cdd97aab-d256-4f07-9145-a0a2b1555322";
//await WeComNotifier.SendErrorAsync(webhook, "http://irc.test.extimaging.com/login", new Exception("测试异常"), new[] { "ZhouHang" });
//throw new Exception("手动测试异常抛出");
return ResponseOutput.Ok(_userInfo.Domain);
}
public async Task<IResponseOutput> GenerateImage()
{
var sourceDir = @"C:\work\测量图像";
var targetDir = @"C:\work\测量图像\纯黑色";
Directory.CreateDirectory(targetDir);
foreach (var inputPath in Directory.EnumerateFiles(sourceDir, "*", SearchOption.TopDirectoryOnly))
{
var relativePath = Path.GetRelativePath(sourceDir, inputPath);
var outputPath = Path.Combine(targetDir, relativePath);
var outputFolder = Path.GetDirectoryName(outputPath);
if (!string.IsNullOrEmpty(outputFolder))
{
Directory.CreateDirectory(outputFolder);
}
await using var input = File.OpenRead(inputPath);
await using var output = File.Create(outputPath);
try
{
Console.WriteLine($"开始处理: {relativePath}");
var dicomFile = await DicomFile.OpenAsync(input, FileReadOption.ReadAll).ConfigureAwait(false);
var ds = dicomFile.Dataset;
var rows = ds.GetSingleValue<int>(DicomTag.Rows);
var cols = ds.GetSingleValue<int>(DicomTag.Columns);
var bitsAllocated = ds.GetSingleValue<int>(DicomTag.BitsAllocated);
var bitsStored = ds.GetSingleValueOrDefault(DicomTag.BitsStored, bitsAllocated);
var samplesPerPixel = ds.GetSingleValue<int>(DicomTag.SamplesPerPixel);
var pixelRepresentation = ds.GetSingleValueOrDefault(DicomTag.PixelRepresentation, (ushort)0);
//Console.WriteLine($"Working Rows={rows}, Cols={cols}, BitsAllocated={bitsAllocated}, BitsStored={bitsStored}, SamplesPerPixel={samplesPerPixel}, PixelRepresentation={pixelRepresentation}");
//遮盖成黑色
var regions = new[] { new MaskRegion(0, 0, rows, cols) };
await DicomPixelMasker.MaskAsync(input, output, regions, new DicomMaskOptions() { GrayscaleMaskValue = 0 });
}
catch (Exception ex)
{
// 跳过该文件
Console.WriteLine();
Console.WriteLine($"error: {relativePath} —————— {ex.Message}");
Console.WriteLine();
}
Console.WriteLine($"处理结束: {relativePath}");
}
var list = new List<GenerateIamgeInfo>();
await GenerateAsync(@"C:\work\测量图像\纯黑色\CT.dcm", @"C:\work\测量图像\output", "CT", 20, list);
await GenerateAsync(@"C:\work\测量图像\纯黑色\MR.dcm", @"C:\work\测量图像\output", "MR", 20, list);
await GenerateAsync(@"C:\work\测量图像\纯黑色\PT.dcm", @"C:\work\测量图像\output", "PT", 10, list);
string exportPath = @$"C:\work\测量图像\outPut.xlsx";
MiniExcel.SaveAs(exportPath, list,overwriteFile:true);
return ResponseOutput.Ok();
}
#region 噪声
public class GenerateIamgeInfo
{
/// <summary>
/// 患者ID (0010,0020)
/// </summary>
public string PatientId { get; set; }
/// <summary>
/// 患者姓名 (0010,0010)
/// </summary>
public string PatientName { get; set; }
/// <summary>
/// 研究实例UID (0020,000D)
/// </summary>
public string StudyInstanceUID { get; set; }
/// <summary>
/// 序列实例UID (0020,000E)
/// </summary>
public string SeriesInstanceUID { get; set; }
/// <summary>
/// SOP实例UID (0008,0018)
/// </summary>
public string SOPInstanceUID { get; set; }
/// <summary>
/// 序列号 (0020,0011)
/// </summary>
public int SeriesNumber { get; set; }
/// <summary>
/// 实例号 (0020,0013)
/// </summary>
public int InstanceNumber { get; set; }
/// <summary>
/// 序列描述 (0008,103E)
/// </summary>
public string SeriesDescription { get; set; }
public int WidthMM => Width / 2;
public int HeightMM => Height / 2;
public int X { get; set; }
public int Y { get; set; }
public int Width { get; set; }
public int Height { get; set; }
/// <summary>
/// 像素间距 (0028,0030)
/// </summary>
public string PixelSpacing { get; set; }
}
/// <summary>
/// 生成随机噪声图
/// </summary>
private MaskRegion GenerateNoisePixel(
DicomDataset ds,
string modality)
{
Random random = new Random(); // 创建实例
int rows = ds.GetSingleValue<int>(DicomTag.Rows);
int cols = ds.GetSingleValue<int>(DicomTag.Columns);
int bits = ds.GetSingleValue<int>(DicomTag.BitsAllocated);
if (bits != 16)
{
throw new Exception(
"只处理16bit CT/MR/PT");
}
ushort[] pixels = new ushort[rows * cols];
//
// 黑底
//
for (int i = 0; i < pixels.Length; i++)
{
pixels[i] = 0;
}
// PixelSpacing
double pixelSpacing = 0.5;
// 生成10cm-20cm矩形
double widthMm = random.Next(100, 200);
double heightMm = random.Next(100, 200);
int width = (int)(widthMm / pixelSpacing);
int height = (int)(heightMm / pixelSpacing);
int x = random.Next(0, cols - width);
int y = random.Next(0, rows - height);
int min;
int max;
if (modality == "PT")
{
min = 0;
max = 16000;
}
else if (modality == "CT")
{
min = 5;
max = 2000;
}
else
{
// MR
min = 5;
max = 2000;
}
FillNoiseRectangle(pixels, cols, x, y, width, height, min, max);
//
// ushort转byte
//
byte[] bytes = new byte[pixels.Length * 2];
Buffer.BlockCopy(pixels, 0, bytes, 0, bytes.Length);
ds.Remove(DicomTag.PixelData);
//ds.Add(DicomTag.PixelData,new DicomOtherByte(DicomTag.PixelData, bytes));
var pixelData = DicomPixelData.Create(ds, true);
pixelData.AddFrame(new MemoryByteBuffer(bytes));
return new MaskRegion(x, y, width, height);
}
/// <summary>
/// 噪声矩形
/// </summary>
private void FillNoiseRectangle(
ushort[] pixels,
int cols,
int x,
int y,
int width,
int height,
int min,
int max)
{
Random random = new Random(); // 创建实例
for (int row = y;
row < y + height;
row++)
{
for (int col = x;
col < x + width;
col++)
{
int index =
row * cols + col;
//
// 每个像素不同
//
pixels[index] = (ushort)random.Next(min, max);
}
}
}
/// <summary>
/// 批量生成Series
/// </summary>
public async Task GenerateAsync(
string template,
string outputDir,
string modality,
int count, List<GenerateIamgeInfo> generateIamgeInfos)
{
Directory.CreateDirectory(outputDir);
//
// Series UID
//
string seriesUid = DicomUIDGenerator.GenerateDerivedFromUUID().UID;
//
// SeriesNumber
//
int seriesNumber = random.Next(1, 101);
for (int i = 1; i <= count; i++)
{
var file = await DicomFile.OpenAsync(template);
var ds = file.Dataset;
//
// Series信息
//
ds.AddOrUpdate(DicomTag.SeriesInstanceUID, seriesUid);
ds.AddOrUpdate(DicomTag.SeriesNumber, seriesNumber);
ds.AddOrUpdate(DicomTag.InstanceNumber, i);
if (modality == "CT")
{
ds.AddOrUpdate(DicomTag.SliceLocation, (i * 5).ToString());
ds.AddOrUpdate(DicomTag.RescaleSlope, "1");
ds.AddOrUpdate(DicomTag.RescaleIntercept, "-1024");
}
if (modality == "PT")
{
// 生成随机身高 (1.60 - 1.80 米)
Random rand = new Random();
double height = Math.Round(rand.NextDouble() * 0.20 + 1.60, 2);
// 根据身高生成符合BMI的体重 (BMI范围 18.5 - 24.9)
double bmi = Math.Round(rand.NextDouble() * 6.4 + 18.5, 1);
double weight = Math.Round(bmi * height * height, 1);
ds.AddOrUpdate(DicomTag.PatientSize, height.ToString("F2"));
ds.AddOrUpdate(DicomTag.PatientWeight, weight.ToString("F1"));
}
var seriesDescription = $"{modality} Data";
ds.AddOrUpdate(DicomTag.SeriesDescription, seriesDescription);
var sopUid = DicomUIDGenerator.GenerateDerivedFromUUID().UID;
//
// SOP Instance UID
//
ds.AddOrUpdate(DicomTag.SOPInstanceUID, sopUid);
//
// Modality
//
ds.AddOrUpdate(DicomTag.Modality, modality);
// ============================
// 2. 修改像素间距
// ============================
ds.AddOrUpdate(DicomTag.PixelSpacing, "0.5\\0.5");
//
// 生成麻子PixelData
//
var region = GenerateNoisePixel(ds, modality);
//
// 文件名
//
string fileName = Path.Combine(outputDir, $"{modality}_{i:D3}.dcm");
await file.SaveAsync(fileName);
var studyUid = ds.GetSingleValueOrDefault(DicomTag.StudyInstanceUID, string.Empty);
var pid = ds.GetSingleValueOrDefault(DicomTag.PatientID, string.Empty);
var pName = ds.GetSingleValueOrDefault(DicomTag.PatientName, string.Empty);
generateIamgeInfos.Add(new GenerateIamgeInfo()
{
// 初始化默认值
PatientId = pid,
PatientName = pName,
StudyInstanceUID = studyUid,
SeriesInstanceUID = seriesUid,
SOPInstanceUID = sopUid,
SeriesDescription = seriesDescription,
SeriesNumber = seriesNumber,
InstanceNumber = i,
X = region.X,
Y = region.Y,
Width = region.Width,
Height = region.Height,
PixelSpacing = "0.5\\0.5",
});
}
}
#endregion
/// <summary>
/// 遮挡影像
/// </summary>
/// <returns></returns>
[AllowAnonymous]
public async Task<IResponseOutput> MaskImage()
{
var sourceDir = @"C:\work\gitea\irc-netcore-api\DownloadImage";
var targetDir = @"C:\work\gitea\irc-netcore-api\DownloadImage\after";
Directory.CreateDirectory(targetDir);
var regions = new[]
{
new MaskRegion(0, 0, 200, 200)
};
foreach (var inputPath in Directory.EnumerateFiles(sourceDir, "IM_*", SearchOption.TopDirectoryOnly))
{
var relativePath = Path.GetRelativePath(sourceDir, inputPath);
var outputPath = Path.Combine(targetDir, relativePath);
var outputFolder = Path.GetDirectoryName(outputPath);
if (!string.IsNullOrEmpty(outputFolder))
{
Directory.CreateDirectory(outputFolder);
}
await using var input = File.OpenRead(inputPath);
await using var output = File.Create(outputPath);
try
{
Console.WriteLine($"开始处理: {relativePath}");
await DicomPixelMasker.MaskAsync(input, output, regions);
}
catch (Exception ex)
{
// 跳过该文件
Console.WriteLine();
Console.WriteLine($"error: {relativePath} —————— {ex.Message}");
Console.WriteLine();
}
Console.WriteLine($"处理结束: {relativePath}");
}
return ResponseOutput.Ok();
}
/// <summary>
/// 设置生命周期
/// </summary>
/// <param name="modelVerify"></param>
/// <returns></returns>
[AllowAnonymous]
public async Task<IResponseOutput> SetTrialLifeCycel()
{
var trialIdList = _trialRepository.Where(t => t.TrialStatusStr == StaticData.TrialState.TrialCompleted).Select(t => t.Id).ToList();
foreach (var trialId in trialIdList)
{
if (_readingQuestionCriterionTrialRepository.Any(t => t.TrialId == trialId && t.IsSigned && t.ImageUploadEnum != ReadingImageUpload.None))
{
await _IOSSService.SetImmediateArchiveRule($"{trialId}/Image/");
await _IOSSService.SetImmediateArchiveRule($"{trialId}/TaskImage/");
}
else
{
await _IOSSService.SetImmediateArchiveRule($"{trialId}/Image/");
}
}
return ResponseOutput.Ok();
}
/// <summary>
/// 归档直读
/// </summary>
/// <returns></returns>
[AllowAnonymous]
public async Task<IResponseOutput> ConvertPrefixToStandard()
{
_IOSSService.ConvertPrefixToStandard("601a0000-3e2c-0016-56de-08dae983124b/Image");
return ResponseOutput.Ok();
}
[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]
public async Task<IResponseOutput> TestOSS(StorageClass storageClass)
{
if (storageClass == StorageClass.IA || storageClass == StorageClass.Archive || storageClass == StorageClass.ColdArchive || storageClass == StorageClass.DeepColdArchive)
{
await _IOSSService.SetImmediateArchiveRule($"Test-Archive/Archive{(int)storageClass}/");
//await _IOSSService.RestoreFilesByPrefixAsync($"Test-Archive/Archive{(int)storageClass}/");
}
return ResponseOutput.Ok();
}
public class TestEfficacyEvaluation
{
public string SubjectCode { get; set; }
public string TaskName { get; set; }
public decimal VisitTaskNum { get; set; }
public string Arm { get; set; }
public bool? IsJudgeSelect { get; set; }
public bool? IsTrigerJudge { get; set; }
public string OverallTumorEvaluation { get; set; }
}
public async Task<IResponseOutput> TestUploadTrialEfficacyEvaluation(IFormFile file)
{
using var stream = file.OpenReadStream();
var list = MiniExcel
.Query<TestEfficacyEvaluation>(stream, excelType: ExcelType.XLSX)
.ToList();
return await TestTrialEfficacyEvaluationStat(list);
}
/// <summary>
/// 测试疗效评估
/// </summary>
/// <param name="list"></param>
/// <returns></returns>
public async Task<IResponseOutput> TestTrialEfficacyEvaluationStat(List<TestEfficacyEvaluation> list)
{
//找到只有一个人阅片的受试者 和访视
var exceptVisit = list
.GroupBy(t => new { t.SubjectCode, t.TaskName }).Where(g => g.Count() == 1).Select(g => new { g.Key.SubjectCode, g.Key.TaskName }).ToList();
//将一个人做的访视任务过滤掉
list = list.Where(t => !exceptVisit.Any(ev => ev.SubjectCode == t.SubjectCode && ev.TaskName == t.TaskName)).ToList();
//找到裁判选择了的,否则就不算,并且排除基线 按照每个subject分组,取最后一次访视
list = list.Where(t => t.IsJudgeSelect == true && t.VisitTaskNum != 0)//全局的答案已经放在对应访视上了
.GroupBy(t => t.SubjectCode).Select(g => g.OrderByDescending(t => t.VisitTaskNum).First()).ToList();
var result = list.GroupBy(t => t.OverallTumorEvaluation).Select(t => new
{
OverallTumorEvaluation = t.Key,
SubjectList = t.Select(t => t.SubjectCode).ToList()
}).ToList();
return ResponseOutput.Ok(result);
}
[AllowAnonymous]
public async Task<IResponseOutput> DealIVUSOCTDicomTag(string subjectCode, bool? isUploadOss)
{
var trialId = Guid.Parse("01000000-AC13-0242-3AE4-08DC9B0495C6");
var trialCode = "ZY2024002";
//var subjectCodeList = new List<string>() { "04032", "12004", "04005" };
var list = await _dicomInstanceRepository.Where(t => t.TrialId == trialId && t.DicomStudy.SubjectVisit.IsBaseLine)
.Where(t => t.DicomStudy.Subject.Code == subjectCode)
.WhereIf(subjectCode == "04032", t => t.DicomStudy.ModalityForEdit == "OCT")
.WhereIf(subjectCode == "12004", t => t.DicomStudy.ModalityForEdit == "IVUS")
.WhereIf(subjectCode == "04004", t => t.DicomStudy.ModalityForEdit == "IVUS" || t.DicomStudy.ModalityForEdit == "OCT")
.WhereIf(subjectCode == "04005", t => t.DicomStudy.ModalityForEdit == "IVUS" || t.DicomStudy.ModalityForEdit == "OCT")
.Select(t => new
{
SubjectCode = t.DicomStudy.Subject.Code,
//t.DicomStudy.ModalityForEdit,
//t.Path,
//t.FileSize,
t.DicomStudy.PatientId,
t.DicomStudy.Id,
t.DicomStudy.StudyDIRPath
}).Distinct().ToListAsync();
foreach (var item in list)
{
if (item.SubjectCode != item.PatientId)
{
await _dicomStudyRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Id, u => new DicomStudy() { PatientId = item.SubjectCode });
await _IOSSService.DeleteFromPrefix(item.StudyDIRPath.TrimStart("/"), true);
}
}
return ResponseOutput.Ok();
//foreach (var item in list)
//{
// Console.WriteLine(item.Path);
// await using var stream = await _IOSSService.GetStreamFromOSSAsync(item.Path);
// var dicomFile = DicomFile.Open(stream, FileReadOption.ReadLargeOnDemand);
// switch (item.SubjectCode)
// {
// case "04032":
// dicomFile.Dataset.AddOrUpdate(DicomTag.PatientID, $"{trialCode}-04032");
// dicomFile.Dataset.AddOrUpdate(DicomTag.ClinicalTrialSubjectID, "04032");
// break;
// case "12004":
// dicomFile.Dataset.AddOrUpdate(DicomTag.PatientID, $"{trialCode}-12004");
// dicomFile.Dataset.AddOrUpdate(DicomTag.ClinicalTrialSubjectID, "12004");
// break;
// case "04004":
// dicomFile.Dataset.AddOrUpdate(DicomTag.PatientID, $"{trialCode}-04004");
// dicomFile.Dataset.AddOrUpdate(DicomTag.ClinicalTrialSubjectID, "04004");
// break;
// case "04005":
// dicomFile.Dataset.AddOrUpdate(DicomTag.PatientID, $"{trialCode}-04005");
// dicomFile.Dataset.AddOrUpdate(DicomTag.ClinicalTrialSubjectID, "04005");
// break;
// default:
// break;
// }
// //获取原始目录 和文件名
// var folder = item.Path.Substring(0, item.Path.LastIndexOf('/')).TrimStart('/');
// var fileName = Path.GetFileName(item.Path);
// //if (isUploadOss == false)
// //{
// // // 本地完整路径
// // var localPath = Path.Combine(Directory.GetCurrentDirectory(), fileName);
// // // 写入文件
// // await using var fileStream = File.Create(localPath);
// // await output.CopyToAsync(fileStream);
// // // 可选:确保写入完成再关闭
// // await fileStream.FlushAsync();
// //}
// //else
// if (isUploadOss == true)
// {
// //4 保存到一个 MemoryStream
// await using var output = new MemoryStream();
// dicomFile.Save(output);
// output.Position = 0;
// await _IOSSService.UploadToOSSAsync(output, folder, fileName, false);
// //var pipe = new System.IO.Pipelines.Pipe();
// //// 写入端:fo-dicom
// //_ = Task.Run(async () =>
// //{
// // try
// // {
// // await using var writer = pipe.Writer.AsStream();
// // dicomFile.Save(writer); // 直接写 Pipe
// // await pipe.Writer.CompleteAsync();
// // }
// // catch (Exception ex)
// // {
// // await pipe.Writer.CompleteAsync(ex);
// // }
// //});
// ////await _IOSSService.UploadToOSSAsync(pipe.Reader.AsStream(), folder, fileName, false);
// await _IOSSService.DeleteFromPrefix(item.Path.TrimStart("/"), true);
// }
//}
//return ResponseOutput.Ok();
}
/// <summary>
/// 重建闭包表
/// </summary>
/// <param name="_auditDocumentClosureRepository"></param>
/// <param name="_auditDocumentRepository"></param>
/// <returns></returns>
[AllowAnonymous]
public async Task<IResponseOutput> RebuildAuditDocumentClosureAsync([FromServices] IRepository<AuditDocumentClosure> _auditDocumentClosureRepository, [FromServices] IRepository<AuditDocument> _auditDocumentRepository)
{
await _auditDocumentClosureRepository.BatchDeleteNoTrackingAsync(t => t.Id != Guid.Empty);
//过滤版本文件,防止污染闭包表
var documents = await _auditDocumentRepository.Where(t => t.MainFileId == null).Select(t => new { t.Id, t.ParentId }).ToListAsync();
var closures = new List<AuditDocumentClosure>();
// 建立一个字典,加快查找
var lookup = documents.ToDictionary(d => d.Id, d => d.ParentId);
foreach (var doc in documents)
{
// 1 自己 -> 自己 (depth = 0)
closures.Add(new AuditDocumentClosure
{
AncestorId = doc.Id,
DescendantId = doc.Id,
Depth = 0
});
// 2 递归向上找所有祖先
int depth = 1;
var currentParentId = doc.ParentId;
//脏数据 parentId==Guid.Empty
while (currentParentId.HasValue && currentParentId != Guid.Empty)
{
closures.Add(new AuditDocumentClosure
{
AncestorId = currentParentId.Value,
DescendantId = doc.Id,
Depth = depth
});
depth++;
// 继续向上查找
if (!lookup.TryGetValue(currentParentId.Value, out var nextParent))
break;
currentParentId = nextParent;
}
}
await _auditDocumentClosureRepository.AddRangeAsync(closures);
await _auditDocumentClosureRepository.SaveChangesAsync();
return ResponseOutput.Ok();
}
/// <summary>
/// 清理一致性分析任务
/// </summary>
/// <param name="trialReadingCriterionId"></param>
/// <param name="_taskConsistentRuleRepository"></param>
/// <param name="_readingConsistentClinicalDataPDFRepository"></param>
/// <param name="_readingConsistentClinicalDataRepository"></param>
/// <returns></returns>
public async Task<IResponseOutput> DeleteConsistentDate(Guid trialReadingCriterionId,
[FromServices] IRepository<TaskConsistentRule> _taskConsistentRuleRepository,
[FromServices] IRepository<ReadingConsistentClinicalDataPDF> _readingConsistentClinicalDataPDFRepository,
[FromServices] IRepository<ReadingConsistentClinicalData> _readingConsistentClinicalDataRepository
)
{
var consistentSubjectIdList = _visitTaskRepository.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId && t.IsAnalysisCreate == true).Select(t => t.SubjectId).ToList();
await _taskConsistentRuleRepository.BatchDeleteNoTrackingAsync(t => t.TrialReadingCriterionId == trialReadingCriterionId);
await _visitTaskRepository.BatchDeleteNoTrackingAsync(t => t.TrialReadingCriterionId == trialReadingCriterionId && t.IsAnalysisCreate == true);
await _readingConsistentClinicalDataPDFRepository.BatchDeleteNoTrackingAsync(t => consistentSubjectIdList.Contains(t.ReadingConsistentClinicalData.SubjectId));
await _readingConsistentClinicalDataRepository.BatchDeleteNoTrackingAsync(t => consistentSubjectIdList.Contains(t.SubjectId));
await _readingConsistentClinicalDataRepository.SaveChangesAsync();
return ResponseOutput.Ok();
}
[AllowAnonymous]
public async Task<IResponseOutput> NewIP([FromServices] IRepository<UserLog> _userLogRepository, [FromServices] IRepository<IdentityUser> _identityUserRepository)
{
var path = Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources, "GeoLite2-City.mmdb");
var ipList = _userLogRepository.Select(t => t.IP).Distinct().ToList();
foreach (var ip in ipList)
{
var ipRegion = IPCityHelper.GetCityResponse(ip);
await _userLogRepository.BatchUpdateNoTrackingAsync(t => t.IP == ip, u => new UserLog() { IPRegion = ipRegion });
}
#region 用户表最后一次登录的ipRegion 需要维护
var userList = _identityUserRepository.Where(t => t.LastLoginIP != "").Select(t => new { t.Id, t.LastLoginIP, t.UpdateUserId }).ToList();
foreach (var user in userList)
{
var lastLoginRegion = _userLogRepository.Where(t => t.ActionIdentityUserId == user.Id && (t.OptType == UserOptType.Login || t.OptType == UserOptType.LoginLockedAccount)).OrderByDescending(t => t.CreateTime).Select(t => t.IPRegion).FirstOrDefault() ?? string.Empty;
await _identityUserRepository.BatchUpdateNoTrackingAsync(t => t.Id == user.Id, u => new Domain.Models.IdentityUser() { LastLoginIP = lastLoginRegion, UpdateUserId = user.UpdateUserId });
}
#endregion
return ResponseOutput.Ok();
}
//添加医学审核问题
[AllowAnonymous]
public async Task<IResponseOutput> AddReadingMedicineSystemQuestion([FromServices] IRepository<ReadingMedicineSystemQuestion> _readingMedicineSystemQuestion)
{
if (!_readingMedicineSystemQuestion.Any(t => t.CriterionTypeEnum == CriterionType.mRECISTHCC))
{
var list = _readingMedicineSystemQuestion.Where(t => t.CriterionTypeEnum == CriterionType.RECIST1Point1).OrderBy(t => t.ShowOrder).ToList();
var initOrder = 500;
foreach (var item in list)
{
item.Id = NewId.NextSequentialGuid();
item.CriterionTypeEnum = CriterionType.mRECISTHCC;
item.CreateTime = DateTime.Now;
item.ShowOrder = initOrder;
initOrder = initOrder + 1;
}
await _readingMedicineSystemQuestion.AddRangeAsync(list, true);
}
return ResponseOutput.Ok();
}
/// <summary>
/// IQC 回退到影像上传
/// </summary>
/// <param name="subjectVisitIdList"></param>
/// <param name="_subjectVisitRepository"></param>
/// <param name="_trialQCQuestionAnswerRepository"></param>
/// <param name="_readingClinicalDataReposiotry"></param>
/// <returns></returns>
[AllowAnonymous]
[HttpPost]
public async Task<IResponseOutput> IQCBackToUpload(Guid[] subjectVisitIdList,
[FromServices] IRepository<SubjectVisit> _subjectVisitRepository,
[FromServices] IRepository<TrialQCQuestionAnswer> _trialQCQuestionAnswerRepository,
[FromServices] IRepository<ReadingClinicalData> _readingClinicalDataReposiotry)
{
foreach (var subjectVisitId in subjectVisitIdList)
{
var sv = (await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId)).IfNullThrowException();
//需要重新产生任务
sv.IsVisitTaskGenerated = false;
sv.IsPMBackOrReReading = true;
sv.AuditState = AuditStateEnum.None;
sv.SubmitState = SubmitStateEnum.ToSubmit;
sv.ReadingStatus = ReadingStatusEnum.ImageNotSubmit;
//回退后,回退状态恢复
sv.RequestBackState = RequestBackStateEnum.NotRequest;
sv.IsCheckBack = false;
sv.CheckBackTime = null;
sv.CheckState = CheckStateEnum.None;
sv.CheckChallengeState = CheckChanllengeTypeEnum.None;
sv.SVENDTC = null;
sv.SVSTDTC = null;
sv.PreliminaryAuditTime = null;
sv.SubmitTime = null;
sv.ReviewAuditTime = null;
sv.CurrentActionUserExpireTime = null;
sv.IsTake = false;
sv.CurrentActionUserId = null;
sv.PreliminaryAuditUserId = null;
sv.ReviewAuditUserId = null;
if (sv.IsBaseLine)
{
await _readingClinicalDataReposiotry.UpdatePartialFromQueryAsync(t => t.ReadingId == sv.Id && (t.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.Subject || t.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.SubjectVisit), c => new ReadingClinicalData() { IsSign = false, ReadingClinicalDataState = ReadingClinicalDataStatus.HaveUploaded });
}
else
{
await _readingClinicalDataReposiotry.UpdatePartialFromQueryAsync(t => t.ReadingId == sv.Id && t.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.SubjectVisit, c => new ReadingClinicalData()
{
IsSign = false,
ReadingClinicalDataState = ReadingClinicalDataStatus.HaveUploaded,
IsBlind = null,
IsComplete = null
});
}
await _trialQCQuestionAnswerRepository.BatchDeleteNoTrackingAsync(t => t.SubjectVisitId == subjectVisitId);
}
var success = await _subjectVisitRepository.SaveChangesAsync();
return ResponseOutput.Ok();
}
/// <summary>
/// 后端处理某个中心缩略图有问题 先下载,生成缩略图上传,然后更新数据库
/// </summary>
/// <returns></returns>
[AllowAnonymous]
public async Task<IResponseOutput> BackImageResize(Guid trialSiteId, Guid subjectId/* , [FromServices] IRepository<>*/)
{
///${params.trialId}/ Image /${params.subjectId}/${params.subjectVisitId}/${ dicomInfo.studyUid}/${ v.seriesUid}.jpg
var dealSeriesList = await _dicomSeriesRepository.Where(t => t.DicomStudy.Subject.TrialSiteId == trialSiteId && t.SubjectId == subjectId).Select(t => new { t.Id, t.SubjectId, t.TrialId, t.SubjectVisitId, t.StudyInstanceUid, t.SeriesInstanceUid, t.ImageResizePath, t.UpdateUserId, FirstInstancePath = t.DicomInstanceList.First().Path }).ToListAsync();
//下载到本地
string tempFolderPath = Path.Combine(Directory.GetCurrentDirectory(), $"DownloadTemp_{NewId.NextGuid()}");
Directory.CreateDirectory(tempFolderPath);
foreach (var dealSeries in dealSeriesList)
{
var fileName = Path.GetFileNameWithoutExtension(dealSeries.FirstInstancePath);
var localFilePath = Path.Combine(tempFolderPath, fileName);
await _IOSSService.DownLoadFromOSSAsync(dealSeries.FirstInstancePath, localFilePath);
var resizePath = localFilePath + "_New.jpg";
//生成缩略图
// 读取 DICOM 文件
var dicomImage = new DicomImage(localFilePath);
// 渲染 DICOM 图像到 ImageSharp 格式
using (var image = dicomImage.RenderImage().AsSharpImage())
{
// 生成缩略图(调整大小)
image.Mutate(x => x.Resize(500, 500));
// 保存缩略图为 JPEG
image.Save(resizePath, new JpegEncoder());
}
var ossFolder = $"{dealSeries.TrialId}/Image/{dealSeries.SubjectId}/{dealSeries.SubjectVisitId}/{dealSeries.StudyInstanceUid}";
var relativePath = await _IOSSService.UploadToOSSAsync(resizePath, ossFolder, false);
await _dicomSeriesRepository.BatchUpdateNoTrackingAsync(t => t.Id == dealSeries.Id, u => new DicomSeries() { ImageResizePath = relativePath, UpdateUserId = dealSeries.UpdateUserId });
}
return ResponseOutput.Ok();
}
public async Task<IResponseOutput> DeleteOSSDate(string rootFolder,
[FromServices] IOSSService _oSSService, [FromServices] IWebHostEnvironment _hostEnvironment)
{
//var deleteIdList = _trialRepository.Where(t => t.IsDeleted == true, false, true).Select(t => t.Id).ToList();
//foreach (var deleteId in deleteIdList)
//{
// await _oSSService.DeleteFromPrefix($"{deleteId}");
//}
var trialIdExistList = _trialRepository.Select(t => t.Id).ToList().Select(t => t.ToString());
#region 列出根目录
var aliConfig = _oSSService.ObjectStoreServiceOptions.AliyunOSS;
var tempToken = _oSSService.GetObjectStoreTempToken();
var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint,
tempToken.AliyunOSS.AccessKeyId,
tempToken.AliyunOSS.AccessKeySecret,
tempToken.AliyunOSS.SecurityToken);
var folderList = new List<string>();
try
{
ObjectListing objectListing = null;
string nextMarker = null;
do
{
// 使用 prefix 模拟目录结构,设置 MaxKeys 和 NextMarker
objectListing = _ossClient.ListObjects(new Aliyun.OSS.ListObjectsRequest(aliConfig.BucketName)
{
Prefix = "", // 根目录,留空即可
Delimiter = "/", // 使用 "/" 来区分目录
MaxKeys = 100,
Marker = nextMarker
});
folderList.AddRange(objectListing.CommonPrefixes.Select(t => t.Trim('/')).ToList());
// 设置 NextMarker 以获取下一页的数据
nextMarker = objectListing.NextMarker;
} while (objectListing.IsTruncated);
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
//清理项
var needDeleteTrialIdList = folderList.Except(trialIdExistList).ToList();
#endregion
await _oSSService.DeleteFromPrefix($"{rootFolder}");
return ResponseOutput.Ok();
}
[AllowAnonymous]
public async Task<IResponseOutput> UserCreateSourceDeal([FromServices] IRepository<IdentityUser> _identityUserRepository,
[FromServices] IRepository<TrialUserRole> _trialUserRoleRepository)
{
var list = _userRoleRepository.Where().IgnoreQueryFilters().ToList();
foreach (var item in list.GroupBy(t => t.IdentityUserId))
{
var userRoleList = item.OrderBy(t => t.CreateTime).ToList();
foreach (var userRole in userRoleList)
{
var isTrue = userRole.UserTypeEnum == UserTypeEnum.SystemAdmin || userRole.UserTypeEnum == UserTypeEnum.OP || userRole.UserTypeEnum == UserTypeEnum.Dashboard;
if (isTrue)
{
await _userRoleRepository.BatchUpdateNoTrackingAsync(t => t.Id == userRole.Id, t => new UserRole() { IsUserRoleDisabled = true });
}
}
var firstCreateRole = userRoleList.FirstOrDefault();
var firstTrialId = _trialUserRoleRepository.Where(t => t.TrialUser.IdentityUserId == firstCreateRole.IdentityUserId).IgnoreQueryFilters().OrderBy(t => t.CreateTime).Select(t => t.TrialId).FirstOrDefault();
if (firstCreateRole.UserTypeEnum == UserTypeEnum.IndependentReviewer)
{
await _identityUserRepository.BatchUpdateNoTrackingAsync(t => t.Id == firstCreateRole.IdentityUserId, u => new Domain.Models.IdentityUser() { UserCeateSource = UserCeateSource.ReviewerSelect, TrialId = firstTrialId });
}
else if (firstCreateRole.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator || firstCreateRole.UserTypeEnum == UserTypeEnum.CRA)
{
await _identityUserRepository.BatchUpdateNoTrackingAsync(t => t.Id == firstCreateRole.IdentityUserId, u => new Domain.Models.IdentityUser() { UserCeateSource = UserCeateSource.AdminCreate, TrialId = firstTrialId });
}
else if (firstCreateRole.UserTypeEnum == UserTypeEnum.SPM || firstCreateRole.UserTypeEnum == UserTypeEnum.CPM ||
firstCreateRole.UserTypeEnum == UserTypeEnum.SMM || firstCreateRole.UserTypeEnum == UserTypeEnum.CMM ||
firstCreateRole.UserTypeEnum == UserTypeEnum.EA || firstCreateRole.UserTypeEnum == UserTypeEnum.MC)
{
await _identityUserRepository.BatchUpdateNoTrackingAsync(t => t.Id == firstCreateRole.IdentityUserId, u => new Domain.Models.IdentityUser() { UserCeateSource = UserCeateSource.AdminCreate, TrialId = firstTrialId });
}
else
{
await _identityUserRepository.BatchUpdateNoTrackingAsync(t => t.Id == firstCreateRole.IdentityUserId, u => new Domain.Models.IdentityUser() { UserCeateSource = UserCeateSource.AdminCreate, TrialId = firstTrialId });
}
}
return ResponseOutput.Ok();
}
[AllowAnonymous]
public async Task<IResponseOutput> DealDicomFileSize([FromServices] IOSSService _oSSService, [FromServices] IRepository<DicomInstance> _dicomInstanceRepository)
{
var instanceList = _dicomInstanceRepository.Where(t => t.TrialId == Guid.Parse("01000000-AC13-0242-3AE4-08DC9B0495C6"))
.Where(t => t.FileSize == 0 || t.FileSize == null)
.Select(t => new { t.Path, t.Id }).ToList();
foreach (var item in instanceList)
{
try
{
var fileSize = await _oSSService.GetObjectSizeAsync(item.Path);
await _dicomInstanceRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Id, u => new DicomInstance() { FileSize = fileSize });
}
catch (Exception ex)
{
Console.WriteLine(item.Path + " : " + ex.Message);
}
}
return ResponseOutput.Ok();
}
/// <summary>
/// 非dicom 临床数据
/// </summary>
/// <param name="_identityUserRepository"></param>
/// <param name="_trialUserRoleRepository"></param>
/// <returns></returns>
[AllowAnonymous]
public async Task<IResponseOutput> DealTialFileSie([FromServices] IOSSService _oSSService,
[FromServices] IRepository<NoneDicomStudyFile> _noneDicomStudyFileRepository,
[FromServices] IRepository<ReadingClinicalDataPDF> _readingClinicalDataPDFRepository)
{
var noneDicomList = _noneDicomStudyFileRepository/*.Where(t=>t.NoneDicomStudy.TrialId==Guid.Parse("01000000-ac13-0242-3ae4-08dc9b0495c6"))*/.Where(t => t.FileSize == 0 || t.FileSize == null).Select(t => new { t.Path, t.Id }).ToList();
var clinicalDataPDFList = _readingClinicalDataPDFRepository.Where(t => t.Size == 0).Select(t => new { t.Path, t.Id }).ToList();
foreach (var item in noneDicomList)
{
try
{
var fileSize = await _oSSService.GetObjectSizeAsync(item.Path);
await _noneDicomStudyFileRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Id, u => new NoneDicomStudyFile() { FileSize = fileSize });
}
catch (Exception ex)
{
Console.WriteLine(item.Path + " : " + ex.Message);
}
}
foreach (var item in clinicalDataPDFList)
{
try
{
var fileSize = await _oSSService.GetObjectSizeAsync(item.Path);
await _readingClinicalDataPDFRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Id, u => new ReadingClinicalDataPDF() { Size = (int)fileSize });
}
catch (Exception ex)
{
Console.WriteLine(item.Path + " : " + ex.Message);
}
}
return ResponseOutput.Ok();
}
[LowerCamelCaseJson]
public class TestModel
{
public Guid TestId { get; set; }
public string? TestName { get; set; }
}
public class TestModel2
{
public Guid TestId { get; set; }
public string TestName { get; set; }
}
public async Task<IResponseOutput> TestAutoEncretpt([FromServices] IRepository<TestLength> _testLengthRepository)
{
await _testLengthRepository.AddAsync(new TestLength() { Name = "zhouhang1" });
await _testLengthRepository.AddAsync(new TestLength() { Name = "hewentao" });
await _testLengthRepository.SaveChangesAsync();
var list = _testLengthRepository.Where().ToList();
var exist = await _testLengthRepository.AnyAsync(t => t.Name == "zhouhang1");
return ResponseOutput.Ok(list, exist);
}
public async Task<IResponseOutput> TestJson()
{
throw new BusinessValidationFailedException("传统控制器异常");
var model1 = new TestModel() { TestId = NewId.NextSequentialGuid(), TestName = null };
var model2 = new TestModel2() { TestId = NewId.NextSequentialGuid(), TestName = "test2" };
var model4 = _mapper.Map(model1, model2);
await _trialBodyPartRepository.FirstOrDefaultAsync();
await _trialBodyPartRepository.Where(t => t.Trial.Id == Guid.Empty).FirstOrDefaultAsync();
return ResponseOutput.Ok(new TestModel(), IRCEmailPasswordHelper.GenerateRandomPassword(10));
}
public string TestHoliday(DateTime startdate, DateTime endDate)
{
var timeSpan = HolidayHelper.GetChinaWorkTimeSpan(startdate, endDate);
_userRoleRepository.Where(t => t.Id == _userInfo.UserRoleId).Select(t => t.FullName).FirstOrDefault();
return $"{timeSpan.Days}天,{timeSpan.Hours}小时{timeSpan.Minutes}分钟{timeSpan.Seconds}秒";
}
public async Task<IResponseOutput> TestEFcore8()
{
var systemDocQuery = from sysDoc in _systemDocumentRepository.Where()
join confirm in _systemDocConfirmedUserRepository.Where().Where(t => t.ConfirmTime != null) on sysDoc.Id equals confirm.SystemDocumentId
select new UnionDocumentWithConfirmInfoView()
{
IsSystemDoc = true,
Id = sysDoc.Id,
CreateTime = sysDoc.CreateTime,
IsDeleted = sysDoc.IsDeleted,
SignViewMinimumMinutes = sysDoc.SignViewMinimumMinutes,
Name = sysDoc.Name,
Path = sysDoc.Path,
FileType = _userInfo.IsEn_Us ? sysDoc.FileType.Value : sysDoc.FileType.ValueCN,
FileTypeId = sysDoc.FileTypeId,
UpdateTime = sysDoc.UpdateTime,
ConfirmUserId = confirm.ConfirmUserId,
ConfirmTime = confirm.ConfirmTime,
RealName = confirm.ConfirmUser.FullName,
UserName = confirm.ConfirmUser.UserName,
FullFilePath = sysDoc.Path
};
var list = systemDocQuery.OrderBy(t => t.ConfirmUserId).ThenBy(t => t.ConfirmTime).ToList();
//var aa= _dicRepository._dbContext.Subject.Where(t => t.Id == Guid.Empty).ExecuteUpdate("FirstName","ddd");
//await _repository.BatchUpdateAsync<Subject>(t => t.Id == Guid.Empty, u => new Subject() { FirstName = "fddd", LastName = "sss", UpdateTime = DateTime.Now });
//await _subjectRepository.Where().ExecuteUpdateAsync(t => t.SetProperty(t => t.UpdateTime, u => DateTime.Now));
return ResponseOutput.Ok(list);
}
// 设置 Ne
[AllowAnonymous]
public async Task<IResponseOutput> TestMinIO([FromServices] IOSSService oSSService)
{
var str = await oSSService.GetSignedUrl("/01000000-c0a8-0242-1c98-08dc7ebcd37d/Read/01000000-c0a8-0242-1c98-08dc7ebcd37d/Visit/1716872544006_1716872544003.png");
//await oSSService.UploadToOSSAsync("C:\\Users\\Administrator\\Desktop\\TrialSiteUserImportTemplate.xlsx", "myfolder");
//await oSSService.DownLoadFromOSSAsync("/myfolder/TrialSiteUserImportTemplate.xlsx", "C:\\Users\\Administrator\\Desktop\\aws.xlsx");
return ResponseOutput.Ok(str);
}
[AllowAnonymous]
public async Task<IResponseOutput> TestDistributedLock()
{
await _userRoleRepository.Where().Select(t => t.FullName).FirstNotNullAsync();
Console.WriteLine($"我进来了当前值是:" + IntValue);
_logger.LogWarning($"我进来了当前值是:" + IntValue);
var @lock = _distributedLockProvider.CreateLock($"UserAccount");
using (await @lock.AcquireAsync())
{
await Task.Delay(4);
IntValue--;
_logger.LogWarning(IntValue.ToString());
Console.WriteLine(IntValue);
}
return ResponseOutput.Ok(IntValue);
}
[AllowAnonymous]
public async Task<IResponseOutput> InternationazitionInit()
{
var rows = await MiniExcel.QueryAsync<InternationalizationAddOrEdit>(@"C:\Users\Administrator\Desktop\i18n-new.xlsx");
rows = rows.Where(t => !string.IsNullOrEmpty(t.Code)).ToList();
foreach (var row in rows)
{
await _internationalizationRepository.InsertOrUpdateAsync(row);
}
await _internationalizationRepository.SaveChangesAsync();
return ResponseOutput.Ok();
}
public class TestEncrept
{
public string Name { get; set; }
public string Code { get; set; }
}
public IResponseOutput TestEncreptTest(TestEncrept testModel)
{
return ResponseOutput.Ok(testModel);
}
//etx5EzcF9XWA6ICzQB5ywEEextuhmUwaHM2TmyyCC8Q=
[HttpPut("{name}/{code}")]
public IResponseOutput TestEncreptTest2(string name, string code)
{
return ResponseOutput.Ok($"name:{name} Code: {code}");
}
public IResponseOutput TestEncreptTest3(string name, string Code)
{
return ResponseOutput.Ok($"name:{name} Code: {Code}");
}
[UnitOfWork]
public async Task<string> Get([FromServices] IOptionsMonitor<IRCEncreptOption> _encreptResponseMonitor)
{
var _IRCEncreptOption = _encreptResponseMonitor.CurrentValue;
var publicKey = Encoding.UTF8.GetString(Convert.FromBase64String(_IRCEncreptOption.Base64RSAPublicKey));
var privateKey = Encoding.UTF8.GetString(Convert.FromBase64String(_IRCEncreptOption.Base64RSAPrivateKey));
Console.WriteLine(RSAEncryption.Encrypt(publicKey, MD5Helper.Md5("123456")));
//U2FsdGVkX1+atIRsUP6uhWIMHIVmn7U2sy4HlgWiWJG1qc0WdYyQqzgTJ1JLeQGHvYrIYm90/YCkBYclYbnm1g==
string plainText = "Hello, BouncyCastle!";
string key = "12345678901234567890123456789012"; // AES 密钥长度应为 16 字节(128 位)
string iv = "your-iv-12345678"; // IV 长度为 16 字节
var encreptMd5 = AesEncryption.Encrypt(MD5Helper.Md5("123456"), key);
Console.WriteLine(encreptMd5);
var decrept = AesEncryption.Decrypt(encreptMd5, key);
Console.WriteLine();
Console.WriteLine(AesEncryption.Encrypt("cyldev", key));
Console.WriteLine($"原始文本: {plainText}");
// 加密
string encrypted = AesEncryption.Encrypt(plainText, key, iv);
Console.WriteLine($"加密后的数据: {encrypted}");
// 解密
string decrypted = AesEncryption.Decrypt(encrypted, key, iv);
Console.WriteLine($"解密后的数据: {decrypted}");
Console.WriteLine($"原始文本: {plainText}");
// 加密
string encrypte = AesEncryption.Encrypt(plainText, key);
Console.WriteLine($"加密后的数据: {encrypte}");
// 解密
string decrypte = AesEncryption.Decrypt(encrypte, key);
Console.WriteLine($"解密后的数据: {decrypte}");
//// Generate RSA keys
//var keyPair = RSAEncryption.GenerateRSAKeyPair(2048);
//// Export the public and private keys to PEM format
//string publicKey = RSAEncryption.ExportPublicKey(keyPair.Public);
//string privateKey = RSAEncryption.ExportPrivateKey(keyPair.Private);
//Console.WriteLine("Public Key:");
//Console.WriteLine(publicKey);
//Console.WriteLine($"{Convert.ToBase64String(Encoding.UTF8.GetBytes(publicKey))}");
//Console.WriteLine("\nPrivate Key:");
//Console.WriteLine(privateKey);
//Console.WriteLine($"{Convert.ToBase64String(Encoding.UTF8.GetBytes(privateKey))}");
Console.WriteLine("Public Key:");
Console.WriteLine(publicKey);
Console.WriteLine("\nPrivate Key:");
Console.WriteLine(privateKey);
Console.WriteLine("encrept sys Key:");
Console.WriteLine($"\n{RSAEncryption.Encrypt(publicKey, key)}");
// Data to encrypt
string dataToEncrypt = "Hello, RSA!";
Console.WriteLine("\nOriginal Data: " + dataToEncrypt);
// Encrypt the data
var encryptedData = RSAEncryption.Encrypt(publicKey, dataToEncrypt);
Console.WriteLine("\nEncrypted Data: " + encryptedData);
// Decrypt the data
string decryptedData = RSAEncryption.Decrypt(privateKey, encryptedData);
Console.WriteLine("\nDecrypted Data: " + decryptedData);
return "测试自动发布--再次提交";
}
//[AllowAnonymous]
//public async Task<string> testDoc([FromServices] IWebHostEnvironment env, string email)
//{
// #region DocX 测试
// //using (DocX document = DocX.Load("C:\\Users\\hang\\Desktop\\test.docx"))
// //{
// // // 查找书签
// // var bookmarkCn_Start = document.Bookmarks.FirstOrDefault(b => b.Name == "zh_cn");
// // var bookmarkEn_Start = document.Bookmarks.FirstOrDefault(b => b.Name == "en_us");
// // if (bookmarkCn_Start != null && bookmarkEn_Start != null)
// // {
// // // 获取书签的起始位置
// // int bookmarkCNStartPos = bookmarkCn_Start.Paragraph.StartIndex;
// // var bookmarkENStartPos = bookmarkEn_Start.Paragraph.StartIndex;
// // // // 创建一个要删除段落的列表
// // List<Paragraph> paragraphsToRemove = new List<Paragraph>();
// // foreach (var item in document.Paragraphs)
// // {
// // //中文模板在前,英文在后,英文模板,就删除英文之前的,中文模板就删除英文之后的
// // //_userInfo.IsEn_Us? item.EndIndex< bookmarkENStartPos :item.StartIndex>= bookmarkENStartPos
// // if (item.StartIndex>= bookmarkENStartPos)
// // {
// // paragraphsToRemove.Add(item);
// // }
// // }
// // foreach (var paragraph in paragraphsToRemove)
// // {
// // document.RemoveParagraph(paragraph);
// // }
// // }
// // // 保存修改
// // document.SaveAs("C:\\Users\\hang\\Desktop\\test1.docx");
// //}
// #endregion
// using (FileStream fs = new FileStream("C:\\Users\\hang\\Desktop\\test.docx", FileMode.Open, FileAccess.Read))
// {
// XWPFDocument doc = new XWPFDocument(fs);
// // 查找包含指定书签的段落及其索引
// var bookmarkParagraph = doc.Paragraphs
// .FirstOrDefault(p => p.GetCTP().GetBookmarkStartList().Any(b => b.name == "en_us"));
// if (bookmarkParagraph != null)
// {
// int bookmarkIndex = doc.Paragraphs.IndexOf(bookmarkParagraph);
// // 删除书签之后的所有段落
// for (int i = doc.Paragraphs.Count - 1; i >= bookmarkIndex; i--)
// {
// doc.RemoveBodyElement(i);
// }
// }
// else
// {
// throw new BusinessValidationFailedException("word 模板没有英文书签");
// }
// // 创建一个要删除段落的列表
// //XWPFParagraph bookmarkParagraph = null;
// //foreach (var paragraph in doc.Paragraphs)
// //{
// // foreach (var bookmark in paragraph.GetCTP().GetBookmarkStartList())
// // {
// // if (bookmark.name == "en_us")
// // {
// // bookmarkParagraph = paragraph;
// // break;
// // }
// // }
// //}
// //// 从书签所在段落开始,删除之前的所有段落
// //for (int i = bookmarkIndex - 1; i >= 0; i--)
// //{
// // doc.RemoveBodyElement(i);
// //}
// using (FileStream outStream = new FileStream("C:\\Users\\hang\\Desktop\\test1.docx", FileMode.Create, FileAccess.Write))
// {
// doc.Write(outStream);
// }
// }
// return "hiddenEmail";
//}
[AllowAnonymous]
public async Task<object> GetEnvironmentName([FromServices] IWebHostEnvironment env)
{
//var a = IdentifierHelper.CreateGuid("123456");
//var k = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes("123456"));
//var c = MD5Helper.Md5("123456");
//return new { env.EnvironmentName, EMailConfig = _systemEmailConfig.CurrentValue, BasicConfig = _basicConfig.CurrentValue };
// Load a document.
//using (var document = DocX.Load(Path.Combine(_hostEnvironment.ContentRootPath, "ReplaceText.docx")))
//{
// // Check if all the replace patterns are used in the loaded document.
// if (document.FindUniqueByPattern(@"<[\w \=]{4,}>", RegexOptions.IgnoreCase).Count > 0)
// {
// // Do the replacement of all the found tags and with green bold strings.
// //for (int i = 0; i < _replacePatterns.Count; ++i)
// //{
// // document.ReplaceText("<(.*?)>", TestService.ReplaceFunc, false, RegexOptions.IgnoreCase, new Formatting() { Bold = true, FontColor = System.Drawing.Color.Green });
// //}
// // Save this document to disk.
// document.ReplaceText("test", "jfdksajfkljflsdjf", false, RegexOptions.IgnoreCase, new Formatting() { Bold = true, FontColor = System.Drawing.Color.Green });
// document.SaveAs("ReplacedText.docx");
// }
//}
//return await NpoiWordHelper.TemplateExportWordAsync(Path.Combine(_hostEnvironment.ContentRootPath, "ReplaceText.docx"), new { test = "xiugai", ZZZZ = "ModiffyZZZZ" }, null, _hostEnvironment);
//_cache.SetString("test" , "cacheStr");
//var aa= _trialRepository.Where(t => t.Id == Guid.Empty).First();
//var aaabb = _trialRepository.BatchDeleteNoTrackingAsync(t => t.Id == Guid.Empty).Result;
//var aaaa = _dicRepository.BatchDeleteNoTrackingAsync(t => t.Id == Guid.Empty).Result;
//var waitModifyEntity = _dicRepository.FirstOrDefaultAsync(t => t.Id == Guid.Parse("e2b97a6c-35a6-4aa3-7f27-08da13ab33ff")).GetAwaiter().GetResult();
//var tt = _dicRepository.UpdateAsync(waitModifyEntity, t => new Dictionary() { Description = "xxxxx" }, true).Result;
//var tt2 = _trialRepository.UpdatePartialFromQueryAsync(Guid.Parse("543d0000-3e10-0016-77e9-08da2827228a"), t => new Trial() { Indication = "WCH测试稽查002" }, true).Result;
//var d = _userRoleRepository.Where(t => t.FullName.Contains("cc")).Select(t => t.FullName).FirstOrDefault();
//var c = _dicRepository.Where(t => t.ParentId != null).Select(t => t.MappedValue).First();
//CultureInfo culture = CultureInfo.CurrentUICulture;
//var dd = _dicRepository.UpdatePartialFields(Guid.Parse("8a90c96e-0776-4f7b-82a6-18933d339584"),
// u => new Dictionary() { ParentId = null, Code = "test" }, true);
//var ggggg = _dicRepository.UpdateFromQueryAsync(t => t.ParentId == Guid.Parse("8a90c96e-0776-4f7b-82a6-18933d339584"), u=>new Dictionary(){Code = "test"}).Result;
//var ddd = _dicRepository.BatchUpdateAsync(t => t.Id == Guid.Parse("8a90c96e-0776-4f7b-82a6-18933d339584"),
// u => new Dictionary() { /*ParentId = null,*/ Code = "test" }).Result;
//var aaaaa= _trialRepository.BatchUpdateAsync(t => t.Id == Guid.Empty,
// u => new SubjectVisit() { CurrentActionUserId = null }).Result;
//var d = _dicRepository.UpdateFromDTOAsync(new AddOrEditBasicDic() { Id = Guid.Parse("60d86683-c33b-4349-b672-08da1e91b622"), ParentId = null, ChildGroup = null, Code = null }, true, true).Result;
//var a = 123;
//throw new BusinessValidationFailedException(_localizer["TrialIsDoubleCheck{0}", "测试"]);
//var b = _localizer["test{0}", "测试"];
//return _localizer["test{0}", "测试"];
//var list = _subjectVisitRepository.Where(t => t.Id == Guid.NewGuid()).SelectMany(t => t.VisitTaskList).ToList();
//var list2 = _visitTaskRepository.Where(t => t.Id == Guid.NewGuid()).Select(t => t.SourceSubjectVisit).ToList();
//var list3 = _visitTaskRepository.Where(t => t.Id == Guid.NewGuid()).SelectMany(t => t.SourceSubjectVisit.VisitTaskList).ToList();
//var list2 = _subjectRepository.Where(t => t.Id == Guid.NewGuid()).SelectMany(t => t.SubjectVisitTaskList).ToList();
//return _userInfo.LocalIp;
return _userInfo.ClientInfo;
}
public async Task<IResponseOutput> ModifyTrialBodyPart()
{
var searchList = await _dicRepository.Where(t => t.Parent.Code == "BodyPart" && t.ParentId != null && t.IsEnable).ProjectTo<BasicDicSelect>(_mapper.ConfigurationProvider).ToListAsync();
var needAddBodyPartList = searchList.Select(t => new TrialBodyPart() { Code = t.Code, Name = t.Value, NameCN = t.ValueCN });
var trialIds = _trialRepository.Where(t => !t.TrialBodyPartList.Any()).Select(t => t.Id).ToList();
foreach (var trialId in trialIds)
{
var tempList = needAddBodyPartList.Clone();
tempList.ForEach(t => t.TrialId = trialId);
await _trialBodyPartRepository.AddRangeAsync(tempList);
}
await _dicRepository.SaveChangesAsync();
return ResponseOutput.Ok();
}
#region 历史维护
/// <summary>
/// 维护临床数据 --一定要在同步表前同步数据才行
/// </summary>
/// <returns></returns>
[AllowAnonymous]
public async Task<IResponseOutput> ModifyClinicalDataTable()
{
var needAddList = _clinicalDataTrialSetRepository.Where(t => t.CriterionEnumListStr != String.Empty && t.TrialClinicalDataSetCriteriaList.Count() == 0).ToList();
//遍历项目
foreach (var needAddTrialGroup in needAddList.GroupBy(t => t.TrialId))
{
//找到项目存在的项目标准
var trialCritrialList = _readingQuestionCriterionTrialRepository.Where(t => t.TrialId == needAddTrialGroup.Key).ToList();
//遍历项目下的临床数据
foreach (var needAddTrial in needAddTrialGroup)
{
//遍历每条临床数据配置的标准
foreach (var item in needAddTrial.CriterionEnumList)
{
var find = trialCritrialList.Where(t => (int)t.CriterionType == item).FirstOrDefault();
if (find != null)
{
await _trialClinicalDataSetCriterionRepository.AddAsync(new TrialClinicalDataSetCriterion() { TrialClinicalDataSetId = needAddTrial.Id, TrialReadingCriterionId = find.Id });
}
}
}
}
await _trialClinicalDataSetCriterionRepository.SaveChangesAsync();
return ResponseOutput.Ok();
}
/// <summary>
/// 维护OSS 影像数据
/// </summary>
/// <returns></returns>
[AllowAnonymous]
[UnitOfWork]
public async Task<IResponseOutput> OldLocalImageResizeJpg([FromServices] IOSSService oSSService, [FromServices] IWebHostEnvironment _hostEnvironment)
{
var aliConfig = oSSService.ObjectStoreServiceOptions.AliyunOSS;
var _ossClient = new OssClient(aliConfig.EndPoint, aliConfig.AccessKeyId, aliConfig.AccessKeySecret);
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
var studyList = _dicomStudyRepository.Where(t => t.SeriesList.Any(t => t.ImageResizePath.Length < 10)).Select(t => new { t.TrialId, t.Subject.TrialSiteId, t.SubjectId, t.SubjectVisitId, t.Id }).ToList();
foreach (var studyitem in studyList)
{
var relativePath = $"{studyitem.TrialId}/{studyitem.TrialSiteId}/{studyitem.SubjectId}/{studyitem.SubjectVisitId}/{StaticData.Folder.DicomFolder}/{studyitem.Id}/";
try
{
string nextMarker = null;
do
{
// 使用 prefix 模拟目录结构,设置 MaxKeys 和 NextMarker
var objectListing = _ossClient.ListObjects(new ListObjectsRequest(aliConfig.BucketName)
{
Prefix = relativePath,
MaxKeys = 1000,
Marker = nextMarker
});
var jpgInfoList = objectListing.ObjectSummaries
.Where(summary => summary.Key.EndsWith(".jpg"))
.Select(summary =>
{
string fileName = summary.Key.Split('/').Last(); // 提取文件夹名
return new
{
Key = summary.Key,
InstanceId = Guid.TryParse(
fileName.Split('.')[0],
out Guid instanceId)
? instanceId
: Guid.Empty
};
})
.Where(info => info.InstanceId != Guid.Empty)
.ToList();
foreach (var jpg in jpgInfoList)
{
var seriesId = _dicomInstanceRepository.Where(t => t.Id == jpg.InstanceId).Select(t => t.SeriesId).FirstOrDefault();
await _dicomSeriesRepository.BatchUpdateNoTrackingAsync(t => t.Id == seriesId, t => new DicomSeries() { ImageResizePath = "/" + jpg.Key });
}
// 设置 NextMarker 以获取下一页的数据
nextMarker = objectListing.NextMarker;
} while (!string.IsNullOrEmpty(nextMarker));
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
await _dicomStudyRepository.SaveChangesAsync();
}
return ResponseOutput.Ok();
}
#endregion
}
public class TestModel
{
//[Required]
public string Id { get; set; }
public string Name { get; set; }
public DateTime? Time { get; set; }
}
}
namespace Localization
{
public class SharedResource
{
}
}