Compare commits

..

46 Commits

Author SHA1 Message Date
hang 3850be9ab8 调研增加参数修改
continuous-integration/drone/push Build was killed Details
2026-08-11 17:36:51 +08:00
hang b757d71fef Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running Details
2026-08-11 17:21:35 +08:00
hang 3cf60f3e9e 中心调研接口改为分页 2026-08-11 17:21:34 +08:00
he 602cfe43d0 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running Details
2026-08-11 17:20:13 +08:00
he bdef193304 添加表和字段 2026-08-11 17:20:10 +08:00
hang 8e85078232 中心调研bug修改 2026-08-11 14:51:10 +08:00
hang 56af80a006 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running Details
2026-08-11 14:38:05 +08:00
hang 95f3cbb79f SPM 是否参与流程 2026-08-11 14:38:04 +08:00
he 9ee7dc78f5 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10 2026-08-11 14:31:53 +08:00
he 9421dda784 复制病灶修改1 2026-08-11 14:31:49 +08:00
hang e24c1dc0cf 增加中心调研日志
continuous-integration/drone/push Build is passing Details
2026-08-11 14:18:58 +08:00
he c32b1131c9 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is pending Details
2026-08-10 16:04:59 +08:00
he bcb3ace564 异常修改 返回-5 2026-08-10 16:04:56 +08:00
hang 36c1f9e790 修改更新web配置接口
continuous-integration/drone/push Build is running Details
2026-08-10 15:27:37 +08:00
hang cf45582a40 增加前端配置获取以及更新接口
continuous-integration/drone/push Build is passing Details
2026-08-10 13:40:29 +08:00
hang 21136f1238 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running Details
2026-08-07 14:56:37 +08:00
hang 540de91485 生成测试图像代码提交 2026-08-07 14:56:35 +08:00
he ff72c4aefc sheet页问题修改
continuous-integration/drone/push Build is running Details
2026-08-06 15:01:26 +08:00
he f94d1caa79 导入忽略空格 2026-08-06 15:01:15 +08:00
he 621fab16a0 匹配去掉空格 2026-08-06 15:01:10 +08:00
he 581ee62a5b Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is passing Details
2026-08-06 09:19:30 +08:00
he 8d9a824ac3 提示修改 2026-08-06 09:19:21 +08:00
he 4357185ac7 导入1和0 兼容 2 2026-08-06 09:19:19 +08:00
he 10793c6a93 导入1和0 兼容 2026-08-06 09:19:17 +08:00
he 37100008eb 导出靶段备注 2026-08-06 09:19:15 +08:00
he adc9b2635a 导出模版只导出靶段 2026-08-06 09:19:12 +08:00
he ffb8894608 导出修改 2026-08-06 09:19:04 +08:00
hang 62421988c4 增加日志详细信息:get请求参数,请求 OS Browser 信息
continuous-integration/drone/push Build is passing Details
2026-08-05 14:13:42 +08:00
hang 96650ced2d Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running Details
2026-08-04 15:08:15 +08:00
hang cdcd3154b4 中心调研这里增加额外的验证 2026-08-04 15:08:13 +08:00
he ef7f0ebc4a 重新发布
continuous-integration/drone/push Build is running Details
2026-08-04 14:32:19 +08:00
he c5eaf847cc 修改行数 2026-08-04 14:27:46 +08:00
he 739f610d4e 字典修改
continuous-integration/drone/push Build is passing Details
2026-08-04 14:15:13 +08:00
he 5c8ccdf434 导入修改
continuous-integration/drone/push Build is running Details
2026-08-04 14:10:22 +08:00
he e0b80b3316 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running Details
2026-08-04 13:32:54 +08:00
he d4bbe47b81 导出修改 2026-08-04 13:32:51 +08:00
hang dc16cc2018 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running Details
2026-08-04 11:38:57 +08:00
hang 2f930ddca3 ivus隐藏导表 2026-08-04 11:38:55 +08:00
he e346593ebb Revert "拷贝病灶"
continuous-integration/drone/push Build is running Details
This reverts commit 282e56e5fc.
2026-08-03 16:47:31 +08:00
he fab6c8c55a Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running Details
2026-08-03 16:43:50 +08:00
he 282e56e5fc 拷贝病灶 2026-08-03 16:43:46 +08:00
hang a600f11422 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10 2026-07-30 17:52:53 +08:00
hang 2db4a293ed 修复后处理增加数量bug 2026-07-30 17:52:44 +08:00
he 8641a11b53 查询修改
continuous-integration/drone/push Build is passing Details
2026-07-30 17:39:10 +08:00
he 980248d899 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is passing Details
2026-07-30 15:59:14 +08:00
he 372ee55241 稽查修改 2026-07-30 15:59:11 +08:00
45 changed files with 47104 additions and 191 deletions

View File

@ -43,7 +43,7 @@ namespace IRaCIS.Core.SCP.Filter
else else
{ {
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (context.Exception.InnerException is null ? (context.Exception.Message /*+ context.Exception.StackTrace*/) context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (context.Exception.InnerException is null ? (context.Exception.Message /*+ context.Exception.StackTrace*/)
: (context.Exception.InnerException?.Message /*+ context.Exception.InnerException?.StackTrace*/)), ApiResponseCodeEnum.ProgramException)); : (context.Exception.InnerException?.Message /*+ context.Exception.InnerException?.StackTrace*/)), ApiResponseCodeEnum.BackEndAnomaly));
} }

View File

@ -43,7 +43,7 @@ namespace IRaCIS.Core.SCP.Filter
else else
{ {
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (context.Exception.InnerException is null ? (context.Exception.Message /*+ context.Exception.StackTrace*/) context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (context.Exception.InnerException is null ? (context.Exception.Message /*+ context.Exception.StackTrace*/)
: (context.Exception.InnerException?.Message /*+ context.Exception.InnerException?.StackTrace*/)), ApiResponseCodeEnum.ProgramException)); : (context.Exception.InnerException?.Message /*+ context.Exception.InnerException?.StackTrace*/)), ApiResponseCodeEnum.BackEndAnomaly));
} }

View File

@ -89,7 +89,6 @@ 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,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();

View File

@ -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);

View File

@ -7,7 +7,7 @@
} }
}, },
"ConnectionStrings": { "ConnectionStrings": {
"RemoteNew": "Server=101.132.193.237,1433;Database=Prod_IRC_pidr_restore;User ID=sa;Password=xc@123456;TrustServerCertificate=true", "RemoteNew": "Server=101.132.193.237,1433;Database=Prod_IRC_pidr_restore_new;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": "LTAI5tFUCCmz5TwghZHsj45Y", "AccessKeyId": "LTAI5tNRTsqL6aWmHkDmTwoH",
"AccessKeySecret": "8evrBy1fVfzJG25i67Jm0xqn9Xcw2T", "AccessKeySecret": "7mtGz3qrYWI6JMMBZiLeC119VWicZH",
"RoleArn": "acs:ram::1078130221702011:role/uat-oss-access", "RoleArn": "acs:ram::1899121822495495:role/irc-oss-access",
"BucketName": "tl-med-irc-event-store", "BucketName": "zy-irc-store",
"ViewEndpoint": "https://tl-med-rc-event-cache.oss-cn-shanghai.aliyuncs.com", "ViewEndpoint": "https://zy-irc-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": false, "OpenLoginLimit": true,
"LoginMaxFailCount": 5, "LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30, "LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 120, "AutoLoginOutMinutes": 120,

View File

@ -127,5 +127,6 @@
"DuplicationWindowMs": 500, "DuplicationWindowMs": 500,
"CacheTimeSeconds": 5, "CacheTimeSeconds": 5,
"ExcludedPaths": [] "ExcludedPaths": []
} },
"FrontWebConfig": "222"
} }

View File

@ -75,7 +75,7 @@ public class ModelActionFilter(IStringLocalizer _localizer, IConfiguration _conf
//---提供给接口的参数无效。 //---提供给接口的参数无效。
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ModelAction_InvalidAPIParameter"] + JsonConvert.SerializeObject(validationErrors))); context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ModelAction_InvalidAPIParameter"] + JsonConvert.SerializeObject(validationErrors), ApiResponseCodeEnum.BackEndAnomaly));
} }
} }
} }

View File

@ -49,7 +49,7 @@ public class ProjectExceptionFilter(ILogger<ProjectExceptionFilter> _logger, ISt
else else
{ {
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (exception.InnerException is null ? (exception.Message) context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (exception.InnerException is null ? (exception.Message)
: (exception.Message + "Inner ExceptionMsg:" + exception.InnerException?.Message)), ApiResponseCodeEnum.ProgramException)); : (exception.Message + "Inner ExceptionMsg:" + exception.InnerException?.Message)), ApiResponseCodeEnum.BackEndAnomaly));
try try
{ {

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

@ -58,7 +58,7 @@ public class GlobalExceptionHandler(IStringLocalizer _localizer, ILogger<GlobalE
else else
{ {
httpContext.Response.WriteAsJsonAsync(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (exception.InnerException is null ? (exception.Message ) httpContext.Response.WriteAsJsonAsync(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (exception.InnerException is null ? (exception.Message )
: (exception.InnerException?.Message)), ApiResponseCodeEnum.ProgramException)); : (exception.InnerException?.Message)), ApiResponseCodeEnum.BackEndAnomaly));
} }

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

@ -579,6 +579,12 @@
<param name="emailConfig"></param> <param name="emailConfig"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.Common.DeployConfigService.GetWebConfigInfo">
<summary>
获取前端配置
</summary>
<returns></returns>
</member>
<member name="P:IRaCIS.Core.Application.Service.Common.TU_TR_RSBaseModel.ResearchProgramNo"> <member name="P:IRaCIS.Core.Application.Service.Common.TU_TR_RSBaseModel.ResearchProgramNo">
<summary> <summary>
方案编号 STUDYID 方案编号 STUDYID
@ -3974,6 +3980,16 @@
<param name="visitTaskId"></param> <param name="visitTaskId"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.GeneralCalculateService.IsSameCustomRowAnswer(IRaCIS.Core.Domain.Models.ReadingTableAnswerRowInfo,IRaCIS.Core.Domain.Models.ReadingTableAnswerRowInfo,System.Collections.Generic.List{IRaCIS.Core.Domain.Models.ReadingTableQuestionAnswer},System.Collections.Generic.List{IRaCIS.Core.Domain.Models.ReadingTableQuestionAnswer})">
<summary>
自定义病灶判断是否是同一个病灶 除了根据器官判断还需要根据复制前值的答案是否相等
</summary>
<param name="currentRow"></param>
<param name="historyRow"></param>
<param name="currentAnswerList"></param>
<param name="historyAnswerList"></param>
<returns></returns>
</member>
<member name="F:IRaCIS.Core.Application.Service.ReadingCalculate.ReadingCalculateService.CalculateServiceDic"> <member name="F:IRaCIS.Core.Application.Service.ReadingCalculate.ReadingCalculateService.CalculateServiceDic">
<summary> <summary>
标准和服务对应 标准和服务对应
@ -9032,6 +9048,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>
帧数 帧数
@ -14788,6 +14834,13 @@
IR影像阅片 IR影像阅片
</summary> </summary>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.Test(IRaCIS.Core.Application.Service.Reading.Dto.GetReportsChartSummaryInDto)">
<summary>
测试异常
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.GetReportsChartData(IRaCIS.Core.Application.Service.Reading.Dto.GetReportsChartDataInDto)"> <member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.GetReportsChartData(IRaCIS.Core.Application.Service.Reading.Dto.GetReportsChartDataInDto)">
<summary> <summary>
获取报告图表数据 获取报告图表数据
@ -16244,6 +16297,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>
遮挡影像 遮挡影像
@ -17584,17 +17697,17 @@
</member> </member>
<member name="F:IRaCIS.Core.Application.ViewModel.AccessToDialogueEnum.Question"> <member name="F:IRaCIS.Core.Application.ViewModel.AccessToDialogueEnum.Question">
<summary> <summary>
质疑 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
</summary> </summary>
</member> </member>
<member name="F:IRaCIS.Core.Application.ViewModel.AccessToDialogueEnum.Consistency"> <member name="F:IRaCIS.Core.Application.ViewModel.AccessToDialogueEnum.Consistency">
<summary> <summary>
一致性核查 һ<EFBFBD><EFBFBD><EFBFBD>Ժ˲<EFBFBD>
</summary> </summary>
</member> </member>
<member name="T:IRaCIS.Core.Application.ViewModel.CopyFrontAuditConfigItemDto"> <member name="T:IRaCIS.Core.Application.ViewModel.CopyFrontAuditConfigItemDto">
<summary> <summary>
复制 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
</summary> </summary>
</member> </member>
<member name="T:IRaCIS.Core.Application.ViewModel.SystemNoticeView"> <member name="T:IRaCIS.Core.Application.ViewModel.SystemNoticeView">
@ -19340,7 +19453,7 @@
TrialSiteSurveyService TrialSiteSurveyService
</summary> </summary>
</member> </member>
<member name="M:IRaCIS.Core.Application.Contracts.TrialSiteSurveyService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialSiteSurvey},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialSiteUserSurvey},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.IdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialIdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialSite},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Doctor},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VerificationCode},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialSiteUserRole},Medallion.Threading.IDistributedLockProvider,IRaCIS.Core.Application.Auth.ITokenService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserType},IRaCIS.Core.Application.Service.IMailVerificationService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserLog},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)"> <member name="M:IRaCIS.Core.Application.Contracts.TrialSiteSurveyService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialSiteSurvey},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SiteSurveyLog},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialSiteEquipmentSurvey},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialSiteUserSurvey},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.IdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialIdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialSite},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Doctor},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VerificationCode},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialSiteUserRole},Medallion.Threading.IDistributedLockProvider,IRaCIS.Core.Application.Auth.ITokenService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserType},IRaCIS.Core.Application.Service.IMailVerificationService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserLog},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<summary> <summary>
TrialSiteSurveyService TrialSiteSurveyService
</summary> </summary>
@ -19461,6 +19574,34 @@
<param name="siteSurvyeSubmit"></param> <param name="siteSurvyeSubmit"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Contracts.TrialSiteSurveyService.GetSiteSurveyLogList(IRaCIS.Core.Application.Contracts.SiteSurveyLogQuery)">
<summary>
获取中心调研日志
</summary>
<param name="inQuery"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Contracts.TrialSiteSurveyService.GetSiteSurveyEquipmentList(IRaCIS.Core.Application.Contracts.SiteSurveyEquipmentQuery)">
<summary>
获取中心设备信息
</summary>
<param name="inQuery"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Contracts.TrialSiteSurveyService.GetSiteSurveyInfoList(IRaCIS.Core.Application.Contracts.SiteSurveyInfoQuery)">
<summary>
调研表基本信息
</summary>
<param name="inQuery"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Contracts.TrialSiteSurveyService.GetTrialIsSPMJoin(System.Guid)">
<summary>
SPM 是否参与流程
</summary>
<param name="trialId"></param>
<returns></returns>
</member>
<member name="T:IRaCIS.Core.Application.Contracts.TrialSiteUserSurveyService"> <member name="T:IRaCIS.Core.Application.Contracts.TrialSiteUserSurveyService">
<summary> <summary>
TrialSiteUserSurveyService TrialSiteUserSurveyService

View File

@ -31,7 +31,7 @@ public class DeployConfigService(IMapper _mapper, IConfiguration _configuration,
//return config; //return config;
var path = Path.Combine( _hostEnvironment.ContentRootPath,$"appsettings.{_hostEnvironment.EnvironmentName}.json"); var path = Path.Combine(_hostEnvironment.ContentRootPath, $"appsettings.{_hostEnvironment.EnvironmentName}.json");
var json = File.ReadAllText(path); var json = File.ReadAllText(path);
@ -123,7 +123,7 @@ public class DeployConfigService(IMapper _mapper, IConfiguration _configuration,
[HttpPost] [HttpPost]
public async Task<IResponseOutput> UpdateSystemEmailConfig(SystemEmailSendConfig emailConfig) public async Task<IResponseOutput> UpdateSystemEmailConfig(SystemEmailSendConfig emailConfig)
{ {
var path = Path.Combine(_hostEnvironment.ContentRootPath,$"appsettings.{_hostEnvironment.EnvironmentName}.json"); var path = Path.Combine(_hostEnvironment.ContentRootPath, $"appsettings.{_hostEnvironment.EnvironmentName}.json");
//var path = $"appsettings.{_hostEnvironment.EnvironmentName}.json"; //var path = $"appsettings.{_hostEnvironment.EnvironmentName}.json";
var @lock = _distributedLockProvider.CreateLock("WriteConfigFile"); var @lock = _distributedLockProvider.CreateLock("WriteConfigFile");
@ -171,4 +171,57 @@ public class DeployConfigService(IMapper _mapper, IConfiguration _configuration,
return ResponseOutput.Ok(); return ResponseOutput.Ok();
} }
/// <summary>
/// 获取前端配置
/// </summary>
/// <returns></returns>
[AllowAnonymous]
public async Task<string> GetWebConfigInfo()
{
var path = Path.Combine(_hostEnvironment.ContentRootPath, $"appsettings.{_hostEnvironment.EnvironmentName}.json");
var json = File.ReadAllText(path);
var obj = JObject.Parse(json);
return obj["FrontWebConfig"]!.ToString();
}
public class WebConfigCommand
{
public string ConfigStr { get; set; }
}
public async Task<IResponseOutput> UpdateWebConfigInfo(WebConfigCommand incommand)
{
var path = Path.Combine(_hostEnvironment.ContentRootPath, $"appsettings.{_hostEnvironment.EnvironmentName}.json");
//var path = $"appsettings.{_hostEnvironment.EnvironmentName}.json";
var @lock = _distributedLockProvider.CreateLock("WriteConfigFile");
using (await @lock.AcquireAsync())
{
string text = System.IO.File.ReadAllText(path);
// 修改
JObject obj = JObject.Parse(text);
// SystemEmailSendConfig 相关配置
obj["FrontWebConfig"] = incommand.ConfigStr;
// 重新写入appsettings.json
string result = obj.ToString();
System.IO.File.WriteAllText(path, result);
}
return ResponseOutput.Ok();
}
} }

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 = true; bool? isIRImageDownloaded = null;
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,7 +739,6 @@ 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);
@ -765,14 +764,6 @@ 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 数量都会增加
@ -1068,7 +1059,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(Guid.NewGuid()); return ResponseOutput.Ok(addEntity.Id);
} }
@ -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 ((findStudy != null) == false) if (studyMonitor.IsDicomReUpload == 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,14 +772,9 @@ 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;
@ -795,53 +790,29 @@ 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;
if (!existInstanceIdList.Any(t => t == insntance.Id)) insntance.TrialId = incommand.TrialId;
{ insntance.SubjectId = incommand.SubjectId;
insntance.StudyId = findStudy.Id; insntance.SubjectVisitId = incommand.SubjectVisitId;
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,19 +168,6 @@ 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,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

View File

@ -81,6 +81,20 @@ namespace IRaCIS.Core.Application.Service
{ {
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue; private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
/// <summary>
/// 测试异常
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<IResponseOutput> Test(GetReportsChartSummaryInDto inDto)
{
var a = 0;
var v = 1 / a;
return ResponseOutput.Ok();
}
/// <summary> /// <summary>
/// 获取报告图表数据 /// 获取报告图表数据
/// </summary> /// </summary>
@ -1074,28 +1088,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

@ -258,7 +258,8 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
if (historyTaskId != Guid.Empty) if (historyTaskId != Guid.Empty)
{ {
var historyTableRowList = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == historyTaskId).ToListAsync(); var criterionType = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == taskinfo.TrialReadingCriterionId).Select(x => x.CriterionType).FirstOrDefaultAsync();
var historyTableRowList = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == historyTaskId).Include(x => x.ReadingQuestionTrial).ToListAsync();
var historyTableAnswerList = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == historyTaskId).ToListAsync(); var historyTableAnswerList = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == historyTaskId).ToListAsync();
@ -278,7 +279,11 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
{ {
continue; continue;
} }
var historyRow = historyTableRowList.Where(x =>
// 自定义标准(SelfDefine)的病灶IdentityRowId不可靠 除了根据器官判断还需要根据复制前值的答案是否相等 优先用答案匹配
var historyRow = historyTableRowList
.WhereIf(criterionType == CriterionType.SelfDefine, x => IsSameCustomRowAnswer(item, x, tableAnswerList, historyTableAnswerList))
.Where(x =>
x.QuestionId == item.QuestionId && x.QuestionId == item.QuestionId &&
x.RowIndex == item.RowIndex && x.RowIndex == item.RowIndex &&
x.IdentityRowId == item.IdentityRowId && x.IdentityRowId == item.IdentityRowId &&
@ -311,6 +316,77 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
} }
} }
// 将失效任务在当前访视新增的病灶添加过来
// 例如现在是访视三,把失效任务访视三中在访视三新增的病灶(FristAddTaskId == historyTaskId)添加过来
var historyAddRowList = historyTableRowList.Where(x => x.FristAddTaskId == historyTaskId && x.SplitOrMergeType != SplitOrMergeType.Merged).ToList();
var historyRowIdSet = historyTableRowList.Select(x => x.Id).ToHashSet();
foreach (var historyRow in historyAddRowList)
{
// 判断当前任务是否已经存在该病灶 失效任务新增的病灶IdentityRowId是新建的不会与当前任务重复
bool isExist = tableRowList.Any(x => x.QuestionId == historyRow.QuestionId && x.IdentityRowId != null && x.IdentityRowId == historyRow.IdentityRowId);
if (isExist)
{
continue;
}
// 通过CopyTableAnswerRowInfo映射复制行字段
var copyRow = _mapper.Map<CopyTableAnswerRowInfo>(historyRow);
copyRow.Id = NewId.NextGuid();
copyRow.VisitTaskId = taskinfo.Id;
copyRow.MeasureData = historyRow.MeasureData.Replace(historyTaskId.ToString(), taskinfo.Id.ToString());
copyRow.IsCurrentTaskAdd = true;
copyRow.FristAddTaskId = taskinfo.Id;
var newRow = _mapper.Map<ReadingTableAnswerRowInfo>(copyRow);
// CopyTableAnswerRowInfo没有Other和PET/CT融合字段 单独复制
newRow.OtherMeasureData = historyRow.OtherMeasureData.Replace(historyTaskId.ToString(), taskinfo.Id.ToString());
newRow.OtherInstanceId = historyRow.OtherInstanceId;
newRow.OtherSeriesId = historyRow.OtherSeriesId;
newRow.OtherStudyId = historyRow.OtherStudyId;
newRow.OtherMarkTool = historyRow.OtherMarkTool;
newRow.OtherPicturePath = historyRow.OtherPicturePath;
newRow.OtherNumberOfFrames = historyRow.OtherNumberOfFrames;
newRow.PTSeriesId = historyRow.PTSeriesId;
newRow.CTSeriesId = historyRow.CTSeriesId;
tableRowList.Add(newRow);
if (!lesionRelationship.ContainsKey(historyRow.Id))
{
lesionRelationship.Add(historyRow.Id, newRow.Id);
}
// 复制该病灶的表格答案
historyTableAnswerList.Where(x => x.RowId == historyRow.Id).ForEach(x =>
{
tableAnswerList.Add(new ReadingTableQuestionAnswer()
{
Id = NewId.NextGuid(),
Answer = x.Answer,
QuestionId = x.QuestionId,
VisitTaskId = taskinfo.Id,
TrialId = x.TrialId,
RowIndex = x.RowIndex,
TableQuestionId = x.TableQuestionId,
RowId = newRow.Id,
});
});
}
// 处理新增病灶的分割合并关系 新增病灶已经在tableRowList里 通过SplitRowId/MergeRowId是否指向失效任务的行来识别
tableRowList.ForEach(x =>
{
if (x.SplitRowId != null && historyRowIdSet.Contains(x.SplitRowId.Value))
{
x.SplitRowId = lesionRelationship.ContainsKey(x.SplitRowId.Value) ? lesionRelationship[x.SplitRowId.Value] : (Guid?)null;
}
if (x.MergeRowId != null && historyRowIdSet.Contains(x.MergeRowId.Value))
{
x.MergeRowId = lesionRelationship.ContainsKey(x.MergeRowId.Value) ? lesionRelationship[x.MergeRowId.Value] : (Guid?)null;
}
});
// 复制外层问题 // 复制外层问题
answerList.ForEach(x => answerList.ForEach(x =>
{ {
@ -920,5 +996,31 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
}); });
return taskInfoList; return taskInfoList;
} }
/// <summary>
/// 自定义病灶判断是否是同一个病灶 除了根据器官判断还需要根据复制前值的答案是否相等
/// </summary>
/// <param name="currentRow"></param>
/// <param name="historyRow"></param>
/// <param name="currentAnswerList"></param>
/// <param name="historyAnswerList"></param>
/// <returns></returns>
private bool IsSameCustomRowAnswer(ReadingTableAnswerRowInfo currentRow, ReadingTableAnswerRowInfo historyRow,
List<ReadingTableQuestionAnswer> currentAnswerList, List<ReadingTableQuestionAnswer> historyAnswerList)
{
// 复制前值的答案即当前任务从上一次有效访视复制过来的答案自定义阅片只有IsCopy的问题会复制值非空的就是复制前值
var currentAnswers = currentAnswerList.Where(x => x.RowId == currentRow.Id && !x.Answer.IsNullOrEmpty())
.GroupBy(x => x.TableQuestionId).ToDictionary(x => x.Key, x => x.First().Answer);
var historyAnswers = historyAnswerList.Where(x => x.RowId == historyRow.Id && !x.Answer.IsNullOrEmpty())
.GroupBy(x => x.TableQuestionId).ToDictionary(x => x.Key, x => x.First().Answer);
// 没有复制前值可以比较时 只根据器官判断
if (currentAnswers.Count == 0)
{
return true;
}
return currentAnswers.All(x => historyAnswers.TryGetValue(x.Key, out var historyAnswer) && historyAnswer == x.Value);
}
} }
} }

View File

@ -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();

View File

@ -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();

View File

@ -131,7 +131,7 @@ namespace IRaCIS.Core.Application.Contracts
/// <summary> TrialSiteSurveyView 列表视图模型 </summary> /// <summary> TrialSiteSurveyView 列表视图模型 </summary>
public class TrialSiteSurveyView: TrialSiteSurveyAddOrEdit public class TrialSiteSurveyView : TrialSiteSurveyAddOrEdit
{ {
public string TrialSiteCode { get; set; } = String.Empty; public string TrialSiteCode { get; set; } = String.Empty;
@ -450,6 +450,70 @@ namespace IRaCIS.Core.Application.Contracts
} }
public class SiteSurveyLogQuery
{
[NotDefault]
public Guid TrialSiteSurveyId { get; set; }
}
public class SiteSurveyLogDTO
{
public Guid TrialSiteSurveyId { get; set; }
public string Name { get; set; }
public UserTypeEnum UserType { get; set; }
public SiteSurveyOptTyp OptType { get; set; }
public string Reason { get; set; }
[MaxLength]
public string Json { get; set; }
[Comment("更新调研表之前的调研表")]
public Guid? OriginTrialSiteSurveyId { get; set; }
public string CreateTime { get; set; }
}
public class SiteSurveyEquipmentDto : TrialSiteEquipmentSurveyView
{
public string TrialSiteCode { get; set; }
public string TrialSiteName { get; set; } = String.Empty;
public string TrialSiteAliasName { get; set; } = String.Empty;
}
public class SiteSurveyEquipmentQuery : PageInput
{
[NotDefault]
public Guid TrialId { get; set; }
public Guid? TrialSiteId { get; set; }
public string? TrialSiteCode { get; set; }
public string? TrialSiteName { get; set; }
}
public class SiteSurveyInfoQuery : PageInput
{
[NotDefault]
public Guid TrialId { get; set; }
public Guid? TrialSiteId { get; set; }
public string? TrialSiteCode { get; set; }
public string? TrialSiteName { get; set; }
}
public class SiteSurveyInfoDto
{
}
} }

View File

@ -3,6 +3,7 @@
// 生成时间 2021-12-23 13:20:59 // 生成时间 2021-12-23 13:20:59
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 // 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
//-------------------------------------------------------------------- //--------------------------------------------------------------------
using DocumentFormat.OpenXml.Spreadsheet;
using IRaCIS.Application.Contracts; using IRaCIS.Application.Contracts;
using IRaCIS.Core.Application.Auth; using IRaCIS.Core.Application.Auth;
using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.Helper;
@ -22,6 +23,8 @@ namespace IRaCIS.Core.Application.Contracts
/// </summary> /// </summary>
[ApiExplorerSettings(GroupName = "Trial")] [ApiExplorerSettings(GroupName = "Trial")]
public class TrialSiteSurveyService(IRepository<TrialSiteSurvey> _trialSiteSurveyRepository, public class TrialSiteSurveyService(IRepository<TrialSiteSurvey> _trialSiteSurveyRepository,
IRepository<SiteSurveyLog> _siteSurveyLogRepository,
IRepository<TrialSiteEquipmentSurvey> _trialSiteEquipmentSurveyRepository,
IRepository<TrialSiteUserSurvey> _trialSiteUserSurveyRepository, IRepository<TrialSiteUserSurvey> _trialSiteUserSurveyRepository,
IRepository<UserRole> _userRoleRepository, IRepository<UserRole> _userRoleRepository,
IRepository<IdentityUser> _identityUserRepository, IRepository<IdentityUser> _identityUserRepository,
@ -474,6 +477,7 @@ namespace IRaCIS.Core.Application.Contracts
public async Task<IResponseOutput> SubmissionRejection(TrialSiteSubmitBackCommand trialSiteSubmitBackCommand, [FromServices] IMailVerificationService _IMailVerificationService) public async Task<IResponseOutput> SubmissionRejection(TrialSiteSubmitBackCommand trialSiteSubmitBackCommand, [FromServices] IMailVerificationService _IMailVerificationService)
{ {
var trialId = trialSiteSubmitBackCommand.TrialId;
var trialSiteSurveyId = trialSiteSubmitBackCommand.TrialSiteSurveyId; var trialSiteSurveyId = trialSiteSubmitBackCommand.TrialSiteSurveyId;
var survey = await _trialSiteSurveyRepository.FirstOrDefaultAsync(t => t.Id == trialSiteSurveyId); var survey = await _trialSiteSurveyRepository.FirstOrDefaultAsync(t => t.Id == trialSiteSurveyId);
@ -520,6 +524,10 @@ namespace IRaCIS.Core.Application.Contracts
} }
var info = await GetSiteSurveyInfo(trialSiteSurveyId, trialId);
await _siteSurveyLogRepository.AddAsync(new SiteSurveyLog() { TrialSiteSurveyId = trialSiteSurveyId, Name = _userInfo.FullName, UserType = (UserTypeEnum)_userInfo.UserTypeEnumInt, OptType = SiteSurveyOptTyp.Reject, Reason = survey.LatestBackReason, Json = info.ToJsonStr() });
} }
await _trialSiteSurveyRepository.SaveChangesAsync(); await _trialSiteSurveyRepository.SaveChangesAsync();
@ -612,6 +620,9 @@ namespace IRaCIS.Core.Application.Contracts
//从项目site 中找到已存在的 加到历史人员中 //从项目site 中找到已存在的 加到历史人员中
addSurvey.TrialSiteUserSurveyList = userList; addSurvey.TrialSiteUserSurveyList = userList;
//添加创建日志
addSurvey.SiteSurveyLogList.Add(new SiteSurveyLog() { Name = userInfo.EmailOrPhone, OptType = SiteSurveyOptTyp.Create });
currentEntity = await _trialSiteSurveyRepository.AddAsync(addSurvey); currentEntity = await _trialSiteSurveyRepository.AddAsync(addSurvey);
} }
@ -674,6 +685,10 @@ namespace IRaCIS.Core.Application.Contracts
{ {
} }
//更新调研表日志 - 老的调研表
currentLatest.SiteSurveyLogList.Add(new SiteSurveyLog() { Name = userInfo.ReplaceUserEmailOrPhone, OptType = SiteSurveyOptTyp.Over });
var copy = currentLatest.Clone(); var copy = currentLatest.Clone();
copy.State = TrialSiteSurveyEnum.ToSubmit; copy.State = TrialSiteSurveyEnum.ToSubmit;
@ -689,6 +704,10 @@ namespace IRaCIS.Core.Application.Contracts
{ {
copy.UserName = String.Empty; copy.UserName = String.Empty;
copy.Phone = String.Empty; copy.Phone = String.Empty;
//更新调研表日志
var info = await GetSiteSurveyInfo(currentLatest.Id, currentLatest.TrialId);
copy.SiteSurveyLogList.Add(new SiteSurveyLog() { Name = userInfo.ReplaceUserEmailOrPhone, OptType = SiteSurveyOptTyp.Update, OriginTrialSiteSurveyId = currentLatest.Id, Json = info.ToJsonStr() });
} }
@ -885,12 +904,25 @@ namespace IRaCIS.Core.Application.Contracts
} }
//审批调研表日志
var info = await GetSiteSurveyInfo(trialSiteSurveyId, trialId);
await _siteSurveyLogRepository.AddAsync(new SiteSurveyLog() { TrialSiteSurveyId = trialSiteSurveyId, Name = trialSiteSurvey.UserName, OptType = SiteSurveyOptTyp.Submit, Json = info.ToJsonStr() });
} }
else if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.SPM || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CPM) else if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.SPM || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CPM)
{ {
await _trialSiteSurveyRepository.UpdatePartialFromQueryAsync(t => t.Id == trialSiteSurveyId && t.State == TrialSiteSurveyEnum.CRCSubmitted, u => new TrialSiteSurvey() { State = TrialSiteSurveyEnum.SPMApproved, PreliminaryUserId = _userInfo.UserRoleId, PreliminaryTime = DateTime.Now }); await _trialSiteSurveyRepository.UpdatePartialFromQueryAsync(t => t.Id == trialSiteSurveyId && t.State == TrialSiteSurveyEnum.CRCSubmitted, u => new TrialSiteSurvey() { State = TrialSiteSurveyEnum.SPMApproved, PreliminaryUserId = _userInfo.UserRoleId, PreliminaryTime = DateTime.Now });
//审批调研表日志
var info = await GetSiteSurveyInfo(trialSiteSurveyId, trialId);
await _siteSurveyLogRepository.AddAsync(new SiteSurveyLog() { TrialSiteSurveyId = trialSiteSurveyId, Name = _userInfo.FullName, UserType = (UserTypeEnum)_userInfo.UserTypeEnumInt, OptType = SiteSurveyOptTyp.Approved, Json = info.ToJsonStr() });
} }
else if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.APM) else if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.APM)
{ {
@ -903,7 +935,16 @@ namespace IRaCIS.Core.Application.Contracts
//将历史锁定的调研表废弃 //将历史锁定的调研表废弃
await _trialSiteSurveyRepository.BatchUpdateNoTrackingAsync(t => t.TrialId == trialId && t.TrialSiteId == trialSiteSurvey.TrialSiteId && t.State == TrialSiteSurveyEnum.PMCreatedAndLock && t.Id != trialSiteSurveyId, z => new TrialSiteSurvey() { IsDeleted = true }); await _trialSiteSurveyRepository.BatchUpdateNoTrackingAsync(t => t.TrialId == trialId && t.TrialSiteId == trialSiteSurvey.TrialSiteId && t.State == TrialSiteSurveyEnum.PMCreatedAndLock && t.Id != trialSiteSurveyId, z => new TrialSiteSurvey() { IsDeleted = true });
//审批调研表日志
var info = await GetSiteSurveyInfo(trialSiteSurveyId, trialId);
await _siteSurveyLogRepository.AddAsync(new SiteSurveyLog() { TrialSiteSurveyId = trialSiteSurveyId, Name = _userInfo.FullName, UserType = (UserTypeEnum)_userInfo.UserTypeEnumInt, OptType = SiteSurveyOptTyp.Approved, Json = info.ToJsonStr() });
} }
await _trialSiteSurveyRepository.SaveChangesAsync(); await _trialSiteSurveyRepository.SaveChangesAsync();
return ResponseOutput.Ok(); return ResponseOutput.Ok();
} }
@ -1149,12 +1190,19 @@ namespace IRaCIS.Core.Application.Contracts
var queitUserTypeIdList = needQuitUserList.Select(t => t.UserTypeId).ToList(); var queitUserTypeIdList = needQuitUserList.Select(t => t.UserTypeId).ToList();
foreach (var item in needQuitUserList)
await _trialSiteUserRoleRepository.UpdatePartialFromQueryAsync(t => t.TrialId == trialId && t.TrialSiteId == trialSiteId && queitUserTypeIdList.Contains(t.UserRole.UserTypeId), c => new TrialSiteUserRole()
{ {
IsDeleted = true, await _trialSiteUserRoleRepository.UpdatePartialFromQueryAsync(t => t.TrialId == trialId && t.TrialSiteId == trialSiteId
DeletedTime = DateTime.Now, && t.UserRole.UserTypeId == item.UserTypeId
}); && t.UserRole.IdentityUserId == item.SystemUserId, c => new TrialSiteUserRole()
{
IsDeleted = true,
DeletedTime = DateTime.Now,
});
}
await _trialSiteSurveyRepository.UpdatePartialFromQueryAsync(t => t.Id == trialSiteSurveyId && t.State == TrialSiteSurveyEnum.SPMApproved, u => new TrialSiteSurvey() { State = TrialSiteSurveyEnum.PMCreatedAndLock, ReviewerUserId = _userInfo.UserRoleId, ReviewerTime = DateTime.Now }); await _trialSiteSurveyRepository.UpdatePartialFromQueryAsync(t => t.Id == trialSiteSurveyId && t.State == TrialSiteSurveyEnum.SPMApproved, u => new TrialSiteSurvey() { State = TrialSiteSurveyEnum.PMCreatedAndLock, ReviewerUserId = _userInfo.UserRoleId, ReviewerTime = DateTime.Now });
@ -1398,5 +1446,81 @@ namespace IRaCIS.Core.Application.Contracts
/// <summary>
/// 获取中心调研日志
/// </summary>
/// <param name="inQuery"></param>
/// <returns></returns>
[HttpPost]
public async Task<List<SiteSurveyLogDTO>> GetSiteSurveyLogList(SiteSurveyLogQuery inQuery)
{
return _siteSurveyLogRepository.Where(t => t.TrialSiteSurveyId == inQuery.TrialSiteSurveyId).ProjectTo<SiteSurveyLogDTO>(_mapper.ConfigurationProvider).ToList();
}
/// <summary>
/// 获取中心设备信息
/// </summary>
/// <param name="inQuery"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> GetSiteSurveyEquipmentList(SiteSurveyEquipmentQuery inQuery)
{
var pageList = await _trialSiteEquipmentSurveyRepository.Where(t => t.TrialSiteSurvey.TrialId == inQuery.TrialId)
.WhereIf(inQuery.TrialSiteId != null, t => t.TrialSiteSurvey.TrialSiteId==inQuery.TrialSiteId)
.WhereIf(inQuery.TrialSiteCode.IsNotNullOrEmpty(), t => t.TrialSiteSurvey.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteCode))
.WhereIf(inQuery.TrialSiteName.IsNotNullOrEmpty(), t => t.TrialSiteSurvey.TrialSite.TrialSiteAliasName.Contains(inQuery.TrialSiteName) ||
t.TrialSiteSurvey.TrialSite.TrialSiteName.Contains(inQuery.TrialSiteName))
.ProjectTo<SiteSurveyEquipmentDto>(_mapper.ConfigurationProvider).ToPagedListAsync(inQuery);
var siteSurveryConfig = _trialRepository.Where(t => t.Id == inQuery.TrialId).Select(t => t.TrialExtraConfigJsonStr).FirstOrDefault() ?? string.Empty;
var config = JsonConvert.DeserializeObject<TrialExtraConfig>(siteSurveryConfig) ?? new TrialExtraConfig();
return ResponseOutput.Ok(pageList, config);
}
/// <summary>
/// 调研表基本信息
/// </summary>
/// <param name="inQuery"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> GetSiteSurveyInfoList(SiteSurveyInfoQuery inQuery)
{
var pageList = await _trialSiteSurveyRepository.Where(t => t.TrialId == inQuery.TrialId)
.WhereIf(inQuery.TrialSiteId != null, t => t.TrialSiteId == inQuery.TrialSiteId)
.WhereIf(inQuery.TrialSiteCode.IsNotNullOrEmpty(), t => t.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteCode))
.WhereIf(inQuery.TrialSiteName.IsNotNullOrEmpty(), t => t.TrialSite.TrialSiteAliasName.Contains(inQuery.TrialSiteName) ||
t.TrialSite.TrialSiteName.Contains(inQuery.TrialSiteName))
.ProjectTo<TrialSiteSurveyView>(_mapper.ConfigurationProvider).ToPagedListAsync(inQuery);
var siteSurveryConfig = _trialRepository.Where(t => t.Id == inQuery.TrialId).Select(t => t.TrialExtraConfigJsonStr).FirstOrDefault() ?? string.Empty;
var config = JsonConvert.DeserializeObject<TrialExtraConfig>(siteSurveryConfig) ?? new TrialExtraConfig();
return ResponseOutput.Ok(pageList, config);
}
/// <summary>
/// SPM 是否参与流程
/// </summary>
/// <param name="trialId"></param>
/// <returns></returns>
public async Task<bool> GetTrialIsSPMJoin(Guid trialId)
{
var hasSPMOrCPM = await _trialRepository.Where(t => t.Id == trialId).AnyAsync(t => t.TrialIdentityUserList.SelectMany(t => t.TrialUserRoleList).Any(t =>
t.UserRole.IdentityUser.Status == UserStateEnum.Enable
&& t.UserRole.IsUserRoleDisabled == false
&& (t.UserRole.UserTypeEnum == UserTypeEnum.SPM || t.UserRole.UserTypeEnum == UserTypeEnum.CPM))
);
var isTrialSPMJoin = await _trialRepository.AnyAsync(t => t.Id == trialId && t.IsSPMJoinSiteSurvey);
var isSPMjoin = isTrialSPMJoin && hasSPMOrCPM;
return isSPMjoin;
}
} }
} }

View File

@ -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();

View File

@ -98,6 +98,16 @@ namespace IRaCIS.Core.Application.AutoMapper
CreateMap<SiteSurveyUserImportDto, IdentityUser>(); CreateMap<SiteSurveyUserImportDto, IdentityUser>();
CreateMap<SiteSurveyLog, SiteSurveyLogDTO>();
CreateMap<TrialSiteEquipmentSurvey, SiteSurveyEquipmentDto>()
.ForMember(d => d.TrialSiteAliasName, u => u.MapFrom(s => s.TrialSiteSurvey.TrialSite.TrialSiteAliasName))
.ForMember(d => d.TrialSiteName, u => u.MapFrom(s => s.TrialSiteSurvey.TrialSite.TrialSiteName))
.ForMember(d => d.TrialSiteCode, u => u.MapFrom(s => s.TrialSiteSurvey.TrialSite.TrialSiteCode));
} }
} }
} }

View File

@ -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;
} }

View File

@ -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>
@ -3376,6 +3381,11 @@ namespace IRaCIS.Core.Domain.Share
/// </summary> /// </summary>
PercentageDifference = 5, PercentageDifference = 5,
/// <summary>
/// 不适用
/// </summary>
NotApplicable = 6,
} }

View File

@ -316,6 +316,11 @@ public class VisitTask : BaseFullAuditEntity
/// </summary> /// </summary>
public bool IsCopyLesionAnswer { get; set; } = false; public bool IsCopyLesionAnswer { get; set; } = false;
/// <summary>
/// 是否计算过裁判
/// </summary>
public bool IsCalculatedJudge { get; set; } = false;
#region 完全随机增加字段 #region 完全随机增加字段
[Comment("完全随机阅片号")] [Comment("完全随机阅片号")]

View File

@ -196,6 +196,73 @@ public class ReadingQuestionCriterionTrial : BaseAddAuditEntity
/// 定圆工具默认半径 /// 定圆工具默认半径
/// </summary> /// </summary>
public decimal CircleRadius { get; set; } = 10; public decimal CircleRadius { get; set; } = 10;
/// <summary>
/// 仲裁模式
/// </summary>
public JudgeMode JudgeModeEnum { get; set; } = JudgeMode.SelectOne;
/// <summary>
/// 裁判规则
/// </summary>
public JudgeRule JudgeRuleEnum { get; set; } = JudgeRule.Consistent;
/// <summary>
/// 裁判任务生成
/// </summary>
public JudgeGenerate JudgeGenerateEnum { get; set; } = JudgeGenerate.Instant;
}
/// <summary>
/// 裁判任务生成时间
/// </summary>
public enum JudgeGenerate
{
/// <summary>
/// 及时
/// </summary>
Instant = 0,
/// <summary>
/// 阶段性
/// </summary>
Phased = 1,
}
/// <summary>
/// 仲裁模式
/// </summary>
public enum JudgeMode
{
/// <summary>
/// 整体结果择一判定
/// </summary>
SelectOne = 0,
/// <summary>
/// 指标组合判定
/// </summary>
Combined = 1,
}
/// <summary>
/// 裁判规则
/// </summary>
public enum JudgeRule
{
/// <summary>
/// 跨访视一致规则
/// </summary>
Consistent = 0,
/// <summary>
/// 访视间差异规则
/// </summary>
Difference = 1,
} }

View File

@ -0,0 +1,60 @@
using IRaCIS.Core.Domain.Share;
using System.Linq;
namespace IRaCIS.Core.Domain.Models;
[Comment("项目阅片访视裁判规则")]
[Table("ReadingQuestionVisitJudgeRule")]
public class ReadingQuestionVisitJudgeRule : BaseAddAuditEntity
{
#region 导航属性
[Comment("分页标准")]
[ForeignKey("ReadingQuestionId")]
[JsonIgnore]
public ReadingQuestionTrial ReadingQuestionTrial { get; set; }
#endregion
/// <summary>
/// 问题Id
/// </summary>
[Comment("问题Id")]
public Guid ReadingQuestionId { get; set; }
/// <summary>
/// 访视Num
/// </summary>
public decimal VisitNum { get; set; }
/// <summary>
/// 答案分组
/// </summary>
[MaxLength]
[Comment("答案分组")]
public List<string> AnswerGroup { get; set; } = new List<string>();
/// <summary>
/// 答案组合
/// </summary>
[Comment("答案组合")]
[MaxLength]
public List<string> AnswerCombination { get; set; } = new List<string>();
/// <summary>
/// 裁判类型
/// </summary>
[Comment("裁判类型")]
public JudgeTypeEnum JudgeType { get; set; } = JudgeTypeEnum.AnswerDisaffinity;
/// <summary>
/// 裁判百分比或绝对值的相差值
/// </summary>
[Comment("裁判百分比或绝对值的相差值")]
public decimal? JudgeDifferenceValue { get; set; } = 0;
/// <summary>
/// 裁判百分比或绝对值的相差值匹配规则
/// </summary>
[Comment("裁判百分比或绝对值的相差值匹配规则")]
public JudgeDifferenceType JudgeDifferenceType { get; set; }
}

View File

@ -23,6 +23,10 @@ public class TrialSiteSurvey : BaseFullDeleteAuditEntity
[JsonIgnore] [JsonIgnore]
public CommonUploadRecord SiteSurveyFile { get; set; } public CommonUploadRecord SiteSurveyFile { get; set; }
[JsonIgnore]
public List<SiteSurveyLog> SiteSurveyLogList { get; set; }=new List<SiteSurveyLog>();
#endregion #endregion
public Guid TrialSiteId { get; set; } public Guid TrialSiteId { get; set; }
@ -64,7 +68,7 @@ public class TrialSiteSurvey : BaseFullDeleteAuditEntity
public bool? IsRoutineMRIPDEE { get; set; } public bool? IsRoutineMRIPDEE { get; set; }
[Comment("MRI-PDFF 单次检查时长")] [Comment("MRI-PDFF 单次检查时长")]
public string MRIPDFFScanTime { get; set; } public string MRIPDFFScanTime { get; set; }
[Comment("MRI-PDFF 预约等待时长")] [Comment("MRI-PDFF 预约等待时长")]
public string MRIPDFFLeadTime { get; set; } public string MRIPDFFLeadTime { get; set; }
@ -88,3 +92,43 @@ public class TrialSiteSurvey : BaseFullDeleteAuditEntity
public string NotStrictManualBurnFlagReason { get; set; } public string NotStrictManualBurnFlagReason { get; set; }
} }
public class SiteSurveyLog : BaseAddAuditEntity
{
[JsonIgnore]
[ForeignKey("TrialSiteSurveyId")]
public TrialSiteSurvey TrialSiteSurvey { get; set; }
public Guid TrialSiteSurveyId { get; set; }
public string Name { get; set; }
public UserTypeEnum UserType { get; set; }
public SiteSurveyOptTyp OptType { get; set; }
public string Reason { get; set; }
[MaxLength]
public string Json { get; set; }
[Comment("更新调研表之前的调研表")]
public Guid? OriginTrialSiteSurveyId { get; set; }
}
public enum SiteSurveyOptTyp
{
Create = 0,
Submit = 1,
Approved = 2,
Reject = 3,
Update = 4,
Over=5,
}

View File

@ -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; }
}
} }

View File

@ -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
{ {
@ -417,7 +462,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

@ -421,6 +421,8 @@ public class IRaCISDBContext : DbContext
public virtual DbSet<ReadingQuestionTrial> ReadingQuestionTrial { get; set; } public virtual DbSet<ReadingQuestionTrial> ReadingQuestionTrial { get; set; }
public virtual DbSet<ReadingQuestionVisitJudgeRule> ReadingQuestionVisitJudgeRule { get; set; }
public virtual DbSet<ReadingClinicalDataPDF> ReadingClinicalDataPDF { get; set; } public virtual DbSet<ReadingClinicalDataPDF> ReadingClinicalDataPDF { get; set; }
public virtual DbSet<ReadingConsistentClinicalData> ReadingConsistentClinicalData { get; set; } public virtual DbSet<ReadingConsistentClinicalData> ReadingConsistentClinicalData { get; set; }

View File

@ -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" />

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;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,61 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace IRaCIS.Core.Infra.EFCore.Migrations
{
/// <inheritdoc />
public partial class siteSurveylog : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "SiteSurveyLog",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TrialSiteSurveyId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Name = table.Column<string>(type: "nvarchar(400)", maxLength: 400, nullable: false),
UserType = table.Column<int>(type: "int", nullable: false),
OptType = table.Column<int>(type: "int", nullable: false),
Reason = table.Column<string>(type: "nvarchar(400)", maxLength: 400, nullable: false),
Json = table.Column<string>(type: "nvarchar(max)", nullable: false),
OriginTrialSiteSurveyId = table.Column<Guid>(type: "uniqueidentifier", nullable: true, comment: "更新调研表之前的调研表"),
CreateUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
CreateTime = table.Column<DateTime>(type: "datetime2", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_SiteSurveyLog", x => x.Id)
.Annotation("SqlServer:Clustered", false);
table.ForeignKey(
name: "FK_SiteSurveyLog_TrialSiteSurvey_TrialSiteSurveyId",
column: x => x.TrialSiteSurveyId,
principalTable: "TrialSiteSurvey",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_SiteSurveyLog_User_CreateUserId",
column: x => x.CreateUserId,
principalTable: "User",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_SiteSurveyLog_CreateTime",
table: "SiteSurveyLog",
column: "CreateTime")
.Annotation("SqlServer:Clustered", true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "SiteSurveyLog");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,95 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace IRaCIS.Core.Infra.EFCore.Migrations
{
/// <inheritdoc />
public partial class JudgeRule : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "IsCalculatedJudge",
table: "VisitTask",
type: "bit",
nullable: false,
defaultValue: false);
migrationBuilder.AddColumn<int>(
name: "JudgeGenerateEnum",
table: "ReadingQuestionCriterionTrial",
type: "int",
nullable: false,
defaultValue: 0);
migrationBuilder.AddColumn<int>(
name: "JudgeModeEnum",
table: "ReadingQuestionCriterionTrial",
type: "int",
nullable: false,
defaultValue: 0);
migrationBuilder.AddColumn<int>(
name: "JudgeRuleEnum",
table: "ReadingQuestionCriterionTrial",
type: "int",
nullable: false,
defaultValue: 0);
migrationBuilder.CreateTable(
name: "ReadingQuestionVisitJudgeRule",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
ReadingQuestionId = table.Column<Guid>(type: "uniqueidentifier", nullable: false, comment: "问题Id"),
VisitNum = table.Column<decimal>(type: "decimal(18,2)", precision: 18, scale: 2, nullable: false),
AnswerGroup = table.Column<string>(type: "nvarchar(max)", nullable: false, comment: "答案分组"),
AnswerCombination = table.Column<string>(type: "nvarchar(max)", nullable: false, comment: "答案组合"),
JudgeType = table.Column<int>(type: "int", nullable: false, comment: "裁判类型"),
JudgeDifferenceValue = table.Column<decimal>(type: "decimal(18,2)", precision: 18, scale: 2, nullable: true, comment: "裁判百分比或绝对值的相差值"),
JudgeDifferenceType = table.Column<int>(type: "int", nullable: false, comment: "裁判百分比或绝对值的相差值匹配规则"),
CreateUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
CreateTime = table.Column<DateTime>(type: "datetime2", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ReadingQuestionVisitJudgeRule", x => x.Id)
.Annotation("SqlServer:Clustered", false);
},
comment: "项目阅片访视裁判规则");
migrationBuilder.CreateIndex(
name: "IX_ReadingQuestionVisitJudgeRule_CreateTime",
table: "ReadingQuestionVisitJudgeRule",
column: "CreateTime")
.Annotation("SqlServer:Clustered", true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "ReadingQuestionVisitJudgeRule");
migrationBuilder.DropColumn(
name: "IsCalculatedJudge",
table: "VisitTask");
migrationBuilder.DropColumn(
name: "JudgeGenerateEnum",
table: "ReadingQuestionCriterionTrial");
migrationBuilder.DropColumn(
name: "JudgeModeEnum",
table: "ReadingQuestionCriterionTrial");
migrationBuilder.DropColumn(
name: "JudgeRuleEnum",
table: "ReadingQuestionCriterionTrial");
}
}
}

View File

@ -6834,6 +6834,15 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
.HasColumnType("bit") .HasColumnType("bit")
.HasComment("eCRF报告是否显示在图像页面"); .HasComment("eCRF报告是否显示在图像页面");
b.Property<int>("JudgeGenerateEnum")
.HasColumnType("int");
b.Property<int>("JudgeModeEnum")
.HasColumnType("int");
b.Property<int>("JudgeRuleEnum")
.HasColumnType("int");
b.Property<DateTime?>("ReadingInfoSignTime") b.Property<DateTime?>("ReadingInfoSignTime")
.HasColumnType("datetime2") .HasColumnType("datetime2")
.HasComment("阅片信息签名时间"); .HasComment("阅片信息签名时间");
@ -7466,6 +7475,62 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
}); });
}); });
modelBuilder.Entity("IRaCIS.Core.Domain.Models.ReadingQuestionVisitJudgeRule", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.PrimitiveCollection<string>("AnswerCombination")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasComment("答案组合");
b.PrimitiveCollection<string>("AnswerGroup")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasComment("答案分组");
b.Property<DateTime>("CreateTime")
.HasColumnType("datetime2");
b.Property<Guid>("CreateUserId")
.HasColumnType("uniqueidentifier");
b.Property<int>("JudgeDifferenceType")
.HasColumnType("int")
.HasComment("裁判百分比或绝对值的相差值匹配规则");
b.Property<decimal?>("JudgeDifferenceValue")
.HasPrecision(18, 2)
.HasColumnType("decimal(18,2)")
.HasComment("裁判百分比或绝对值的相差值");
b.Property<int>("JudgeType")
.HasColumnType("int")
.HasComment("裁判类型");
b.Property<Guid>("ReadingQuestionId")
.HasColumnType("uniqueidentifier")
.HasComment("问题Id");
b.Property<decimal>("VisitNum")
.HasPrecision(18, 2)
.HasColumnType("decimal(18,2)");
b.HasKey("Id");
SqlServerKeyBuilderExtensions.IsClustered(b.HasKey("Id"), false);
b.HasIndex("CreateTime");
SqlServerIndexBuilderExtensions.IsClustered(b.HasIndex("CreateTime"));
b.ToTable("ReadingQuestionVisitJudgeRule", t =>
{
t.HasComment("项目阅片访视裁判规则");
});
});
modelBuilder.Entity("IRaCIS.Core.Domain.Models.ReadingSystemCriterionDictionary", b => modelBuilder.Entity("IRaCIS.Core.Domain.Models.ReadingSystemCriterionDictionary", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
@ -9827,6 +9892,55 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
}); });
}); });
modelBuilder.Entity("IRaCIS.Core.Domain.Models.SiteSurveyLog", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("CreateTime")
.HasColumnType("datetime2");
b.Property<Guid>("CreateUserId")
.HasColumnType("uniqueidentifier");
b.Property<string>("Json")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(400)
.HasColumnType("nvarchar(400)");
b.Property<int>("OptType")
.HasColumnType("int");
b.Property<Guid?>("OriginTrialSiteSurveyId")
.HasColumnType("uniqueidentifier")
.HasComment("更新调研表之前的调研表");
b.Property<string>("Reason")
.IsRequired()
.HasMaxLength(400)
.HasColumnType("nvarchar(400)");
b.Property<Guid>("TrialSiteSurveyId")
.HasColumnType("uniqueidentifier");
b.Property<int>("UserType")
.HasColumnType("int");
b.HasKey("Id");
SqlServerKeyBuilderExtensions.IsClustered(b.HasKey("Id"), false);
b.HasIndex("CreateTime");
SqlServerIndexBuilderExtensions.IsClustered(b.HasIndex("CreateTime"));
b.ToTable("SiteSurveyLog");
});
modelBuilder.Entity("IRaCIS.Core.Domain.Models.Sponsor", b => modelBuilder.Entity("IRaCIS.Core.Domain.Models.Sponsor", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
@ -16633,6 +16747,9 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
.HasColumnType("bit") .HasColumnType("bit")
.HasComment("阅片结果是否和原数据有差异"); .HasComment("阅片结果是否和原数据有差异");
b.Property<bool>("IsCalculatedJudge")
.HasColumnType("bit");
b.Property<bool>("IsCanEditUrgentState") b.Property<bool>("IsCanEditUrgentState")
.HasColumnType("bit") .HasColumnType("bit")
.HasComment("是否和编辑加急状态"); .HasComment("是否和编辑加急状态");
@ -18978,6 +19095,25 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
b.Navigation("RelevanceReadingQuestionTrial"); b.Navigation("RelevanceReadingQuestionTrial");
}); });
modelBuilder.Entity("IRaCIS.Core.Domain.Models.ReadingQuestionVisitJudgeRule", b =>
{
b.HasOne("IRaCIS.Core.Domain.Models.UserRole", "CreateUserRole")
.WithMany()
.HasForeignKey("CreateUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("IRaCIS.Core.Domain.Models.ReadingQuestionTrial", "ReadingQuestionTrial")
.WithMany()
.HasForeignKey("ReadingQuestionId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("CreateUserRole");
b.Navigation("ReadingQuestionTrial");
});
modelBuilder.Entity("IRaCIS.Core.Domain.Models.ReadingSystemCriterionDictionary", b => modelBuilder.Entity("IRaCIS.Core.Domain.Models.ReadingSystemCriterionDictionary", b =>
{ {
b.HasOne("IRaCIS.Core.Domain.Models.UserRole", "CreateUserRole") b.HasOne("IRaCIS.Core.Domain.Models.UserRole", "CreateUserRole")
@ -19563,6 +19699,25 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
b.Navigation("Hospital"); b.Navigation("Hospital");
}); });
modelBuilder.Entity("IRaCIS.Core.Domain.Models.SiteSurveyLog", b =>
{
b.HasOne("IRaCIS.Core.Domain.Models.UserRole", "CreateUserRole")
.WithMany()
.HasForeignKey("CreateUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("IRaCIS.Core.Domain.Models.TrialSiteSurvey", "TrialSiteSurvey")
.WithMany("SiteSurveyLogList")
.HasForeignKey("TrialSiteSurveyId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("CreateUserRole");
b.Navigation("TrialSiteSurvey");
});
modelBuilder.Entity("IRaCIS.Core.Domain.Models.Sponsor", b => modelBuilder.Entity("IRaCIS.Core.Domain.Models.Sponsor", b =>
{ {
b.HasOne("IRaCIS.Core.Domain.Models.UserRole", "CreateUserRole") b.HasOne("IRaCIS.Core.Domain.Models.UserRole", "CreateUserRole")
@ -22356,6 +22511,8 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
modelBuilder.Entity("IRaCIS.Core.Domain.Models.TrialSiteSurvey", b => modelBuilder.Entity("IRaCIS.Core.Domain.Models.TrialSiteSurvey", b =>
{ {
b.Navigation("SiteSurveyLogList");
b.Navigation("TrialSiteEquipmentSurveyList"); b.Navigation("TrialSiteEquipmentSurveyList");
b.Navigation("TrialSiteUserSurveyList"); b.Navigation("TrialSiteUserSurveyList");

View File

@ -64,6 +64,11 @@ namespace IRaCIS.Core.Infrastructure.Extention
/// </summary> /// </summary>
NotRemind = -4, NotRemind = -4,
/// <summary>
/// 后端异常 不提醒
/// </summary>
BackEndAnomaly=-5,
} }