diff --git a/IRC.Core.SCP/HostConfig/EFSetup.cs b/IRC.Core.SCP/HostConfig/EFSetup.cs index 00ee49222..73b279ffc 100644 --- a/IRC.Core.SCP/HostConfig/EFSetup.cs +++ b/IRC.Core.SCP/HostConfig/EFSetup.cs @@ -4,6 +4,7 @@ using IRaCIS.Core.Infra.EFCore; using Medallion.Threading; using Medallion.Threading.SqlServer; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -15,11 +16,12 @@ namespace IRaCIS.Core.SCP { services.AddHttpContextAccessor(); services.AddScoped(); + services.AddScoped(); + - //这个注入没有成功--注入是没问题的,构造函数也只是支持参数就好,错在注入的地方不能写DbContext //Web程序中通过重用池中DbContext实例可提高高并发场景下的吞吐量, 这在概念上类似于ADO.NET Provider原生的连接池操作方式,具有节省DbContext实例化成本的优点 - services.AddDbContextPool(options => + services.AddDbContextPool((sp, options) => { // 在控制台 //public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); }); @@ -35,6 +37,7 @@ namespace IRaCIS.Core.SCP options.EnableSensitiveDataLogging(); options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor()); + options.AddInterceptors(sp.GetServices()); options.UseProjectables(); diff --git a/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs b/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs index aa4d6a673..40ee6fe3f 100644 --- a/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs +++ b/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs @@ -889,89 +889,6 @@ namespace IRaCIS.Core.API.Controllers - #region 废弃 - - /// - /// 下载多个医生的所有附件 - /// - /// - /// - [Obsolete] - [HttpPost, Route("file/downloadDoctorAttachments")] - public async Task> DownloadAttachment(Guid[] doctorIds) - { - - var path = await _fileService.CreateDoctorsAllAttachmentZip(doctorIds); - - return ResponseOutput.Ok(new UploadFileInfoDTO - { - FilePath = path, - FullFilePath = path + "?access_token=" + HttpContext.Request.Headers["Authorization"].ToString().Substring(7) - - }); - } - - /// - /// 下载指定医生的指定附件 - /// - /// 医生Id - /// 要下载的附件Id - /// - [HttpPost, Route("file/downloadByAttachmentId/{doctorId}")] - [Obsolete] - public async Task> DownloadAttachmentById(Guid doctorId, Guid[] attachmentIds) - { - var path = await _fileService.CreateZipPackageByAttachment(doctorId, attachmentIds); - return ResponseOutput.Ok(new UploadFileInfoDTO - { - FilePath = await _fileService.CreateZipPackageByAttachment(doctorId, attachmentIds), - FullFilePath = path + "?access_token=" + HttpContext.Request.Headers["Authorization"].ToString().Substring(7) - }); - } - - - /// - /// 下载医生官方简历 首页 区分 中文和英文 - /// - /// - /// - /// - [HttpPost, Route("file/downloadOfficialCV/{language}")] - [Obsolete] - public async Task> DownloadOfficialResume(int language, Guid[] doctorIds) - { - - var path = await _fileService.CreateDoctorsAllAttachmentZip(doctorIds); - return ResponseOutput.Ok(new UploadFileInfoDTO - { - FilePath = await _fileService.CreateOfficialResumeZip(language, doctorIds), - FullFilePath = path + "?access_token=" + HttpContext.Request.Headers["Authorization"].ToString().Substring(7) - }); - } - - - - - /// - /// 入组 项目下载简历 - /// - /// - /// - /// - /// - [HttpPost, Route("enroll/downloadResume/{trialId:guid}/{language}")] - [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] - [AllowAnonymous] - [Obsolete] - public async Task> DownloadResume(int language, Guid trialId, Guid[] doctorIdArray) - { - var zipPath = await _fileService.CreateOfficialResumeZip(language, doctorIdArray); - - return ResponseOutput.Ok(zipPath); - } - #endregion - - } #endregion diff --git a/IRaCIS.Core.API/IRaCIS.Core.API.xml b/IRaCIS.Core.API/IRaCIS.Core.API.xml index 726d34a48..d82437315 100644 --- a/IRaCIS.Core.API/IRaCIS.Core.API.xml +++ b/IRaCIS.Core.API/IRaCIS.Core.API.xml @@ -326,38 +326,6 @@ - - - 下载多个医生的所有附件 - - - - - - - 下载指定医生的指定附件 - - 医生Id - 要下载的附件Id - - - - - 下载医生官方简历 首页 区分 中文和英文 - - - - - - - - 入组 项目下载简历 - - - - - - 通用文件下载 diff --git a/IRaCIS.Core.API/Progranm.cs b/IRaCIS.Core.API/Progranm.cs index 40ffb2743..64f3f79a7 100644 --- a/IRaCIS.Core.API/Progranm.cs +++ b/IRaCIS.Core.API/Progranm.cs @@ -29,6 +29,10 @@ using IRaCIS.Core.Application.Service.ImageAndDoc; using IP2Region.Net.Abstractions; using IP2Region.Net.XDB; using IRaCIS.Core.Application.BusinessFilter; +using Microsoft.AspNetCore.Http; +using IRaCIS.Core.Infrastructure.Extention; +using Newtonsoft.Json; +using Microsoft.AspNetCore.Diagnostics; #region 获取环境变量 @@ -117,7 +121,7 @@ builder.Services.AddOptions().Configure(_configuratio builder.Services.AddOptions().Configure(_configuration.GetSection("AliyunOSS")); builder.Services.AddOptions().Configure(_configuration.GetSection("ObjectStoreService")); builder.Services.AddOptions().Configure(_configuration.GetSection("EncrypteResponseConfig")); - +builder.Services.AddOptions().Configure(_configuration.GetSection("SystemPacsConfig")); //动态WebApi + UnifiedApiResultFilter 省掉控制器代码 @@ -164,6 +168,8 @@ builder.Services.AddSingleton(); builder.Services.AddSingleton(new Searcher(CachePolicy.Content, Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources, "ip2region.xdb"))); +//builder.Services.AddExceptionHandler(); +//builder.Services.AddProblemDetails(); #region 历史废弃配置 //builder.Services.AddMemoryCache(); @@ -190,6 +196,56 @@ var env = app.Environment; // Configure the HTTP request pipeline. +#region 异常处理 全局业务异常已统一处理了,非业务错误会来到这里 400 -500状态码 + + +//app.UseStatusCodePagesWithReExecute("/Error/{0}"); + +app.UseStatusCodePages(async context => +{ + var code = context.HttpContext.Response.StatusCode; + context.HttpContext.Response.ContentType = "application/json"; + if (code < 500) + { + await context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk($"Client error, actual request error status code({code})"))); + } + else + { + //ResultFilter 里面的异常并不会到这里 + await context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject((ResponseOutput.NotOk($"Server error , actual request error status code({code})")))); + } + +}); + +//app.UseExceptionHandler(o => { }); + +//这里没生效,原因未知,官方文档也是这种写法,也用了GlobalExceptionHandler 尝试,还是不行,怀疑框架bug +//app.UseExceptionHandler(configure => +//{ +// configure.Run(async context => +// { +// var exceptionHandlerPathFeature = context.Features.Get(); +//var ex = exceptionHandlerPathFeature?.Error; +//context.Response.ContentType = "application/json"; + +//if (ex != null) +//{ +// var errorInfo = $"Exception: {ex.Message}[{ex.StackTrace}]" + (ex.InnerException != null ? $" InnerException: {ex.InnerException.Message}[{ex.InnerException.StackTrace}]" : ""); + +// await context.Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk($"{ex?.Message}"))); + +// Log.Logger.Error(errorInfo); + + +//} + +// }); +//}); + + + +#endregion + //本地化 app.UseLocalization(); @@ -198,12 +254,11 @@ 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(); + //LogDashboard app.UseLogDashboard("/LogDashboard"); @@ -211,22 +266,24 @@ app.UseLogDashboard("/LogDashboard"); //hangfire app.UseHangfireConfig(env); +#region 暂时废弃 +//app.UseMiddleware(); ////限流 中间件 //app.UseIpRateLimiting(); +//if (env.IsDevelopment()) +//{ +// app.UseDeveloperExceptionPage(); +//} +//else +//{ +// //app.UseHsts(); +//} +#endregion + -if (env.IsDevelopment()) -{ - app.UseDeveloperExceptionPage(); -} -else -{ - //app.UseHsts(); -} -// 特殊异常处理 比如 404 -app.UseStatusCodePagesWithReExecute("/Error/{0}"); SwaggerSetup.Configure(app, env); diff --git a/IRaCIS.Core.API/_PipelineExtensions/LocalizationConfig.cs b/IRaCIS.Core.API/_PipelineExtensions/LocalizationConfig.cs index 45ab1ec1f..d94b96b65 100644 --- a/IRaCIS.Core.API/_PipelineExtensions/LocalizationConfig.cs +++ b/IRaCIS.Core.API/_PipelineExtensions/LocalizationConfig.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Builder; +using IRaCIS.Core.Domain.Share; +using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Localization; using System.Collections.Generic; using System.Globalization; @@ -12,8 +13,9 @@ namespace IRaCIS.Core.API { var supportedCultures = new List { - new CultureInfo("en-US"), - new CultureInfo("zh-CN") + + new CultureInfo(StaticData.CultureInfo.en_US), + new CultureInfo(StaticData.CultureInfo.zh_CN) }; var options = new RequestLocalizationOptions diff --git a/IRaCIS.Core.API/_ServiceExtensions/EFSetup.cs b/IRaCIS.Core.API/_ServiceExtensions/EFSetup.cs index 820a2a67e..ae82e3027 100644 --- a/IRaCIS.Core.API/_ServiceExtensions/EFSetup.cs +++ b/IRaCIS.Core.API/_ServiceExtensions/EFSetup.cs @@ -7,6 +7,7 @@ using IRaCIS.Core.Infra.EFCore; using Medallion.Threading; using Medallion.Threading.SqlServer; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -21,12 +22,14 @@ namespace IRaCIS.Core.API services.AddHttpContextAccessor(); services.AddScoped(); + services.AddScoped(); + // First, register a pooling context factory as a Singleton service, as usual: //这个注入没有成功--注入是没问题的,构造函数也只是支持参数就好,错在注入的地方不能写DbContext //Web程序中通过重用池中DbContext实例可提高高并发场景下的吞吐量, 这在概念上类似于ADO.NET Provider原生的连接池操作方式,具有节省DbContext实例化成本的优点 - services.AddDbContext(options => + services.AddDbContext((sp, options) => { // 在控制台 @@ -43,6 +46,7 @@ namespace IRaCIS.Core.API options.EnableSensitiveDataLogging(); options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor()); + options.AddInterceptors(sp.GetServices()); options.UseProjectables(); diff --git a/IRaCIS.Core.API/appsettings.Event_IRC.json b/IRaCIS.Core.API/appsettings.Event_IRC.json index 216571d78..fa5674cb6 100644 --- a/IRaCIS.Core.API/appsettings.Event_IRC.json +++ b/IRaCIS.Core.API/appsettings.Event_IRC.json @@ -47,7 +47,11 @@ "ContinuousReadingTimeMin": 120, - "ReadingRestTimeMin": 10 + "ReadingRestTimeMin": 10, + + "IsNeedChangePassWord": true, + + "ChangePassWordDays": 90 }, "SystemEmailSendConfig": { "Port": 465, diff --git a/IRaCIS.Core.API/appsettings.Prod_IRC.json b/IRaCIS.Core.API/appsettings.Prod_IRC.json index 7b2b1d376..c3dd1e8a2 100644 --- a/IRaCIS.Core.API/appsettings.Prod_IRC.json +++ b/IRaCIS.Core.API/appsettings.Prod_IRC.json @@ -49,8 +49,10 @@ "ContinuousReadingTimeMin": 120, - "ReadingRestTimeMin": 10 + "ReadingRestTimeMin": 10, + "IsNeedChangePassWord": true, + "ChangePassWordDays": 90 }, "SystemEmailSendConfig": { diff --git a/IRaCIS.Core.API/appsettings.Test_IRC.json b/IRaCIS.Core.API/appsettings.Test_IRC.json index c397ac52d..938cbb330 100644 --- a/IRaCIS.Core.API/appsettings.Test_IRC.json +++ b/IRaCIS.Core.API/appsettings.Test_IRC.json @@ -65,7 +65,10 @@ "ContinuousReadingTimeMin": 120, - "ReadingRestTimeMin": 10 + "ReadingRestTimeMin": 10, + "IsNeedChangePassWord": true, + + "ChangePassWordDays": 90 }, "SystemEmailSendConfig": { @@ -82,8 +85,10 @@ "CompanyNameCN": "上海展影医疗科技有限公司", "CompanyShortName": "Extensive Imaging", "CompanyShortNameCN": "展影医疗" + }, + + "SystemPacsConfig": { + "Port": "11113", + "IP": "106.14.89.110" } - - - } diff --git a/IRaCIS.Core.API/appsettings.US_Prod_IRC.json b/IRaCIS.Core.API/appsettings.US_Prod_IRC.json index 0c7ed8158..b2d650a67 100644 --- a/IRaCIS.Core.API/appsettings.US_Prod_IRC.json +++ b/IRaCIS.Core.API/appsettings.US_Prod_IRC.json @@ -63,7 +63,10 @@ "ContinuousReadingTimeMin": 120, - "ReadingRestTimeMin": 10 + "ReadingRestTimeMin": 10, + "IsNeedChangePassWord": true, + + "ChangePassWordDays": 90 }, "SystemEmailSendConfig": { diff --git a/IRaCIS.Core.API/appsettings.US_Test_IRC.json b/IRaCIS.Core.API/appsettings.US_Test_IRC.json index 67d4b1fe7..a0eed7266 100644 --- a/IRaCIS.Core.API/appsettings.US_Test_IRC.json +++ b/IRaCIS.Core.API/appsettings.US_Test_IRC.json @@ -69,7 +69,10 @@ "ContinuousReadingTimeMin": 120, - "ReadingRestTimeMin": 10 + "ReadingRestTimeMin": 10, + "IsNeedChangePassWord": true, + + "ChangePassWordDays": 90 }, "SystemEmailSendConfig": { diff --git a/IRaCIS.Core.API/appsettings.US_Uat_IRC.json b/IRaCIS.Core.API/appsettings.US_Uat_IRC.json index 8697adda1..f16b2410d 100644 --- a/IRaCIS.Core.API/appsettings.US_Uat_IRC.json +++ b/IRaCIS.Core.API/appsettings.US_Uat_IRC.json @@ -62,6 +62,9 @@ "ContinuousReadingTimeMin": 120, "ReadingRestTimeMin": 10, + "IsNeedChangePassWord": true, + + "ChangePassWordDays": 90, "OpenLoginMFA": true }, diff --git a/IRaCIS.Core.API/appsettings.Uat_IRC.json b/IRaCIS.Core.API/appsettings.Uat_IRC.json index 923001d1a..18d24b8ce 100644 --- a/IRaCIS.Core.API/appsettings.Uat_IRC.json +++ b/IRaCIS.Core.API/appsettings.Uat_IRC.json @@ -12,7 +12,7 @@ }, "ObjectStoreService": { - "ObjectStoreUse": "MinIO", + "ObjectStoreUse": "AliyunOSS", "AliyunOSS": { "regionId": "cn-shanghai", @@ -56,7 +56,10 @@ "ContinuousReadingTimeMin": 120, - "ReadingRestTimeMin": 10 + "ReadingRestTimeMin": 10, + "IsNeedChangePassWord": true, + + "ChangePassWordDays": 90 }, "SystemEmailSendConfig": { @@ -72,7 +75,11 @@ "CompanyNameCN": "上海展影医疗科技有限公司", "CompanyShortName": "Extensive Imaging", "CompanyShortNameCN": "展影医疗" + }, + + "SystemPacsConfig": { + "Port": "11113", + "IP": "47.117.164.182" } - } diff --git a/IRaCIS.Core.Application/BaseService.cs b/IRaCIS.Core.Application/BaseService.cs index 9101ffa80..00df0c376 100644 --- a/IRaCIS.Core.Application/BaseService.cs +++ b/IRaCIS.Core.Application/BaseService.cs @@ -8,6 +8,7 @@ using Panda.DynamicWebApi; using Panda.DynamicWebApi.Attributes; using System.Diagnostics.CodeAnalysis; using IRaCIS.Core.Domain.Share; +using Microsoft.AspNetCore.Mvc; namespace IRaCIS.Core.Application { @@ -17,7 +18,8 @@ namespace IRaCIS.Core.Application #region 非泛型版本 - [Authorize, DynamicWebApi, UnifiedApiResultFilter] + [TypeFilter(typeof(UnifiedApiResultFilter))] + [Authorize, DynamicWebApi] public class BaseService : IBaseService, IDynamicWebApi { public IMapper _mapper { get; set; } @@ -83,8 +85,8 @@ namespace IRaCIS.Core.Application } - - [Authorize, DynamicWebApi, UnifiedApiResultFilter] + [TypeFilter(typeof(UnifiedApiResultFilter))] + [Authorize, DynamicWebApi] public class BaseServiceTest : IBaseServiceTest, IDynamicWebApi where T : Entity { public IMapper _mapper { get; set; } diff --git a/IRaCIS.Core.Application/BusinessFilter/GlobalExceptionHandler.cs b/IRaCIS.Core.Application/BusinessFilter/GlobalExceptionHandler.cs new file mode 100644 index 000000000..bdd19c962 --- /dev/null +++ b/IRaCIS.Core.Application/BusinessFilter/GlobalExceptionHandler.cs @@ -0,0 +1,50 @@ +using Microsoft.AspNetCore.Diagnostics; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + + +namespace IRaCIS.Core.Application.BusinessFilter +{ + + /// + /// 不生效,不知道为啥 + /// + public class GlobalExceptionHandler : IExceptionHandler + { + private readonly ILogger _logger; + public GlobalExceptionHandler(ILogger logger) + { + this._logger = logger; + } + public ValueTask TryHandleAsync( + HttpContext httpContext, + Exception exception, + CancellationToken cancellationToken) + { + + + httpContext.Response.ContentType = "application/json"; + + + var ex = exception; + var errorInfo = $"Exception: {ex.Message}[{ex.StackTrace}]" + (ex.InnerException != null ? $" InnerException: {ex.InnerException.Message}[{ex.InnerException.StackTrace}]" : ""); + + httpContext.Response.WriteAsJsonAsync(ResponseOutput.NotOk($"{ex?.Message}")); + + + + + + _logger.LogError(errorInfo); + + // return true to signal that this exception is handled + return ValueTask.FromResult(false); + } + } +} diff --git a/IRaCIS.Core.Application/BusinessFilter/ProjectExceptionFilter.cs b/IRaCIS.Core.Application/BusinessFilter/ProjectExceptionFilter.cs index 5638e52ea..011e9ceae 100644 --- a/IRaCIS.Core.Application/BusinessFilter/ProjectExceptionFilter.cs +++ b/IRaCIS.Core.Application/BusinessFilter/ProjectExceptionFilter.cs @@ -1,4 +1,5 @@ -using IRaCIS.Core.Infrastructure; +using IRaCIS.Core.Domain.Share; +using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Infrastructure.Extention; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; @@ -11,13 +12,13 @@ namespace IRaCIS.Core.Application.Filter { private readonly ILogger _logger; - public IStringLocalizer _localizer; + public IStringLocalizer _localizer; - public ProjectExceptionFilter(IStringLocalizer localizer, ILogger logger) + public ProjectExceptionFilter(IStringLocalizer localizer, ILogger logger) { _logger = logger; - _localizer = localizer; - } + _localizer = localizer; + } public void OnException(ExceptionContext context) { //context.ExceptionHandled;//记录当前这个异常是否已经被处理过了 @@ -26,7 +27,7 @@ namespace IRaCIS.Core.Application.Filter { if (context.Exception.GetType().Name == "DbUpdateConcurrencyException") { - //---并发更新,当前不允许该操作 + //---并发更新,当前不允许该操作 context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ProjectException_ConcurrentUpdateNotAllowed"] + context.Exception.Message)); } @@ -34,28 +35,43 @@ namespace IRaCIS.Core.Application.Filter { var error = context.Exception as BusinessValidationFailedException; - context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, error!.Code)); + var info = string.Empty; + + if (!string.IsNullOrWhiteSpace(error!.LocalizedKey) && StaticData.Log_Locoalize_Dic.ContainsKey(error!.LocalizedKey)) + { + info = $"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}"; + } + + + context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, "", error!.Code, localizedInfo: info)); + + + //warning 级别记录 + //_logger.LogWarning($"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}"); } - else if(context.Exception.GetType() == typeof(QueryBusinessObjectNotExistException)) + else if (context.Exception.GetType() == typeof(QueryBusinessObjectNotExistException)) { - context.Result = new JsonResult(ResponseOutput.NotOk( context.Exception.Message, ApiResponseCodeEnum.DataNotExist)); + context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, ApiResponseCodeEnum.DataNotExist)); } else { 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)); + + _logger.LogError(context.Exception.InnerException is null ? (context.Exception.Message + context.Exception.StackTrace) : (context.Exception.InnerException?.Message + context.Exception.InnerException?.StackTrace)); + } + context.ExceptionHandled = true;//标记当前异常已经被处理过了 - _logger.LogError(context.Exception.InnerException is null ? (context.Exception.Message + context.Exception.StackTrace) : (context.Exception.InnerException?.Message + context.Exception.InnerException?.StackTrace)); + //throw new Exception("test-result-exceptioin"); } else { //继续 } - context.ExceptionHandled = true;//标记当前异常已经被处理过了 } } } diff --git a/IRaCIS.Core.Application/BusinessFilter/UnifiedApiResultFilter.cs b/IRaCIS.Core.Application/BusinessFilter/UnifiedApiResultFilter.cs index 9e5fdf591..3e135e386 100644 --- a/IRaCIS.Core.Application/BusinessFilter/UnifiedApiResultFilter.cs +++ b/IRaCIS.Core.Application/BusinessFilter/UnifiedApiResultFilter.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc; using IRaCIS.Core.Domain.Share; +using Microsoft.Extensions.Logging; namespace IRaCIS.Application.Services.BusinessFilter { @@ -10,6 +11,12 @@ namespace IRaCIS.Application.Services.BusinessFilter /// public class UnifiedApiResultFilter : Attribute, IAsyncResultFilter { + private readonly ILogger _logger; + + public UnifiedApiResultFilter(ILogger logger) + { + _logger = logger; + } /// /// 异步版本 @@ -31,12 +38,11 @@ namespace IRaCIS.Application.Services.BusinessFilter var type = objectResult.Value?.GetType(); - if ( type!=null&& type.IsGenericType&&(type.GetGenericTypeDefinition()==typeof(ValueTuple<,>)|| type.GetGenericTypeDefinition()==typeof(Tuple<,>))) + if (type != null && type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(ValueTuple<,>) || type.GetGenericTypeDefinition() == typeof(Tuple<,>))) { //报错 //var tuple = (object, object))objectResult.Value; - //var (val1, val2) = ((dynamic, dynamic))objectResult.Value; //var apiResponse = ResponseOutput.Ok(val1, val2); @@ -56,16 +62,20 @@ namespace IRaCIS.Application.Services.BusinessFilter objectResult.DeclaredType = apiResponse.GetType(); } - + } - //如果不是200 是IResponseOutput 不处理 - else if (statusCode != 200 && (objectResult.Value is IResponseOutput)) + //如果是200 是IResponseOutput 记录下日志 + else if (statusCode == 200 && (objectResult.Value is IResponseOutput)) { + var result = objectResult.Value as IResponseOutput; + + //统一在这里记录国际化的日志信息 + _logger.LogWarning($"{result.LocalizedInfo}"); } - else if(statusCode != 200&&!(objectResult.Value is IResponseOutput)) + else if (statusCode != 200 && !(objectResult.Value is IResponseOutput)) { - //---程序错误,请联系开发人员。 + //---程序错误,请联系开发人员。 var apiResponse = ResponseOutput.NotOk(StaticData.International("UnifiedAPI_ProgramError")); objectResult.Value = apiResponse; diff --git a/IRaCIS.Core.Application/Helper/ExcelExportHelper.cs b/IRaCIS.Core.Application/Helper/ExcelExportHelper.cs index fb48b1d97..069eb3b3f 100644 --- a/IRaCIS.Core.Application/Helper/ExcelExportHelper.cs +++ b/IRaCIS.Core.Application/Helper/ExcelExportHelper.cs @@ -117,7 +117,7 @@ public static class ExcelExportHelper - var (physicalPath, fileNmae) = await FileStoreHelper.GetCommonDocPhysicalFilePathAsync(_hostEnvironment, _commonDocumentRepository, code); + var (physicalPath, fileName) = await FileStoreHelper.GetCommonDocPhysicalFilePathAsync(_hostEnvironment, _commonDocumentRepository, code); //模板路径 @@ -157,7 +157,7 @@ public static class ExcelExportHelper } // 文件名称 从sheet里面取 - fileNmae = workbook.GetSheetName(0); + //fileNmae = workbook.GetSheetName(0); #endregion @@ -181,7 +181,7 @@ public static class ExcelExportHelper return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") { - FileDownloadName = $"{exportFileNamePrefix}_{fileNmae/*.Substring(0, fileNmae.LastIndexOf('.'))*/}_{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx" + FileDownloadName = $"{(string.IsNullOrEmpty(exportFileNamePrefix) ? "" : exportFileNamePrefix+ "_") }{Path.GetFileNameWithoutExtension(fileName) }_{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx" }; #endregion @@ -328,7 +328,7 @@ public static class ExcelExportHelper } // 文件名称 从sheet里面取 - fileName = workbook.GetSheetName(0); + //fileName = workbook.GetSheetName(0); #endregion #region MiniExcel diff --git a/IRaCIS.Core.Application/Helper/FileStoreHelper.cs b/IRaCIS.Core.Application/Helper/FileStoreHelper.cs index 0be0c270e..55c01d7f0 100644 --- a/IRaCIS.Core.Application/Helper/FileStoreHelper.cs +++ b/IRaCIS.Core.Application/Helper/FileStoreHelper.cs @@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Hosting; using Newtonsoft.Json.Linq; using System.Configuration; +using System.Globalization; using System.Text.RegularExpressions; namespace IRaCIS.Core.Application.Helper; @@ -128,65 +129,6 @@ public static class FileStoreHelper #endregion - /// - /// - /// - /// - /// - /// - /// - /// - public static async Task<(string PhysicalPath, string FileName)> GetSystemClinicalPathAsync(IWebHostEnvironment _hostEnvironment, IRepository _clinicalDataTrialSetRepository, Guid id) - { - var systemClinicalData = await _clinicalDataTrialSetRepository.FirstOrDefaultAsync(t => t.Id == id); - - if (systemClinicalData == null || systemClinicalData.Path == string.Empty) - { - //---数据库没有找到对应的数据模板文件,请联系系统运维人员。 - throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileNotFound")); - } - - var filePath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, systemClinicalData.Path); - - if (!System.IO.File.Exists(filePath)) - { - //---数据模板文件存储路径上未找对应文件,请联系系统运维人员。 - throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileStoragePathInvalid")); - } - - return (filePath, systemClinicalData.FileName); - } - - - /// - /// - /// - /// - /// - /// - /// - /// - public static async Task<(string PhysicalPath, string FileName)> GetTrialClinicalPathAsync(IWebHostEnvironment _hostEnvironment, IRepository _clinicalDataTrialSetRepository, Guid id) - { - var trialClinicalData = await _clinicalDataTrialSetRepository.FirstOrDefaultAsync(t => t.Id == id); - - if (trialClinicalData == null|| trialClinicalData.Path==string.Empty) - { - //---数据库没有找到对应的数据模板文件,请联系系统运维人员。 - throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileNotFound")); - } - - var filePath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, trialClinicalData.Path); - - if (!System.IO.File.Exists(filePath)) - { - //---数据模板文件存储路径上未找对应文件,请联系系统运维人员。 - throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileStoragePathInvalid")); - } - - return (filePath, trialClinicalData.FileName); - } - //通过编码获取通用文档具体物理路径 @@ -194,6 +136,7 @@ public static class FileStoreHelper { var doc = await _commonDocumentRepository.FirstOrDefaultAsync(t => t.Code == code); + var isEn_US = CultureInfo.CurrentCulture.Name!= "zh-CN"; if (doc == null) { //---数据库没有找到对应的数据模板文件,请联系系统运维人员。 @@ -208,7 +151,7 @@ public static class FileStoreHelper throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileStoragePathInvalid")); } - return (filePath, doc.Name.Trim('/')); + return (filePath, isEn_US? doc.Name.Trim('/'): doc.NameCN.Trim('/')); } @@ -235,44 +178,6 @@ public static class FileStoreHelper return writeCount; } - // 获取项目签名文档存放路径 - - public static (string PhysicalPath, string RelativePath) GetTrialSignDocPath(IWebHostEnvironment _hostEnvironment, Guid trialId, string fileName) - { - var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment); - - //文件类型路径处理 - var uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), StaticData.Folder.SignDocumentFolder); - if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath); - - var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName); - - var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{StaticData.Folder.SignDocumentFolder}/{trustedFileNameForFileStorage}"; - - var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage); - - return (serverFilePath, relativePath); - } - - // 获取系统签名文档存放路径 - public static (string PhysicalPath, string RelativePath) GetSystemSignDocPath(IWebHostEnvironment _hostEnvironment, string fileName) - { - var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment); - - - //文件类型路径处理 - var uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.SystemDataFolder, StaticData.Folder.SignDocumentFolder); - if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath); - - - var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName); - - var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.SystemDataFolder}/{ StaticData.Folder.SignDocumentFolder}/{trustedFileNameForFileStorage}"; - - var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage); - - return (serverFilePath, relativePath); - } // 获取通用文档存放路径(excel模板 ) @@ -295,224 +200,6 @@ public static class FileStoreHelper return (serverFilePath, relativePath); } - //获取系统通知文档存放路径 - - public static (string PhysicalPath, string RelativePath) GetSystemNoticePath(IWebHostEnvironment _hostEnvironment, string fileName) - { - var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment); - - //文件类型路径处理 - var uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.SystemDataFolder, StaticData.Folder.NoticeAttachment); - if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath); - - - var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName); - - - - var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.SystemDataFolder}/{StaticData.Folder.NoticeAttachment}/{trustedFileNameForFileStorage}"; - - var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage); - - return (serverFilePath, relativePath); - } - - // 获取一致性核查路径 - public static (string PhysicalPath, string RelativePath) GetTrialCheckFilePath(IWebHostEnvironment _hostEnvironment, string fileName,Guid trialId) - { - var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment); - - //上传根路径 - string uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), StaticData.Folder.UploadEDCData); - - if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath); - - - //存放核对表 - var (trustedFileNameForFileStorage, realFileName) = FileStoreHelper.GetStoreFileName(fileName); - - - var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{StaticData.Folder.UploadEDCData}/{trustedFileNameForFileStorage}"; - - var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage); - - return (serverFilePath, relativePath); - } - - - public static (string PhysicalPath, string RelativePath, string FileRealName) GetClinicalTemplatePath(IWebHostEnvironment _hostEnvironment, string fileName,Guid trialId) - { - - var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment); - - string uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, "ClinicalTemplate", trialId.ToString(), StaticData.Folder.TreatmenthistoryFolder); - - if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath); - - var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName); - - - var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/ClinicalTemplate/{trialId}/{StaticData.Folder.TreatmenthistoryFolder}/{trustedFileNameForFileStorage}"; - - var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage); - - return (serverFilePath, relativePath, fileRealName); - - } - - - public static (string PhysicalPath, string RelativePath, string FileRealName) GetReadClinicalDataPath(IWebHostEnvironment _hostEnvironment, string fileName, Guid trialId, Guid siteId, Guid subjectId, Guid readingId) - { - var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment); - - string uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), siteId.ToString(), subjectId.ToString(), StaticData.Folder.Reading, readingId.ToString()); - - if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath); - - var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName); - - - var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{siteId}/{subjectId}/{StaticData.Folder.Reading}/{readingId}/{trustedFileNameForFileStorage}"; - - var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage); - - return (serverFilePath, relativePath, fileRealName); - - } - - //获取临床数据存放路径 - public static (string PhysicalPath, string RelativePath,string FileRealName) GetClinicalDataPath(IWebHostEnvironment _hostEnvironment, string fileName,Guid trialId,Guid siteId,Guid subjectId,Guid subjectVisitId) - { - var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment); - - string uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(),siteId.ToString(), subjectId.ToString(), subjectVisitId.ToString(), StaticData.Folder.TreatmenthistoryFolder); - - if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath); - - var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName); - - - var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{siteId}/{subjectId}/{subjectVisitId}/{StaticData.Folder.TreatmenthistoryFolder}/{trustedFileNameForFileStorage}"; - - var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage); - - return (serverFilePath, relativePath, fileRealName); - - } - - - public static (string PhysicalPath, string RelativePath, string FileRealName) GetClinicalDataPath(IWebHostEnvironment _hostEnvironment, string fileName, Guid trialId , Guid subjectId) - { - var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment); - - string uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), subjectId.ToString(), StaticData.Folder.TreatmenthistoryFolder); - - if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath); - - var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName); - - - var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{subjectId}/{StaticData.Folder.TreatmenthistoryFolder}/{trustedFileNameForFileStorage}"; - - var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage); - - return (serverFilePath, relativePath, fileRealName); - - } - - - /// - /// 上传截图 - /// - /// - /// - /// - /// - /// - /// - public static (string PhysicalPath, string RelativePath, string FileRealName) GetUploadPrintscreenFilePath(IWebHostEnvironment _hostEnvironment, string fileName, Guid trialId, Guid siteid, Guid subjectId) - { - var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment); - - string uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), siteid.ToString(), subjectId.ToString()); - - if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath); - - var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName); - - - var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{siteid}/{subjectId}/{trustedFileNameForFileStorage}"; - - var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage); - - return (serverFilePath, relativePath, fileRealName); - } - - - /// - /// 通用获取文件路径 - /// - /// - /// - /// - /// - /// - /// - public static (string PhysicalPath, string RelativePath, string FileRealName) GetFilePath(IWebHostEnvironment _hostEnvironment, string fileName, Guid trialId, Guid id,string type) - { - var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment); - - string uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), id.ToString(), type); - - if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath); - - var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName); - - - var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{id}/{type}/{trustedFileNameForFileStorage}"; - - var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage); - - return (serverFilePath, relativePath, fileRealName); - } - - public static (string PhysicalPath, string RelativePath, string FileRealName) GetMedicalReviewImage(IWebHostEnvironment _hostEnvironment, string fileName, Guid trialId, Guid taskMedicalReviewId) - { - var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment); - - string uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), taskMedicalReviewId.ToString(), StaticData.Folder.MedicalReview); - - if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath); - - var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName); - - - var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{taskMedicalReviewId}/{StaticData.Folder.MedicalReview}/{trustedFileNameForFileStorage}"; - - var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage); - - return (serverFilePath, relativePath, fileRealName); - } - - //获取非dicom文件存放路径 - public static (string PhysicalPath, string RelativePath, string FileRealName) GetNoneDicomFilePath(IWebHostEnvironment _hostEnvironment, string fileName, Guid trialId, Guid siteId, Guid subjectId, Guid subjectVisitId) - { - var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment); - - string uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), siteId.ToString(), subjectId.ToString(), subjectVisitId.ToString(), StaticData.Folder.NoneDicomFolder); - - if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath); - - var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName); - - - var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{siteId}/{subjectId}/{subjectVisitId}/{StaticData.Folder.NoneDicomFolder}/{trustedFileNameForFileStorage}"; - - var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage); - - return (serverFilePath, relativePath, fileRealName); - } - // 获取 入组确认 PD 进展发送邮件Word|PDF 存放路径 public static (string PhysicalPath, string RelativePath, string FileRealName) GetSubjectEnrollConfirmOrPDEmailPath(IWebHostEnvironment _hostEnvironment, string fileName, Guid trialId, Guid trialSiteId, Guid subjectId,bool isChangeToPdfFormat=false) @@ -629,49 +316,7 @@ public static class FileStoreHelper - // 获取医生通用文件存放路径 - public static (string PhysicalPath, string RelativePath) GetDoctorOrdinaryFilePath(IWebHostEnvironment _hostEnvironment, string fileName,Guid doctorId,string attachmentType) - { - - var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment); - - //文件类型路径处理 - var uploadFolderPath = Path.Combine(rootPath, "UploadFile", doctorId.ToString(), attachmentType); - if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath); - - - var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName); - - - - var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.UploadFileFolder}/{doctorId}/{attachmentType}/{trustedFileNameForFileStorage}"; - - var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage); - - return (serverFilePath, relativePath); - } - - public static (string PhysicalPath, string RelativePath) GetNonDoctorFilePath(IWebHostEnvironment _hostEnvironment, string fileName, string attachmentType) - { - - var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment); - - //文件类型路径处理 - var uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.UploadFileFolder, attachmentType); - if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath); - - - var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName); - - - - var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.UploadFileFolder}/{attachmentType}/{trustedFileNameForFileStorage}"; - - var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage); - - return (serverFilePath, relativePath); - } diff --git a/IRaCIS.Core.Application/Helper/InternationalizationHelper.cs b/IRaCIS.Core.Application/Helper/InternationalizationHelper.cs index 11159c5cd..910f35e14 100644 --- a/IRaCIS.Core.Application/Helper/InternationalizationHelper.cs +++ b/IRaCIS.Core.Application/Helper/InternationalizationHelper.cs @@ -9,7 +9,6 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; -using static BeetleX.Redis.Commands.HSCAN; using static IRaCIS.Core.Application.Service.Common.SystemMonitor; namespace IRaCIS.Core.Application.Helper @@ -54,6 +53,9 @@ namespace IRaCIS.Core.Application.Helper jsonObject[item.Code] = item.Value; StaticData.En_US_Dic[item.Code] = item.Value; + + //日志记录该信息方便自己人看, 返回给客户的是配置的 + StaticData.Log_Locoalize_Dic[item.Code] = item.Description; } } else @@ -72,7 +74,7 @@ namespace IRaCIS.Core.Application.Helper } } - public static async Task AddOrUpdateJsonKeyValueAsync(string key, string value, string valueCN) + public static async Task AddOrUpdateJsonKeyValueAsync(string key, string value, string valueCN,string description) { VerifyFolder(); @@ -95,6 +97,9 @@ namespace IRaCIS.Core.Application.Helper jsonObject[key] = value; StaticData.En_US_Dic[key] = value; + + //日志记录该信息方便自己人看, 返回给客户的是配置的 + StaticData.Log_Locoalize_Dic[key] = description; } else { @@ -118,7 +123,8 @@ namespace IRaCIS.Core.Application.Helper { t.Code, t.Value, - t.ValueCN + t.ValueCN, + t.Description }).ToListAsync(); //组织成json 文件 @@ -132,6 +138,9 @@ namespace IRaCIS.Core.Application.Helper { StaticData.En_US_Dic[tojsonItem.Code] = tojsonItem.Value; StaticData.Zh_CN_Dic[tojsonItem.Code] = tojsonItem.ValueCN; + + //日志记录该信息方便自己人看, 返回给客户的是配置的 + StaticData.Log_Locoalize_Dic[tojsonItem.Code] = tojsonItem.Description; } File.WriteAllText(usJsonPath, JsonConvert.SerializeObject(StaticData.En_US_Dic)); diff --git a/IRaCIS.Core.Application/Helper/SendEmailHelper.cs b/IRaCIS.Core.Application/Helper/SendEmailHelper.cs index 974a60f02..7a223b275 100644 --- a/IRaCIS.Core.Application/Helper/SendEmailHelper.cs +++ b/IRaCIS.Core.Application/Helper/SendEmailHelper.cs @@ -52,15 +52,19 @@ public static class SendEmailHelper public static async Task TestEmailConfigAsync(SystemEmailSendConfig _systemEmailConfig) { - using (var client = new MailKit.Net.Smtp.SmtpClient()) + using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5))) { + using (var client = new MailKit.Net.Smtp.SmtpClient()) + { - await client.ConnectAsync(_systemEmailConfig.Host, _systemEmailConfig.Port, SecureSocketOptions.Auto); + await client.ConnectAsync(_systemEmailConfig.Host, _systemEmailConfig.Port, SecureSocketOptions.Auto, cts.Token); - await client.AuthenticateAsync(_systemEmailConfig.FromEmail, _systemEmailConfig.AuthorizationCode); + await client.AuthenticateAsync(_systemEmailConfig.FromEmail, _systemEmailConfig.AuthorizationCode, cts.Token); - await client.DisconnectAsync(true); + await client.DisconnectAsync(true); + } } + return true; } diff --git a/IRaCIS.Core.Application/Helper/WordTempleteHelper.cs b/IRaCIS.Core.Application/Helper/WordTempleteHelper.cs new file mode 100644 index 000000000..9f605be81 --- /dev/null +++ b/IRaCIS.Core.Application/Helper/WordTempleteHelper.cs @@ -0,0 +1,101 @@ +using IRaCIS.Core.Domain.Share; +using NPOI.XWPF.UserModel; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xceed.Document.NET; +using Xceed.Words.NET; + +namespace IRaCIS.Core.Application.Helper +{ + /// + /// 利用DocX 库 处理word国际化模板 + /// + public static class WordTempleteHelper + { + public static void DocX_GetInternationalTempleteStream(string filePath, Stream memoryStream) + { + + var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US; + + using (DocX document = DocX.Load(filePath)) + { + // 查找书签 + var bookmarkEn_Start = document.Bookmarks.FirstOrDefault(b => b.Name == StaticData.CultureInfo.en_US_bookMark); + + if (bookmarkEn_Start != null) + { + // 获取书签的起始位置 + //int bookmarkCNStartPos = bookmarkCn_Start.Paragraph.StartIndex; + + var bookmarkENStartPos = bookmarkEn_Start.Paragraph.StartIndex; + + // 创建一个要删除段落的列表 + List paragraphsToRemove = new List(); + + foreach (var item in document.Paragraphs) + { + //中文模板在前,英文在后,英文模板,就删除英文之前的,中文模板就删除英文之后的 + + if (isEn_US ? item.EndIndex < bookmarkENStartPos : item.StartIndex >= bookmarkENStartPos) + { + paragraphsToRemove.Add(item); + } + } + + foreach (var paragraph in paragraphsToRemove) + { + document.RemoveParagraph(paragraph); + } + + } + + // 保存修改 + document.SaveAs(memoryStream); + } + } + + + public static void Npoi_GetInternationalTempleteStream(string filePath, Stream memoryStream) + { + + var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US; + + using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) + { + XWPFDocument doc = new XWPFDocument(fs); + + // 查找包含指定书签的段落及其索引 + var bookmarkParagraph = doc.Paragraphs + .FirstOrDefault(p => p.GetCTP().GetBookmarkStartList().Any(b => b.name == StaticData.CultureInfo.en_US_bookMark)); + + if (bookmarkParagraph != null) + { + int bookmarkIndex = doc.Paragraphs.IndexOf(bookmarkParagraph); + + if (isEn_US) + { + // 从书签所在段落开始,删除之前的所有段落 + for (int i = bookmarkIndex - 1; i >= 0; i--) + { + doc.RemoveBodyElement(i); + } + } + else + { + // 删除书签之后的所有段落 + for (int i = doc.Paragraphs.Count - 1; i >= bookmarkIndex; i--) + { + doc.RemoveBodyElement(i); + } + } + } + doc.Write(memoryStream); + } + } + + } +} diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj b/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj index 72dc549f8..ab00314fc 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj @@ -42,7 +42,7 @@ - + @@ -50,11 +50,6 @@ - - PreserveNewest - true - PreserveNewest - Always true @@ -63,10 +58,10 @@ - + + - - + @@ -74,22 +69,22 @@ - - - + + + - + true - + - + diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml index ef44e414d..3aa7acb09 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -29,31 +29,16 @@ 签名 + + + 不生效,不知道为啥 + + 主要为了 处理项目结束 锁库,不允许操作 - - - - - - - - - - - - - - - - - - - - 写文件导到磁盘 @@ -62,28 +47,6 @@ 文件保存路径 - - - 上传截图 - - - - - - - - - - - 通用获取文件路径 - - - - - - - - oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder @@ -117,6 +80,11 @@ 解密后的字符串 + + + 利用DocX 库 处理word国际化模板 + + 分配规则 @@ -543,9 +511,19 @@ + + + 项目列表导出---new + + + + + + + - getDocumentConfirmList 培训记录导出 + getDocumentConfirmList 培训记录导出--new @@ -567,7 +545,7 @@ - 影像质控导出 + 影像质控导出---new @@ -9910,7 +9888,7 @@ - + 测试scp server 是否可以连接 @@ -15368,6 +15346,13 @@ + + + 清理一致性分析任务 + + + + 维护临床数据 --一定要在同步表前同步数据才行 diff --git a/IRaCIS.Core.Application/Service/Allocation/DTO/TaskConsistentRuleViewModel.cs b/IRaCIS.Core.Application/Service/Allocation/DTO/TaskConsistentRuleViewModel.cs index e45e9c2bb..0a566607e 100644 --- a/IRaCIS.Core.Application/Service/Allocation/DTO/TaskConsistentRuleViewModel.cs +++ b/IRaCIS.Core.Application/Service/Allocation/DTO/TaskConsistentRuleViewModel.cs @@ -107,7 +107,7 @@ namespace IRaCIS.Core.Application.ViewModel public class DoctorSelfConsistentSubjectView: ConsistentCommonView { - + public string FirstGlobalVisitName { get; set; } = string.Empty; public string? BlindSubjectCode { get; set; } public List VisitTaskList { get; set; } diff --git a/IRaCIS.Core.Application/Service/Allocation/DTO/VisitTaskViewModel.cs b/IRaCIS.Core.Application/Service/Allocation/DTO/VisitTaskViewModel.cs index 302351e3d..64e526983 100644 --- a/IRaCIS.Core.Application/Service/Allocation/DTO/VisitTaskViewModel.cs +++ b/IRaCIS.Core.Application/Service/Allocation/DTO/VisitTaskViewModel.cs @@ -211,7 +211,9 @@ namespace IRaCIS.Core.Application.ViewModel { public bool? IsSelfAnalysis { get; set; } - public bool IsReReadingOrBackInfluenceAnalysis { get; set; } + public int ConsistentClinicalDataCount { get; set; } = 0; + + public bool IsReReadingOrBackInfluenceAnalysis { get; set; } } diff --git a/IRaCIS.Core.Application/Service/Allocation/TaskConsistentRuleService.cs b/IRaCIS.Core.Application/Service/Allocation/TaskConsistentRuleService.cs index 579c1e766..77e0a2737 100644 --- a/IRaCIS.Core.Application/Service/Allocation/TaskConsistentRuleService.cs +++ b/IRaCIS.Core.Application/Service/Allocation/TaskConsistentRuleService.cs @@ -20,6 +20,7 @@ using IRaCIS.Core.Infrastructure.Extention; using System; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using NPOI.SS.Formula.Functions; +using IRaCIS.Core.Application.Service.Reading.Dto; namespace IRaCIS.Core.Application.Service { @@ -32,6 +33,8 @@ namespace IRaCIS.Core.Application.Service private readonly IRepository _taskConsistentRuleRepository; private readonly IRepository _visitTaskRepository; + private readonly IRepository _readingConsistentClinicalDataRepository; + private readonly IReadingClinicalDataService _readingClinicalDataService; private readonly IRepository _subjectUserRepository; private readonly IRepository _subjectRepository; private readonly IRepository _enrollRepository; @@ -44,11 +47,16 @@ namespace IRaCIS.Core.Application.Service private readonly IVisitTaskHelpeService _visitTaskCommonService; - public TaskConsistentRuleService(IRepository visitTaskRepository, IRepository enrollRepository, IRepository taskConsistentRuleRepository, IRepository subjectUserRepository, IRepository subjectRepository, IDistributedLockProvider distributedLockProvider, + public TaskConsistentRuleService(IRepository visitTaskRepository, + IRepository readingConsistentClinicalDataRepository, + IReadingClinicalDataService readingClinicalDataService, + IRepository enrollRepository, IRepository taskConsistentRuleRepository, IRepository subjectUserRepository, IRepository subjectRepository, IDistributedLockProvider distributedLockProvider, IRepository trialRepository, IRepository trialSiteRepository, IRepository trialVirtualSiteCodeUpdateRepository, IVisitTaskHelpeService visitTaskCommonService) { _taskConsistentRuleRepository = taskConsistentRuleRepository; _visitTaskRepository = visitTaskRepository; + this._readingConsistentClinicalDataRepository = readingConsistentClinicalDataRepository; + this._readingClinicalDataService = readingClinicalDataService; _subjectUserRepository = subjectUserRepository; _subjectRepository = subjectRepository; _enrollRepository = enrollRepository; @@ -117,6 +125,20 @@ namespace IRaCIS.Core.Application.Service var defalutSortArray = new string[] { nameof(VisitTask.IsUrgent) + " desc", nameof(VisitTask.SubjectId), nameof(VisitTask.VisitTaskNum) }; var pageList = await visitTaskQueryable.ToPagedListAsync(queryVisitTask.PageIndex, queryVisitTask.PageSize, queryVisitTask.SortField, queryVisitTask.Asc, string.IsNullOrWhiteSpace(queryVisitTask.SortField), defalutSortArray); + #region 统计一致性分析临床数据数量 + + foreach (var item in pageList.CurrentPageData) + { + item.ConsistentClinicalDataCount = (await _readingClinicalDataService.GetClinicalDataList(new GetReadingOrTaskClinicalDataListInDto() + { + SubjectId = item.SubjectId, + TrialId = item.TrialId, + SelectIsSign = false, + IsGetAllConsistencyAnalysis = false, + VisitTaskId = item.Id, + })).Count(); + } + #endregion var trialTaskConfig = _repository.Where(t => t.Id == queryVisitTask.TrialId).Select(t => new { IsHaveDoubleReadCriterion = t.TrialReadingCriterionList.Any(t => t.IsSigned && t.IsConfirm && t.ReadingType == ReadingMethod.Double), t.VitrualSiteCode }).FirstOrDefault(); @@ -253,6 +275,7 @@ namespace IRaCIS.Core.Application.Service TaskName = lastTask.TaskName + "_Global", TaskBlindName = lastTask.TaskBlindName + "_Global", TrialReadingCriterionId = trialReadingCriterionId, + VisitTaskNum= lastTask.VisitTaskNum + ReadingCommon.TaskNumDic[ReadingCategory.Global] }; var afterGlobal = _visitTaskRepository.Where(t => t.SubjectId == lastTask.SubjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.TaskState == TaskState.Effect && t.ReadingCategory == ReadingCategory.Global && t.VisitTaskNum > lastTask.VisitTaskNum).ProjectTo(_mapper.ConfigurationProvider).FirstOrDefault(); @@ -496,7 +519,9 @@ namespace IRaCIS.Core.Application.Service TrialReadingCriterionId = trialReadingCriterionId, BlindSubjectCode = blindSubjectCode, - BlindTrialSiteCode = filterObj.BlindTrialSiteCode + BlindTrialSiteCode = filterObj.BlindTrialSiteCode, + + VisitTaskNum = lastTask.VisitTaskNum + ReadingCommon.TaskNumDic[ReadingCategory.Global] }; } @@ -599,6 +624,8 @@ namespace IRaCIS.Core.Application.Service IsReReadingOrBackInfluenceAnalysis = t.IsReReadingOrBackInfluenceAnalysis, + FirstGlobalVisitName= t.ReadModuleList.Where(c=>c.TrialReadingCriterionId== trialReadingCriterionId && c.ModuleType== ModuleTypeEnum.Global).OrderBy(k=>k.SubjectVisit.VisitNum).Select(u=>u.SubjectVisit.VisitName).FirstOrDefault(), + BlindSubjectCode = t.SubjectVisitTaskList.Where(t => t.IsAnalysisCreate && t.TrialReadingCriterionId == trialReadingCriterionId).OrderByDescending(t => t.BlindSubjectCode).Select(t => t.BlindSubjectCode).FirstOrDefault(), IsHaveGeneratedTask = t.SubjectVisitTaskList.Any(c => c.DoctorUserId == doctorUserId && c.IsSelfAnalysis == true && c.TrialReadingCriterionId == trialReadingCriterionId), @@ -711,7 +738,7 @@ namespace IRaCIS.Core.Application.Service IsHaveGeneratedTask = t.SubjectVisitTaskList.Any(c => c.IsSelfAnalysis == false && c.TrialReadingCriterionId == trialReadingCriterionId), - DoctorUserList = t.SubjectDoctorList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId && t.IsConfirmed).Select(t => new UserSimpleInfo() + DoctorUserList = t.SubjectDoctorList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId && t.IsConfirmed && t.ArmEnum <= Arm.DoubleReadingArm2).Select(t => new UserSimpleInfo() { UserId = t.Id, FullName = t.DoctorUser.FullName, diff --git a/IRaCIS.Core.Application/Service/Allocation/VisitTaskHelpeService.cs b/IRaCIS.Core.Application/Service/Allocation/VisitTaskHelpeService.cs index 9bd628b3d..72553ebd3 100644 --- a/IRaCIS.Core.Application/Service/Allocation/VisitTaskHelpeService.cs +++ b/IRaCIS.Core.Application/Service/Allocation/VisitTaskHelpeService.cs @@ -1420,14 +1420,16 @@ namespace IRaCIS.Core.Application.Service //判断是否存在传输方式为Pdf得临床数据 - var exsitPDF = await _trialClinicalDataSetRepository.AnyAsync(t => t.TrialId == trialId && - t.TrialClinicalDataSetCriteriaList.Any(c => c.TrialReadingCriterionId == readingCriterionId) - && t.ClinicalUploadType == ClinicalUploadType.PDF); - - var taskState = exsitPDF ? TaskState.NotEffect : TaskState.Effect; - - var clinicalDataList = _readingClinicalDataRepository.Where(t => t.SubjectId == subjectId && t.ClinicalDataTrialSet.ClinicalUploadType == ClinicalUploadType.PDF).Include(t => t.ReadingClinicalDataPDFList).Include(t => t.ClinicalDataTrialSet).ToList(); + var firsttask = generateTaskCommand.GenerataConsistentTaskList[0]; + var clinicalDataList = _readingClinicalDataRepository.Where(t => t.SubjectId == subjectId + && t.ClinicalDataTrialSet.TrialClinicalDataSetCriteriaList.Any(y => y.TrialReadingCriterionId == firsttask.TrialReadingCriterionId) + && t.ClinicalDataTrialSet.ClinicalDataLevel!= ClinicalLevel.Study + && t.ClinicalDataTrialSet.ClinicalUploadType == ClinicalUploadType.PDF) + // crc受试者和访视的临床数据没上传 一致性分析的时候也不用显示 + .Where(x=>x.ClinicalDataTrialSet.UploadRole == UploadRole.PM||x.FileCount>0) + .Include(t => t.ReadingClinicalDataPDFList).Include(t => t.ClinicalDataTrialSet).ToList(); + foreach (var clinicalData in clinicalDataList) { var consistnentClinicalData = _mapper.Map(clinicalData); @@ -1438,6 +1440,7 @@ namespace IRaCIS.Core.Application.Service { consistnentClinicalData.IsSign = false; consistnentClinicalData.IsBlind = false; + consistnentClinicalData.IsComplete = true; consistnentClinicalData.ReadingClinicalDataState = ReadingClinicalDataStatus.HaveUploaded; consistnentClinicalData.ClinicalDataTrialSet = null; } @@ -1453,6 +1456,15 @@ namespace IRaCIS.Core.Application.Service foreach (var task in generateTaskCommand.GenerataConsistentTaskList) { + + var exsitPDF = await _readingClinicalDataRepository.AnyAsync(t => t.TrialId == trialId && + t.SubjectId== task.SubjectId&& + + t.ClinicalDataTrialSet.TrialClinicalDataSetCriteriaList.Any(c => c.TrialReadingCriterionId == readingCriterionId) + && t.ClinicalDataTrialSet.ClinicalDataLevel != ClinicalLevel.Study + && t.ClinicalDataTrialSet.ClinicalUploadType == ClinicalUploadType.PDF); + + var taskState = exsitPDF ? TaskState.NotEffect : TaskState.Effect; var consistentTask = new VisitTask() { TrialId = task.TrialId, diff --git a/IRaCIS.Core.Application/Service/Allocation/VisitTaskService.cs b/IRaCIS.Core.Application/Service/Allocation/VisitTaskService.cs index 4898ac25c..12f90e6ca 100644 --- a/IRaCIS.Core.Application/Service/Allocation/VisitTaskService.cs +++ b/IRaCIS.Core.Application/Service/Allocation/VisitTaskService.cs @@ -290,7 +290,7 @@ namespace IRaCIS.Core.Application.Service.Allocation { foreach (var command in cancelCommand.CancelList.Where(t => t.IsCancelAssign)) { - if (await _visitTaskRepository.AnyAsync(t => t.TrialReadingCriterionId == cancelCommand.TrialReadingCriterionId && t.SubjectId == command.SubjectId && t.DoctorUserId == command.DoctorUserId && t.ArmEnum == command.ArmEnum && t.ReadingTaskState != ReadingTaskState.WaitReading)) + if (await _visitTaskRepository.AnyAsync(t => t.TaskState==TaskState.Effect && t.TrialReadingCriterionId == cancelCommand.TrialReadingCriterionId && t.SubjectId == command.SubjectId && t.DoctorUserId == command.DoctorUserId && t.ArmEnum == command.ArmEnum && t.ReadingTaskState != ReadingTaskState.WaitReading)) { //---当前医生已开始做该Subject 该标准的任务,不允许取消分配 throw new BusinessValidationFailedException(_localizer["VisitTask_DoctorConfigNotFound"]); @@ -786,7 +786,7 @@ namespace IRaCIS.Core.Application.Service.Allocation .WhereIf(!string.IsNullOrEmpty(queryVisitTask.SubjectCode), t => (t.Subject.Code.Contains(queryVisitTask.SubjectCode) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(queryVisitTask.SubjectCode) && t.IsAnalysisCreate)) .WhereIf(queryVisitTask.BeginAllocateDate != null, t => t.AllocateTime > queryVisitTask.BeginAllocateDate) .WhereIf(queryVisitTask.EndAllocateDate != null, t => t.AllocateTime < queryVisitTask.EndAllocateDate) - .WhereIf(queryVisitTask.BeginSignTime != null, t => t.SignTime > queryVisitTask.BeginSignTime) + .WhereIf(queryVisitTask.BeginSignTime != null, t => t.SignTime > queryVisitTask.BeginSignTime) .WhereIf(queryVisitTask.EndSignTime != null, t => t.SignTime < queryVisitTask.EndSignTime) .ProjectTo(_mapper.ConfigurationProvider); diff --git a/IRaCIS.Core.Application/Service/Allocation/_MapConfig.cs b/IRaCIS.Core.Application/Service/Allocation/_MapConfig.cs index 8ae10c42c..00dc9b3ef 100644 --- a/IRaCIS.Core.Application/Service/Allocation/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/Allocation/_MapConfig.cs @@ -104,7 +104,7 @@ namespace IRaCIS.Core.Application.Service CreateMap().IncludeBase() - .ForMember(o => o.IsHaveReading, t => t.MapFrom(u => u.Subject.SubjectVisitTaskList.Any(t => t.ReadingTaskState != ReadingTaskState.WaitReading && t.TrialReadingCriterionId==u.TrialReadingCriterionId && t.DoctorUserId==u.DoctorUserId))); + .ForMember(o => o.IsHaveReading, t => t.MapFrom(u => u.Subject.SubjectVisitTaskList.Any(t => t.ReadingTaskState != ReadingTaskState.WaitReading && t.TrialReadingCriterionId==u.TrialReadingCriterionId && t.DoctorUserId==u.DoctorUserId && t.TaskState == TaskState.Effect))); CreateMap(); diff --git a/IRaCIS.Core.Application/Service/Common/CommonDocumentService.cs b/IRaCIS.Core.Application/Service/Common/CommonDocumentService.cs index 0171c67c2..35eac6a73 100644 --- a/IRaCIS.Core.Application/Service/Common/CommonDocumentService.cs +++ b/IRaCIS.Core.Application/Service/Common/CommonDocumentService.cs @@ -41,7 +41,7 @@ namespace IRaCIS.Core.Application.Service .WhereIf(string.IsNullOrEmpty(queryCommonDocument.Name), t => t.Name.Contains(queryCommonDocument.Name)) .ProjectTo(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken, userId = _userInfo.Id }); - return await commonDocumentQueryable.ToPagedListAsync(queryCommonDocument.PageIndex, queryCommonDocument.PageSize, String.IsNullOrEmpty(queryCommonDocument.SortField) ? nameof(CommonDocument.Code) : queryCommonDocument.SortField, queryCommonDocument.Asc); ; + return await commonDocumentQueryable.ToPagedListAsync(queryCommonDocument); } @@ -119,7 +119,7 @@ namespace IRaCIS.Core.Application.Service var filePath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, dbbeforeEntity.Path); - if (File.Exists(filePath)) + if (File.Exists(filePath) && dbbeforeEntity.Path!=addOrEditCommonDocument.Path) { File.Delete(filePath); } diff --git a/IRaCIS.Core.Application/Service/Common/DTO/InternationalizationViewModel.cs b/IRaCIS.Core.Application/Service/Common/DTO/InternationalizationViewModel.cs index eb64a391e..53b162923 100644 --- a/IRaCIS.Core.Application/Service/Common/DTO/InternationalizationViewModel.cs +++ b/IRaCIS.Core.Application/Service/Common/DTO/InternationalizationViewModel.cs @@ -76,8 +76,7 @@ namespace IRaCIS.Core.Application.ViewModel public string ValueCN { get; set; } = string.Empty; public string Module { get; set; } = string.Empty; - //关联版本历史记录表Id - public Guid? PublishLogId { get; set; } + } public class BatchAddInternationalizationDto : BatchInternationalizationDto diff --git a/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs b/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs index 386e6d2a7..830742482 100644 --- a/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs +++ b/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs @@ -16,6 +16,7 @@ using MiniExcelLibs; using MiniExcelLibs.OpenXml; using NPOI.HPSF; using NPOI.HSSF.UserModel; +using NPOI.SS.Formula.Functions; using NPOI.XSSF.UserModel; using System; using System.Collections.Generic; @@ -181,6 +182,132 @@ namespace IRaCIS.Core.Application.Service.Common } + /// + /// 项目列表导出---new + /// + /// + /// + /// + /// + /// + [HttpPost] + [AllowAnonymous] + public async Task GetTrialList_Export(TrialToBeDoneQuery inQuery, + [FromServices] IRepository _commonDocumentRepository, + [FromServices] IDictionaryService _dictionaryService, + [FromServices] IRepository _trialRepository + ) + { + var isPM = _userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.APM; + var isCRC = _userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator; + var isIQC = _userInfo.UserTypeEnumInt == (int)UserTypeEnum.IQC; + var isMIM = _userInfo.UserTypeEnumInt == (int)UserTypeEnum.MIM; + var isSPMOrCPM = _userInfo.UserTypeEnumInt == (int)UserTypeEnum.SPM || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CPM; + var isIR = _userInfo.UserTypeEnumInt == (int)UserTypeEnum.IndependentReviewer; + + + var query = _trialRepository.AsQueryable().IgnoreQueryFilters() + + .WhereIf(inQuery.SponsorId != null, o => o.SponsorId == inQuery.SponsorId) + .WhereIf(!string.IsNullOrEmpty(inQuery.Code), o => o.TrialCode.Contains(inQuery.Code)) + .WhereIf(!string.IsNullOrEmpty(inQuery.ResearchProgramNo), o => o.ResearchProgramNo.Contains(inQuery.ResearchProgramNo)) + .WhereIf(!string.IsNullOrWhiteSpace(inQuery.ExperimentName), o => o.ExperimentName.Contains(inQuery.ExperimentName)) + .WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin && _userInfo.UserTypeEnumInt != (int)UserTypeEnum.Admin && _userInfo.UserTypeEnumInt != (int)UserTypeEnum.OP, t => t.TrialUserList.Any(t => t.UserId == _userInfo.Id && t.IsDeleted == false) && t.IsDeleted == false) + .WhereIf(inQuery.CriterionType != null, o => o.TrialReadingCriterionList.Any(t => t.CriterionType == inQuery.CriterionType && t.IsSigned && t.IsConfirm)) + .WhereIf(!string.IsNullOrEmpty(inQuery.PM_EMail), o => o.TrialUserList.Any(t => t.User.EMail.Contains(inQuery.PM_EMail) && (t.User.UserTypeEnum == UserTypeEnum.ProjectManager || t.User.UserTypeEnum == UserTypeEnum.APM))) + .Select(t => new TrialToBeDoneDto() + { + TrialId = t.Id, + ResearchProgramNo = t.ResearchProgramNo, + ExperimentName = t.ExperimentName, + TrialCode = t.TrialCode, + CreateTime = t.CreateTime, + Sponsor = _userInfo.IsEn_Us ? t.Sponsor.SponsorName : t.Sponsor.SponsorNameCN, + TrialStatusStr = t.TrialStatusStr, + + ExpetiedTaskCount = isPM ? t.VisitTaskList.Where(t => t.IsUrgent).Count() : 0, + + ReReadingApprovalCount = isPM ? t.VisitTaskReReadingList.Where(t => t.OriginalReReadingTask.ReReadingApplyState == ReReadingApplyState.DocotorHaveApplyed).Count() : 0, + + PendingReconciliationCount = isPM ? t.SubjectVisitList.Where(t => t.CheckState == CheckStateEnum.ToCheck).Count() : 0, + + PendingResponseCount = isPM ? t.SubjectVisitList.Where(u => u.CheckState == CheckStateEnum.CVIng && + u.CheckChallengeDialogList.OrderByDescending(t => t.CreateTime).First().UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Count() : 0, + + + SPM_ReReadingApprovalCount = isSPMOrCPM ? t.VisitTaskReReadingList.Where(t => t.OriginalReReadingTask.ReReadingApplyState == ReReadingApplyState.TrialGroupHaveApplyed).Count() : 0, + + SPM_ReviewerSelectApprovalCount = isSPMOrCPM ? t.EnrollList.Where(u => u.EnrollStatus == EnrollStatus.HasCommittedToCRO).Count() : 0, + + MIM_UrgentCount = isMIM ? t.TaskMedicalReviewList.Where(t => t.IsClosedDialog == false && t.VisitTask.TaskState == TaskState.Effect && t.IsInvalid == false && t.MedicalManagerUserId == _userInfo.Id) + .Where(u => u.VisitTask.IsUrgent && + u.AuditState != MedicalReviewAuditState.HaveSigned).Count() : 0, + + MIM_PendingResponseCount = isMIM ? t.TaskMedicalReviewList.Where(t => t.IsClosedDialog == false && t.VisitTask.TaskState == TaskState.Effect && t.IsInvalid == false && t.MedicalManagerUserId == _userInfo.Id) + .Where(u => u.LatestReplyUser.UserTypeEnum == UserTypeEnum.IndependentReviewer && u.AuditState == MedicalReviewAuditState.Auditing).Count() : 0, + + MIM_PendingReviewCount = isMIM ? t.TaskMedicalReviewList.Where(t => t.IsClosedDialog == false && t.VisitTask.TaskState == TaskState.Effect && t.IsInvalid == false && t.MedicalManagerUserId == _userInfo.Id) + .Where(u => u.AuditState != MedicalReviewAuditState.HaveSigned && u.LatestReplyUser.UserTypeEnum != UserTypeEnum.IndependentReviewer).Count() : 0, + + CRC_UrgentCount = isCRC ? t.SubjectVisitList.Where(c => c.TrialSite.CRCUserList.Any(u => u.UserId == _userInfo.Id) && t.IsUrgent).Count() : 0, + + CRC_CheckQuestionCount = isCRC ? t.SubjectVisitList.Where(c => c.TrialSite.CRCUserList.Any(u => u.UserId == _userInfo.Id)) + .Where(u => u.CheckState == CheckStateEnum.CVIng && u.CheckChallengeState == CheckChanllengeTypeEnum.PMWaitCRCReply).Count() : 0, + + CRC_QCQuestionCount = isCRC ? t.SubjectVisitList.Where(c => c.TrialSite.CRCUserList.Any(u => u.UserId == _userInfo.Id)).SelectMany(c => c.QCChallengeList) + .Where(u => u.IsClosed == false && (u.LatestReplyUser.UserTypeEnum == UserTypeEnum.IQC || u.LatestReplyUserId == null)).Count() : 0, + + + //待审核 审核中 加急的数量 + IQC_UrgentCount = isIQC ? t.SubjectVisitList.Where(u => u.CurrentActionUserId == _userInfo.Id && t.QCProcessEnum != TrialQCProcess.NotAudit && t.IsUrgent).Count() : 0, + + //审核未完成 + IQC_AuditToBeDealedCount = isIQC ? t.SubjectVisitList.Where(u => u.CurrentActionUserId == _userInfo.Id && t.QCProcessEnum != TrialQCProcess.NotAudit).Count() : 0, + + //质疑待处理 + IQC_QuestionToBeDealedCount = isIQC ? t.SubjectVisitList.SelectMany(c => c.QCChallengeList) + .Where(u => u.CreateUserId == _userInfo.Id && u.IsClosed == false && u.LatestReplyUser.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Count() : 0, + + //待领取 + IQC_ToBeClaimedCount = isIQC ? t.SubjectVisitList.Where(t => t.SubmitState == SubmitStateEnum.Submitted && t.AuditState != AuditStateEnum.QCPassed) + .Where(u => u.CurrentActionUserId == null && (u.PreliminaryAuditUserId == null || (u.PreliminaryAuditUserId != _userInfo.Id && u.ReviewAuditUserId == null))).Count() : 0, + + + IR_ReadingCriterionList = isIR ? t.TrialReadingCriterionList.Where(t => t.IsConfirm && t.IsSigned).OrderBy(t => t.CriterionName).Select(t => t.CriterionName).ToList() : null, + + IR_PMEmailList = isIR ? t.TrialUserList.Where(t => t.User.UserTypeEnum == UserTypeEnum.ProjectManager || t.User.UserTypeEnum == UserTypeEnum.APM).OrderBy(t => t.User.EMail).Select(t => t.User.EMail).ToList() : null, + + IR_TotalReadCount = isIR ? t.VisitTaskList.Where(t => t.DoctorUserId == _userInfo.Id && t.TaskState == TaskState.Effect && t.ReadingTaskState == ReadingTaskState.HaveSigned).Count() : 0, + + + IR_UnReadCount = isIR ? t.VisitTaskList + .Where(c => c.DoctorUserId == _userInfo.Id && c.ReadingTaskState != ReadingTaskState.HaveSigned && c.TaskState == TaskState.Effect && c.TrialReadingCriterion.IsSigned) + // 前序 不存在 未一致性核查未通过的 + .Where(t => !t.Subject.SubjectVisitList.Any(sv => sv.CheckState != CheckStateEnum.CVPassed && t.VisitTaskNum > sv.VisitNum)) + //前序 不存在 未生成任务的访视 + .Where(t => t.TrialReadingCriterion.IsAutoCreate == false ? !t.Subject.SubjectCriteriaEvaluationVisitFilterList.Where(d => d.TrialReadingCriterionId == t.TrialReadingCriterionId).Any(f => f.IsGeneratedTask == false && t.VisitTaskNum > f.SubjectVisit.VisitNum) : true) + + .Where(y => y.IsFrontTaskNeedSignButNotSign == false && (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true)).Count() : 0, + + IR_UrgentCount = isIR ? t.VisitTaskList.Where(t => t.SourceSubjectVisit.IsUrgent).Count() : 0, + + }); + + + var list = query.ToList(); + + var exportInfo = new ExcelExportInfo(); + + exportInfo.List = ExportExcelConverterDate.ConvertToClientTimeInObject(list, _userInfo.TimeZoneId); + exportInfo.IsEn_US = _userInfo.IsEn_Us; + exportInfo.ClientZoneId = _userInfo.TimeZoneId; + + + return await ExcelExportHelper.DataExportAsync(StaticData.Export.TrialList_Export, exportInfo, exportInfo.TrialCode, _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(TrialToBeDoneDto)); + + } + + #endregion @@ -190,7 +317,7 @@ namespace IRaCIS.Core.Application.Service.Common #region 导表查询 /// - /// getDocumentConfirmList 培训记录导出 + /// getDocumentConfirmList 培训记录导出--new /// /// /// @@ -357,7 +484,7 @@ namespace IRaCIS.Core.Application.Service.Common } /// - /// 影像质控导出 + /// 影像质控导出---new /// /// /// @@ -376,9 +503,9 @@ namespace IRaCIS.Core.Application.Service.Common { var svExpression = QCCommon.GetSubjectVisitFilter(inQuery.VisitPlanArray); var query = _subjectVisitRepository.Where(x => x.TrialId == inQuery.TrialId) - .WhereIf(inQuery.VisitId != null, t => t.Id == inQuery.VisitId) - .WhereIf(inQuery.CurrentActionUserId != null, t => t.CurrentActionUserId == inQuery.CurrentActionUserId) - .WhereIf(inQuery.ChallengeState != null, t => t.ChallengeState == inQuery.ChallengeState) + .WhereIf(inQuery.VisitId != null, t => t.Id == inQuery.VisitId) + .WhereIf(inQuery.CurrentActionUserId != null, t => t.CurrentActionUserId == inQuery.CurrentActionUserId) + .WhereIf(inQuery.ChallengeState != null, t => t.ChallengeState == inQuery.ChallengeState) .WhereIf(inQuery.TrialSiteId != null, t => t.TrialSiteId == inQuery.TrialSiteId) .WhereIf(inQuery.SubjectId != null, t => t.Subject.Id == inQuery.SubjectId) .WhereIf(!string.IsNullOrEmpty(inQuery.SubjectInfo), t => /*t.Subject.FirstName.Contains(subjectInfo) || t.Subject.LastName.Contains(subjectInfo) ||*/ t.Subject.Code.Contains(inQuery.SubjectInfo)) @@ -489,9 +616,9 @@ namespace IRaCIS.Core.Application.Service.Common .WhereIf(inQuery.TrialSiteId != null, t => t.TrialSiteId == inQuery.TrialSiteId) // CRC 只负责他管理site的受试者 - .WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA, t => t.TrialSite.CRCUserList.Any(t => t.UserId == _userInfo.Id)) + .WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA, t => t.TrialSite.CRCUserList.Any(t => t.UserId == _userInfo.Id)) .ProjectTo(_mapper.ConfigurationProvider) - .WhereIf(inQuery.IsMissingImages == true, t => t.MissingSubmmitCount> 0) + .WhereIf(inQuery.IsMissingImages == true, t => t.MissingSubmmitCount > 0) .WhereIf(inQuery.IsMissingImages == false, t => t.MissingSubmmitCount == 0) ; @@ -915,10 +1042,10 @@ namespace IRaCIS.Core.Application.Service.Common [FromServices] IRepository _trialRepository) { var list = await _repository.Where(t => t.TrialId == queryVisitTask.TrialId && t.IsAnalysisCreate == false) - //.Where(t => t.IsAnalysisCreate == false && t.DoctorUserId != null) + //.Where(t => t.IsAnalysisCreate == false && t.DoctorUserId != null) - .WhereIf(queryVisitTask.TaskState != null, t => t.TaskState == queryVisitTask.TaskState) - .WhereIf(queryVisitTask.ArmEnum != null, t => t.ArmEnum == queryVisitTask.ArmEnum) + .WhereIf(queryVisitTask.TaskState != null, t => t.TaskState == queryVisitTask.TaskState) + .WhereIf(queryVisitTask.ArmEnum != null, t => t.ArmEnum == queryVisitTask.ArmEnum) .WhereIf(queryVisitTask.TrialSiteId != null, t => t.Subject.TrialSiteId == queryVisitTask.TrialSiteId) .WhereIf(queryVisitTask.SubjectId != null, t => t.SubjectId == queryVisitTask.SubjectId) .WhereIf(queryVisitTask.IsUrgent != null, t => t.IsUrgent == queryVisitTask.IsUrgent) @@ -1314,7 +1441,7 @@ namespace IRaCIS.Core.Application.Service.Common list.Add(new ExportDocumentDes() { Code = StaticData.Export.PCWG3Point1DetailedOfEvaluatedLesion_Export, ExportCatogory = ExportCatogory.DetailedOfEvaluatedLesion }); } - var result = _repository.Where(t => list.Select(c => c.Code).Contains(t.Code)).Select(c => new ExportDocumentDes() { Code = c.Code, FileName = c.Name }).ToList(); + var result = _repository.Where(t => list.Select(c => c.Code).Contains(t.Code)).Select(c => new ExportDocumentDes() { Code = c.Code, FileName = _userInfo.IsEn_Us ? c.Name : c.NameCN }).ToList(); foreach (var item in list) { @@ -1325,63 +1452,154 @@ namespace IRaCIS.Core.Application.Service.Common public List DealJudgeMark(ArbitrationRule arbitrationRule, IEnumerable list) where T : OverallTumorEvaluationExport { - //处理裁判标记 - - var resultList = list.Where(t => t.ReadingCategory != ReadingCategory.Judge).ToList(); + //处理访视任务的裁判标记 + var resultExceptJudgeList = list.Where(t => t.ReadingCategory != ReadingCategory.Judge).ToList(); + var judegeList = list.Where(t => t.ReadingCategory == ReadingCategory.Judge).ToList(); if (arbitrationRule == ArbitrationRule.Visit) { - foreach (var item in resultList) + foreach (var item in resultExceptJudgeList) { - item.IsGenerateJudge = list.FirstOrDefault(t => t.ReadingCategory == ReadingCategory.Judge && t.SubjectCode == item.SubjectCode + item.IsGenerateJudge = judegeList.FirstOrDefault(t => t.SubjectCode == item.SubjectCode && (t.VisitTaskNum - ReadingCommon.TaskNumDic[ReadingCategory.Judge]) == item.VisitTaskNum)?.JudgeArmEnum == item.ArmEnum ? true : false; } + //如果没有产生裁判,默认选择R1 + + //找到没有裁判的访视任务 + var notJudgeList = resultExceptJudgeList.GroupBy(t => new { t.SubjectCode, t.VisitTaskNum }).Where(g => g.All(t => t.IsGenerateJudge == false)).Select(g => new { g.Key.SubjectCode, g.Key.VisitTaskNum }).ToList(); + + foreach (var item in resultExceptJudgeList) + { + if (notJudgeList.Any(t => t.SubjectCode == item.SubjectCode && t.VisitTaskNum == item.VisitTaskNum) && item.ArmEnum == Arm.DoubleReadingArm1) + { + item.IsGenerateJudge = true; + } + } + } if (arbitrationRule == ArbitrationRule.Reading) { - //先确定裁判选定的是谁 - foreach (var item in resultList) + //处理访视裁判标记 + foreach (var visitItem in resultExceptJudgeList.Where(t => t.ReadingCategory == ReadingCategory.Visit)) { - //以最后一次裁判为准 找到最大的裁判的裁判选择的Arm,相同就设置裁判标记 - item.IsGenerateJudge = list.Where(t => t.ReadingCategory == ReadingCategory.Judge && t.SubjectCode == item.SubjectCode && t.VisitTaskNum > item.VisitTaskNum - ).OrderByDescending(t => t.VisitTaskNum).FirstOrDefault()?.JudgeArmEnum == item.ArmEnum ? true : false; + //默认设置为false 只处理为true 和 空的情况 + visitItem.IsGenerateJudge = false; - } - //全局裁判了,选择了那个全局,那么对应全局下面的访视 设置裁判标记 - foreach (var item in resultList.Where(t => t.ReadingCategory == ReadingCategory.Visit)) - { + if (judegeList.Count > 0) + { - var selectJudegeGlobalList = resultList.Where(t => t.ReadingCategory == ReadingCategory.Global && t.IsGenerateJudge == true).ToList(); + var maxFinishedJudge = judegeList.Where(t => t.ReadingTaskState == ReadingTaskState.HaveSigned).FirstOrDefault(); - //全局修改了答案,那么给访视上赋值全局的结果 并且取的是最后的全局 - var existGlobalAnswer = selectJudegeGlobalList.Where(t => t.SubjectCode == item.SubjectCode).SelectMany(t => t.GlobalTaskAnswerList).Where(t => t.VisitTaskId == item.Id) - .OrderByDescending(t => t.GlobalTaskVisitNum).FirstOrDefault()?.Answer; + var maxNotFinishedJudge = judegeList.Where(t => t.ReadingTaskState != ReadingTaskState.HaveSigned).FirstOrDefault(); - item.OverallTumorEvaluationResult = string.IsNullOrEmpty(existGlobalAnswer) ? item.OverallTumorEvaluationResult : existGlobalAnswer; + if (maxFinishedJudge == null && maxNotFinishedJudge != null) + { + //仅有一个未完成的全局裁判,那么都是null + if (visitItem.VisitTaskNum < maxNotFinishedJudge.VisitTaskNum) + { + visitItem.IsGenerateJudge = null; + } + } + else if (maxFinishedJudge != null && maxNotFinishedJudge == null) + { + //全局裁判都完成了,那么以最后一次裁判选择的为准 - item.IsGenerateJudge = true; - } + if (visitItem.ArmEnum == maxFinishedJudge.JudgeArmEnum && visitItem.VisitTaskNum < maxFinishedJudge.VisitTaskNum) + { + visitItem.IsGenerateJudge = true; + } + + else if (visitItem.ArmEnum == Arm.DoubleReadingArm1) + { + visitItem.IsGenerateJudge = true; + } + } + else + { + //两个都不为null 肯定是不同的裁判 + + //在完成裁判之后的,和未完成裁判之前的 + if (/*visitItem.VisitTaskNum < maxNotFinishedJudge.VisitTaskNum &&*/ visitItem.VisitTaskNum > maxFinishedJudge.VisitTaskNum) + { + visitItem.IsGenerateJudge = null; + } + else if (visitItem.ArmEnum == maxFinishedJudge.JudgeArmEnum && visitItem.VisitTaskNum < maxFinishedJudge.VisitTaskNum) + { + visitItem.IsGenerateJudge = true; + } + //else if (visitItem.ArmEnum == Arm.DoubleReadingArm1) + //{ + // visitItem.IsGenerateJudge = true; + //} + + } + } + else + { + //不存在裁判 将R1设置 + if (visitItem.ArmEnum == Arm.DoubleReadingArm1) + { + visitItem.IsGenerateJudge = true; + } + } + #region 全局的维度考虑 - } + //// 该阅片人 subject 已完成的最大的全局(全局都是已完成的任务,裁判可能完成了,可能没完成) + //var subjectMaxGlobal = resultExceptJudgeList.Where(t => t.ReadingCategory == ReadingCategory.Global && t.SubjectCode == item.SubjectCode && t.ArmEnum == item.ArmEnum).OrderByDescending(t => t.VisitTaskNum).FirstOrDefault(); - //如果没有产生裁判,默认选择R1 + ////没有全局 + //if (subjectMaxGlobal == null) + //{ + // //这个时候肯定没有裁判 默认选择R1 - //找到没有裁判的访视任务 - var notJudgeList = resultList.GroupBy(t => new { t.SubjectCode, t.VisitTaskNum }).Where(g => g.All(t => t.IsGenerateJudge == false)).Select(g => new { g.Key.SubjectCode, g.Key.VisitTaskNum }).ToList(); + // if (item.ArmEnum == Arm.DoubleReadingArm1) + // { + // item.IsGenerateJudge = true; + // } - foreach (var item in resultList) - { - if (notJudgeList.Any(t => t.SubjectCode == item.SubjectCode && t.VisitTaskNum == item.VisitTaskNum) && item.ArmEnum == Arm.DoubleReadingArm1) - { - item.IsGenerateJudge = true; + + //} + ////有全局 + //else + //{ + // //判断当前受试者已完成的最大的全局是否有裁判 + // var existSubjectMaxGlobalJudge = judegeList.Where(t => t.SubjectCode == item.SubjectCode && t.VisitTaskNum - ReadingCommon.TaskNumDic[ReadingCategory.Judge] == subjectMaxGlobal.VisitTaskNum).FirstOrDefault(); + + // //最大的全局没有裁判(有一个做完了,有一个没做,或者都做完了,没产生裁判) + // if (existSubjectMaxGlobalJudge == null) + // { + // //找到最大的全局裁判 + // var maxJudgedGlobal= judegeList.Where(t => t.SubjectCode == item.SubjectCode ).OrderByDescending(t => t.VisitTaskNum).FirstOrDefault(); + + + // } + // else + // { + // //将该裁判选择的全局的阅片人之前的裁判标记都设置为是 + + // //是否是裁判选择的 + // if (item.ArmEnum == existSubjectMaxGlobalJudge.JudgeArmEnum) + // { + // //是否是裁判选择之前的 + // if (item.VisitTaskNum < existSubjectMaxGlobalJudge.VisitTaskNum) + // { + // item.IsGenerateJudge = true; + + // } + // } + + // } + + //} + + #endregion } } - - return resultList; + return resultExceptJudgeList; } @@ -1413,8 +1631,10 @@ namespace IRaCIS.Core.Application.Service.Common throw new Exception(_localizer["ExcelExport_UnsupportedExport"]); } - var list = await _repository.Where(t => t.TrialId == queryVisitTask.TrialId && t.TaskState == TaskState.Effect && t.IsAnalysisCreate == false && t.ReadingTaskState == ReadingTaskState.HaveSigned) + var list = await _repository.Where(t => t.TrialId == queryVisitTask.TrialId && t.IsAnalysisCreate == false && t.TaskState == TaskState.Effect) + //访视和全局查询已签名完成的,裁判可以是未签名,未完成的 + .Where(t => (t.ReadingTaskState == ReadingTaskState.HaveSigned && (t.ReadingCategory == ReadingCategory.Visit || t.ReadingCategory == ReadingCategory.Global)) || (t.ReadingCategory == ReadingCategory.Judge)) //.WhereIf(queryVisitTask.SubjectId != null, t => t.SubjectId == queryVisitTask.SubjectId) //.WhereIf(queryVisitTask.TaskState != null, t => t.TaskState == queryVisitTask.TaskState) //.WhereIf(queryVisitTask.IsSelfAnalysis != null, t => t.IsSelfAnalysis == queryVisitTask.IsSelfAnalysis) @@ -1541,10 +1761,6 @@ namespace IRaCIS.Core.Application.Service.Common var query = _repository.Where(t => t.TrialId == queryVisitTask.TrialId && t.TaskState == TaskState.Effect && t.IsAnalysisCreate == false && t.ReadingTaskState == ReadingTaskState.HaveSigned) - //.WhereIf(queryVisitTask.SubjectId != null, t => t.SubjectId == queryVisitTask.SubjectId) - //.WhereIf(queryVisitTask.TaskState != null, t => t.TaskState == queryVisitTask.TaskState) - //.WhereIf(queryVisitTask.IsSelfAnalysis != null, t => t.IsSelfAnalysis == queryVisitTask.IsSelfAnalysis) - .WhereIf(queryVisitTask.TrialReadingCriterionId != null, t => t.TrialReadingCriterionId == queryVisitTask.TrialReadingCriterionId) .WhereIf(queryVisitTask.TrialSiteId != null, t => t.Subject.TrialSiteId == queryVisitTask.TrialSiteId) diff --git a/IRaCIS.Core.Application/Service/Common/InternationalizationService.cs b/IRaCIS.Core.Application/Service/Common/InternationalizationService.cs index 6e3edeeb9..47723708e 100644 --- a/IRaCIS.Core.Application/Service/Common/InternationalizationService.cs +++ b/IRaCIS.Core.Application/Service/Common/InternationalizationService.cs @@ -81,7 +81,9 @@ namespace IRaCIS.Core.Application.Service { var mapItem = _mapper.Map(item); mapItem.InternationalizationType = 0; - mapItem.State = 1; + + // 0 是预翻译 1是已确认 2是后端废弃 + mapItem.State = 0; await _internationalizationRepository.AddAsync(mapItem); } @@ -182,7 +184,7 @@ namespace IRaCIS.Core.Application.Service if (addOrEditInternationalization.InternationalizationType == 1) { - await InternationalizationHelper.AddOrUpdateJsonKeyValueAsync(entity.Code, addOrEditInternationalization.Value, addOrEditInternationalization.ValueCN); + await InternationalizationHelper.AddOrUpdateJsonKeyValueAsync(entity.Code, addOrEditInternationalization.Value, addOrEditInternationalization.ValueCN,addOrEditInternationalization.Description); } else { diff --git a/IRaCIS.Core.Application/Service/Common/MailService.cs b/IRaCIS.Core.Application/Service/Common/MailService.cs index e1c0a65ad..f71f70f4a 100644 --- a/IRaCIS.Core.Application/Service/Common/MailService.cs +++ b/IRaCIS.Core.Application/Service/Common/MailService.cs @@ -322,7 +322,7 @@ namespace IRaCIS.Application.Services }; - await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.UnloginUseEmailResetPassword, messageToSend, emailConfigFunc); + await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.ReviewerLogin, messageToSend, emailConfigFunc); //此时不知道用户 var sucessHandle = GetEmailSuccessHandle(Guid.Empty, verificationCode, emailAddress); diff --git a/IRaCIS.Core.Application/Service/Document/Interface/ITrialDocumentService.cs b/IRaCIS.Core.Application/Service/Document/Interface/ITrialDocumentService.cs index f9957b755..9060e8f1a 100644 --- a/IRaCIS.Core.Application/Service/Document/Interface/ITrialDocumentService.cs +++ b/IRaCIS.Core.Application/Service/Document/Interface/ITrialDocumentService.cs @@ -25,7 +25,7 @@ namespace IRaCIS.Core.Application.Contracts Task> GetTrialUserSelect(Guid trialId); - PageOutput GetTrialSystemDocumentList(DocumentTrialUnionQuery querySystemDocument); + Task> GetTrialSystemDocumentList(DocumentTrialUnionQuery querySystemDocument); List GetTrialUserDocumentList(Guid trialId); } } \ No newline at end of file diff --git a/IRaCIS.Core.Application/Service/Document/TrialDocumentService.cs b/IRaCIS.Core.Application/Service/Document/TrialDocumentService.cs index 1c32b6040..44f1b0324 100644 --- a/IRaCIS.Core.Application/Service/Document/TrialDocumentService.cs +++ b/IRaCIS.Core.Application/Service/Document/TrialDocumentService.cs @@ -26,8 +26,8 @@ namespace IRaCIS.Core.Application.Services private readonly IRepository _trialDocumentRepository; private readonly IRepository _trialDocUserTypeConfirmedUserRepository; private readonly IRepository _trialRepository; - private readonly ISystemDocumentService _systemDocumentService; - private readonly IRepository _systemDocConfirmedUserRepository; + private readonly ISystemDocumentService _systemDocumentService; + private readonly IRepository _systemDocConfirmedUserRepository; private readonly IRepository _systemDocumentRepository; private readonly IRepository _trialCriterionAdditionalAssessmentTypeRepository; private readonly IRepository _readingQuestionCriterionTrialRepository; @@ -36,8 +36,8 @@ namespace IRaCIS.Core.Application.Services public TrialDocumentService(IRepository trialDocumentRepository, IRepository trialDocUserTypeConfirmedUserRepository, IRepository trialRepository, - ISystemDocumentService systemDocumentService, - IRepository systemDocConfirmedUserRepository, + ISystemDocumentService systemDocumentService, + IRepository systemDocConfirmedUserRepository, IRepository trialCriterionAdditionalAssessmentTypeRepository, IRepository readingQuestionCriterionTrialRepository , IRepository systemDocumentRepository) @@ -45,8 +45,8 @@ namespace IRaCIS.Core.Application.Services _trialDocumentRepository = trialDocumentRepository; this._trialDocUserTypeConfirmedUserRepository = trialDocUserTypeConfirmedUserRepository; this._trialRepository = trialRepository; - this._systemDocumentService = systemDocumentService; - this._systemDocConfirmedUserRepository = systemDocConfirmedUserRepository; + this._systemDocumentService = systemDocumentService; + this._systemDocConfirmedUserRepository = systemDocConfirmedUserRepository; _systemDocumentRepository = systemDocumentRepository; _readingQuestionCriterionTrialRepository = readingQuestionCriterionTrialRepository; _trialCriterionAdditionalAssessmentTypeRepository = trialCriterionAdditionalAssessmentTypeRepository; @@ -64,7 +64,7 @@ namespace IRaCIS.Core.Application.Services var trialDocumentQueryable = _trialDocumentRepository.AsQueryable(true).Where(t => t.TrialId == queryTrialDocument.TrialId) .WhereIf(!string.IsNullOrEmpty(queryTrialDocument.Name), t => t.Name.Contains(queryTrialDocument.Name)) .WhereIf(queryTrialDocument.FileTypeId != null, t => t.FileTypeId == queryTrialDocument.FileTypeId) - .WhereIf(queryTrialDocument.UserTypeId != null, t => t.NeedConfirmedUserTypeList.Any(t=>t.NeedConfirmUserTypeId== queryTrialDocument.UserTypeId) ) + .WhereIf(queryTrialDocument.UserTypeId != null, t => t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == queryTrialDocument.UserTypeId)) .WhereIf(queryTrialDocument.IsDeleted != null, t => t.IsDeleted == queryTrialDocument.IsDeleted) .ProjectTo(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken, isEn_Us = _userInfo.IsEn_Us }); @@ -75,17 +75,17 @@ namespace IRaCIS.Core.Application.Services public async Task> GetTrialSignDocumentList(TrialDocQuery querySystemDocument) { var trialDocQueryable = from trialDoc in _trialDocumentRepository.AsQueryable(true) - .WhereIf(querySystemDocument.TrialId!=null,t=>t.TrialId==querySystemDocument.TrialId) - .Where(t => t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == _userInfo.UserTypeId) ) + .WhereIf(querySystemDocument.TrialId != null, t => t.TrialId == querySystemDocument.TrialId) + .Where(t => t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == _userInfo.UserTypeId)) - join trialUser in _repository.Where(t=>t.UserId==_userInfo.Id) on trialDoc.TrialId equals trialUser.TrialId + join trialUser in _repository.Where(t => t.UserId == _userInfo.Id) on trialDoc.TrialId equals trialUser.TrialId join confirm in _repository.Where() on new { trialUser.UserId, TrialDocumentId = trialDoc.Id } equals new { UserId = confirm.ConfirmUserId, confirm.TrialDocumentId } into cc from confirm in cc.DefaultIfEmpty() select new TrialSignDocView() { - TrialCode=trialDoc.Trial.TrialCode, + TrialCode = trialDoc.Trial.TrialCode, ResearchProgramNo = trialDoc.Trial.ResearchProgramNo, ExperimentName = trialDoc.Trial.ExperimentName, Id = trialDoc.Id, @@ -116,7 +116,7 @@ namespace IRaCIS.Core.Application.Services .WhereIf(querySystemDocument.IsSigned == false, t => t.ConfirmTime == null); - return await trialDocQueryable.ToPagedListAsync(querySystemDocument.PageIndex, querySystemDocument.PageSize, querySystemDocument.SortField, querySystemDocument.Asc); + return await trialDocQueryable.ToPagedListAsync(querySystemDocument.PageIndex, querySystemDocument.PageSize, querySystemDocument.SortField, querySystemDocument.Asc); } @@ -142,19 +142,19 @@ namespace IRaCIS.Core.Application.Services PageSize = 1, })).Data; } - else + else { result = await _systemDocumentService.getWaitSignSysDocList(new SystemDocumentQuery() { - PageIndex=1, + PageIndex = 1, IsSigned = false, - PageSize=1, - Asc=false, - SortField="UpdateTime", - }); + PageSize = 1, + Asc = false, + SortField = "UpdateTime", + }); + + } - } - if (result.CurrentPageData.Count > 0) { @@ -823,7 +823,7 @@ namespace IRaCIS.Core.Application.Services /// [HttpPost] [Obsolete] - public PageOutput GetTrialSystemDocumentList(DocumentTrialUnionQuery querySystemDocument) + public async Task> GetTrialSystemDocumentList(DocumentTrialUnionQuery querySystemDocument) { var systemDocumentQueryable = _repository .WhereIf(!_userInfo.IsAdmin, t => t.IsDeleted == false) @@ -867,7 +867,7 @@ namespace IRaCIS.Core.Application.Services .WhereIf(!string.IsNullOrEmpty(querySystemDocument.Name), t => t.Name.Contains(querySystemDocument.Name)) .WhereIf(querySystemDocument.FileTypeId != null, t => t.FileTypeId == querySystemDocument.FileTypeId); - return unionQuery.ToPagedList(querySystemDocument.PageIndex, querySystemDocument.PageSize, querySystemDocument.SortField, querySystemDocument.Asc); + return await unionQuery.ToPagedListAsync(querySystemDocument.PageIndex, querySystemDocument.PageSize, querySystemDocument.SortField, querySystemDocument.Asc); } #endregion diff --git a/IRaCIS.Core.Application/Service/Document/TrialEmailNoticeConfigService.cs b/IRaCIS.Core.Application/Service/Document/TrialEmailNoticeConfigService.cs index dbd0d57d0..5698b1e26 100644 --- a/IRaCIS.Core.Application/Service/Document/TrialEmailNoticeConfigService.cs +++ b/IRaCIS.Core.Application/Service/Document/TrialEmailNoticeConfigService.cs @@ -1272,6 +1272,8 @@ namespace IRaCIS.Core.Application.Service public async Task> GetSysEmailNoticeConfigList(EmailNoticeConfigQuery queryEmailNoticeConfig) { var emailNoticeConfigQueryable = _emailNoticeConfigRepository + .WhereIf(queryEmailNoticeConfig.SystemLevel == null, t => t.SystemLevel == SysEmailLevel.not_sys) + .WhereIf(queryEmailNoticeConfig.SystemLevel != null, t => t.SystemLevel == queryEmailNoticeConfig.SystemLevel) .WhereIf(queryEmailNoticeConfig.BusinessScenarioEnum != null, t => t.BusinessScenarioEnum == queryEmailNoticeConfig.BusinessScenarioEnum) .WhereIf(queryEmailNoticeConfig.IsReturnRequired != null, t => t.IsReturnRequired == queryEmailNoticeConfig.IsReturnRequired) .WhereIf(queryEmailNoticeConfig.IsEnable != null, t => t.IsEnable == queryEmailNoticeConfig.IsEnable) @@ -1477,7 +1479,7 @@ namespace IRaCIS.Core.Application.Service { //---发件人配置错误,请核对服务器地址或者授权码是否填写有误 - throw new BusinessValidationFailedException(_localizer["TrialEmailN_InvalidSenderEmailConfig"] + ex.Message); + throw new BusinessValidationFailedException(_localizer["TrialEmailN_InvalidSenderEmailConfig"]); } diff --git a/IRaCIS.Core.Application/Service/Fixed/CriterionAdditionalAssessment.cs b/IRaCIS.Core.Application/Service/Fixed/CriterionAdditionalAssessment.cs index 2cb4b236a..54ba91882 100644 --- a/IRaCIS.Core.Application/Service/Fixed/CriterionAdditionalAssessment.cs +++ b/IRaCIS.Core.Application/Service/Fixed/CriterionAdditionalAssessment.cs @@ -66,7 +66,7 @@ namespace IRaCIS.Core.Application.Service { GroupId=gropId, LimitEdit=LimitEdit.OnlyBaseLine, - DictionaryCode="YesOrNoOrNa", + DictionaryCode="YesOrNoOrNE", IsJudgeQuestion=false, IsShowInDicom=false, GlobalReadingShowType=GlobalReadingShowType.NotShow, diff --git a/IRaCIS.Core.Application/Service/Inspection/InspectionService.cs b/IRaCIS.Core.Application/Service/Inspection/InspectionService.cs index b3f13a70b..c73aa2032 100644 --- a/IRaCIS.Core.Application/Service/Inspection/InspectionService.cs +++ b/IRaCIS.Core.Application/Service/Inspection/InspectionService.cs @@ -3,6 +3,7 @@ using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Application.Service.Inspection.DTO; using IRaCIS.Core.Application.Service.Inspection.Interface; using IRaCIS.Core.Domain.Share; +using IRaCIS.Core.Infra.EFCore.Common; using IRaCIS.Core.Infrastructure; using Panda.DynamicWebApi.Attributes; @@ -58,8 +59,11 @@ namespace IRaCIS.Core.Application.Service.Inspection join usertype in _repository.GetQueryable().IgnoreQueryFilters() on leftuser.UserTypeId equals usertype.Id into usertypetemp from leftusertype in usertypetemp.DefaultIfEmpty() - //join trialCriterion in _repository.GetQueryable().IgnoreQueryFilters() on data.TrialReadingCriterionId equals trialCriterion.Id into criterion - //from leftCriterion in criterion.DefaultIfEmpty() + join visttask in _repository.GetQueryable().IgnoreQueryFilters() on data.VisitTaskId equals visttask.Id into visttasktemp + from leftvisttask in visttasktemp.DefaultIfEmpty() + + //join trialCriterion in _repository.GetQueryable().IgnoreQueryFilters() on data.TrialReadingCriterionId equals trialCriterion.Id into criterion + //from leftCriterion in criterion.DefaultIfEmpty() //join moduleTyped in _repository.GetQueryable().Where(x => x.Code == "ModuleType") on 1 equals 1 //join moduleTypec in _repository.GetQueryable() on new { ParentId = moduleTyped.Id, ModuleType = data.ModuleType } equals new { ParentId = moduleTypec.ParentId.Value, ModuleType = moduleTypec.Value } into moduleTypectemp @@ -131,7 +135,7 @@ namespace IRaCIS.Core.Application.Service.Inspection ExperimentName = leftrial.ExperimentName, - SubjectCode = leftsubject.Code, + SubjectCode = leftvisttask.BlindSubjectCode.IsNullOrEmpty()? leftsubject.Code: leftvisttask.BlindSubjectCode, SiteCode = lefttrialSite.TrialSiteCode, ResearchProgramNo = leftrial.ResearchProgramNo, diff --git a/IRaCIS.Core.Application/Service/Institution/DTO/SiteModel.cs b/IRaCIS.Core.Application/Service/Institution/DTO/SiteModel.cs index e900e5c59..55213b696 100644 --- a/IRaCIS.Core.Application/Service/Institution/DTO/SiteModel.cs +++ b/IRaCIS.Core.Application/Service/Institution/DTO/SiteModel.cs @@ -36,6 +36,7 @@ namespace IRaCIS.Application.Contracts public class SiteSelectionDTO { public Guid Id { get; set; } + public string SiteName { get; set; } = String.Empty; public string SiteNameCN { get; set; } = String.Empty; diff --git a/IRaCIS.Core.Application/Service/Management/DTO/UserModel.cs b/IRaCIS.Core.Application/Service/Management/DTO/UserModel.cs index a54ec9ad4..3f22371f2 100644 --- a/IRaCIS.Core.Application/Service/Management/DTO/UserModel.cs +++ b/IRaCIS.Core.Application/Service/Management/DTO/UserModel.cs @@ -39,7 +39,7 @@ namespace IRaCIS.Application.Contracts public Guid Id { get; set; } public string UserName { get; set; } = string.Empty; public string RealName { get; set; } = string.Empty; - public int Sex { get; set; } // 1-男 2-女 + public int? Sex { get; set; } // 1-男 2-女 /// /// LastLoginIP @@ -131,7 +131,7 @@ namespace IRaCIS.Application.Contracts public string FirstName { get; set; } = string.Empty; public string LastName { get; set; } = string.Empty; - public int Sex { get; set; } // 1-男 2-女 + public int? Sex { get; set; } // 1-男 2-女 public int Status { get; set; } = 1; // 0-已删除 1-正常 diff --git a/IRaCIS.Core.Application/Service/Management/UserService.cs b/IRaCIS.Core.Application/Service/Management/UserService.cs index a719dbab3..3fe37375c 100644 --- a/IRaCIS.Core.Application/Service/Management/UserService.cs +++ b/IRaCIS.Core.Application/Service/Management/UserService.cs @@ -16,9 +16,9 @@ using EasyCaching.Core; using IRaCIS.Core.Application.Contracts; using LoginReturnDTO = IRaCIS.Application.Contracts.LoginReturnDTO; using IRaCIS.Core.Application.Auth; -using BeetleX.Redis.Commands; using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Application.Helper; +using IP2Region.Net.Abstractions; namespace IRaCIS.Application.Services { @@ -38,6 +38,7 @@ namespace IRaCIS.Application.Services private readonly IReadingImageTaskService _readingImageTaskService; private readonly IOptionsMonitor _verifyConfig; private readonly SystemEmailSendConfig _systemEmailConfig; + public ISearcher _searcher; public UserService(IRepository userRepository, @@ -45,6 +46,7 @@ namespace IRaCIS.Application.Services IRepository verificationCodeRepository, IRepository doctorRepository, IEasyCachingProvider cache, + ISearcher searcher, IReadingImageTaskService readingImageTaskService, IRepository userTrialRepository, IOptionsMonitor verifyConfig, @@ -58,6 +60,7 @@ namespace IRaCIS.Application.Services this._userPassWordLogRepository = userPassWordLogRepository; _verifyConfig = verifyConfig; _cache = cache; + this._searcher = searcher; this._readingImageTaskService = readingImageTaskService; _userRepository = userRepository; _mailVerificationService = mailVerificationService; @@ -794,7 +797,7 @@ namespace IRaCIS.Application.Services } //超过90天没修改密码 - if (loginUser.LastChangePassWordTime != null && DateTime.Now.AddDays(-90) > loginUser.LastChangePassWordTime.Value) + if (_verifyConfig.CurrentValue.IsNeedChangePassWord&& loginUser.LastChangePassWordTime != null && DateTime.Now.AddDays(-_verifyConfig.CurrentValue.ChangePassWordDays) > loginUser.LastChangePassWordTime.Value) { loginUser.LoginState = 1; } @@ -803,12 +806,14 @@ namespace IRaCIS.Application.Services //登录成功 清除缓存 _cache.Set(cacheKey, 0, TimeSpan.FromMinutes(lockoutMinutes)); + var ipinfo = _searcher.Search(_userInfo.IP); + var iPRegion = string.Join('|', ipinfo.Split('|').TakeLast(3)); if (loginUser.LastLoginIP != string.Empty) { // 与上一次IP不一致 - if (loginUser.LastLoginIP != _userInfo.IP) + if (loginUser.LastLoginIP != iPRegion) { loginUser.LoginState = 2; } @@ -829,10 +834,10 @@ namespace IRaCIS.Application.Services }); } - + await _userRepository.BatchUpdateNoTrackingAsync(x => x.Id == loginUser.Id, x => new User() { - LastLoginIP = _userInfo.IP, + LastLoginIP = iPRegion, LastLoginTime = DateTime.Now }); diff --git a/IRaCIS.Core.Application/Service/Management/UserTypeService.cs b/IRaCIS.Core.Application/Service/Management/UserTypeService.cs index f12c9e3e8..f608346b2 100644 --- a/IRaCIS.Core.Application/Service/Management/UserTypeService.cs +++ b/IRaCIS.Core.Application/Service/Management/UserTypeService.cs @@ -119,12 +119,12 @@ namespace IRaCIS.Core.Application.Contracts if (userTypeSelectEnum == UserTypeSelectEnum.InnerUser) { - userTypeEnums = new List() { UserTypeEnum.IQC, UserTypeEnum.APM, UserTypeEnum.MIM, UserTypeEnum.QA ,UserTypeEnum.MW,UserTypeEnum.MC}; + userTypeEnums = new List() { UserTypeEnum.ClinicalResearchCoordinator, UserTypeEnum.ProjectManager, UserTypeEnum.CRA, UserTypeEnum.IQC, UserTypeEnum.APM, UserTypeEnum.MIM, UserTypeEnum.QA ,UserTypeEnum.MW,UserTypeEnum.MC}; - if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.SuperAdmin) - { - userTypeEnums.Add(UserTypeEnum.ProjectManager); - } + //if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.SuperAdmin) + //{ + // userTypeEnums.Add(UserTypeEnum.ProjectManager); + //} } if (userTypeSelectEnum == UserTypeSelectEnum.SiteSurvey) diff --git a/IRaCIS.Core.Application/Service/Management/_MapConfig.cs b/IRaCIS.Core.Application/Service/Management/_MapConfig.cs index 5619e7127..d9ec78199 100644 --- a/IRaCIS.Core.Application/Service/Management/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/Management/_MapConfig.cs @@ -131,7 +131,7 @@ namespace IRaCIS.Core.Application.Service .ForMember(d => d.ExperimentName, c => c.MapFrom(t => t.Trial.ExperimentName)) .ForMember(d => d.TrialCode, c => c.MapFrom(t => t.Trial.TrialCode)) .ForMember(d => d.SubjectCode, c => c.MapFrom(t => t.Subject.Code)) - .ForMember(d => d.TrialSiteCode, c => c.MapFrom(t => t.TrialSite.TrialSiteCode)) + .ForMember(d => d.TrialSiteCode, c => c.MapFrom(t => t.VisitTask.IsAnalysisCreate? t.VisitTask.BlindTrialSiteCode: t.TrialSite.TrialSiteCode)) .ForMember(d => d.SubjectVisitName, c => c.MapFrom(t => t.SubjectVisit.VisitName)) .ForMember(d => d.FeedBackUserName, c => c.MapFrom(t => t.CreateUser.UserName)) .ForMember(d => d.FeedBackFullName, c => c.MapFrom(t => t.CreateUser.FullName)) diff --git a/IRaCIS.Core.Application/Service/QC/DTO/QCListViewModel.cs b/IRaCIS.Core.Application/Service/QC/DTO/QCListViewModel.cs index 12e02ab62..c06c05c5f 100644 --- a/IRaCIS.Core.Application/Service/QC/DTO/QCListViewModel.cs +++ b/IRaCIS.Core.Application/Service/QC/DTO/QCListViewModel.cs @@ -157,6 +157,8 @@ namespace IRaCIS.Core.Application.Contracts public bool IsHaveVisitClinicalData { get; set; } = false; + public bool IsPacsConnectConfiged { get; set; } + } @@ -201,15 +203,15 @@ namespace IRaCIS.Core.Application.Contracts { //关闭 未关闭 [DictionaryTranslateAttribute("CheckIsClosedEnum")] - public ChallengeStateEnum CheckIsClosedEnum { get; set; } + public ChallengeStateEnum ChallengeState { get; set; } //强行要分为两个字段 有无质疑 [DictionaryTranslateAttribute("YesOrNo")] - public bool IsChallengeClosed => (int)CheckIsClosedEnum > 0; + public bool IsHaveChallenge => (int)ChallengeState > 0; //临床数据收集 - public string ClinicalDataCollect => $"{DicomStudyCount},{NoneDicomStudyCount}{(IsBaseLine? (ClinicalInformationTransmissionEnum>0 &&IsHaveClinicalData ? "w/" : "w/o") :"" )}"; + public string ClinicalDataCollect => $"{DicomStudyCount},{NoneDicomStudyCount}{(IsBaseLine? (ClinicalInformationTransmissionEnum>0 && IsHaveClinicalData ? ",w/" : ",w/o") :"" )}"; public int? DicomStudyCount { get; set; } public int? NoneDicomStudyCount { get; set; } @@ -266,7 +268,7 @@ namespace IRaCIS.Core.Application.Contracts public string CurrentActionUserName { get; set; } - + public string HistoryAuditUserName => string.Join(' ', PreliminaryAuditUserName, ReviewAuditUserName); } public class QCChanllengeExportDto @@ -325,7 +327,7 @@ namespace IRaCIS.Core.Application.Contracts //public bool IsUrgent { get; set; } - //public DateTime? ReUploadedTime { get; set; } + public DateTime? ReUploadedTime { get; set; } //public RequestBackStateEnum RequestBackState { get; set; } @@ -676,6 +678,8 @@ namespace IRaCIS.Core.Application.Contracts { public string? TalkContent { get; set; } = String.Empty; public string BlindName { get; set; } = String.Empty; + + [DictionaryTranslateAttribute("YesOrNo")] public bool IsUrgent { get; set; } public DateTime? CheckPassedTime { get; set; } @@ -831,11 +835,12 @@ namespace IRaCIS.Core.Application.Contracts public AuditAdvice AuditAdviceEnum { get; set; } //审核结论 - [DictionaryTranslateAttribute("IsPass")] + public bool IsHaveQuestion { get; set; } + [DictionaryTranslateAttribute("IsPass")] - + public bool? IsHaveQuestionView => AuditState == MedicalReviewAuditState.WaitAudit ? null : IsHaveQuestion; //public UserSimpleInfo DoctorUser { get; set; } //public UserSimpleInfo MedicalManagerUser { get; set; } @@ -932,6 +937,9 @@ namespace IRaCIS.Core.Application.Contracts public string SubjectCode { get; set; } = String.Empty; public Guid Id { get; set; } + + public Guid DoctorUserId { get; set; } + public string TaskName { get; set; } public string TaskBlindName { get; set; } @@ -944,6 +952,8 @@ namespace IRaCIS.Core.Application.Contracts public Arm ArmEnum { get; set; } public string UserName { get; set; } + public ReadingTaskState ReadingTaskState { get; set; } + public ReadingCategory ReadingCategory { get; set; } [DictionaryTranslateAttribute("ExistDisease", CriterionType.RECIST1Point1, nameof(OverallTumorEvaluationExport.IsBaseline), "true")] @@ -958,15 +968,17 @@ namespace IRaCIS.Core.Application.Contracts public Arm? JudgeArmEnum { get; set; } + //public Guid? JudgeResultTaskId { get; set; } + //根据裁判的任务结果 设置访视任务的这个字段 该字段表示 裁判认同该任务的结果 [DictionaryTranslateAttribute("YesOrNo")] - public bool IsGenerateJudge { get; set; } + public bool? IsGenerateJudge { get; set; } - [JsonIgnore] + //[JsonIgnore] - public List GlobalTaskAnswerList { get; set; } + //public List GlobalTaskAnswerList { get; set; } } diff --git a/IRaCIS.Core.Application/Service/QC/QCListService.cs b/IRaCIS.Core.Application/Service/QC/QCListService.cs index 657675744..a44086439 100644 --- a/IRaCIS.Core.Application/Service/QC/QCListService.cs +++ b/IRaCIS.Core.Application/Service/QC/QCListService.cs @@ -547,6 +547,7 @@ namespace IRaCIS.Core.Application.Image.QA config.IsHaveStudyClinicalData = await _clinicalDataTrialSetRepository.AnyAsync(x => x.IsConfirm && x.TrialId == visit.TrialId && x.ClinicalDataLevel == ClinicalLevel.Study); + config.IsPacsConnectConfiged= await _subjectVisitRepository.Where(t=>t.Id==subjectVisitId).AnyAsync(t=>t.Trial.IsPACSConnect && t.Subject.TrialSite.TrialSiteDicomAEList.Any()); return (list, config); } diff --git a/IRaCIS.Core.Application/Service/QC/QCQuestionService.cs b/IRaCIS.Core.Application/Service/QC/QCQuestionService.cs index 1d574c465..3e9a526e9 100644 --- a/IRaCIS.Core.Application/Service/QC/QCQuestionService.cs +++ b/IRaCIS.Core.Application/Service/QC/QCQuestionService.cs @@ -103,8 +103,10 @@ namespace IRaCIS.Core.Application.Contracts .OrderByDescending(x=>x.LanguageType) .ThenBy(t=>t.ShowOrder) .ProjectTo(_mapper.ConfigurationProvider); - - return await QCQuestionQueryable.ToPagedListAsync(queryQCQuestionConfigure.PageIndex, queryQCQuestionConfigure.PageSize, new string[2] { "LanguageType desc", "ShowOrder asc" }); + + var defalutSortArray = new string[] { nameof(QCQuestionConfigureView.LanguageType) + " desc", nameof(QCQuestionConfigureView.ShowOrder) }; + + return await QCQuestionQueryable.ToPagedListAsync(queryQCQuestionConfigure.PageIndex, queryQCQuestionConfigure.PageSize, new string[2] { "LanguageType desc", "ShowOrder asc" }); } public async Task AddOrUpdateQCQuestionConfigure(QCQuestionAddOrEdit addOrEditQCQuestionConfigure) diff --git a/IRaCIS.Core.Application/Service/QC/TrialQCQuestionService.cs b/IRaCIS.Core.Application/Service/QC/TrialQCQuestionService.cs index 0521af0ca..ea2f77451 100644 --- a/IRaCIS.Core.Application/Service/QC/TrialQCQuestionService.cs +++ b/IRaCIS.Core.Application/Service/QC/TrialQCQuestionService.cs @@ -54,9 +54,9 @@ namespace IRaCIS.Core.Application.Contracts var trialQCQuestionQueryable = _trialQcQuestionRepository.Where(t => t.TrialId == queryTrialQCQuestionConfigure.TrialId) .WhereIf(!string.IsNullOrWhiteSpace(queryTrialQCQuestionConfigure.QuestionName), t => t.QuestionName.Contains(queryTrialQCQuestionConfigure.QuestionName)) .WhereIf(!string.IsNullOrWhiteSpace(queryTrialQCQuestionConfigure.Type), t => t.Type.Contains(queryTrialQCQuestionConfigure.Type)) - .WhereIf(queryTrialQCQuestionConfigure.IsEnable != null, t => t.IsEnable == queryTrialQCQuestionConfigure.IsEnable) - .WhereIf(queryTrialQCQuestionConfigure.IsRequired != null, t => t.IsRequired == queryTrialQCQuestionConfigure.IsRequired) - .WhereIf(queryTrialQCQuestionConfigure.LanguageType != null, t => t.LanguageType == queryTrialQCQuestionConfigure.LanguageType) + .WhereIf(queryTrialQCQuestionConfigure.IsEnable != null, t => t.IsEnable == queryTrialQCQuestionConfigure.IsEnable) + .WhereIf(queryTrialQCQuestionConfigure.IsRequired != null, t => t.IsRequired == queryTrialQCQuestionConfigure.IsRequired) + .WhereIf(queryTrialQCQuestionConfigure.LanguageType != null, t => t.LanguageType == queryTrialQCQuestionConfigure.LanguageType) .ProjectTo(_mapper.ConfigurationProvider); diff --git a/IRaCIS.Core.Application/Service/QC/_MapConfig.cs b/IRaCIS.Core.Application/Service/QC/_MapConfig.cs index 16b0d4ba6..b1bfd53c1 100644 --- a/IRaCIS.Core.Application/Service/QC/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/QC/_MapConfig.cs @@ -25,7 +25,8 @@ namespace IRaCIS.Core.Application.Service .ForMember(d => d.QCProcessEnum, u => u.MapFrom(s => s.Trial.QCProcessEnum)) .ForMember(d => d.SubjectCode, u => u.MapFrom(s => s.Subject.Code)) .ForMember(d => d.SubmitUserName, u => u.MapFrom(s => s.SubmitUser.FullName)) - + .ForMember(d => d.ClinicalInformationTransmissionEnum, u => u.MapFrom(s => s.Trial.ClinicalInformationTransmissionEnum)) + .ForMember(d => d.IsHaveClinicalData, u => u.MapFrom(t => t.IsBaseLine ? t.PreviousHistoryList.Any() || t.PreviousOtherList.Any() || t.ReadingClinicalDataList.Any(x => x.ClinicalDataTrialSet.UploadRole == Domain.Share.UploadRole.CRC && x.ReadingClinicalDataPDFList.Count > 0) || t.PreviousSurgeryList.Any() : false)) @@ -116,7 +117,7 @@ namespace IRaCIS.Core.Application.Service .ForMember(d => d.SubjectCode, u => u.MapFrom(s => s.Subject.Code)) .ForMember(d => d.TrialSiteCode, u => u.MapFrom(s => s.TrialSite.TrialSiteCode)) - .ForMember(d => d.CheckDialogStr, u => u.MapFrom(t => string.Join(" | ", t.CheckChallengeDialogList.OrderBy(t => t.CreateTime).Select(c => c.CreateUser.UserName + " " + c.CreateTime.ToString("yyyy-MM-dd HH:mm:ss") + " :" + c.TalkContent)))) + .ForMember(d => d.CheckDialogStr, u => u.MapFrom(t => string.Join("\n\n", t.CheckChallengeDialogList.OrderBy(t => t.CreateTime).Select(c => c.CreateUser.UserName + " (" + c.CreateTime.ToString("yyyy-MM-dd HH:mm:ss") + ") :" + c.TalkContent)))) .ForMember(d => d.ModalityList, c => c.MapFrom(s => (s.NoneDicomStudyList.Select(t => t.Modality) .Union(s.StudyList.Select(k => k.ModalityForEdit))).Distinct())) @@ -154,7 +155,7 @@ namespace IRaCIS.Core.Application.Service .ForMember(o => o.MedicalNo, t => t.MapFrom(u => u.VisitTask.Subject.MedicalNo)) .ForMember(o => o.DoctorUserName, t => t.MapFrom(u => u.VisitTask.DoctorUser.UserName)) .ForMember(o => o.MedicalManagerUserName, t => t.MapFrom(u => u.MedicalManagerUser.UserName)) - .ForMember(o => o.QuestionContent, t => t.MapFrom(u=> string.Join('|', u.ReadingMedicalReviewDialogList.Where(t => t.IsHaveQuestion).Select(t=>t.Questioning))) ); + .ForMember(o => o.QuestionContent, t => t.MapFrom(u=> string.Join("\n\n", u.ReadingMedicalReviewDialogList.Where(t => t.IsHaveQuestion).Select(t=>t.Questioning))) ); CreateMap() .ForMember(o => o.TrialReadingCriterionName, t => t.MapFrom(u => u.TrialReadingCriterion.CriterionName)) @@ -191,15 +192,14 @@ namespace IRaCIS.Core.Application.Service .ForMember(o => o.OverallTumorEvaluationResult, t => t.MapFrom(u => criterionType == CriterionType.RECIST1Point1 ?( u.SourceSubjectVisit.IsBaseLine==true ? u.ReadingTaskQuestionAnswerList.Where(c => c.ReadingQuestionTrial.QuestionType == QuestionType.ExistDisease).FirstOrDefault()!.Answer: - u.ReadingTaskQuestionAnswerList.Where(c => c.ReadingQuestionTrial.QuestionType == QuestionType.Tumor).FirstOrDefault()!.Answer) + u.ReadingTaskQuestionAnswerList.Where(c => c.ReadingQuestionTrial.QuestionType == QuestionType.Tumor).Select(t=>t.IsGlobalChange?t.GlobalChangeAnswer:t.Answer).FirstOrDefault()) : criterionType == CriterionType.PCWG3 ? u.ReadingTaskQuestionAnswerList.Where(c => c.ReadingQuestionTrial.QuestionType == QuestionType.SiteVisitForTumorEvaluation).FirstOrDefault()!.Answer : String.Empty )) .ForMember(o => o.TrialSiteCode, t => t.MapFrom(u => u.Subject.TrialSite.TrialSiteCode)) .ForMember(o => o.SubjectCode, t => t.MapFrom(u => u.Subject.Code)) .ForMember(o => o.UserName, t => t.MapFrom(u => u.DoctorUser.UserName)) - .ForMember(o => o.GlobalTaskAnswerList, t => t.MapFrom(u => u.GlobalVisitResultList.Where(t=>t.GlobalAnswerType== GlobalAnswerType.Question) - .Select(c=>new GlobalAnswerInfo() { GlobalTaskVisitNum=c.VisitTask.VisitTaskNum,VisitTaskId=c.TaskId ,Answer=c.Answer}))) + //.ForMember(o => o.GlobalTaskAnswerList, t => t.MapFrom(u => u.GlobalVisitResultList.Where(t=>t.GlobalAnswerType== GlobalAnswerType.Question).Select(c=>new GlobalAnswerInfo() { GlobalTaskVisitNum=c.VisitTask.VisitTaskNum,VisitTaskId=c.TaskId ,Answer=c.Answer}))) ; diff --git a/IRaCIS.Core.Application/Service/Reading/AdditionalEvaluate/SubjectCriteriaEvaluationService.cs b/IRaCIS.Core.Application/Service/Reading/AdditionalEvaluate/SubjectCriteriaEvaluationService.cs index e6b07c261..82f19867c 100644 --- a/IRaCIS.Core.Application/Service/Reading/AdditionalEvaluate/SubjectCriteriaEvaluationService.cs +++ b/IRaCIS.Core.Application/Service/Reading/AdditionalEvaluate/SubjectCriteriaEvaluationService.cs @@ -442,9 +442,9 @@ namespace IRaCIS.Core.Application.Service join subjectCriteriaEvaluationVisitFilter in _subjectCriteriaEvaluationVisitFilterRepository .Where(t => t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId) - .WhereIf(inQuery.ImageDeterminationResultState != null, t => t.ImageDeterminationResultState == inQuery.ImageDeterminationResultState) - .WhereIf(inQuery.ImageFilterState != null, t => t.ImageFilterState == inQuery.ImageFilterState) - .WhereIf(inQuery.IsGeneratedTask != null, t => t.IsGeneratedTask == inQuery.IsGeneratedTask) + .WhereIf(inQuery.ImageDeterminationResultState != null, t => t.ImageDeterminationResultState == inQuery.ImageDeterminationResultState) + .WhereIf(inQuery.ImageFilterState != null, t => t.ImageFilterState == inQuery.ImageFilterState) + .WhereIf(inQuery.IsGeneratedTask != null, t => t.IsGeneratedTask == inQuery.IsGeneratedTask) on subjectVisit.Id equals subjectCriteriaEvaluationVisitFilter.SubjectVisitId //into d from subjectCriteriaEvaluationVisitFilter in d.DefaultIfEmpty() @@ -687,7 +687,7 @@ namespace IRaCIS.Core.Application.Service var subjectVisit = await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == command.SubjectVisitId); //仅仅影响该标准自己的任务 - Expression> filterExpression = t => t.TrialId == command.TrialId && t.SubjectId == command.SubjectId && t.TaskState == TaskState.Effect && t.TaskAllocationState == TaskAllocationState.Allocated + Expression> filterExpression = t => t.TrialId == command.TrialId && t.SubjectId == command.SubjectId && t.TaskState == TaskState.Effect /*&& t.TaskAllocationState == TaskAllocationState.Allocated*/ && t.TrialReadingCriterionId == command.TrialReadingCriterionId; //有序 diff --git a/IRaCIS.Core.Application/Service/Reading/ClinicalData/ClinicalAnswerService.cs b/IRaCIS.Core.Application/Service/Reading/ClinicalData/ClinicalAnswerService.cs index 19ca221bf..8f299b175 100644 --- a/IRaCIS.Core.Application/Service/Reading/ClinicalData/ClinicalAnswerService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ClinicalData/ClinicalAnswerService.cs @@ -637,8 +637,9 @@ namespace IRaCIS.Core.Application.Service ModuleName=x.ModuleName, }); + var defalutSortArray = new string[] { nameof(GetCRCConfirmListOutDto.SubjectCode) + " desc", nameof(GetCRCConfirmListOutDto.LatestScanDate) }; - var result = await query.ToPagedListAsync(inDto.PageIndex, inDto.PageSize, new string[2] { "SubjectCode asc", "LatestScanDate asc" }); + var result = await query.ToPagedListAsync(inDto.PageIndex, inDto.PageSize, new string[2] { "SubjectCode asc", "LatestScanDate asc" }); var formList = await _clinicalFormRepository.Where(x => x.TrialId == inDto.TrialId) .Where(x => x.ClinicalDataTrialSet.UploadRole == UploadRole.CRC) diff --git a/IRaCIS.Core.Application/Service/Reading/ClinicalData/ReadingClinicalDataService.cs b/IRaCIS.Core.Application/Service/Reading/ClinicalData/ReadingClinicalDataService.cs index f33e41df5..f7694241b 100644 --- a/IRaCIS.Core.Application/Service/Reading/ClinicalData/ReadingClinicalDataService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ClinicalData/ReadingClinicalDataService.cs @@ -12,7 +12,6 @@ using System.Linq.Dynamic.Core; using Microsoft.Extensions.Logging; using IRaCIS.Core.Infrastructure.Extention; using System.Linq; -using BeetleX.Redis.Commands; using NPOI.SS.Formula.Functions; namespace IRaCIS.Application.Services @@ -394,7 +393,7 @@ namespace IRaCIS.Application.Services //如果先生成了任务,再签名subject级别 PM 临床数据,那么会导致其他标准的任务签名状态无法得到维护 - if (await _repository.AnyAsync(t => t.Id == data.ClinicalDataTrialSetId && t.UploadRole == UploadRole.PM && t.ClinicalDataLevel == ClinicalLevel.Subject)) + if (await _repository.AnyAsync(t => t.Id == data.ClinicalDataTrialSetId && t.UploadRole == UploadRole.PM && (t.ClinicalDataLevel == ClinicalLevel.Subject|| t.ClinicalDataLevel == ClinicalLevel.SubjectVisit))) { var needDealTrialReadingCriterionIdList = _repository.Where(t => t.Id == data.ClinicalDataTrialSetId) .SelectMany(t => t.TrialClinicalDataSetCriteriaList) @@ -431,9 +430,6 @@ namespace IRaCIS.Application.Services // data.IsComplete = inDto.IsComplete; // data.IsSign = true; // data.ReadingClinicalDataState = ReadingClinicalDataStatus.HaveSigned; - - - // var result = await _readingClinicalDataRepository.SaveChangesAsync(); @@ -479,6 +475,7 @@ namespace IRaCIS.Application.Services var needSignCount = 0; var haveSignedCount = _readingClinicalDataRepository.Where(t => t.TrialId == trialId && t.IsSign && t.ReadingClinicalDataState == ReadingClinicalDataStatus.HaveSigned && t.ReadingId == readingId && t.ClinicalDataTrialSet.UploadRole == UploadRole.PM).Count(); + ReadModule readModule = null; if (isVisit) { @@ -514,7 +511,7 @@ namespace IRaCIS.Application.Services else { //判断是影像学 还是肿瘤学阅片 - var readModule = await _readModuleRepository.Where(t => t.Id == readingId).FirstNotNullAsync(); + readModule = await _readModuleRepository.Where(t => t.Id == readingId).FirstNotNullAsync(); //CRC 阅片期自定义结构化录入是否签名 bool crcReadModuleSign = true; @@ -576,7 +573,7 @@ namespace IRaCIS.Application.Services Expression> visitTaskLambda = x => x.TrialId == trialId && x.SubjectId == subjectId && x.TrialReadingCriterionId == trialReadingCritrialId; - if (isVisit) + if (isVisit ||(isVisit==false && readModule.ReadingSetType == ReadingSetType.ImageReading)) { //访视类型的任务 不影响肿瘤学任务的临床数据状态 visitTaskLambda = visitTaskLambda.And(x => x.ArmEnum != Arm.TumorArm); @@ -730,11 +727,14 @@ namespace IRaCIS.Application.Services public async Task<(List, object)> GetReadingOrTaskClinicalDataList(GetReadingOrTaskClinicalDataListInDto inDto) { var readingNameOrTaskBlindName = string.Empty; + var subjectCode = string.Empty; if (inDto.ReadingId == null) { - var visitTask = await _visitTaskRepository.FirstOrDefaultAsync(x => x.Id == inDto.VisitTaskId); - - readingNameOrTaskBlindName = visitTask.TaskBlindName; + var visitTask = await _visitTaskRepository.AsQueryable().Include(x=>x.Subject) + + .FirstOrDefaultAsync(x => x.Id == inDto.VisitTaskId); + subjectCode=visitTask.BlindSubjectCode.IsNullOrEmpty() ? visitTask.Subject.Code : visitTask.BlindSubjectCode; + readingNameOrTaskBlindName = visitTask.TaskBlindName; } inDto.SelectIsSign = false; var result = await GetClinicalDataList(inDto); @@ -777,7 +777,7 @@ namespace IRaCIS.Application.Services return (result, new { - SubjectCode = await _subjectRepository.Where(x => x.Id == inDto.SubjectId).Select(x => x.Code).FirstOrDefaultAsync(), + SubjectCode = subjectCode, ReadingNameOrTaskBlindName = readingNameOrTaskBlindName, }); } @@ -906,7 +906,7 @@ namespace IRaCIS.Application.Services .WhereIf(inDto.SelectIsSign, x => x.IsSign == true) .Where(x => x.ReadingId == inDto.ReadingId) .WhereIf(inDto.TrialReadingCriterionId != null, x => x.ClinicalDataTrialSet.TrialClinicalDataSetCriteriaList.Any(t => t.TrialReadingCriterionId == inDto.TrialReadingCriterionId)) - .Where(x => x.ClinicalDataTrialSet.ClinicalUploadType != ClinicalUploadType.PDF) + .Where(x => x.ClinicalDataTrialSet.ClinicalUploadType != ClinicalUploadType.PDF||x.ClinicalDataTrialSet.ClinicalDataLevel== ClinicalLevel.Study) .Select(x => new GetReadingClinicalDataListOutDto() { ClinicalDataLevel = x.ClinicalDataTrialSet.ClinicalDataLevel, @@ -1185,8 +1185,8 @@ namespace IRaCIS.Application.Services }).ToList(); entity.ReadingClinicalDataState = ReadingClinicalDataStatus.HaveUploaded; - entity.IsBlind = null; - entity.IsComplete = null; + entity.IsBlind = false; + entity.IsComplete = true; entity.FileCount = entity.ReadingClinicalDataPDFList.Count; await _readingConsistentClinicalDataRepository.AddAsync(entity, true); var success = await _readingConsistentClinicalDataRepository.SaveChangesAsync(); @@ -1215,8 +1215,8 @@ namespace IRaCIS.Application.Services if (indto.AddFileList.Count > 0 || indto.AddFileList.Count > 0) { - entity.IsComplete = null; - entity.IsBlind = null; + entity.IsComplete = true; + entity.IsBlind = false; } await _readingConsistentClinicalDataPDFRepository.AddRangeAsync(addFileList); @@ -1227,6 +1227,7 @@ namespace IRaCIS.Application.Services entity.ReadingClinicalDataState = ReadingClinicalDataStatus.HaveUploaded; entity.IsSign = false; entity.FileCount = fileCount; + entity.CreateTime=DateTime.Now; var success = await _readingConsistentClinicalDataRepository.SaveChangesAsync(); return ResponseOutput.Ok(entity.Id); @@ -1267,13 +1268,26 @@ namespace IRaCIS.Application.Services [HttpPost] public async Task SetTaskValid(SetTaskValidInDto inDto) { - var visittask = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync(); + var visittask = await _visitTaskRepository.AsQueryable().Include(x=>x.TrialReadingCriterion).Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync(); var readingId = visittask.SouceReadModuleId==null? visittask.SourceSubjectVisitId: visittask.SouceReadModuleId; - if (await _readingConsistentClinicalDataRepository.AnyAsync(x => x.ReadingId == readingId && x.IsSign == false)) + if (await _readingConsistentClinicalDataRepository.AnyAsync(x => x.ReadingId == readingId + + && x.ClinicalDataTrialSet.TrialClinicalDataSetCriteriaList.Any(t => t.TrialReadingCriterionId == visittask.TrialReadingCriterionId) && x.IsSign == false)) { return ResponseOutput.NotOk(_localizer["ReadingClinicalData_HaveUnsignedClinicalData"]); } + if(visittask.TrialReadingCriterion.IsReadingTaskViewInOrder== ReadingOrder.InOrder) + { + if(await _visitTaskRepository.Where(x=>x.SubjectId== visittask.SubjectId + &&x.TrialReadingCriterionId== visittask.TrialReadingCriterionId + &&x.VisitTaskNum< visittask.VisitTaskNum&&x.IsAnalysisCreate==visittask.IsAnalysisCreate + &&x.IsSelfAnalysis==visittask.IsSelfAnalysis&&x.ArmEnum==visittask.ArmEnum&&x.TaskState==TaskState.NotEffect).AnyAsync() + ) + { + return ResponseOutput.NotOk(_localizer["ReadingClinicalData_NeedSetBeforeTaskEffect"]); + } + } await _visitTaskRepository.UpdatePartialFromQueryAsync(x => x.Id == inDto.VisitTaskId, x => new VisitTask() { diff --git a/IRaCIS.Core.Application/Service/Reading/Interface/IReadingClinicalDataService.cs b/IRaCIS.Core.Application/Service/Reading/Interface/IReadingClinicalDataService.cs index 521a9d843..24c4a39ad 100644 --- a/IRaCIS.Core.Application/Service/Reading/Interface/IReadingClinicalDataService.cs +++ b/IRaCIS.Core.Application/Service/Reading/Interface/IReadingClinicalDataService.cs @@ -31,5 +31,6 @@ namespace IRaCIS.Core.Application.Contracts Task DealVisiTaskClinicalDataSignedAsync(Guid trialId, Guid subjectId, Guid readingId, bool isVisit, Guid trialReadingCritrialId); Task SignConsistencyAnalysisReadingClinicalData(SignConsistencyAnalysisReadingClinicalDataInDto inDto); + } } \ No newline at end of file diff --git a/IRaCIS.Core.Application/Service/Reading/MedicalAudit/ReadingMedicineQuestionService.cs b/IRaCIS.Core.Application/Service/Reading/MedicalAudit/ReadingMedicineQuestionService.cs index 12ab48a55..a148bed8f 100644 --- a/IRaCIS.Core.Application/Service/Reading/MedicalAudit/ReadingMedicineQuestionService.cs +++ b/IRaCIS.Core.Application/Service/Reading/MedicalAudit/ReadingMedicineQuestionService.cs @@ -65,7 +65,9 @@ namespace IRaCIS.Core.Application.Service .WhereIf(inDto.LanguageType != null, x => x.LanguageType == inDto.LanguageType!.Value) .ProjectTo(_mapper.ConfigurationProvider).OrderBy(x => x.ShowOrder); - return await query.ToPagedListAsync(inDto.PageIndex, inDto.PageSize, new string[2] { "LanguageType desc", "ShowOrder asc" }); + var defalutSortArray = new string[] { nameof(ReadingMedicineSystemQuestionView.LanguageType) + " desc", nameof(ReadingMedicineSystemQuestionView.ShowOrder) }; + + return await query.ToPagedListAsync(inDto.PageIndex, inDto.PageSize, new string[2] { "LanguageType desc", "ShowOrder asc" }); } /// diff --git a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingGlobalTaskService.cs b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingGlobalTaskService.cs index 5759c9ced..9c7371891 100644 --- a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingGlobalTaskService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingGlobalTaskService.cs @@ -34,6 +34,23 @@ namespace IRaCIS.Application.Services await VerifyTaskIsSign(inDto.GlobalTaskId); await this.SubmitTaskChangeState(inDto.GlobalTaskId); + var globalAnswerList = await _readingGlobalTaskInfoRepository.Where(x => + x.QuestionId!=null &&x.Answer!=string.Empty&& x.Answer != null && + x.GlobalTaskId == inDto.GlobalTaskId).ToListAsync(); + + foreach (var item in globalAnswerList) + { + await _readingTaskQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x => x.VisitTaskId == item.TaskId && x.ReadingQuestionTrialId == item.QuestionId + && x.Answer != item.Answer + , x => new ReadingTaskQuestionAnswer() + { + GlobalChangeAnswer = item.Answer, + IsGlobalChange = true, + }); + } + + await _readingTaskQuestionAnswerRepository.SaveChangesAsync(); + return ResponseOutput.Ok(true); } @@ -60,24 +77,15 @@ namespace IRaCIS.Application.Services if (criterionType == CriterionType.PCWG3) { await _readingTaskQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x => x.VisitTaskId == item.VisitTaskId && x.ReadingQuestionTrialId == answer.QuestionId - && x.Answer != answer.Answer && answer.Answer != string.Empty && answer.Answer != null - , x => new ReadingTaskQuestionAnswer() - { + && x.Answer != answer.Answer && answer.Answer != string.Empty && answer.Answer != null + , x => new ReadingTaskQuestionAnswer() + { Answer= answer.Answer, GlobalChangeAnswer = answer.Answer, IsGlobalChange = true, - }); - } - else - { - await _readingTaskQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x => x.VisitTaskId == item.VisitTaskId && x.ReadingQuestionTrialId == answer.QuestionId - && x.Answer != answer.Answer && answer.Answer != string.Empty && answer.Answer != null - , x => new ReadingTaskQuestionAnswer() - { - GlobalChangeAnswer = answer.Answer, - IsGlobalChange = true, - }); + }); } + } } diff --git a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs index 3cae0656b..c27c2e8bd 100644 --- a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs @@ -2968,7 +2968,7 @@ namespace IRaCIS.Application.Services task.SubjectCode = await _subjectRepository.Where(x => x.Id == task.SubjectId).Select(x => x.Code).FirstNotNullAsync(); } - await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => x.Id == task.VisitTaskId && x.FirstReadingTime == null, x => new VisitTask() + await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => x.Id == task.VisitTaskId&&x.TaskState==TaskState.Effect&&x.ReadingTaskState!=ReadingTaskState.HaveSigned && x.FirstReadingTime == null, x => new VisitTask() { FirstReadingTime = DateTime.Now, }); diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/DicomAEViewModel.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/DicomAEViewModel.cs index 50cc7d550..cd9cbd134 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/DicomAEViewModel.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/DicomAEViewModel.cs @@ -19,7 +19,6 @@ namespace IRaCIS.Core.Application.ViewModel public DateTime? LatestTestTime { get; set; } - public bool IsTestOK { get; set; } //public bool IsPACSConnect { get; set; } @@ -61,6 +60,15 @@ namespace IRaCIS.Core.Application.ViewModel public bool IsPACSConnect { get; set; } + + public bool? IsTestOK { get; set; } + } + + public class TestAECommand + { + public string CalledAE { get; set; } = string.Empty; + public string IP { get; set; } = string.Empty; + public int Port { get; set; } } diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/PersonalWorkstationViewModel.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/PersonalWorkstationViewModel.cs index bb5102c50..c833214ef 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/PersonalWorkstationViewModel.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/PersonalWorkstationViewModel.cs @@ -2,6 +2,7 @@ using System.ComponentModel.DataAnnotations; using System.Web; using IRaCIS.Application.Contracts; +using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Domain.Share; namespace IRaCIS.Core.Application.Contracts @@ -289,6 +290,7 @@ namespace IRaCIS.Core.Application.Contracts public string Sponsor { get; set; } + [DictionaryTranslateAttribute("TrialStatusEnum")] public string TrialStatusStr { get; set; } #region PM diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/UserTrialViewModel.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/UserTrialViewModel.cs index a2fdd4c03..a6d85a694 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/UserTrialViewModel.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/UserTrialViewModel.cs @@ -321,7 +321,7 @@ namespace IRaCIS.Application.Contracts public class TrialUserScreeningDTO : TrialUserAddCommand { - public int Sex { get; set; } // 1-男 2-女 + public int? Sex { get; set; } // 1-男 2-女 public string Phone { get; set; } = string.Empty; public string EMail { get; set; } = string.Empty; diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs index 636a8c3b2..b130638a7 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs @@ -22,6 +22,7 @@ using IRaCIS.Core.Domain.Models; using IRaCIS.Application.Contracts; using SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors; using Newtonsoft.Json; +using Microsoft.Extensions.Options; namespace IRaCIS.Core.Application { @@ -1347,7 +1348,7 @@ namespace IRaCIS.Core.Application { var codeList = await _repository.Where(t => t.TrialId == incommand.TrialId) - .WhereIf(incommand.Id!=null,t=>t.Id!=incommand.Id) + .WhereIf(incommand.Id != null, t => t.Id != incommand.Id) .Select(t => t.Code).ToListAsync(); @@ -1384,5 +1385,12 @@ namespace IRaCIS.Core.Application return JsonConvert.DeserializeObject(extralConfig) ?? new TrialExtraConfig(); } + + public async Task GetTrialPacsConfigInfo(Guid trialId, [FromServices] IOptionsMonitor optionsMonitor) + { + var trialCode = await _trialRepository.Where(t => t.Id == trialId).Select(t => t.TrialCode).FirstOrDefaultAsync(); + + return new TrialPacsInfo() { Ip=optionsMonitor.CurrentValue.IP,Port=optionsMonitor.CurrentValue.Port,TrialCalledAE=$"EI{trialCode}" }; + } } } diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialDicomAEService.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialDicomAEService.cs index b0e1be07c..9c59315b4 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialDicomAEService.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialDicomAEService.cs @@ -12,6 +12,7 @@ using FellowOakDicom.Network.Client; using FellowOakDicom.Network; using IRaCIS.Application.Contracts; using IRaCIS.Core.Domain.Share; +using DocumentFormat.OpenXml.InkML; namespace IRaCIS.Core.Application.Service { /// @@ -84,6 +85,14 @@ namespace IRaCIS.Core.Application.Service VerifyMsg = _localizer["TrialDicomAE_RepeatCalledAE"] }; + var verifyExp3 = new EntityVerifyExp() + { + VerifyExp = u => u.TrialId == addOrEditDicomAE.TrialId, + + //"AE名称不能与其他项目相同" + VerifyMsg = "该项目只允许添加一条dicom AE记录(前端对接有bug时出现)" + }; + //var verifyExp2 = new EntityVerifyExp() //{ // VerifyExp = u => u.TrialId == addOrEditDicomAE.TrialId, @@ -98,7 +107,7 @@ namespace IRaCIS.Core.Application.Service if (addOrEditDicomAE.IsPACSConnect) { // 在此处拷贝automapper 映射 - var entity = await _dicomAERepository.InsertOrUpdateAsync(addOrEditDicomAE, true, verifyExp1, verifyExp2); + var entity = await _dicomAERepository.InsertOrUpdateAsync(addOrEditDicomAE, true, verifyExp3, verifyExp1, verifyExp2); return ResponseOutput.Ok(entity.Id.ToString()); } @@ -123,42 +132,33 @@ namespace IRaCIS.Core.Application.Service /// 测试scp server 是否可以连接 /// /// - [HttpGet("{dicomAEId:guid}")] - public async Task TestSCPServerConnect(Guid dicomAEId) + [HttpPost] + public async Task TestSCPServerConnect(TestAECommand inCommand) { - var find = await _dicomAERepository.FirstOrDefaultAsync(t => t.Id == dicomAEId); - - if (find == null) + try { + var client = DicomClientFactory.Create(inCommand.IP, inCommand.Port, false, "test-callingAE", inCommand.CalledAE); - return false; + client.NegotiateAsyncOps(); + + await client.AddRequestAsync(new DicomCEchoRequest()); + + // 创建一个超时任务,设置超时时间为1秒 + var timeoutTask = Task.Delay(TimeSpan.FromSeconds(3)); + + // 发送 DICOM 请求 + var sendTask = client.SendAsync(); + + // 等待任务完成,若超时任务先完成则抛出超时异常 + if (await Task.WhenAny(sendTask, timeoutTask) == timeoutTask) + { + throw new TimeoutException("DICOM 请求超时。"); + } + return true; } - else + catch (Exception ex) { - find.LatestTestTime = DateTime.Now; - - try - { - var client = DicomClientFactory.Create(find.IP, find.Port, false, "test-callingAE", find.CalledAE); - - client.NegotiateAsyncOps(); - - await client.AddRequestAsync(new DicomCEchoRequest()); - - await client.SendAsync(); - - find.IsTestOK = true; - await _dicomAERepository.SaveChangesAsync(); - - return true; - } - catch (Exception ex) - { - find.IsTestOK = false; - await _dicomAERepository.SaveChangesAsync(); - - return false; - } + return false; } diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialMaintenanceService.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialMaintenanceService.cs index 0629f5579..9e060eb76 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialMaintenanceService.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialMaintenanceService.cs @@ -121,8 +121,9 @@ namespace IRaCIS.Application.Services { var trialType = _trialRepository.Where(t => t.Id == trialUserQuery.TrialId).Select(t => t.TrialType).FirstOrDefault(); - var userTypeEnums = new List() { UserTypeEnum.IQC, UserTypeEnum.APM, UserTypeEnum.MIM, UserTypeEnum.QA, UserTypeEnum.MW }; - if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.SuperAdmin) + var userTypeEnums = new List() { UserTypeEnum.ClinicalResearchCoordinator, UserTypeEnum.CRA, UserTypeEnum.IQC, UserTypeEnum.APM, UserTypeEnum.MIM, UserTypeEnum.QA, UserTypeEnum.MW, UserTypeEnum.MC }; + + //if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.SuperAdmin) { userTypeEnums.Add(UserTypeEnum.ProjectManager); } @@ -138,7 +139,7 @@ namespace IRaCIS.Application.Services .WhereIf(trialType == TrialType.NoneOfficial, t => t.IsTestUser == true || (t.IsTestUser == false && t.IsZhiZhun)) - + .Where(t=>userTypeEnums.Contains(t.UserTypeEnum)) .WhereIf(!string.IsNullOrWhiteSpace(trialUserQuery.UserRealName), t => (t.FullName).Contains(trialUserQuery.UserRealName)) diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialSiteDicomAEService.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialSiteDicomAEService.cs index 7bd160513..5ed3452e0 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialSiteDicomAEService.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialSiteDicomAEService.cs @@ -51,8 +51,7 @@ namespace IRaCIS.Core.Application.Service { var verifyExp1 = new EntityVerifyExp() { - VerifyExp = u => u.IP == addOrEditTrialSiteDicomAE.IP && u.Port == addOrEditTrialSiteDicomAE.Port - && u.CallingAE == addOrEditTrialSiteDicomAE.CallingAE && u.TrialId == addOrEditTrialSiteDicomAE.TrialId + VerifyExp = u => u.CallingAE == addOrEditTrialSiteDicomAE.CallingAE && u.TrialId == addOrEditTrialSiteDicomAE.TrialId && u.TrialSiteId == addOrEditTrialSiteDicomAE.TrialSiteId, //"不允许添加相同的记录" diff --git a/IRaCIS.Core.Application/Service/Visit/SubjectService.cs b/IRaCIS.Core.Application/Service/Visit/SubjectService.cs index d9e1ace36..cb21db1dc 100644 --- a/IRaCIS.Core.Application/Service/Visit/SubjectService.cs +++ b/IRaCIS.Core.Application/Service/Visit/SubjectService.cs @@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; using IRaCIS.Core.Application.Auth; using IRaCIS.Core.Domain.Models; +using IRaCIS.Core.Infrastructure; namespace IRaCIS.Application.Services { diff --git a/IRaCIS.Core.Application/TestService.cs b/IRaCIS.Core.Application/TestService.cs index b0dd183e8..6d617ec9c 100644 --- a/IRaCIS.Core.Application/TestService.cs +++ b/IRaCIS.Core.Application/TestService.cs @@ -1,4 +1,5 @@ using Aliyun.OSS; +using DocumentFormat.OpenXml.Wordprocessing; using IP2Region.Net.XDB; using IRaCIS.Application.Contracts; using IRaCIS.Core.Application.Contracts; @@ -18,12 +19,15 @@ using Microsoft.Extensions.Options; using MiniExcelLibs; using Minio; using Minio.DataModel.Args; +using NPOI.XWPF.UserModel; using SharpCompress.Common; using Spire.Doc; using System.Linq.Expressions; using System.Reflection.Metadata; using System.Text; using System.Text.RegularExpressions; +using Xceed.Document.NET; +using Xceed.Words.NET; namespace IRaCIS.Application.Services @@ -65,6 +69,30 @@ namespace IRaCIS.Application.Services //_cache = cache; } + /// + /// 清理一致性分析任务 + /// + /// + /// + public async Task DeleteConsistentDate(Guid trialReadingCriterionId) + { + + + var consistentSubjectIdList = _repository.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId && t.IsAnalysisCreate == true).Select(t => t.SubjectId).ToList(); + + await _repository.BatchDeleteAsync(t => t.TrialReadingCriterionId == trialReadingCriterionId); + + await _repository.BatchDeleteAsync(t => t.TrialReadingCriterionId == trialReadingCriterionId && t.IsAnalysisCreate == true); + + + await _repository.BatchDeleteAsync(t => consistentSubjectIdList.Contains(t.ReadingConsistentClinicalData.SubjectId)); + + await _repository.BatchDeleteAsync(t => consistentSubjectIdList.Contains(t.SubjectId)); + + + await _repository.SaveChangesAsync(); + return ResponseOutput.Ok(); + } public async Task TestEFcore8() @@ -113,7 +141,7 @@ namespace IRaCIS.Application.Services public async Task TestMinIO([FromServices] IOSSService oSSService) { - var str= await oSSService.GetSignedUrl("/01000000-c0a8-0242-1c98-08dc7ebcd37d/Read/01000000-c0a8-0242-1c98-08dc7ebcd37d/Visit/1716872544006_1716872544003.png"); + var str = await oSSService.GetSignedUrl("/01000000-c0a8-0242-1c98-08dc7ebcd37d/Read/01000000-c0a8-0242-1c98-08dc7ebcd37d/Visit/1716872544006_1716872544003.png"); //await oSSService.UploadToOSSAsync("C:\\Users\\Administrator\\Desktop\\TrialSiteUserImportTemplate.xlsx", "myfolder"); @@ -170,6 +198,9 @@ namespace IRaCIS.Application.Services [UnitOfWork] public async Task Get() { + + await _repository.Where(t => t.SubjectId == Guid.Empty).Include(t => t.ReadingClinicalDataPDFList).ExecuteDeleteAsync(); + // Generate RSA keys var keyPair = RSAHelper.GenerateRSAKeyPair(2048); @@ -187,11 +218,11 @@ namespace IRaCIS.Application.Services Console.WriteLine("\nOriginal Data: " + dataToEncrypt); // Encrypt the data - var encryptedData = RSAHelper.Encrypt( publicKey, dataToEncrypt); + var encryptedData = RSAHelper.Encrypt(publicKey, dataToEncrypt); Console.WriteLine("\nEncrypted Data: " + encryptedData); // Decrypt the data - string decryptedData = RSAHelper.Decrypt( privateKey, encryptedData); + string decryptedData = RSAHelper.Decrypt(privateKey, encryptedData); Console.WriteLine("\nDecrypted Data: " + decryptedData); @@ -201,12 +232,111 @@ namespace IRaCIS.Application.Services [AllowAnonymous] - public async Task testEmail([FromServices] IWebHostEnvironment env ,string email) + public async Task testDoc([FromServices] IWebHostEnvironment env, string email) { + #region DocX 测试 + //using (DocX document = DocX.Load("C:\\Users\\hang\\Desktop\\test.docx")) + //{ + // // 查找书签 + // var bookmarkCn_Start = document.Bookmarks.FirstOrDefault(b => b.Name == "zh_cn"); + // var bookmarkEn_Start = document.Bookmarks.FirstOrDefault(b => b.Name == "en_us"); - var hiddenEmail = EmailMaskHelper.MaskEmail(email); + // if (bookmarkCn_Start != null && bookmarkEn_Start != null) + // { + // // 获取书签的起始位置 + // int bookmarkCNStartPos = bookmarkCn_Start.Paragraph.StartIndex; - return hiddenEmail; + // var bookmarkENStartPos = bookmarkEn_Start.Paragraph.StartIndex; + + // // // 创建一个要删除段落的列表 + // List paragraphsToRemove = new List(); + + // foreach (var item in document.Paragraphs) + // { + + // //中文模板在前,英文在后,英文模板,就删除英文之前的,中文模板就删除英文之后的 + // //_userInfo.IsEn_Us? item.EndIndex< bookmarkENStartPos :item.StartIndex>= bookmarkENStartPos + // if (item.StartIndex>= bookmarkENStartPos) + // { + // paragraphsToRemove.Add(item); + + // } + // } + + // foreach (var paragraph in paragraphsToRemove) + // { + // document.RemoveParagraph(paragraph); + // } + + // } + + // // 保存修改 + // document.SaveAs("C:\\Users\\hang\\Desktop\\test1.docx"); + //} + #endregion + + using (FileStream fs = new FileStream("C:\\Users\\hang\\Desktop\\test.docx", FileMode.Open, FileAccess.Read)) + { + XWPFDocument doc = new XWPFDocument(fs); + + + // 查找包含指定书签的段落及其索引 + var bookmarkParagraph = doc.Paragraphs + .FirstOrDefault(p => p.GetCTP().GetBookmarkStartList().Any(b => b.name == "en_us")); + + + if (bookmarkParagraph != null) + { + int bookmarkIndex = doc.Paragraphs.IndexOf(bookmarkParagraph); + + // 删除书签之后的所有段落 + for (int i = doc.Paragraphs.Count - 1; i >= bookmarkIndex; i--) + { + doc.RemoveBodyElement(i); + } + + } + else + { + throw new BusinessValidationFailedException("word 模板没有英文书签"); + } + + // 创建一个要删除段落的列表 + + //XWPFParagraph bookmarkParagraph = null; + + //foreach (var paragraph in doc.Paragraphs) + //{ + + // foreach (var bookmark in paragraph.GetCTP().GetBookmarkStartList()) + // { + // if (bookmark.name == "en_us") + // { + // bookmarkParagraph = paragraph; + // break; + // } + // } + //} + + + + + //// 从书签所在段落开始,删除之前的所有段落 + //for (int i = bookmarkIndex - 1; i >= 0; i--) + //{ + // doc.RemoveBodyElement(i); + //} + + + + using (FileStream outStream = new FileStream("C:\\Users\\hang\\Desktop\\test1.docx", FileMode.Create, FileAccess.Write)) + { + doc.Write(outStream); + } + } + + + return "hiddenEmail"; } diff --git a/IRaCIS.Core.Domain.Share/Trial/TrialExpedited.cs b/IRaCIS.Core.Domain.Share/Trial/TrialExpedited.cs index 506830ba6..dcdb9c795 100644 --- a/IRaCIS.Core.Domain.Share/Trial/TrialExpedited.cs +++ b/IRaCIS.Core.Domain.Share/Trial/TrialExpedited.cs @@ -64,6 +64,15 @@ namespace IRaCIS.Core.Domain.Share } + public class TrialPacsInfo + { + public int Port { get; set; } + + public string Ip { get; set; } + + public string TrialCalledAE { get; set; } + } + public class SiteSurveyModifyFiled { public string NeedModifyFiled { get; set; } diff --git a/IRaCIS.Core.Domain/BaseModel/Entity.cs b/IRaCIS.Core.Domain/BaseModel/Entity.cs index 939bf9f13..8482a17d4 100644 --- a/IRaCIS.Core.Domain/BaseModel/Entity.cs +++ b/IRaCIS.Core.Domain/BaseModel/Entity.cs @@ -17,4 +17,52 @@ namespace IRaCIS.Core.Domain.Models abstract TKey Id { get; set; } } + #region 减少实体属性,增加基类 + + public abstract class BaseAuditAddEntity : Entity, IAuditAdd + { + + public Guid CreateUserId { get; set; } + public DateTime CreateTime { get; set; } + } + + public abstract class BaseFullAuditEntity : Entity, IAuditUpdate, IAuditAdd + { + public Guid CreateUserId { get; set; } + public DateTime CreateTime { get; set; } + public Guid UpdateUserId { get; set; } + public DateTime UpdateTime { get; set; } + } + + + public abstract class BaseFullAuditDeleteEntity : Entity, IAuditUpdate, IAuditAdd, ISoftDelete + { + public Guid? DeleteUserId { get; set; } + public bool IsDeleted { get; set; } + public DateTime? DeletedTime { get; set; } + public Guid CreateUserId { get; set; } + public DateTime CreateTime { get; set; } + public Guid UpdateUserId { get; set; } + public DateTime UpdateTime { get; set; } + } + + + + public abstract class BaseAuditAddEntityWithUserName : Entity, IAuditAddWithUserName + { + public string CreateUser { get; set; } + + public Guid CreateUserId { get; set; } + public DateTime CreateTime { get; set; } + } + + public abstract class BaseAuditUpdateEntity : Entity, IAuditUpdate + { + public Guid UpdateUserId { get; set; } + public DateTime UpdateTime { get; set; } + } + + + #endregion + } diff --git a/IRaCIS.Core.Domain/BaseModel/IAuditAdd.cs b/IRaCIS.Core.Domain/BaseModel/IAuditAdd.cs index 70cd25e2b..4786c8e6d 100644 --- a/IRaCIS.Core.Domain/BaseModel/IAuditAdd.cs +++ b/IRaCIS.Core.Domain/BaseModel/IAuditAdd.cs @@ -19,7 +19,9 @@ namespace IRaCIS.Core.Domain.Models public interface IAuditAddWithUserName : IAuditAdd { - string CreateUser { get; set; } + public string CreateUser { get; set; } } + + } diff --git a/IRaCIS.Core.Domain/BaseModel/IAuditUpdate.cs b/IRaCIS.Core.Domain/BaseModel/IAuditUpdate.cs index e154ccecc..05d422a16 100644 --- a/IRaCIS.Core.Domain/BaseModel/IAuditUpdate.cs +++ b/IRaCIS.Core.Domain/BaseModel/IAuditUpdate.cs @@ -5,7 +5,6 @@ namespace IRaCIS.Core.Domain.Models public interface IAuditUpdate where TKey : struct { public TKey UpdateUserId { get; set; } - //string UpdateUserName { get; set; } public DateTime UpdateTime { get; set; } } @@ -13,4 +12,9 @@ namespace IRaCIS.Core.Domain.Models { } + + + + + } diff --git a/IRaCIS.Core.Domain/BaseModel/ISoftDelete.cs b/IRaCIS.Core.Domain/BaseModel/ISoftDelete.cs index 8cfa535b1..e0549348b 100644 --- a/IRaCIS.Core.Domain/BaseModel/ISoftDelete.cs +++ b/IRaCIS.Core.Domain/BaseModel/ISoftDelete.cs @@ -2,16 +2,18 @@ namespace IRaCIS.Core.Domain.Models { - - - public interface ISoftDelete + public interface ISoftDelete where TKey : struct { - bool IsDeleted { get; set; } + public TKey? DeleteUserId { get; set; } + public bool IsDeleted { get; set; } public DateTime? DeletedTime { get; set; } - - public Guid? DeleteUserId { get; set; } } - + public interface ISoftDelete : ISoftDelete + { + + } + + } diff --git a/IRaCIS.Core.Domain/Common/CommonDocument.cs b/IRaCIS.Core.Domain/Common/CommonDocument.cs index 37a29aeee..579fb3da8 100644 --- a/IRaCIS.Core.Domain/Common/CommonDocument.cs +++ b/IRaCIS.Core.Domain/Common/CommonDocument.cs @@ -9,82 +9,30 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace IRaCIS.Core.Domain.Models { - /// - ///CommonDocument - /// - [Table("CommonDocument")] - public class CommonDocument : Entity, IAuditUpdate, IAuditAdd,ISoftDelete - { + /// + ///CommonDocument + /// + [Table("CommonDocument")] + public class CommonDocument : BaseFullAuditDeleteEntity + { + + public string Code { get; set; } = String.Empty; - [Required] - public string Code { get; set; } = String.Empty; + public string Name { get; set; } = String.Empty; - [Required] - public string Name { get; set; } = String.Empty; + public string NameCN { get; set; } = string.Empty; - public string NameCN { get; set; } = string.Empty; - - /// - /// Path - /// - [Required] - public string Path { get; set; } = String.Empty; - - /// - /// CreateTime - /// - [Required] - public DateTime CreateTime { get; set; } - - /// - /// CreateUserId - /// - [Required] - public Guid CreateUserId { get; set; } - - /// - /// UpdateTime - /// - [Required] - public DateTime UpdateTime { get; set; } - - /// - /// UpdateUserId - /// - [Required] - public Guid UpdateUserId { get; set; } - - /// - /// Description - /// - [Required] - public string Description { get; set; } = String.Empty; - - /// - /// IsDeleted - /// - [Required] - public bool IsDeleted { get; set; } - - public DateTime? DeletedTime { get; set; } - - public Guid? DeleteUserId { get; set; } + public string Path { get; set; } = String.Empty; - public CriterionType? CriterionTypeEnum { get; set; } - public CommonDocumentFileType FileTypeEnum { get; set; } - public EmailBusinessScenario BusinessScenarioEnum { get; set; } + public string Description { get; set; } = String.Empty; + + public CriterionType? CriterionTypeEnum { get; set; } + public CommonDocumentFileType FileTypeEnum { get; set; } + public EmailBusinessScenario BusinessScenarioEnum { get; set; } - //[Required] - //public Guid FileTypeId { get; set; } - //public Guid ModuleTypeId { get; set; } + } - - //public Dictionary FileType { get; set; } - //public Dictionary ModuleType { get; set; } - - } - -} +} diff --git a/IRaCIS.Core.Domain/Common/Internationalization.cs b/IRaCIS.Core.Domain/Common/Internationalization.cs index 0da0a2f35..1f6b63cc7 100644 --- a/IRaCIS.Core.Domain/Common/Internationalization.cs +++ b/IRaCIS.Core.Domain/Common/Internationalization.cs @@ -29,7 +29,9 @@ namespace IRaCIS.Core.Domain.Models public Guid UpdateUserId { get; set; } - + /// + /// 0 1 2 预翻译 已确认 废除 + /// public int State { get; set; } diff --git a/IRaCIS.Core.Domain/IRaCIS.Core.Domain.csproj b/IRaCIS.Core.Domain/IRaCIS.Core.Domain.csproj index ac7815099..80a3e8702 100644 --- a/IRaCIS.Core.Domain/IRaCIS.Core.Domain.csproj +++ b/IRaCIS.Core.Domain/IRaCIS.Core.Domain.csproj @@ -10,6 +10,7 @@ + diff --git a/IRaCIS.Core.Domain/Image/TrialDicomAE.cs b/IRaCIS.Core.Domain/Image/TrialDicomAE.cs index 0d91a9c77..3a1f963ab 100644 --- a/IRaCIS.Core.Domain/Image/TrialDicomAE.cs +++ b/IRaCIS.Core.Domain/Image/TrialDicomAE.cs @@ -45,7 +45,7 @@ namespace IRaCIS.Core.Domain.Models public DateTime? LatestTestTime { get; set; } - public bool IsTestOK { get; set; } + public bool? IsTestOK { get; set; } } diff --git a/IRaCIS.Core.Domain/Management/User.cs b/IRaCIS.Core.Domain/Management/User.cs index 775c56fd5..099b0a9f9 100644 --- a/IRaCIS.Core.Domain/Management/User.cs +++ b/IRaCIS.Core.Domain/Management/User.cs @@ -36,7 +36,7 @@ namespace IRaCIS.Core.Domain.Models public string Phone { get; set; } = string.Empty; public string EMail { get; set; } = string.Empty; - public int Sex { get; set; } + public int? Sex { get; set; } public UserStateEnum Status { get; set; } = UserStateEnum.Enable; public DateTime? LastLoginTime { get; set; } diff --git a/IRaCIS.Core.Domain/Reading/ClinicalData/ReadingConsistentClinicalData.cs b/IRaCIS.Core.Domain/Reading/ClinicalData/ReadingConsistentClinicalData.cs index c57fc08e7..4de50e36a 100644 --- a/IRaCIS.Core.Domain/Reading/ClinicalData/ReadingConsistentClinicalData.cs +++ b/IRaCIS.Core.Domain/Reading/ClinicalData/ReadingConsistentClinicalData.cs @@ -54,12 +54,12 @@ namespace IRaCIS.Core.Domain.Models /// /// 是否盲化 /// - public bool? IsBlind { get; set; } + public bool? IsBlind { get; set; } = false; /// /// 是否完整 /// - public bool? IsComplete { get; set; } + public bool? IsComplete { get; set; } = true; /// /// 创建人 diff --git a/IRaCIS.Core.Domain/_Config/_AppSettings.cs b/IRaCIS.Core.Domain/_Config/_AppSettings.cs index b4c890257..fac748828 100644 --- a/IRaCIS.Core.Domain/_Config/_AppSettings.cs +++ b/IRaCIS.Core.Domain/_Config/_AppSettings.cs @@ -36,6 +36,17 @@ namespace IRaCIS.Core.Domain.Share /// public int ReadingRestTimeMin { get; set; } + + /// + /// 是否需要修改密码 + /// + public bool IsNeedChangePassWord { get; set; } + + /// + /// 修改密码的天数 + /// + public int ChangePassWordDays { get; set; } + } public class SystemEmailSendConfig @@ -67,6 +78,15 @@ namespace IRaCIS.Core.Domain.Share } + public class SystemPacsConfig + { + public int Port { get; set; } + + public string IP { get; set; } + } + + + public class EncreptResponseOption { public bool IsEnable { get; set; } diff --git a/IRaCIS.Core.Infra.EFCore/Common/AuditingData.cs b/IRaCIS.Core.Infra.EFCore/Common/AuditingData.cs index ec1e86542..be961736e 100644 --- a/IRaCIS.Core.Infra.EFCore/Common/AuditingData.cs +++ b/IRaCIS.Core.Infra.EFCore/Common/AuditingData.cs @@ -158,7 +158,8 @@ namespace IRaCIS.Core.Infra.EFCore.Common t.IsTrialBasicLogicConfirmed, t.IsTrialProcessConfirmed, t.IsTrialUrgentConfirmed, - t.IsConfigureEmail + t.IsConfigureEmail, + t.IsTrialPACSConfirmed, }).FirstOrDefaultAsync(); switch (_userInfo.RequestUrl) { @@ -172,6 +173,9 @@ namespace IRaCIS.Core.Infra.EFCore.Common case "configTrialBasicInfo/ConfigTrialUrgentInfoConfirm": extraIdentification = $"/{oldentity.IsTrialUrgentConfirmed.ToString()}"; break; + case "configTrialBasicInfo/ConfigTrialPACSInfoConfirm": + extraIdentification = $"/{oldentity.IsTrialPACSConfirmed.ToString()}"; + break; case "TrialEmailNoticeConfig/setTrialEmail": @@ -328,6 +332,34 @@ namespace IRaCIS.Core.Infra.EFCore.Common }); } + + // PACS直连 + foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(TrialSiteDicomAE))) + { + var type = GetEntityAuditOpt(item); + + var entity = item.Entity as TrialSiteDicomAE; + + + await InsertInspection(entity, type, x => new InspectionConvertDTO() + { + ObjectRelationParentId=entity.TrialSiteId, + }); + } + + // PACS直连 + foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(TrialDicomAE))) + { + var type = GetEntityAuditOpt(item); + + var entity = item.Entity as TrialDicomAE; + + + await InsertInspection(entity, type, x => new InspectionConvertDTO() + { + }); + } + //系统标准问题 foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(ReadingQuestionSystem))) { @@ -2314,6 +2346,27 @@ namespace IRaCIS.Core.Infra.EFCore.Common }, new { FileCountViewStr = config?.ClinicalDataLevel == ClinicalLevel.Subject && config?.ClinicalUploadType == ClinicalUploadType.Table ? "NA" : entity.FileCount.ToString() }); } + foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(ReadingConsistentClinicalData))) + { + var type = GetEntityAuditOpt(item); + + var entity = item.Entity as ReadingConsistentClinicalData; + + var config = await _dbContext.ClinicalDataTrialSet.FindAsync(entity.ClinicalDataTrialSetId); + + await InsertInspection(item.Entity as ReadingConsistentClinicalData, type, x => new InspectionConvertDTO() + { + + IsDistinctionInterface = type == AuditOpt.Update ? true : false, + + SubjectVisitId = x.IsVisit ? x.ReadingId : null, + + ObjectRelationParentId = entity.ClinicalDataTrialSetId, + + //ObjectRelationParentId2 = x.IsVisit == false?x.ReadingId:null + }, new { FileCountViewStr = config?.ClinicalDataLevel == ClinicalLevel.Subject && config?.ClinicalUploadType == ClinicalUploadType.Table ? "NA" : entity.FileCount.ToString() }); + } + //阅片期计划 foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(ReadingPeriodSet))) { @@ -2870,7 +2923,6 @@ namespace IRaCIS.Core.Infra.EFCore.Common { Unit = (ValueUnit)int.Parse(x.Code), - UnitName = x.Value.ToString(), }).ToList(); //获取表格问题名称 组合成数组 diff --git a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs index 44a2ad291..15414fe37 100644 --- a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs +++ b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs @@ -21,6 +21,7 @@ using Microsoft.Identity.Client; using EntityFramework.Exceptions.Common; using System.Data; using IRaCIS.Core.Infrastructure; +using System.Reflection.Metadata; namespace IRaCIS.Core.Infra.EFCore { @@ -49,7 +50,7 @@ namespace IRaCIS.Core.Infra.EFCore public class IRaCISDBContext : DbContext { - private IUserInfo _userInfo; + private IUserInfo _userInfo; private readonly ILogger _logger; @@ -57,7 +58,7 @@ namespace IRaCIS.Core.Infra.EFCore ) : base(options) { - _userInfo= userInfo; + _userInfo = userInfo; _logger = logger; } @@ -72,7 +73,7 @@ namespace IRaCIS.Core.Infra.EFCore }); - modelBuilder.Entity().HasQueryFilter(p => p.IsAdditional==false); + modelBuilder.Entity().HasQueryFilter(p => p.IsAdditional == false); modelBuilder.Entity().HasMany(t => t.VisitTaskList).WithOne(t => t.DoctorUser).HasForeignKey(t => t.DoctorUserId).IsRequired(false); @@ -98,11 +99,12 @@ namespace IRaCIS.Core.Infra.EFCore modelBuilder.Entity().HasMany(t => t.TaskInfluenceList).WithOne(s => s.OriginalTask).HasForeignKey(t => t.OriginalTaskId); - modelBuilder.Entity().HasMany(t => t.GlobalVisitResultList).WithOne(s => s.GlobalVisitTask).HasForeignKey(t => t.GlobalTaskId); + modelBuilder.Entity().HasMany(t => t.GlobalVisitResultList).WithOne(s => s.GlobalVisitTask).HasForeignKey(t => t.GlobalTaskId); modelBuilder.Entity().HasMany(t => t.ChildList).WithOne(t => t.Parent); modelBuilder.Entity().HasMany(t => t.EarlierSubjectUserList).WithOne(t => t.OrignalSubjectUser); + modelBuilder.Entity().HasQueryFilter(b => b.Subject.IsDeleted == false); //遍历实体模型手动配置 var typesToRegister = Assembly.GetExecutingAssembly().GetTypes().Where(q => q.GetInterface(typeof(IEntityTypeConfiguration<>).FullName) != null); @@ -239,18 +241,18 @@ namespace IRaCIS.Core.Infra.EFCore public virtual DbSet CriterionNidusSystem { get; set; } - public virtual DbSet CriterionNidusTrial { get; set; } + public virtual DbSet CriterionNidusTrial { get; set; } - public virtual DbSet ReadingTrialCriterionDictionary { get; set; } + public virtual DbSet ReadingTrialCriterionDictionary { get; set; } - public virtual DbSet ReadingTableQuestionTrial { get; set; } + public virtual DbSet ReadingTableQuestionTrial { get; set; } public virtual DbSet TumorAssessment_RECIST1Point1BM { get; set; } public virtual DbSet TumorAssessment_RECIST1Point1 { get; set; } public virtual DbSet TumorAssessment_IRECIST1Point1 { get; set; } - + public virtual DbSet TrialClinicalDataSetCriterion { get; set; } public virtual DbSet TrialCriterionAdditionalAssessmentType { get; set; } @@ -319,7 +321,7 @@ namespace IRaCIS.Core.Infra.EFCore #region Trial public virtual DbSet Trial { get; set; } - + public virtual DbSet TrialDictionary { get; set; } public virtual DbSet TrialDetail { get; set; } public virtual DbSet UserTrial { get; set; } @@ -333,9 +335,9 @@ namespace IRaCIS.Core.Infra.EFCore public virtual DbSet User { get; set; } - public virtual DbSet UserPassWordLog { get; set; } + public virtual DbSet UserPassWordLog { get; set; } - public virtual DbSet TrialSiteUserSurvey { get; set; } + public virtual DbSet TrialSiteUserSurvey { get; set; } public virtual DbSet TrialSiteEquipmentSurvey { get; set; } public virtual DbSet TrialSiteSurvey { get; set; } @@ -391,8 +393,8 @@ namespace IRaCIS.Core.Infra.EFCore public virtual DbSet ClinicalTableAnswer { get; set; } - public virtual DbSet ReadModuleCriterionFrom { get; set; } - public virtual DbSet ClinicalForm { get; set; } + public virtual DbSet ReadModuleCriterionFrom { get; set; } + public virtual DbSet ClinicalForm { get; set; } #endregion @@ -448,8 +450,8 @@ namespace IRaCIS.Core.Infra.EFCore public virtual DbSet ShortcutKey { get; set; } - public virtual DbSet UserWLTemplate { get; set; } - public virtual DbSet EmailNoticeConfig { get; set; } + public virtual DbSet UserWLTemplate { get; set; } + public virtual DbSet EmailNoticeConfig { get; set; } public virtual DbSet SystemBasicData { get; set; } public virtual DbSet TrialSign { get; set; } @@ -498,7 +500,7 @@ namespace IRaCIS.Core.Infra.EFCore public virtual DbSet TrialDicomAE { get; set; } - public virtual DbSet TrialSiteDicomAE { get; set; } + public virtual DbSet TrialSiteDicomAE { get; set; } public virtual DbSet SCPImageUpload { get; set; } @@ -509,7 +511,6 @@ namespace IRaCIS.Core.Infra.EFCore public override async Task SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken()) { // 采用触发器的方式 设置 CreateUserId CreateTime UpdateTime UpdateUserId 稽查实体里面没有这四个字段的值 因为先后顺序的原因 - SetCommonEntityAuditInfo(); await AddAudit(); try @@ -519,7 +520,7 @@ namespace IRaCIS.Core.Infra.EFCore } catch (UniqueConstraintException 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("该唯一键已经存在于数据库中。"); @@ -567,7 +568,7 @@ namespace IRaCIS.Core.Infra.EFCore } } - + public async Task AddAudit() @@ -589,91 +590,13 @@ namespace IRaCIS.Core.Infra.EFCore await auditingData.InsertAddEntitys(entities); } - - - } - - /// - /// 重写savechange方式 统一增加审计信息 CreateUserId CreateTime UpdateTime Update UserId - /// - private void SetCommonEntityAuditInfo() - { - - ChangeTracker.DetectChanges(); // Important! - - // 获取所有更改,删除,新增的实体,但排除审计实体(避免死循环) - var entities = ChangeTracker.Entries() - .Where(u => (u.State == EntityState.Modified || u.State == EntityState.Deleted || u.State == EntityState.Added)).Where(x => !typeof(DataInspection).IsAssignableFrom(x.Entity.GetType())).ToList(); - - foreach (var t in entities) - { - switch (t.State) - { - - case EntityState.Deleted: - - break; - case EntityState.Modified: - - if (t.Entity is IAuditUpdate updateEntity1) - { - updateEntity1.UpdateTime = DateTime.Now; - updateEntity1.UpdateUserId = _userInfo.Id; - } - - if (t.Entity is ISoftDelete softDelete) - { - if (softDelete.IsDeleted) - { - softDelete.DeleteUserId = _userInfo.Id; - softDelete.DeletedTime = DateTime.Now; - } - else - { - softDelete.DeletedTime = null; - } - } - - break; - //添加的时候,更新审计字段也赋值 - case EntityState.Added: - - - if (t.Entity is IAuditAdd addEntity) - { - if (addEntity.CreateTime == default(DateTime)) - { - addEntity.CreateTime = DateTime.Now; - } - - addEntity.CreateUserId = _userInfo.Id; - } - - if (t.Entity is IAuditUpdate updateEntity) - { - updateEntity.UpdateTime = DateTime.Now; - updateEntity.UpdateUserId = _userInfo.Id; - } - - if (t.Entity is IAuditAddWithUserName addEntity3) - { - if (addEntity3.CreateTime == default(DateTime)) - { - addEntity3.CreateTime = DateTime.Now; - - } - - addEntity3.CreateUserId = _userInfo.Id; - addEntity3.CreateUser = _userInfo.RealName; - } - break; - } - } } + + public virtual DbSet TaskAllocationRule { get; set; } public virtual DbSet VisitTask { get; set; } diff --git a/IRaCIS.Core.Infra.EFCore/Interceptor/AuditEntityInterceptor.cs b/IRaCIS.Core.Infra.EFCore/Interceptor/AuditEntityInterceptor.cs new file mode 100644 index 000000000..b2f99decd --- /dev/null +++ b/IRaCIS.Core.Infra.EFCore/Interceptor/AuditEntityInterceptor.cs @@ -0,0 +1,103 @@ +using IRaCIS.Core.Domain.Models; +using IRaCIS.Core.Domain.Share; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + + +namespace IRaCIS.Core.Infra.EFCore; + +public class AuditEntityInterceptor(IUserInfo _userInfo) : SaveChangesInterceptor +{ + public override InterceptionResult SavingChanges(DbContextEventData eventData, InterceptionResult result) + { + AuditEntities(eventData.Context); + + return base.SavingChanges(eventData, result); + } + + public override ValueTask> SavingChangesAsync(DbContextEventData eventData, + InterceptionResult result, CancellationToken cancellationToken = default) + { + AuditEntities(eventData.Context); + + return base.SavingChangesAsync(eventData, result, cancellationToken); + } + + public void AuditEntities(DbContext? context) + { + if (context == null) return; + + // 获取所有更改,删除,新增的实体,但排除审计实体(避免死循环) + foreach (var entry in context.ChangeTracker.Entries().Where(u => (u.State == EntityState.Modified || u.State == EntityState.Added)) + .Where(x => !typeof(DataInspection).IsAssignableFrom(x.Entity.GetType())).ToList()) + { + switch (entry.State) + { + + case EntityState.Deleted: + + break; + case EntityState.Modified: + + if (entry.Entity is IAuditUpdate updateEntity1) + { + updateEntity1.UpdateTime = DateTime.Now; + updateEntity1.UpdateUserId = _userInfo.Id; + } + + if (entry.Entity is ISoftDelete softDelete) + { + if (softDelete.IsDeleted) + { + softDelete.DeleteUserId = _userInfo.Id; + softDelete.DeletedTime = DateTime.Now; + } + else + { + softDelete.DeletedTime = null; + } + } + + break; + //添加的时候,更新审计字段也赋值 + case EntityState.Added: + + + if (entry.Entity is IAuditAdd addEntity) + { + if (addEntity.CreateTime == default(DateTime)) + { + addEntity.CreateTime = DateTime.Now; + } + + addEntity.CreateUserId = _userInfo.Id; + } + + if (entry.Entity is IAuditUpdate updateEntity) + { + updateEntity.UpdateTime = DateTime.Now; + updateEntity.UpdateUserId = _userInfo.Id; + } + + if (entry.Entity is IAuditAddWithUserName addEntity3) + { + if (addEntity3.CreateTime == default(DateTime)) + { + addEntity3.CreateTime = DateTime.Now; + + } + + addEntity3.CreateUserId = _userInfo.Id; + addEntity3.CreateUser = _userInfo.RealName; + } + break; + } + } + + + } +} \ No newline at end of file diff --git a/IRaCIS.Core.Infra.EFCore/Interceptor/AuditInterceptor.cs b/IRaCIS.Core.Infra.EFCore/Interceptor/OldAuditInterceptor.cs similarity index 100% rename from IRaCIS.Core.Infra.EFCore/Interceptor/AuditInterceptor.cs rename to IRaCIS.Core.Infra.EFCore/Interceptor/OldAuditInterceptor.cs diff --git a/IRaCIS.Core.Infrastructure/IRaCIS.Core.Infrastructure.csproj b/IRaCIS.Core.Infrastructure/IRaCIS.Core.Infrastructure.csproj index f2b268e49..324ac91a0 100644 --- a/IRaCIS.Core.Infrastructure/IRaCIS.Core.Infrastructure.csproj +++ b/IRaCIS.Core.Infrastructure/IRaCIS.Core.Infrastructure.csproj @@ -11,6 +11,8 @@ + + diff --git a/IRaCIS.Core.Infrastructure/_IRaCIS/Exception/BusinessValidationFailedException.cs b/IRaCIS.Core.Infrastructure/_IRaCIS/Exception/BusinessValidationFailedException.cs index cbe9ec767..1939d57cd 100644 --- a/IRaCIS.Core.Infrastructure/_IRaCIS/Exception/BusinessValidationFailedException.cs +++ b/IRaCIS.Core.Infrastructure/_IRaCIS/Exception/BusinessValidationFailedException.cs @@ -1,4 +1,5 @@ using IRaCIS.Core.Infrastructure.Extention; +using Microsoft.Extensions.Localization; using System; namespace IRaCIS.Core.Infrastructure @@ -8,15 +9,24 @@ namespace IRaCIS.Core.Infrastructure public ApiResponseCodeEnum Code { get; set; } - public BusinessValidationFailedException() + public string LocalizedKey { get; set; }=string.Empty; + + public BusinessValidationFailedException() { } + public BusinessValidationFailedException(LocalizedString message, ApiResponseCodeEnum code = ApiResponseCodeEnum.BusinessValidationFailed) : base(message) + { + Code = code; + LocalizedKey=message.Name; + + } + public BusinessValidationFailedException(string message, ApiResponseCodeEnum code = ApiResponseCodeEnum.BusinessValidationFailed) : base(message) { - Code = code; + Code = code; - } + } } } diff --git a/IRaCIS.Core.Infrastructure/_IRaCIS/IQueryablePageListExtensions.cs b/IRaCIS.Core.Infrastructure/_IRaCIS/IQueryablePageListExtensions.cs index ef697e09b..d04cc4ca8 100644 --- a/IRaCIS.Core.Infrastructure/_IRaCIS/IQueryablePageListExtensions.cs +++ b/IRaCIS.Core.Infrastructure/_IRaCIS/IQueryablePageListExtensions.cs @@ -5,44 +5,86 @@ using Microsoft.EntityFrameworkCore; using System.Linq.Dynamic.Core; using System.Collections.Generic; using System; +using System.Reflection; +using Microsoft.EntityFrameworkCore.Metadata.Internal; namespace IRaCIS.Core.Infrastructure.Extention { public static class QueryablePageListExtensions { - //单字段排序 - public static PageOutput ToPagedList(this IQueryable source, int pageIndex, int pageSize, string defaultSortFiled = "Id", bool isAsc = true) + + //单字段排序 异步 (或者默认排序字段是空,多字段排序,传递了,就以传递的单字段为准) + public static async Task> ToPagedListAsync(this IQueryable source, PageInput pageInput, bool isMultiSortFiled = false, string[] sortArray = default, CancellationToken cancellationToken = default) { - if (pageIndex <= 0) + + if (isMultiSortFiled && sortArray == default) { - pageIndex = 1; + throw new InvalidOperationException("The sort field must be specified"); } - if (pageSize <= 0) + + + if (pageInput.PageIndex <= 0) { - pageSize = 10; + pageInput.PageIndex = 1; } - var count = source.Count(); + if (pageInput.PageSize <= 0) + { + pageInput.PageSize = 10; + } + + var count = await source.CountAsync(cancellationToken).ConfigureAwait(false); if (count == 0) { return new PageOutput() { CurrentPageData = new T[0] }; } + var propName=string.Empty; - var propName = string.IsNullOrWhiteSpace(defaultSortFiled) ? "Id" : defaultSortFiled; + if (string.IsNullOrWhiteSpace(pageInput.SortField)) + { + //没有指定,优先以Id排序,否则从属性里面随便取出来一个排序 + var propertyNameList = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(t => t.CanWrite).Select(t => t.Name).OrderBy(t => t).ToList(); - source = isAsc ? source.OrderBy(propName) : source.OrderBy(propName + " desc"); + if (propertyNameList.Count == 0) + { + throw new InvalidOperationException("no default sort field."); + } + else + { + propName= propertyNameList.Contains("Id") ? "Id" : propertyNameList.FirstOrDefault(); + } + + } + else + { + //有值,以前段传输的为主 + propName = pageInput.SortField; + } + - source = source.Skip((pageIndex - 1) * pageSize); + if (!isMultiSortFiled) + { + source = pageInput.Asc ? source.OrderBy(propName) : source.OrderBy(propName + " desc"); - var items = source - .Take(pageSize) - .ToArray(); + } + else + { + var sortString = string.Join(',', sortArray); + + source = source.OrderBy(sortString); + } + + source = source.Skip((pageInput.PageIndex - 1) * pageInput.PageSize); + var items = await source + .Take(pageInput.PageSize) + .ToArrayAsync(cancellationToken) + .ConfigureAwait(false); var pagedList = new PageOutput() { - PageIndex = pageIndex, - PageSize = pageSize, + PageIndex = pageInput.PageIndex, + PageSize = pageInput.PageSize, TotalCount = count, CurrentPageData = items }; @@ -50,8 +92,10 @@ namespace IRaCIS.Core.Infrastructure.Extention return pagedList; } + + //单字段排序 异步 - public static async Task> ToPagedListAsync(this IQueryable source, int pageNumber, int pageSize, string defaultSortFiled = "Id", bool isAsc = true, bool isMultiSortFiled = false, string[] sortArray = default, CancellationToken cancellationToken = default) + public static async Task> ToPagedListAsync(this IQueryable source, int pageNumber, int pageSize, string defaultSortFiled = "Id", bool isAsc = true, bool isMultiSortFiled = false, string[] sortArray = default) { if (isMultiSortFiled && sortArray == default) @@ -68,7 +112,7 @@ namespace IRaCIS.Core.Infrastructure.Extention pageSize = 10; } - var count = await source.CountAsync(cancellationToken).ConfigureAwait(false); + var count = await source.CountAsync().ConfigureAwait(false); if (count == 0) { @@ -90,7 +134,7 @@ namespace IRaCIS.Core.Infrastructure.Extention source = source.Skip((pageNumber - 1) * pageSize); var items = await source .Take(pageSize) - .ToArrayAsync(cancellationToken) + .ToArrayAsync() .ConfigureAwait(false); var pagedList = new PageOutput() @@ -105,85 +149,11 @@ namespace IRaCIS.Core.Infrastructure.Extention } - public static PageOutput ToPagedList(this IList source, int pageIndex, int pageSize, string defaultSortFiled = "Id", bool isAsc = true) - { - if (pageIndex <= 0) - { - pageIndex = 1; - } - if (pageSize <= 0) - { - pageSize = 10; - } - var count = source.Count(); - if (count == 0) - { - return new PageOutput() { CurrentPageData = new List() }; - } - var propName = string.IsNullOrWhiteSpace(defaultSortFiled) ? "Id" : defaultSortFiled; - - IQueryable sourceQuery = isAsc ? source.AsQueryable().OrderBy(propName) : source.AsQueryable().OrderBy(propName + " desc"); - - sourceQuery = sourceQuery.Skip((pageIndex - 1) * pageSize); - - var items = sourceQuery - .Take(pageSize) - .ToArray(); - - var pagedList = new PageOutput() - { - PageIndex = pageIndex, - PageSize = pageSize, - TotalCount = count, - CurrentPageData = items - }; - - return pagedList; - } - - //多字段排序 ["a asc", "b desc", "c asc"] - public static PageOutput ToPagedList(this IQueryable source, int pageIndex, int pageSize, string[] sortArray) - { - if (pageIndex <= 0) - { - pageIndex = 1; - } - if (pageSize <= 0) - { - pageSize = 10; - } - var count = source.Count(); - - if (count == 0) - { - return new PageOutput() { CurrentPageData = new T[0] }; - } - - var sortString = string.Join(',', sortArray); - - source.OrderBy(sortString); - - source = source.Skip((pageIndex - 1) * pageSize); - - var items = source - .Take(pageSize) - .ToArray(); - - var pagedList = new PageOutput() - { - PageIndex = pageIndex, - PageSize = pageSize, - TotalCount = count, - CurrentPageData = items - }; - - return pagedList; - } //多字段排序异步 ["a asc", "b desc", "c asc"] - public static async Task> ToPagedListAsync(this IQueryable source, int pageNumber, int pageSize, string[] sortArray, CancellationToken cancellationToken = default) + public static async Task> ToPagedListAsync(this IQueryable source, int pageNumber, int pageSize, string[] sortArray) { if (pageNumber <= 0) { @@ -194,7 +164,7 @@ namespace IRaCIS.Core.Infrastructure.Extention pageSize = 10; } - var count = await source.CountAsync(cancellationToken).ConfigureAwait(false); + var count = await source.CountAsync().ConfigureAwait(false); if (count == 0) { @@ -212,7 +182,7 @@ namespace IRaCIS.Core.Infrastructure.Extention source = source.Skip((pageNumber - 1) * pageSize); var items = await source .Take(pageSize) - .ToArrayAsync(cancellationToken) + .ToArrayAsync() .ConfigureAwait(false); var pagedList = new PageOutput() @@ -227,6 +197,127 @@ namespace IRaCIS.Core.Infrastructure.Extention } + #region 同步方法废弃 + ////单字段排序 + //public static PageOutput ToPagedList(this IQueryable source, int pageIndex, int pageSize, string defaultSortFiled = "Id", bool isAsc = true) + //{ + // if (pageIndex <= 0) + // { + // pageIndex = 1; + // } + // if (pageSize <= 0) + // { + // pageSize = 10; + // } + // var count = source.Count(); + + // if (count == 0) + // { + // return new PageOutput() { CurrentPageData = new T[0] }; + // } + + + // var propName = string.IsNullOrWhiteSpace(defaultSortFiled) ? "Id" : defaultSortFiled; + + // source = isAsc ? source.OrderBy(propName) : source.OrderBy(propName + " desc"); + + // source = source.Skip((pageIndex - 1) * pageSize); + + // var items = source + // .Take(pageSize) + // .ToArray(); + + // var pagedList = new PageOutput() + // { + // PageIndex = pageIndex, + // PageSize = pageSize, + // TotalCount = count, + // CurrentPageData = items + // }; + + // return pagedList; + //} + + //public static PageOutput ToPagedList(this IList source, int pageIndex, int pageSize, string defaultSortFiled = "Id", bool isAsc = true) + //{ + // if (pageIndex <= 0) + // { + // pageIndex = 1; + // } + // if (pageSize <= 0) + // { + // pageSize = 10; + // } + // var count = source.Count(); + + // if (count == 0) + // { + // return new PageOutput() { CurrentPageData = new List() }; + // } + + // var propName = string.IsNullOrWhiteSpace(defaultSortFiled) ? "Id" : defaultSortFiled; + + // IQueryable sourceQuery = isAsc ? source.AsQueryable().OrderBy(propName) : source.AsQueryable().OrderBy(propName + " desc"); + + // sourceQuery = sourceQuery.Skip((pageIndex - 1) * pageSize); + + // var items = sourceQuery + // .Take(pageSize) + // .ToArray(); + + // var pagedList = new PageOutput() + // { + // PageIndex = pageIndex, + // PageSize = pageSize, + // TotalCount = count, + // CurrentPageData = items + // }; + + // return pagedList; + //} + + + ////多字段排序 ["a asc", "b desc", "c asc"] + //public static PageOutput ToPagedList(this IQueryable source, int pageIndex, int pageSize, string[] sortArray) + //{ + // if (pageIndex <= 0) + // { + // pageIndex = 1; + // } + // if (pageSize <= 0) + // { + // pageSize = 10; + // } + // var count = source.Count(); + + // if (count == 0) + // { + // return new PageOutput() { CurrentPageData = new T[0] }; + // } + + // var sortString = string.Join(',', sortArray); + + // source.OrderBy(sortString); + + // source = source.Skip((pageIndex - 1) * pageSize); + + // var items = source + // .Take(pageSize) + // .ToArray(); + + // var pagedList = new PageOutput() + // { + // PageIndex = pageIndex, + // PageSize = pageSize, + // TotalCount = count, + // CurrentPageData = items + // }; + + // return pagedList; + //} + #endregion + + } } diff --git a/IRaCIS.Core.Infrastructure/_IRaCIS/Output/IResponseOutput.cs b/IRaCIS.Core.Infrastructure/_IRaCIS/Output/IResponseOutput.cs index 13b15698a..c9f51dece 100644 --- a/IRaCIS.Core.Infrastructure/_IRaCIS/Output/IResponseOutput.cs +++ b/IRaCIS.Core.Infrastructure/_IRaCIS/Output/IResponseOutput.cs @@ -16,6 +16,11 @@ /// 消息 /// string ErrorMessage { get; } + + + public string LocalizedInfo { get; set; } + + } /// @@ -30,13 +35,4 @@ T Data { get; set; } } - //public interface IResponseOutput : IResponseOutput - //{ - // /// - // /// 返回数据 - // /// - // T Data { get; } - - // T2 OtherInfo { get; } - //} } diff --git a/IRaCIS.Core.Infrastructure/_IRaCIS/Output/ResponseOutput.cs b/IRaCIS.Core.Infrastructure/_IRaCIS/Output/ResponseOutput.cs index 74325db91..9023c87e5 100644 --- a/IRaCIS.Core.Infrastructure/_IRaCIS/Output/ResponseOutput.cs +++ b/IRaCIS.Core.Infrastructure/_IRaCIS/Output/ResponseOutput.cs @@ -1,4 +1,8 @@ -using Newtonsoft.Json; +using IRaCIS.Core.Domain.Share; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using static System.Runtime.InteropServices.JavaScript.JSType; namespace IRaCIS.Core.Infrastructure.Extention { @@ -7,10 +11,10 @@ namespace IRaCIS.Core.Infrastructure.Extention /// public class ResponseOutput : IResponseOutput { - /// - /// 是否成功标记 - /// - public bool IsSuccess { get; private set; } + /// + /// 是否成功标记 + /// + public bool IsSuccess { get; private set; } public ApiResponseCodeEnum Code { get; set; } = ApiResponseCodeEnum.OK; @@ -25,34 +29,20 @@ namespace IRaCIS.Core.Infrastructure.Extention /// 数据 兼顾以前 Json序列化的时候返回属性名为“Result” /// [JsonProperty("Result")] - public T Data { get; set; } + public T Data { get; set; } [JsonProperty("OtherInfo")] public object OtherData { get; set; } + public string LocalizedInfo { get; set; } - /// - /// 成功 - /// - /// 数据 - /// 消息 - //public ResponseOutput Ok(T data, string msg = "", ApiResponseCodeEnum code = ApiResponseCodeEnum.OK) - //{ - // IsSuccess = true; - // Code = code; - // Data = data; - // ErrorMessage = msg; - - // return this; - //} - - public ResponseOutput Ok(T data, object otherData, string msg = "", ApiResponseCodeEnum code = ApiResponseCodeEnum.OK) + public ResponseOutput Ok(T data, object otherData, string msg = "", ApiResponseCodeEnum code = ApiResponseCodeEnum.OK) { IsSuccess = true; Code = code; Data = data; - OtherData=otherData; + OtherData = otherData; ErrorMessage = msg; return this; @@ -64,12 +54,13 @@ namespace IRaCIS.Core.Infrastructure.Extention /// 提示消息 /// 数据 /// - public ResponseOutput NotOk(string msg = "", T data = default, ApiResponseCodeEnum code = ApiResponseCodeEnum.OK) + public ResponseOutput NotOk(string msg = "", T data = default, ApiResponseCodeEnum code = ApiResponseCodeEnum.OK, string localizedInfo = "") { IsSuccess = false; - Code = code; + Code = code; ErrorMessage = msg; Data = data; + LocalizedInfo = localizedInfo; return this; } @@ -77,33 +68,6 @@ namespace IRaCIS.Core.Infrastructure.Extention } - //public class ResponseOutput : IResponseOutput - //{ - // [JsonProperty("Result")] - // public T Data { get; private set; } - - // public T2 OtherInfo { get; private set; } - - // public bool IsSuccess { get; private set; } - - // public ApiResponseCodeEnum Code { get; set; } - - - // public string ErrorMessage { get; private set; } - - - // public ResponseOutput Ok(T data, T2 otherInfo, string msg = "") - // { - // IsSuccess = true; - // Data = data; - // OtherInfo = otherInfo; - // ErrorMessage = msg; - - // return this; - // } - //} - - /// /// 响应数据静态输出 为了代码简洁 不用每处都New /// @@ -111,23 +75,6 @@ namespace IRaCIS.Core.Infrastructure.Extention { - //public static IResponseOutput Ok(T data, T2 otherInfo, string msg = "") - //{ - // return new ResponseOutput().Ok(data, otherInfo); - //} - - - /// - /// 成功 -----适合查询 - /// - /// 数据 - /// 消息 - /// - //public static IResponseOutput Ok(T data = default, string msg = "") - //{ - // return new ResponseOutput().Ok(data, msg); - //} - public static IResponseOutput Ok(T data = default, object otherData = default, string msg = "", ApiResponseCodeEnum code = ApiResponseCodeEnum.OK) { return new ResponseOutput().Ok(data, otherData, msg, code); @@ -147,15 +94,11 @@ namespace IRaCIS.Core.Infrastructure.Extention /// 消息 /// 数据 /// - public static IResponseOutput NotOk(string msg = "", T data = default, ApiResponseCodeEnum code = ApiResponseCodeEnum.BusinessValidationFailed) + public static IResponseOutput NotOk(string msg = "", T data = default, ApiResponseCodeEnum code = ApiResponseCodeEnum.BusinessValidationFailed, string localizedInfo = "") { - return new ResponseOutput().NotOk(msg, data, code); + return new ResponseOutput().NotOk(msg, data, code, localizedInfo); } - //public static IResponseOutput NotOk( T data = default, ApiResponseCodeEnum code = ApiResponseCodeEnum.BusinessValidationFailed) - //{ - // return new ResponseOutput().NotOk("", data, code); - //} /// /// 失败 @@ -164,7 +107,22 @@ namespace IRaCIS.Core.Infrastructure.Extention /// public static IResponseOutput NotOk(string msg = "", ApiResponseCodeEnum code = ApiResponseCodeEnum.BusinessValidationFailed) { - return new ResponseOutput().NotOk(msg,code:code); + return new ResponseOutput().NotOk(msg, code: code); + } + + public static IResponseOutput NotOk(LocalizedString msg, ApiResponseCodeEnum code = ApiResponseCodeEnum.BusinessValidationFailed) + { + + var key = msg.Name; + + var info = string.Empty; + + if (!string.IsNullOrWhiteSpace(key) && StaticData.Log_Locoalize_Dic.ContainsKey(key)) + { + info = $"[{key}]:{StaticData.Log_Locoalize_Dic[key]}"; + } + + return new ResponseOutput().NotOk(msg, code: code, localizedInfo: info); } public static IResponseOutput DBNotExistIfNUll(object businessObject) @@ -172,7 +130,7 @@ namespace IRaCIS.Core.Infrastructure.Extention return new ResponseOutput().NotOk($"The business object{businessObject.GetType().Name} does not exist in the database, or was deleted by someone else, or an incorrect parameter query caused"); } - + /// /// 根据布尔值返回结果 --适合删除 /// @@ -190,7 +148,7 @@ namespace IRaCIS.Core.Infrastructure.Extention /// public static IResponseOutput Result(bool success, T data = default) { - return success ? Ok(data) : NotOk("Saved failed",data); + return success ? Ok(data) : NotOk("Saved failed", data); } ///// diff --git a/IRaCIS.Core.Domain/_Config/_StaticData.cs b/IRaCIS.Core.Infrastructure/_IRaCIS/_Config/_StaticData.cs similarity index 95% rename from IRaCIS.Core.Domain/_Config/_StaticData.cs rename to IRaCIS.Core.Infrastructure/_IRaCIS/_Config/_StaticData.cs index fd2c73df6..42ab4a9ca 100644 --- a/IRaCIS.Core.Domain/_Config/_StaticData.cs +++ b/IRaCIS.Core.Infrastructure/_IRaCIS/_Config/_StaticData.cs @@ -12,11 +12,21 @@ public static class StaticData public static Dictionary Zh_CN_Dic = new Dictionary(); + public static Dictionary Log_Locoalize_Dic = new Dictionary(); + public static readonly string En_US_Json = "en-US.json"; public static readonly string Zh_CN_Json = "zh-CN.json"; + public static class CultureInfo + { + public static readonly string zh_CN = "zh-CN"; + public static readonly string en_US = "en-US"; + + public static readonly string en_US_bookMark = "en_us"; + } + /// /// 获取国际化 /// @@ -208,6 +218,8 @@ public static class StaticData /// public static class Export { + public const string TrialList_Export = "TrialList_Export"; + public const string TrialTrainingRecordList_Export = "TrialTrainingRecordList_Export"; public const string TrialSiteUserList_Export = "TrialSiteUserList_Export"; diff --git a/IRaCIS.Core.Test/IRaCIS.Core.Test.csproj b/IRaCIS.Core.Test/IRaCIS.Core.Test.csproj index dae984eb7..2d9915d1d 100644 --- a/IRaCIS.Core.Test/IRaCIS.Core.Test.csproj +++ b/IRaCIS.Core.Test/IRaCIS.Core.Test.csproj @@ -77,11 +77,6 @@ True IRaCIS.Core.Dto.tt - - True - True - IRaCIS.Core.Entity.tt - True True @@ -102,12 +97,18 @@ True IRaCIS.Core.Services.tt + + True + True + IRaCIS.Core.Entity.tt + + diff --git a/IRaCIS.Core.Test/TT_Template/IRaCIS .Core.ServiceAsync.tt b/IRaCIS.Core.Test/TT_Template/IRaCIS .Core.ServiceAsync.tt index 5a1998a61..4fcd115d0 100644 --- a/IRaCIS.Core.Test/TT_Template/IRaCIS .Core.ServiceAsync.tt +++ b/IRaCIS.Core.Test/TT_Template/IRaCIS .Core.ServiceAsync.tt @@ -72,11 +72,9 @@ namespace IRaCIS.Core.Application.Service var <#=char.ToLower(tableName[0]) + tableName.Substring(1)#>Queryable = _<#=char.ToLower(tableName[0]) + tableName.Substring(1)#>Repository - .ProjectTo<<#=tableName#>View>(_mapper.ConfigurationProvider); + .ProjectTo<<#=tableName#>View>(_mapper.ConfigurationProvider); - var pageList= await <#=char.ToLower(tableName[0]) + tableName.Substring(1)#>Queryable - .ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrWhiteSpace(inQuery.SortField) ? nameof(<#=tableName#>View.Id) : inQuery.SortField, - inQuery.Asc); + var pageList= await <#=char.ToLower(tableName[0]) + tableName.Substring(1)#>Queryable.ToPagedListAsync(<#=tableName#>Query); return pageList; } diff --git a/IRaCIS.Core.Test/TT_Template/IRaCIS.Core.Dto.tt b/IRaCIS.Core.Test/TT_Template/IRaCIS.Core.Dto.tt index bf59c18a7..128807500 100644 --- a/IRaCIS.Core.Test/TT_Template/IRaCIS.Core.Dto.tt +++ b/IRaCIS.Core.Test/TT_Template/IRaCIS.Core.Dto.tt @@ -42,30 +42,34 @@ using IRaCIS.Core.Domain.Share; using System.Collections.Generic; namespace IRaCIS.Core.Application.ViewModel { - /// <#=tableName#>View 列表视图模型 - public class <#=tableName#>View + <# var excludedColumns = new[] { "CreateUserId", "UpdateUserId", "CreateTime", "UpdateTime" };#> + + /// <#=tableName#>View 列表视图 + public class <#=tableName#>View:<#=tableName#>AddOrEdit { <# foreach(DbColumn column in DbHelper.GetDbColumns(config.ConnectionString, config.DbDatabase, tableName)){#> + <# if (excludedColumns.Contains(column.ColumnName)){ #> public <#= column.CSharpType#><# if(column.CommonType.IsValueType && column.IsNullable){#>?<#}#> <#=column.ColumnName#> { get; set; } + <# }#> <# }#> } - ///<#=tableName#>Query 列表查询参数模型 + ///<#=tableName#>Query 列表查询参数 public class <#=tableName#>Query { - <# foreach(DbColumn column in DbHelper.GetDbColumns(config.ConnectionString, config.DbDatabase, tableName)){#><# if(column.CSharpType=="string"){#> - /// <#= column.Remark == "" ? column.ColumnName : column.Remark.Replace("\r\n","") #> - public <#= column.CSharpType#><# if(column.CommonType.IsValueType && column.IsNullable){#>?<#}#> <#=column.ColumnName#> { get; set; } - - <# }#> - <# }#> + <# foreach(DbColumn column in DbHelper.GetDbColumns(config.ConnectionString, config.DbDatabase, tableName)){#><# if(column.CSharpType=="string"){#> + public <#= column.CSharpType#><# if(column.CommonType.IsValueType && column.IsNullable){#>?<#}#> <#=column.ColumnName#> { get; set; } + <# }#> + <# }#> } - /// <#=tableName#>AddOrEdit 列表查询参数模型 + /// <#=tableName#>AddOrEdit 添加编辑 public class <#=tableName#>AddOrEdit { <# foreach(DbColumn column in DbHelper.GetDbColumns(config.ConnectionString, config.DbDatabase, tableName)){#> + <# if (!excludedColumns.Contains(column.ColumnName)){ #> public <#= column.CSharpType#><# if(column.CommonType.IsValueType && column.IsNullable){#>?<#}#> <#=column.ColumnName#> { get; set; } + <#}#> <# }#> } diff --git a/IRaCIS.Core.Test/TT_Template/IRaCIS.Core.Entity.cs b/IRaCIS.Core.Test/TT_Template/IRaCIS.Core.Entity.cs index 171fad3cb..b28b04f64 100644 --- a/IRaCIS.Core.Test/TT_Template/IRaCIS.Core.Entity.cs +++ b/IRaCIS.Core.Test/TT_Template/IRaCIS.Core.Entity.cs @@ -1,3 +1,3 @@ - + diff --git a/IRaCIS.Core.Test/TT_Template/IRaCIS.Core.Entity.tt b/IRaCIS.Core.Test/TT_Template/IRaCIS.Core.Entity.tt index c15229ffb..248a2d82a 100644 --- a/IRaCIS.Core.Test/TT_Template/IRaCIS.Core.Entity.tt +++ b/IRaCIS.Core.Test/TT_Template/IRaCIS.Core.Entity.tt @@ -1,4 +1,4 @@ -<#@ template debug="false" hostspecific="true" language="C#" #> +<#@ template debug="false" hostspecific="true" language="C#" #> <#@ output extension=".cs" #> <#@ assembly name="System.Core.dll" #> <#@ assembly name="System.Data.dll" #> @@ -27,13 +27,13 @@ <# foreach (var item in DbHelper.GetDbTablesNew(config.ConnectionString, config.DbDatabase,config.TableName)) { var tableName=item.ToString(); - manager.StartBlock(tableName+".cs",OutputPath1);//文件名 + manager.StartBlock(tableName+".cs",OutputPath1);//ļ #> //-------------------------------------------------------------------- -// 此代码由T4模板自动生成 byzhouhang 20210918 -// 生成时间 <#=DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")#> -// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 +// ˴T4ģԶ byzhouhang 20210918 +// ʱ <#=DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")#> +// ԴļĸĿܻᵼ²ȷΪɴ룬ЩĽᶪʧ using System; using IRaCIS.Core.Domain.Share; using System.ComponentModel.DataAnnotations; @@ -44,19 +44,15 @@ namespace IRaCIS.Core.Domain.Models ///<#=tableName#> /// [Table("<#=tableName#>")] - public class <#=tableName#> : Entity, IAuditUpdate, IAuditAdd + public class <#=tableName#> : BaseFullAuditEntity { - <# foreach(DbColumn column in DbHelper.GetDbColumns(config.ConnectionString, config.DbDatabase, tableName)){#> - - /// - /// <#= column.Remark == "" ? column.ColumnName : column.Remark.Replace("\r\n"," ") #> - /// - <# - if(column.IsPrimaryKey) - {#>[Key] - <#}#><# if(!column.IsNullable) {#>[Required] - <# }#>public <#= column.CSharpType#><# if(column.CommonType.IsValueType && column.IsNullable){#>?<#}#> <#=column.ColumnName#> { get; set; } - <#}#> + <# var excludedColumns = new[] { "CreateUserId", "Id", "UpdateUserId", "CreateTime", "UpdateTime", "DeleteUserId", "IsDeleted", "DeletedTime" };#> + <# foreach(DbColumn column in DbHelper.GetDbColumns(config.ConnectionString, config.DbDatabase, tableName)){ #> + <# if (!excludedColumns.Contains(column.ColumnName)){ #> + /// <#= column.Remark == "" ? column.ColumnName : column.Remark.Replace("\r\n"," ") #> + public <#= column.CSharpType#><# if(column.CommonType.IsValueType && column.IsNullable){#>?<#}#> <#=column.ColumnName#> { get; set; } + <#}#> + <#}#> } public virtual DbSet<<#=tableName#>> <#=tableName#> { get; set; } diff --git a/irc_api.drone.yml b/irc_api.drone.yml index 290fa2b13..a6e09d6e3 100644 --- a/irc_api.drone.yml +++ b/irc_api.drone.yml @@ -19,7 +19,7 @@ steps: - name: build-uat-irc commands: - cd /opt/1panel/xc-deploy/Uat_IRC/devops-build-publish/Uat-To-Uat - - sh pull-build-uat-irc-image.sh v${DRONE_BUILD_NUMBER} + - sh uat-branch-latest-build-image-publish.sh v${DRONE_BUILD_NUMBER} trigger: branch: