diff --git a/IRC.Core.SCP/BusinessFilter/UnifiedApiResultFilter.cs b/IRC.Core.SCP/BusinessFilter/UnifiedApiResultFilter.cs index 4dffb183c..69af4a5f9 100644 --- a/IRC.Core.SCP/BusinessFilter/UnifiedApiResultFilter.cs +++ b/IRC.Core.SCP/BusinessFilter/UnifiedApiResultFilter.cs @@ -77,7 +77,7 @@ namespace IRaCIS.Core.Application.Service.BusinessFilter else if(statusCode != 200&&!(objectResult.Value is IResponseOutput)) { //---程序错误,请联系开发人员。 - var apiResponse = ResponseOutput.NotOk(StaticData.International("UnifiedAPI_ProgramError")); + var apiResponse = ResponseOutput.NotOk(I18n.T("UnifiedAPI_ProgramError")); objectResult.Value = apiResponse; objectResult.DeclaredType = apiResponse.GetType(); diff --git a/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs b/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs index 847a069bb..c011f1f40 100644 --- a/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs +++ b/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs @@ -18,6 +18,8 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.StaticFiles; using Microsoft.AspNetCore.WebUtilities; @@ -43,6 +45,28 @@ namespace IRaCIS.Core.API.Controllers #region 上传基类封装 + + + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] + public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter + { + public void OnResourceExecuting(ResourceExecutingContext context) + { + + + var factories = context.ValueProviderFactories; + //factories.RemoveType(); + factories.RemoveType(); + factories.RemoveType(); + context.HttpContext.Request.EnableBuffering(); + } + + public void OnResourceExecuted(ResourceExecutedContext context) + { + } + } + + [DisableFormValueModelBinding] public abstract class UploadBaseController : ControllerBase { diff --git a/IRaCIS.Core.API/Progranm.cs b/IRaCIS.Core.API/Progranm.cs index 5c555bd6e..6d2307421 100644 --- a/IRaCIS.Core.API/Progranm.cs +++ b/IRaCIS.Core.API/Progranm.cs @@ -17,6 +17,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Localization; using Newtonsoft.Json; using Serilog; using System; @@ -62,14 +63,6 @@ builder.Configuration.AddJsonFile(ConfigMapFileProvider.FromRelativePath(""), "a builder.Host.UseSerilog(); -#region Autofac 废弃 -//builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory()) -// .ConfigureContainer(containerBuilder => -// { -// containerBuilder.RegisterModule(); -// }).UseWindowsService(); -#endregion - #endregion @@ -79,8 +72,8 @@ var _configuration = builder.Configuration; //手动注册服务 builder.Services.ConfigureServices(_configuration); -//异常处理 -//builder.Services.AddExceptionHandler(); +//minimal api 异常处理 +builder.Services.AddExceptionHandler(); //builder.Services.AddProblemDetails(); //健康检查 @@ -91,7 +84,6 @@ builder.Services.AddJsonLocalization(options => options.ResourcesPath = "Resourc // 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim() builder.Services.AddControllers(options => { - //options.Filters.Add(); options.Filters.Add(); options.Filters.Add(); options.Filters.Add(); @@ -148,7 +140,11 @@ builder.Services.AddMasaMinimalAPIs(options => options.DeletePrefixes = new List { "Delete", "Remove" }; options.RouteHandlerBuilder= t=> { - t.RequireAuthorization().AddEndpointFilter().WithGroupName("Institution"); + t.RequireAuthorization() + .AddEndpointFilter() + .AddEndpointFilter() + .AddEndpointFilter() + .WithGroupName("Institution"); }; options.DisableTrimMethodPrefix = true; //禁用去除方法前缀 options.DisableAutoMapRoute = false;//可通过配置true禁用全局自动路由映射或者删除此配置以启用全局自动路由映射 @@ -186,28 +182,8 @@ app.UseStatusCodePages(async context => }); -//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); - -//} -// }); -//}); +//app.UseExceptionHandler(); +app.UseExceptionHandler(o => { }); #region 暂时废弃 @@ -272,10 +248,16 @@ app.MapMasaMinimalAPIs(); // Serilog SerilogExtension.AddSerilogSetup(enviromentName, app.Services); + +//设置国际化I18n +var localizer = app.Services.GetRequiredService(); +I18n.SetLocalizer(localizer); + var hangfireJobService = app.Services.GetRequiredService(); await hangfireJobService.InitHangfireJobTaskAsync(); + try { #region 运行环境 部署平台 diff --git a/IRaCIS.Core.Application/BackGroundJob/IRaCISCHangfireJob.cs b/IRaCIS.Core.Application/BackGroundJob/IRaCISCHangfireJob.cs index efd823af2..18b02bbf5 100644 --- a/IRaCIS.Core.Application/BackGroundJob/IRaCISCHangfireJob.cs +++ b/IRaCIS.Core.Application/BackGroundJob/IRaCISCHangfireJob.cs @@ -1,7 +1,10 @@ using Hangfire; using Hangfire.Storage; using IRaCIS.Core.Application.Helper; +using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Share; +using MassTransit; +using MassTransit.Scheduling; using Microsoft.Extensions.Logging; namespace IRaCIS.Core.Application.Service.BackGroundJob @@ -9,15 +12,13 @@ namespace IRaCIS.Core.Application.Service.BackGroundJob public interface IIRaCISHangfireJob { - - //Task MemoryCacheTrialStatusAsync(); - Task InitHangfireJobTaskAsync(); } public class IRaCISCHangfireJob(ILogger _logger, IRepository _internationalizationRepository, - IRepository _trialEmailNoticeConfigRepository + IRepository _trialEmailNoticeConfigRepository, + IMessageScheduler _IMessageScheduler ) : IIRaCISHangfireJob { public static string JsonFileFolder = Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources); @@ -29,43 +30,29 @@ namespace IRaCIS.Core.Application.Service.BackGroundJob //初始化国际化 - await InternationalizationHelper.InitInternationlizationDataAndWatchJsonFileAsync(_internationalizationRepository); + //查询数据库的数据 + var toJsonList = await _internationalizationRepository.Where(t => t.InternationalizationType == 1).Select(t => new IRCGlobalInfoDTO() + { + Code = t.Code, + Value = t.Value, + ValueCN = t.ValueCN, + Description = t.Description + }).ToListAsync(); + + + await InternationalizationHelper.BatchAddJsonKeyValueAsync(toJsonList); //创建邮件定时任务 await InitSysAndTrialCronJobAsync(); - #region 废弃 - ////项目状态 立即加载到缓存中 - //await MemoryCacheTrialStatusAsync(); - - ////await MemoryCacheAnonymizeData(); - - - ////创建项目缓存 定时任务 - //HangfireJobHelper.AddOrUpdateInitCronJob("RecurringJob_Cache_TrialState", t => t.MemoryCacheTrialStatusAsync(), Cron.Daily()); - #endregion - _logger.LogInformation("项目启动 hangfire 任务初始化 执行结束"); } - - - - public async Task InitSysAndTrialCronJobAsync() { - //var deleteJobIdList = await _trialEmailNoticeConfigRepository.Where(t => t.Trial.TrialStatusStr != StaticData.TrialState.TrialOngoing && t.EmailCron != string.Empty && t.IsAutoSend) - // .Select(t => t.TrialId + "_" + t.Id) - // .ToListAsync(); - - //foreach (var jobId in deleteJobIdList) - //{ - // HangfireJobHelper.RemoveCronJob(jobId); - //} - var taskInfoList = await _trialEmailNoticeConfigRepository.Where(t => t.Trial.TrialStatusStr == StaticData.TrialState.TrialOngoing && t.EmailCron != string.Empty && t.IsAutoSend) .Select(t => new { t.Id, t.Code, t.EmailCron, t.BusinessScenarioEnum, t.TrialId }) @@ -76,24 +63,29 @@ namespace IRaCIS.Core.Application.Service.BackGroundJob //利用主键作为任务Id var jobId = $"{task.TrialId}_{task.Id}"; + switch (task.BusinessScenarioEnum) + { + + case EmailBusinessScenario.QCTask: + + break; + + case EmailBusinessScenario.CRCToQCQuestion: + + break; + case EmailBusinessScenario.QCToCRCImageQuestion: + break; + + default: + break; + } + + + + HangfireJobHelper.AddOrUpdateTrialCronJob(jobId, task.TrialId, task.BusinessScenarioEnum, task.EmailCron); } - var addOrUpdateJobIdList = taskInfoList.Select(t => $"{t.TrialId}_{t.Id}").ToList(); - - var list = JobStorage.Current.GetConnection().GetRecurringJobs().ToList(); - - //项目定时任务都在default 队列 - //var dbJobIdList = JobStorage.Current.GetConnection().GetRecurringJobs().Where(t => t.Queue == "default").Select(t => t.Id).ToList(); - - //var deleteList= dbJobIdList.Except(addOrUpdateJobIdList).ToList(); - - // foreach (var jobId in deleteList) - // { - // HangfireJobHelper.RemoveCronJob(jobId); - // } - - } diff --git a/IRaCIS.Core.Application/BusinessFilter/GlobalExceptionHandler.cs b/IRaCIS.Core.Application/BusinessFilter/GlobalExceptionHandler.cs deleted file mode 100644 index 70688e7e2..000000000 --- a/IRaCIS.Core.Application/BusinessFilter/GlobalExceptionHandler.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Microsoft.AspNetCore.Diagnostics; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Logging; - - -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/Encryption/EncreptApiResultFilter.cs b/IRaCIS.Core.Application/BusinessFilter/LegacyController/EncreptApiResultFilter.cs similarity index 100% rename from IRaCIS.Core.Application/BusinessFilter/Encryption/EncreptApiResultFilter.cs rename to IRaCIS.Core.Application/BusinessFilter/LegacyController/EncreptApiResultFilter.cs diff --git a/IRaCIS.Core.Application/BusinessFilter/LimitUserRequestAuthorization.cs b/IRaCIS.Core.Application/BusinessFilter/LegacyController/LimitUserRequestAuthorization.cs similarity index 86% rename from IRaCIS.Core.Application/BusinessFilter/LimitUserRequestAuthorization.cs rename to IRaCIS.Core.Application/BusinessFilter/LegacyController/LimitUserRequestAuthorization.cs index ec5ea0863..69bafe0f9 100644 --- a/IRaCIS.Core.Application/BusinessFilter/LimitUserRequestAuthorization.cs +++ b/IRaCIS.Core.Application/BusinessFilter/LegacyController/LimitUserRequestAuthorization.cs @@ -13,24 +13,10 @@ namespace IRaCIS.Core.Application.Filter; -public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter +public class LimitUserRequestAuthorization( + IFusionCache _fusionCache, IUserInfo _userInfo, IStringLocalizer _localizer, + IOptionsMonitor _verifyConfig) : IAsyncAuthorizationFilter { - public IStringLocalizer _localizer { get; set; } - - private readonly IFusionCache _fusionCache; - - private readonly IUserInfo _userInfo; - - private readonly IOptionsMonitor _verifyConfig; - - public LimitUserRequestAuthorization(IFusionCache fusionCache, IUserInfo userInfo, IStringLocalizer localizer, IOptionsMonitor verifyConfig) - { - _fusionCache = fusionCache; - _userInfo = userInfo; - _verifyConfig = verifyConfig; - _localizer = localizer; - } - public async Task OnAuthorizationAsync(AuthorizationFilterContext context) { diff --git a/IRaCIS.Core.Application/BusinessFilter/ModelActionFilter .cs b/IRaCIS.Core.Application/BusinessFilter/LegacyController/ModelActionFilter .cs similarity index 80% rename from IRaCIS.Core.Application/BusinessFilter/ModelActionFilter .cs rename to IRaCIS.Core.Application/BusinessFilter/LegacyController/ModelActionFilter .cs index a52ca0a52..63255f4fa 100644 --- a/IRaCIS.Core.Application/BusinessFilter/ModelActionFilter .cs +++ b/IRaCIS.Core.Application/BusinessFilter/LegacyController/ModelActionFilter .cs @@ -8,13 +8,9 @@ namespace IRaCIS.Core.Application.Filter; -public class ModelActionFilter : ActionFilterAttribute, IActionFilter +public class ModelActionFilter(IStringLocalizer _localizer) : ActionFilterAttribute, IActionFilter { - public IStringLocalizer _localizer; - public ModelActionFilter(IStringLocalizer localizer) - { - _localizer = localizer; - } + public override void OnActionExecuting(ActionExecutingContext context) { diff --git a/IRaCIS.Core.Application/BusinessFilter/LegacyController/ProjectExceptionFilter.cs b/IRaCIS.Core.Application/BusinessFilter/LegacyController/ProjectExceptionFilter.cs new file mode 100644 index 000000000..444c1dfbd --- /dev/null +++ b/IRaCIS.Core.Application/BusinessFilter/LegacyController/ProjectExceptionFilter.cs @@ -0,0 +1,66 @@ +using IRaCIS.Core.Domain.Share; +using IRaCIS.Core.Infrastructure; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; + +namespace IRaCIS.Core.Application.Filter; + +public class ProjectExceptionFilter(ILogger _logger, IStringLocalizer _localizer) : Attribute, IExceptionFilter +{ + + public void OnException(ExceptionContext context) + { + //context.ExceptionHandled;//记录当前这个异常是否已经被处理过了 + + var exception = context.Exception; + + if (!context.ExceptionHandled) + { + if (exception.GetType().Name == "DbUpdateConcurrencyException") + { + //---并发更新,当前不允许该操作 + context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ProjectException_ConcurrentUpdateNotAllowed"] + exception.Message)); + } + + if (exception.GetType() == typeof(BusinessValidationFailedException)) + { + var error = exception as BusinessValidationFailedException; + + var info = string.Empty; + + if (!string.IsNullOrWhiteSpace(error!.LocalizedKey) && StaticData.Localizer_Dev_Dic.ContainsKey(error!.LocalizedKey)) + { + info = $"[{error!.LocalizedKey}]:{StaticData.Localizer_Dev_Dic[error!.LocalizedKey]}"; + } + + + context.Result = new JsonResult(ResponseOutput.NotOk(exception.Message, "", error!.Code, localizedInfo: info)); + + } + else if (exception.GetType() == typeof(QueryBusinessObjectNotExistException)) + { + context.Result = new JsonResult(ResponseOutput.NotOk(exception.Message, ApiResponseCodeEnum.DataNotExist)); + } + else + { + context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (exception.InnerException is null ? (exception.Message) + : (exception.InnerException?.Message )), ApiResponseCodeEnum.ProgramException)); + + } + + context.ExceptionHandled = true;//标记当前异常已经被处理过了 + + + var errorInfo = $"Exception: {exception.Message}[{exception.StackTrace}]" + (exception.InnerException != null ? $" InnerException: {exception.InnerException.Message}[{exception.InnerException.StackTrace}]" : ""); + + _logger.LogError(errorInfo); + + } + else + { + //继续 + } + } +} diff --git a/IRaCIS.Core.Application/BusinessFilter/TrialResourceFilter.cs b/IRaCIS.Core.Application/BusinessFilter/LegacyController/TrialResourceFilter.cs similarity index 100% rename from IRaCIS.Core.Application/BusinessFilter/TrialResourceFilter.cs rename to IRaCIS.Core.Application/BusinessFilter/LegacyController/TrialResourceFilter.cs diff --git a/IRaCIS.Core.Application/BusinessFilter/LegacyController/UnifiedApiResultFilter.cs b/IRaCIS.Core.Application/BusinessFilter/LegacyController/UnifiedApiResultFilter.cs index a1997eabc..bba090181 100644 --- a/IRaCIS.Core.Application/BusinessFilter/LegacyController/UnifiedApiResultFilter.cs +++ b/IRaCIS.Core.Application/BusinessFilter/LegacyController/UnifiedApiResultFilter.cs @@ -83,7 +83,7 @@ public class UnifiedApiResultFilter : Attribute, IAsyncResultFilter else if (statusCode != 200 && !(objectResult.Value is IResponseOutput)) { //---程序错误,请联系开发人员。 - var apiResponse = ResponseOutput.NotOk(StaticData.International("UnifiedAPI_ProgramError")); + var apiResponse = ResponseOutput.NotOk(I18n.T("UnifiedAPI_ProgramError")); objectResult.Value = apiResponse; objectResult.DeclaredType = apiResponse.GetType(); diff --git a/IRaCIS.Core.Application/BusinessFilter/MinimalAPI/GlobalExceptionHandler.cs b/IRaCIS.Core.Application/BusinessFilter/MinimalAPI/GlobalExceptionHandler.cs new file mode 100644 index 000000000..1cdec4619 --- /dev/null +++ b/IRaCIS.Core.Application/BusinessFilter/MinimalAPI/GlobalExceptionHandler.cs @@ -0,0 +1,73 @@ +using DocumentFormat.OpenXml.InkML; +using IRaCIS.Core.Infrastructure; +using Microsoft.AspNetCore.Diagnostics; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; + + +namespace IRaCIS.Core.Application.BusinessFilter; + + +/// +/// minimal api 生效,但是传统控制器,没生效 +/// 参考处理链接: https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/error-handling?view=aspnetcore-8.0 +/// +public class GlobalExceptionHandler(IStringLocalizer _localizer, ILogger _logger) : IExceptionHandler +{ + + public ValueTask TryHandleAsync( + HttpContext httpContext, + Exception exception, + CancellationToken cancellationToken) + { + + httpContext.Response.StatusCode =StatusCodes.Status200OK; + + httpContext.Response.ContentType = "application/json"; + + if (exception.GetType().Name == "DbUpdateConcurrencyException") + { + //---并发更新,当前不允许该操作 + + httpContext.Response.WriteAsJsonAsync(ResponseOutput.NotOk(_localizer["ProjectException_ConcurrentUpdateNotAllowed"] + exception.Message)); + } + + if (exception.GetType() == typeof(BusinessValidationFailedException)) + { + var error = exception as BusinessValidationFailedException; + + var info = string.Empty; + + if (!string.IsNullOrWhiteSpace(error!.LocalizedKey) && StaticData.Localizer_Dev_Dic.ContainsKey(error!.LocalizedKey)) + { + info = $"[{error!.LocalizedKey}]:{StaticData.Localizer_Dev_Dic[error!.LocalizedKey]}"; + } + + httpContext.Response.WriteAsJsonAsync(ResponseOutput.NotOk(exception.Message, "", error!.Code, localizedInfo: info)); + + + + //warning 级别记录 + //_logger.LogWarning($"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}"); + } + else if (exception.GetType() == typeof(QueryBusinessObjectNotExistException)) + { + httpContext.Response.WriteAsJsonAsync(ResponseOutput.NotOk(exception.Message, ApiResponseCodeEnum.DataNotExist)); + } + else + { + httpContext.Response.WriteAsJsonAsync(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (exception.InnerException is null ? (exception.Message ) + : (exception.InnerException?.Message)), ApiResponseCodeEnum.ProgramException)); + + } + + var errorInfo = $"Exception: {exception.Message}[{exception.StackTrace}]" + (exception.InnerException != null ? $" InnerException: {exception.InnerException.Message}[{exception.InnerException.StackTrace}]" : ""); + + _logger.LogError(errorInfo); + + // Return false to continue with the default behavior + // - or - return true to signal that this exception is handled + return ValueTask.FromResult(false); + } +} diff --git a/IRaCIS.Core.Application/BusinessFilter/MinimalAPI/LimitUserRequestAuthorizationEndpointFilter.cs b/IRaCIS.Core.Application/BusinessFilter/MinimalAPI/LimitUserRequestAuthorizationEndpointFilter.cs new file mode 100644 index 000000000..0d7a9f5a3 --- /dev/null +++ b/IRaCIS.Core.Application/BusinessFilter/MinimalAPI/LimitUserRequestAuthorizationEndpointFilter.cs @@ -0,0 +1,85 @@ +using IRaCIS.Core.Application.Helper; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace IRaCIS.Core.Application.Service.BusinessFilter; + +#region minimalapi 流程 + + +public class LimitUserRequestAuthorizationEndpointFilter( + IFusionCache _fusionCache, IUserInfo _userInfo, IStringLocalizer _localizer, + IOptionsMonitor _verifyConfig) : IEndpointFilter +{ + + public async ValueTask InvokeAsync(EndpointFilterInvocationContext context, EndpointFilterDelegate next) + { + var minutes = _verifyConfig.CurrentValue.AutoLoginOutMinutes; + + if (_verifyConfig.CurrentValue.OpenLoginLimit) + { + // 如果此请求允许匿名访问,不进行处理 + var endpoint = context.HttpContext.GetEndpoint(); + if (endpoint?.Metadata?.GetMetadata() != null) + { + return await next(context); + } + + // 没有从请求中取到 token + if (string.IsNullOrWhiteSpace(_userInfo.UserToken)) + { + context.HttpContext.Response.ContentType = "application/json"; + return Results.Json(ResponseOutput.NotOk(_localizer["LimitUser_AuthTokenMissing"]), statusCode: StatusCodes.Status200OK); + } + + // 获取缓存中的用户 token + var cacheUserToken = await _fusionCache.GetOrDefaultAsync(CacheKeys.UserToken(_userInfo.Id)); + + // 缓存中没有取到 token + if (string.IsNullOrWhiteSpace(cacheUserToken)) + { + // 设置当前用户最新 token + await _fusionCache.SetAsync(CacheKeys.UserToken(_userInfo.Id), _userInfo.UserToken, TimeSpan.FromDays(7)); + await _fusionCache.SetAsync(CacheKeys.UserAutoLoginOut(_userInfo.Id), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(minutes)); + } + // 如果是同一个用户 + else if (cacheUserToken == _userInfo.UserToken) + { + var cacheTime = await _fusionCache.GetOrDefaultAsync(CacheKeys.UserAutoLoginOut(_userInfo.Id)); + + // 如果过期,自动登出 + if (string.IsNullOrEmpty(cacheTime)) + { + context.HttpContext.Response.ContentType = "application/json"; + return Results.Json(ResponseOutput.NotOk(_localizer["LimitUser_AccountAuto_LoginOut"], ApiResponseCodeEnum.AutoLoginOut), statusCode: StatusCodes.Status403Forbidden); + } + else + { + await _fusionCache.SetAsync(CacheKeys.UserAutoLoginOut(_userInfo.Id), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(minutes)); + } + } + else + { + // 如果账户在其他地方已登录,当前用户被迫下线 + context.HttpContext.Response.ContentType = "application/json"; + return Results.Json(ResponseOutput.NotOk(_localizer["LimitUser_AccountLoggedInElsewhere"], ApiResponseCodeEnum.LoginInOtherPlace), statusCode: StatusCodes.Status403Forbidden); + } + } + + // 如果通过授权,继续执行请求管道 + return await next(context); + + } + + +} + +#endregion \ No newline at end of file diff --git a/IRaCIS.Core.Application/BusinessFilter/MinimalAPI/ModelValidationEndpointFilter.cs b/IRaCIS.Core.Application/BusinessFilter/MinimalAPI/ModelValidationEndpointFilter.cs new file mode 100644 index 000000000..32af30c35 --- /dev/null +++ b/IRaCIS.Core.Application/BusinessFilter/MinimalAPI/ModelValidationEndpointFilter.cs @@ -0,0 +1,58 @@ +using Microsoft.AspNetCore.Http; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace IRaCIS.Core.Application.BusinessFilter; + +public class ModelValidationEndpointFilter(IStringLocalizer _localizer) : IEndpointFilter +{ + public async ValueTask InvokeAsync(EndpointFilterInvocationContext context, EndpointFilterDelegate next) + { + var httpContext = context.HttpContext; + + //// 1. 获取路由参数并验证 + //foreach (var routeValue in httpContext.Request.RouteValues) + //{ + // { + // return Results.BadRequest(new { ErrorMessage = $"Invalid format for {routeValue.Key}." }); + // } + //} + + //// 2. 获取查询参数并验证 + //foreach (var queryValue in httpContext.Request.Query) + //{ + // { + // return Results.BadRequest(new { ErrorMessage = $"Invalid format for {queryValue.Key}." }); + // } + //} + + + // 获取请求中的模型参数 + var model = context.Arguments.FirstOrDefault(a => a != null && a.GetType().IsClass); + + // 仅当模型存在时执行验证 + if (model != null) + { + var validationResults = new List(); + var validationContext = new ValidationContext(model); + bool isValid = Validator.TryValidateObject(model, validationContext, validationResults, true); + + if (!isValid) + { + var validationErrors = validationResults.Select(vr => vr.ErrorMessage).ToArray(); + return Results.Json(new + { + ErrorMessage = _localizer["ModelAction_InvalidAPIParameter"], + Errors = validationErrors + }, statusCode: StatusCodes.Status400BadRequest); + } + } + + // 验证通过,继续执行 + return await next(context); + } +} diff --git a/IRaCIS.Core.Application/BusinessFilter/MinimalAPI/TrialGlobalLimitEndpointFilter.cs b/IRaCIS.Core.Application/BusinessFilter/MinimalAPI/TrialGlobalLimitEndpointFilter.cs new file mode 100644 index 000000000..d50a6c102 --- /dev/null +++ b/IRaCIS.Core.Application/BusinessFilter/MinimalAPI/TrialGlobalLimitEndpointFilter.cs @@ -0,0 +1,17 @@ +using Microsoft.AspNetCore.Http; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace IRaCIS.Core.Application.BusinessFilter; + +public class TrialGlobalLimitEndpointFilter : IEndpointFilter + +{ + public ValueTask InvokeAsync(EndpointFilterInvocationContext context, EndpointFilterDelegate next) + { + throw new NotImplementedException(); + } +} diff --git a/IRaCIS.Core.Application/BusinessFilter/MinimalAPI/UnifiedApiResultEndpointFilter.cs b/IRaCIS.Core.Application/BusinessFilter/MinimalAPI/UnifiedApiResultEndpointFilter.cs index 559c9f3ab..008655bc5 100644 --- a/IRaCIS.Core.Application/BusinessFilter/MinimalAPI/UnifiedApiResultEndpointFilter.cs +++ b/IRaCIS.Core.Application/BusinessFilter/MinimalAPI/UnifiedApiResultEndpointFilter.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; @@ -11,14 +12,8 @@ namespace IRaCIS.Core.Application.Service.BusinessFilter; #region minimalapi 流程 -public class UnifiedApiResultEndpointFilter : IEndpointFilter +public class UnifiedApiResultEndpointFilter(ILogger _logger) : IEndpointFilter { - private readonly ILogger _logger; - - public UnifiedApiResultEndpointFilter(ILogger logger) - { - _logger = logger; - } public async ValueTask InvokeAsync(EndpointFilterInvocationContext context, EndpointFilterDelegate next) { @@ -37,8 +32,13 @@ public class UnifiedApiResultEndpointFilter : IEndpointFilter return ResponseOutput.Ok(tuple.Item1, tuple.Item2); } - if (result is IResponseOutput) - { + if (result is IResponseOutput responseOutput) + { + if (!string.IsNullOrWhiteSpace(responseOutput.LocalizedInfo)) + { + //统一在这里记录国际化的日志信息 + _logger.LogWarning($"{responseOutput.LocalizedInfo}"); + } return result; } diff --git a/IRaCIS.Core.Application/BusinessFilter/ModelBinding.cs b/IRaCIS.Core.Application/BusinessFilter/ModelBinding.cs deleted file mode 100644 index 994d9fa09..000000000 --- a/IRaCIS.Core.Application/BusinessFilter/ModelBinding.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.AspNetCore.Mvc.ModelBinding; - -namespace IRaCIS.Core.Application.Filter; - -#region snippet_DisableFormValueModelBindingAttribute -[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] -public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter -{ - public void OnResourceExecuting(ResourceExecutingContext context) - { - - - var factories = context.ValueProviderFactories; - //factories.RemoveType(); - factories.RemoveType(); - factories.RemoveType(); - context.HttpContext.Request.EnableBuffering(); - } - - public void OnResourceExecuted(ResourceExecutedContext context) - { - } -} -#endregion diff --git a/IRaCIS.Core.Application/BusinessFilter/ProjectExceptionFilter.cs b/IRaCIS.Core.Application/BusinessFilter/ProjectExceptionFilter.cs deleted file mode 100644 index 1825c3728..000000000 --- a/IRaCIS.Core.Application/BusinessFilter/ProjectExceptionFilter.cs +++ /dev/null @@ -1,75 +0,0 @@ -using IRaCIS.Core.Domain.Share; -using IRaCIS.Core.Infrastructure; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.Extensions.Localization; -using Microsoft.Extensions.Logging; - -namespace IRaCIS.Core.Application.Filter; - -public class ProjectExceptionFilter : Attribute, IExceptionFilter -{ - private readonly ILogger _logger; - - public IStringLocalizer _localizer; - - public ProjectExceptionFilter(IStringLocalizer localizer, ILogger logger) - { - _logger = logger; - _localizer = localizer; - } - public void OnException(ExceptionContext context) - { - //context.ExceptionHandled;//记录当前这个异常是否已经被处理过了 - - if (!context.ExceptionHandled) - { - if (context.Exception.GetType().Name == "DbUpdateConcurrencyException") - { - //---并发更新,当前不允许该操作 - context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ProjectException_ConcurrentUpdateNotAllowed"] + context.Exception.Message)); - } - - if (context.Exception.GetType() == typeof(BusinessValidationFailedException)) - { - var error = context.Exception as BusinessValidationFailedException; - - 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)) - { - 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;//标记当前异常已经被处理过了 - - - //throw new Exception("test-result-exceptioin"); - - } - else - { - //继续 - } - } -} diff --git a/IRaCIS.Core.Application/Helper/FileStoreHelper.cs b/IRaCIS.Core.Application/Helper/FileStoreHelper.cs index bfb4e39d3..709631876 100644 --- a/IRaCIS.Core.Application/Helper/FileStoreHelper.cs +++ b/IRaCIS.Core.Application/Helper/FileStoreHelper.cs @@ -135,7 +135,7 @@ public static class FileStoreHelper if (doc == null) { //---数据库没有找到对应的数据模板文件,请联系系统运维人员。 - throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileNotFound")); + throw new BusinessValidationFailedException(I18n.T("FileStore_TemplateFileNotFound")); } var filePath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, doc.Path); @@ -143,7 +143,7 @@ public static class FileStoreHelper if (!System.IO.File.Exists(filePath)) { //---数据模板文件存储路径上未找对应文件,请联系系统运维人员。 - throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileStoragePathInvalid")); + throw new BusinessValidationFailedException(I18n.T("FileStore_TemplateFileStoragePathInvalid")); } return (filePath, isEn_US ? doc.Name.Trim('/') : doc.NameCN.Trim('/')); @@ -269,7 +269,7 @@ public static class FileStoreHelper { //---解析Json文件配置出现问题 - throw new BusinessValidationFailedException(StaticData.International("SysMon_JsonConfig") + e.Message); + throw new BusinessValidationFailedException(I18n.T("SysMon_JsonConfig") + e.Message); } //默认存储的路径 diff --git a/IRaCIS.Core.Application/Helper/HangfireJobHelper.cs b/IRaCIS.Core.Application/Helper/HangfireJobHelper.cs index 7b4d669c3..f27c6c1f9 100644 --- a/IRaCIS.Core.Application/Helper/HangfireJobHelper.cs +++ b/IRaCIS.Core.Application/Helper/HangfireJobHelper.cs @@ -64,10 +64,10 @@ namespace IRaCIS.Core.Application.Helper case EmailBusinessScenario.QCTask: HangfireJobHelper.AddOrUpdateCronJob(jobId, t => t.SendTrialImageQCTaskEmailAsync(trialId), emailCron); break; - case EmailBusinessScenario.QCQuestion: + case EmailBusinessScenario.CRCToQCQuestion: HangfireJobHelper.AddOrUpdateCronJob(jobId, t => t.SendTrialQCQuestionEmailAsync(trialId), emailCron); break; - case EmailBusinessScenario.ImageQuestion: + case EmailBusinessScenario.QCToCRCImageQuestion: HangfireJobHelper.AddOrUpdateCronJob(jobId, t => t.SendTrialImageQuestionAsync(trialId), emailCron); break; diff --git a/IRaCIS.Core.Application/Helper/InternationalizationHelper.cs b/IRaCIS.Core.Application/Helper/InternationalizationHelper.cs index a1b47c837..05bb7c97f 100644 --- a/IRaCIS.Core.Application/Helper/InternationalizationHelper.cs +++ b/IRaCIS.Core.Application/Helper/InternationalizationHelper.cs @@ -4,201 +4,134 @@ using IRaCIS.Core.Infrastructure; using Microsoft.Extensions.Configuration; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using SharpCompress.Common; namespace IRaCIS.Core.Application.Helper; + +public class IRCGlobalInfoDTO +{ + public string Code { get; set; } + + public string Value { get; set; } + + public string ValueCN { get; set; } + + public string Description { get; set; } +} + public static class InternationalizationHelper { public static string JsonFileFolder = Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources); - public static FileSystemWatcher FileSystemWatcher_US { get; set; } - public static FileSystemWatcher FileSystemWatcher_CN { get; set; } + public static string USJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json); + public static string CNJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json); - private static void VerifyFolder() + static InternationalizationHelper() { if (!Directory.Exists(JsonFileFolder) || - !Directory.GetFiles(JsonFileFolder).Any(filePath => Path.GetExtension(filePath).Equals(".json", StringComparison.OrdinalIgnoreCase))) + !Directory.GetFiles(JsonFileFolder).Any(filePath => Path.GetExtension(filePath).Equals(".json", StringComparison.OrdinalIgnoreCase)) || + !File.Exists(USJsonPath) || !File.Exists(CNJsonPath)) { - throw new BusinessValidationFailedException("国际化Json文件目录有误"); + throw new BusinessValidationFailedException(I18n.T("IRaCISCHangfireJob_FileNotFound")); } } - public static async Task BatchAddJsonKeyValueAsync(List batchAddDtos) + + + public static async Task BatchAddJsonKeyValueAsync(List list) { - VerifyFolder(); + await StoreInfoToFileAsync(list); + } - var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json); - var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json); + public static async Task AddOrUpdateJsonKeyValueAsync(IRCGlobalInfoDTO info) + { + var list = new List() { info }; + + await StoreInfoToFileAsync(list); + + } - //更新json 文件 同时更新内存缓存的数据 - foreach (var filePath in new string[] { usJsonPath, cnJsonPath }) + public static async Task StoreInfoToFileAsync(List list) + { + foreach (var filePath in new string[] { USJsonPath, CNJsonPath }) { var json = await File.ReadAllTextAsync(filePath); JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load }); - // 添加或更新指定的键值对 - if (filePath.Contains(StaticData.En_US_Json)) { - foreach (var item in batchAddDtos) + foreach (var tojsonItem in list) { - jsonObject[item.Code] = item.Value; - - StaticData.En_US_Dic[item.Code] = item.Value; + jsonObject[tojsonItem.Code] = tojsonItem.Value; //日志记录该信息方便自己人看, 返回给客户的是配置的 - StaticData.Log_Locoalize_Dic[item.Code] = item.Description; + StaticData.Localizer_Dev_Dic[tojsonItem.Code] = tojsonItem.Description; } } else { - foreach (var item in batchAddDtos) + foreach (var tojsonItem in list) { - jsonObject[item.Code] = item.Value; + jsonObject[tojsonItem.Code] = tojsonItem.ValueCN; - StaticData.Zh_CN_Dic[item.Code] = item.Value; } } - await File.WriteAllTextAsync(filePath, jsonObject.ToString()); - } } - public static async Task AddOrUpdateJsonKeyValueAsync(string key, string value, string valueCN, string description) - { - - VerifyFolder(); - - var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json); - var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json); - //更新json 文件 同时更新内存缓存的数据 - foreach (var filePath in new string[] { usJsonPath, cnJsonPath }) - { - var json = await File.ReadAllTextAsync(filePath); + #region 监测Json文件变更 实时刷新数据 废弃 + //FileSystemWatcher_US = new FileSystemWatcher + //{ + // Path = Path.GetDirectoryName(USJsonPath)!, + // NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size, + // Filter = Path.GetFileName(USJsonPath), + // EnableRaisingEvents = true, - JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load }); - - // 添加或更新指定的键值对 - - if (filePath.Contains(StaticData.En_US_Json)) - { - jsonObject[key] = value; - - StaticData.En_US_Dic[key] = value; - - //日志记录该信息方便自己人看, 返回给客户的是配置的 - StaticData.Log_Locoalize_Dic[key] = description; - } - else - { - jsonObject[key] = valueCN; - - StaticData.Zh_CN_Dic[key] = valueCN; - } + //}; + //// 添加文件更改事件的处理程序 + //FileSystemWatcher_US.Changed += (sender, e) => LoadJsonFile(StaticData.Folder.Resources + "\\" + StaticData.En_US_Json); - await File.WriteAllTextAsync(filePath, jsonObject.ToString()); + //FileSystemWatcher_CN = new FileSystemWatcher + //{ + // Path = Path.GetDirectoryName(CNJsonPath)!, + // NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size, + // Filter = Path.GetFileName(CNJsonPath), + // EnableRaisingEvents = true, - } - - } + //}; + //FileSystemWatcher_CN.Changed += (sender, e) => LoadJsonFile(StaticData.Folder.Resources + "\\" + StaticData.Zh_CN_Json); - public static async Task InitInternationlizationDataAndWatchJsonFileAsync(IRepository _internationalizationRepository) - { - //查询数据库的数据 - var toJsonList = await _internationalizationRepository.Where(t => t.InternationalizationType == 1).Select(t => new - { - t.Code, - t.Value, - t.ValueCN, - t.Description - }).ToListAsync(); + //private static void LoadJsonFile(string filePath) + //{ + // Console.WriteLine("刷新json内存数据"); + // IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile(filePath, false, false); - //组织成json 文件 + // IConfigurationRoot enConfiguration = builder.Build(); - var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json); - var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json); + // foreach (IConfigurationSection section in enConfiguration.GetChildren()) + // { + // if (filePath.Contains(StaticData.En_US_Json)) + // { + // StaticData.En_US_Dic[section.Key] = section.Value; + // } + // else + // { + // StaticData.Zh_CN_Dic[section.Key] = section.Value; + // } + // } + //} - //本地静态文件国际化需要 - foreach (var tojsonItem in toJsonList) - { - 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)); - File.WriteAllText(cnJsonPath, JsonConvert.SerializeObject(StaticData.Zh_CN_Dic)); - - - //监测Json文件变更 实时刷新数据 - - if (!File.Exists(usJsonPath) || !File.Exists(cnJsonPath)) - { - throw new BusinessValidationFailedException(StaticData.International("IRaCISCHangfireJob_FileNotFound")); - } - - - // //监测Json文件变更 实时刷新数据 - - - FileSystemWatcher_US = new FileSystemWatcher - { - Path = Path.GetDirectoryName(usJsonPath)!, - NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size, - Filter = Path.GetFileName(usJsonPath), - EnableRaisingEvents = true, - - }; - // 添加文件更改事件的处理程序 - FileSystemWatcher_US.Changed += (sender, e) => LoadJsonFile(StaticData.Folder.Resources + "\\" + StaticData.En_US_Json); - - - FileSystemWatcher_CN = new FileSystemWatcher - { - Path = Path.GetDirectoryName(cnJsonPath)!, - NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size, - Filter = Path.GetFileName(cnJsonPath), - EnableRaisingEvents = true, - - }; - FileSystemWatcher_CN.Changed += (sender, e) => LoadJsonFile(StaticData.Folder.Resources + "\\" + StaticData.Zh_CN_Json); - - } - - - - private static void LoadJsonFile(string filePath) - { - Console.WriteLine("刷新json内存数据"); - IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile(filePath, false, false); - - IConfigurationRoot enConfiguration = builder.Build(); - - foreach (IConfigurationSection section in enConfiguration.GetChildren()) - { - if (filePath.Contains(StaticData.En_US_Json)) - { - StaticData.En_US_Dic[section.Key] = section.Value; - - } - else - { - StaticData.Zh_CN_Dic[section.Key] = section.Value; - } - } - } - + #endregion diff --git a/IRaCIS.Core.Application/Helper/SendEmailHelper.cs b/IRaCIS.Core.Application/Helper/SendEmailHelper.cs index c424a0814..3179c16e1 100644 --- a/IRaCIS.Core.Application/Helper/SendEmailHelper.cs +++ b/IRaCIS.Core.Application/Helper/SendEmailHelper.cs @@ -42,7 +42,7 @@ public static class SendEmailHelper { //---邮件发送失败,您进行的操作未能成功,请检查邮箱或联系维护人员 - throw new Exception(StaticData.International("SendEmail_SendFail"), new Exception(ex.Message)); + throw new Exception(I18n.T("SendEmail_SendFail"), new Exception(ex.Message)); } @@ -82,7 +82,7 @@ public static class SendEmailHelper if (sMTPEmailConfig.ToMailAddressList.Count == 0) { //---没有收件人 - throw new ArgumentException(StaticData.International("SendEmail_NoRecipient")); + throw new ArgumentException(I18n.T("SendEmail_NoRecipient")); } else { diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj b/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj index eb12535aa..9c039cd04 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj @@ -27,6 +27,7 @@ + @@ -40,6 +41,9 @@ true PreserveNewest + + Always + diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml index c1b4fc0cc..21ebebc56 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -12747,7 +12747,14 @@ - 不生效,不知道为啥 + minimal api 生效,但是传统控制器,没生效 + 参考处理链接: https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/error-handling?view=aspnetcore-8.0 + + + + + minimal api 生效,但是传统控制器,没生效 + 参考处理链接: https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/error-handling?view=aspnetcore-8.0 @@ -12890,42 +12897,6 @@ 构造函数注入 - - - 添加Subject 触发添加访视 不能代替 Trigger,稽查BatchId 不一致 - 因为消费者这里的数据库上下文 和消息发送者上下文不是同一个,相当于两个独立的事务 - - - - - - - - - 添加Subject 触发添加访视 不能代替 Trigger,稽查BatchId 不一致 - 因为消费者这里的数据库上下文 和消息发送者上下文不是同一个,相当于两个独立的事务 - - - - - - - - - meditor send 的时候,请求流会先到消费者,返回后才会执行后续代码 - publish 请求流不会先到消费者,发布后,直接执行后续代码 - - - - - - - meditor send 的时候,请求流会先到消费者,返回后才会执行后续代码 - publish 请求流不会先到消费者,发布后,直接执行后续代码 - - - - 加急的医学反馈任务 通知MIM @@ -13014,11 +12985,42 @@ 通知PM 进行一致性核查 + + + meditor send 的时候,请求流会先到消费者,返回后才会执行后续代码 + publish 请求流不会先到消费者,发布后,直接执行后续代码 + + + + + + + meditor send 的时候,请求流会先到消费者,返回后才会执行后续代码 + publish 请求流不会先到消费者,发布后,直接执行后续代码 + + + + 参考链接:https://github.com/MassTransit/MassTransit/discussions/2498 + + + QC 影像质疑待处理 + + + + + CRC 影像质疑 + + + + + 影像质控 + + TaskAllocationRuleView 列表视图模型 diff --git a/IRaCIS.Core.Application/MassTransit/Consumer/NeedVerify/AddSubjectTriggerConsumer.cs b/IRaCIS.Core.Application/MassTransit/Consumer/NeedVerify/AddSubjectTriggerConsumer.cs deleted file mode 100644 index f9875948e..000000000 --- a/IRaCIS.Core.Application/MassTransit/Consumer/NeedVerify/AddSubjectTriggerConsumer.cs +++ /dev/null @@ -1,101 +0,0 @@ - - -using AutoMapper; -using IRaCIS.Core.Domain; -using MassTransit; -using Microsoft.AspNetCore.Http; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; - -namespace IRaCIS.Core.Application.MassTransit.Consumer; - - - - -/// -/// 添加Subject 触发添加访视 不能代替 Trigger,稽查BatchId 不一致 -/// 因为消费者这里的数据库上下文 和消息发送者上下文不是同一个,相当于两个独立的事务 -/// -/// -/// -/// -/// -public class AddSubjectTriggerConsumer(IRepository _subjectVisitRepository, - - IRepository _visitStageRepository, - IRepository _trialRepository, - IMapper _mapper) : IConsumer -{ - public async Task Consume(ConsumeContext context) - { - var addSubjectEvent = context.Message; - - - { - Console.WriteLine(_visitStageRepository._dbContext.GetHashCode()); - - Console.WriteLine("两个 DbContext 不是同一个实例"); - } - - - //添加受试者的时候,获取访视计划列表,添加到受试者访视表。 - var visitPlanList = await _visitStageRepository.Where(t => t.TrialId == addSubjectEvent.TrialId && t.IsConfirmed).ToListAsync(); - - var svList = _mapper.Map>(visitPlanList); - - var IsEnrollementQualificationConfirm = await _trialRepository.Where(t => t.Id == addSubjectEvent.TrialId).Select(u => u.IsEnrollementQualificationConfirm).FirstOrDefaultAsync(); - - svList.ForEach(t => - { - t.SubjectId = addSubjectEvent.SubjectId; - t.TrialId = addSubjectEvent.TrialId; - t.TrialSiteId = addSubjectEvent.TrialSiteId; - t.IsEnrollmentConfirm = t.IsBaseLine ? IsEnrollementQualificationConfirm : false; - t.Id = NewId.NextGuid(); - - }); - - await _subjectVisitRepository.AddRangeAsync(svList); - } -} - -public class AddSubjectTriggerConsumer2(IRepository _subjectVisitRepository, - - IRepository _visitStageRepository, - IRepository _trialRepository, - IMapper _mapper) : IConsumer -{ - public async Task Consume(ConsumeContext context) - { - var addSubjectEvent = context.Message; - - - { - Console.WriteLine(_visitStageRepository._dbContext.GetHashCode()); - - Console.WriteLine("两个 DbContext 不是同一个实例"); - } - - - //添加受试者的时候,获取访视计划列表,添加到受试者访视表。 - var visitPlanList = await _visitStageRepository.Where(t => t.TrialId == addSubjectEvent.TrialId && t.IsConfirmed).ToListAsync(); - - var svList = _mapper.Map>(visitPlanList); - - var IsEnrollementQualificationConfirm = await _trialRepository.Where(t => t.Id == addSubjectEvent.TrialId).Select(u => u.IsEnrollementQualificationConfirm).FirstOrDefaultAsync(); - - svList.ForEach(t => - { - t.SubjectId = addSubjectEvent.SubjectId; - t.TrialId = addSubjectEvent.TrialId; - t.TrialSiteId = addSubjectEvent.TrialSiteId; - t.IsEnrollmentConfirm = t.IsBaseLine ? IsEnrollementQualificationConfirm : false; - t.Id = NewId.NextGuid(); - - }); - - await _subjectVisitRepository.AddRangeAsync(svList); - } -} - - diff --git a/IRaCIS.Core.Application/MassTransit/Consumer/NeedVerify/TestConsumer.cs b/IRaCIS.Core.Application/MassTransit/Consumer/TestConsumer.cs similarity index 99% rename from IRaCIS.Core.Application/MassTransit/Consumer/NeedVerify/TestConsumer.cs rename to IRaCIS.Core.Application/MassTransit/Consumer/TestConsumer.cs index 07d313afa..0dbef2b9d 100644 --- a/IRaCIS.Core.Application/MassTransit/Consumer/NeedVerify/TestConsumer.cs +++ b/IRaCIS.Core.Application/MassTransit/Consumer/TestConsumer.cs @@ -54,6 +54,7 @@ public class TestMasstransitService : BaseService { var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US; + Console.WriteLine(_testLengthRepository._dbContext.GetHashCode()); //IScopedMediator 上下文一致, IMediator上下文不一致 diff --git a/IRaCIS.Core.Application/MassTransit/Recurring/RecurringEmailConsumer.cs b/IRaCIS.Core.Application/MassTransit/Recurring/RecurringEmailConsumer.cs new file mode 100644 index 000000000..fb35a334a --- /dev/null +++ b/IRaCIS.Core.Application/MassTransit/Recurring/RecurringEmailConsumer.cs @@ -0,0 +1,56 @@ +using MassTransit; +using MassTransit.Scheduling; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace IRaCIS.Core.Application.MassTransit.Consumer; +public abstract class IRCRecurringSchedule : + RecurringSchedule +{ + protected IRCRecurringSchedule() + { + ScheduleGroup = GetType().Name; + + TimeZoneId = TimeZoneInfo.Local.Id; + StartTime = DateTime.Now; + } + + public MissedEventPolicy MisfirePolicy { get; protected set; } + public string TimeZoneId { get; protected set; } + public DateTimeOffset StartTime { get; protected set; } + public DateTimeOffset? EndTime { get; protected set; } + public string ScheduleId { get; private set; } + public string ScheduleGroup { get; private set; } + public string CronExpression { get; protected set; } + public string Description { get; protected set; } +} + +/// +/// QC 影像质疑待处理 +/// +public class QCImageQuestionSchedule : IRCRecurringSchedule +{ + +} + +/// +/// CRC 影像质疑 +/// +public class CRCImageQuestionSchedule : IRCRecurringSchedule +{ + +} + +/// +/// 影像质控 +/// +public class ImageQCSchedule : IRCRecurringSchedule +{ + +} + + + diff --git a/IRaCIS.Core.Application/Service/Common/InternationalizationService.cs b/IRaCIS.Core.Application/Service/Common/InternationalizationService.cs index f3f03ec80..5adee87e1 100644 --- a/IRaCIS.Core.Application/Service/Common/InternationalizationService.cs +++ b/IRaCIS.Core.Application/Service/Common/InternationalizationService.cs @@ -175,7 +175,7 @@ namespace IRaCIS.Core.Application.Service if (addOrEditInternationalization.InternationalizationType == 1) { - await InternationalizationHelper.AddOrUpdateJsonKeyValueAsync(entity.Code, addOrEditInternationalization.Value, addOrEditInternationalization.ValueCN, addOrEditInternationalization.Description); + await InternationalizationHelper.AddOrUpdateJsonKeyValueAsync(_mapper.Map(addOrEditInternationalization)); } else { diff --git a/IRaCIS.Core.Application/Service/Common/_MapConfig.cs b/IRaCIS.Core.Application/Service/Common/_MapConfig.cs index d37f359fd..607f64bfc 100644 --- a/IRaCIS.Core.Application/Service/Common/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/Common/_MapConfig.cs @@ -1,6 +1,7 @@ using AutoMapper; using IRaCIS.Application.Contracts; using IRaCIS.Core.Application.Contracts; +using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.ViewModel; namespace IRaCIS.Core.Application.Service @@ -70,7 +71,10 @@ namespace IRaCIS.Core.Application.Service CreateMap().ReverseMap(); + CreateMap(); + CreateMap(); + CreateMap(); diff --git a/IRaCIS.Core.Application/Service/Document/EmailSendService.cs b/IRaCIS.Core.Application/Service/Document/EmailSendService.cs index d64befeff..16aa1eb8d 100644 --- a/IRaCIS.Core.Application/Service/Document/EmailSendService.cs +++ b/IRaCIS.Core.Application/Service/Document/EmailSendService.cs @@ -203,7 +203,7 @@ namespace IRaCIS.Core.Application.Service return (topicStr, htmlBodyStr, false, userId); }; - await SendTrialEmailAsync(trialId, EmailBusinessScenario.QCQuestion, topicAndHtmlFunc); + await SendTrialEmailAsync(trialId, EmailBusinessScenario.CRCToQCQuestion, topicAndHtmlFunc); } } } @@ -253,7 +253,7 @@ namespace IRaCIS.Core.Application.Service return (topicStr, htmlBodyStr, isEn_us, userId); }; - await SendTrialEmailAsync(trialId, EmailBusinessScenario.ImageQuestion, topicAndHtmlFunc); + await SendTrialEmailAsync(trialId, EmailBusinessScenario.QCToCRCImageQuestion, topicAndHtmlFunc); } } } diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs index 2c927292b..7b231a7d1 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs @@ -397,7 +397,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc if (_fusionCache.GetOrDefault(CacheKeys.TrialTaskStudyUidDBLock(incommand.TrialId, incommand.VisitTaskId, incommand.Study.StudyInstanceUid)) != Guid.Empty) { //---当前已有人正在上传和归档该检查! - return ResponseOutput.NotOk(StaticData.International("UploadDownLoad_ArchiveInProgress")); + return ResponseOutput.NotOk(I18n.T("UploadDownLoad_ArchiveInProgress")); } else { diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs index ce3ab2dbb..3fc485f84 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs @@ -102,7 +102,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc if (cacheValue != Guid.Empty && cacheValue != _userInfo.Id) { //---当前已有人正在上传和归档该检查! - return ResponseOutput.NotOk(StaticData.International("UploadDownLoad_ArchiveInProgress")); + return ResponseOutput.NotOk(I18n.T("UploadDownLoad_ArchiveInProgress")); } else { @@ -134,7 +134,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc if (_fusionCache.GetOrDefault(CacheKeys.TrialStudyUidDBLock(incommand.TrialId, incommand.Study.StudyInstanceUid)) != Guid.Empty) { //---当前已有人正在上传和归档该检查! - return ResponseOutput.NotOk(StaticData.International("UploadDownLoad_ArchiveInProgress")); + return ResponseOutput.NotOk(I18n.T("UploadDownLoad_ArchiveInProgress")); } else { diff --git a/IRaCIS.Core.Application/TestService.cs b/IRaCIS.Core.Application/TestService.cs index 0ed9d9fb7..f3955893b 100644 --- a/IRaCIS.Core.Application/TestService.cs +++ b/IRaCIS.Core.Application/TestService.cs @@ -28,7 +28,7 @@ using NPOI.XWPF.UserModel; using System.Globalization; using System.Runtime.InteropServices; using System.Text; -using Tea; + namespace IRaCIS.Core.Application.Service @@ -56,10 +56,25 @@ namespace IRaCIS.Core.Application.Service return Task.FromResult(list); } + [AllowAnonymous] public IResponseOutput GetTest() { + + //throw new BusinessValidationFailedException("手动抛出的异常"); + return ResponseOutput.Ok(_userInfo.IP); } + + public IResponseOutput GetTestI18n() + { + var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US; + + //CultureInfo.CurrentCulture = new CultureInfo(StaticData.CultureInfo.en_US); + //CultureInfo.CurrentUICulture = new CultureInfo(StaticData.CultureInfo.en_US); + + return ResponseOutput.Ok(I18n.T("TaskAllocation_DoctorConfigExists")); + } + } @@ -167,6 +182,8 @@ namespace IRaCIS.Core.Application.Service public async Task TestJson() { + throw new BusinessValidationFailedException("传统控制器异常"); + var model1 = new TestModel() { TestId = NewId.NextSequentialGuid(), TestName = null }; var model2 = new TestModel2() { TestId = NewId.NextSequentialGuid(), TestName = "test2" }; diff --git a/IRaCIS.Core.Domain.Share/Common/EmailScenarioEnum.cs b/IRaCIS.Core.Domain.Share/Common/EmailScenarioEnum.cs index 64594296b..1caeec8d2 100644 --- a/IRaCIS.Core.Domain.Share/Common/EmailScenarioEnum.cs +++ b/IRaCIS.Core.Domain.Share/Common/EmailScenarioEnum.cs @@ -46,11 +46,13 @@ namespace IRaCIS.Core.Domain.Share //Reviewer=4, + //QC影像质控任务 QCTask = 5, - QCQuestion = 6, - ImageQuestion = 7, + CRCToQCQuestion = 6, + + QCToCRCImageQuestion = 7, diff --git a/IRaCIS.Core.Domain/GlobalUsings.cs b/IRaCIS.Core.Domain/GlobalUsings.cs index c7a91c2b9..8970cf57c 100644 --- a/IRaCIS.Core.Domain/GlobalUsings.cs +++ b/IRaCIS.Core.Domain/GlobalUsings.cs @@ -4,3 +4,4 @@ global using System; global using System.Collections.Generic; global using System.ComponentModel.DataAnnotations; global using System.ComponentModel.DataAnnotations.Schema; +global using IRaCIS.Core.Infrastructure.Extention; diff --git a/IRaCIS.Core.Domain/Reading/ReadingCriterion/ReadingQuestionCriterionTrial.cs b/IRaCIS.Core.Domain/Reading/ReadingCriterion/ReadingQuestionCriterionTrial.cs index 51e0a0d57..3a2d77ac4 100644 --- a/IRaCIS.Core.Domain/Reading/ReadingCriterion/ReadingQuestionCriterionTrial.cs +++ b/IRaCIS.Core.Domain/Reading/ReadingCriterion/ReadingQuestionCriterionTrial.cs @@ -62,7 +62,7 @@ public class ReadingQuestionCriterionTrial : BaseAddAuditEntity [Comment("全局阅片评估更新类型")] public string GlobalUpdateType { get; set; } = string.Empty; [Comment("评估原因")] - public string EvaluationReason { get; set; } = StaticData.International("CriterionTrial_EvaluationReason"); + public string EvaluationReason { get; set; } = I18n.T("CriterionTrial_EvaluationReason"); [Comment("是否显示详情")] public bool IsShowDetail { get; set; } = true; diff --git a/IRaCIS.Core.Domain/Trial/Trial.cs b/IRaCIS.Core.Domain/Trial/Trial.cs index d112c6cf7..cba96ac82 100644 --- a/IRaCIS.Core.Domain/Trial/Trial.cs +++ b/IRaCIS.Core.Domain/Trial/Trial.cs @@ -132,7 +132,7 @@ public partial class Trial : BaseFullDeleteAuditEntity public bool VisitPlanConfirmed { get; set; } [Comment("受试者编号具体规则")] - public string SubjectCodeRule { get; set; } = StaticData.International("Trial_number"); + public string SubjectCodeRule { get; set; } = I18n.T("Trial_number"); [Comment("是否 提醒受试者编号规则")] public bool IsNoticeSubjectCodeRule { get; set; } = true; diff --git a/IRaCIS.Core.Infra.EFCore/Repository/IRepository.cs b/IRaCIS.Core.Infra.EFCore/Repository/IRepository.cs index bd33d1a93..ddecbf4d5 100644 --- a/IRaCIS.Core.Infra.EFCore/Repository/IRepository.cs +++ b/IRaCIS.Core.Infra.EFCore/Repository/IRepository.cs @@ -71,23 +71,9 @@ namespace IRaCIS.Core.Infra.EFCore bool autoSave = false, bool ignoreQueryFilter = false) where T : Entity; } - public class Repository : IRepository + public class Repository(IRaCISDBContext _dbContext, IMapper _mapper, IUserInfo _userInfo) : IRepository { - #region 构造 基本 - private IRaCISDBContext _dbContext { get; } - public IMapper _mapper { get; set; } - - public IUserInfo _userInfo { get; set; } - - public IStringLocalizer _localizer { get; set; } - - public Repository(IRaCISDBContext dbContext, IMapper mapper, IUserInfo userInfo, IStringLocalizer localizer) - { - _localizer = localizer; - _dbContext = dbContext; - _mapper = mapper; - _userInfo = userInfo; - } + /// /// 设置是使用哪个仓储 默认不跟踪 @@ -171,7 +157,7 @@ namespace IRaCIS.Core.Infra.EFCore if (dbEntity == null) { - throw new BusinessValidationFailedException(_localizer["Repository_UpdateError"]); + throw new BusinessValidationFailedException(I18n.T("Repository_UpdateError")); } var dbBeforEntity = dbEntity.Clone(); @@ -450,7 +436,6 @@ namespace IRaCIS.Core.Infra.EFCore } - #endregion diff --git a/IRaCIS.Core.Infra.EFCore/Repository/Repository.cs b/IRaCIS.Core.Infra.EFCore/Repository/Repository.cs index d27e4021f..98b87f116 100644 --- a/IRaCIS.Core.Infra.EFCore/Repository/Repository.cs +++ b/IRaCIS.Core.Infra.EFCore/Repository/Repository.cs @@ -100,7 +100,7 @@ namespace IRaCIS.Core.Infra.EFCore if (dbEntity == null) { - throw new BusinessValidationFailedException(_localizer["Repository_UpdateError"]); + throw new BusinessValidationFailedException(I18n.T("Repository_UpdateError")); } var dbBeforEntity = dbEntity.Clone(); @@ -156,7 +156,7 @@ namespace IRaCIS.Core.Infra.EFCore if (searchEntity == null) { - throw new BusinessValidationFailedException(_localizer["Repository_UpdateError"]); + throw new BusinessValidationFailedException(I18n.T("Repository_UpdateError")); } _dbContext.EntityModifyPartialFiled(searchEntity, updateFactory); @@ -208,7 +208,7 @@ namespace IRaCIS.Core.Infra.EFCore if (waitDelete == null) { - throw new BusinessValidationFailedException(_localizer["Repository_DeleteError"]); + throw new BusinessValidationFailedException(I18n.T("Repository_DeleteError")); } await DeleteAsync(waitDelete, autoSave); diff --git a/IRaCIS.Core.Infrastructure/_IRaCIS/Globalization/I18n.cs b/IRaCIS.Core.Infrastructure/_IRaCIS/Globalization/I18n.cs new file mode 100644 index 000000000..58e54d4d4 --- /dev/null +++ b/IRaCIS.Core.Infrastructure/_IRaCIS/Globalization/I18n.cs @@ -0,0 +1,31 @@ +using Microsoft.Extensions.Localization; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + + namespace IRaCIS.Core.Infrastructure.Extention; + +public static class I18n +{ + private static IStringLocalizer _localizer; + + public static void SetLocalizer(IStringLocalizer localizer) + { + _localizer = localizer; + } + + + + public static string T(string key) + { + return _localizer[key]; + } + + public static string T(string key, params object[] arguments) + { + return _localizer[key, arguments]; + } + +} diff --git a/IRaCIS.Core.Infrastructure/_IRaCIS/Output/ResponseOutput.cs b/IRaCIS.Core.Infrastructure/_IRaCIS/Output/ResponseOutput.cs index 9023c87e5..d4ceae5be 100644 --- a/IRaCIS.Core.Infrastructure/_IRaCIS/Output/ResponseOutput.cs +++ b/IRaCIS.Core.Infrastructure/_IRaCIS/Output/ResponseOutput.cs @@ -117,9 +117,9 @@ namespace IRaCIS.Core.Infrastructure.Extention var info = string.Empty; - if (!string.IsNullOrWhiteSpace(key) && StaticData.Log_Locoalize_Dic.ContainsKey(key)) + if (!string.IsNullOrWhiteSpace(key) && StaticData.Localizer_Dev_Dic.ContainsKey(key)) { - info = $"[{key}]:{StaticData.Log_Locoalize_Dic[key]}"; + info = $"[{key}]:{StaticData.Localizer_Dev_Dic[key]}"; } return new ResponseOutput().NotOk(msg, code: code, localizedInfo: info); diff --git a/IRaCIS.Core.Infrastructure/_IRaCIS/_Config/_StaticData.cs b/IRaCIS.Core.Infrastructure/_IRaCIS/_Config/_StaticData.cs index d10de14af..e437bdf91 100644 --- a/IRaCIS.Core.Infrastructure/_IRaCIS/_Config/_StaticData.cs +++ b/IRaCIS.Core.Infrastructure/_IRaCIS/_Config/_StaticData.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Threading; @@ -7,12 +8,7 @@ namespace IRaCIS.Core.Domain.Share; public static class StaticData { - - public static Dictionary En_US_Dic = new Dictionary(); - - public static Dictionary Zh_CN_Dic = new Dictionary(); - - public static Dictionary Log_Locoalize_Dic = new Dictionary(); + public static Dictionary Localizer_Dev_Dic = new Dictionary(); #region 国际化 @@ -28,48 +24,34 @@ public static class StaticData public static readonly string en_US_bookMark = "en_us"; } - /// - /// 获取国际化 - /// - /// - /// - public static string International(string key, params object?[] args) - { - try - { - return string.Format(GetLanguageDictionary(key), args); - } - catch (Exception) - { + #region 国际化废弃 - return string.Empty; - } - } + //public static Dictionary En_US_Dic = new Dictionary(); + + //public static Dictionary Zh_CN_Dic = new Dictionary(); + ///// + ///// 获取国际化 + ///// + ///// + ///// + //public static string I18n(string key, params object?[] args) + //{ + // var isEn_US = System.Globalization.CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US; + + // if (isEn_US) + // { + // return En_US_Dic[key]; + // } + // else + // { + // return Zh_CN_Dic[key]; + // } + //} - public static string GetLanguageDictionary(string key) - { - try - { - var type = Thread.CurrentThread.CurrentUICulture.Name; - if (type == "zh-CN") - { - return Zh_CN_Dic[key]; + #endregion - } - else - { - return En_US_Dic[key]; - } - } - catch (Exception) - { - - return string.Empty; - } - - } #endregion