Compare commits
31 Commits
irc-add-im
...
Test_IRC_N
| Author | SHA1 | Date |
|---|---|---|
|
|
21136f1238 | |
|
|
540de91485 | |
|
|
ff72c4aefc | |
|
|
f94d1caa79 | |
|
|
621fab16a0 | |
|
|
581ee62a5b | |
|
|
8d9a824ac3 | |
|
|
4357185ac7 | |
|
|
10793c6a93 | |
|
|
37100008eb | |
|
|
adc9b2635a | |
|
|
ffb8894608 | |
|
|
62421988c4 | |
|
|
96650ced2d | |
|
|
cdcd3154b4 | |
|
|
ef7f0ebc4a | |
|
|
c5eaf847cc | |
|
|
739f610d4e | |
|
|
5c8ccdf434 | |
|
|
e0b80b3316 | |
|
|
d4bbe47b81 | |
|
|
dc16cc2018 | |
|
|
2f930ddca3 | |
|
|
e346593ebb | |
|
|
fab6c8c55a | |
|
|
282e56e5fc | |
|
|
a600f11422 | |
|
|
2db4a293ed | |
|
|
8641a11b53 | |
|
|
980248d899 | |
|
|
372ee55241 |
|
|
@ -4,30 +4,16 @@ 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);
|
||||||
|
|
@ -95,6 +81,8 @@ 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();
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ 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
|
||||||
{
|
{
|
||||||
|
|
@ -17,11 +18,14 @@ 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} {RequestBody} responded {StatusCode} in {Elapsed:0.0000} ms";
|
opts.MessageTemplate = "{FullName} {UserType} {UserIp} {Host} {RequestMethod} {RequestPath}{QueryString} {RequestBody} {OS} {Browser} {DeviceType} responded {StatusCode} in {Elapsed:0.0000} ms";
|
||||||
|
|
||||||
opts.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
|
opts.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
|
||||||
{
|
{
|
||||||
|
|
@ -33,10 +37,9 @@ 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);
|
||||||
|
|
||||||
|
|
@ -52,6 +55,38 @@ 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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3284,6 +3284,20 @@
|
||||||
批次Id
|
批次Id
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="M:IRaCIS.Core.Application.Service.Inspection.InspectionService.getInspectionById(IRaCIS.Core.Application.Service.Inspection.DTO.InspectionDto)">
|
||||||
|
<summary>
|
||||||
|
根据Id获取稽查记录
|
||||||
|
</summary>
|
||||||
|
<param name="inDto"></param>
|
||||||
|
<returns></returns>
|
||||||
|
</member>
|
||||||
|
<member name="M:IRaCIS.Core.Application.Service.Inspection.InspectionService.SetJsonDetail(IRaCIS.Core.Application.Service.Inspection.DTO.InspectionDto)">
|
||||||
|
<summary>
|
||||||
|
设置稽查记录JsonDetail
|
||||||
|
</summary>
|
||||||
|
<param name="inDto"></param>
|
||||||
|
<returns></returns>
|
||||||
|
</member>
|
||||||
<member name="M:IRaCIS.Core.Application.Service.Inspection.InspectionService.SetTrialShowInspection(IRaCIS.Core.Application.Service.Inspection.DTO.SetTrialShowInspection)">
|
<member name="M:IRaCIS.Core.Application.Service.Inspection.InspectionService.SetTrialShowInspection(IRaCIS.Core.Application.Service.Inspection.DTO.SetTrialShowInspection)">
|
||||||
<summary>
|
<summary>
|
||||||
设置项目稽查配置
|
设置项目稽查配置
|
||||||
|
|
@ -9018,6 +9032,36 @@
|
||||||
斑块破裂
|
斑块破裂
|
||||||
</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>
|
||||||
帧数
|
帧数
|
||||||
|
|
@ -10218,6 +10262,11 @@
|
||||||
问题分类
|
问题分类
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.GetFilterTableQuestionInDto.QuestionClassify">
|
||||||
|
<summary>
|
||||||
|
问题分类
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.SetOncologyQuestion.EvaluationResult">
|
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.SetOncologyQuestion.EvaluationResult">
|
||||||
<summary>
|
<summary>
|
||||||
评估结果
|
评估结果
|
||||||
|
|
@ -15001,6 +15050,13 @@
|
||||||
<param name="inDto"></param>
|
<param name="inDto"></param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.GetFilterTableQuestion(IRaCIS.Core.Application.Service.Reading.Dto.GetFilterTableQuestionInDto)">
|
||||||
|
<summary>
|
||||||
|
获取单个表格问题及答案 过滤问题
|
||||||
|
</summary>
|
||||||
|
<param name="inDto"></param>
|
||||||
|
<returns></returns>
|
||||||
|
</member>
|
||||||
<member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.GetCustomTableQuestionAnswer(IRaCIS.Core.Application.Service.Reading.Dto.GetCustomTableQuestionAnswerInDto)">
|
<member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.GetCustomTableQuestionAnswer(IRaCIS.Core.Application.Service.Reading.Dto.GetCustomTableQuestionAnswerInDto)">
|
||||||
<summary>
|
<summary>
|
||||||
获取自定义问题以及答案
|
获取自定义问题以及答案
|
||||||
|
|
@ -16218,6 +16274,66 @@
|
||||||
访视数据模型
|
访视数据模型
|
||||||
</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>
|
||||||
遮挡影像
|
遮挡影像
|
||||||
|
|
|
||||||
|
|
@ -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*/)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -708,9 +708,12 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
||||||
|
|
||||||
TaskSeries dicomSeries = await _taskSeriesRepository.FirstOrDefaultAsync(t => t.Id == seriesId);
|
TaskSeries dicomSeries = await _taskSeriesRepository.FirstOrDefaultAsync(t => t.Id == seriesId);
|
||||||
|
|
||||||
|
var isNewSeries = false;
|
||||||
//判断重复
|
//判断重复
|
||||||
if (dicomSeries == null)
|
if (dicomSeries == null)
|
||||||
{
|
{
|
||||||
|
isNewSeries = true;
|
||||||
|
|
||||||
var series = _mapper.Map<TaskSeries>(seriesItem);
|
var series = _mapper.Map<TaskSeries>(seriesItem);
|
||||||
|
|
||||||
series.Id = seriesId;
|
series.Id = seriesId;
|
||||||
|
|
@ -755,7 +758,10 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
||||||
|
|
||||||
await _taskInstanceRepository.AddAsync(insntance);
|
await _taskInstanceRepository.AddAsync(insntance);
|
||||||
|
|
||||||
|
if (isNewSeries == false)
|
||||||
|
{
|
||||||
dicomSeries.InstanceCount++;
|
dicomSeries.InstanceCount++;
|
||||||
|
}
|
||||||
findStudy.InstanceCount++;
|
findStudy.InstanceCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -449,6 +449,12 @@ namespace IRaCIS.Core.Application.Service.Inspection.DTO
|
||||||
public List<GetTrialShowInspectionOutDto> Children { get; set; }
|
public List<GetTrialShowInspectionOutDto> Children { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class InspectionDto
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
|
public string? JsonDetail { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class SetTrialShowInspection
|
public class SetTrialShowInspection
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,39 @@ namespace IRaCIS.Core.Application.Service.Inspection
|
||||||
IRepository<FrontAuditConfig> _frontAuditConfigRepository, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, IInspectionService
|
IRepository<FrontAuditConfig> _frontAuditConfigRepository, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, IInspectionService
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据Id获取稽查记录
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<IResponseOutput> getInspectionById(InspectionDto inDto)
|
||||||
|
{
|
||||||
|
var dataInspection = await _dataInspectionRepository.Where(x=>x.Id==inDto.Id).Select(x=> new InspectionDto()
|
||||||
|
{
|
||||||
|
Id=x.Id,
|
||||||
|
JsonDetail = x.JsonDetail,
|
||||||
|
|
||||||
|
}).FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
return ResponseOutput.Ok(dataInspection);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置稽查记录JsonDetail
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<IResponseOutput> SetJsonDetail(InspectionDto inDto)
|
||||||
|
{
|
||||||
|
await _dataInspectionRepository.BatchUpdateNoTrackingAsync(x => x.Id == inDto.Id, u => new DataInspection() { JsonDetail = inDto.JsonDetail });
|
||||||
|
|
||||||
|
return ResponseOutput.Ok(inDto);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置项目稽查配置
|
/// 设置项目稽查配置
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -250,6 +250,37 @@ 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
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
using IRaCIS.Core.Application.Service.Reading.Dto;
|
using DocumentFormat.OpenXml.Spreadsheet;
|
||||||
|
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;
|
||||||
|
|
@ -6,6 +8,7 @@ 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
|
||||||
{
|
{
|
||||||
|
|
@ -18,6 +21,8 @@ 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,
|
||||||
|
|
@ -414,10 +419,70 @@ 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()
|
||||||
{
|
{
|
||||||
|
|
@ -442,7 +507,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
|
||||||
|
|
||||||
List<string> sheetNames = new List<string>()
|
List<string> sheetNames = new List<string>()
|
||||||
{
|
{
|
||||||
"各匹配片段测量值","MeasuredValue"
|
"ROI测量值","ROI 测量值"
|
||||||
};
|
};
|
||||||
|
|
||||||
if (sheetNames.Intersect(uploadInfo.SheetNames).Count() == 0)
|
if (sheetNames.Intersect(uploadInfo.SheetNames).Count() == 0)
|
||||||
|
|
@ -510,6 +575,8 @@ 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"},
|
||||||
|
|
@ -520,6 +587,8 @@ 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"},
|
||||||
|
|
@ -529,7 +598,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 = 3; i < dataTable.Rows.Count; i++)
|
for (int i = 9; i < dataTable.Rows.Count; i++)
|
||||||
{
|
{
|
||||||
IVUSMeasuredValue iVUSMeasuredValue = new IVUSMeasuredValue() { };
|
IVUSMeasuredValue iVUSMeasuredValue = new IVUSMeasuredValue() { };
|
||||||
try
|
try
|
||||||
|
|
@ -691,7 +760,100 @@ 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();
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
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;
|
||||||
|
|
@ -12,6 +13,7 @@ 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
|
||||||
{
|
{
|
||||||
|
|
@ -24,6 +26,8 @@ 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,
|
||||||
|
|
@ -271,10 +275,68 @@ 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()
|
||||||
{
|
{
|
||||||
|
|
@ -299,7 +361,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
|
||||||
|
|
||||||
List<string> sheetNames = new List<string>()
|
List<string> sheetNames = new List<string>()
|
||||||
{
|
{
|
||||||
"FCT导入","FCT"
|
"ROI测量值","ROI 测量值"
|
||||||
};
|
};
|
||||||
|
|
||||||
if (sheetNames.Intersect(uploadInfo.SheetNames).Count() == 0)
|
if (sheetNames.Intersect(uploadInfo.SheetNames).Count() == 0)
|
||||||
|
|
@ -338,6 +400,8 @@ 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"},
|
||||||
|
|
@ -356,11 +420,12 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 3; i < dataTable.Rows.Count; i++)
|
for (int i = 8; 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()))
|
||||||
{
|
{
|
||||||
|
|
@ -404,6 +469,8 @@ 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"},
|
||||||
|
|
@ -411,7 +478,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
|
||||||
{ string.Empty,string.Empty},
|
{ string.Empty,string.Empty},
|
||||||
};
|
};
|
||||||
|
|
||||||
int row = 3;
|
int row = 8;
|
||||||
foreach (var item in measuredValueList)
|
foreach (var item in measuredValueList)
|
||||||
{
|
{
|
||||||
row++;
|
row++;
|
||||||
|
|
@ -664,6 +731,91 @@ 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();
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,12 @@ 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();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
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;
|
||||||
|
|
@ -57,6 +58,9 @@ 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)
|
||||||
|
|
@ -431,6 +435,439 @@ 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>
|
||||||
|
|
@ -1728,10 +2165,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();
|
||||||
|
|
@ -1741,6 +2178,8 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3060,6 +3060,11 @@ namespace IRaCIS.Core.Domain.Share
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ROIAllLength = 1015,
|
ROIAllLength = 1015,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 斑块类型
|
||||||
|
/// </summary>
|
||||||
|
PlaqueType=1018,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// PAV(冠状动脉粥样硬化体积百分比)
|
/// PAV(冠状动脉粥样硬化体积百分比)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -63,5 +63,17 @@ 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; }
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,15 @@
|
||||||
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 : IUserInfo
|
public class UserInfo(IHttpContextAccessor _accessor, Parser parser) : IUserInfo
|
||||||
{
|
{
|
||||||
private readonly IHttpContextAccessor _accessor;
|
|
||||||
|
|
||||||
public UserInfo(IHttpContextAccessor accessor)
|
|
||||||
{
|
|
||||||
_accessor = accessor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 用户角色Id
|
/// 用户角色Id
|
||||||
|
|
@ -348,6 +344,55 @@ 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
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
</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" />
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue