整理命名空间
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>
|
<param name="doctorId"></param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</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>
|
<summary> 系统用户登录接口[New] </summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.AddOrUpdateTrialInspection(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Application.Contracts.TrialCommand})">
|
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.AddOrUpdateTrialInspection(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Application.Contracts.TrialCommand})">
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
<param name="param"></param>
|
<param name="param"></param>
|
||||||
<returns>新记录Id</returns>
|
<returns>新记录Id</returns>
|
||||||
</member>
|
</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>
|
<summary>
|
||||||
添加或更新工作量[AUTH]
|
添加或更新工作量[AUTH]
|
||||||
</summary>
|
</summary>
|
||||||
|
|
|
@ -10,7 +10,7 @@ using Panda.DynamicWebApi.Attributes;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using ZiggyCreatures.Caching.Fusion;
|
using ZiggyCreatures.Caching.Fusion;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application
|
namespace IRaCIS.Core.Application.Service
|
||||||
{
|
{
|
||||||
|
|
||||||
#pragma warning disable CS8618
|
#pragma warning disable CS8618
|
||||||
|
|
|
@ -3,42 +3,41 @@ using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.BusinessFilter
|
namespace IRaCIS.Core.Application.BusinessFilter;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 不生效,不知道为啥
|
||||||
|
/// </summary>
|
||||||
|
public class GlobalExceptionHandler : IExceptionHandler
|
||||||
{
|
{
|
||||||
|
private readonly ILogger<GlobalExceptionHandler> _logger;
|
||||||
/// <summary>
|
public GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger)
|
||||||
/// 不生效,不知道为啥
|
{
|
||||||
/// </summary>
|
this._logger = logger;
|
||||||
public class GlobalExceptionHandler : IExceptionHandler
|
}
|
||||||
|
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 ex = exception;
|
||||||
var errorInfo = $"Exception: {ex.Message}[{ex.StackTrace}]" + (ex.InnerException != null ? $" InnerException: {ex.InnerException.Message}[{ex.InnerException.StackTrace}]" : "");
|
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 true to signal that this exception is handled
|
||||||
return ValueTask.FromResult(false);
|
return ValueTask.FromResult(false);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,33 +4,31 @@ using Microsoft.Extensions.Localization;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Filter
|
namespace IRaCIS.Core.Application.Filter;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class ModelActionFilter : ActionFilterAttribute, IActionFilter
|
||||||
{
|
{
|
||||||
|
public IStringLocalizer _localizer;
|
||||||
|
public ModelActionFilter(IStringLocalizer localizer)
|
||||||
public class ModelActionFilter : ActionFilterAttribute, IActionFilter
|
|
||||||
{
|
{
|
||||||
public IStringLocalizer _localizer;
|
_localizer = 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)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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.Filters;
|
||||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
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
|
public void OnResourceExecuting(ResourceExecutingContext context)
|
||||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
|
||||||
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
|
|
||||||
{
|
{
|
||||||
public void OnResourceExecuting(ResourceExecutingContext context)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
var factories = context.ValueProviderFactories;
|
var factories = context.ValueProviderFactories;
|
||||||
//factories.RemoveType<FormValueProviderFactory>();
|
//factories.RemoveType<FormValueProviderFactory>();
|
||||||
factories.RemoveType<FormFileValueProviderFactory>();
|
factories.RemoveType<FormFileValueProviderFactory>();
|
||||||
factories.RemoveType<JQueryFormValueProviderFactory>();
|
factories.RemoveType<JQueryFormValueProviderFactory>();
|
||||||
context.HttpContext.Request.EnableBuffering();
|
context.HttpContext.Request.EnableBuffering();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnResourceExecuted(ResourceExecutedContext context)
|
public void OnResourceExecuted(ResourceExecutedContext context)
|
||||||
{
|
{
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
|
@ -5,72 +5,71 @@ using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
using Microsoft.Extensions.Localization;
|
using Microsoft.Extensions.Localization;
|
||||||
using Microsoft.Extensions.Logging;
|
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;
|
if (!context.ExceptionHandled)
|
||||||
|
|
||||||
public ProjectExceptionFilter(IStringLocalizer localizer, ILogger<ProjectExceptionFilter> logger)
|
|
||||||
{
|
{
|
||||||
_logger = logger;
|
if (context.Exception.GetType().Name == "DbUpdateConcurrencyException")
|
||||||
_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(_localizer["ProjectException_ConcurrentUpdateNotAllowed"] + context.Exception.Message));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.Exception.GetType() == typeof(BusinessValidationFailedException))
|
|
||||||
{
|
|
||||||
var error = context.Exception as BusinessValidationFailedException;
|
|
||||||
|
|
||||||
var info = string.Empty;
|
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, "", error!.Code, localizedInfo: info));
|
||||||
|
|
||||||
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]}");
|
||||||
|
}
|
||||||
//warning 级别记录
|
else if (context.Exception.GetType() == typeof(QueryBusinessObjectNotExistException))
|
||||||
//_logger.LogWarning($"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}");
|
{
|
||||||
}
|
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, ApiResponseCodeEnum.DataNotExist));
|
||||||
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
|
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 ZiggyCreatures.Caching.Fusion;
|
||||||
using static IRaCIS.Core.Domain.Share.StaticData;
|
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>
|
private readonly IUserInfo _userInfo;
|
||||||
/// 主要为了 处理项目结束 锁库,不允许操作
|
private readonly IFusionCache _fusionCache;
|
||||||
/// </summary>
|
public IStringLocalizer _localizer;
|
||||||
public class TrialResourceFilter : Attribute, IAsyncResourceFilter
|
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;
|
_fusionCache = fusionCache;
|
||||||
private readonly IFusionCache _fusionCache;
|
_userInfo = userInfo;
|
||||||
public IStringLocalizer _localizer;
|
_localizer = localizer;
|
||||||
private readonly IRepository<Trial> _trialRepository;
|
_trialRepository = trialRepository;
|
||||||
private readonly List<string> _trialOptList = new List<string>();
|
|
||||||
|
|
||||||
|
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;
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"]));
|
||||||
_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());
|
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//优先选择异步的方法
|
#endregion
|
||||||
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
|
|
||||||
|
|
||||||
|
|
||||||
|
//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();
|
trialIdStr = context.HttpContext.Request.Query["trialId"];
|
||||||
//var _trialOptList= typeFilter.Arguments.Select(t => t.ToString()).ToList();
|
}
|
||||||
|
|
||||||
#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();
|
||||||
|
|
||||||
// 后期列举出具体的类型,其他任何用户类型,都不允许操作
|
var trialIdIndex = headerStr.IndexOf("trialId");
|
||||||
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower() != "TrialDocument/userConfirm".ToLower())
|
|
||||||
|
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
//---对不起,您的账户没有操作权限。
|
trialIdStr = matchResult.Value;
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"]));
|
}
|
||||||
|
else
|
||||||
return;
|
{
|
||||||
|
//---正则取请求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
|
if (trialIdIndex > -1)
|
||||||
var trialIdStr = string.Empty;
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(context.HttpContext.Request.Query["trialId"]))
|
|
||||||
{
|
{
|
||||||
trialIdStr = context.HttpContext.Request.Query["trialId"];
|
// (?<="trialId" *: *").*?(?=",)
|
||||||
}
|
|
||||||
|
|
||||||
//先尝试从path中取TrialId
|
//使用正则 [0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}
|
||||||
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();
|
|
||||||
|
|
||||||
var trialIdIndex = headerStr.IndexOf("trialId");
|
var matchResult = Regex.Match(contentFromBody.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
|
||||||
|
|
||||||
|
|
||||||
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)
|
if (matchResult.Success)
|
||||||
{
|
{
|
||||||
|
//有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下
|
||||||
|
|
||||||
trialIdStr = matchResult.Value;
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -89,93 +133,48 @@ namespace IRaCIS.Core.Application.Filter
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
//使用字符串取 如果是swagger 可能有时取的不对 因为空格的原因
|
||||||
else
|
//trialIdStr = contentFromBody.Substring(trialIdIndex + "TrialId".Length + 4, 3
|
||||||
{
|
|
||||||
#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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//通过path 或者body 找到trialId 了
|
#endregion
|
||||||
if (!string.IsNullOrWhiteSpace(trialIdStr))
|
}
|
||||||
|
|
||||||
|
//通过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();
|
await next.Invoke();
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
|
// 项目停止、或者完成 不允许操作
|
||||||
else
|
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.AspNetCore.Mvc.Filters;
|
||||||
using Microsoft.Extensions.Logging;
|
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>
|
private readonly ILogger _logger;
|
||||||
/// 统一返回前端数据包装,之前在控制器包装,现在修改为动态Api 在ResultFilter这里包装,减少重复冗余代码
|
|
||||||
/// by zhouhang 2021.09.12 周末
|
public UnifiedApiResultFilter(ILogger<UnifiedApiResultFilter> logger)
|
||||||
/// </summary>
|
|
||||||
public class UnifiedApiResultFilter : Attribute, IAsyncResultFilter
|
|
||||||
{
|
{
|
||||||
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>
|
//是200 并且没有包装 那么包装结果
|
||||||
/// 异步版本
|
if (statusCode == 200 && !(objectResult.Value is IResponseOutput))
|
||||||
/// </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)
|
|
||||||
{
|
{
|
||||||
var statusCode = objectResult.StatusCode ?? context.HttpContext.Response.StatusCode;
|
|
||||||
|
|
||||||
//是200 并且没有包装 那么包装结果
|
var type = objectResult.Value?.GetType();
|
||||||
if (statusCode == 200 && !(objectResult.Value is IResponseOutput))
|
|
||||||
|
|
||||||
|
if (type != null && type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(ValueTuple<,>) || type.GetGenericTypeDefinition() == typeof(Tuple<,>)))
|
||||||
{
|
{
|
||||||
|
|
||||||
var type = objectResult.Value?.GetType();
|
//报错
|
||||||
|
//var tuple = (object, object))objectResult.Value;
|
||||||
|
//var (val1, val2) = ((dynamic, dynamic))objectResult.Value;
|
||||||
if (type != null && type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(ValueTuple<,>) || type.GetGenericTypeDefinition() == typeof(Tuple<,>)))
|
//var apiResponse = ResponseOutput.Ok(val1, val2);
|
||||||
{
|
|
||||||
|
//OK
|
||||||
//报错
|
var tuple = (dynamic)objectResult.Value;
|
||||||
//var tuple = (object, object))objectResult.Value;
|
var apiResponse = ResponseOutput.Ok(tuple!.Item1, tuple!.Item2);
|
||||||
//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();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
objectResult.Value = apiResponse;
|
||||||
|
objectResult.DeclaredType = apiResponse.GetType();
|
||||||
}
|
}
|
||||||
//如果是200 是IResponseOutput 记录下日志
|
else
|
||||||
else if (statusCode == 200 && (objectResult.Value is IResponseOutput))
|
|
||||||
{
|
{
|
||||||
var result = objectResult.Value as IResponseOutput;
|
var apiResponse = ResponseOutput.Ok(objectResult.Value);
|
||||||
|
|
||||||
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"));
|
|
||||||
|
|
||||||
objectResult.Value = apiResponse;
|
objectResult.Value = apiResponse;
|
||||||
objectResult.DeclaredType = apiResponse.GetType();
|
objectResult.DeclaredType = apiResponse.GetType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
//如果是200 是IResponseOutput 记录下日志
|
||||||
await next.Invoke();
|
else if (statusCode == 200 && (objectResult.Value is IResponseOutput))
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
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 result = objectResult.Value as IResponseOutput;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(result.LocalizedInfo))
|
||||||
{
|
{
|
||||||
var genType = type.GetGenericTypeDefinition();
|
//统一在这里记录国际化的日志信息
|
||||||
if (genType == typeof(Tuple<>)
|
_logger.LogWarning($"{result.LocalizedInfo}");
|
||||||
|| genType == typeof(Tuple<,>)
|
|
||||||
|| genType == typeof(Tuple<,>))
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 AutoMapper.QueryableExtensions;
|
||||||
global using IRaCIS.Core.Application;
|
|
||||||
global using IRaCIS.Core.Application.Service;
|
global using IRaCIS.Core.Application.Service;
|
||||||
global using IRaCIS.Core.Domain.Models;
|
global using IRaCIS.Core.Domain.Models;
|
||||||
global using IRaCIS.Core.Infra.EFCore;
|
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)
|
||||||
{
|
{
|
||||||
//项目缓存
|
var statusStr = await _trialRepository.Where(t => t.Id == trialId, ignoreQueryFilters: true).Select(t => t.TrialStatusStr).FirstOrDefaultAsync();
|
||||||
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";
|
|
||||||
|
|
||||||
|
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 list = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
|
||||||
{
|
|
||||||
var statusStr = await _trialRepository.Where(t => t.Id == trialId, ignoreQueryFilters: true).Select(t => t.TrialStatusStr).FirstOrDefaultAsync();
|
|
||||||
|
|
||||||
return statusStr;
|
return list;
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<List<SystemAnonymization>> GetSystemAnonymizationListAsync(IRepository<SystemAnonymization> _systemAnonymizationRepository)
|
|
||||||
{
|
|
||||||
var list = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +1,33 @@
|
||||||
using System.Diagnostics;
|
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}\"";
|
||||||
|
|
||||||
|
// 启动 libreoffice 进程
|
||||||
static public void ConvertWordToPdf(string inputWordFilePath, string outputPdfDir)
|
using (Process process = new Process())
|
||||||
{
|
{
|
||||||
// 设置 libreoffice 命令行参数
|
process.StartInfo.FileName = "libreoffice";
|
||||||
string arguments = $"--headless --invisible --convert-to pdf \"{inputWordFilePath}\" --outdir \"{outputPdfDir}\"";
|
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 进程
|
process.Start();
|
||||||
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.WaitForExit();
|
||||||
// 等待进程结束
|
|
||||||
process.WaitForExit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,106 +1,105 @@
|
||||||
using RestSharp;
|
using RestSharp;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Helper
|
namespace IRaCIS.Core.Application.Helper;
|
||||||
|
|
||||||
|
|
||||||
|
#region 对接模型
|
||||||
|
public class HolidayCalendar
|
||||||
{
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
#region 对接模型
|
public string Version { get; set; }
|
||||||
public class HolidayCalendar
|
public string Generated { get; set; }
|
||||||
{
|
public string Timezone { get; set; }
|
||||||
public string Name { get; set; }
|
public string Author { get; set; }
|
||||||
public string Version { get; set; }
|
public string URL { get; set; }
|
||||||
public string Generated { get; set; }
|
public Dictionary<string, List<HolidayYear>> Years { get; set; }
|
||||||
public string Timezone { get; set; }
|
}
|
||||||
public string Author { get; set; }
|
|
||||||
public string URL { get; set; }
|
public class HolidayYear
|
||||||
public Dictionary<string, List<HolidayYear>> Years { get; set; }
|
{
|
||||||
}
|
public string Name { get; set; }
|
||||||
|
public DateTime StartDate { get; set; }
|
||||||
public class HolidayYear
|
public DateTime EndDate { get; set; }
|
||||||
{
|
public int Duration { get; set; }
|
||||||
public string Name { get; set; }
|
public List<DateTime> CompDays { get; set; }
|
||||||
public DateTime StartDate { get; set; }
|
public string URL { get; set; }
|
||||||
public DateTime EndDate { get; set; }
|
public string Memo { get; set; }
|
||||||
public int Duration { get; set; }
|
}
|
||||||
public List<DateTime> CompDays { get; set; }
|
#endregion
|
||||||
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
|
||||||
public class HolidayHelper
|
/// 接口请求参考文档:https://www.koudingke.cn/docs/zh-Hans/net-lib-docs/latest/RestSharp/Usage/Usage
|
||||||
{
|
/// </summary>
|
||||||
/// <summary>
|
private static RestClient _client => new RestClient("https://www.shuyz.com/githubfiles/china-holiday-calender/master/holidayAPI.json");
|
||||||
/// 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
|
private static HolidayCalendar _holidayCalendar { get; set; }
|
||||||
/// </summary>
|
|
||||||
private static RestClient _client => new RestClient("https://www.shuyz.com/githubfiles/china-holiday-calender/master/holidayAPI.json");
|
|
||||||
|
private static List<DateTime> _holidays = new List<DateTime>();
|
||||||
private static HolidayCalendar _holidayCalendar { get; set; }
|
private static List<DateTime> _compensatedWorkdays = new List<DateTime>();
|
||||||
|
|
||||||
|
static HolidayHelper()
|
||||||
private static List<DateTime> _holidays = new List<DateTime>();
|
{
|
||||||
private static List<DateTime> _compensatedWorkdays = new List<DateTime>();
|
_holidayCalendar = _client.Get<HolidayCalendar>(new RestRequest()) ?? new HolidayCalendar();
|
||||||
|
|
||||||
static HolidayHelper()
|
foreach (var year in _holidayCalendar.Years.Values.SelectMany(x => x))
|
||||||
{
|
{
|
||||||
_holidayCalendar = _client.Get<HolidayCalendar>(new RestRequest()) ?? new HolidayCalendar();
|
// 添加节假日到假日集合
|
||||||
|
for (DateTime date = year.StartDate; date <= year.EndDate; date = date.AddDays(1))
|
||||||
foreach (var year in _holidayCalendar.Years.Values.SelectMany(x => x))
|
{
|
||||||
{
|
_holidays.Add(date);
|
||||||
// 添加节假日到假日集合
|
}
|
||||||
for (DateTime date = year.StartDate; date <= year.EndDate; date = date.AddDays(1))
|
|
||||||
{
|
// 添加补班日到补班日集合
|
||||||
_holidays.Add(date);
|
foreach (var compDay in year.CompDays)
|
||||||
}
|
{
|
||||||
|
_compensatedWorkdays.Add(compDay);
|
||||||
// 添加补班日到补班日集合
|
}
|
||||||
foreach (var compDay in year.CompDays)
|
}
|
||||||
{
|
|
||||||
_compensatedWorkdays.Add(compDay);
|
}
|
||||||
}
|
|
||||||
}
|
public static TimeSpan GetChinaWorkTimeSpan(DateTime startDate, DateTime endDate)
|
||||||
|
{
|
||||||
}
|
if (startDate > endDate)
|
||||||
|
{
|
||||||
public static TimeSpan GetChinaWorkTimeSpan(DateTime startDate, DateTime endDate)
|
throw new ArgumentException("结束日期必须大于或等于开始日期");
|
||||||
{
|
}
|
||||||
if (startDate > endDate)
|
|
||||||
{
|
var diffTimeSpan = endDate - startDate;
|
||||||
throw new ArgumentException("结束日期必须大于或等于开始日期");
|
|
||||||
}
|
// 初始化工作日数为0
|
||||||
|
int workdays = 0;
|
||||||
var diffTimeSpan = endDate - startDate;
|
|
||||||
|
// 找出在给定日期范围内的假期和补班日
|
||||||
// 初始化工作日数为0
|
var filteredHolidays = _holidays.Where(d => d >= startDate && d <= endDate).ToList();
|
||||||
int workdays = 0;
|
var filteredCompensatedWorkdays = _compensatedWorkdays.Where(d => d >= startDate && d <= endDate).ToList();
|
||||||
|
|
||||||
// 找出在给定日期范围内的假期和补班日
|
// 遍历日期范围,计算工作日 注意 这里是小于
|
||||||
var filteredHolidays = _holidays.Where(d => d >= startDate && d <= endDate).ToList();
|
for (DateTime date = startDate.Date; date < endDate.Date; date = date.AddDays(1))
|
||||||
var filteredCompensatedWorkdays = _compensatedWorkdays.Where(d => d >= startDate && d <= endDate).ToList();
|
{
|
||||||
|
// 判断是否为工作日
|
||||||
// 遍历日期范围,计算工作日 注意 这里是小于
|
bool isWeekend = date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday;
|
||||||
for (DateTime date = startDate.Date; date < endDate.Date; date = date.AddDays(1))
|
bool isHoliday = filteredHolidays.Contains(date);
|
||||||
{
|
bool isCompensatedWorkday = filteredCompensatedWorkdays.Contains(date);
|
||||||
// 判断是否为工作日
|
|
||||||
bool isWeekend = date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday;
|
// 如果是补班日,或是平日(非假期,非周末),则算作工作日
|
||||||
bool isHoliday = filteredHolidays.Contains(date);
|
if (isCompensatedWorkday || (!isWeekend && !isHoliday))
|
||||||
bool isCompensatedWorkday = filteredCompensatedWorkdays.Contains(date);
|
{
|
||||||
|
workdays++;
|
||||||
// 如果是补班日,或是平日(非假期,非周末),则算作工作日
|
}
|
||||||
if (isCompensatedWorkday || (!isWeekend && !isHoliday))
|
}
|
||||||
{
|
|
||||||
workdays++;
|
return new TimeSpan(workdays, diffTimeSpan.Hours, diffTimeSpan.Minutes, diffTimeSpan.Seconds);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
}
|
||||||
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的位数,向上取整
|
// 找到 "@" 符号的位置
|
||||||
//取哪几个个值:最后一位和前面几位
|
int atIndex = email.IndexOf('@');
|
||||||
//其他:3个***。
|
|
||||||
//比如:hlj23@126.com
|
|
||||||
//为:hlj***3@126.com
|
|
||||||
|
|
||||||
//he@126.com
|
string visiblePartBefore = email.Substring(0, atIndex);
|
||||||
//为:h*** e@126.com
|
|
||||||
|
|
||||||
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);
|
// 填充剩余的字符
|
||||||
|
for (int i = requiredCharacters.Length; i < length; i++)
|
||||||
// 替换中间两位字符为星号
|
{
|
||||||
string hiddenPartBeforeAt = visiblePartBefore.Substring(0, visibleLength - 1) + "***" + visiblePartBefore.Last();
|
password[i] = allCharacters[Random.Next(allCharacters.Length)];
|
||||||
|
|
||||||
|
|
||||||
// 组合隐藏和可见部分
|
|
||||||
string hiddenEmail = hiddenPartBeforeAt + "@" + afterAt;
|
|
||||||
|
|
||||||
return hiddenEmail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
// 随机打乱密码字符顺序
|
||||||
/// 密码必须包含:1)8 – 32 个字符;2)至少1个数字;3) 至少1个大写字母;4)至少1个小写字母;5)至少1个特殊字符 (~!-@#$%^&*_+?)
|
return new string(password.OrderBy(_ => Random.Next()).ToArray());
|
||||||
/// </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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,204 +5,203 @@ using Microsoft.Extensions.Configuration;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
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);
|
if (!Directory.Exists(JsonFileFolder) ||
|
||||||
|
!Directory.GetFiles(JsonFileFolder).Any(filePath => Path.GetExtension(filePath).Equals(".json", StringComparison.OrdinalIgnoreCase)))
|
||||||
public static FileSystemWatcher FileSystemWatcher_US { get; set; }
|
|
||||||
public static FileSystemWatcher FileSystemWatcher_CN { get; set; }
|
|
||||||
|
|
||||||
private static void VerifyFolder()
|
|
||||||
{
|
{
|
||||||
if (!Directory.Exists(JsonFileFolder) ||
|
throw new BusinessValidationFailedException("国际化Json文件目录有误");
|
||||||
!Directory.GetFiles(JsonFileFolder).Any(filePath => Path.GetExtension(filePath).Equals(".json", StringComparison.OrdinalIgnoreCase)))
|
|
||||||
{
|
|
||||||
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);
|
JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
|
||||||
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
|
|
||||||
|
|
||||||
|
// 添加或更新指定的键值对
|
||||||
|
|
||||||
//更新json 文件 同时更新内存缓存的数据
|
if (filePath.Contains(StaticData.En_US_Json))
|
||||||
foreach (var filePath in new string[] { usJsonPath, cnJsonPath })
|
|
||||||
{
|
{
|
||||||
var json = await File.ReadAllTextAsync(filePath);
|
foreach (var item in batchAddDtos)
|
||||||
|
|
||||||
JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
|
|
||||||
|
|
||||||
// 添加或更新指定的键值对
|
|
||||||
|
|
||||||
if (filePath.Contains(StaticData.En_US_Json))
|
|
||||||
{
|
{
|
||||||
foreach (var item in batchAddDtos)
|
jsonObject[item.Code] = item.Value;
|
||||||
{
|
|
||||||
jsonObject[item.Code] = item.Value;
|
|
||||||
|
|
||||||
StaticData.En_US_Dic[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.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 json = await File.ReadAllTextAsync(filePath);
|
||||||
var toJsonList = await _internationalizationRepository.Where(t => t.InternationalizationType == 1).Select(t => new
|
|
||||||
|
JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
|
||||||
|
|
||||||
|
// 添加或更新指定的键值对
|
||||||
|
|
||||||
|
if (filePath.Contains(StaticData.En_US_Json))
|
||||||
{
|
{
|
||||||
t.Code,
|
jsonObject[key] = value;
|
||||||
t.Value,
|
|
||||||
t.ValueCN,
|
|
||||||
t.Description
|
|
||||||
}).ToListAsync();
|
|
||||||
|
|
||||||
//组织成json 文件
|
StaticData.En_US_Dic[key] = value;
|
||||||
|
|
||||||
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;
|
StaticData.Log_Locoalize_Dic[key] = description;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
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"));
|
jsonObject[key] = valueCN;
|
||||||
|
|
||||||
|
StaticData.Zh_CN_Dic[key] = valueCN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// //监测Json文件变更 实时刷新数据
|
await File.WriteAllTextAsync(filePath, jsonObject.ToString());
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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.Document.NET;
|
||||||
using Xceed.Words.NET;
|
using Xceed.Words.NET;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Helper
|
namespace IRaCIS.Core.Application.Helper;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 利用DocX 库 处理word国际化模板
|
||||||
|
/// </summary>
|
||||||
|
public static class WordTempleteHelper
|
||||||
{
|
{
|
||||||
/// <summary>
|
public static void DocX_GetInternationalTempleteStream(string filePath, Stream memoryStream)
|
||||||
/// 利用DocX 库 处理word国际化模板
|
|
||||||
/// </summary>
|
|
||||||
public static class WordTempleteHelper
|
|
||||||
{
|
{
|
||||||
public static void DocX_GetInternationalTempleteStream(string filePath, Stream memoryStream)
|
|
||||||
|
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
||||||
|
|
||||||
|
using (DocX document = DocX.Load(filePath))
|
||||||
{
|
{
|
||||||
|
// 查找书签
|
||||||
|
var bookmarkEn_Start = document.Bookmarks.FirstOrDefault(b => b.Name == StaticData.CultureInfo.en_US_bookMark);
|
||||||
|
|
||||||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
if (bookmarkEn_Start != null)
|
||||||
|
|
||||||
using (DocX document = DocX.Load(filePath))
|
|
||||||
{
|
{
|
||||||
// 查找书签
|
// 获取书签的起始位置
|
||||||
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;
|
if (isEn_US ? item.EndIndex < bookmarkENStartPos : item.StartIndex >= bookmarkENStartPos)
|
||||||
|
|
||||||
// 创建一个要删除段落的列表
|
|
||||||
List<Paragraph> paragraphsToRemove = new List<Paragraph>();
|
|
||||||
|
|
||||||
foreach (var item in document.Paragraphs)
|
|
||||||
{
|
{
|
||||||
//中文模板在前,英文在后,英文模板,就删除英文之前的,中文模板就删除英文之后的
|
paragraphsToRemove.Add(item);
|
||||||
|
|
||||||
if (isEn_US ? item.EndIndex < bookmarkENStartPos : item.StartIndex >= bookmarkENStartPos)
|
|
||||||
{
|
|
||||||
paragraphsToRemove.Add(item);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var paragraph in paragraphsToRemove)
|
|
||||||
{
|
|
||||||
document.RemoveParagraph(paragraph);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存修改
|
foreach (var paragraph in paragraphsToRemove)
|
||||||
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);
|
document.RemoveParagraph(paragraph);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存修改
|
||||||
|
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