整理命名空间
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
fc30cb39ee
commit
103d4b42a3
|
@ -29,7 +29,7 @@
|
|||
<param name="doctorId"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Api.Controllers.ExtraController.Login(IRaCIS.Application.Contracts.UserLoginDTO,ZiggyCreatures.Caching.Fusion.IFusionCache,IRaCIS.Application.Services.IUserService,IRaCIS.Core.Application.Auth.ITokenService,IRaCIS.Core.Application.Contracts.IReadingImageTaskService,Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.ServiceVerifyConfigOption},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig},IRaCIS.Application.Services.IMailVerificationService)">
|
||||
<member name="M:IRaCIS.Api.Controllers.ExtraController.Login(IRaCIS.Application.Contracts.UserLoginDTO,ZiggyCreatures.Caching.Fusion.IFusionCache,IRaCIS.Core.Application.Service.IUserService,IRaCIS.Core.Application.Auth.ITokenService,IRaCIS.Core.Application.Contracts.IReadingImageTaskService,Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.ServiceVerifyConfigOption},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig},IRaCIS.Core.Application.Service.IMailVerificationService)">
|
||||
<summary> 系统用户登录接口[New] </summary>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.AddOrUpdateTrialInspection(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Application.Contracts.TrialCommand})">
|
||||
|
@ -41,7 +41,7 @@
|
|||
<param name="param"></param>
|
||||
<returns>新记录Id</returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.WorkLoadAddOrUpdate(IRaCIS.Application.Services.IDoctorWorkloadService,IRaCIS.Application.Contracts.WorkloadCommand)">
|
||||
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.WorkLoadAddOrUpdate(IRaCIS.Core.Application.Service.IDoctorWorkloadService,IRaCIS.Application.Contracts.WorkloadCommand)">
|
||||
<summary>
|
||||
添加或更新工作量[AUTH]
|
||||
</summary>
|
||||
|
|
|
@ -10,7 +10,7 @@ using Panda.DynamicWebApi.Attributes;
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using ZiggyCreatures.Caching.Fusion;
|
||||
|
||||
namespace IRaCIS.Core.Application
|
||||
namespace IRaCIS.Core.Application.Service
|
||||
{
|
||||
|
||||
#pragma warning disable CS8618
|
||||
|
|
|
@ -3,42 +3,41 @@ using Microsoft.AspNetCore.Http;
|
|||
using Microsoft.Extensions.Logging;
|
||||
|
||||
|
||||
namespace IRaCIS.Core.Application.BusinessFilter
|
||||
namespace IRaCIS.Core.Application.BusinessFilter;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 不生效,不知道为啥
|
||||
/// </summary>
|
||||
public class GlobalExceptionHandler : IExceptionHandler
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 不生效,不知道为啥
|
||||
/// </summary>
|
||||
public class GlobalExceptionHandler : IExceptionHandler
|
||||
private readonly ILogger<GlobalExceptionHandler> _logger;
|
||||
public GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger)
|
||||
{
|
||||
this._logger = logger;
|
||||
}
|
||||
public ValueTask<bool> TryHandleAsync(
|
||||
HttpContext httpContext,
|
||||
Exception exception,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
private readonly ILogger<GlobalExceptionHandler> _logger;
|
||||
public GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger)
|
||||
{
|
||||
this._logger = logger;
|
||||
}
|
||||
public ValueTask<bool> TryHandleAsync(
|
||||
HttpContext httpContext,
|
||||
Exception exception,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
|
||||
httpContext.Response.ContentType = "application/json";
|
||||
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}]" : "");
|
||||
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}"));
|
||||
httpContext.Response.WriteAsJsonAsync(ResponseOutput.NotOk($"{ex?.Message}"));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
_logger.LogError(errorInfo);
|
||||
_logger.LogError(errorInfo);
|
||||
|
||||
// return true to signal that this exception is handled
|
||||
return ValueTask.FromResult(false);
|
||||
}
|
||||
// return true to signal that this exception is handled
|
||||
return ValueTask.FromResult(false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,33 +4,31 @@ using Microsoft.Extensions.Localization;
|
|||
using Newtonsoft.Json;
|
||||
|
||||
|
||||
namespace IRaCIS.Core.Application.Filter
|
||||
namespace IRaCIS.Core.Application.Filter;
|
||||
|
||||
|
||||
|
||||
public class ModelActionFilter : ActionFilterAttribute, IActionFilter
|
||||
{
|
||||
|
||||
|
||||
public class ModelActionFilter : ActionFilterAttribute, IActionFilter
|
||||
public IStringLocalizer _localizer;
|
||||
public ModelActionFilter(IStringLocalizer localizer)
|
||||
{
|
||||
public IStringLocalizer _localizer;
|
||||
public ModelActionFilter(IStringLocalizer localizer)
|
||||
{
|
||||
_localizer = localizer;
|
||||
}
|
||||
|
||||
public override void OnActionExecuting(ActionExecutingContext context)
|
||||
{
|
||||
if (!context.ModelState.IsValid)
|
||||
{
|
||||
|
||||
var validationErrors = context.ModelState
|
||||
.Keys
|
||||
.SelectMany(k => context.ModelState[k]!.Errors)
|
||||
.Select(e => e.ErrorMessage)
|
||||
.ToArray();
|
||||
|
||||
//---提供给接口的参数无效。
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ModelAction_InvalidAPIParameter"] + JsonConvert.SerializeObject(validationErrors)));
|
||||
}
|
||||
}
|
||||
_localizer = localizer;
|
||||
}
|
||||
|
||||
public override void OnActionExecuting(ActionExecutingContext context)
|
||||
{
|
||||
if (!context.ModelState.IsValid)
|
||||
{
|
||||
|
||||
var validationErrors = context.ModelState
|
||||
.Keys
|
||||
.SelectMany(k => context.ModelState[k]!.Errors)
|
||||
.Select(e => e.ErrorMessage)
|
||||
.ToArray();
|
||||
|
||||
//---提供给接口的参数无效。
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ModelAction_InvalidAPIParameter"] + JsonConvert.SerializeObject(validationErrors)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,26 +2,25 @@ using Microsoft.AspNetCore.Http;
|
|||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
|
||||
namespace IRaCIS.Core.Application.Filter
|
||||
namespace IRaCIS.Core.Application.Filter;
|
||||
|
||||
#region snippet_DisableFormValueModelBindingAttribute
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
||||
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
|
||||
{
|
||||
#region snippet_DisableFormValueModelBindingAttribute
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
||||
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
|
||||
public void OnResourceExecuting(ResourceExecutingContext context)
|
||||
{
|
||||
public void OnResourceExecuting(ResourceExecutingContext context)
|
||||
{
|
||||
|
||||
|
||||
var factories = context.ValueProviderFactories;
|
||||
//factories.RemoveType<FormValueProviderFactory>();
|
||||
factories.RemoveType<FormFileValueProviderFactory>();
|
||||
factories.RemoveType<JQueryFormValueProviderFactory>();
|
||||
context.HttpContext.Request.EnableBuffering();
|
||||
}
|
||||
|
||||
public void OnResourceExecuted(ResourceExecutedContext context)
|
||||
{
|
||||
}
|
||||
var factories = context.ValueProviderFactories;
|
||||
//factories.RemoveType<FormValueProviderFactory>();
|
||||
factories.RemoveType<FormFileValueProviderFactory>();
|
||||
factories.RemoveType<JQueryFormValueProviderFactory>();
|
||||
context.HttpContext.Request.EnableBuffering();
|
||||
}
|
||||
|
||||
public void OnResourceExecuted(ResourceExecutedContext context)
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
|
|
|
@ -5,72 +5,71 @@ using Microsoft.AspNetCore.Mvc.Filters;
|
|||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace IRaCIS.Core.Application.Filter
|
||||
namespace IRaCIS.Core.Application.Filter;
|
||||
|
||||
public class ProjectExceptionFilter : Attribute, IExceptionFilter
|
||||
{
|
||||
public class ProjectExceptionFilter : Attribute, IExceptionFilter
|
||||
private readonly ILogger<ProjectExceptionFilter> _logger;
|
||||
|
||||
public IStringLocalizer _localizer;
|
||||
|
||||
public ProjectExceptionFilter(IStringLocalizer localizer, ILogger<ProjectExceptionFilter> logger)
|
||||
{
|
||||
private readonly ILogger<ProjectExceptionFilter> _logger;
|
||||
_logger = logger;
|
||||
_localizer = localizer;
|
||||
}
|
||||
public void OnException(ExceptionContext context)
|
||||
{
|
||||
//context.ExceptionHandled;//记录当前这个异常是否已经被处理过了
|
||||
|
||||
public IStringLocalizer _localizer;
|
||||
|
||||
public ProjectExceptionFilter(IStringLocalizer localizer, ILogger<ProjectExceptionFilter> logger)
|
||||
if (!context.ExceptionHandled)
|
||||
{
|
||||
_logger = logger;
|
||||
_localizer = localizer;
|
||||
}
|
||||
public void OnException(ExceptionContext context)
|
||||
{
|
||||
//context.ExceptionHandled;//记录当前这个异常是否已经被处理过了
|
||||
|
||||
if (!context.ExceptionHandled)
|
||||
if (context.Exception.GetType().Name == "DbUpdateConcurrencyException")
|
||||
{
|
||||
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))
|
||||
{
|
||||
//---并发更新,当前不允许该操作
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ProjectException_ConcurrentUpdateNotAllowed"] + context.Exception.Message));
|
||||
info = $"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}";
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
|
||||
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");
|
||||
|
||||
//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
|
||||
{
|
||||
//继续
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,80 +8,124 @@ using System.Text.RegularExpressions;
|
|||
using ZiggyCreatures.Caching.Fusion;
|
||||
using static IRaCIS.Core.Domain.Share.StaticData;
|
||||
|
||||
namespace IRaCIS.Core.Application.Filter
|
||||
namespace IRaCIS.Core.Application.Filter;
|
||||
|
||||
/// <summary>
|
||||
/// 主要为了 处理项目结束 锁库,不允许操作
|
||||
/// </summary>
|
||||
public class TrialResourceFilter : Attribute, IAsyncResourceFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// 主要为了 处理项目结束 锁库,不允许操作
|
||||
/// </summary>
|
||||
public class TrialResourceFilter : Attribute, IAsyncResourceFilter
|
||||
private readonly IUserInfo _userInfo;
|
||||
private readonly IFusionCache _fusionCache;
|
||||
public IStringLocalizer _localizer;
|
||||
private readonly IRepository<Trial> _trialRepository;
|
||||
private readonly List<string> _trialOptList = new List<string>();
|
||||
|
||||
|
||||
public TrialResourceFilter(IFusionCache fusionCache, IRepository<Trial> trialRepository, IStringLocalizer localizer, IUserInfo userInfo, string trialOpt = null, string trialOpt2 = null, string trialOpt3 = null)
|
||||
{
|
||||
private readonly IUserInfo _userInfo;
|
||||
private readonly IFusionCache _fusionCache;
|
||||
public IStringLocalizer _localizer;
|
||||
private readonly IRepository<Trial> _trialRepository;
|
||||
private readonly List<string> _trialOptList = new List<string>();
|
||||
_fusionCache = fusionCache;
|
||||
_userInfo = userInfo;
|
||||
_localizer = localizer;
|
||||
_trialRepository = trialRepository;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(trialOpt)) _trialOptList.Add(trialOpt.Trim());
|
||||
if (!string.IsNullOrWhiteSpace(trialOpt2)) _trialOptList.Add(trialOpt2.Trim());
|
||||
if (!string.IsNullOrWhiteSpace(trialOpt3)) _trialOptList.Add(trialOpt3.Trim());
|
||||
|
||||
public TrialResourceFilter(IFusionCache fusionCache, IRepository<Trial> trialRepository, IStringLocalizer localizer, IUserInfo userInfo, string trialOpt = null, string trialOpt2 = null, string trialOpt3 = null)
|
||||
}
|
||||
|
||||
//优先选择异步的方法
|
||||
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
|
||||
{
|
||||
// var typeFilter = context.ActionDescriptor.EndpointMetadata.Where(t => t.GetType() == typeof(TypeFilterAttribute)).Select(t => (TypeFilterAttribute)t).ToList().FirstOrDefault();
|
||||
//var _trialOptList= typeFilter.Arguments.Select(t => t.ToString()).ToList();
|
||||
|
||||
#region 处理新的用户类型,不能操作项目相关接口
|
||||
|
||||
// 后期列举出具体的类型,其他任何用户类型,都不允许操作
|
||||
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower() != "TrialDocument/userConfirm".ToLower())
|
||||
{
|
||||
_fusionCache = fusionCache;
|
||||
_userInfo = userInfo;
|
||||
_localizer = localizer;
|
||||
_trialRepository = trialRepository;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(trialOpt)) _trialOptList.Add(trialOpt.Trim());
|
||||
if (!string.IsNullOrWhiteSpace(trialOpt2)) _trialOptList.Add(trialOpt2.Trim());
|
||||
if (!string.IsNullOrWhiteSpace(trialOpt3)) _trialOptList.Add(trialOpt3.Trim());
|
||||
//---对不起,您的账户没有操作权限。
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"]));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//优先选择异步的方法
|
||||
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
//TrialId 传递的途径多种,可能在path 可能在body 可能在数组中,也可能在对象中,可能就在url
|
||||
var trialIdStr = string.Empty;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(context.HttpContext.Request.Query["trialId"]))
|
||||
{
|
||||
// var typeFilter = context.ActionDescriptor.EndpointMetadata.Where(t => t.GetType() == typeof(TypeFilterAttribute)).Select(t => (TypeFilterAttribute)t).ToList().FirstOrDefault();
|
||||
//var _trialOptList= typeFilter.Arguments.Select(t => t.ToString()).ToList();
|
||||
trialIdStr = context.HttpContext.Request.Query["trialId"];
|
||||
}
|
||||
|
||||
#region 处理新的用户类型,不能操作项目相关接口
|
||||
//先尝试从path中取TrialId
|
||||
else if (context.RouteData.Values.Keys.Any(t => t.Contains("trialId")))
|
||||
{
|
||||
var index = context.RouteData.Values.Keys.ToList().IndexOf("trialId");
|
||||
trialIdStr = context.RouteData.Values.Values.ToList()[index] as string;
|
||||
}
|
||||
else if (context.HttpContext.Request.Headers["Referer"].ToString().Contains("trialId"))
|
||||
{
|
||||
var headerStr = context.HttpContext.Request.Headers["Referer"].ToString();
|
||||
|
||||
// 后期列举出具体的类型,其他任何用户类型,都不允许操作
|
||||
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower() != "TrialDocument/userConfirm".ToLower())
|
||||
var trialIdIndex = headerStr.IndexOf("trialId");
|
||||
|
||||
|
||||
var matchResult = Regex.Match(headerStr.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
|
||||
|
||||
if (matchResult.Success)
|
||||
{
|
||||
//---对不起,您的账户没有操作权限。
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"]));
|
||||
|
||||
return;
|
||||
trialIdStr = matchResult.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
else
|
||||
{
|
||||
#region body 中取数据
|
||||
|
||||
//设置可以多次读
|
||||
context.HttpContext.Request.EnableBuffering();
|
||||
var reader = new StreamReader(context.HttpContext.Request.Body);
|
||||
var contentFromBody = await reader.ReadToEndAsync();
|
||||
//读取后,流的位置还原
|
||||
context.HttpContext.Request.Body.Seek(0, SeekOrigin.Begin);
|
||||
//context.HttpContext.Request.Body.Position = 0;
|
||||
|
||||
//找到参数位置在字符串中的索引
|
||||
var trialIdIndex = contentFromBody.IndexOf("\"TrialId\"", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
//TrialId 传递的途径多种,可能在path 可能在body 可能在数组中,也可能在对象中,可能就在url
|
||||
var trialIdStr = string.Empty;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(context.HttpContext.Request.Query["trialId"]))
|
||||
if (trialIdIndex > -1)
|
||||
{
|
||||
trialIdStr = context.HttpContext.Request.Query["trialId"];
|
||||
}
|
||||
// (?<="trialId" *: *").*?(?=",)
|
||||
|
||||
//先尝试从path中取TrialId
|
||||
else if (context.RouteData.Values.Keys.Any(t => t.Contains("trialId")))
|
||||
{
|
||||
var index = context.RouteData.Values.Keys.ToList().IndexOf("trialId");
|
||||
trialIdStr = context.RouteData.Values.Values.ToList()[index] as string;
|
||||
}
|
||||
else if (context.HttpContext.Request.Headers["Referer"].ToString().Contains("trialId"))
|
||||
{
|
||||
var headerStr = context.HttpContext.Request.Headers["Referer"].ToString();
|
||||
//使用正则 [0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}
|
||||
|
||||
var trialIdIndex = headerStr.IndexOf("trialId");
|
||||
|
||||
|
||||
var matchResult = Regex.Match(headerStr.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
|
||||
var matchResult = Regex.Match(contentFromBody.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
|
||||
|
||||
if (matchResult.Success)
|
||||
{
|
||||
//有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下
|
||||
|
||||
trialIdStr = matchResult.Value;
|
||||
|
||||
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(trialStatusStr))
|
||||
{
|
||||
//数据库 检查该项目Id不对
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -89,93 +133,48 @@ namespace IRaCIS.Core.Application.Filter
|
|||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
#region body 中取数据
|
||||
|
||||
//设置可以多次读
|
||||
context.HttpContext.Request.EnableBuffering();
|
||||
var reader = new StreamReader(context.HttpContext.Request.Body);
|
||||
var contentFromBody = await reader.ReadToEndAsync();
|
||||
//读取后,流的位置还原
|
||||
context.HttpContext.Request.Body.Seek(0, SeekOrigin.Begin);
|
||||
//context.HttpContext.Request.Body.Position = 0;
|
||||
|
||||
//找到参数位置在字符串中的索引
|
||||
var trialIdIndex = contentFromBody.IndexOf("\"TrialId\"", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
if (trialIdIndex > -1)
|
||||
{
|
||||
// (?<="trialId" *: *").*?(?=",)
|
||||
|
||||
//使用正则 [0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}
|
||||
|
||||
var matchResult = Regex.Match(contentFromBody.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
|
||||
|
||||
if (matchResult.Success)
|
||||
{
|
||||
//有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下
|
||||
|
||||
trialIdStr = matchResult.Value;
|
||||
|
||||
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(trialStatusStr))
|
||||
{
|
||||
//数据库 检查该项目Id不对
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||
}
|
||||
|
||||
//使用字符串取 如果是swagger 可能有时取的不对 因为空格的原因
|
||||
//trialIdStr = contentFromBody.Substring(trialIdIndex + "TrialId".Length + 4, 3
|
||||
}
|
||||
|
||||
#endregion
|
||||
//使用字符串取 如果是swagger 可能有时取的不对 因为空格的原因
|
||||
//trialIdStr = contentFromBody.Substring(trialIdIndex + "TrialId".Length + 4, 3
|
||||
}
|
||||
|
||||
//通过path 或者body 找到trialId 了
|
||||
if (!string.IsNullOrWhiteSpace(trialIdStr))
|
||||
#endregion
|
||||
}
|
||||
|
||||
//通过path 或者body 找到trialId 了
|
||||
if (!string.IsNullOrWhiteSpace(trialIdStr))
|
||||
{
|
||||
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
|
||||
|
||||
// 这里是统一拦截 项目有关的操作允许情况(特殊的地方,比如项目配置(有的在多种状态(初始化,ongoing)都可以操作,有的仅仅在Initializing)还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口)
|
||||
if (trialStatusStr == StaticData.TrialState.TrialOngoing || _trialOptList.Any(t => t == TrialOpt.BeforeOngoingCantOpt))
|
||||
{
|
||||
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
|
||||
|
||||
// 这里是统一拦截 项目有关的操作允许情况(特殊的地方,比如项目配置(有的在多种状态(初始化,ongoing)都可以操作,有的仅仅在Initializing)还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口)
|
||||
if (trialStatusStr == StaticData.TrialState.TrialOngoing || _trialOptList.Any(t => t == TrialOpt.BeforeOngoingCantOpt))
|
||||
{
|
||||
|
||||
await next.Invoke();
|
||||
|
||||
}
|
||||
// 项目停止、或者完成 不允许操作
|
||||
else
|
||||
{
|
||||
//---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_InterceptedProjectStatusRule"]));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
//添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截
|
||||
else if (_trialOptList.Any(t => t == TrialOpt.AddOrUpdateTrial || t == TrialOpt.SignSystemDocNoTrialId))
|
||||
{
|
||||
await next.Invoke();
|
||||
}
|
||||
|
||||
}
|
||||
// 项目停止、或者完成 不允许操作
|
||||
else
|
||||
{
|
||||
//如果项目相关接口没有传递trialId 会来到这里,提醒,以便修改
|
||||
//---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_InterceptedProjectStatusRule"]));
|
||||
|
||||
//---该接口参数中,没有传递项目编号,请核对。
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_MissingProjectNumber"]));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
//添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截
|
||||
else if (_trialOptList.Any(t => t == TrialOpt.AddOrUpdateTrial || t == TrialOpt.SignSystemDocNoTrialId))
|
||||
{
|
||||
await next.Invoke();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
//如果项目相关接口没有传递trialId 会来到这里,提醒,以便修改
|
||||
|
||||
//---该接口参数中,没有传递项目编号,请核对。
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_MissingProjectNumber"]));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,121 +3,120 @@ using Microsoft.AspNetCore.Mvc;
|
|||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace IRaCIS.Core.Application.Service.BusinessFilter
|
||||
namespace IRaCIS.Core.Application.Service.BusinessFilter;
|
||||
|
||||
/// <summary>
|
||||
/// 统一返回前端数据包装,之前在控制器包装,现在修改为动态Api 在ResultFilter这里包装,减少重复冗余代码
|
||||
/// by zhouhang 2021.09.12 周末
|
||||
/// </summary>
|
||||
public class UnifiedApiResultFilter : Attribute, IAsyncResultFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// 统一返回前端数据包装,之前在控制器包装,现在修改为动态Api 在ResultFilter这里包装,减少重复冗余代码
|
||||
/// by zhouhang 2021.09.12 周末
|
||||
/// </summary>
|
||||
public class UnifiedApiResultFilter : Attribute, IAsyncResultFilter
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public UnifiedApiResultFilter(ILogger<UnifiedApiResultFilter> logger)
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public UnifiedApiResultFilter(ILogger<UnifiedApiResultFilter> logger)
|
||||
/// <summary>
|
||||
/// 异步版本
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="next"></param>
|
||||
/// <returns></returns>
|
||||
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
|
||||
{
|
||||
|
||||
if (context.Result is ObjectResult objectResult)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
var statusCode = objectResult.StatusCode ?? context.HttpContext.Response.StatusCode;
|
||||
|
||||
/// <summary>
|
||||
/// 异步版本
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="next"></param>
|
||||
/// <returns></returns>
|
||||
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
|
||||
{
|
||||
|
||||
if (context.Result is ObjectResult objectResult)
|
||||
//是200 并且没有包装 那么包装结果
|
||||
if (statusCode == 200 && !(objectResult.Value is IResponseOutput))
|
||||
{
|
||||
var statusCode = objectResult.StatusCode ?? context.HttpContext.Response.StatusCode;
|
||||
|
||||
//是200 并且没有包装 那么包装结果
|
||||
if (statusCode == 200 && !(objectResult.Value is IResponseOutput))
|
||||
var type = objectResult.Value?.GetType();
|
||||
|
||||
|
||||
if (type != null && type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(ValueTuple<,>) || type.GetGenericTypeDefinition() == typeof(Tuple<,>)))
|
||||
{
|
||||
|
||||
var type = objectResult.Value?.GetType();
|
||||
|
||||
|
||||
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);
|
||||
|
||||
//OK
|
||||
var tuple = (dynamic)objectResult.Value;
|
||||
var apiResponse = ResponseOutput.Ok(tuple!.Item1, tuple!.Item2);
|
||||
|
||||
|
||||
objectResult.Value = apiResponse;
|
||||
objectResult.DeclaredType = apiResponse.GetType();
|
||||
}
|
||||
else
|
||||
{
|
||||
var apiResponse = ResponseOutput.Ok(objectResult.Value);
|
||||
|
||||
objectResult.Value = apiResponse;
|
||||
objectResult.DeclaredType = apiResponse.GetType();
|
||||
}
|
||||
//报错
|
||||
//var tuple = (object, object))objectResult.Value;
|
||||
//var (val1, val2) = ((dynamic, dynamic))objectResult.Value;
|
||||
//var apiResponse = ResponseOutput.Ok(val1, val2);
|
||||
|
||||
//OK
|
||||
var tuple = (dynamic)objectResult.Value;
|
||||
var apiResponse = ResponseOutput.Ok(tuple!.Item1, tuple!.Item2);
|
||||
|
||||
|
||||
objectResult.Value = apiResponse;
|
||||
objectResult.DeclaredType = apiResponse.GetType();
|
||||
}
|
||||
//如果是200 是IResponseOutput 记录下日志
|
||||
else if (statusCode == 200 && (objectResult.Value is IResponseOutput))
|
||||
else
|
||||
{
|
||||
var result = objectResult.Value as IResponseOutput;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(result.LocalizedInfo))
|
||||
{
|
||||
//统一在这里记录国际化的日志信息
|
||||
_logger.LogWarning($"{result.LocalizedInfo}");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else if (statusCode != 200 && !(objectResult.Value is IResponseOutput))
|
||||
{
|
||||
//---程序错误,请联系开发人员。
|
||||
var apiResponse = ResponseOutput.NotOk(StaticData.International("UnifiedAPI_ProgramError"));
|
||||
var apiResponse = ResponseOutput.Ok(objectResult.Value);
|
||||
|
||||
objectResult.Value = apiResponse;
|
||||
objectResult.DeclaredType = apiResponse.GetType();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
await next.Invoke();
|
||||
|
||||
}
|
||||
|
||||
public static bool IsTupleType(Type type, bool checkBaseTypes = false)
|
||||
{
|
||||
if (type == null)
|
||||
throw new ArgumentNullException(nameof(type));
|
||||
|
||||
if (type == typeof(Tuple))
|
||||
return true;
|
||||
|
||||
while (type != null)
|
||||
//如果是200 是IResponseOutput 记录下日志
|
||||
else if (statusCode == 200 && (objectResult.Value is IResponseOutput))
|
||||
{
|
||||
if (type.IsGenericType)
|
||||
var result = objectResult.Value as IResponseOutput;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(result.LocalizedInfo))
|
||||
{
|
||||
var genType = type.GetGenericTypeDefinition();
|
||||
if (genType == typeof(Tuple<>)
|
||||
|| genType == typeof(Tuple<,>)
|
||||
|| genType == typeof(Tuple<,>))
|
||||
return true;
|
||||
//统一在这里记录国际化的日志信息
|
||||
_logger.LogWarning($"{result.LocalizedInfo}");
|
||||
}
|
||||
|
||||
if (!checkBaseTypes)
|
||||
break;
|
||||
|
||||
type = type.BaseType;
|
||||
}
|
||||
|
||||
return false;
|
||||
else if (statusCode != 200 && !(objectResult.Value is IResponseOutput))
|
||||
{
|
||||
//---程序错误,请联系开发人员。
|
||||
var apiResponse = ResponseOutput.NotOk(StaticData.International("UnifiedAPI_ProgramError"));
|
||||
|
||||
objectResult.Value = apiResponse;
|
||||
objectResult.DeclaredType = apiResponse.GetType();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
await next.Invoke();
|
||||
|
||||
}
|
||||
|
||||
public static bool IsTupleType(Type type, bool checkBaseTypes = false)
|
||||
{
|
||||
if (type == null)
|
||||
throw new ArgumentNullException(nameof(type));
|
||||
|
||||
if (type == typeof(Tuple))
|
||||
return true;
|
||||
|
||||
while (type != null)
|
||||
{
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
var genType = type.GetGenericTypeDefinition();
|
||||
if (genType == typeof(Tuple<>)
|
||||
|| genType == typeof(Tuple<,>)
|
||||
|| genType == typeof(Tuple<,>))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!checkBaseTypes)
|
||||
break;
|
||||
|
||||
type = type.BaseType;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
global using AutoMapper.QueryableExtensions;
|
||||
global using IRaCIS.Core.Application;
|
||||
global using IRaCIS.Core.Application.Service;
|
||||
global using IRaCIS.Core.Domain.Models;
|
||||
global using IRaCIS.Core.Infra.EFCore;
|
||||
|
|
|
@ -1,70 +1,69 @@
|
|||
namespace IRaCIS.Core.Application.Helper
|
||||
namespace IRaCIS.Core.Application.Helper;
|
||||
|
||||
|
||||
public static class CacheKeys
|
||||
{
|
||||
//项目缓存
|
||||
public static string Trial(string trialIdStr) => $"TrialId:{trialIdStr}";
|
||||
|
||||
public static class CacheKeys
|
||||
//检查编号递增锁
|
||||
public static string TrialStudyMaxCode(Guid trialId) => $"TrialStudyMaxCode:{trialId}";
|
||||
|
||||
public static string TrialStudyUidUploading(Guid trialId, string studyUid) => $"TrialStudyUid:{trialId}_{studyUid}";
|
||||
//CRC上传影像提交锁key
|
||||
public static string TrialStudyUidDBLock(Guid trialId, string studyUid) => $"TrialStudyUidDBLock:{trialId}_{studyUid}";
|
||||
|
||||
public static string TrialTaskStudyUidUploading(Guid trialId, Guid visiTaskId, string studyUid) => $"TrialStudyUid:{trialId}_{visiTaskId}_{studyUid}";
|
||||
//影像后处理上传提交锁key
|
||||
public static string TrialTaskStudyUidDBLock(Guid trialId, Guid visiTaskId, string studyUid) => $"TrialTaskStudyUidDBLock:{trialId}_{visiTaskId}_{studyUid}";
|
||||
//系统匿名化
|
||||
public static string SystemAnonymization => $"SystemAnonymization";
|
||||
//前端国际化
|
||||
public static string FrontInternational => $"FrontInternationalList";
|
||||
|
||||
//登录挤账号
|
||||
public static string UserToken(Guid userId) => $"UserToken:{userId}";
|
||||
|
||||
//超时没请求接口自动退出
|
||||
public static string UserAutoLoginOut(Guid userId) => $"UserAutoLoginOut:{userId}";
|
||||
|
||||
/// <summary>
|
||||
/// 跳过阅片
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
public static string SkipReadingCacheKey(Guid userId) => $"{userId}SkipReadingCache";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 开始阅片时间
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
public static string StartReadingTimeKey(Guid userId) => $"{userId}StartReadingTime";
|
||||
|
||||
/// <summary>
|
||||
/// 开始休息时间
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
public static string StartRestTime(Guid userId) => $"{userId}StartRestTime";
|
||||
|
||||
}
|
||||
|
||||
public static class CacheHelper
|
||||
{
|
||||
public static async Task<string?> GetTrialStatusAsync(Guid trialId, IRepository<Trial> _trialRepository)
|
||||
{
|
||||
//项目缓存
|
||||
public static string Trial(string trialIdStr) => $"TrialId:{trialIdStr}";
|
||||
|
||||
//检查编号递增锁
|
||||
public static string TrialStudyMaxCode(Guid trialId) => $"TrialStudyMaxCode:{trialId}";
|
||||
|
||||
public static string TrialStudyUidUploading(Guid trialId, string studyUid) => $"TrialStudyUid:{trialId}_{studyUid}";
|
||||
//CRC上传影像提交锁key
|
||||
public static string TrialStudyUidDBLock(Guid trialId, string studyUid) => $"TrialStudyUidDBLock:{trialId}_{studyUid}";
|
||||
|
||||
public static string TrialTaskStudyUidUploading(Guid trialId, Guid visiTaskId, string studyUid) => $"TrialStudyUid:{trialId}_{visiTaskId}_{studyUid}";
|
||||
//影像后处理上传提交锁key
|
||||
public static string TrialTaskStudyUidDBLock(Guid trialId, Guid visiTaskId, string studyUid) => $"TrialTaskStudyUidDBLock:{trialId}_{visiTaskId}_{studyUid}";
|
||||
//系统匿名化
|
||||
public static string SystemAnonymization => $"SystemAnonymization";
|
||||
//前端国际化
|
||||
public static string FrontInternational => $"FrontInternationalList";
|
||||
|
||||
//登录挤账号
|
||||
public static string UserToken(Guid userId) => $"UserToken:{userId}";
|
||||
|
||||
//超时没请求接口自动退出
|
||||
public static string UserAutoLoginOut(Guid userId) => $"UserAutoLoginOut:{userId}";
|
||||
|
||||
/// <summary>
|
||||
/// 跳过阅片
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
public static string SkipReadingCacheKey(Guid userId) => $"{userId}SkipReadingCache";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 开始阅片时间
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
public static string StartReadingTimeKey(Guid userId) => $"{userId}StartReadingTime";
|
||||
|
||||
/// <summary>
|
||||
/// 开始休息时间
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
public static string StartRestTime(Guid userId) => $"{userId}StartRestTime";
|
||||
var statusStr = await _trialRepository.Where(t => t.Id == trialId, ignoreQueryFilters: true).Select(t => t.TrialStatusStr).FirstOrDefaultAsync();
|
||||
|
||||
return statusStr;
|
||||
}
|
||||
|
||||
public static class CacheHelper
|
||||
public static async Task<List<SystemAnonymization>> GetSystemAnonymizationListAsync(IRepository<SystemAnonymization> _systemAnonymizationRepository)
|
||||
{
|
||||
public static async Task<string?> GetTrialStatusAsync(Guid trialId, IRepository<Trial> _trialRepository)
|
||||
{
|
||||
var statusStr = await _trialRepository.Where(t => t.Id == trialId, ignoreQueryFilters: true).Select(t => t.TrialStatusStr).FirstOrDefaultAsync();
|
||||
var list = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
|
||||
|
||||
return statusStr;
|
||||
}
|
||||
|
||||
public static async Task<List<SystemAnonymization>> GetSystemAnonymizationListAsync(IRepository<SystemAnonymization> _systemAnonymizationRepository)
|
||||
{
|
||||
var list = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
|
||||
|
||||
return list;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,34 +1,33 @@
|
|||
using System.Diagnostics;
|
||||
|
||||
namespace IRaCIS.Core.Application.Helper
|
||||
namespace IRaCIS.Core.Application.Helper;
|
||||
|
||||
public class FileConvertHelper
|
||||
{
|
||||
public class FileConvertHelper
|
||||
|
||||
|
||||
static public void ConvertWordToPdf(string inputWordFilePath, string outputPdfDir)
|
||||
{
|
||||
// 设置 libreoffice 命令行参数
|
||||
string arguments = $"--headless --invisible --convert-to pdf \"{inputWordFilePath}\" --outdir \"{outputPdfDir}\"";
|
||||
|
||||
|
||||
static public void ConvertWordToPdf(string inputWordFilePath, string outputPdfDir)
|
||||
// 启动 libreoffice 进程
|
||||
using (Process process = new Process())
|
||||
{
|
||||
// 设置 libreoffice 命令行参数
|
||||
string arguments = $"--headless --invisible --convert-to pdf \"{inputWordFilePath}\" --outdir \"{outputPdfDir}\"";
|
||||
process.StartInfo.FileName = "libreoffice";
|
||||
process.StartInfo.Arguments = arguments;
|
||||
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
||||
process.StartInfo.RedirectStandardOutput = true;
|
||||
process.StartInfo.RedirectStandardError = true;
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
process.StartInfo.CreateNoWindow = true;
|
||||
|
||||
// 启动 libreoffice 进程
|
||||
using (Process process = new Process())
|
||||
{
|
||||
process.StartInfo.FileName = "libreoffice";
|
||||
process.StartInfo.Arguments = arguments;
|
||||
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
||||
process.StartInfo.RedirectStandardOutput = true;
|
||||
process.StartInfo.RedirectStandardError = true;
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
process.StartInfo.CreateNoWindow = true;
|
||||
process.Start();
|
||||
|
||||
process.Start();
|
||||
|
||||
// 等待进程结束
|
||||
process.WaitForExit();
|
||||
}
|
||||
// 等待进程结束
|
||||
process.WaitForExit();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,106 +1,105 @@
|
|||
using RestSharp;
|
||||
|
||||
namespace IRaCIS.Core.Application.Helper
|
||||
namespace IRaCIS.Core.Application.Helper;
|
||||
|
||||
|
||||
#region 对接模型
|
||||
public class HolidayCalendar
|
||||
{
|
||||
|
||||
#region 对接模型
|
||||
public class HolidayCalendar
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Version { get; set; }
|
||||
public string Generated { get; set; }
|
||||
public string Timezone { get; set; }
|
||||
public string Author { get; set; }
|
||||
public string URL { get; set; }
|
||||
public Dictionary<string, List<HolidayYear>> Years { get; set; }
|
||||
}
|
||||
|
||||
public class HolidayYear
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public DateTime StartDate { get; set; }
|
||||
public DateTime EndDate { get; set; }
|
||||
public int Duration { get; set; }
|
||||
public List<DateTime> CompDays { get; set; }
|
||||
public string URL { get; set; }
|
||||
public string Memo { get; set; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
public class HolidayHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// github 链接:https://github.com/lanceliao/china-holiday-calender?tab=readme-ov-file
|
||||
/// 接口请求参考文档:https://www.koudingke.cn/docs/zh-Hans/net-lib-docs/latest/RestSharp/Usage/Usage
|
||||
/// </summary>
|
||||
private static RestClient _client => new RestClient("https://www.shuyz.com/githubfiles/china-holiday-calender/master/holidayAPI.json");
|
||||
|
||||
private static HolidayCalendar _holidayCalendar { get; set; }
|
||||
|
||||
|
||||
private static List<DateTime> _holidays = new List<DateTime>();
|
||||
private static List<DateTime> _compensatedWorkdays = new List<DateTime>();
|
||||
|
||||
static HolidayHelper()
|
||||
{
|
||||
_holidayCalendar = _client.Get<HolidayCalendar>(new RestRequest()) ?? new HolidayCalendar();
|
||||
|
||||
foreach (var year in _holidayCalendar.Years.Values.SelectMany(x => x))
|
||||
{
|
||||
// 添加节假日到假日集合
|
||||
for (DateTime date = year.StartDate; date <= year.EndDate; date = date.AddDays(1))
|
||||
{
|
||||
_holidays.Add(date);
|
||||
}
|
||||
|
||||
// 添加补班日到补班日集合
|
||||
foreach (var compDay in year.CompDays)
|
||||
{
|
||||
_compensatedWorkdays.Add(compDay);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static TimeSpan GetChinaWorkTimeSpan(DateTime startDate, DateTime endDate)
|
||||
{
|
||||
if (startDate > endDate)
|
||||
{
|
||||
throw new ArgumentException("结束日期必须大于或等于开始日期");
|
||||
}
|
||||
|
||||
var diffTimeSpan = endDate - startDate;
|
||||
|
||||
// 初始化工作日数为0
|
||||
int workdays = 0;
|
||||
|
||||
// 找出在给定日期范围内的假期和补班日
|
||||
var filteredHolidays = _holidays.Where(d => d >= startDate && d <= endDate).ToList();
|
||||
var filteredCompensatedWorkdays = _compensatedWorkdays.Where(d => d >= startDate && d <= endDate).ToList();
|
||||
|
||||
// 遍历日期范围,计算工作日 注意 这里是小于
|
||||
for (DateTime date = startDate.Date; date < endDate.Date; date = date.AddDays(1))
|
||||
{
|
||||
// 判断是否为工作日
|
||||
bool isWeekend = date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday;
|
||||
bool isHoliday = filteredHolidays.Contains(date);
|
||||
bool isCompensatedWorkday = filteredCompensatedWorkdays.Contains(date);
|
||||
|
||||
// 如果是补班日,或是平日(非假期,非周末),则算作工作日
|
||||
if (isCompensatedWorkday || (!isWeekend && !isHoliday))
|
||||
{
|
||||
workdays++;
|
||||
}
|
||||
}
|
||||
|
||||
return new TimeSpan(workdays, diffTimeSpan.Hours, diffTimeSpan.Minutes, diffTimeSpan.Seconds);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
public string Name { get; set; }
|
||||
public string Version { get; set; }
|
||||
public string Generated { get; set; }
|
||||
public string Timezone { get; set; }
|
||||
public string Author { get; set; }
|
||||
public string URL { get; set; }
|
||||
public Dictionary<string, List<HolidayYear>> Years { get; set; }
|
||||
}
|
||||
|
||||
public class HolidayYear
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public DateTime StartDate { get; set; }
|
||||
public DateTime EndDate { get; set; }
|
||||
public int Duration { get; set; }
|
||||
public List<DateTime> CompDays { get; set; }
|
||||
public string URL { get; set; }
|
||||
public string Memo { get; set; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
public class HolidayHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// github 链接:https://github.com/lanceliao/china-holiday-calender?tab=readme-ov-file
|
||||
/// 接口请求参考文档:https://www.koudingke.cn/docs/zh-Hans/net-lib-docs/latest/RestSharp/Usage/Usage
|
||||
/// </summary>
|
||||
private static RestClient _client => new RestClient("https://www.shuyz.com/githubfiles/china-holiday-calender/master/holidayAPI.json");
|
||||
|
||||
private static HolidayCalendar _holidayCalendar { get; set; }
|
||||
|
||||
|
||||
private static List<DateTime> _holidays = new List<DateTime>();
|
||||
private static List<DateTime> _compensatedWorkdays = new List<DateTime>();
|
||||
|
||||
static HolidayHelper()
|
||||
{
|
||||
_holidayCalendar = _client.Get<HolidayCalendar>(new RestRequest()) ?? new HolidayCalendar();
|
||||
|
||||
foreach (var year in _holidayCalendar.Years.Values.SelectMany(x => x))
|
||||
{
|
||||
// 添加节假日到假日集合
|
||||
for (DateTime date = year.StartDate; date <= year.EndDate; date = date.AddDays(1))
|
||||
{
|
||||
_holidays.Add(date);
|
||||
}
|
||||
|
||||
// 添加补班日到补班日集合
|
||||
foreach (var compDay in year.CompDays)
|
||||
{
|
||||
_compensatedWorkdays.Add(compDay);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static TimeSpan GetChinaWorkTimeSpan(DateTime startDate, DateTime endDate)
|
||||
{
|
||||
if (startDate > endDate)
|
||||
{
|
||||
throw new ArgumentException("结束日期必须大于或等于开始日期");
|
||||
}
|
||||
|
||||
var diffTimeSpan = endDate - startDate;
|
||||
|
||||
// 初始化工作日数为0
|
||||
int workdays = 0;
|
||||
|
||||
// 找出在给定日期范围内的假期和补班日
|
||||
var filteredHolidays = _holidays.Where(d => d >= startDate && d <= endDate).ToList();
|
||||
var filteredCompensatedWorkdays = _compensatedWorkdays.Where(d => d >= startDate && d <= endDate).ToList();
|
||||
|
||||
// 遍历日期范围,计算工作日 注意 这里是小于
|
||||
for (DateTime date = startDate.Date; date < endDate.Date; date = date.AddDays(1))
|
||||
{
|
||||
// 判断是否为工作日
|
||||
bool isWeekend = date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday;
|
||||
bool isHoliday = filteredHolidays.Contains(date);
|
||||
bool isCompensatedWorkday = filteredCompensatedWorkdays.Contains(date);
|
||||
|
||||
// 如果是补班日,或是平日(非假期,非周末),则算作工作日
|
||||
if (isCompensatedWorkday || (!isWeekend && !isHoliday))
|
||||
{
|
||||
workdays++;
|
||||
}
|
||||
}
|
||||
|
||||
return new TimeSpan(workdays, diffTimeSpan.Hours, diffTimeSpan.Minutes, diffTimeSpan.Seconds);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,78 +1,77 @@
|
|||
namespace IRaCIS.Core.Application.Helper
|
||||
namespace IRaCIS.Core.Application.Helper;
|
||||
|
||||
public static class IRCEmailPasswordHelper
|
||||
{
|
||||
public static class IRCEmailPasswordHelper
|
||||
private static readonly Random Random = new Random();
|
||||
|
||||
//显示位数:3分之2的位数,向上取整
|
||||
//取哪几个个值:最后一位和前面几位
|
||||
//其他:3个***。
|
||||
//比如:hlj23@126.com
|
||||
//为:hlj***3@126.com
|
||||
|
||||
//he@126.com
|
||||
//为:h*** e@126.com
|
||||
|
||||
public static string MaskEmail(string email)
|
||||
{
|
||||
private static readonly Random Random = new Random();
|
||||
|
||||
//显示位数:3分之2的位数,向上取整
|
||||
//取哪几个个值:最后一位和前面几位
|
||||
//其他:3个***。
|
||||
//比如:hlj23@126.com
|
||||
//为:hlj***3@126.com
|
||||
// 找到 "@" 符号的位置
|
||||
int atIndex = email.IndexOf('@');
|
||||
|
||||
//he@126.com
|
||||
//为:h*** e@126.com
|
||||
string visiblePartBefore = email.Substring(0, atIndex);
|
||||
|
||||
public static string MaskEmail(string email)
|
||||
string afterAt = email.Substring(atIndex + 1);
|
||||
|
||||
int visibleLength = (int)Math.Ceiling((double)visiblePartBefore.Length * 2 / 3);
|
||||
|
||||
// 替换中间两位字符为星号
|
||||
string hiddenPartBeforeAt = visiblePartBefore.Substring(0, visibleLength - 1) + "***" + visiblePartBefore.Last();
|
||||
|
||||
|
||||
// 组合隐藏和可见部分
|
||||
string hiddenEmail = hiddenPartBeforeAt + "@" + afterAt;
|
||||
|
||||
return hiddenEmail;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 密码必须包含:1)8 – 32 个字符;2)至少1个数字;3) 至少1个大写字母;4)至少1个小写字母;5)至少1个特殊字符 (~!-@#$%^&*_+?)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string GenerateRandomPassword(int length)
|
||||
{
|
||||
// 必须包含的字符组
|
||||
const string numbers = "0123456789";
|
||||
const string upperCaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
const string lowerCaseLetters = "abcdefghijklmnopqrstuvwxyz";
|
||||
const string specialCharacters = "~!-@#$%^&*_+?";
|
||||
|
||||
// 随机选择至少一个字符
|
||||
char[] requiredCharacters =
|
||||
{
|
||||
numbers[Random.Next(numbers.Length)],
|
||||
upperCaseLetters[Random.Next(upperCaseLetters.Length)],
|
||||
lowerCaseLetters[Random.Next(lowerCaseLetters.Length)],
|
||||
specialCharacters[Random.Next(specialCharacters.Length)]
|
||||
};
|
||||
|
||||
// 找到 "@" 符号的位置
|
||||
int atIndex = email.IndexOf('@');
|
||||
// 构建剩余的字符集,用于填充密码的其余部分
|
||||
string allCharacters = numbers + upperCaseLetters + lowerCaseLetters + specialCharacters;
|
||||
|
||||
string visiblePartBefore = email.Substring(0, atIndex);
|
||||
// 确保密码长度满足用户要求
|
||||
char[] password = new char[length];
|
||||
|
||||
string afterAt = email.Substring(atIndex + 1);
|
||||
// 将必须包含的字符放入密码中
|
||||
requiredCharacters.CopyTo(password, 0);
|
||||
|
||||
int visibleLength = (int)Math.Ceiling((double)visiblePartBefore.Length * 2 / 3);
|
||||
|
||||
// 替换中间两位字符为星号
|
||||
string hiddenPartBeforeAt = visiblePartBefore.Substring(0, visibleLength - 1) + "***" + visiblePartBefore.Last();
|
||||
|
||||
|
||||
// 组合隐藏和可见部分
|
||||
string hiddenEmail = hiddenPartBeforeAt + "@" + afterAt;
|
||||
|
||||
return hiddenEmail;
|
||||
// 填充剩余的字符
|
||||
for (int i = requiredCharacters.Length; i < length; i++)
|
||||
{
|
||||
password[i] = allCharacters[Random.Next(allCharacters.Length)];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 密码必须包含:1)8 – 32 个字符;2)至少1个数字;3) 至少1个大写字母;4)至少1个小写字母;5)至少1个特殊字符 (~!-@#$%^&*_+?)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string GenerateRandomPassword(int length)
|
||||
{
|
||||
// 必须包含的字符组
|
||||
const string numbers = "0123456789";
|
||||
const string upperCaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
const string lowerCaseLetters = "abcdefghijklmnopqrstuvwxyz";
|
||||
const string specialCharacters = "~!-@#$%^&*_+?";
|
||||
|
||||
// 随机选择至少一个字符
|
||||
char[] requiredCharacters =
|
||||
{
|
||||
numbers[Random.Next(numbers.Length)],
|
||||
upperCaseLetters[Random.Next(upperCaseLetters.Length)],
|
||||
lowerCaseLetters[Random.Next(lowerCaseLetters.Length)],
|
||||
specialCharacters[Random.Next(specialCharacters.Length)]
|
||||
};
|
||||
|
||||
// 构建剩余的字符集,用于填充密码的其余部分
|
||||
string allCharacters = numbers + upperCaseLetters + lowerCaseLetters + specialCharacters;
|
||||
|
||||
// 确保密码长度满足用户要求
|
||||
char[] password = new char[length];
|
||||
|
||||
// 将必须包含的字符放入密码中
|
||||
requiredCharacters.CopyTo(password, 0);
|
||||
|
||||
// 填充剩余的字符
|
||||
for (int i = requiredCharacters.Length; i < length; i++)
|
||||
{
|
||||
password[i] = allCharacters[Random.Next(allCharacters.Length)];
|
||||
}
|
||||
|
||||
// 随机打乱密码字符顺序
|
||||
return new string(password.OrderBy(_ => Random.Next()).ToArray());
|
||||
}
|
||||
// 随机打乱密码字符顺序
|
||||
return new string(password.OrderBy(_ => Random.Next()).ToArray());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,204 +5,203 @@ using Microsoft.Extensions.Configuration;
|
|||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace IRaCIS.Core.Application.Helper
|
||||
namespace IRaCIS.Core.Application.Helper;
|
||||
|
||||
public static class InternationalizationHelper
|
||||
{
|
||||
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; }
|
||||
|
||||
private static void VerifyFolder()
|
||||
{
|
||||
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; }
|
||||
|
||||
private static void VerifyFolder()
|
||||
if (!Directory.Exists(JsonFileFolder) ||
|
||||
!Directory.GetFiles(JsonFileFolder).Any(filePath => Path.GetExtension(filePath).Equals(".json", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
if (!Directory.Exists(JsonFileFolder) ||
|
||||
!Directory.GetFiles(JsonFileFolder).Any(filePath => Path.GetExtension(filePath).Equals(".json", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
throw new BusinessValidationFailedException("国际化Json文件目录有误");
|
||||
}
|
||||
throw new BusinessValidationFailedException("国际化Json文件目录有误");
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task BatchAddJsonKeyValueAsync(List<BatchAddInternationalizationDto> batchAddDtos)
|
||||
public static async Task BatchAddJsonKeyValueAsync(List<BatchAddInternationalizationDto> batchAddDtos)
|
||||
{
|
||||
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 })
|
||||
{
|
||||
VerifyFolder();
|
||||
var json = await File.ReadAllTextAsync(filePath);
|
||||
|
||||
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
|
||||
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
|
||||
JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
|
||||
|
||||
// 添加或更新指定的键值对
|
||||
|
||||
//更新json 文件 同时更新内存缓存的数据
|
||||
foreach (var filePath in new string[] { usJsonPath, cnJsonPath })
|
||||
if (filePath.Contains(StaticData.En_US_Json))
|
||||
{
|
||||
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 item in batchAddDtos)
|
||||
{
|
||||
jsonObject[item.Code] = item.Value;
|
||||
jsonObject[item.Code] = item.Value;
|
||||
|
||||
StaticData.En_US_Dic[item.Code] = item.Value;
|
||||
|
||||
//日志记录该信息方便自己人看, 返回给客户的是配置的
|
||||
StaticData.Log_Locoalize_Dic[item.Code] = item.Description;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var item in batchAddDtos)
|
||||
{
|
||||
jsonObject[item.Code] = item.Value;
|
||||
|
||||
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);
|
||||
|
||||
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.En_US_Dic[item.Code] = item.Value;
|
||||
|
||||
//日志记录该信息方便自己人看, 返回给客户的是配置的
|
||||
StaticData.Log_Locoalize_Dic[key] = description;
|
||||
StaticData.Log_Locoalize_Dic[item.Code] = item.Description;
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var item in batchAddDtos)
|
||||
{
|
||||
jsonObject[key] = valueCN;
|
||||
jsonObject[item.Code] = item.Value;
|
||||
|
||||
StaticData.Zh_CN_Dic[key] = valueCN;
|
||||
StaticData.Zh_CN_Dic[item.Code] = item.Value;
|
||||
}
|
||||
|
||||
|
||||
await File.WriteAllTextAsync(filePath, jsonObject.ToString());
|
||||
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
||||
|
||||
public static async Task InitInternationlizationDataAndWatchJsonFileAsync(IRepository<Internationalization> _internationalizationRepository)
|
||||
//更新json 文件 同时更新内存缓存的数据
|
||||
foreach (var filePath in new string[] { usJsonPath, cnJsonPath })
|
||||
{
|
||||
//查询数据库的数据
|
||||
var toJsonList = await _internationalizationRepository.Where(t => t.InternationalizationType == 1).Select(t => new
|
||||
var json = await File.ReadAllTextAsync(filePath);
|
||||
|
||||
JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
|
||||
|
||||
// 添加或更新指定的键值对
|
||||
|
||||
if (filePath.Contains(StaticData.En_US_Json))
|
||||
{
|
||||
t.Code,
|
||||
t.Value,
|
||||
t.ValueCN,
|
||||
t.Description
|
||||
}).ToListAsync();
|
||||
jsonObject[key] = value;
|
||||
|
||||
//组织成json 文件
|
||||
|
||||
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
|
||||
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
|
||||
|
||||
|
||||
//本地静态文件国际化需要
|
||||
foreach (var tojsonItem in toJsonList)
|
||||
{
|
||||
StaticData.En_US_Dic[tojsonItem.Code] = tojsonItem.Value;
|
||||
StaticData.Zh_CN_Dic[tojsonItem.Code] = tojsonItem.ValueCN;
|
||||
StaticData.En_US_Dic[key] = value;
|
||||
|
||||
//日志记录该信息方便自己人看, 返回给客户的是配置的
|
||||
StaticData.Log_Locoalize_Dic[tojsonItem.Code] = tojsonItem.Description;
|
||||
StaticData.Log_Locoalize_Dic[key] = 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))
|
||||
else
|
||||
{
|
||||
throw new BusinessValidationFailedException(StaticData.International("IRaCISCHangfireJob_FileNotFound"));
|
||||
jsonObject[key] = valueCN;
|
||||
|
||||
StaticData.Zh_CN_Dic[key] = valueCN;
|
||||
}
|
||||
|
||||
|
||||
// //监测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);
|
||||
await File.WriteAllTextAsync(filePath, jsonObject.ToString());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static async Task InitInternationlizationDataAndWatchJsonFileAsync(IRepository<Internationalization> _internationalizationRepository)
|
||||
{
|
||||
//查询数据库的数据
|
||||
var toJsonList = await _internationalizationRepository.Where(t => t.InternationalizationType == 1).Select(t => new
|
||||
{
|
||||
t.Code,
|
||||
t.Value,
|
||||
t.ValueCN,
|
||||
t.Description
|
||||
}).ToListAsync();
|
||||
|
||||
//组织成json 文件
|
||||
|
||||
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
|
||||
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
|
||||
|
||||
|
||||
//本地静态文件国际化需要
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -4,93 +4,92 @@ using System.Globalization;
|
|||
using Xceed.Document.NET;
|
||||
using Xceed.Words.NET;
|
||||
|
||||
namespace IRaCIS.Core.Application.Helper
|
||||
namespace IRaCIS.Core.Application.Helper;
|
||||
|
||||
/// <summary>
|
||||
/// 利用DocX 库 处理word国际化模板
|
||||
/// </summary>
|
||||
public static class WordTempleteHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 利用DocX 库 处理word国际化模板
|
||||
/// </summary>
|
||||
public static class WordTempleteHelper
|
||||
public static void DocX_GetInternationalTempleteStream(string filePath, Stream memoryStream)
|
||||
{
|
||||
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);
|
||||
|
||||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
||||
|
||||
using (DocX document = DocX.Load(filePath))
|
||||
if (bookmarkEn_Start != null)
|
||||
{
|
||||
// 查找书签
|
||||
var bookmarkEn_Start = document.Bookmarks.FirstOrDefault(b => b.Name == StaticData.CultureInfo.en_US_bookMark);
|
||||
// 获取书签的起始位置
|
||||
//int bookmarkCNStartPos = bookmarkCn_Start.Paragraph.StartIndex;
|
||||
|
||||
if (bookmarkEn_Start != null)
|
||||
var bookmarkENStartPos = bookmarkEn_Start.Paragraph.StartIndex;
|
||||
|
||||
// 创建一个要删除段落的列表
|
||||
List<Paragraph> paragraphsToRemove = new List<Paragraph>();
|
||||
|
||||
foreach (var item in document.Paragraphs)
|
||||
{
|
||||
// 获取书签的起始位置
|
||||
//int bookmarkCNStartPos = bookmarkCn_Start.Paragraph.StartIndex;
|
||||
//中文模板在前,英文在后,英文模板,就删除英文之前的,中文模板就删除英文之后的
|
||||
|
||||
var bookmarkENStartPos = bookmarkEn_Start.Paragraph.StartIndex;
|
||||
|
||||
// 创建一个要删除段落的列表
|
||||
List<Paragraph> paragraphsToRemove = new List<Paragraph>();
|
||||
|
||||
foreach (var item in document.Paragraphs)
|
||||
if (isEn_US ? item.EndIndex < bookmarkENStartPos : item.StartIndex >= bookmarkENStartPos)
|
||||
{
|
||||
//中文模板在前,英文在后,英文模板,就删除英文之前的,中文模板就删除英文之后的
|
||||
|
||||
if (isEn_US ? item.EndIndex < bookmarkENStartPos : item.StartIndex >= bookmarkENStartPos)
|
||||
{
|
||||
paragraphsToRemove.Add(item);
|
||||
}
|
||||
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)
|
||||
foreach (var paragraph in paragraphsToRemove)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
document.RemoveParagraph(paragraph);
|
||||
}
|
||||
doc.Write(memoryStream);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 保存修改
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue