Compare commits

..

9 Commits

Author SHA1 Message Date
hang 80d78cb989 修改 2026-07-31 18:53:15 +08:00
hang 681ba17e37 修改清理缓存 2026-07-31 18:03:46 +08:00
hang 3385b65967 修复后处理增加数量bug 2026-07-30 17:52:21 +08:00
hang d6045ef7e7 Merge branch 'irc-add-image' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into irc-add-image 2026-07-30 17:43:17 +08:00
hang f66829ca62 上传记录屏蔽+IR已下载修改 2026-07-30 17:43:17 +08:00
he 471ea524b7 查询修改 2026-07-30 17:38:50 +08:00
he 34e9269916 提交答案取消签名验证 2026-07-30 16:03:57 +08:00
he 29d50fdd2d 稽查修改 2026-07-30 16:02:04 +08:00
hang 9f19dfceac 临时屏蔽CRC 上传监控 以及稽查 2026-07-30 16:00:30 +08:00
23 changed files with 163 additions and 1077 deletions

View File

@ -89,6 +89,7 @@ public class FileUploadRecordService(IRepository<FileUploadRecord> _fileUploadRe
public async Task<IResponseOutput> AddOrUpdateFileUploadRecord(FileUploadRecordAddOrEdit addOrEditFileUploadRecord) public async Task<IResponseOutput> AddOrUpdateFileUploadRecord(FileUploadRecordAddOrEdit addOrEditFileUploadRecord)
{ {
return ResponseOutput.Ok();
addOrEditFileUploadRecord.IP = _userInfo.IP; addOrEditFileUploadRecord.IP = _userInfo.IP;

View File

@ -4,16 +4,30 @@ using IRaCIS.Core.API.HostService;
using IRaCIS.Core.Application.BusinessFilter; using IRaCIS.Core.Application.BusinessFilter;
using IRaCIS.Core.Application.BusinessFilter.LegacyController.Database.Api; using IRaCIS.Core.Application.BusinessFilter.LegacyController.Database.Api;
using IRaCIS.Core.Application.Filter; using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.MassTransit.Consumer;
using IRaCIS.Core.Application.Service; using IRaCIS.Core.Application.Service;
using IRaCIS.Core.Application.Service.BusinessFilter;
using IRaCIS.Core.Infra.EFCore; using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Infrastructure.Extention; using IRaCIS.Core.Infrastructure.Extention;
using MassTransit; using MassTransit;
using MassTransit.NewIdProviders; using MassTransit.NewIdProviders;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Localization;
using Newtonsoft.Json; using Newtonsoft.Json;
using Serilog; using Serilog;
using System;
using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using UAParser;
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
AppContext.SetSwitch("Npgsql.DisableDateTimeInfinityConversions", true); AppContext.SetSwitch("Npgsql.DisableDateTimeInfinityConversions", true);
@ -81,8 +95,6 @@ builder.Services.AddSingleton<FileSyncQueue>();
builder.Services.AddHostedService<SyncFileRecoveryService>(); builder.Services.AddHostedService<SyncFileRecoveryService>();
builder.Services.AddHostedService<FileSyncWorker>(); builder.Services.AddHostedService<FileSyncWorker>();
builder.Services.AddSingleton(_ => Parser.GetDefault());
//minimal api 异常处理 //minimal api 异常处理
builder.Services.AddExceptionHandler<GlobalExceptionHandler>(); builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
//builder.Services.AddProblemDetails(); //builder.Services.AddProblemDetails();

View File

@ -5,7 +5,6 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Serilog; using Serilog;
using System.Linq; using System.Linq;
using UAParser;
namespace IRaCIS.Core.API namespace IRaCIS.Core.API
{ {
@ -18,14 +17,11 @@ namespace IRaCIS.Core.API
{ {
app.UseMiddleware<RequestResponseLoggingMiddleware>(); app.UseMiddleware<RequestResponseLoggingMiddleware>();
// 从 DI 容器中获取 Parser 实例
var uaParser = app.ApplicationServices.GetRequiredService<Parser>();
app.UseSerilogRequestLogging(opts app.UseSerilogRequestLogging(opts
=> =>
{ {
opts.MessageTemplate = "{FullName} {UserType} {UserIp} {Host} {RequestMethod} {RequestPath}{QueryString} {RequestBody} {OS} {Browser} {DeviceType} responded {StatusCode} in {Elapsed:0.0000} ms"; opts.MessageTemplate = "{FullName} {UserType} {UserIp} {Host} {RequestMethod} {RequestPath} {RequestBody} responded {StatusCode} in {Elapsed:0.0000} ms";
opts.EnrichDiagnosticContext = (diagnosticContext, httpContext) => opts.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
{ {
@ -37,9 +33,10 @@ namespace IRaCIS.Core.API
// Only set it if available. You're not sending sensitive data in a querystring right?! // Only set it if available. You're not sending sensitive data in a querystring right?!
if (request.QueryString.HasValue)
diagnosticContext.Set("QueryString", request.QueryString.Value ?? ""); {
diagnosticContext.Set("QueryString", request.QueryString.Value);
}
diagnosticContext.Set("FullName", httpContext?.User?.FindFirst(JwtIRaCISClaimType.FullName)?.Value); diagnosticContext.Set("FullName", httpContext?.User?.FindFirst(JwtIRaCISClaimType.FullName)?.Value);
@ -55,38 +52,6 @@ namespace IRaCIS.Core.API
diagnosticContext.Set("UserIp", clientIp); diagnosticContext.Set("UserIp", clientIp);
// ==================== 新增:解析 User-Agent ====================
try
{
var userAgent = httpContext.Request.Headers["User-Agent"].ToString();
if (!string.IsNullOrEmpty(userAgent))
{
var clientInfo = uaParser.Parse(userAgent);
diagnosticContext.Set("OS", clientInfo.OS.ToString());
diagnosticContext.Set("Browser", clientInfo.UA.ToString());
//diagnosticContext.Set("DeviceType", clientInfo.Device.ToString());
diagnosticContext.Set("DeviceType", userAgent.Contains("Mobile") ? "Mobile": "Desktop");
}
else
{
diagnosticContext.Set("OS", "Unknown");
diagnosticContext.Set("Browser", "Unknown");
diagnosticContext.Set("DeviceType", "Unknown");
}
}
catch (Exception ex)
{
// 解析失败时记录异常,但不要影响主流程
diagnosticContext.Set("OS", "ParseError");
diagnosticContext.Set("Browser", "ParseError");
diagnosticContext.Set("DeviceType", "ParseError");
}
// ==============================================================
#region 非必要不记录 #region 非必要不记录
//diagnosticContext.Set("Protocol", request.Protocol); //diagnosticContext.Set("Protocol", request.Protocol);
//diagnosticContext.Set("Scheme", request.Scheme); //diagnosticContext.Set("Scheme", request.Scheme);

View File

@ -7,7 +7,7 @@
} }
}, },
"ConnectionStrings": { "ConnectionStrings": {
"RemoteNew": "Server=101.132.193.237,1433;Database=Prod_IRC_pidr_restore_new;User ID=sa;Password=xc@123456;TrustServerCertificate=true", "RemoteNew": "Server=101.132.193.237,1433;Database=Prod_IRC_pidr_restore;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=101.132.193.237,1433;Database=irc_Hangfire_bak;User ID=sa;Password=xc@123456;TrustServerCertificate=true" "Hangfire": "Server=101.132.193.237,1433;Database=irc_Hangfire_bak;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
//"RemoteNew": "Server=prod_mssql_standard,1433;Database=Prod_IRC;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true", //"RemoteNew": "Server=prod_mssql_standard,1433;Database=Prod_IRC;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true",
//"Hangfire": "Server=prod_mssql_standard,1433;Database=Prod_IRC_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true" //"Hangfire": "Server=prod_mssql_standard,1433;Database=Prod_IRC_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true"
@ -44,11 +44,11 @@
"RegionId": "cn-shanghai", "RegionId": "cn-shanghai",
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com", "InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com", "EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
"AccessKeyId": "LTAI5tNRTsqL6aWmHkDmTwoH", "AccessKeyId": "LTAI5tFUCCmz5TwghZHsj45Y",
"AccessKeySecret": "7mtGz3qrYWI6JMMBZiLeC119VWicZH", "AccessKeySecret": "8evrBy1fVfzJG25i67Jm0xqn9Xcw2T",
"RoleArn": "acs:ram::1899121822495495:role/irc-oss-access", "RoleArn": "acs:ram::1078130221702011:role/uat-oss-access",
"BucketName": "zy-irc-store", "BucketName": "tl-med-irc-event-store",
"ViewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com", "ViewEndpoint": "https://tl-med-rc-event-cache.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai", "Region": "oss-cn-shanghai",
"DurationSeconds": 7200 "DurationSeconds": 7200
}, },
@ -70,7 +70,7 @@
"OpenUserComplexPassword": true, "OpenUserComplexPassword": true,
"OpenSignDocumentBeforeWork": true, "OpenSignDocumentBeforeWork": true,
"OpenLoginLimit": true, "OpenLoginLimit": false,
"LoginMaxFailCount": 5, "LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30, "LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 120, "AutoLoginOutMinutes": 120,

View File

@ -37,13 +37,13 @@ public class TrialGlobalLimitActionFilter(IFusionCache _fusionCache, IUserInfo _
#region 特殊用户类型拦截 #region 特殊用户类型拦截
// 用户类型检查 // 用户类型检查
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower() != "TrialDocument/userConfirm".ToLower()) //if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower() != "TrialDocument/userConfirm".ToLower())
{ //{
//对不起,您的账户没有操作权限 // //对不起,您的账户没有操作权限
context.Result = new JsonResult(ResponseOutput.NotOk(I18n.T("TrialResource_NoAccessPermission"))); // context.Result = new JsonResult(ResponseOutput.NotOk(I18n.T("TrialResource_NoAccessPermission")));
return; // return;
} //}
#endregion #endregion

View File

@ -47,12 +47,12 @@ public class TrialGlobalLimitEndpointFilter(IFusionCache _fusionCache, IUserInfo
} }
#region 特殊用户类型拦截 #region 特殊用户类型拦截
// 用户类型检查 //// 用户类型检查
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower() != "TrialDocument/userConfirm".ToLower()) //if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower() != "TrialDocument/userConfirm".ToLower())
{ //{
//对不起,您的账户没有操作权限 // //对不起,您的账户没有操作权限
return Results.Json(ResponseOutput.NotOk(I18n.T("TrialResource_NoAccessPermission"))); // return Results.Json(ResponseOutput.NotOk(I18n.T("TrialResource_NoAccessPermission")));
} //}
#endregion #endregion

View File

@ -930,8 +930,8 @@ public static class ExcelExportHelper
int sheetCount = workbook.Worksheets.Count; int sheetCount = workbook.Worksheets.Count;
//if (sheetCount == 2) if (sheetCount == 2)
//{ {
if (inDto.IsEnglish) if (inDto.IsEnglish)
{ {
workbook.Worksheet(1).Delete(); // 删除第一个工作表 workbook.Worksheet(1).Delete(); // 删除第一个工作表
@ -940,7 +940,7 @@ public static class ExcelExportHelper
{ {
workbook.Worksheet(2).Delete(); // 删除第二个工作表 workbook.Worksheet(2).Delete(); // 删除第二个工作表
} }
//} }
#endregion #endregion

View File

@ -9032,36 +9032,6 @@
斑块破裂 斑块破裂
</summary> </summary>
</member> </member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.TemplateData.TargetSegment">
<summary>
靶段
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.TemplateData.TargetSegmentRemarks">
<summary>
靶段备注
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.TemplateData.ROIAllLength">
<summary>
ROI段落总长度
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.TemplateData.PullbackFrameCount">
<summary>
回撤中的图像帧数
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.TemplateData.PlaqueType">
<summary>
斑块类型
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.TemplateData.AdjustReason">
<summary>
访视点备注(如有)
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.OCTFCTUploadData.FrameNumber"> <member name="P:IRaCIS.Core.Application.Service.Reading.Dto.OCTFCTUploadData.FrameNumber">
<summary> <summary>
帧数 帧数
@ -16274,66 +16244,6 @@
访视数据模型 访视数据模型
</summary> </summary>
</member> </member>
<member name="P:IRaCIS.Core.Application.Service.TestService.GenerateIamgeInfo.PatientId">
<summary>
患者ID (0010,0020)
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.TestService.GenerateIamgeInfo.PatientName">
<summary>
患者姓名 (0010,0010)
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.TestService.GenerateIamgeInfo.StudyInstanceUID">
<summary>
研究实例UID (0020,000D)
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.TestService.GenerateIamgeInfo.SeriesInstanceUID">
<summary>
序列实例UID (0020,000E)
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.TestService.GenerateIamgeInfo.SOPInstanceUID">
<summary>
SOP实例UID (0008,0018)
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.TestService.GenerateIamgeInfo.SeriesNumber">
<summary>
序列号 (0020,0011)
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.TestService.GenerateIamgeInfo.InstanceNumber">
<summary>
实例号 (0020,0013)
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.TestService.GenerateIamgeInfo.SeriesDescription">
<summary>
序列描述 (0008,103E)
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.TestService.GenerateIamgeInfo.PixelSpacing">
<summary>
像素间距 (0028,0030)
</summary>
</member>
<member name="M:IRaCIS.Core.Application.Service.TestService.GenerateNoisePixel(FellowOakDicom.DicomDataset,System.String)">
<summary>
生成随机噪声图
</summary>
</member>
<member name="M:IRaCIS.Core.Application.Service.TestService.FillNoiseRectangle(System.UInt16[],System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32)">
<summary>
噪声矩形
</summary>
</member>
<member name="M:IRaCIS.Core.Application.Service.TestService.GenerateAsync(System.String,System.String,System.String,System.Int32,System.Collections.Generic.List{IRaCIS.Core.Application.Service.TestService.GenerateIamgeInfo})">
<summary>
批量生成Series
</summary>
</member>
<member name="M:IRaCIS.Core.Application.Service.TestService.MaskImage"> <member name="M:IRaCIS.Core.Application.Service.TestService.MaskImage">
<summary> <summary>
遮挡影像 遮挡影像

View File

@ -2763,11 +2763,11 @@ namespace IRaCIS.Core.Application.Service.Common
if (criterion.CriterionType == CriterionType.OCT) if (criterion.CriterionType == CriterionType.OCT)
{ {
list.Add(new ExportDocumentDes() { Code = StaticData.Export.OCT_ReadingLession_Export, ExportCatogory = ExportResult.OCT_ReadingLession_Export }); list.Add(new ExportDocumentDes() { Code = StaticData.Export.OCT_ReadingLession_Export, ExportCatogory = ExportResult.OCT_ReadingLession_Export });
//list.Add(new ExportDocumentDes() { Code = StaticData.Export.OCT_CDISC_Export, ExportCatogory = ExportResult.OCT_CDISC_Export }); list.Add(new ExportDocumentDes() { Code = StaticData.Export.OCT_CDISC_Export, ExportCatogory = ExportResult.OCT_CDISC_Export });
} }
if (criterion.CriterionType == CriterionType.IVUS) if (criterion.CriterionType == CriterionType.IVUS)
{ {
//list.Add(new ExportDocumentDes() { Code = StaticData.Export.IVUS_CDISC_Export, ExportCatogory = ExportResult.IVUS_CDISC_Export }); list.Add(new ExportDocumentDes() { Code = StaticData.Export.IVUS_CDISC_Export, ExportCatogory = ExportResult.IVUS_CDISC_Export });
} }
if (criterion.CriterionGroup != CriterionGroup.Tumor /*&& criterion.CriterionType != CriterionType.OCT && criterion.CriterionType != CriterionType.IVUS*/) if (criterion.CriterionGroup != CriterionGroup.Tumor /*&& criterion.CriterionType != CriterionType.OCT && criterion.CriterionType != CriterionType.IVUS*/)
{ {

View File

@ -119,11 +119,11 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
var subjectCode = string.Empty; var subjectCode = string.Empty;
var subjectId = inQuery.SubjectId; var subjectId = inQuery.SubjectId;
bool? isIRImageDownloaded = null; bool? isIRImageDownloaded = true;
if(inQuery.VisitTaskId != null) if(inQuery.VisitTaskId != null)
{ {
isIRImageDownloaded= _visitTaskRepository.Where(t => t.Id == inQuery.VisitTaskId).Select(t => t.IsIRImageDownloaded).FirstOrDefault(); //isIRImageDownloaded= _visitTaskRepository.Where(t => t.Id == inQuery.VisitTaskId).Select(t => t.IsIRImageDownloaded).FirstOrDefault();
} }
if (criterionInfo.IsReadingTaskViewInOrder == ReadingOrder.Random) if (criterionInfo.IsReadingTaskViewInOrder == ReadingOrder.Random)
@ -228,7 +228,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
var query = _visitTaskRepository.Where(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId && t.SourceSubjectVisit.CheckState == CheckStateEnum.CVPassed var query = _visitTaskRepository.Where(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId && t.SourceSubjectVisit.CheckState == CheckStateEnum.CVPassed
&& t.DoctorUserId == _userInfo.UserRoleId && t.TaskState == TaskState.Effect) /* && t.DoctorUserId == _userInfo.UserRoleId*/ && t.TaskState == TaskState.Effect)
//满足 有序或者随机只看到当前任务的dicom 非dicom检查 //满足 有序或者随机只看到当前任务的dicom 非dicom检查
.WhereIf(criterionInfo.IsReadingTaskViewInOrder != ReadingOrder.SubjectRandom && inQuery.VisitTaskId != null, t => t.Id == inQuery.VisitTaskId) .WhereIf(criterionInfo.IsReadingTaskViewInOrder != ReadingOrder.SubjectRandom && inQuery.VisitTaskId != null, t => t.Id == inQuery.VisitTaskId)
.Select(u => new SubjectImageUploadDTO() .Select(u => new SubjectImageUploadDTO()
@ -739,6 +739,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
//找到该序列已经存在的instanceId //找到该序列已经存在的instanceId
var existInstanceIdList = _taskInstanceRepository.Where(t => t.SeriesId == dicomSeries.Id).Select(t => t.Id).ToList(); var existInstanceIdList = _taskInstanceRepository.Where(t => t.SeriesId == dicomSeries.Id).Select(t => t.Id).ToList();
foreach (var instanceItem in seriesItem.InstanceList) foreach (var instanceItem in seriesItem.InstanceList)
{ {
var insntance = _mapper.Map<TaskInstance>(instanceItem); var insntance = _mapper.Map<TaskInstance>(instanceItem);
@ -764,6 +765,14 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
} }
findStudy.InstanceCount++; findStudy.InstanceCount++;
} }
else
{
//更新,需要删除缓存,并更新路径
await _oSSService.DeleteFromPrefix(insntance.Path, true);
await _taskInstanceRepository.BatchUpdateNoTrackingAsync(t => t.Id == instanceId, u => new TaskInstance() { Path = insntance.Path });
}
} }
// 不管是新的序列 还是 该序列 掉了Instance 重传的时候 检查的instance 数量都会增加 // 不管是新的序列 还是 该序列 掉了Instance 重传的时候 检查的instance 数量都会增加
@ -1059,7 +1068,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
else else
{ {
var query = from u in _visitTaskRepository.Where(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId var query = from u in _visitTaskRepository.Where(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId
&& t.SourceSubjectVisit.CheckState == CheckStateEnum.CVPassed && t.DoctorUserId == doctorUserId && t.TaskState == TaskState.Effect) && t.SourceSubjectVisit.CheckState == CheckStateEnum.CVPassed /*&& t.DoctorUserId == doctorUserId*/ && t.TaskState == TaskState.Effect)
//满足 有序或者随机只看到当前任务的dicom 非dicom检查 //满足 有序或者随机只看到当前任务的dicom 非dicom检查
.WhereIf(info.IsReadingTaskViewInOrder != ReadingOrder.SubjectRandom && inQuery.VisitTaskId != null, t => t.Id == inQuery.VisitTaskId) .WhereIf(info.IsReadingTaskViewInOrder != ReadingOrder.SubjectRandom && inQuery.VisitTaskId != null, t => t.Id == inQuery.VisitTaskId)
join ns in _noneDicomStudyReposiotry.Where(t => t.SubjectId == subjectId).WhereIf(info.IsImageFilter, t => ("|" + info.CriterionModalitys + "|").Contains("|" + t.Modality + "|")) join ns in _noneDicomStudyReposiotry.Where(t => t.SubjectId == subjectId).WhereIf(info.IsImageFilter, t => ("|" + info.CriterionModalitys + "|").Contains("|" + t.Modality + "|"))

View File

@ -581,9 +581,9 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
}; };
var addEntity = await _studyMonitorRepository.AddAsync(studyMonitor, true); //var addEntity = await _studyMonitorRepository.AddAsync(studyMonitor, true);
return ResponseOutput.Ok(addEntity.Id); return ResponseOutput.Ok(Guid.NewGuid());
} }
@ -644,20 +644,20 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
{ {
var trialId = incommand.TrialId; var trialId = incommand.TrialId;
var studyMonitor = await _studyMonitorRepository.FirstOrDefaultAsync(t => t.Id == incommand.StudyMonitorId); //var studyMonitor = await _studyMonitorRepository.FirstOrDefaultAsync(t => t.Id == incommand.StudyMonitorId);
studyMonitor.UploadFinishedTime = DateTime.Now; //studyMonitor.UploadFinishedTime = DateTime.Now;
studyMonitor.ArchiveFinishedTime = DateTime.Now; //studyMonitor.ArchiveFinishedTime = DateTime.Now;
studyMonitor.FailedFileCount = incommand.FailedFileCount; //studyMonitor.FailedFileCount = incommand.FailedFileCount;
studyMonitor.IsSuccess = incommand.FailedFileCount == 0; //studyMonitor.IsSuccess = incommand.FailedFileCount == 0;
studyMonitor.RecordPath = incommand.RecordPath; //studyMonitor.RecordPath = incommand.RecordPath;
studyMonitor.FileSize = incommand.Study.SeriesList.SelectMany(t => t.InstanceList).Sum(t => t.FileSize); //studyMonitor.FileSize = incommand.Study.SeriesList.SelectMany(t => t.InstanceList).Sum(t => t.FileSize);
var studyId = IdentifierHelper.CreateGuid(incommand.Study.StudyInstanceUid, incommand.TrialId.ToString()); var studyId = IdentifierHelper.CreateGuid(incommand.Study.StudyInstanceUid, incommand.TrialId.ToString());
var findStudy = await _dicomStudyRepository.FirstOrDefaultAsync(t => t.Id == studyId); var findStudy = await _dicomStudyRepository.FirstOrDefaultAsync(t => t.Id == studyId);
studyMonitor.StudyId = studyId; //studyMonitor.StudyId = studyId;
studyMonitor.StudyCode = findStudy?.StudyCode ?? ""; //studyMonitor.StudyCode = findStudy?.StudyCode ?? "";
studyMonitor.IsDicomReUpload = findStudy != null; //studyMonitor.IsDicomReUpload = findStudy != null;
if (incommand.Study.SeriesList.SelectMany(t => t.InstanceList).Count() == 0) if (incommand.Study.SeriesList.SelectMany(t => t.InstanceList).Count() == 0)
@ -668,7 +668,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
} }
//上传 //上传
if (studyMonitor.IsDicomReUpload == false) if ((findStudy != null) == false)
{ {
var addStudy = _mapper.Map<DicomStudy>(incommand.Study); var addStudy = _mapper.Map<DicomStudy>(incommand.Study);
@ -713,7 +713,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
studyMonitor.StudyCode = addStudy.StudyCode; //studyMonitor.StudyCode = addStudy.StudyCode;
foreach (var seriesItem in incommand.Study.SeriesList) foreach (var seriesItem in incommand.Study.SeriesList)
@ -772,9 +772,14 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
DicomSeries dicomSeries = await _dicomSeriesRepository.FirstOrDefaultAsync(t => t.Id == seriesId); DicomSeries dicomSeries = await _dicomSeriesRepository.FirstOrDefaultAsync(t => t.Id == seriesId);
var isNewSeries = false;
//判断重复 //判断重复
if (dicomSeries == null) if (dicomSeries == null)
{ {
isNewSeries = true;
var series = _mapper.Map<DicomSeries>(seriesItem); var series = _mapper.Map<DicomSeries>(seriesItem);
series.Id = seriesId; series.Id = seriesId;
@ -790,29 +795,53 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
//新的序列 那么 检查的序列数量+1 //新的序列 那么 检查的序列数量+1
findStudy.SeriesCount += 1; findStudy.SeriesCount += 1;
} }
else //else
{ //{
//该序列掉了instance // //该序列掉了instance
dicomSeries.InstanceCount += seriesItem.InstanceList.Count; // dicomSeries.InstanceCount += seriesItem.InstanceList.Count;
} //}
//找到该序列已经存在的instanceId
var existInstanceIdList = _dicomInstanceRepository.Where(t => t.SeriesId == dicomSeries.Id).Select(t => t.Id).ToList();
foreach (var instanceItem in seriesItem.InstanceList) foreach (var instanceItem in seriesItem.InstanceList)
{ {
var insntance = _mapper.Map<DicomInstance>(instanceItem); var insntance = _mapper.Map<DicomInstance>(instanceItem);
insntance.Id = IdentifierHelper.CreateGuid(insntance.StudyInstanceUid, insntance.SeriesInstanceUid, insntance.SopInstanceUid, trialId.ToString()); insntance.Id = IdentifierHelper.CreateGuid(insntance.StudyInstanceUid, insntance.SeriesInstanceUid, insntance.SopInstanceUid, trialId.ToString());
insntance.StudyId = findStudy.Id;
insntance.SeriesId = dicomSeries.Id;
insntance.TrialId = incommand.TrialId; if (!existInstanceIdList.Any(t => t == insntance.Id))
insntance.SubjectId = incommand.SubjectId; {
insntance.SubjectVisitId = incommand.SubjectVisitId; insntance.StudyId = findStudy.Id;
insntance.SeriesId = dicomSeries.Id;
insntance.TrialId = incommand.TrialId;
insntance.SubjectId = incommand.SubjectId;
insntance.SubjectVisitId = incommand.SubjectVisitId;
await _dicomInstanceRepository.AddAsync(insntance);
if (isNewSeries == false)
{
dicomSeries.InstanceCount++;
}
findStudy.InstanceCount++;
}
else
{
//更新,需要删除缓存,并更新路径
await _oSSService.DeleteFromPrefix(insntance.Path,true);
await _dicomInstanceRepository.BatchUpdateNoTrackingAsync(t => t.Id == insntance.Id, u => new DicomInstance() { Path = insntance.Path });
}
await _dicomInstanceRepository.AddAsync(insntance);
} }
// 不管是新的序列 还是 该序列 掉了Instance 重传的时候 检查的instance 数量都会增加 //// 不管是新的序列 还是 该序列 掉了Instance 重传的时候 检查的instance 数量都会增加
findStudy.InstanceCount += seriesItem.InstanceList.Count; //findStudy.InstanceCount += seriesItem.InstanceList.Count;
if (incommand.Study.RadionuclideTotalDose != string.Empty if (incommand.Study.RadionuclideTotalDose != string.Empty

View File

@ -168,6 +168,19 @@ namespace IRaCIS.Core.Application.Service
.Where(t => t.UserTypeId == _userInfo.UserTypeId && (t.Menu.MenuType == "M" || t.Menu.MenuType == "C") && t.Menu.IsEnable) .Where(t => t.UserTypeId == _userInfo.UserTypeId && (t.Menu.MenuType == "M" || t.Menu.MenuType == "C") && t.Menu.IsEnable)
.ProjectTo<MenuTreeNode>(_mapper.ConfigurationProvider).ToListAsync(); .ProjectTo<MenuTreeNode>(_mapper.ConfigurationProvider).ToListAsync();
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA)
{
var otherGuid = new List<Guid>() { Guid.Parse("41d2bcbe-4ae2-4158-856e-08da0661d17d"), Guid.Parse("5acebe02-99de-4e39-f090-08da0c7fe82c") };
var otherlist = await _userTypeMenuRepository
.Where(t => otherGuid.Contains(t.MenuId) && (t.Menu.MenuType == "M" || t.Menu.MenuType == "C") && t.Menu.IsEnable)
.ProjectTo<MenuTreeNode>(_mapper.ConfigurationProvider).Distinct().ToListAsync();
menuFunctionlist.AddRange(otherlist);
}
var list = menuFunctionlist!.ToTree((root, child) => child!.ParentId == Guid.Empty, var list = menuFunctionlist!.ToTree((root, child) => child!.ParentId == Guid.Empty,
(root, child) => child!.ParentId == root!.MenuId, (root, child) => child!.ParentId == root!.MenuId,
(child, datalist) => (child, datalist) =>

View File

@ -250,37 +250,6 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
public string TaskBlindName { get; set; } public string TaskBlindName { get; set; }
public string SubjectID { get; set; } public string SubjectID { get; set; }
/// <summary>
/// 靶段
/// </summary>
public string TargetSegment { get; set; } = string.Empty;
/// <summary>
/// 靶段备注
/// </summary>
public string TargetSegmentRemarks { get; set; } = string.Empty;
/// <summary>
/// ROI段落总长度
/// </summary>
public string ROIAllLength { get; set; } = string.Empty;
/// <summary>
/// 回撤中的图像帧数
/// </summary>
public string PullbackFrameCount { get; set; } = string.Empty;
/// <summary>
/// 斑块类型
/// </summary>
public string PlaqueType { get; set; } = string.Empty;
/// <summary>
/// 访视点备注(如有)
/// </summary>
public string AdjustReason { get; set; } = string.Empty;
} }
public class OCTFCTUploadData public class OCTFCTUploadData

View File

@ -1074,28 +1074,28 @@ namespace IRaCIS.Core.Application.Service
/// <exception cref="BusinessValidationFailedException"></exception> /// <exception cref="BusinessValidationFailedException"></exception>
private async Task VerifyTaskIsSign(Guid visitTaskid) private async Task VerifyTaskIsSign(Guid visitTaskid)
{ {
var taskInfo = await _visitTaskRepository.Where(x => x.Id == visitTaskid).FirstNotNullAsync(); //var taskInfo = await _visitTaskRepository.Where(x => x.Id == visitTaskid).FirstNotNullAsync();
if (await _visitTaskRepository.AnyAsync(x => x.Id == visitTaskid && x.ReadingTaskState == ReadingTaskState.HaveSigned)) //if (await _visitTaskRepository.AnyAsync(x => x.Id == visitTaskid && x.ReadingTaskState == ReadingTaskState.HaveSigned))
{ //{
throw new BusinessValidationFailedException(_localizer["ReadingImage_BeSigned"]); // throw new BusinessValidationFailedException(_localizer["ReadingImage_BeSigned"]);
} //}
if (await _visitTaskRepository.AnyAsync(x => x.Id == visitTaskid && x.TaskState != TaskState.Effect)) //if (await _visitTaskRepository.AnyAsync(x => x.Id == visitTaskid && x.TaskState != TaskState.Effect))
{ //{
throw new BusinessValidationFailedException(_localizer["ReadingImage_Beinvalid"]); // throw new BusinessValidationFailedException(_localizer["ReadingImage_Beinvalid"]);
} //}
if (await _visitTaskRepository.AnyAsync(x => x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId //if (await _visitTaskRepository.AnyAsync(x => x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId
&& x.IsAnalysisCreate && taskInfo.IsAnalysisCreate //&& x.IsAnalysisCreate && taskInfo.IsAnalysisCreate
&& x.SubjectId == taskInfo.SubjectId && x.TaskState == TaskState.Effect && //&& x.SubjectId == taskInfo.SubjectId && x.TaskState == TaskState.Effect &&
((x.ReReadingApplyState == ReReadingApplyState.DocotorHaveApplyed && x.DoctorUserId == taskInfo.DoctorUserId) || x.ReReadingApplyState == ReReadingApplyState.TrialGroupHaveApplyed) //((x.ReReadingApplyState == ReReadingApplyState.DocotorHaveApplyed && x.DoctorUserId == taskInfo.DoctorUserId) || x.ReReadingApplyState == ReReadingApplyState.TrialGroupHaveApplyed)
)) //))
{ //{
throw new BusinessValidationFailedException(_localizer["ReadingImage_PresenceReview"]); // throw new BusinessValidationFailedException(_localizer["ReadingImage_PresenceReview"]);
} //}
} }

View File

@ -1,6 +1,4 @@
using DocumentFormat.OpenXml.Spreadsheet; using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Application.Interfaces;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Infra.EFCore.Common; using IRaCIS.Core.Infra.EFCore.Common;
using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Infrastructure;
@ -8,7 +6,6 @@ using MassTransit;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace IRaCIS.Core.Application.Service.ReadingCalculate namespace IRaCIS.Core.Application.Service.ReadingCalculate
{ {
@ -21,8 +18,6 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
IRepository<ReadingTableAnswerRowInfo> _readingTableAnswerRowInfoRepository, IRepository<ReadingTableAnswerRowInfo> _readingTableAnswerRowInfoRepository,
IRepository<ReadingQuestionTrial> _readingQuestionTrialRepository, IRepository<ReadingQuestionTrial> _readingQuestionTrialRepository,
IRepository<OrganInfo> _organInfoRepository, IRepository<OrganInfo> _organInfoRepository,
ISubjectVisitService iSubjectVisitService,
IRepository<Dictionary> _dictionaryRepository,
IRepository<ReadingGlobalTaskInfo> _readingGlobalTaskInfoRepository, IRepository<ReadingGlobalTaskInfo> _readingGlobalTaskInfoRepository,
IRepository<SubjectVisit> _subjectVisitRepository, IRepository<SubjectVisit> _subjectVisitRepository,
IRepository<TumorAssessment_IRECIST1Point1> _tumorAssessmentRepository, IRepository<TumorAssessment_IRECIST1Point1> _tumorAssessmentRepository,
@ -419,70 +414,10 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Include(x=>x.Subject).FirstNotNullAsync(); var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Include(x=>x.Subject).FirstNotNullAsync();
//靶段
var targetSegmentdic = await _dictionaryRepository.Where(x => x.Parent.Code == "TargetSegment").ToListAsync();
//斑块类型
var plaqueTypedic = await _dictionaryRepository.Where(x => x.Parent.Code == "PlaqueType").ToListAsync();
var awswerList=await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).Include(x=>x.ReadingQuestionTrial).ToListAsync();
var targetSegmentAnswer = awswerList.Where(x => x.ReadingQuestionTrial.QuestionType == QuestionType.TargetSegment).Select(x => x.Answer).FirstOrDefault() ?? string.Empty;
if (targetSegmentAnswer.IsNotNullOrEmpty())
{
var data= JsonConvert.DeserializeObject<List<string>>(targetSegmentAnswer);
targetSegmentAnswer = string.Join(",", targetSegmentdic
.Where(x => data.Contains(x.Code))
.Select(x => x.ValueCN));
}
else
{
var targetSegmentData = await iSubjectVisitService.GetReadingVisitStudyList(new Contracts.GetReadingVisitStudyListIndto()
{
SujectVisitId = taskinfo.SourceSubjectVisitId ?? default(Guid),
TrialId = taskinfo.TrialId,
VisitTaskId = inDto.VisitTaskId
});
targetSegmentAnswer = string.Join(",", targetSegmentData
.Where(x => x.BodyPartForEdit.IsNotNullOrEmpty())
.SelectMany(x => x.BodyPartForEdit.Split('|'))
.Where(s => !string.IsNullOrWhiteSpace(s))
.Distinct());
}
var plaqueTypeAnswer = awswerList.Where(x => x.ReadingQuestionTrial.QuestionType == QuestionType.PlaqueType).Select(x => x.Answer).FirstOrDefault() ?? string.Empty;
if (plaqueTypeAnswer.IsNotNullOrEmpty())
{
var data = JsonConvert.DeserializeObject<List<string>>(plaqueTypeAnswer);
plaqueTypeAnswer = string.Join(",", plaqueTypedic
.Where(x => data.Contains(x.Code))
.Select(x => x.ValueCN));
}
var values = new TemplateData() var values = new TemplateData()
{ {
SubjectID = (taskinfo.BlindSubjectCode.IsNullOrEmpty() ? taskinfo.Subject.Code : taskinfo.BlindSubjectCode), SubjectID = (taskinfo.BlindSubjectCode.IsNullOrEmpty() ? taskinfo.Subject.Code : taskinfo.BlindSubjectCode),
TaskBlindName = taskinfo.TaskBlindName, TaskBlindName = taskinfo.TaskBlindName,
TargetSegment= targetSegmentAnswer,
TargetSegmentRemarks = awswerList.Where(x=>x.ReadingQuestionTrial.QuestionType == QuestionType.TargetSegmentRemarks).Select(x=>x.Answer).FirstOrDefault()??string.Empty,
//ROIAllLength = awswerList.Where(x => x.ReadingQuestionTrial.QuestionType == QuestionType.ROIAllLength).Select(x => x.Answer).FirstOrDefault() ?? string.Empty,
//PullbackFrameCount = awswerList.Where(x => x.ReadingQuestionTrial.QuestionType == QuestionType.PullbackFrameCount).Select(x => x.Answer).FirstOrDefault() ?? string.Empty,
//AdjustReason = awswerList.Where(x => x.ReadingQuestionTrial.QuestionType == QuestionType.AdjustReason).Select(x => x.Answer).FirstOrDefault() ?? string.Empty,
//PlaqueType = plaqueTypeAnswer,
}; };
return await _visitTaskHelpeService.ExportTemplateAsync(new IRaCIS.Application.Contracts.ExportTemplateAsyncDto() return await _visitTaskHelpeService.ExportTemplateAsync(new IRaCIS.Application.Contracts.ExportTemplateAsyncDto()
{ {
@ -507,7 +442,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
List<string> sheetNames = new List<string>() List<string> sheetNames = new List<string>()
{ {
"ROI测量值","ROI 测量值" "各匹配片段测量值","MeasuredValue"
}; };
if (sheetNames.Intersect(uploadInfo.SheetNames).Count() == 0) if (sheetNames.Intersect(uploadInfo.SheetNames).Count() == 0)
@ -575,8 +510,6 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
Dictionary<string, string> isPresent = new Dictionary<string, string>() Dictionary<string, string> isPresent = new Dictionary<string, string>()
{ {
{ "1","1"},
{ "0","0"},
{ "有","1"}, { "有","1"},
{ "无","0"}, { "无","0"},
{ "Existence","1"}, { "Existence","1"},
@ -587,8 +520,6 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
Dictionary<string, string> yesOrNo = new Dictionary<string, string>() Dictionary<string, string> yesOrNo = new Dictionary<string, string>()
{ {
{ "1","1"},
{ "0","0"},
{ "是","1"}, { "是","1"},
{ "否","0"}, { "否","0"},
{ "Yes","1"}, { "Yes","1"},
@ -598,7 +529,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
List<IVUSMeasuredValue> measuredValueList = new List<IVUSMeasuredValue>(); List<IVUSMeasuredValue> measuredValueList = new List<IVUSMeasuredValue>();
var errorRow = new List<int> { }; var errorRow = new List<int> { };
for (int i = 9; i < dataTable.Rows.Count; i++) for (int i = 3; i < dataTable.Rows.Count; i++)
{ {
IVUSMeasuredValue iVUSMeasuredValue = new IVUSMeasuredValue() { }; IVUSMeasuredValue iVUSMeasuredValue = new IVUSMeasuredValue() { };
try try
@ -760,100 +691,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
} }
} }
#region 构造外层问题答案
List<ReadingTaskQuestionAnswer> questionAnswers = new List<ReadingTaskQuestionAnswer>();
var readingQuestionList = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == taskinfo.TrialReadingCriterionId).ToListAsync();
var targetSegmentAnswer = dataTable.Rows[2]["B"].ToString();
if (targetSegmentAnswer.IsNotNullOrEmpty())
{
var targetSegmentValues = targetSegmentAnswer.Replace(" ", "").Replace("", ",").Split(",").ToList();
var targetSegmentdic = await _dictionaryRepository.Where(x => x.Parent.Code == "TargetSegment").ToListAsync();
targetSegmentAnswer = JsonConvert.SerializeObject(targetSegmentdic.Where(x => targetSegmentValues.Contains(x.ValueCN.Replace(" ", ""))).Select(x => x.Code).ToList());
}
questionAnswers.Add(new ReadingTaskQuestionAnswer()
{
Answer= targetSegmentAnswer??string.Empty,
ReadingQuestionCriterionTrialId = taskinfo.TrialReadingCriterionId,
ReadingQuestionTrialId = readingQuestionList.Where(x => x.QuestionType == QuestionType.TargetSegment).Select(x => x.Id).FirstOrDefault(),
TrialId = taskinfo.TrialId,
SubjectId= taskinfo.SubjectId,
VisitTaskId = taskinfo.Id,
});
questionAnswers.Add(new ReadingTaskQuestionAnswer()
{
Answer = dataTable.Rows[3]["B"].ToString()??string.Empty,
ReadingQuestionCriterionTrialId = taskinfo.TrialReadingCriterionId,
ReadingQuestionTrialId = readingQuestionList.Where(x => x.QuestionType == QuestionType.TargetSegmentRemarks).Select(x => x.Id).FirstOrDefault(),
TrialId = taskinfo.TrialId,
SubjectId = taskinfo.SubjectId,
VisitTaskId = taskinfo.Id,
});
questionAnswers.Add(new ReadingTaskQuestionAnswer()
{
Answer = dataTable.Rows[4]["B"].ToString() ?? string.Empty,
ReadingQuestionCriterionTrialId = taskinfo.TrialReadingCriterionId,
ReadingQuestionTrialId = readingQuestionList.Where(x => x.QuestionType == QuestionType.ROIAllLength).Select(x => x.Id).FirstOrDefault(),
TrialId = taskinfo.TrialId,
SubjectId = taskinfo.SubjectId,
VisitTaskId = taskinfo.Id,
});
questionAnswers.Add(new ReadingTaskQuestionAnswer()
{
Answer = dataTable.Rows[5]["B"].ToString() ?? string.Empty,
ReadingQuestionCriterionTrialId = taskinfo.TrialReadingCriterionId,
ReadingQuestionTrialId = readingQuestionList.Where(x => x.QuestionType == QuestionType.PullbackFrameCount).Select(x => x.Id).FirstOrDefault(),
TrialId = taskinfo.TrialId,
SubjectId = taskinfo.SubjectId,
VisitTaskId = taskinfo.Id,
});
var plaqueTypeAnswer = dataTable.Rows[6]["B"].ToString();
if (plaqueTypeAnswer.IsNotNullOrEmpty())
{
var plaqueTypeAnswerValues = plaqueTypeAnswer.Replace(" ", "").Replace("", ",").Split(",").ToList();
var plaqueTypeAnswerdic = await _dictionaryRepository.Where(x => x.Parent.Code == "PlaqueType").ToListAsync();
plaqueTypeAnswer = JsonConvert.SerializeObject(plaqueTypeAnswerdic
.Where(x => plaqueTypeAnswerValues.Any(val => x.ValueCN.Replace(" ", "").Contains(val)))
.Select(x => x.Code)
.ToList());
}
questionAnswers.Add(new ReadingTaskQuestionAnswer()
{
Answer = plaqueTypeAnswer ?? string.Empty,
ReadingQuestionCriterionTrialId = taskinfo.TrialReadingCriterionId,
ReadingQuestionTrialId = readingQuestionList.Where(x => x.QuestionType == QuestionType.PlaqueType).Select(x => x.Id).FirstOrDefault(),
TrialId = taskinfo.TrialId,
SubjectId = taskinfo.SubjectId,
VisitTaskId = taskinfo.Id,
});
questionAnswers.Add(new ReadingTaskQuestionAnswer()
{
Answer = dataTable.Rows[7]["B"].ToString() ?? string.Empty,
ReadingQuestionCriterionTrialId = taskinfo.TrialReadingCriterionId,
ReadingQuestionTrialId = readingQuestionList.Where(x => x.QuestionType == QuestionType.AdjustReason).Select(x => x.Id).FirstOrDefault(),
TrialId = taskinfo.TrialId,
SubjectId = taskinfo.SubjectId,
VisitTaskId = taskinfo.Id,
});
var questionids = questionAnswers.Select(x => x.ReadingQuestionTrialId).ToList();
await _readingTaskQuestionAnswerRepository.DeleteFromQueryAsync(x => x.VisitTaskId == taskinfo.Id && questionids.Contains(x.ReadingQuestionTrialId));
await _readingTableQuestionAnswerRepository.SaveChangesAsync();
await _readingTaskQuestionAnswerRepository.AddRangeAsync(questionAnswers);
await _readingTaskQuestionAnswerRepository.SaveChangesAsync();
#endregion
await _readingTableAnswerRowInfoRepository.DeleteFromQueryAsync(x => x.QuestionId == questionInfo.Id && x.VisitTaskId == taskinfo.Id); await _readingTableAnswerRowInfoRepository.DeleteFromQueryAsync(x => x.QuestionId == questionInfo.Id && x.VisitTaskId == taskinfo.Id);
await _readingTableQuestionAnswerRepository.DeleteFromQueryAsync(x => x.QuestionId == questionInfo.Id && x.VisitTaskId == taskinfo.Id); await _readingTableQuestionAnswerRepository.DeleteFromQueryAsync(x => x.QuestionId == questionInfo.Id && x.VisitTaskId == taskinfo.Id);
await _readingTableQuestionAnswerRepository.SaveChangesAsync(); await _readingTableQuestionAnswerRepository.SaveChangesAsync();

View File

@ -2,7 +2,6 @@
using DocumentFormat.OpenXml.Drawing.Spreadsheet; using DocumentFormat.OpenXml.Drawing.Spreadsheet;
using DocumentFormat.OpenXml.Office.SpreadSheetML.Y2023.MsForms; using DocumentFormat.OpenXml.Office.SpreadSheetML.Y2023.MsForms;
using DocumentFormat.OpenXml.Office2010.Excel; using DocumentFormat.OpenXml.Office2010.Excel;
using IRaCIS.Core.Application.Interfaces;
using IRaCIS.Core.Application.Service.Reading.Dto; using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Models;
@ -13,7 +12,6 @@ using MassTransit;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace IRaCIS.Core.Application.Service.ReadingCalculate namespace IRaCIS.Core.Application.Service.ReadingCalculate
{ {
@ -26,8 +24,6 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
IRepository<ReadingTableAnswerRowInfo> _readingTableAnswerRowInfoRepository, IRepository<ReadingTableAnswerRowInfo> _readingTableAnswerRowInfoRepository,
IRepository<ReadingQuestionTrial> _readingQuestionTrialRepository, IRepository<ReadingQuestionTrial> _readingQuestionTrialRepository,
IRepository<OrganInfo> _organInfoRepository, IRepository<OrganInfo> _organInfoRepository,
ISubjectVisitService iSubjectVisitService,
IRepository<Dictionary> _dictionaryRepository,
IHttpContextAccessor httpContext, IHttpContextAccessor httpContext,
IRepository<ReadingGlobalTaskInfo> _readingGlobalTaskInfoRepository, IRepository<ReadingGlobalTaskInfo> _readingGlobalTaskInfoRepository,
IRepository<SubjectVisit> _subjectVisitRepository, IRepository<SubjectVisit> _subjectVisitRepository,
@ -275,68 +271,10 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
public async Task<FileResult> GetOCTFCTTemplate(GetExportTemplateInDto inDto) public async Task<FileResult> GetOCTFCTTemplate(GetExportTemplateInDto inDto)
{ {
var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Include(x => x.Subject).FirstNotNullAsync(); var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Include(x => x.Subject).FirstNotNullAsync();
//靶段
var targetSegmentdic = await _dictionaryRepository.Where(x => x.Parent.Code == "TargetSegment").ToListAsync();
//斑块类型
var plaqueTypedic = await _dictionaryRepository.Where(x => x.Parent.Code == "PlaqueType").ToListAsync();
var awswerList = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).Include(x => x.ReadingQuestionTrial).ToListAsync();
var targetSegmentAnswer = awswerList.Where(x => x.ReadingQuestionTrial.QuestionType == QuestionType.TargetSegment).Select(x => x.Answer).FirstOrDefault() ?? string.Empty;
if (targetSegmentAnswer.IsNotNullOrEmpty())
{
var data = JsonConvert.DeserializeObject<List<string>>(targetSegmentAnswer);
targetSegmentAnswer = string.Join(",", targetSegmentdic
.Where(x => data.Contains(x.Code))
.Select(x => x.ValueCN));
}
else
{
var targetSegmentData = await iSubjectVisitService.GetReadingVisitStudyList(new Contracts.GetReadingVisitStudyListIndto()
{
SujectVisitId = taskinfo.SourceSubjectVisitId ?? default(Guid),
TrialId = taskinfo.TrialId,
VisitTaskId = inDto.VisitTaskId
});
targetSegmentAnswer = string.Join(",", targetSegmentData
.Where(x => x.BodyPartForEdit.IsNotNullOrEmpty())
.SelectMany(x => x.BodyPartForEdit.Split('|'))
.Where(s => !string.IsNullOrWhiteSpace(s))
.Distinct());
}
var plaqueTypeAnswer = awswerList.Where(x => x.ReadingQuestionTrial.QuestionType == QuestionType.PlaqueType).Select(x => x.Answer).FirstOrDefault() ?? string.Empty;
if (plaqueTypeAnswer.IsNotNullOrEmpty())
{
var data = JsonConvert.DeserializeObject<List<string>>(plaqueTypeAnswer);
plaqueTypeAnswer = string.Join(",", plaqueTypedic
.Where(x => data.Contains(x.Code))
.Select(x => x.ValueCN));
}
var values = new TemplateData() var values = new TemplateData()
{ {
SubjectID = (taskinfo.BlindSubjectCode.IsNullOrEmpty() ? taskinfo.Subject.Code : taskinfo.BlindSubjectCode), SubjectID = (taskinfo.BlindSubjectCode.IsNullOrEmpty() ? taskinfo.Subject.Code : taskinfo.BlindSubjectCode),
TaskBlindName = taskinfo.TaskBlindName, TaskBlindName = taskinfo.TaskBlindName,
TargetSegment = targetSegmentAnswer,
TargetSegmentRemarks = awswerList.Where(x => x.ReadingQuestionTrial.QuestionType == QuestionType.TargetSegmentRemarks).Select(x => x.Answer).FirstOrDefault() ?? string.Empty,
//ROIAllLength = awswerList.Where(x => x.ReadingQuestionTrial.QuestionType == QuestionType.ROIAllLength).Select(x => x.Answer).FirstOrDefault() ?? string.Empty,
////PullbackFrameCount = awswerList.Where(x => x.ReadingQuestionTrial.QuestionType == QuestionType.PullbackFrameCount).Select(x => x.Answer).FirstOrDefault() ?? string.Empty,
//PlaqueType = plaqueTypeAnswer,
//AdjustReason = awswerList.Where(x => x.ReadingQuestionTrial.QuestionType == QuestionType.AdjustReason).Select(x => x.Answer).FirstOrDefault() ?? string.Empty,
}; };
return await _visitTaskHelpeService.ExportTemplateAsync(new IRaCIS.Application.Contracts.ExportTemplateAsyncDto() return await _visitTaskHelpeService.ExportTemplateAsync(new IRaCIS.Application.Contracts.ExportTemplateAsyncDto()
{ {
@ -361,7 +299,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
List<string> sheetNames = new List<string>() List<string> sheetNames = new List<string>()
{ {
"ROI测量值","ROI 测量值" "FCT导入","FCT"
}; };
if (sheetNames.Intersect(uploadInfo.SheetNames).Count() == 0) if (sheetNames.Intersect(uploadInfo.SheetNames).Count() == 0)
@ -400,8 +338,6 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
Dictionary<string, string> yesOrNo = new Dictionary<string, string>() Dictionary<string, string> yesOrNo = new Dictionary<string, string>()
{ {
{ "1","1"},
{ "0","0"},
{ "是","1"}, { "是","1"},
{ "否","0"}, { "否","0"},
{ "Yes","1"}, { "Yes","1"},
@ -420,12 +356,11 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
return value; return value;
} }
} }
for (int i = 8; i < dataTable.Rows.Count; i++) for (int i = 3; i < dataTable.Rows.Count; i++)
{ {
try try
{ {
// 手动抛出异常进入catch // 手动抛出异常进入catch
if (!yesOrNo.ContainsKey(dataTable.Rows[i]["K"].ToString())|| !yesOrNo.ContainsKey(dataTable.Rows[i]["L"].ToString())) if (!yesOrNo.ContainsKey(dataTable.Rows[i]["K"].ToString())|| !yesOrNo.ContainsKey(dataTable.Rows[i]["L"].ToString()))
{ {
@ -469,8 +404,6 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
Dictionary<string, string> isPresent = new Dictionary<string, string>() Dictionary<string, string> isPresent = new Dictionary<string, string>()
{ {
{ "1","1"},
{ "0","0"},
{ "有","1"}, { "有","1"},
{ "无","0"}, { "无","0"},
{ "Existence","1"}, { "Existence","1"},
@ -478,7 +411,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
{ string.Empty,string.Empty}, { string.Empty,string.Empty},
}; };
int row = 8; int row = 3;
foreach (var item in measuredValueList) foreach (var item in measuredValueList)
{ {
row++; row++;
@ -731,91 +664,6 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
} }
} }
#region 构造外层问题答案
List<ReadingTaskQuestionAnswer> questionAnswers = new List<ReadingTaskQuestionAnswer>();
var readingQuestionList = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == taskinfo.TrialReadingCriterionId).ToListAsync();
var targetSegmentAnswer = dataTable.Rows[2]["B"].ToString();
if (targetSegmentAnswer.IsNotNullOrEmpty())
{
var targetSegmentValues = targetSegmentAnswer.Replace(" ", "").Replace("", ",").Split(",").ToList();
var targetSegmentdic = await _dictionaryRepository.Where(x => x.Parent.Code == "TargetSegment").ToListAsync();
targetSegmentAnswer = JsonConvert.SerializeObject(targetSegmentdic.Where(x => targetSegmentValues.Contains(x.ValueCN.Replace(" ", ""))).Select(x => x.Code).ToList());
}
questionAnswers.Add(new ReadingTaskQuestionAnswer()
{
Answer = targetSegmentAnswer ?? string.Empty,
ReadingQuestionCriterionTrialId = taskinfo.TrialReadingCriterionId,
ReadingQuestionTrialId = readingQuestionList.Where(x => x.QuestionType == QuestionType.TargetSegment).Select(x => x.Id).FirstOrDefault(),
TrialId = taskinfo.TrialId,
SubjectId = taskinfo.SubjectId,
VisitTaskId = taskinfo.Id,
});
questionAnswers.Add(new ReadingTaskQuestionAnswer()
{
Answer = dataTable.Rows[3]["B"].ToString() ?? string.Empty,
ReadingQuestionCriterionTrialId = taskinfo.TrialReadingCriterionId,
ReadingQuestionTrialId = readingQuestionList.Where(x => x.QuestionType == QuestionType.TargetSegmentRemarks).Select(x => x.Id).FirstOrDefault(),
TrialId = taskinfo.TrialId,
SubjectId = taskinfo.SubjectId,
VisitTaskId = taskinfo.Id,
});
questionAnswers.Add(new ReadingTaskQuestionAnswer()
{
Answer = dataTable.Rows[4]["B"].ToString() ?? string.Empty,
ReadingQuestionCriterionTrialId = taskinfo.TrialReadingCriterionId,
ReadingQuestionTrialId = readingQuestionList.Where(x => x.QuestionType == QuestionType.ROIAllLength).Select(x => x.Id).FirstOrDefault(),
TrialId = taskinfo.TrialId,
SubjectId = taskinfo.SubjectId,
VisitTaskId = taskinfo.Id,
});
var plaqueTypeAnswer = dataTable.Rows[5]["B"].ToString();
if (plaqueTypeAnswer.IsNotNullOrEmpty())
{
var plaqueTypeAnswerValues = plaqueTypeAnswer.Replace(" ", "").Replace("", ",").Split(",").ToList();
var plaqueTypeAnswerdic = await _dictionaryRepository.Where(x => x.Parent.Code == "PlaqueType").ToListAsync();
plaqueTypeAnswer = JsonConvert.SerializeObject(plaqueTypeAnswerdic
.Where(x => plaqueTypeAnswerValues.Any(val => x.ValueCN.Replace(" ", "").Contains(val)))
.Select(x => x.Code)
.ToList());
}
questionAnswers.Add(new ReadingTaskQuestionAnswer()
{
Answer = plaqueTypeAnswer ?? string.Empty,
ReadingQuestionCriterionTrialId = taskinfo.TrialReadingCriterionId,
ReadingQuestionTrialId = readingQuestionList.Where(x => x.QuestionType == QuestionType.PlaqueType).Select(x => x.Id).FirstOrDefault(),
TrialId = taskinfo.TrialId,
SubjectId = taskinfo.SubjectId,
VisitTaskId = taskinfo.Id,
});
questionAnswers.Add(new ReadingTaskQuestionAnswer()
{
Answer = dataTable.Rows[6]["B"].ToString() ?? string.Empty,
ReadingQuestionCriterionTrialId = taskinfo.TrialReadingCriterionId,
ReadingQuestionTrialId = readingQuestionList.Where(x => x.QuestionType == QuestionType.AdjustReason).Select(x => x.Id).FirstOrDefault(),
TrialId = taskinfo.TrialId,
SubjectId = taskinfo.SubjectId,
VisitTaskId = taskinfo.Id,
});
var questionids = questionAnswers.Select(x => x.ReadingQuestionTrialId).ToList();
await _readingTaskQuestionAnswerRepository.DeleteFromQueryAsync(x => x.VisitTaskId == taskinfo.Id && questionids.Contains(x.ReadingQuestionTrialId));
await _readingTableQuestionAnswerRepository.SaveChangesAsync();
await _readingTaskQuestionAnswerRepository.AddRangeAsync(questionAnswers);
await _readingTaskQuestionAnswerRepository.SaveChangesAsync();
#endregion
await _readingTableAnswerRowInfoRepository.DeleteFromQueryAsync(x => x.QuestionId == questionInfo.Id && x.VisitTaskId == taskinfo.Id); await _readingTableAnswerRowInfoRepository.DeleteFromQueryAsync(x => x.QuestionId == questionInfo.Id && x.VisitTaskId == taskinfo.Id);
await _readingTableQuestionAnswerRepository.DeleteFromQueryAsync(x => x.QuestionId == questionInfo.Id && x.VisitTaskId == taskinfo.Id); await _readingTableQuestionAnswerRepository.DeleteFromQueryAsync(x => x.QuestionId == questionInfo.Id && x.VisitTaskId == taskinfo.Id);
await _readingTableQuestionAnswerRepository.SaveChangesAsync(); await _readingTableQuestionAnswerRepository.SaveChangesAsync();

View File

@ -56,12 +56,6 @@ namespace IRaCIS.Core.Application.Contracts
var item = addOrEditTrialSiteUserSurvey; var item = addOrEditTrialSiteUserSurvey;
if (item.UserTypeId == null)
{
throw new BusinessValidationFailedException(_localizer["SystemCommon_WebErrorArgument"]);
}
//找下系统中是否存在该用户类型的 并且邮箱 或者手机的账户 //找下系统中是否存在该用户类型的 并且邮箱 或者手机的账户
var sysUserInfo = await _identityUserRepository.Where(t => t.EMail == item.Email,true).Include(t => t.UserRoleList).FirstOrDefaultAsync(); var sysUserInfo = await _identityUserRepository.Where(t => t.EMail == item.Email,true).Include(t => t.UserRoleList).FirstOrDefaultAsync();

View File

@ -2,7 +2,6 @@
using ClosedXML.Excel; using ClosedXML.Excel;
using FellowOakDicom; using FellowOakDicom;
using FellowOakDicom.Imaging; using FellowOakDicom.Imaging;
using FellowOakDicom.IO.Buffer;
using IRaCIS.Application.Contracts; using IRaCIS.Application.Contracts;
using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.Helper;
@ -58,9 +57,6 @@ namespace IRaCIS.Core.Application.Service
{ {
public static int IntValue = 100; public static int IntValue = 100;
private readonly Random random = new();
static string ReplaceText(string text, Dictionary<string, string> replaceRules) static string ReplaceText(string text, Dictionary<string, string> replaceRules)
{ {
foreach (var rule in replaceRules) foreach (var rule in replaceRules)
@ -435,439 +431,6 @@ namespace IRaCIS.Core.Application.Service
} }
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>
/// 遮挡影像 /// 遮挡影像
/// </summary> /// </summary>
@ -2165,10 +1728,10 @@ namespace IRaCIS.Core.Application.Service
//var d = _dicRepository.UpdateFromDTOAsync(new AddOrEditBasicDic() { Id = Guid.Parse("60d86683-c33b-4349-b672-08da1e91b622"), ParentId = null, ChildGroup = null, Code = null }, true, true).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; //var a = 123;
//throw new BusinessValidationFailedException(_localizer["TrialIsDoubleCheck{0}", "测试"]); throw new BusinessValidationFailedException(_localizer["TrialIsDoubleCheck{0}", "测试"]);
//var b = _localizer["test{0}", "测试"]; var b = _localizer["test{0}", "测试"];
//return _localizer["test{0}", "测试"]; return _localizer["test{0}", "测试"];
//var list = _subjectVisitRepository.Where(t => t.Id == Guid.NewGuid()).SelectMany(t => t.VisitTaskList).ToList(); //var list = _subjectVisitRepository.Where(t => t.Id == Guid.NewGuid()).SelectMany(t => t.VisitTaskList).ToList();
@ -2178,8 +1741,6 @@ namespace IRaCIS.Core.Application.Service
//var list3 = _visitTaskRepository.Where(t => t.Id == Guid.NewGuid()).SelectMany(t => t.SourceSubjectVisit.VisitTaskList).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(); //var list2 = _subjectRepository.Where(t => t.Id == Guid.NewGuid()).SelectMany(t => t.SubjectVisitTaskList).ToList();
//return _userInfo.LocalIp; //return _userInfo.LocalIp;
return _userInfo.ClientInfo;
} }

View File

@ -3060,11 +3060,6 @@ namespace IRaCIS.Core.Domain.Share
/// </summary> /// </summary>
ROIAllLength = 1015, ROIAllLength = 1015,
/// <summary>
/// 斑块类型
/// </summary>
PlaqueType=1018,
/// <summary> /// <summary>
/// PAV冠状动脉粥样硬化体积百分比) /// PAV冠状动脉粥样硬化体积百分比)
/// </summary> /// </summary>

View File

@ -63,17 +63,5 @@ namespace IRaCIS.Core.Domain.Share
string BrowserFingerprint { get; } string BrowserFingerprint { get; }
UserWorkLanguage UserWorkLanguage { get; } UserWorkLanguage UserWorkLanguage { get; }
ClientInfo ClientInfo { get; }
} }
public class ClientInfo
{
public string Browser { get; set; }
public string OS { get; set; }
public string DeviceType { get; set; }
}
} }

View File

@ -1,15 +1,19 @@
using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Models;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using UAParser;
namespace IRaCIS.Core.Domain.Share namespace IRaCIS.Core.Domain.Share
{ {
/// <summary> /// <summary>
/// 用户信息 /// 用户信息
/// </summary> /// </summary>
public class UserInfo(IHttpContextAccessor _accessor, Parser parser) : IUserInfo public class UserInfo : IUserInfo
{ {
private readonly IHttpContextAccessor _accessor;
public UserInfo(IHttpContextAccessor accessor)
{
_accessor = accessor;
}
/// <summary> /// <summary>
/// 用户角色Id /// 用户角色Id
@ -344,55 +348,6 @@ namespace IRaCIS.Core.Domain.Share
} }
public ClientInfo ClientInfo
{
get
{
try
{
var userAgent = _accessor?.HttpContext.Request.Headers["User-Agent"].ToString();
if (!string.IsNullOrEmpty(userAgent))
{
var clientInfo = parser.Parse(userAgent);
return new ClientInfo()
{
OS = clientInfo.OS.ToString(),
Browser = clientInfo.UA.ToString(),
DeviceType = userAgent.Contains("Mobile") ? "Mobile" : "Desktop"
};
}
else
{
return new ClientInfo()
{
OS = "Unknown",
Browser = "Unknown",
DeviceType = "Unknown"
};
}
}
catch (Exception ex)
{
return new ClientInfo()
{
OS = "ParseError",
Browser = "ParseError",
DeviceType = "ParseError"
};
}
}
}
public Guid? SignId public Guid? SignId
{ {
@ -462,7 +417,7 @@ namespace IRaCIS.Core.Domain.Share
public const string PermissionStr = "permissionStr"; public const string PermissionStr = "permissionStr";
public const string UserWorkLanguage = "userWorkLanguage"; public const string UserWorkLanguage = "userWorkLanguage";
} }

View File

@ -15,7 +15,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="UAParser" Version="3.1.47" />
<PackageReference Include="EFCore.BulkExtensions" Version="10.0.1" /> <PackageReference Include="EFCore.BulkExtensions" Version="10.0.1" />
<PackageReference Include="EntityFrameworkCore.Triggered" Version="3.2.2" /> <PackageReference Include="EntityFrameworkCore.Triggered" Version="3.2.2" />
<PackageReference Include="EntityFrameworkCore.Projectables" Version="6.0.5" /> <PackageReference Include="EntityFrameworkCore.Projectables" Version="6.0.5" />

View File

@ -48,7 +48,7 @@ public class AuditEntityInterceptor(IUserInfo _userInfo,
AuditEntities(eventData.Context); AuditEntities(eventData.Context);
//IRC稽查 放在savechange 之前 不影响之前的逻辑 //IRC稽查 放在savechange 之前 不影响之前的逻辑
IRCDataInspection(eventData.Context); //IRCDataInspection(eventData.Context);
//return result; //return result;
@ -64,7 +64,7 @@ public class AuditEntityInterceptor(IUserInfo _userInfo,
AuditEntities(eventData.Context); AuditEntities(eventData.Context);
//IRC稽查 放在savechange 之前 不影响之前的逻辑 //IRC稽查 放在savechange 之前 不影响之前的逻辑
IRCDataInspection(eventData.Context); //IRCDataInspection(eventData.Context);
//return result; //return result;