Merge branch 'Test.IRC' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test.IRC
continuous-integration/drone/push Build is passing Details

IRC_NewDev
he 2023-12-06 17:02:31 +08:00
commit 0ad9da1076
39 changed files with 418 additions and 2759 deletions

View File

@ -17,7 +17,7 @@ using System.Runtime.InteropServices;
namespace IRaCIS.Core.API namespace IRaCIS.Core.API
{ {
public class Program public class Program1
{ {
public readonly string environment; public readonly string environment;
public static async Task Main(string[] args) public static async Task Main(string[] args)

View File

@ -1,231 +0,0 @@
//using Autofac;
//using Autofac.Extensions.DependencyInjection;
//using IRaCIS.Core.API;
//using IRaCIS.Core.Application.Filter;
//using IRaCIS.Core.Application.MediatR.Handlers;
//using LogDashboard;
//using MassTransit;
//using MassTransit.NewIdProviders;
//using MediatR;
//using Microsoft.AspNetCore.Builder;
//using Microsoft.AspNetCore.Http.Features;
//using Microsoft.AspNetCore.HttpOverrides;
//using Microsoft.AspNetCore.SignalR;
//using Microsoft.Extensions.Configuration;
//using Microsoft.Extensions.DependencyInjection;
//using Microsoft.Extensions.Hosting;
//using Serilog;
//using System;
//var builder = WebApplication.CreateBuilder(args);
// //以配置文件为准,否则 从url中取环境值(服务以命令行传递参数启动,配置文件配置了就不需要传递环境参数)
// var config = new ConfigurationBuilder()
// .AddEnvironmentVariables()
// .Build();
// var enviromentName = config["ASPNETCORE_ENVIRONMENT"];
// if (string.IsNullOrWhiteSpace(enviromentName))
// {
// var index = Array.IndexOf(args, "--env");
// enviromentName = index > -1
// ? args[index + 1]
// : "Development";
// }
// NewId.SetProcessIdProvider(new CurrentProcessIdProvider());
//builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory())
// .ConfigureContainer<ContainerBuilder>(containerBuilder =>
// {
// containerBuilder.RegisterModule<AutofacModuleSetup>();
// })
// .UseWindowsService().UseSerilog();
//// Add services to the container.
////本地化
//builder.Services.AddJsonLocalization(options => options.ResourcesPath = "Resources");
//// 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim()
//builder.Services.AddControllers(options =>
//{
// //options.Filters.Add<LogActionFilter>();
// options.Filters.Add<ModelActionFilter>();
// options.Filters.Add<ProjectExceptionFilter>();
// //options.Filters.Add<UnitOfWorkFilter>();
// //if (_configuration.GetSection("BasicSystemConfig").GetValue<bool>("OpenLoginLimit"))
// //{
// // options.Filters.Add<LimitUserRequestAuthorization>();
// //}
//}).AddNewtonsoftJsonSetup(); // NewtonsoftJson 序列化 处理
////动态WebApi + UnifiedApiResultFilter 省掉控制器代码
//builder.Services.AddDynamicWebApiSetup();
////AutoMapper
//builder.Services.AddAutoMapperSetup();
////EF ORM QueryWithNoLock
//builder.Services.AddEFSetup(builder.Configuration);
////Http 响应压缩
//builder.Services.AddResponseCompressionSetup();
////Swagger Api 文档
//builder.Services.AddSwaggerSetup();
////JWT Token 验证
//builder.Services.AddJWTAuthSetup(builder.Configuration);
//// MediatR 进程内消息 事件解耦 从程序集中 注册命令和handler对应关系
//builder.Services.AddMediatR(typeof(ConsistencyVerificationHandler).Assembly);
//// EasyCaching 缓存
//builder.Services.AddEasyCachingSetup();
////services.AddDistributedMemoryCache();
////// hangfire 定时任务框架 有界面,更友好~
//builder.Services.AddhangfireSetup(builder.Configuration);
////// QuartZ 定时任务框架 使用了hangfire 暂时不用,后续需要可以打开,已经配好
////builder.Services.AddQuartZSetup(_configuration);
//// 保护上传文件
////services.AddStaticFileAuthorizationSetup();
//////HttpReports 暂时废弃
////services.AddHttpReports().AddHttpTransport();
////Serilog 日志可视化 LogDashboard日志
//builder.Services.AddLogDashboardSetup();
////上传限制 配置
//builder.Services.Configure<FormOptions>(options =>
//{
// options.MultipartBodyLengthLimit = int.MaxValue;
// options.ValueCountLimit = int.MaxValue;
// options.ValueLengthLimit = int.MaxValue;
//});
////IP 限流 可设置白名单 或者黑名单
////services.AddIpPolicyRateLimitSetup(_configuration);
////用户类型 策略授权
//builder.Services.AddAuthorizationPolicySetup(builder.Configuration);
//builder.Services.AddJsonConfigSetup(builder.Configuration);
////转发头设置 获取真实IP
//builder.Services.Configure<ForwardedHeadersOptions>(options =>
//{
// options.ForwardedHeaders =
// ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
//});
////Dicom影像渲染图片 跨平台
//builder.Services.AddDicomSetup();
//// 实时应用
//builder.Services.AddSignalR();
//builder.Services.AddSingleton<IUserIdProvider, IRaCISUserIdProvider>();
//builder.Services.AddControllers();
//// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
////builder.Services.AddEndpointsApiExplorer();
////builder.Services.AddSwaggerGen();
////SerilogExtension.AddSerilogSetup(enviromentName, builder.Host.confi);
//var app = builder.Build();
//// Configure the HTTP request pipeline.
////本地化
//app.UseLocalization();
//app.UseForwardedHeaders();
////不需要 token 访问的静态文件 wwwroot css, JavaScript, and images don't require authentication.
//app.UseStaticFiles();
//app.UseIRacisHostStaticFileStore(app.Environment);
////LogDashboard
//app.UseLogDashboard("/LogDashboard");
////hangfire
////app.UseHangfireConfig(app.Environment);
//////暂时废弃
////app.UseHttpReports();
//////限流 中间件
////app.UseIpRateLimiting();
////响应压缩
//app.UseResponseCompression();
//if (app.Environment.IsDevelopment())
//{
// app.UseDeveloperExceptionPage();
//}
//else
//{
// //app.UseHsts();
//}
//SwaggerSetup.Configure(app, app.Environment);
//Console.WriteLine("当前环境: " + builder.Environment.EnvironmentName);
////app.UseMiddleware<AuthMiddleware>();
//// 特殊异常处理 比如 404
//app.UseStatusCodePagesWithReExecute("/Error/{0}");
//////serilog 记录请求的用户信息
//app.UseSerilogConfig(app.Environment);
//app.UseRouting();
//app.UseCors(t => t.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
//app.UseAuthentication();
////app.UseJwtBearerQueryString();
//app.UseAuthorization();
//////文件伺服 必须带Token 访问
//////app.UseIRacisHostStaticFileStore(env);
////app.UseEndpoints(endpoints =>
////{
//// endpoints.MapControllers();
//// endpoints.MapHub<UploadHub>("/UploadHub")/*.RequireCors(t=>t.WithOrigins(new string[] {"null"}).AllowAnyMethod().AllowAnyHeader().AllowCredentials())*/;
////});
//app.MapControllers();
//app.MapHub<UploadHub>("/UploadHub")/*.RequireCors(t=>t.WithOrigins(new string[] {"null"}).AllowAnyMethod().AllowAnyHeader().AllowCredentials())*/;
//app.Run();
//测试同步

View File

@ -402,7 +402,7 @@ namespace IRaCIS.Core.API.Controllers
} }
catch (Exception ex) catch (Exception )
{ {
_provider.Remove($"StudyUid_{trialId}_{archiveStudyCommand.StudyInstanceUid}"); _provider.Remove($"StudyUid_{trialId}_{archiveStudyCommand.StudyInstanceUid}");

View File

@ -24,12 +24,7 @@
<NoWarn>1701;1702;1591</NoWarn> <NoWarn>1701;1702;1591</NoWarn>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<Compile Remove="wwwroot\**" />
<EmbeddedResource Remove="UploadFile\**" />
<EmbeddedResource Remove="wwwroot\**" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<Content Remove="web.config" /> <Content Remove="web.config" />
@ -70,20 +65,20 @@
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" /> <PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="8.0.0" /> <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" /> <PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
<PackageReference Include="EasyCaching.Interceptor.Castle" Version="1.9.1" /> <PackageReference Include="EasyCaching.Interceptor.Castle" Version="1.9.2" />
<PackageReference Include="EasyCaching.Serialization.MessagePack" Version="1.9.1"> <PackageReference Include="EasyCaching.Serialization.MessagePack" Version="1.9.2">
<TreatAsUsed>true</TreatAsUsed> <TreatAsUsed>true</TreatAsUsed>
</PackageReference> </PackageReference>
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.5" /> <PackageReference Include="Hangfire.AspNetCore" Version="1.8.6" />
<PackageReference Include="Hangfire.Dashboard.BasicAuthorization" Version="1.0.2" /> <PackageReference Include="Hangfire.Dashboard.BasicAuthorization" Version="1.0.2" />
<PackageReference Include="Hangfire.SqlServer" Version="1.8.5" /> <PackageReference Include="Hangfire.SqlServer" Version="1.8.6" />
<PackageReference Include="Invio.Extensions.Authentication.JwtBearer" Version="2.0.1" /> <PackageReference Include="Invio.Extensions.Authentication.JwtBearer" Version="2.0.1" />
<PackageReference Include="LogDashboard" Version="1.4.8" /> <PackageReference Include="LogDashboard" Version="1.4.8" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.10" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.10" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.5" /> <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.5" />
<PackageReference Include="Serilog.AspNetCore" Version="7.0.0" /> <PackageReference Include="Serilog.AspNetCore" Version="8.0.0" />
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.0.1" /> <PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.0.3" />
<PackageReference Include="Serilog.Sinks.Email" Version="2.4.0" /> <PackageReference Include="Serilog.Sinks.Email" Version="2.4.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" /> <PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.5.0" /> <PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.5.0" />

View File

@ -4,34 +4,6 @@
<name>IRaCIS.Core.API</name> <name>IRaCIS.Core.API</name>
</assembly> </assembly>
<members> <members>
<member name="M:EasyCaching.Demo.Interceptors.Controllers.ErrorController.Error(System.Int32)">
<summary>
主要处理 前端404等错误 全局业务异常已统一处理了,非业务错误会来到这里
</summary>
<param name="code"></param>
<returns></returns>
</member>
<member name="T:IRaCIS.Api.Controllers.ExtraController">
<summary>
医生基本信息 、工作信息 专业信息、审核状态
</summary>
</member>
<member name="M:IRaCIS.Api.Controllers.ExtraController.GetDoctorDetail(IRaCIS.Application.Interfaces.IAttachmentService,IRaCIS.Application.Interfaces.IDoctorService,IRaCIS.Application.Interfaces.IEducationService,IRaCIS.Application.Interfaces.ITrialExperienceService,IRaCIS.Application.Interfaces.IResearchPublicationService,IRaCIS.Application.Interfaces.IVacationService,System.Guid)">
<summary>
获取医生详情
</summary>
<param name="attachmentService"></param>
<param name="_doctorService"></param>
<param name="_educationService"></param>
<param name="_trialExperienceService"></param>
<param name="_researchPublicationService"></param>
<param name="_vacationService"></param>
<param name="doctorId"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Api.Controllers.ExtraController.Login(IRaCIS.Application.Contracts.UserLoginDTO,EasyCaching.Core.IEasyCachingProvider,IRaCIS.Application.Services.IUserService,IRaCIS.Core.Application.Auth.ITokenService,Microsoft.Extensions.Configuration.IConfiguration)">
<summary> 系统用户登录接口[New] </summary>
</member>
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.AddOrUpdateTrialInspection(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Application.Contracts.TrialCommand})"> <member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.AddOrUpdateTrialInspection(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Application.Contracts.TrialCommand})">
<summary> 添加实验项目-返回新增Id[AUTH]</summary> <summary> 添加实验项目-返回新增Id[AUTH]</summary>
<returns>新记录Id</returns> <returns>新记录Id</returns>
@ -373,6 +345,27 @@
<param name="memberSerialization">序列化成员</param> <param name="memberSerialization">序列化成员</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="T:IRaCIS.Api.Controllers.ExtraController">
<summary>
医生基本信息 、工作信息 专业信息、审核状态
</summary>
</member>
<member name="M:IRaCIS.Api.Controllers.ExtraController.GetDoctorDetail(IRaCIS.Application.Interfaces.IAttachmentService,IRaCIS.Application.Interfaces.IDoctorService,IRaCIS.Application.Interfaces.IEducationService,IRaCIS.Application.Interfaces.ITrialExperienceService,IRaCIS.Application.Interfaces.IResearchPublicationService,IRaCIS.Application.Interfaces.IVacationService,System.Guid)">
<summary>
获取医生详情
</summary>
<param name="attachmentService"></param>
<param name="_doctorService"></param>
<param name="_educationService"></param>
<param name="_trialExperienceService"></param>
<param name="_researchPublicationService"></param>
<param name="_vacationService"></param>
<param name="doctorId"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Api.Controllers.ExtraController.Login(IRaCIS.Application.Contracts.UserLoginDTO,EasyCaching.Core.IEasyCachingProvider,IRaCIS.Application.Services.IUserService,IRaCIS.Core.Application.Auth.ITokenService,Microsoft.Extensions.Configuration.IConfiguration)">
<summary> 系统用户登录接口[New] </summary>
</member>
<member name="M:IRaCIS.WX.CoreApi.Auth.AuthMiddleware.Invoke(Microsoft.AspNetCore.Http.HttpContext)"> <member name="M:IRaCIS.WX.CoreApi.Auth.AuthMiddleware.Invoke(Microsoft.AspNetCore.Http.HttpContext)">
<summary> <summary>
为了前端 一段时间无操作,需要重新登陆 为了前端 一段时间无操作,需要重新登陆
@ -380,6 +373,13 @@
<param name="httpContext"></param> <param name="httpContext"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:EasyCaching.Demo.Interceptors.Controllers.ErrorController.Error(System.Int32)">
<summary>
主要处理 前端404等错误 全局业务异常已统一处理了,非业务错误会来到这里
</summary>
<param name="code"></param>
<returns></returns>
</member>
<member name="T:ZhaoXi._001.NET5Demo.Practice.WebApi.Utility.Jwt.CustomHSJWTService"> <member name="T:ZhaoXi._001.NET5Demo.Practice.WebApi.Utility.Jwt.CustomHSJWTService">
<summary> <summary>
对称可逆加密 对称可逆加密

306
IRaCIS.Core.API/Progranm.cs Normal file
View File

@ -0,0 +1,306 @@
using System;
using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Configuration;
using Serilog;
using MediatR;
using IRaCIS.Core.Application.MediatR.Handlers;
using System.Threading.Tasks;
using MassTransit;
using MassTransit.NewIdProviders;
using System.IO;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Application.Helper;
using System.Runtime.InteropServices;
using Microsoft.AspNetCore.Builder;
using IRaCIS.Core.API;
using Autofac;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.DependencyInjection;
using IRaCIS.Core.Application.Filter;
using Microsoft.AspNetCore.HttpOverrides;
using IRaCIS.Application.Services.BackGroundJob;
using LogDashboard;
using OfficeOpenXml.Utils;
#region 获取环境变量
//以配置文件为准,否则 从url中取环境值(服务以命令行传递参数启动,配置文件配置了就不需要传递环境参数)
var config = new ConfigurationBuilder()
.AddEnvironmentVariables()
.Build();
var enviromentName = config["ASPNETCORE_ENVIRONMENT"];
if (string.IsNullOrWhiteSpace(enviromentName))
{
var index = Array.IndexOf(args, "--env");
enviromentName = index > -1
? args[index + 1]
: "Development";
}
#endregion
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
EnvironmentName = enviromentName
});
#region 兼容windows 服务命令行的方式
//foreach (var arg in args)
//{
// Console.WriteLine(arg);
//}
int urlsIndex = Array.FindIndex(args, arg => arg != null && arg.StartsWith("--urls"));
if (urlsIndex > -1)
{
var url = args[urlsIndex].Substring("--urls=".Length);
Console.WriteLine(url);
builder.WebHost.UseUrls(url);
}
#endregion
#region 主机配置
NewId.SetProcessIdProvider(new CurrentProcessIdProvider());
builder.Host
.ConfigureAppConfiguration((hostContext, config) =>
{
//Console.WriteLine(hostContext.HostingEnvironment.EnvironmentName);
config.AddJsonFile("appsettings.json", false, true)
.AddJsonFile($"appsettings.{enviromentName}.json", false, true);
})
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureContainer<ContainerBuilder>(containerBuilder =>
{
containerBuilder.RegisterModule<AutofacModuleSetup>();
})
.UseWindowsService().UseSerilog();
#endregion
#region 配置服务
var _configuration = builder.Configuration;
//健康检查
builder.Services.AddHealthChecks();
//本地化
builder.Services.AddJsonLocalization(options => options.ResourcesPath = "Resources");
// 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim()
builder.Services.AddControllers(options =>
{
//options.Filters.Add<LogActionFilter>();
options.Filters.Add<ModelActionFilter>();
options.Filters.Add<ProjectExceptionFilter>();
options.Filters.Add<UnitOfWorkFilter>();
if (_configuration.GetSection("BasicSystemConfig").GetValue<bool>("OpenLoginLimit"))
{
options.Filters.Add<LimitUserRequestAuthorization>();
}
})
.AddNewtonsoftJsonSetup(); // NewtonsoftJson 序列化 处理
builder.Services.AddOptions().Configure<SystemEmailSendConfig>(_configuration.GetSection("SystemEmailSendConfig"));
builder.Services.AddOptions().Configure<ServiceVerifyConfigOption>(_configuration.GetSection("BasicSystemConfig"));
builder.Services.AddOptions().Configure<AliyunOSSOptions>(_configuration.GetSection("AliyunOSS"));
builder.Services.AddOptions().Configure<ObjectStoreServiceOptions>(_configuration.GetSection("ObjectStoreService"));
//动态WebApi + UnifiedApiResultFilter 省掉控制器代码
builder.Services.AddDynamicWebApiSetup();
//AutoMapper
builder.Services.AddAutoMapperSetup();
//EF ORM QueryWithNoLock
builder.Services.AddEFSetup(_configuration);
//Http 响应压缩
builder.Services.AddResponseCompressionSetup();
//Swagger Api 文档
builder.Services.AddSwaggerSetup();
//JWT Token 验证
builder.Services.AddJWTAuthSetup(_configuration);
// MediatR 进程内消息 事件解耦 从程序集中 注册命令和handler对应关系
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<ConsistencyVerificationHandler>());
// EasyCaching 缓存
builder.Services.AddEasyCachingSetup(_configuration);
// hangfire 定时任务框架 有界面,更友好~
builder.Services.AddhangfireSetup(_configuration);
//Serilog 日志可视化 LogDashboard日志
builder.Services.AddLogDashboardSetup();
builder.Services.AddJsonConfigSetup(_configuration);
//转发头设置 获取真实IP
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
//Dicom影像渲染图片 跨平台
builder.Services.AddDicomSetup();
// 实时应用
builder.Services.AddSignalR();
builder.Services.AddSingleton<IUserIdProvider, IRaCISUserIdProvider>();
#region 历史废弃配置
//builder.Services.AddMemoryCache();
////上传限制 配置
//builder.Services.Configure<FormOptions>(options =>
//{
// options.MultipartBodyLengthLimit = int.MaxValue;
// options.ValueCountLimit = int.MaxValue;
// options.ValueLengthLimit = int.MaxValue;
//});
//IP 限流 可设置白名单 或者黑名单
//services.AddIpPolicyRateLimitSetup(_configuration);
// 用户类型 策略授权
//services.AddAuthorizationPolicySetup(_configuration);
#endregion
#endregion
var app = builder.Build();
var env = app.Environment;
#region 配置中间件
// Configure the HTTP request pipeline.
//本地化
app.UseLocalization();
app.UseForwardedHeaders();
//响应压缩
app.UseResponseCompression();
//app.UseCors(t => t.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
//不需要 token 访问的静态文件 wwwroot css, JavaScript, and images don't require authentication.
app.UseStaticFiles();
app.UseMiddleware<MultiDiskStaticFilesMiddleware>();
//LogDashboard
app.UseLogDashboard("/LogDashboard");
//hangfire
app.UseHangfireConfig(env);
////限流 中间件
//app.UseIpRateLimiting();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
//app.UseHsts();
}
// 特殊异常处理 比如 404
app.UseStatusCodePagesWithReExecute("/Error/{0}");
SwaggerSetup.Configure(app, env);
////serilog 记录请求的用户信息
app.UseSerilogConfig(env);
app.UseRouting();
app.UseCors(t => t.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
//app.UseIRacisHostStaticFileStore(env);
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHub<UploadHub>("/UploadHub");
endpoints.MapHealthChecks("/health");
});
// Serilog
SerilogExtension.AddSerilogSetup(enviromentName, app.Services);
var hangfireJobService = app.Services.GetRequiredService<IIRaCISHangfireJob>();
await hangfireJobService.InitHangfireJobTaskAsync();
#endregion
try
{
#region 运行环境 部署平台
Log.Logger.Warning($"当前环境:{enviromentName}");
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
Log.Logger.Warning($"当前部署平台环境windows");
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
Log.Logger.Warning($"当前部署平台环境linux");
}
else
{
Log.Logger.Warning($"当前部署平台环境OSX or FreeBSD");
}
#endregion
app.Run();
}
catch (Exception e)
{
Log.Logger.Error(e.InnerException is null ? e.Message + e.StackTrace : e.InnerException?.Message + e.InnerException?.StackTrace);
}

View File

@ -1,7 +1,6 @@
using Autofac; using Autofac;
using Autofac.Extras.DynamicProxy; using Autofac.Extras.DynamicProxy;
using IRaCIS.Core.Application; using IRaCIS.Core.Application;
using IRaCIS.Core.Application.AOP;
using IRaCIS.Core.Application.BackGroundJob; using IRaCIS.Core.Application.BackGroundJob;
using IRaCIS.Core.Infra.EFCore; using IRaCIS.Core.Infra.EFCore;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;

View File

@ -37,17 +37,6 @@
} }
}, },
"AliyunOSS": {
"RegionId": "cn-shanghai",
"Endpoint": "https://oss-cn-shanghai.aliyuncs.com",
"AccessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
"AccessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
"BucketName": "zy-irc-test-store",
"RoleArn": "acs:ram::1899121822495495:role/oss-upload",
"ViewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai"
},
"BasicSystemConfig": { "BasicSystemConfig": {
"OpenUserComplexPassword": false, "OpenUserComplexPassword": false,

View File

@ -1,97 +0,0 @@
using Castle.DynamicProxy;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.AOP
{
public abstract class AsyncInterceptorBase : IInterceptor
{
public AsyncInterceptorBase()
{
}
public void Intercept(IInvocation invocation)
{
BeforeProceed(invocation);
invocation.Proceed();
if (IsAsyncMethod(invocation.MethodInvocationTarget))
{
invocation.ReturnValue = InterceptAsync((dynamic)invocation.ReturnValue, invocation);
}
else
{
AfterProceedSync(invocation);
}
}
private bool CheckMethodReturnTypeIsTaskType(MethodInfo method)
{
var methodReturnType = method.ReturnType;
if (methodReturnType.IsGenericType)
{
if (methodReturnType.GetGenericTypeDefinition() == typeof(Task<>) ||
methodReturnType.GetGenericTypeDefinition() == typeof(ValueTask<>))
return true;
}
else
{
if (methodReturnType == typeof(Task) ||
methodReturnType == typeof(ValueTask))
return true;
}
return false;
}
private bool IsAsyncMethod(MethodInfo method)
{
bool isDefAsync = Attribute.IsDefined(method, typeof(AsyncStateMachineAttribute), false);
bool isTaskType = CheckMethodReturnTypeIsTaskType(method);
bool isAsync = isDefAsync && isTaskType;
return isAsync;
}
protected object ProceedAsyncResult { get; set; }
private async Task InterceptAsync(Task task, IInvocation invocation)
{
await task.ConfigureAwait(false);
await AfterProceedAsync(invocation, false);
}
private async Task<TResult> InterceptAsync<TResult>(Task<TResult> task, IInvocation invocation)
{
ProceedAsyncResult = await task.ConfigureAwait(false);
await AfterProceedAsync(invocation, true);
return (TResult)ProceedAsyncResult;
}
private async ValueTask InterceptAsync(ValueTask task, IInvocation invocation)
{
await task.ConfigureAwait(false);
await AfterProceedAsync(invocation, false);
}
private async ValueTask<TResult> InterceptAsync<TResult>(ValueTask<TResult> task, IInvocation invocation)
{
ProceedAsyncResult = await task.ConfigureAwait(false);
await AfterProceedAsync(invocation, true);
return (TResult)ProceedAsyncResult;
}
protected virtual void BeforeProceed(IInvocation invocation) { }
protected virtual void AfterProceedSync(IInvocation invocation) { }
protected virtual Task AfterProceedAsync(IInvocation invocation, bool hasAsynResult)
{
return Task.CompletedTask;
}
}
}

View File

@ -1,499 +0,0 @@
//using System;
//using Castle.DynamicProxy;
//using IRaCIS.Core.Application.Contracts.Dicom.DTO;
//using IRaCIS.Core.Infra.EFCore;
//using System.Linq;
//using IRaCIS.Core.Domain.Models;
//using IRaCIS.Core.Domain.Share;
//namespace IRaCIS.Core.API.Utility.AOP
//{
//#pragma warning disable
// public class QANoticeAOP : IInterceptor
// {
// private readonly IRepository<QANotice> _qaNoticeRepository;
// private readonly IRepository<DicomStudy> _studyRepository;
// private readonly IRepository<TrialUser> _userTrialRepository;
// private readonly IRepository<TrialSiteUser> _userTrialSiteRepository;
// private readonly IUserInfo _userInfo;
// public QANoticeAOP(IRepository<QANotice> qaNoticeRepository,
// IUserInfo userInfo, IRepository<DicomStudy> studyRepository, IRepository<TrialUser> userTrialRepository, IRepository<TrialSiteUser> userTrialSiteRepository)
// {
// _qaNoticeRepository = qaNoticeRepository;
// _studyRepository = studyRepository;
// _userTrialRepository = userTrialRepository;
// _userTrialSiteRepository = userTrialSiteRepository;
// _userInfo = userInfo;
// }
// public void Intercept(IInvocation invocation)
// {
// //处理拦截的方法
// invocation.Proceed();
// if (invocation.Method.Name == "UpdateStudyStatus")
// {
// var studyStatus = invocation.Arguments[0] as StudyStatusDetailCommand;
// var study = _studyRepository.FirstOrDefault(t=>t.Id==studyStatus.StudyId);
// if (study.Status == (int)StudyStatus.Uploaded)
// {
// _qaNoticeRepository.Add(new QANotice()
// {
// TrialId = study.TrialId,
// SubjectVisitId = study.Id,
// FromUser = _userInfo.RealName,
// FromUserId = _userInfo.Id,
// FromUserType = _userInfo.UserTypeShortName,
// NoticeTypeEnum = NoticeType.NotNeedNotice,
// NeedDeal = false,
// StudyStatusStr = "Uploaded",
// Message = $"CRC : {_userInfo.RealName} has uploaded {study.StudyCode} ",
// SendTime = DateTime.Now,
// });
// }
// #region 处理QA通知模块
// //查询项目的参与者 和 负责site下CRC用户
// var trialUserList = _userTrialRepository.Where(t => t.TrialId == study.TrialId).ToList();
// // 找到该study 关联Site 下的CRC
// var crcList = _userTrialSiteRepository.Where(t =>
// t.SiteId == study.SiteId && t.User.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator && t.TrialId == study.TrialId).ToList();
// var qaList = trialUserList.Where(t => t.User.UserTypeEnum == UserTypeEnum.IQC).ToList();
// var pm = trialUserList.FirstOrDefault(t => t.User.UserTypeEnum == UserTypeEnum.ProjectManager);
// // CRC =>QA
// if (studyStatus.Status == (int)StudyStatus.QARequested)
// {
// //找出当前操作的CRC
// //PM 或者admin可以代替CRC角色 不能从CRC列表中查询用户
// //var currentCRC = trialUserList.First(t => t.UserId == _userInfo.Id);
// var notice = new QANotice()
// {
// TrialId = study.TrialId,
// SubjectVisitId = study.Id,
// FromUser = _userInfo.RealName,
// FromUserId = _userInfo.Id,
// FromUserType = _userInfo.UserTypeShortName,
// //FromUser = currentCRC.UserRealName,
// //FromUserId = _userInfo.Id,
// //FromUserType = currentCRC.UserType,
// NoticeTypeEnum = NoticeType.CRC_RequestToQA_NoticeQA,
// NeedDeal = true,
// StudyStatusStr = "QA Requested",
// Message =
// $"CRC -> QA : {_userInfo.RealName} request QA {study.StudyCode} , Inquiry can be performed! ",
// SendTime = DateTime.Now,
// };
// qaList.ForEach(t => notice.QANoticeUserList.Add(new QANoticeUser()
// {
// QANoticeId = notice.Id,
// SubjectVisitId = study.Id,
// ToUser = t.User.LastName + " / " + t.User.FirstName,
// ToUserId = t.UserId,
// ToUserType = t.User.UserTypeRole.UserTypeShortName
// }));
// _qaNoticeRepository.Add(notice);
// //DealRequestToQA(study.Id);
// var needDealNoticeList = _qaNoticeRepository.AsQueryable()
// .Where(t => t.SubjectVisitId == study.Id && t.NeedDeal && t.NoticeTypeEnum == NoticeType.CRC_RequestToQA_NoticeQA).ToList();
// needDealNoticeList.ForEach(t =>
// {
// t.NeedDeal = false;
// t.DealTime = DateTime.Now;
// _qaNoticeRepository.Update(t);
// });
// }
// // QA =>CRC 向CRC推送消息影像有问题 同时作为 requestToQA 的边界
// else if (studyStatus.Status == (int)StudyStatus.QAing)
// {
// //找出当前操作的QA 如果是pm 或者admin 代替操作 此时会有问题 所以 谁代替,就以谁的名义执行
// //var currentQA = qaList.First(t => t.UserId == _userInfo.Id);
// //var currentQA = trialUserList.First(t => t.UserId == _userInfo.Id);
// //在项目CRC列表中筛选出 负责该study关联 site的CRC
// var siteCRCList = _userTrialSiteRepository.Where(t =>
// t.SiteId == study.SiteId && t.User.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator && t.TrialId == study.TrialId).ToList();
// //查询项目的参与者 和 负责site下CRC用户
// var notice = new QANotice()
// {
// TrialId = study.TrialId,
// SubjectVisitId = study.Id,
// //FromUser = currentQA.UserRealName,
// //FromUserId = _userInfo.Id,
// //FromUserType = currentQA.UserType,
// FromUser = _userInfo.RealName,
// FromUserId = _userInfo.Id,
// FromUserType = _userInfo.UserTypeShortName,
// NoticeTypeEnum = NoticeType.QA_InQA_NoticeCRC,
// NeedDeal = true,
// StudyStatusStr = "In QA",
// Message = $"QA -> CRC : {_userInfo.RealName} inquiry {study.StudyCode} ",
// SendTime = DateTime.Now,
// };
// siteCRCList.ForEach(t => notice.QANoticeUserList.Add(new QANoticeUser()
// {
// QANoticeId = notice.Id,
// SubjectVisitId = study.Id,
// ToUser = t.User.LastName + " / " + t.User.FirstName,
// ToUserId = t.UserId,
// ToUserType = t.UserTypeRole.UserTypeShortName
// }));
// //添加 发送给CRC的消息 消息和CRC是 一对多
// _qaNoticeRepository.Add(notice);
// //处理 消息 标记已处理
// var needDealNoticeList = _qaNoticeRepository.AsQueryable()
// .Where(t => t.SubjectVisitId == study.Id && t.NeedDeal &&
// (t.NoticeTypeEnum == NoticeType.CRC_RequestToQA_NoticeQA ||
// t.NoticeTypeEnum == NoticeType.CRC_ReUpload_NoticeQA ||
// t.NoticeTypeEnum == NoticeType.CRC_QARecordDialogPost_NoticeQA)).ToList();
// needDealNoticeList.ForEach(t =>
// {
// t.NeedDeal = false;
// t.DealTime = DateTime.Now;
// _qaNoticeRepository.Update(t);
// });
// }
// // QA =>QA 给自己的消息 通知需要匿名化 同时作为 requestToQA 的边界
// else if (studyStatus.Status == (int)StudyStatus.QAFinish)
// {
// //找出当前操作的QA 如果是pm 或者admin 代替操作 此时会有问题 所以 谁代替,就以谁的名义执行
// //var currentQA = qaList.First(t => t.UserId == _userInfo.Id);
// //var currentQA = trialUserList.First(t => t.UserId == _userInfo.Id);
// //发送给当前项目QA列表
// var notice = new QANotice()
// {
// TrialId = study.TrialId,
// SubjectVisitId = study.Id,
// //FromUser = currentQA.UserRealName,
// //FromUserId = _userInfo.Id,
// //FromUserType = currentQA.UserType,
// FromUser = _userInfo.RealName,
// FromUserId = _userInfo.Id,
// FromUserType = _userInfo.UserTypeShortName,
// NoticeTypeEnum = NoticeType.QA_QAPass_NoticeQA,
// NeedDeal = true,
// StudyStatusStr = "QA-Passed",
// Message =
// $"QA -> QA : {_userInfo.RealName} inquiry {study.StudyCode} finishedAnonymization can be performed",
// SendTime = DateTime.Now,
// };
// qaList.ForEach(t => notice.QANoticeUserList.Add(new QANoticeUser()
// {
// QANoticeId = notice.Id,
// SubjectVisitId = study.Id,
// ToUser = t.User.LastName+" / "+t.User.FirstName,
// ToUserId = t.UserId,
// ToUserType = t.User.UserTypeRole.UserTypeShortName
// }));
// _qaNoticeRepository.Add(notice);
// //处理 消息 标记已处理 存在意外情况 qa发给CRC的 但是qa里面设置了 通过或者不通过 此时qa发送的消息也设置为已处理
// var needDealNoticeList = _qaNoticeRepository.AsQueryable()
// .Where(t => t.SubjectVisitId == study.Id && t.NeedDeal &&
// (t.NoticeTypeEnum == NoticeType.CRC_RequestToQA_NoticeQA ||
// t.NoticeTypeEnum == NoticeType.CRC_ReUpload_NoticeQA ||
// t.NoticeTypeEnum == NoticeType.CRC_QARecordDialogPost_NoticeQA ||
// t.NoticeTypeEnum == NoticeType.QA_QARecordDialogPost_NoticeCRC ||
// t.NoticeTypeEnum == NoticeType.QA_InQA_NoticeCRC ||
// t.NoticeTypeEnum == NoticeType.QA_AddQARecord_NoticeCRC)).ToList();
// needDealNoticeList.ForEach(t =>
// {
// t.NeedDeal = false;
// t.DealTime = DateTime.Now;
// _qaNoticeRepository.Update(t);
// });
// }
// // QA =>CRC 暂时不用发送消息给CRC 因为CRC 暂时没有入口回复 同时作为 requestToQA 的边界
// else if (studyStatus.Status == (int)StudyStatus.QAFInishNotPass)
// {
// _qaNoticeRepository.Add(new QANotice()
// {
// TrialId = study.TrialId,
// SubjectVisitId = study.Id,
// FromUser = _userInfo.RealName,
// FromUserId = _userInfo.Id,
// FromUserType = _userInfo.UserTypeShortName,
// NoticeTypeEnum = NoticeType.NotNeedNotice,
// NeedDeal = false,
// StudyStatusStr = "QA-Failed",
// Message = $"QA : {_userInfo.RealName} set {study.StudyCode} QA-Failed ",
// SendTime = DateTime.Now,
// });
// //处理 消息 标记已处理
// var needDealNoticeList = _qaNoticeRepository.AsQueryable()
// .Where(t => t.SubjectVisitId == study.Id && t.NeedDeal &&
// (t.NoticeTypeEnum == NoticeType.CRC_RequestToQA_NoticeQA ||
// t.NoticeTypeEnum == NoticeType.CRC_ReUpload_NoticeQA ||
// t.NoticeTypeEnum == NoticeType.CRC_QARecordDialogPost_NoticeQA ||
// t.NoticeTypeEnum == NoticeType.QA_QARecordDialogPost_NoticeCRC ||
// t.NoticeTypeEnum == NoticeType.QA_InQA_NoticeCRC ||
// t.NoticeTypeEnum == NoticeType.QA_AddQARecord_NoticeCRC)).ToList();
// needDealNoticeList.ForEach(t =>
// {
// t.NeedDeal = false;
// t.DealTime = DateTime.Now;
// _qaNoticeRepository.Update(t);
// });
// }
// #endregion
// }
// else if (invocation.Method.Name == "ReUploadSameStudy")
// {
// var studyId = Guid.Parse(invocation.Arguments[0].ToString());
// var study = _studyRepository.FirstOrDefault(t => t.Id == studyId);
// var status = study.Status;
// //处理CRC 重传时 QA消息
// if (status == (int)StudyStatus.QAing)
// {
// //查询项目的参与者 和 负责site下CRC用户
// var trialUserList = _userTrialRepository.Where(t => t.TrialId == study.TrialId).ToList();
// // 找到该study 关联Site 下的CRC
// var crcList = _userTrialSiteRepository.Where(t =>
// t.SiteId == study.SiteId && t.User.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator && t.TrialId == study.TrialId).ToList();
// var qaList = trialUserList.Where(t => t.User.UserTypeEnum == UserTypeEnum.IQC).ToList();
// //CRC =>QA CRC的职能被PM 或者admin代替
// //if (_userInfo.UserTypeEnumInt == (int)UserType.ClinicalResearchCoordinator)
// {
// //PM 或者admin可以代替CRC角色 不能从CRC列表中查询用户
// //var currentCRC = trialUserList.First(t => t.UserId == _userInfo.Id);
// var notice = new QANotice()
// {
// TrialId = study.TrialId,
// SubjectVisitId = study.Id,
// //FromUser = currentCRC.UserRealName,
// //FromUserId = _userInfo.Id,
// //FromUserType = currentCRC.UserType,
// FromUser = _userInfo.RealName,
// FromUserId = _userInfo.Id,
// FromUserType = _userInfo.UserTypeShortName,
// NoticeTypeEnum = NoticeType.CRC_ReUpload_NoticeQA,
// NeedDeal = true,
// Message = $"CRC -> QA :{_userInfo.RealName} has reuploaded {study.StudyCode} , Need to be inquiry again",
// SendTime = DateTime.Now
// };
// qaList.ForEach(t => notice.QANoticeUserList.Add(new QANoticeUser()
// {
// QANoticeId = notice.Id,
// SubjectVisitId = study.Id,
// ToUser = t.User.LastName+" / "+t.User.FirstName,
// ToUserId = t.UserId,
// ToUserType = t.User.UserTypeRole.UserTypeShortName
// }));
// _qaNoticeRepository.Add(notice);
// //这里作为 QA 设置 Inqa 状态的回复 或者QA和CRC对话的
// var needDealNoticeList = _qaNoticeRepository.Where(t => t.SubjectVisitId == study.Id && t.NeedDeal
// && (t.NoticeTypeEnum == NoticeType.QA_InQA_NoticeCRC || t.NoticeTypeEnum == NoticeType.QA_QARecordDialogPost_NoticeCRC))
// .ToList();
// needDealNoticeList.ForEach(t =>
// {
// t.NeedDeal = false;
// t.DealTime = DateTime.Now;
// _qaNoticeRepository.Update(t);
// });
// }
// }
// else
// {
// //不是QAing 的重传 不发送qa消息
// return;
// }
// }
// else if (invocation.Method.Name == "DicomAnonymize")
// {
// var studyId = Guid.Parse(invocation.Arguments[0].ToString());
// var study = _studyRepository.FirstOrDefault(t => t.Id == studyId);
// #region 处理QA通知 匿名化完毕 通知PM
// //查询项目的参与者 和 负责site下CRC用户
// var trialUserList = _userTrialRepository.Where(t => t.TrialId == study.TrialId).ToList();
// // 找到该study 关联Site 下的CRC
// var crcList = _userTrialSiteRepository.Where(t =>
// t.SiteId == study.SiteId && t.User.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator && t.TrialId == study.TrialId).ToList();
// var qaList = trialUserList.Where(t => t.User.UserTypeEnum == UserTypeEnum.IQC).ToList();
// //
// var pm = trialUserList.FirstOrDefault(t => t.User.UserTypeEnum == UserTypeEnum.ProjectManager);
// //找出当前操作的QA 如果是pm 或者admin 代替操作 此时会有问题 所以 谁代替,就以谁的名义执行
// //var currentQA = trialUserList.First(t =>
// // t.UserTypeEnum == UserType.IQC && t.UserId == _userInfo.Id);
// //var currentQA = trialUserList.First(t => t.UserId == _userInfo.Id);
// var notice = new QANotice()
// {
// TrialId = study.TrialId,
// SubjectVisitId = study.Id,
// //FromUser = currentQA.UserRealName,
// //FromUserId = _userInfo.Id,
// //FromUserType = currentQA.UserType,
// FromUser = _userInfo.RealName,
// FromUserId = _userInfo.Id,
// FromUserType = _userInfo.UserTypeShortName,
// NoticeTypeEnum = NoticeType.QA_Anonymized_NoticeQA,
// NeedDeal = true,
// StudyStatusStr = "Anonymized",
// //Message = $"QA -> PM :{_userInfo.RealName} has anonymized {study.StudyCode} Forward can be performed",
// Message = $"QA -> QA :{_userInfo.RealName} has anonymized {study.StudyCode} Forward can be performed",
// SendTime = DateTime.Now,
// };
// //notice.QANoticeUserList.Add(new QANoticeUser()
// //{
// // QANoticeId = notice.Id,
// // StudyId = study.Id,
// // ToUser = pm.UserRealName,
// // ToUserId = pm.UserId,
// // ToUserType = pm.UserType
// //});
// qaList.ForEach(t => notice.QANoticeUserList.Add(new QANoticeUser()
// {
// QANoticeId = notice.Id,
// SubjectVisitId = study.Id,
// ToUser = t.User.LastName+" / "+t.User.FirstName,
// ToUserId = t.UserId,
// ToUserType = t.User.UserTypeRole.UserTypeShortName
// }));
// _qaNoticeRepository.Add(notice);
// var needDealNoticeList = _qaNoticeRepository.AsQueryable()
// .Where(t => t.SubjectVisitId == study.Id && t.NeedDeal && (t.NoticeTypeEnum == NoticeType.QA_QAPass_NoticeQA)).ToList();
// needDealNoticeList.ForEach(t =>
// {
// t.NeedDeal = false;
// t.DealTime = DateTime.Now;
// _qaNoticeRepository.Update(t);
// });
// #endregion
// }
// else if (invocation.Method.Name == "ForwardStudy")
// {
// var studyId = Guid.Parse(invocation.Arguments[0].ToString());
// var study = _studyRepository.FirstOrDefault(t => t.Id == studyId);
// //匿名化操作产生的消息 设置为已经处理
// _qaNoticeRepository.Add(new QANotice()
// {
// TrialId = study.TrialId,
// SubjectVisitId = study.Id,
// //FromUser = currentQA.UserRealName,
// //FromUserId = _userInfo.Id,
// //FromUserType = currentQA.UserType,
// FromUser = _userInfo.RealName,
// FromUserId = _userInfo.Id,
// FromUserType = _userInfo.UserTypeShortName,
// NoticeTypeEnum = NoticeType.NotNeedNotice,
// NeedDeal = false,
// StudyStatusStr = "Forwarded",
// //Message = $"PM :{_userInfo.RealName} has forwarded {study.StudyCode} ",
// Message = $"QA :{_userInfo.RealName} has forwarded {study.StudyCode} ",
// SendTime = DateTime.Now,
// });
// var needDealList = _qaNoticeRepository.Where(t =>
// t.SubjectVisitId == study.Id && t.NeedDeal && t.NoticeTypeEnum == NoticeType.QA_Anonymized_NoticeQA).ToList();
// needDealList.ForEach(t =>
// {
// t.NeedDeal = false;
// t.DealTime = DateTime.Now;
// _qaNoticeRepository.Update(t);
// });
// }
// var success = _qaNoticeRepository.SaveChanges();
// if (!success)
// {
// throw new Exception("Send QA message failed");
// }
// }
// }
//}

View File

@ -1,89 +0,0 @@
using Castle.DynamicProxy;
using EasyCaching.Core;
using IRaCIS.Application.Contracts;
using IRaCIS.Core.Domain.Share;
namespace IRaCIS.Core.Application.AOP
{
public class TrialStatusAutofacAOP : IAsyncInterceptor
{
private readonly IEasyCachingProvider _provider;
public TrialStatusAutofacAOP(IEasyCachingProvider provider)
{
_provider = provider;
}
public void InterceptAsynchronous(IInvocation invocation)
{
invocation.Proceed();
}
//这里AOP 处理两个方法 分别是 项目的添加和更新、项目状态的变更
public void InterceptAsynchronous<TResult>(IInvocation invocation)
{
//处理拦截的方法
invocation.Proceed();
dynamic result = invocation.ReturnValue;
//接口成功了,才修改缓存
if (!result.IsSuccess)
{
return;
}
#region 处理项目列表的查询 在前端界面已经在某个界面,但是服务器重置了,此时没有缓存项目信息,接口不能正确返回,因故采用,启动时查询,每天查询一次,缓存一天,然后项目添加、更改状态时,及时更新
//if (invocation.Method.Name == "GetTrialList")
//{
// //在此 将当前查询的项目Id 和对应的项目状态进行缓存
// dynamic result = invocation.ReturnValue;
// foreach (var item in result.CurrentPageData)
// {
// _provider.Remove(item.Id.ToString());
// _provider.Set(item.Id.ToString(), item.TrialStatusStr.ToString(), TimeSpan.FromDays(1));
// }
//}
#endregion
if (invocation.Method.Name == "AddOrUpdateTrial")
{
//如果是添加 那么将对应的初始状态加进去 更新状态是单独操作的
var trialModel = (invocation.Arguments[0] as TrialCommand).IfNullThrowConvertException();
if (trialModel.Id == null || trialModel.Id == Guid.Empty)
{
_provider.Set(result.Data.Id.ToString(), StaticData.TrialState.TrialOngoing, TimeSpan.FromDays(1));
}
}
// 更新缓存
else if (invocation.Method.Name == "UpdateTrialStatus")
{
//项目状态更新,也需要及时更新
_provider.Set(invocation.Arguments[0].ToString(), invocation.Arguments[1].ToString(), TimeSpan.FromDays(1));
////Test参数是否符合要求
//var tt = invocation.Arguments[0].ToString();
//var cc = _provider.Get<string>(invocation.Arguments[0].ToString());
}
}
public void InterceptSynchronous(IInvocation invocation)
{
invocation.Proceed();
}
}
}

View File

@ -1,81 +0,0 @@
//using System.Diagnostics;
//using IRaCIS.Application.Interfaces;
//using IRaCIS.Application.Contracts;
//using IRaCIS.Core.Infra.EFCore;
//using IRaCIS.Core.Infrastructure.Extention;
//using Microsoft.AspNetCore.Mvc;
//using Microsoft.AspNetCore.Mvc.Filters;
//using Microsoft.Extensions.Logging;
//using Newtonsoft.Json;
//namespace IRaCIS.Core.Application.Filter
//{
// [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
// public class LogFilter : Attribute
// {
// }
// public class LogActionFilter : IAsyncActionFilter
// {
// private readonly ILogService _logService;
// private readonly IUserInfo _userInfo;
// private readonly ILogger<LogActionFilter> _logger;
// public LogActionFilter(ILogService logService, IUserInfo userInfo , ILogger<LogActionFilter> logger)
// {
// _logService = logService;
// _userInfo = userInfo;
// _logger = logger;
// }
// public Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
// {
// if (context.ActionDescriptor.EndpointMetadata!=null&& context.ActionDescriptor.EndpointMetadata.Any(m => m.GetType() == typeof(LogFilter)))
// {
// return LogAsync(context, next);
// }
// return next();
// }
// public async Task LogAsync(ActionExecutingContext context, ActionExecutionDelegate next)
// {
// var sw = new Stopwatch();
// sw.Start();
// dynamic actionResult = (await next()).Result;
// sw.Stop();
// var args = JsonConvert.SerializeObject(context.ActionArguments);
// var result = JsonConvert.SerializeObject(actionResult?.Value);
// var attr = (ApiExplorerSettingsAttribute)context.ActionDescriptor.EndpointMetadata.FirstOrDefault(m => m.GetType() == typeof(ApiExplorerSettingsAttribute));
// var groupName = attr?.GroupName;
// var res = actionResult?.Value as IResponseOutput;
// var input = new SystemLogDTO
// {
// ClientIP = string.Empty,
// OptUserId = _userInfo.Id,
// OptUserName = _userInfo.UserName,
// ApiPath = context.ActionDescriptor.AttributeRouteInfo.Template.ToLower(),
// Params = args,
// Result = result,
// RequestTime = DateTime.Now,
// ElapsedMilliseconds = sw.ElapsedMilliseconds,
// Status =res?.IsSuccess?? false,
// Message = res?.ErrorMessage,
// LogCategory = groupName
// };
// try
// {
// _logService.SaveLog2Db(input);
// }
// catch (Exception ex)
// {
// _logger.LogError(ex.Message);
// }
// }
// }
//}

File diff suppressed because it is too large Load Diff

View File

@ -14,40 +14,6 @@ namespace IRaCIS.Core.Application.Helper;
public static class FileStoreHelper public static class FileStoreHelper
{ {
public static string UploadOOS(string filePath,string route)
{
var endpoint = ConfigurationManager.AppSettings["AliyunOSS:endpoint"];
// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1杭州为例Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
// 阿里云账号AccessKey拥有所有API的访问权限风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维请登录RAM控制台创建RAM用户。
var accessKeyId = ConfigurationManager.AppSettings["AliyunOSS:accessKeyId"];
var accessKeySecret = ConfigurationManager.AppSettings["AliyunOSS:accessKeySecret"];
// 填写Bucket名称例如examplebucket。
var bucketName = ConfigurationManager.AppSettings["AliyunOSS:bucketName"];
// 填写Object完整路径完整路径中不能包含Bucket名称例如exampledir/exampleobject.txt。
var fileNameList = filePath.Split(',').ToList();
var fileName = fileNameList[fileNameList.Count - 1];
var objectName = route+ fileName;
// 填写本地文件完整路径例如D:\\localpath\\examplefile.txt。如果未指定本地路径则默认从示例程序所属项目对应本地路径中上传文件。
var localFilename = filePath;
// 创建OSSClient实例。
var client = new OssClient(endpoint, accessKeyId, accessKeySecret);
try
{
// 上传文件。
var result = client.PutObject(bucketName, objectName, localFilename);
return result.ETag;
}
catch (Exception ex)
{
throw new BusinessValidationFailedException("上传异常!");
}
}
//处理文件名 压缩包,或者目录类的 会带上相对路径 //处理文件名 压缩包,或者目录类的 会带上相对路径
public static (string TrustedFileNameForFileStorage, string RealName) GetStoreFileName(string fileName,bool isChangeToPdfFormat=false) public static (string TrustedFileNameForFileStorage, string RealName) GetStoreFileName(string fileName,bool isChangeToPdfFormat=false)
{ {

View File

@ -104,11 +104,11 @@ namespace IRaCIS.Core.Application.Helper
public OSSService(IOptionsMonitor<AliyunOSSOptions> options) public OSSService(IOptionsMonitor<ObjectStoreServiceOptions> options)
{ {
var ossOptions = options.CurrentValue; var ossOptions = options.CurrentValue;
_OSSConfig = ossOptions; _OSSConfig = ossOptions.AliyunOSS;
_ossClient = new OssClient(_OSSConfig.endPoint, _OSSConfig.accessKeyId, _OSSConfig.accessKeySecret); _ossClient = new OssClient(_OSSConfig.endPoint, _OSSConfig.accessKeyId, _OSSConfig.accessKeySecret);

View File

@ -65,18 +65,18 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.13.0" /> <PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.13.0" />
<PackageReference Include="FreeSpire.Doc" Version="11.6.0" /> <PackageReference Include="FreeSpire.Doc" Version="11.6.0" />
<PackageReference Include="Hangfire.Core" Version="1.8.5" /> <PackageReference Include="Hangfire.Core" Version="1.8.6" />
<PackageReference Include="BeetleX.BNR" Version="1.0.1" /> <PackageReference Include="BeetleX.BNR" Version="1.0.1" />
<PackageReference Include="Castle.Core.AsyncInterceptor" Version="2.1.0" /> <PackageReference Include="Castle.Core.AsyncInterceptor" Version="2.1.0" />
<PackageReference Include="EasyCaching.Redis" Version="1.9.1" /> <PackageReference Include="EasyCaching.Redis" Version="1.9.2" />
<PackageReference Include="EasyCaching.InMemory" Version="1.9.1" /> <PackageReference Include="EasyCaching.InMemory" Version="1.9.2" />
<PackageReference Include="ExcelDataReader" Version="3.6.0" /> <PackageReference Include="ExcelDataReader" Version="3.6.0" />
<PackageReference Include="ExcelDataReader.DataSet" Version="3.6.0" /> <PackageReference Include="ExcelDataReader.DataSet" Version="3.6.0" />
<PackageReference Include="DistributedLock.Redis" Version="1.0.2" /> <PackageReference Include="DistributedLock.Redis" Version="1.0.2" />
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.3" /> <PackageReference Include="DistributedLock.SqlServer" Version="1.0.3" />
<PackageReference Include="fo-dicom" Version="5.1.1" /> <PackageReference Include="fo-dicom" Version="5.1.1" />
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.1.0" /> <PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.1.0" />
<PackageReference Include="fo-dicom.Codecs" Version="5.10.8" /> <PackageReference Include="fo-dicom.Codecs" Version="5.11.0" />
<PackageReference Include="Magicodes.IE.Core" Version="2.7.4.5" /> <PackageReference Include="Magicodes.IE.Core" Version="2.7.4.5" />
<PackageReference Include="Magicodes.IE.Csv" Version="2.7.4.5"> <PackageReference Include="Magicodes.IE.Csv" Version="2.7.4.5">
<TreatAsUsed>true</TreatAsUsed> <TreatAsUsed>true</TreatAsUsed>
@ -85,9 +85,9 @@
<TreatAsUsed>true</TreatAsUsed> <TreatAsUsed>true</TreatAsUsed>
</PackageReference> </PackageReference>
<PackageReference Include="Magicodes.IE.Excel.AspNetCore" Version="2.7.4.5" /> <PackageReference Include="Magicodes.IE.Excel.AspNetCore" Version="2.7.4.5" />
<PackageReference Include="MailKit" Version="4.2.0" /> <PackageReference Include="MailKit" Version="4.3.0" />
<PackageReference Include="MediatR" Version="12.1.1" /> <PackageReference Include="MediatR" Version="12.2.0" />
<PackageReference Include="MimeKit" Version="4.2.0" /> <PackageReference Include="MimeKit" Version="4.3.0" />
<PackageReference Include="MiniExcel" Version="1.31.2" /> <PackageReference Include="MiniExcel" Version="1.31.2" />
<PackageReference Include="Minio" Version="6.0.1" /> <PackageReference Include="Minio" Version="6.0.1" />
<PackageReference Include="MiniWord" Version="0.7.0" /> <PackageReference Include="MiniWord" Version="0.7.0" />
@ -96,8 +96,8 @@
</PackageReference> </PackageReference>
<PackageReference Include="NPOI" Version="2.6.2" /> <PackageReference Include="NPOI" Version="2.6.2" />
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.1" /> <PackageReference Include="Panda.DynamicWebApi" Version="1.2.1" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.0.2" /> <PackageReference Include="SixLabors.ImageSharp" Version="3.1.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="7.0.11" /> <PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="7.0.12" />
<PackageReference Include="WinSCP" Version="6.1.2" /> <PackageReference Include="WinSCP" Version="6.1.2" />
</ItemGroup> </ItemGroup>

View File

@ -12012,7 +12012,7 @@
构造函数注入 构造函数注入
</summary> </summary>
</member> </member>
<member name="M:IRaCIS.Core.Application.MediatR.Handlers.ConsistencyVerificationHandler.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomStudy},IRaCIS.Core.Domain.Share.IUserInfo,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Subject},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialSite},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudy},AutoMapper.IMapper)"> <member name="M:IRaCIS.Core.Application.MediatR.Handlers.ConsistencyVerificationHandler.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomStudy},IRaCIS.Core.Domain.Share.IUserInfo,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Subject},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialSite},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudy},AutoMapper.IMapper,Microsoft.Extensions.Localization.IStringLocalizer)">
<summary> <summary>
构造函数注入 构造函数注入
</summary> </summary>

View File

@ -23,9 +23,9 @@ namespace IRaCIS.Application.Services
public async Task<ResearchPublicationDTO> GetResearchPublication(Guid doctorId) public async Task<ResearchPublicationDTO> GetResearchPublication(Guid doctorId)
{ {
var doctorScientificResearchInfo = await researchPublicationRepository.Where(o => o.DoctorId == doctorId) var doctorScientificResearchInfo = await researchPublicationRepository.Where(o => o.DoctorId == doctorId)
.ProjectTo<ResearchPublicationDTO>(_mapper.ConfigurationProvider).FirstNotNullAsync(); .ProjectTo<ResearchPublicationDTO>(_mapper.ConfigurationProvider).FirstOrDefaultAsync();
return doctorScientificResearchInfo; return doctorScientificResearchInfo!;
} }

View File

@ -357,7 +357,6 @@ namespace IRaCIS.Core.Application.Service.Inspection.DTO
public class GetDataInspectionOutDto : DataInspection public class GetDataInspectionOutDto : DataInspection
{ {
public Guid? TrialReadingCriterionId { get; set; }
public string TrialReadingCriterionName { get; set; } public string TrialReadingCriterionName { get; set; }
public string BlindName { get; set; } public string BlindName { get; set; }
@ -371,9 +370,6 @@ namespace IRaCIS.Core.Application.Service.Inspection.DTO
//public string ParentJson { get; set; } = string.Empty; //public string ParentJson { get; set; } = string.Empty;
public string CreateUserRealName { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty; public string Description { get; set; } = string.Empty;
public string DescriptionCN { get; set; } = string.Empty; public string DescriptionCN { get; set; } = string.Empty;

View File

@ -9,7 +9,6 @@ namespace IRaCIS.Core.Application.Contracts
/// <summary> UserTypeRoleView 列表视图模型 </summary> /// <summary> UserTypeRoleView 列表视图模型 </summary>
public class UserTypeRoleView : UserTypeMenuAddOrEdit public class UserTypeRoleView : UserTypeMenuAddOrEdit
{ {
public UserTypeEnum UserTypeEnum { get; set; }
public List<UserTypeGroupInfo> UserTypeGroupList { get; set; } = new List<UserTypeGroupInfo>(); public List<UserTypeGroupInfo> UserTypeGroupList { get; set; } = new List<UserTypeGroupInfo>();
public new List<Guid> UserTypeGroupIdList => UserTypeGroupList.Select(t => t.DictionaryId).ToList(); public new List<Guid> UserTypeGroupIdList => UserTypeGroupList.Select(t => t.DictionaryId).ToList();

View File

@ -12,6 +12,7 @@ using Microsoft.Identity.Client;
using static IRaCIS.Core.Domain.Share.StaticData; using static IRaCIS.Core.Domain.Share.StaticData;
using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Application.ViewModel;
using Medallion.Threading; using Medallion.Threading;
using EasyCaching.Core;
namespace IRaCIS.Application.Services namespace IRaCIS.Application.Services
{ {
@ -26,7 +27,7 @@ namespace IRaCIS.Application.Services
private readonly IRepository<UserLog> _userLogRepository; private readonly IRepository<UserLog> _userLogRepository;
private readonly IDistributedLockProvider _distributedLockProvider; private readonly IDistributedLockProvider _distributedLockProvider;
private readonly IMemoryCache _cache; private readonly IEasyCachingProvider _cache;
private readonly IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig; private readonly IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig;
@ -36,7 +37,7 @@ namespace IRaCIS.Application.Services
IMailVerificationService mailVerificationService, IMailVerificationService mailVerificationService,
IRepository<VerificationCode> verificationCodeRepository, IRepository<VerificationCode> verificationCodeRepository,
IRepository<Doctor> doctorRepository, IRepository<Doctor> doctorRepository,
IMemoryCache cache, IEasyCachingProvider cache,
IRepository<TrialUser> userTrialRepository, IRepository<TrialUser> userTrialRepository,
IOptionsMonitor<ServiceVerifyConfigOption> verifyConfig, IOptionsMonitor<ServiceVerifyConfigOption> verifyConfig,
IRepository<UserLog> userLogRepository IRepository<UserLog> userLogRepository
@ -281,7 +282,7 @@ namespace IRaCIS.Application.Services
{ {
await _mailVerificationService.AdminResetPwdSendEmailAsync(userId, pwd); await _mailVerificationService.AdminResetPwdSendEmailAsync(userId, pwd);
} }
catch (Exception ex) catch (Exception )
{ {
//---请检查邮箱地址或者联系维护人员, 邮件发送失败, 未能创建账户成功 //---请检查邮箱地址或者联系维护人员, 邮件发送失败, 未能创建账户成功
throw new BusinessValidationFailedException(_localizer["User_CreateFailed"]); throw new BusinessValidationFailedException(_localizer["User_CreateFailed"]);
@ -631,7 +632,7 @@ namespace IRaCIS.Application.Services
string cacheKey = $"{cachePrefix}{userName}"; string cacheKey = $"{cachePrefix}{userName}";
// 从缓存中获取登录失败次数 // 从缓存中获取登录失败次数
int? failCount = _cache.Get<int?>(cacheKey); int? failCount = _cache.Get<int?>(cacheKey).Value;
if (failCount == null) if (failCount == null)
{ {

View File

@ -476,7 +476,7 @@ namespace IRaCIS.Core.Application.Contracts.DTO
{ {
return JsonConvert.DeserializeObject<List<ParamInfoDto>>(ParamInfo); return JsonConvert.DeserializeObject<List<ParamInfoDto>>(ParamInfo);
} }
catch (Exception e) catch (Exception )
{ {
return new List<ParamInfoDto>(); return new List<ParamInfoDto>();

View File

@ -711,7 +711,6 @@ namespace IRaCIS.Core.Application.Contracts
public string RequestReReadingReason { get; set; } = string.Empty; public string RequestReReadingReason { get; set; } = string.Empty;
public DateTime? SuggesteFinishedTime { get; set; }
[DictionaryTranslateAttribute("RequestReReadingResult")] [DictionaryTranslateAttribute("RequestReReadingResult")]
public RequestReReadingResult RequestReReadingResultEnum { get; set; } public RequestReReadingResult RequestReReadingResultEnum { get; set; }

View File

@ -10,7 +10,7 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
{ {
public class ReadingPeriodSetAddOrEdit public class ReadingPeriodSetAddOrEdit
{ {
public new Guid? Id { get; set; } public Guid? Id { get; set; }
/// <summary> /// <summary>
/// 项目ID /// 项目ID

View File

@ -62,12 +62,10 @@ namespace IRaCIS.Application.Services
private readonly IRepository<NoneDicomStudyFile> _noneDicomStudyFileSystem; private readonly IRepository<NoneDicomStudyFile> _noneDicomStudyFileSystem;
private readonly IRepository<ReadingQuestionTrial> _readingQuestionTrialRepository; private readonly IRepository<ReadingQuestionTrial> _readingQuestionTrialRepository;
private readonly IMemoryCache _cache;
private readonly ITrialEmailNoticeConfigService _trialEmailNoticeConfigService; private readonly ITrialEmailNoticeConfigService _trialEmailNoticeConfigService;
public ReadingImageTaskService( public ReadingImageTaskService(
IMapper mapper,
IRepository<NoneDicomStudy> noneDicomStudyRepository, IRepository<NoneDicomStudy> noneDicomStudyRepository,
IRepository<VisitTask> visitTaskRepository, IRepository<VisitTask> visitTaskRepository,
IRepository<Trial> TrialRepository, IRepository<Trial> TrialRepository,
@ -90,8 +88,7 @@ namespace IRaCIS.Application.Services
IRepository<User> userRepository, IRepository<User> userRepository,
IEasyCachingProvider provider, IEasyCachingProvider provider,
IRepository<ReadingCustomTag> readingCustomTagRepository, IRepository<ReadingCustomTag> readingCustomTagRepository,
IRepository<ReadingTaskQuestionMark> readingTaskQuestionMarkRepository, IRepository<ReadingTaskQuestionMark> readingTaskQuestionMarkRepository,
IMemoryCache cache,
IRepository<ReadingSystemCriterionDictionary> readingCriterionDictionaryRepository, IRepository<ReadingSystemCriterionDictionary> readingCriterionDictionaryRepository,
IRepository<ReadingTrialCriterionDictionary> readingTrialCriterionDictionaryRepository, IRepository<ReadingTrialCriterionDictionary> readingTrialCriterionDictionaryRepository,
IRepository<TumorAssessment_RECIST1Point1> tumorAssessmentRepository, IRepository<TumorAssessment_RECIST1Point1> tumorAssessmentRepository,
@ -107,7 +104,6 @@ namespace IRaCIS.Application.Services
IRepository<ReadingQuestionTrial> readingQuestionTrialRepository IRepository<ReadingQuestionTrial> readingQuestionTrialRepository
) )
{ {
base._mapper = mapper;
this._noneDicomStudyRepository = noneDicomStudyRepository; this._noneDicomStudyRepository = noneDicomStudyRepository;
this._visitTaskRepository = visitTaskRepository; this._visitTaskRepository = visitTaskRepository;
this._trialRepository = TrialRepository; this._trialRepository = TrialRepository;
@ -144,7 +140,6 @@ namespace IRaCIS.Application.Services
this._readingQuestionSystem = ReadingQuestionSystem; this._readingQuestionSystem = ReadingQuestionSystem;
this._noneDicomStudyFileSystem = noneDicomStudyFileSystem; this._noneDicomStudyFileSystem = noneDicomStudyFileSystem;
this._readingQuestionTrialRepository = readingQuestionTrialRepository; this._readingQuestionTrialRepository = readingQuestionTrialRepository;
this._cache = cache;
this._trialEmailNoticeConfigService = trialEmailNoticeConfigService; this._trialEmailNoticeConfigService = trialEmailNoticeConfigService;
} }

View File

@ -348,7 +348,6 @@ namespace IRaCIS.Core.Application.Services
/// <summary>删除 项目 下某一site </summary> /// <summary>删除 项目 下某一site </summary>
[HttpDelete("{id:guid}/{trialId:guid}")] [HttpDelete("{id:guid}/{trialId:guid}")]
[TrialAudit(AuditType.TrialAudit, AuditOptType.DeleteTrialSite)]
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
[Obsolete] [Obsolete]
public async Task<IResponseOutput> DeleteTrialSite(Guid id) public async Task<IResponseOutput> DeleteTrialSite(Guid id)

View File

@ -26,7 +26,6 @@ namespace IRaCIS.Application.Services
/// <param name="subjectCommand">state:1-访视中2-出组。0-全部</param> /// <param name="subjectCommand">state:1-访视中2-出组。0-全部</param>
/// <returns></returns> /// <returns></returns>
[TrialAudit(AuditType.SubjectAudit, AuditOptType.AddOrUpdateSubject)]
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
//[Authorize(Policy = IRaCISPolicy.PM_APM_CRC_QC)] //[Authorize(Policy = IRaCISPolicy.PM_APM_CRC_QC)]
public async Task<IResponseOutput<string>> AddOrUpdateSubject([FromBody] SubjectCommand subjectCommand) public async Task<IResponseOutput<string>> AddOrUpdateSubject([FromBody] SubjectCommand subjectCommand)

View File

@ -1,6 +1,7 @@
using EntityFrameworkCore.Triggered; using EntityFrameworkCore.Triggered;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Infrastructure;
using Microsoft.Extensions.Localization;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -11,18 +12,19 @@ namespace IRaCIS.Core.Application.Triggers
{ {
// 统一处理 外部用户、中心调研(先添加 再发送邮件)、参与医生加入到项目 ----废弃 // 统一处理 外部用户、中心调研(先添加 再发送邮件)、参与医生加入到项目 ----废弃
public class AddlTrialUserTrigger :BaseService, IBeforeSaveTrigger<TrialUser> public class AddlTrialUserTrigger :IBeforeSaveTrigger<TrialUser>
{ {
public IStringLocalizer _localizer;
private readonly IRepository<Trial> _trialRepository; private readonly IRepository<Trial> _trialRepository;
private readonly IRepository<User> _userRepository; private readonly IRepository<User> _userRepository;
public AddlTrialUserTrigger(IRepository<Trial> trialRepository, IRepository<User> userRepository) public AddlTrialUserTrigger(IRepository<Trial> trialRepository, IRepository<User> userRepository, IStringLocalizer localizer)
{ {
_trialRepository = trialRepository; _trialRepository = trialRepository;
_userRepository = userRepository; _userRepository = userRepository;
_localizer = localizer;
} }
public async Task BeforeSave(ITriggerContext<TrialUser> context, CancellationToken cancellationToken) public async Task BeforeSave(ITriggerContext<TrialUser> context, CancellationToken cancellationToken)
{ {

View File

@ -1,20 +1,26 @@
using AutoMapper; using AutoMapper;
using EntityFrameworkCore.Triggered; using EntityFrameworkCore.Triggered;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Infrastructure;
using MassTransit; using MassTransit;
using Microsoft.Extensions.Localization;
namespace IRaCIS.Core.Application.Triggers namespace IRaCIS.Core.Application.Triggers
{ {
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
public class SubjectStateTrigger :BaseService, IAfterSaveTrigger<Subject> public class SubjectStateTrigger : IAfterSaveTrigger<Subject>
{ {
public IStringLocalizer _localizer;
private readonly IRepository _repository;
private readonly IRepository<SubjectVisit> _subjectVisitRepository; private readonly IRepository<SubjectVisit> _subjectVisitRepository;
public SubjectStateTrigger(IRepository<SubjectVisit> subjectVisitRepository) public SubjectStateTrigger(IRepository<SubjectVisit> subjectVisitRepository, IStringLocalizer localizer, IRepository repository)
{ {
_repository = repository;
_localizer = localizer;
_subjectVisitRepository = subjectVisitRepository; _subjectVisitRepository = subjectVisitRepository;
} }

View File

@ -2,15 +2,17 @@
using IRaCIS.Core.Application.Service; using IRaCIS.Core.Application.Service;
using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Infrastructure;
using MassTransit; using MassTransit;
using Microsoft.Extensions.Localization;
namespace IRaCIS.Core.Application.Triggers namespace IRaCIS.Core.Application.Triggers
{ {
/// <summary> /// <summary>
/// 处理 访视 末次评估 会影响Subject 状态 /// 处理 访视 末次评估 会影响Subject 状态
/// </summary> /// </summary>
public class SubjectVisitFinalVisitTrigger :BaseService, IAfterSaveTrigger<SubjectVisit> public class SubjectVisitFinalVisitTrigger :IAfterSaveTrigger<SubjectVisit>
{ {
private readonly IRepository<SubjectVisit> _subjectVisitRepository; private readonly IRepository<SubjectVisit> _subjectVisitRepository;
private readonly IRepository<ReadingPeriodSet> _readingPeriodSetRepository; private readonly IRepository<ReadingPeriodSet> _readingPeriodSetRepository;
@ -19,7 +21,8 @@ namespace IRaCIS.Core.Application.Triggers
private readonly IRepository<Subject> _subjectRepository; private readonly IRepository<Subject> _subjectRepository;
private readonly IRepository<VisitTask> _visitTaskRepository; private readonly IRepository<VisitTask> _visitTaskRepository;
private readonly IVisitTaskHelpeService _ivisitTaskHelpeService; private readonly IVisitTaskHelpeService _ivisitTaskHelpeService;
public IStringLocalizer _localizer;
private readonly IRepository _repository;
public SubjectVisitFinalVisitTrigger(IRepository<SubjectVisit> subjectVisitRepository, public SubjectVisitFinalVisitTrigger(IRepository<SubjectVisit> subjectVisitRepository,
IRepository<ReadingPeriodSet> readingPeriodSetRepository, IRepository<ReadingPeriodSet> readingPeriodSetRepository,
@ -27,7 +30,9 @@ namespace IRaCIS.Core.Application.Triggers
IRepository<VisitTask> visitTaskRepository, IRepository<VisitTask> visitTaskRepository,
IVisitTaskHelpeService visitTaskHelpeService, IVisitTaskHelpeService visitTaskHelpeService,
IRepository<ReadModule> readModuleRepository, IRepository<ReadModule> readModuleRepository,
IRepository<Subject> subjectRepository) IRepository<Subject> subjectRepository,
IStringLocalizer localizer,
IRepository repository)
{ {
_subjectVisitRepository = subjectVisitRepository; _subjectVisitRepository = subjectVisitRepository;
this._readingPeriodSetRepository = readingPeriodSetRepository; this._readingPeriodSetRepository = readingPeriodSetRepository;
@ -36,6 +41,8 @@ namespace IRaCIS.Core.Application.Triggers
this._readingPeriodPlanRepository = readingPeriodPlanRepository; this._readingPeriodPlanRepository = readingPeriodPlanRepository;
this._readModuleRepository = readModuleRepository; this._readModuleRepository = readModuleRepository;
_subjectRepository = subjectRepository; _subjectRepository = subjectRepository;
_repository = repository;
_localizer = localizer;
} }
public async Task AfterSave(ITriggerContext<SubjectVisit> context, CancellationToken cancellationToken) public async Task AfterSave(ITriggerContext<SubjectVisit> context, CancellationToken cancellationToken)

View File

@ -5,6 +5,7 @@ using Newtonsoft.Json;
using MediatR; using MediatR;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Text; using System.Text;
using Microsoft.Extensions.Localization;
namespace IRaCIS.Core.Application.MediatR.Handlers namespace IRaCIS.Core.Application.MediatR.Handlers
{ {
@ -17,6 +18,7 @@ namespace IRaCIS.Core.Application.MediatR.Handlers
private readonly IRepository<TrialSite> _trialSiteRepository; private readonly IRepository<TrialSite> _trialSiteRepository;
private readonly IMapper _mapper; private readonly IMapper _mapper;
private readonly IRepository<NoneDicomStudy> _noneDicomStudyRepository; private readonly IRepository<NoneDicomStudy> _noneDicomStudyRepository;
public IStringLocalizer _localizer { get; set; }
/// <summary> /// <summary>
/// 构造函数注入 /// 构造函数注入
@ -25,7 +27,7 @@ namespace IRaCIS.Core.Application.MediatR.Handlers
public ConsistencyVerificationHandler(IRepository<DicomStudy> studyRepository, IUserInfo userInfo, public ConsistencyVerificationHandler(IRepository<DicomStudy> studyRepository, IUserInfo userInfo,
IRepository<Subject> subjectRepository, IRepository<SubjectVisit> subjectVisitRepository, IRepository<Subject> subjectRepository, IRepository<SubjectVisit> subjectVisitRepository,
IRepository<TrialSite> trialSiteRepository, IRepository<NoneDicomStudy> noneDicomStudyRepository, IRepository<TrialSite> trialSiteRepository, IRepository<NoneDicomStudy> noneDicomStudyRepository,
IMapper mapper) IMapper mapper, IStringLocalizer localizer)
{ {
_noneDicomStudyRepository = noneDicomStudyRepository; _noneDicomStudyRepository = noneDicomStudyRepository;
_studyRepository = studyRepository; _studyRepository = studyRepository;
@ -34,6 +36,7 @@ namespace IRaCIS.Core.Application.MediatR.Handlers
_subjectVisitRepository = subjectVisitRepository; _subjectVisitRepository = subjectVisitRepository;
_trialSiteRepository = trialSiteRepository; _trialSiteRepository = trialSiteRepository;
_mapper = mapper; _mapper = mapper;
_localizer = localizer;
} }
async Task<string> IRequestHandler<ConsistencyVerificationRequest, string>.Handle(ConsistencyVerificationRequest request, CancellationToken cancellationToken) async Task<string> IRequestHandler<ConsistencyVerificationRequest, string>.Handle(ConsistencyVerificationRequest request, CancellationToken cancellationToken)
@ -113,7 +116,7 @@ namespace IRaCIS.Core.Application.MediatR.Handlers
StringBuilder dialogMsg = new StringBuilder(); StringBuilder dialogMsg = new StringBuilder();
//---您好,根据本系统自动识别该受试者当前访视在IRC系统中已提交的影像检查情况如下 //---您好,根据本系统自动识别该受试者当前访视在IRC系统中已提交的影像检查情况如下
dialogMsg.Append($"<div>{StaticData.International("ConsistencyVerification_Img")}</div>"); dialogMsg.Append($"<div>{_localizer["ConsistencyVerification_Img"]}</div>");
var num = 0; var num = 0;
List<ParamInfoDto> paramInfoList = new List<ParamInfoDto>(); List<ParamInfoDto> paramInfoList = new List<ParamInfoDto>();
@ -121,16 +124,8 @@ namespace IRaCIS.Core.Application.MediatR.Handlers
{ {
num++; num++;
if (_userInfo.IsEn_Us) dialogMsg.AppendLine($"<br/><div style='text-indent: 20px;'>{num}. {_localizer["ConsistencyVerification_ImgC", item.StudyDate, item.Modality]}</div>");
{
dialogMsg.AppendLine($"<br/><div style='text-indent: 20px;'>{num}. {item.StudyDate} {item.Modality} {StaticData.International("ConsistencyVerification_ImgC")}</div>");
}
else
{
dialogMsg.AppendLine($"<br/><div style='text-indent: 20px;'>{num}. {item.StudyDate} {StaticData.International("ConsistencyVerification_Of")}{item.Modality}{StaticData.International("ConsistencyVerification_ImgC")}</div>");
}
paramInfoList.Add(new ParamInfoDto() paramInfoList.Add(new ParamInfoDto()
{ {
@ -189,7 +184,7 @@ namespace IRaCIS.Core.Application.MediatR.Handlers
{ {
dialogMsg.AppendLine($"<br/>"); dialogMsg.AppendLine($"<br/>");
//---核对EDC数据完全一致, 审核通过 //---核对EDC数据完全一致, 审核通过
dialogMsg.AppendLine(StaticData.International("ConsistencyVerification_EDCA")); dialogMsg.AppendLine(_localizer["ConsistencyVerification_EDCA"]);
// dialogMsg.AppendLine(@$"<br>说明:为高效解决/处理以上全部质疑问题麻烦您准确核实实际影像检查情况。请注意影像日期与实际检查的日期可能会不一致部分检查如PET -CT)可能同时存在多种模态影像。准确核实后,请回复该访视正确的影像检查情况。"); // dialogMsg.AppendLine(@$"<br>说明:为高效解决/处理以上全部质疑问题麻烦您准确核实实际影像检查情况。请注意影像日期与实际检查的日期可能会不一致部分检查如PET -CT)可能同时存在多种模态影像。准确核实后,请回复该访视正确的影像检查情况。");
@ -197,9 +192,9 @@ namespace IRaCIS.Core.Application.MediatR.Handlers
dbSV.CheckUserId = _userInfo.Id; dbSV.CheckUserId = _userInfo.Id;
dbSV.CheckPassedTime = DateTime.Now; dbSV.CheckPassedTime = DateTime.Now;
//---核对EDC数据完全一致 //---核对EDC数据完全一致
dbSV.CheckResult = StaticData.International("ConsistencyVerification_EDCB"); dbSV.CheckResult = _localizer["ConsistencyVerification_EDCB"];
//---自动核查通过 //---自动核查通过
dbSV.ManualPassReason = StaticData.International("ConsistencyVerification_Auto"); dbSV.ManualPassReason = _localizer["ConsistencyVerification_Auto"];
//维护状态 //维护状态
dbSV.ReadingStatus = ReadingStatusEnum.TaskAllocate; dbSV.ReadingStatus = ReadingStatusEnum.TaskAllocate;
@ -218,55 +213,33 @@ namespace IRaCIS.Core.Application.MediatR.Handlers
else else
{ {
//"Problems are as follows: //"Problems are as follows:
dialogMsg.AppendLine($"<br/><div style='color: #f00'>{StaticData.International("ConsistencyVerification_Prob")}</div>"); dialogMsg.AppendLine($"<br/><div style='color: #f00'>{_localizer["ConsistencyVerification_Prob"]}</div>");
num = 0; num = 0;
foreach (var item in dbExceptExcel) foreach (var item in dbExceptExcel)
{ {
num++; num++;
//影像检查(EDC 缺少) ConsistencyVerification_EdcL //影像检查(EDC 缺少) ConsistencyVerification_EdcL
dialogMsg.AppendLine($"<br/><div style='text-indent: 20px;'>{num}. {_localizer["ConsistencyVerification_EdcL", item.StudyDate, item.Modality]}</div>");
if (_userInfo.IsEn_Us)
{
dialogMsg.AppendLine($"<br/><div style='text-indent: 20px;'>{num}. {item.StudyDate} {item.Modality} {StaticData.International("ConsistencyVerification_ImgC")} {StaticData.International("ConsistencyVerification_EdcL")} </div>");
}
else
{
dialogMsg.AppendLine($"<br/><div style='text-indent: 20px;'>{num}. {StaticData.International("ConsistencyVerification_EdcL")}{item.StudyDate}{StaticData.International("ConsistencyVerification_Of")}{item.Modality}{StaticData.International("ConsistencyVerification_ImgC")}</div>");
}
} }
foreach (var item in excelExceptDB) foreach (var item in excelExceptDB)
{ {
num++; num++;
// 影像检查(IRC 缺少) // 影像检查(IRC 缺少)
dialogMsg.AppendLine($"<br/><div style='text-indent: 20px;'>{num}. {_localizer["ConsistencyVerification_IrcLi", item.StudyDate, item.Modality]}</div>");
if (_userInfo.IsEn_Us)
{
dialogMsg.AppendLine($"<br/><div style='text-indent: 20px;'>{num}. {item.StudyDate} {item.Modality} {StaticData.International("ConsistencyVerification_ImgC")} {StaticData.International("ConsistencyVerification_IrcL")}</div>");
}
else
{
dialogMsg.AppendLine($"<br/><div style='text-indent: 20px;'>{num}. {StaticData.International("ConsistencyVerification_IrcL")}{item.StudyDate}{StaticData.International("ConsistencyVerification_Of")}{item.Modality}{StaticData.International("ConsistencyVerification_ImgC")}</div>");
}
} }
dialogMsg.AppendLine($"<br/>"); dialogMsg.AppendLine($"<br/>");
dialogMsg.AppendLine(@$"<div>{StaticData.International("ConsistencyVerification_Desc")}<div/>"); dialogMsg.AppendLine(@$"<div>{_localizer["ConsistencyVerification_Desc"]}<div/>");
dbSV.CheckResult = _localizer["ConsistencyVerification_Conf"] +
String.Join(" | ", dbExceptExcel.Select(t => $"{_localizer["ConsistencyVerification_EdcL", t.StudyDate, t.Modality]}")) + " | "
+ String.Join(" | ", excelExceptDB.Select(t => $"{_localizer["ConsistencyVerification_IrcLi", t.StudyDate, t.Modality]}"));
//---根据导入的一致性核查数据,请确认本访视以下不一致检查项信息:
dbSV.CheckResult = StaticData.International("ConsistencyVerification_Conf") + String.Join(" | ", dbExceptExcel.Select(t => $"{StaticData.International("ConsistencyVerification_Edc")}{t.StudyDate} {t.Modality} ")) + " | "
+ String.Join(" | ", excelExceptDB.Select(t => $"{StaticData.International("ConsistencyVerification_IrcLi")}{t.StudyDate} {t.Modality}"));
//新增一致性核查质疑记录 //新增一致性核查质疑记录
dbSV.CheckState = CheckStateEnum.CVIng; dbSV.CheckState = CheckStateEnum.CVIng;
dbSV.CheckChallengeState = CheckChanllengeTypeEnum.PMWaitCRCReply; dbSV.CheckChallengeState = CheckChanllengeTypeEnum.PMWaitCRCReply;

View File

@ -16,8 +16,8 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="EntityFrameworkCore.Projectables.Abstractions" Version="2.3.0" /> <PackageReference Include="EntityFrameworkCore.Projectables.Abstractions" Version="2.3.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.4" /> <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -587,12 +587,12 @@ namespace IRaCIS.Core.Infra.EFCore
throw new DBSaveFailedException("SQL 事务失败,请检查环境。"); throw new DBSaveFailedException("SQL 事务失败,请检查环境。");
} }
catch (Exception ex) //catch (Exception ex)
{ //{
_logger.LogError(ex.InnerException is null ? ex.Message : ex.InnerException?.Message); // _logger.LogError(ex.InnerException is null ? ex.Message : ex.InnerException?.Message);
throw new DBSaveFailedException("数据保存异常。"); // throw new DBSaveFailedException(ex.Message);
} //}
} }

View File

@ -23,8 +23,8 @@
<PackageReference Include="EntityFrameworkCore.Triggered" Version="3.2.2" /> <PackageReference Include="EntityFrameworkCore.Triggered" Version="3.2.2" />
<PackageReference Include="EntityFrameworkCore.Projectables" Version="2.3.0" /> <PackageReference Include="EntityFrameworkCore.Projectables" Version="2.3.0" />
<PackageReference Include="EntityFrameworkCore.Exceptions.SqlServer" Version="6.0.3.2" /> <PackageReference Include="EntityFrameworkCore.Exceptions.SqlServer" Version="6.0.3.2" />
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="7.0.12" /> <PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
<PackageReference Include="NewId" Version="4.0.1" /> <PackageReference Include="NewId" Version="4.0.1" />
</ItemGroup> </ItemGroup>

View File

@ -13,9 +13,9 @@
<PackageReference Include="AutoMapper.Collection.EntityFrameworkCore" Version="9.0.0" /> <PackageReference Include="AutoMapper.Collection.EntityFrameworkCore" Version="9.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.12" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.12" />
<PackageReference Include="SharpCompress" Version="0.34.1" /> <PackageReference Include="SharpCompress" Version="0.34.2" />
<PackageReference Include="SharpZipLib" Version="1.4.2" /> <PackageReference Include="SharpZipLib" Version="1.4.2" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.3.5" /> <PackageReference Include="System.Linq.Dynamic.Core" Version="1.3.7" />
</ItemGroup> </ItemGroup>

View File

@ -14,7 +14,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.12" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.12" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" /> <PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
<PackageReference Include="coverlet.collector" Version="6.0.0"> <PackageReference Include="coverlet.collector" Version="6.0.0">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>