Compare commits
387 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 30e71b11e8 | |||
| 2de504005e | |||
| 6a41c33d34 | |||
| 3b48dfae31 | |||
| c7fd9a6bcb | |||
| 169ef180ff | |||
| f33d3d474b | |||
| 63e1331bd1 | |||
| 418cc9b4b9 | |||
| 71fb1eac6b | |||
| 0804a05925 | |||
| de6098013d | |||
| f8cd361415 | |||
| 0b1a640c3e | |||
| aa9df5838c | |||
| 2edacc9ff5 | |||
| a9a0a9d307 | |||
| 1937804e47 | |||
| 8e8b55fa46 | |||
| 3096671595 | |||
| a6102490c8 | |||
| 9e1cc1521f | |||
| a579c26ada | |||
| 754da2c7fc | |||
| 995bdee1f6 | |||
| a70f661e86 | |||
| 8312bfb78b | |||
| 7194796841 | |||
| c6918cca46 | |||
| be7b38c6ce | |||
| a7ebd50536 | |||
| 05f9b81e04 | |||
| 1f9eb9e36b | |||
| af46eb2d65 | |||
| d1e54629e7 | |||
| 78dbe23d0e | |||
| 4bf93d10b0 | |||
| 00827e9975 | |||
| 021b32587a | |||
| 5ffe1675db | |||
| d34eca2cb8 | |||
| 12ac7af11e | |||
| a19eb2abca | |||
| 4c9a8aadab | |||
| 034058999d | |||
| 34ea39e764 | |||
| 7caf00bd75 | |||
| aabe604e18 | |||
| f2bc281e2b | |||
| 4187a568f8 | |||
| 1611554c00 | |||
| 60fc8f9bce | |||
| 48eb20fa66 | |||
| 9e7bc09f84 | |||
| ec9e35180b | |||
| c757212c07 | |||
| 8415dd2be1 | |||
| 17d734ba11 | |||
| 476387b468 | |||
| 3a2cb138ab | |||
| fa763e6341 | |||
| c988ca0bca | |||
| c257dd4171 | |||
| ff026f45fc | |||
| cd2166f11b | |||
| 33cfacec84 | |||
| 5c2bebf96c | |||
| ef5ae76907 | |||
| 7546ba412c | |||
| 6b536f4a4f | |||
| a540326031 | |||
| 45dd2e90c5 | |||
| e3188c0419 | |||
| 423fa4001b | |||
| 3701d8bcd9 | |||
| 0689f731b7 | |||
| d97025aeca | |||
| fa929ebde4 | |||
| 32c4d634ed | |||
| 8d4a791a1c | |||
| 59f376e720 | |||
| a5017c1571 | |||
| 8767911a16 | |||
| f1170244da | |||
| 921c66140f | |||
| 0f2a73cb3c | |||
| a16f567ade | |||
| 5e8b5eed9f | |||
| 682e40febd | |||
| 568ef07438 | |||
| cafdbaac57 | |||
| 505184b200 | |||
| 1d7e1be641 | |||
| 8ba22a343a | |||
| ab34c947ca | |||
| 062387e6a8 | |||
| 161213f2af | |||
| c1fcb4f6e3 | |||
| a9d81f5af5 | |||
| 2900f2fa7f | |||
| 4e44d163f3 | |||
| ffa6d62d3d | |||
| d9ba6a7a89 | |||
| 8e0105b71f | |||
| c45461937d | |||
| b9c9088de2 | |||
| a6cfe19139 | |||
| 1f11de4a20 | |||
| 871333b9e9 | |||
| 47d8ec7576 | |||
| 46a304b5a6 | |||
| 098ade3c8a | |||
| 86489b2117 | |||
| 64b5206f86 | |||
| ea0b7f1eca | |||
| 7e8dd1c6a7 | |||
| d3b8716a66 | |||
| af77baba60 | |||
| 2f1cfc3e67 | |||
| 37d15736e2 | |||
| 5f8045c611 | |||
| d62562149c | |||
| 63e2ca07b5 | |||
| ed94423f32 | |||
| e705e12656 | |||
| 035ce2ae4e | |||
| a1778d836b | |||
| cebcf908f9 | |||
| 202a3c26d1 | |||
| fbbda8c0d1 | |||
| 7954bdeca8 | |||
| d8a0c80ca4 | |||
| 100faa3b9f | |||
| 7894a4991c | |||
| 0405ba4b13 | |||
| ca6e96929f | |||
| b832a66abf | |||
| 168c7447bb | |||
| 891c442da4 | |||
| 74098641f6 | |||
| eedfa2add8 | |||
| 2838f09268 | |||
| ab800d09ca | |||
| 44e4fe3a29 | |||
| d279bad2d0 | |||
| a5737073c4 | |||
| 4a82812b4e | |||
| 8ec67d72f1 | |||
| 405db77dea | |||
| 8b8ed1fee3 | |||
| c1e496530d | |||
| a43ba04bf3 | |||
| 7b78e4b399 | |||
| e92ea3ea0c | |||
| 2bb4630351 | |||
| ef63c19c93 | |||
| cda134e92c | |||
| 75d162b353 | |||
| 9cbfb2c7e4 | |||
| a47e20ff74 | |||
| 36a63d7628 | |||
| 2217ae0353 | |||
| 31a444508b | |||
| 37c898ea0c | |||
| 03c2a67fe4 | |||
| 795caf19e7 | |||
| 99ef28be99 | |||
| 97a5eda8f8 | |||
| 2d8cb0c818 | |||
| 2d1325ca52 | |||
| 9f5b8e9858 | |||
| 4eaf070243 | |||
| c353ae645b | |||
| e1038c27f6 | |||
| 994a770fef | |||
| 1875b56b37 | |||
| 99eef31202 | |||
| 826f8a670d | |||
| cb53dbefcf | |||
| 9b4e29a812 | |||
| fa9c9de12c | |||
| c98db93ecb | |||
| eb1dcc9f0a | |||
| 63c6c2f67b | |||
| 62f37a4bb4 | |||
| 02a8289ad4 | |||
| 7c5f3323de | |||
| 2149bfa782 | |||
| 3561df7574 | |||
| 9cd4e272c7 | |||
| 7069a17d8e | |||
| 3e5d0b650d | |||
| a6b8db30c3 | |||
| 613f2d8c6c | |||
| b8e0c74d45 | |||
| 13acd950ad | |||
| 8ec86017f0 | |||
| ee43a5dc9d | |||
| e3ee1a42fb | |||
| 9fa24a35ef | |||
| 0e631e6f29 | |||
| 622d598392 | |||
| 3ab411578e | |||
| d1e21a9f4b | |||
| cd2ebe700b | |||
| 7f5a3bffd1 | |||
| cdbe74f1d9 | |||
| de01da975e | |||
| aae243e36e | |||
| d3f7c199c7 | |||
| ca41fac53d | |||
| 6ccbfc466f | |||
| 81aa7fb8ef | |||
| da102dfed2 | |||
| 63c225fb9b | |||
| f0f6f0bd23 | |||
| 52b60338c3 | |||
| d3e7b3a8d8 | |||
| 48cba94995 | |||
| a2ca3a8245 | |||
| d602238f82 | |||
| 5f141212f4 | |||
| 8b05c01e42 | |||
| 307ed2ca7f | |||
| e9a90a4c3a | |||
| a9407c3290 | |||
| f9fc79d3aa | |||
| ee4b4a62ac | |||
| 7d7027a753 | |||
| e36dd04d3e | |||
| fd9af47606 | |||
| 633507d4cd | |||
| 8c94e17c14 | |||
| 942f3adfe0 | |||
| 3b92aaf61c | |||
| 4f5d89732d | |||
| 55bb70179c | |||
| 6c9c8ee5dc | |||
| 73e9e3239a | |||
| 8d67a3be5f | |||
| 5175c857ec | |||
| d2a9f478e4 | |||
| 9f32b92af3 | |||
| 880525b015 | |||
| 0536a57075 | |||
| abb3b02e74 | |||
| cad7132b0a | |||
| c6e5d31244 | |||
| b0302d0e6d | |||
| 9a958276db | |||
| 44bcdf7973 | |||
| 6311884a5c | |||
| de5fc7c277 | |||
| 3414c50975 | |||
| 39736c3ce4 | |||
| 14fb158e13 | |||
| 81f55a9e07 | |||
| 94e942e344 | |||
| 95fbe6085a | |||
| 4f4dda7a09 | |||
| 8021d6a860 | |||
| 3cdfd3a771 | |||
| 76792a127f | |||
| fc36cbcb75 | |||
| 3fab377454 | |||
| 5246c10e32 | |||
| 63530b7847 | |||
| 99be08dc20 | |||
| 9898673dbf | |||
| d7f0fdd0e7 | |||
| 795cb0aba2 | |||
| 32ba46206b | |||
| 22c9386101 | |||
| ff4136e02d | |||
| 04cccf1174 | |||
| ab9203eef0 | |||
| 924ba90384 | |||
| 353b2c99cb | |||
| 0b3542e9c3 | |||
| 425bd7bf9a | |||
| e0aa9fb1d9 | |||
| c65a484b13 | |||
| d9fc5e3646 | |||
| d72f3e89a2 | |||
| 85a303171c | |||
| 4026eca656 | |||
| 74aec46a94 | |||
| 49e21a6342 | |||
| 0e0dd0c7d3 | |||
| 8fedcdaf00 | |||
| 9924375f82 | |||
| a60661aaa5 | |||
| 5041ebd58b | |||
| 594574c846 | |||
| 6e7545be65 | |||
| b77d2d9160 | |||
| 0c94ef86b0 | |||
| e0c6e9aabf | |||
| 814f1e576a | |||
| d62d2770f4 | |||
| cec678a24b | |||
| 7baf301785 | |||
| ded0dbaa2d | |||
| 8c16bc2ac5 | |||
| 0827ede4b6 | |||
| 239e0b84c2 | |||
| 73b77a477a | |||
| c032c42321 | |||
| cb7140ad38 | |||
| 29ea2a0ef1 | |||
| 46af71e3df | |||
| 67819fc85d | |||
| 4b15bcdc55 | |||
| 0ba439e5bd | |||
| c25c855b46 | |||
| 003b227f7d | |||
| 461976f6d3 | |||
| 7636c82b11 | |||
| d1e4863e01 | |||
| d483aca73b | |||
| cf45169de2 | |||
| 0075c18cd8 | |||
| e55bc5fe7a | |||
| e6bd7ad0ea | |||
| a98bc37045 | |||
| 06209a945d | |||
| d5c628d916 | |||
| 905fdd9861 | |||
| 3ff95ede2c | |||
| f9734dc5cc | |||
| c32ec2f132 | |||
| 28c3adaf64 | |||
| 6435746660 | |||
| c6531e9249 | |||
| b1be0e2a98 | |||
| 31d22e2b4f | |||
| 1e5f01fdeb | |||
| 213787bbcf | |||
| 933a43f4ea | |||
| 6264d105ab | |||
| 0c7495870b | |||
| a615b5cefd | |||
| 9f66a932fc | |||
| d094f22ab2 | |||
| 5cc41b3b0f | |||
| 27b99eb3be | |||
| e324850811 | |||
| 7c3b0e9e72 | |||
| 709529da87 | |||
| 2354ee9174 | |||
| f158f092ce | |||
| f446d400a1 | |||
| 5b0026f30f | |||
| 1efd41e7ac | |||
| 76c6e8442a | |||
| f92ace1894 | |||
| 4585b7b732 | |||
| ae2907ad5d | |||
| 1a3ad4f602 | |||
| 9c95928add | |||
| 10380994a4 | |||
| 49993edb37 | |||
| 3efc40e9ae | |||
| 4922ffa5c3 | |||
| c7935ee90f | |||
| a91a706e0b | |||
| a16fbc187a | |||
| 4a314f2070 | |||
| 27d9104607 | |||
| acad258319 | |||
| ba8f22f260 | |||
| f524aa5e57 | |||
| 5c9664ec7d | |||
| be27376dde | |||
| 452535b561 | |||
| 9048963ea5 | |||
| d3ab051a39 | |||
| 73edbe8fd3 | |||
| de70f68640 | |||
| 97b97a164d | |||
| fb87f4d06a | |||
| 20092d6757 | |||
| 96c4165cda | |||
| a4226d4e2f | |||
| f97565d9d8 | |||
| ab84e66fe4 | |||
| 1f9d29e005 |
@@ -0,0 +1,4 @@
|
|||||||
|
FROM registry.cn-shanghai.aliyuncs.com/extimaging/aspnetcore:v8.2
|
||||||
|
WORKDIR /app
|
||||||
|
COPY publish .
|
||||||
|
ENTRYPOINT ["dotnet", "IRaCIS.Core.API.dll"]
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using IRaCIS.Core.Infrastructure.Extention;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.SCP.Filter
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
public class ModelActionFilter : ActionFilterAttribute, IActionFilter
|
||||||
|
{
|
||||||
|
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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.SCP.Filter
|
||||||
|
{
|
||||||
|
#region snippet_DisableFormValueModelBindingAttribute
|
||||||
|
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
||||||
|
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
|
||||||
|
{
|
||||||
|
public void OnResourceExecuting(ResourceExecutingContext context)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
var factories = context.ValueProviderFactories;
|
||||||
|
//factories.RemoveType<FormValueProviderFactory>();
|
||||||
|
factories.RemoveType<FormFileValueProviderFactory>();
|
||||||
|
factories.RemoveType<JQueryFormValueProviderFactory>();
|
||||||
|
context.HttpContext.Request.EnableBuffering();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnResourceExecuted(ResourceExecutedContext context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
using IRaCIS.Core.Infrastructure;
|
||||||
|
using IRaCIS.Core.Infrastructure.Extention;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.SCP.Filter
|
||||||
|
{
|
||||||
|
public class ProjectExceptionFilter : Attribute, IExceptionFilter
|
||||||
|
{
|
||||||
|
private readonly ILogger<ProjectExceptionFilter> _logger;
|
||||||
|
|
||||||
|
public IStringLocalizer _localizer;
|
||||||
|
|
||||||
|
public ProjectExceptionFilter(IStringLocalizer localizer, ILogger<ProjectExceptionFilter> logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_localizer = localizer;
|
||||||
|
}
|
||||||
|
public void OnException(ExceptionContext context)
|
||||||
|
{
|
||||||
|
//context.ExceptionHandled;//记录当前这个异常是否已经被处理过了
|
||||||
|
|
||||||
|
if (!context.ExceptionHandled)
|
||||||
|
{
|
||||||
|
if (context.Exception.GetType().Name == "DbUpdateConcurrencyException")
|
||||||
|
{
|
||||||
|
//---并发更新,当前不允许该操作
|
||||||
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ProjectException_ConcurrentUpdateNotAllowed"] + context.Exception.Message));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.Exception.GetType() == typeof(BusinessValidationFailedException))
|
||||||
|
{
|
||||||
|
var error = context.Exception as BusinessValidationFailedException;
|
||||||
|
|
||||||
|
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, error!.Code));
|
||||||
|
}
|
||||||
|
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));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//继续
|
||||||
|
}
|
||||||
|
context.ExceptionHandled = true;//标记当前异常已经被处理过了
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using IRaCIS.Core.Infrastructure.Extention;
|
||||||
|
|
||||||
|
namespace IRaCIS.Application.Services.BusinessFilter
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 统一返回前端数据包装,之前在控制器包装,现在修改为动态Api 在ResultFilter这里包装,减少重复冗余代码
|
||||||
|
/// by zhouhang 2021.09.12 周末
|
||||||
|
/// </summary>
|
||||||
|
public class UnifiedApiResultFilter : Attribute, IAsyncResultFilter
|
||||||
|
{
|
||||||
|
/// <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)
|
||||||
|
{
|
||||||
|
var statusCode = objectResult.StatusCode ?? context.HttpContext.Response.StatusCode;
|
||||||
|
|
||||||
|
//是200 并且没有包装 那么包装结果
|
||||||
|
if (statusCode == 200 && !(objectResult.Value is IResponseOutput))
|
||||||
|
{
|
||||||
|
//if (objectResult.Value == null)
|
||||||
|
//{
|
||||||
|
// var apiResponse = ResponseOutput.DBNotExist();
|
||||||
|
|
||||||
|
// objectResult.Value = apiResponse;
|
||||||
|
// objectResult.DeclaredType = apiResponse.GetType();
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
}
|
||||||
|
//如果不是200 是IResponseOutput 不处理
|
||||||
|
else if (statusCode != 200 && (objectResult.Value is IResponseOutput))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(statusCode != 200&&!(objectResult.Value is IResponseOutput))
|
||||||
|
{
|
||||||
|
//---程序错误,请联系开发人员。
|
||||||
|
var apiResponse = ResponseOutput.NotOk(StaticData.International("UnifiedAPI_ProgramError"));
|
||||||
|
|
||||||
|
objectResult.Value = apiResponse;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
|
||||||
|
using FellowOakDicom.Imaging;
|
||||||
|
using SixLabors.ImageSharp.Formats.Jpeg;
|
||||||
|
using SixLabors.ImageSharp;
|
||||||
|
using SixLabors.ImageSharp.Processing;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.Application.Helper;
|
||||||
|
|
||||||
|
public static class ImageHelper
|
||||||
|
{
|
||||||
|
|
||||||
|
// 采用ImageSharp组件 跨平台,不依赖windows 平台图像处理组件,这里大坑(net 6 下,之前由于Dicom处理最新组件 依赖了这个库的一个旧版本,导致缩略图bug,单独升级依赖组件才解决)
|
||||||
|
public static void ResizeSave(string filePath, string? fileStorePath)
|
||||||
|
{
|
||||||
|
|
||||||
|
fileStorePath = fileStorePath ?? filePath + ".preview.jpeg";
|
||||||
|
|
||||||
|
using (var image = SixLabors.ImageSharp.Image.Load(filePath))
|
||||||
|
{
|
||||||
|
|
||||||
|
image.Mutate(x => x.Resize(500, 500));
|
||||||
|
|
||||||
|
image.Save(fileStorePath);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static Stream RenderPreviewJpeg(string filePath)
|
||||||
|
{
|
||||||
|
string jpegPath = filePath + ".preview.jpg";
|
||||||
|
|
||||||
|
if (!File.Exists(jpegPath))
|
||||||
|
{
|
||||||
|
using (Stream stream = new FileStream(jpegPath, FileMode.Create))
|
||||||
|
{
|
||||||
|
DicomImage image = new DicomImage(filePath);
|
||||||
|
|
||||||
|
var sharpimage = image.RenderImage().AsSharpImage();
|
||||||
|
|
||||||
|
sharpimage.Save(stream, new JpegEncoder());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new FileStream(jpegPath, FileMode.Open);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RemovePreviewJpeg(string filePath)
|
||||||
|
{
|
||||||
|
string jpegPath = filePath + ".preview.jpg";
|
||||||
|
if (File.Exists(jpegPath)) File.Delete(jpegPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
using Autofac;
|
||||||
|
using IRaCIS.Core.Infra.EFCore;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Panda.DynamicWebApi;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using IRaCIS.Core.Domain.Models;
|
||||||
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using IRaCIS.Application.Services;
|
||||||
|
using AutoMapper;
|
||||||
|
using IRaCIS.Core.SCP.Service;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.SCP
|
||||||
|
{
|
||||||
|
// ReSharper disable once IdentifierTypo
|
||||||
|
public class AutofacModuleSetup : Autofac.Module
|
||||||
|
{
|
||||||
|
protected override void Load(ContainerBuilder containerBuilder)
|
||||||
|
{
|
||||||
|
|
||||||
|
#region byzhouhang 20210917 此处注册泛型仓储 可以减少Domain层 和Infra.EFcore 两层 空的仓储接口定义和 仓储文件定义
|
||||||
|
|
||||||
|
containerBuilder.RegisterGeneric(typeof(Repository<>))
|
||||||
|
.As(typeof(IRepository<>)).InstancePerLifetimeScope();//注册泛型仓储
|
||||||
|
|
||||||
|
containerBuilder.RegisterType<Repository>().As<IRepository>().InstancePerLifetimeScope();
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 指定控制器也由autofac 来进行实例获取 https://www.cnblogs.com/xwhqwer/p/15320838.html
|
||||||
|
|
||||||
|
//获取所有控制器类型并使用属性注入
|
||||||
|
containerBuilder.RegisterAssemblyTypes(typeof(BaseService).Assembly)
|
||||||
|
.Where(type => typeof(IDynamicWebApi).IsAssignableFrom(type))
|
||||||
|
.PropertiesAutowired();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Assembly application = Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory + typeof(BaseService).Assembly.GetName().Name+".dll");
|
||||||
|
containerBuilder.RegisterAssemblyTypes(application).Where(t => t.FullName.Contains("Service"))
|
||||||
|
.PropertiesAutowired().AsImplementedInterfaces();
|
||||||
|
|
||||||
|
|
||||||
|
//containerBuilder.RegisterType<HttpContextAccessor>().As<IHttpContextAccessor>().SingleInstance();
|
||||||
|
//containerBuilder.RegisterType<UserInfo>().As<IUserInfo>().InstancePerLifetimeScope();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
using EntityFramework.Exceptions.SqlServer;
|
||||||
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using IRaCIS.Core.Infra.EFCore;
|
||||||
|
using Medallion.Threading;
|
||||||
|
using Medallion.Threading.SqlServer;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.SCP
|
||||||
|
{
|
||||||
|
public static class EFSetup
|
||||||
|
{
|
||||||
|
public static void AddEFSetup( this IServiceCollection services, IConfiguration configuration)
|
||||||
|
{
|
||||||
|
services.AddHttpContextAccessor();
|
||||||
|
services.AddScoped<IUserInfo, UserInfo>();
|
||||||
|
services.AddScoped<ISaveChangesInterceptor, AuditEntityInterceptor>();
|
||||||
|
|
||||||
|
|
||||||
|
//这个注入没有成功--注入是没问题的,构造函数也只是支持参数就好,错在注入的地方不能写DbContext
|
||||||
|
//Web程序中通过重用池中DbContext实例可提高高并发场景下的吞吐量, 这在概念上类似于ADO.NET Provider原生的连接池操作方式,具有节省DbContext实例化成本的优点
|
||||||
|
services.AddDbContext<IRaCISDBContext>((sp, options) =>
|
||||||
|
{
|
||||||
|
// 在控制台
|
||||||
|
//public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); });
|
||||||
|
var logFactory = LoggerFactory.Create(builder => { builder.AddDebug(); });
|
||||||
|
|
||||||
|
options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value,
|
||||||
|
contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure());
|
||||||
|
|
||||||
|
options.UseLoggerFactory(logFactory);
|
||||||
|
|
||||||
|
options.UseExceptionProcessor();
|
||||||
|
|
||||||
|
options.EnableSensitiveDataLogging();
|
||||||
|
|
||||||
|
options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor());
|
||||||
|
options.AddInterceptors(sp.GetServices<ISaveChangesInterceptor>());
|
||||||
|
|
||||||
|
options.UseProjectables();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
//// Register an additional context factory as a Scoped service, which gets a pooled context from the Singleton factory we registered above,
|
||||||
|
//services.AddScoped<IRaCISDBScopedFactory>();
|
||||||
|
|
||||||
|
//// Finally, arrange for a context to get injected from our Scoped factory:
|
||||||
|
//services.AddScoped(sp => sp.GetRequiredService<IRaCISDBScopedFactory>().CreateDbContext());
|
||||||
|
|
||||||
|
//注意区分 easy caching 也有 IDistributedLockProvider
|
||||||
|
services.AddSingleton<IDistributedLockProvider>(sp =>
|
||||||
|
{
|
||||||
|
//var connection = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!);
|
||||||
|
|
||||||
|
return new SqlDistributedSynchronizationProvider(configuration.GetSection("ConnectionStrings:RemoteNew").Value);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
|
||||||
|
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.SCP
|
||||||
|
{
|
||||||
|
public static class NewtonsoftJsonSetup
|
||||||
|
{
|
||||||
|
public static void AddNewtonsoftJsonSetup(this IMvcBuilder builder, IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddHttpContextAccessor();
|
||||||
|
services.AddScoped<IOSSService,OSSService>();
|
||||||
|
|
||||||
|
builder.AddNewtonsoftJson(options =>
|
||||||
|
{
|
||||||
|
//options.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
|
||||||
|
// 忽略循环引用
|
||||||
|
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
|
||||||
|
//options.SerializerSettings.TypeNameHandling = TypeNameHandling.All;
|
||||||
|
|
||||||
|
//处理返回给前端 可空类型 给出默认值 比如in? 为null 设置 默认值0
|
||||||
|
options.SerializerSettings.ContractResolver = new NullToEmptyStringResolver(); //new DefaultContractResolver();// new NullToEmptyStringResolver();
|
||||||
|
// 设置时间格式
|
||||||
|
options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
|
||||||
|
|
||||||
|
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
|
||||||
|
|
||||||
|
//options.SerializerSettings.Converters.Add(new JSONCustomDateConverter()) ;
|
||||||
|
|
||||||
|
//options.SerializerSettings.Converters.Add(services.BuildServiceProvider().GetService<JSONTimeZoneConverter>());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
.AddControllersAsServices()//动态webApi属性注入需要
|
||||||
|
.ConfigureApiBehaviorOptions(o =>
|
||||||
|
{
|
||||||
|
o.SuppressModelStateInvalidFilter = true; //自己写验证
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
Newtonsoft.Json.JsonSerializerSettings setting = new Newtonsoft.Json.JsonSerializerSettings();
|
||||||
|
JsonConvert.DefaultSettings = new Func<JsonSerializerSettings>(() =>
|
||||||
|
{
|
||||||
|
//日期类型默认格式化处理
|
||||||
|
setting.DateFormatString = "yyyy-MM-dd HH:mm:ss";
|
||||||
|
setting.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
|
||||||
|
|
||||||
|
return setting;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.SCP
|
||||||
|
{
|
||||||
|
public class NullToEmptyStringResolver : DefaultContractResolver
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
|
||||||
|
{
|
||||||
|
IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
|
||||||
|
|
||||||
|
var list= type.GetProperties()
|
||||||
|
.Select(p =>
|
||||||
|
{
|
||||||
|
var jp = base.CreateProperty(p, memberSerialization);
|
||||||
|
jp.ValueProvider = new NullToEmptyStringValueProvider(p);
|
||||||
|
return jp;
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
var uu = list.Select(t => t.PropertyName).ToList();
|
||||||
|
|
||||||
|
//获取复杂对象属性
|
||||||
|
properties = properties.TakeWhile(t => !uu.Contains(t.PropertyName)).ToList();
|
||||||
|
|
||||||
|
list.AddRange(properties);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.SCP
|
||||||
|
{
|
||||||
|
|
||||||
|
public class NullToEmptyStringValueProvider : IValueProvider
|
||||||
|
{
|
||||||
|
PropertyInfo _MemberInfo;
|
||||||
|
public NullToEmptyStringValueProvider(PropertyInfo memberInfo)
|
||||||
|
{
|
||||||
|
_MemberInfo = memberInfo;
|
||||||
|
}
|
||||||
|
public object GetValue(object target)
|
||||||
|
{
|
||||||
|
object result = _MemberInfo.GetValue(target);
|
||||||
|
if (_MemberInfo.PropertyType == typeof(string) && result == null) result = "";
|
||||||
|
else if (_MemberInfo.PropertyType == typeof(String[]) && result == null) result = new string[] { };
|
||||||
|
//else if (_MemberInfo.PropertyType == typeof(Nullable<Int32>) && result == null) result = 0;
|
||||||
|
else if (_MemberInfo.PropertyType == typeof(Nullable<Decimal>) && result == null) result = 0.00M;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
public void SetValue(object target, object value)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(_MemberInfo.PropertyType == typeof(string))
|
||||||
|
{
|
||||||
|
//去掉前后空格
|
||||||
|
_MemberInfo.SetValue(target, value==null?string.Empty: value.ToString()==string.Empty? value:value.ToString().Trim());
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_MemberInfo.SetValue(target, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.13.0" />
|
||||||
|
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="9.0.0" />
|
||||||
|
<PackageReference Include="DistributedLock.Core" Version="1.0.6" />
|
||||||
|
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.4" />
|
||||||
|
<PackageReference Include="fo-dicom" Version="5.1.2" />
|
||||||
|
<PackageReference Include="fo-dicom.Codecs" Version="5.12.0" />
|
||||||
|
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.4" />
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.20.1" />
|
||||||
|
<PackageReference Include="AutoMapper" Version="13.0.1" />
|
||||||
|
<PackageReference Include="Minio" Version="6.0.2" />
|
||||||
|
<PackageReference Include="My.Extensions.Localization.Json" Version="3.3.0">
|
||||||
|
<TreatAsUsed>true</TreatAsUsed>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" />
|
||||||
|
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.0.3" />
|
||||||
|
<PackageReference Include="Serilog.Extensions.Hosting" Version="8.0.0" />
|
||||||
|
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
|
||||||
|
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\IRaCIS.Core.Domain\IRaCIS.Core.Domain.csproj" />
|
||||||
|
<ProjectReference Include="..\IRaCIS.Core.Infra.EFCore\IRaCIS.Core.Infra.EFCore.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,214 @@
|
|||||||
|
|
||||||
|
using Autofac;
|
||||||
|
using Autofac.Extensions.DependencyInjection;
|
||||||
|
using AutoMapper.EquivalencyExpression;
|
||||||
|
using FellowOakDicom;
|
||||||
|
using FellowOakDicom.Imaging;
|
||||||
|
using FellowOakDicom.Imaging.NativeCodec;
|
||||||
|
using FellowOakDicom.Network;
|
||||||
|
using IRaCIS.Core.Infra.EFCore;
|
||||||
|
using IRaCIS.Core.SCP;
|
||||||
|
using IRaCIS.Core.SCP.Filter;
|
||||||
|
using IRaCIS.Core.SCP.Service;
|
||||||
|
using MassTransit;
|
||||||
|
using MassTransit.NewIdProviders;
|
||||||
|
using Microsoft.AspNetCore.HttpOverrides;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Panda.DynamicWebApi;
|
||||||
|
using Serilog;
|
||||||
|
using Serilog.Events;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
|
||||||
|
//以配置文件为准,否则 从url中取环境值(服务以命令行传递参数启动,配置文件配置了就不需要传递环境参数)
|
||||||
|
var config = new ConfigurationBuilder()
|
||||||
|
.AddEnvironmentVariables()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var enviromentName = config["ASPNETCORE_ENVIRONMENT"];
|
||||||
|
|
||||||
|
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
|
||||||
|
{
|
||||||
|
EnvironmentName = enviromentName
|
||||||
|
});
|
||||||
|
|
||||||
|
#region 兼容windows 服务命令行的方式
|
||||||
|
|
||||||
|
int urlsIndex = Array.FindIndex(args, arg => arg != null && arg.StartsWith("--port"));
|
||||||
|
|
||||||
|
if (urlsIndex > -1)
|
||||||
|
{
|
||||||
|
var port = args[urlsIndex].Substring("--port=".Length);
|
||||||
|
Console.WriteLine(port);
|
||||||
|
builder.WebHost.UseUrls($"http://0.0.0.0:{port}");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 主机配置
|
||||||
|
|
||||||
|
NewId.SetProcessIdProvider(new CurrentProcessIdProvider());
|
||||||
|
|
||||||
|
builder.Configuration.AddJsonFile("appsettings.json", false, true)
|
||||||
|
.AddJsonFile($"appsettings.{enviromentName}.json", false, true);
|
||||||
|
builder.Host
|
||||||
|
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
|
||||||
|
.ConfigureContainer<ContainerBuilder>(containerBuilder =>
|
||||||
|
{
|
||||||
|
containerBuilder.RegisterModule<AutofacModuleSetup>();
|
||||||
|
})
|
||||||
|
.UseSerilog();
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 配置服务
|
||||||
|
var _configuration = builder.Configuration;
|
||||||
|
|
||||||
|
//健康检查
|
||||||
|
builder.Services.AddHealthChecks();
|
||||||
|
|
||||||
|
//本地化
|
||||||
|
builder.Services.AddJsonLocalization(options => options.ResourcesPath = "Resources");
|
||||||
|
|
||||||
|
|
||||||
|
// 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim()
|
||||||
|
builder.Services.AddControllers(options =>
|
||||||
|
{
|
||||||
|
options.Filters.Add<ModelActionFilter>();
|
||||||
|
options.Filters.Add<ProjectExceptionFilter>();
|
||||||
|
options.Filters.Add<UnitOfWorkFilter>();
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
.AddNewtonsoftJsonSetup(builder.Services); // NewtonsoftJson 序列化 处理
|
||||||
|
|
||||||
|
|
||||||
|
builder.Services.AddOptions().Configure<AliyunOSSOptions>(_configuration.GetSection("AliyunOSS"));
|
||||||
|
builder.Services.AddOptions().Configure<ObjectStoreServiceOptions>(_configuration.GetSection("ObjectStoreService"));
|
||||||
|
builder.Services.AddOptions().Configure<DicomSCPServiceOption>(_configuration.GetSection("DicomSCPServiceConfig"));
|
||||||
|
|
||||||
|
|
||||||
|
//动态WebApi + UnifiedApiResultFilter 省掉控制器代码
|
||||||
|
//动态webApi 目前存在的唯一小坑是生成api上服务上的动态代理AOP失效 间接掉用不影响
|
||||||
|
builder.Services
|
||||||
|
.AddDynamicWebApi(dynamicWebApiOption =>
|
||||||
|
{
|
||||||
|
//默认是 api
|
||||||
|
dynamicWebApiOption.DefaultApiPrefix = "";
|
||||||
|
//首字母小写
|
||||||
|
dynamicWebApiOption.GetRestFulActionName = (actionName) => char.ToLower(actionName[0]) + actionName.Substring(1);
|
||||||
|
//删除 Service后缀
|
||||||
|
dynamicWebApiOption.RemoveControllerPostfixes.Add("Service");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
//AutoMapper
|
||||||
|
builder.Services.AddAutoMapper(automapper =>
|
||||||
|
{
|
||||||
|
|
||||||
|
automapper.AddCollectionMappers();
|
||||||
|
|
||||||
|
|
||||||
|
}, typeof(BaseService).Assembly);
|
||||||
|
|
||||||
|
//EF ORM QueryWithNoLock
|
||||||
|
builder.Services.AddEFSetup(_configuration);
|
||||||
|
|
||||||
|
|
||||||
|
//转发头设置 获取真实IP
|
||||||
|
builder.Services.Configure<ForwardedHeadersOptions>(options =>
|
||||||
|
{
|
||||||
|
options.ForwardedHeaders =
|
||||||
|
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
|
||||||
|
});
|
||||||
|
|
||||||
|
//Dicom影像渲染图片 跨平台
|
||||||
|
//builder.Services.AddDicomSetup();
|
||||||
|
new DicomSetupBuilder()
|
||||||
|
.RegisterServices(s =>
|
||||||
|
s.AddFellowOakDicom()
|
||||||
|
.AddTranscoderManager<NativeTranscoderManager>()
|
||||||
|
//.AddTranscoderManager<FellowOakDicom.Imaging.NativeCodec.NativeTranscoderManager>()
|
||||||
|
.AddImageManager<ImageSharpImageManager>())
|
||||||
|
.SkipValidation()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
// Add services to the container.
|
||||||
|
|
||||||
|
builder.Services.AddControllers();
|
||||||
|
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||||
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
|
builder.Services.AddSwaggerGen();
|
||||||
|
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
// Configure the HTTP request pipeline.
|
||||||
|
//if (app.Environment.IsDevelopment())
|
||||||
|
//{
|
||||||
|
app.UseSwagger();
|
||||||
|
app.UseSwaggerUI();
|
||||||
|
//}
|
||||||
|
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
app.MapControllers();
|
||||||
|
|
||||||
|
#region 日志
|
||||||
|
|
||||||
|
//Log.Logger = new LoggerConfiguration()
|
||||||
|
// .MinimumLevel.Information()
|
||||||
|
// .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
|
||||||
|
// // Filter out ASP.NET Core infrastructre logs that are Information and below 日志太多了 一个请求 记录好几条
|
||||||
|
// .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
|
||||||
|
// .MinimumLevel.Override("Hangfire", LogEventLevel.Warning)
|
||||||
|
// .MinimumLevel.Override("System.Net.Http.HttpClient.HttpReports", LogEventLevel.Warning)
|
||||||
|
// .Enrich.WithClientIp()
|
||||||
|
|
||||||
|
// .Enrich.FromLogContext()
|
||||||
|
|
||||||
|
// //控制台 方便调试 问题 我们显示记录日志 时 获取上下文的ip 和用户名 用户类型
|
||||||
|
// .WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Warning,
|
||||||
|
// outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {SourceContext:l} || {Message} || {Exception} ||end {NewLine}")
|
||||||
|
|
||||||
|
// .WriteTo.File($"{AppContext.BaseDirectory}Serilogs/.log", rollingInterval: RollingInterval.Day,
|
||||||
|
// outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {SourceContext:l} || {Message} || {Exception} ||end {NewLine}")
|
||||||
|
// .CreateLogger();
|
||||||
|
|
||||||
|
Log.Logger = new LoggerConfiguration()
|
||||||
|
//.MinimumLevel.Information()
|
||||||
|
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
|
||||||
|
.WriteTo.Console()
|
||||||
|
.WriteTo.File($"{AppContext.BaseDirectory}Serilogs/.log", rollingInterval: RollingInterval.Day)
|
||||||
|
.CreateLogger();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region 运行环境 部署平台
|
||||||
|
|
||||||
|
Log.Logger.Warning($"当前环境:{enviromentName}");
|
||||||
|
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
Log.Logger.Warning($"当前部署平台环境:windows");
|
||||||
|
}
|
||||||
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||||
|
{
|
||||||
|
Log.Logger.Warning($"当前部署平台环境:linux");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.Logger.Warning($"当前部署平台环境:OSX or FreeBSD");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
var logger = app.Services.GetService<Microsoft.Extensions.Logging.ILogger<Program>>();
|
||||||
|
|
||||||
|
var server = DicomServerFactory.Create<CStoreSCPService>(_configuration.GetSection("DicomSCPServiceConfig").GetValue<int>("ServerPort"), userState: app.Services,logger: logger);
|
||||||
|
|
||||||
|
|
||||||
|
app.Run();
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||||
|
"profiles": {
|
||||||
|
"Test_IRC_SCP": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"applicationUrl": "http://localhost:6200",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Test_IRC_SCP"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Uat_IRC_SCP": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"applicationUrl": "http://localhost:6200",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Uat_IRC_SCP"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
using AutoMapper;
|
||||||
|
using IRaCIS.Application.Services.BusinessFilter;
|
||||||
|
using IRaCIS.Core.Infra.EFCore;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
using Panda.DynamicWebApi;
|
||||||
|
using Panda.DynamicWebApi.Attributes;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using IRaCIS.Core.Infrastructure.Extention;
|
||||||
|
using IRaCIS.Core.Domain.Models;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.SCP.Service
|
||||||
|
{
|
||||||
|
|
||||||
|
#pragma warning disable CS8618
|
||||||
|
|
||||||
|
|
||||||
|
#region 非泛型版本
|
||||||
|
|
||||||
|
[Authorize, DynamicWebApi, UnifiedApiResultFilter]
|
||||||
|
public class BaseService : IBaseService, IDynamicWebApi
|
||||||
|
{
|
||||||
|
public IMapper _mapper { get; set; }
|
||||||
|
|
||||||
|
public IUserInfo _userInfo { get; set; }
|
||||||
|
|
||||||
|
public IRepository _repository { get; set; }
|
||||||
|
|
||||||
|
public IStringLocalizer _localizer { get; set; }
|
||||||
|
|
||||||
|
public IWebHostEnvironment _hostEnvironment { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class
|
||||||
|
{
|
||||||
|
return new ResponseOutput<string>()
|
||||||
|
.NotOk($"The query object {typeof(TEntity).Name} does not exist , or was deleted by someone else, or an incorrect parameter query caused", code: ApiResponseCodeEnum.DataNotExist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public interface IBaseService
|
||||||
|
{
|
||||||
|
[MemberNotNull(nameof(_mapper))]
|
||||||
|
public IMapper _mapper { get; set; }
|
||||||
|
|
||||||
|
[MemberNotNull(nameof(_userInfo))]
|
||||||
|
public IUserInfo _userInfo { get; set; }
|
||||||
|
|
||||||
|
[MemberNotNull(nameof(_repository))]
|
||||||
|
public IRepository _repository { get; set; }
|
||||||
|
|
||||||
|
[MemberNotNull(nameof(_localizer))]
|
||||||
|
public IStringLocalizer _localizer { get; set; }
|
||||||
|
|
||||||
|
[MemberNotNull(nameof(_hostEnvironment))]
|
||||||
|
public IWebHostEnvironment _hostEnvironment { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region 泛型版本测试
|
||||||
|
|
||||||
|
|
||||||
|
public interface IBaseServiceTest<T> where T : Entity
|
||||||
|
{
|
||||||
|
[MemberNotNull(nameof(_mapper))]
|
||||||
|
public IMapper _mapper { get; set; }
|
||||||
|
|
||||||
|
[MemberNotNull(nameof(_userInfo))]
|
||||||
|
public IUserInfo _userInfo { get; set; }
|
||||||
|
|
||||||
|
[MemberNotNull(nameof(_repository))]
|
||||||
|
public IRepository _repository { get; set; }
|
||||||
|
|
||||||
|
[MemberNotNull(nameof(_localizer))]
|
||||||
|
public IStringLocalizer _localizer { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Authorize, DynamicWebApi, UnifiedApiResultFilter]
|
||||||
|
public class BaseServiceTest<T> : IBaseServiceTest<T>, IDynamicWebApi where T : Entity
|
||||||
|
{
|
||||||
|
public IMapper _mapper { get; set; }
|
||||||
|
|
||||||
|
public IUserInfo _userInfo { get; set; }
|
||||||
|
|
||||||
|
public IRepository _repository { get; set; }
|
||||||
|
|
||||||
|
public IStringLocalizer _localizer { get; set; }
|
||||||
|
|
||||||
|
public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class
|
||||||
|
{
|
||||||
|
return new ResponseOutput<string>()
|
||||||
|
.NotOk($"The query object {typeof(TEntity).Name} does not exist , or was deleted by someone else, or an incorrect parameter query caused", code: ApiResponseCodeEnum.DataNotExist);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,370 @@
|
|||||||
|
using FellowOakDicom.Network;
|
||||||
|
using FellowOakDicom;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using IRaCIS.Core.SCP.Service;
|
||||||
|
using IRaCIS.Core.Domain.Models;
|
||||||
|
using IRaCIS.Core.Infra.EFCore;
|
||||||
|
using Medallion.Threading;
|
||||||
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using Serilog;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using System.Data;
|
||||||
|
using FellowOakDicom.Imaging;
|
||||||
|
using SharpCompress.Common;
|
||||||
|
using SixLabors.ImageSharp.Formats.Jpeg;
|
||||||
|
using IRaCIS.Core.Infrastructure;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.SCP.Service
|
||||||
|
{
|
||||||
|
|
||||||
|
public class DicomSCPServiceOption
|
||||||
|
{
|
||||||
|
public List<string> CalledAEList { get; set; }
|
||||||
|
|
||||||
|
public string ServerPort { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class CStoreSCPService : DicomService, IDicomServiceProvider, IDicomCStoreProvider, IDicomCEchoProvider
|
||||||
|
{
|
||||||
|
private IServiceProvider _serviceProvider { get; set; }
|
||||||
|
|
||||||
|
private List<Guid> _SCPStudyIdList { get; set; } = new List<Guid>();
|
||||||
|
|
||||||
|
private SCPImageUpload _upload { get; set; }
|
||||||
|
|
||||||
|
private Guid _trialId { get; set; }
|
||||||
|
|
||||||
|
private Guid _trialSiteId { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static readonly DicomTransferSyntax[] _acceptedTransferSyntaxes = new DicomTransferSyntax[]
|
||||||
|
{
|
||||||
|
DicomTransferSyntax.ExplicitVRLittleEndian,
|
||||||
|
DicomTransferSyntax.ExplicitVRBigEndian,
|
||||||
|
DicomTransferSyntax.ImplicitVRLittleEndian
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly DicomTransferSyntax[] _acceptedImageTransferSyntaxes = new DicomTransferSyntax[]
|
||||||
|
{
|
||||||
|
// Lossless
|
||||||
|
DicomTransferSyntax.JPEGLSLossless, //1.2.840.10008.1.2.4.80
|
||||||
|
DicomTransferSyntax.JPEG2000Lossless, //1.2.840.10008.1.2.4.90
|
||||||
|
DicomTransferSyntax.JPEGProcess14SV1, //1.2.840.10008.1.2.4.70
|
||||||
|
DicomTransferSyntax.JPEGProcess14, //1.2.840.10008.1.2.4.57 JPEG Lossless, Non-Hierarchical (Process 14)
|
||||||
|
DicomTransferSyntax.RLELossless, //1.2.840.10008.1.2.5
|
||||||
|
// Lossy
|
||||||
|
DicomTransferSyntax.JPEGLSNearLossless,//1.2.840.10008.1.2.4.81"
|
||||||
|
DicomTransferSyntax.JPEG2000Lossy, //1.2.840.10008.1.2.4.91
|
||||||
|
DicomTransferSyntax.JPEGProcess1, //1.2.840.10008.1.2.4.50
|
||||||
|
DicomTransferSyntax.JPEGProcess2_4, //1.2.840.10008.1.2.4.51
|
||||||
|
// Uncompressed
|
||||||
|
DicomTransferSyntax.ExplicitVRLittleEndian, //1.2.840.10008.1.2.1
|
||||||
|
DicomTransferSyntax.ExplicitVRBigEndian, //1.2.840.10008.1.2.2
|
||||||
|
DicomTransferSyntax.ImplicitVRLittleEndian //1.2.840.10008.1.2
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
public CStoreSCPService(INetworkStream stream, Encoding fallbackEncoding, Microsoft.Extensions.Logging.ILogger log, DicomServiceDependencies dependencies)
|
||||||
|
: base(stream, fallbackEncoding, log, dependencies)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public Task OnReceiveAssociationRequestAsync(DicomAssociation association)
|
||||||
|
{
|
||||||
|
|
||||||
|
_upload = new SCPImageUpload() { StartTime = DateTime.Now, CallingAE = association.CallingAE, CalledAE = association.CalledAE, CallingAEIP = association.RemoteHost };
|
||||||
|
|
||||||
|
|
||||||
|
Log.Logger.Warning($"接收到来自{association.CallingAE}的连接");
|
||||||
|
|
||||||
|
_serviceProvider = (IServiceProvider)this.UserState;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var _trialDicomAERepository = _serviceProvider.GetService<IRepository<TrialDicomAE>>();
|
||||||
|
|
||||||
|
|
||||||
|
var trialDicomAEList = _trialDicomAERepository.Select(t => new { t.CalledAE, t.TrialId }).ToList();
|
||||||
|
var trialCalledAEList = trialDicomAEList.Select(t => t.CalledAE).ToList();
|
||||||
|
|
||||||
|
Log.Logger.Information("当前系统配置:", string.Join('|', trialDicomAEList));
|
||||||
|
|
||||||
|
var findCalledAE = trialDicomAEList.Where(t => t.CalledAE == association.CalledAE).FirstOrDefault();
|
||||||
|
|
||||||
|
var isCanReceiveIamge = false;
|
||||||
|
|
||||||
|
if (findCalledAE != null)
|
||||||
|
{
|
||||||
|
_trialId = findCalledAE.TrialId;
|
||||||
|
|
||||||
|
var _trialSiteDicomAERepository = _serviceProvider.GetService<IRepository<TrialSiteDicomAE>>();
|
||||||
|
|
||||||
|
|
||||||
|
var findTrialSiteAE = _trialSiteDicomAERepository.Where(t => t.CallingAE == association.CallingAE && t.TrialId==_trialId).FirstOrDefault();
|
||||||
|
|
||||||
|
if (findTrialSiteAE != null)
|
||||||
|
{
|
||||||
|
_trialSiteId = findTrialSiteAE.TrialSiteId;
|
||||||
|
|
||||||
|
isCanReceiveIamge = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (association.CallingAE == "test-callingAE")
|
||||||
|
{
|
||||||
|
isCanReceiveIamge = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!trialCalledAEList.Contains(association.CalledAE) || isCanReceiveIamge == false)
|
||||||
|
{
|
||||||
|
|
||||||
|
Log.Logger.Warning($"拒绝CallingAE:{association.CallingAE} CalledAE:{association.CalledAE}的连接");
|
||||||
|
|
||||||
|
return SendAssociationRejectAsync(
|
||||||
|
DicomRejectResult.Permanent,
|
||||||
|
DicomRejectSource.ServiceUser,
|
||||||
|
DicomRejectReason.CalledAENotRecognized);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var pc in association.PresentationContexts)
|
||||||
|
{
|
||||||
|
if (pc.AbstractSyntax == DicomUID.Verification)
|
||||||
|
{
|
||||||
|
pc.AcceptTransferSyntaxes(_acceptedTransferSyntaxes);
|
||||||
|
}
|
||||||
|
else if (pc.AbstractSyntax.StorageCategory != DicomStorageCategory.None)
|
||||||
|
{
|
||||||
|
pc.AcceptTransferSyntaxes(_acceptedImageTransferSyntaxes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return SendAssociationAcceptAsync(association);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task OnReceiveAssociationReleaseRequestAsync()
|
||||||
|
{
|
||||||
|
await DataMaintenanceAsaync();
|
||||||
|
|
||||||
|
//记录监控
|
||||||
|
|
||||||
|
var _SCPImageUploadRepository = _serviceProvider.GetService<IRepository<SCPImageUpload>>();
|
||||||
|
|
||||||
|
_upload.EndTime = DateTime.Now;
|
||||||
|
_upload.StudyCount = _SCPStudyIdList.Count;
|
||||||
|
_upload.TrialId = _trialId;
|
||||||
|
_upload.TrialSiteId = _trialSiteId;
|
||||||
|
|
||||||
|
await _SCPImageUploadRepository.AddAsync(_upload, true);
|
||||||
|
|
||||||
|
await SendAssociationReleaseResponseAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async Task DataMaintenanceAsaync()
|
||||||
|
{
|
||||||
|
Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE}传输结束:开始维护数据,处理检查Modality");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//处理检查Modality
|
||||||
|
var _dictionaryRepository = _serviceProvider.GetService<IRepository<Dictionary>>();
|
||||||
|
var _seriesRepository = _serviceProvider.GetService<IRepository<SCPSeries>>();
|
||||||
|
var _studyRepository = _serviceProvider.GetService<IRepository<SCPStudy>>();
|
||||||
|
|
||||||
|
var dicModalityList = _dictionaryRepository.Where(t => t.Code == "Modality").SelectMany(t => t.ChildList.Select(c => c.Value)).ToList();
|
||||||
|
var seriesModalityList = _seriesRepository.Where(t => _SCPStudyIdList.Contains(t.StudyId)).Select(t => new { SCPStudyId = t.StudyId, t.Modality }).ToList();
|
||||||
|
|
||||||
|
foreach (var g in seriesModalityList.GroupBy(t => t.SCPStudyId))
|
||||||
|
{
|
||||||
|
var modality = string.Join('、', g.Select(t => t.Modality).Distinct().ToList());
|
||||||
|
|
||||||
|
//特殊逻辑
|
||||||
|
var modalityForEdit = dicModalityList.Contains(modality) ? modality : String.Empty;
|
||||||
|
|
||||||
|
if (modality == "MR")
|
||||||
|
{
|
||||||
|
modalityForEdit = "MRI";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modality == "PT")
|
||||||
|
{
|
||||||
|
modalityForEdit = "PET";
|
||||||
|
}
|
||||||
|
if (modality == "PT、CT" || modality == "CT、PT")
|
||||||
|
{
|
||||||
|
modalityForEdit = "PET-CT";
|
||||||
|
}
|
||||||
|
|
||||||
|
await _studyRepository.BatchUpdateNoTrackingAsync(t => t.Id == g.Key, u => new SCPStudy() { Modalities = modality, ModalityForEdit = modalityForEdit });
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE}维护数据结束");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnReceiveAbort(DicomAbortSource source, DicomAbortReason reason)
|
||||||
|
{
|
||||||
|
Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE}接收中断,中断原因:{source.ToString() + reason.ToString()}");
|
||||||
|
/* nothing to do here */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async void OnConnectionClosed(Exception exception)
|
||||||
|
{
|
||||||
|
/* nothing to do here */
|
||||||
|
|
||||||
|
//奇怪的bug 上传的时候,用王捷修改的影像,会关闭,重新连接,导致检查id 丢失,然后状态不一致
|
||||||
|
if (exception == null)
|
||||||
|
{
|
||||||
|
var _studyRepository = _serviceProvider.GetService<IRepository<SCPStudy>>();
|
||||||
|
//将检查设置为传输结束
|
||||||
|
await _studyRepository.BatchUpdateNoTrackingAsync(t => _SCPStudyIdList.Contains(t.Id), u => new SCPStudy() { IsUploadFinished = true });
|
||||||
|
|
||||||
|
await _studyRepository.SaveChangesAndClearAllTrackingAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.Logger.Warning($"连接关闭 {exception?.Message} {exception?.InnerException?.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<DicomCStoreResponse> OnCStoreRequestAsync(DicomCStoreRequest request)
|
||||||
|
{
|
||||||
|
|
||||||
|
string studyInstanceUid = request.Dataset.GetString(DicomTag.StudyInstanceUID);
|
||||||
|
string seriesInstanceUid = request.Dataset.GetString(DicomTag.SeriesInstanceUID);
|
||||||
|
string sopInstanceUid = request.Dataset.GetString(DicomTag.SOPInstanceUID);
|
||||||
|
|
||||||
|
//Guid studyId = IdentifierHelper.CreateGuid(studyInstanceUid, trialId.ToString());
|
||||||
|
Guid seriesId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, _trialId.ToString());
|
||||||
|
Guid instanceId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, sopInstanceUid, _trialId.ToString());
|
||||||
|
|
||||||
|
|
||||||
|
var ossService = _serviceProvider.GetService<IOSSService>();
|
||||||
|
var dicomArchiveService = _serviceProvider.GetService<IDicomArchiveService>();
|
||||||
|
var _seriesRepository = _serviceProvider.GetService<IRepository<SCPSeries>>();
|
||||||
|
|
||||||
|
var _distributedLockProvider = _serviceProvider.GetService<IDistributedLockProvider>();
|
||||||
|
|
||||||
|
var storeRelativePath = string.Empty;
|
||||||
|
var ossFolderPath = $"{_trialId}/Image/PACS/{_trialSiteId}{studyInstanceUid}";
|
||||||
|
|
||||||
|
|
||||||
|
long fileSize = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
using (MemoryStream ms = new MemoryStream())
|
||||||
|
{
|
||||||
|
await request.File.SaveAsync(ms);
|
||||||
|
|
||||||
|
//irc 从路径最后一截取Guid
|
||||||
|
storeRelativePath = await ossService.UploadToOSSAsync(ms, ossFolderPath, instanceId.ToString(), false);
|
||||||
|
|
||||||
|
fileSize = ms.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.Logger.Information($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE} {request.SOPInstanceUID} 上传完成 ");
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ec)
|
||||||
|
{
|
||||||
|
Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE} 上传异常 {ec.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var @lock = _distributedLockProvider.CreateLock($"{studyInstanceUid}");
|
||||||
|
|
||||||
|
using (await @lock.AcquireAsync())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var scpStudyId = await dicomArchiveService.ArchiveDicomFileAsync(request.Dataset, _trialId, _trialSiteId, storeRelativePath, Association.CallingAE, Association.CalledAE);
|
||||||
|
|
||||||
|
if (!_SCPStudyIdList.Contains(scpStudyId))
|
||||||
|
{
|
||||||
|
_SCPStudyIdList.Add(scpStudyId);
|
||||||
|
}
|
||||||
|
|
||||||
|
var series = await _seriesRepository.FindAsync(seriesId);
|
||||||
|
|
||||||
|
//没有缩略图
|
||||||
|
if (series != null && string.IsNullOrEmpty(series.ImageResizePath))
|
||||||
|
{
|
||||||
|
|
||||||
|
// 生成缩略图
|
||||||
|
using (var memoryStream = new MemoryStream())
|
||||||
|
{
|
||||||
|
DicomImage image = new DicomImage(request.Dataset);
|
||||||
|
|
||||||
|
var sharpimage = image.RenderImage().AsSharpImage();
|
||||||
|
sharpimage.Save(memoryStream, new JpegEncoder());
|
||||||
|
|
||||||
|
// 上传缩略图到 OSS
|
||||||
|
|
||||||
|
var seriesPath = await ossService.UploadToOSSAsync(memoryStream, ossFolderPath, seriesId.ToString() + ".preview.jpg", false);
|
||||||
|
|
||||||
|
Console.WriteLine(seriesPath + " Id: " + seriesId);
|
||||||
|
|
||||||
|
series.ImageResizePath = seriesPath;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
await _seriesRepository.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
|
||||||
|
Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE} 传输处理异常:{ex.ToString()}");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//监控信息设置
|
||||||
|
_upload.FileCount++;
|
||||||
|
_upload.FileSize = _upload.FileSize + fileSize;
|
||||||
|
return new DicomCStoreResponse(request, DicomStatus.Success);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Task OnCStoreRequestExceptionAsync(string tempFileName, Exception e)
|
||||||
|
{
|
||||||
|
// let library handle logging and error response
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Task<DicomCEchoResponse> OnCEchoRequestAsync(DicomCEchoRequest request)
|
||||||
|
{
|
||||||
|
return Task.FromResult(new DicomCEchoResponse(request, DicomStatus.Success));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,352 @@
|
|||||||
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using IRaCIS.Core.Infrastructure;
|
||||||
|
using Medallion.Threading;
|
||||||
|
using FellowOakDicom;
|
||||||
|
using FellowOakDicom.Imaging.Codec;
|
||||||
|
using System.Data;
|
||||||
|
using IRaCIS.Core.Domain.Models;
|
||||||
|
using FellowOakDicom.Network;
|
||||||
|
using IRaCIS.Core.SCP.Service;
|
||||||
|
using IRaCIS.Core.Infra.EFCore;
|
||||||
|
using MassTransit;
|
||||||
|
using System.Runtime.Intrinsics.X86;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.SCP.Service
|
||||||
|
{
|
||||||
|
public class DicomArchiveService : BaseService, IDicomArchiveService
|
||||||
|
{
|
||||||
|
private readonly IRepository<SCPPatient> _patientRepository;
|
||||||
|
private readonly IRepository<SCPStudy> _studyRepository;
|
||||||
|
private readonly IRepository<SCPSeries> _seriesRepository;
|
||||||
|
private readonly IRepository<SCPInstance> _instanceRepository;
|
||||||
|
private readonly IRepository<Dictionary> _dictionaryRepository;
|
||||||
|
private readonly IDistributedLockProvider _distributedLockProvider;
|
||||||
|
|
||||||
|
|
||||||
|
private List<Guid> _instanceIdList = new List<Guid>();
|
||||||
|
|
||||||
|
public DicomArchiveService(IRepository<SCPPatient> patientRepository, IRepository<SCPStudy> studyRepository,
|
||||||
|
IRepository<SCPSeries> seriesRepository,
|
||||||
|
IRepository<SCPInstance> instanceRepository,
|
||||||
|
IRepository<Dictionary> dictionaryRepository,
|
||||||
|
IDistributedLockProvider distributedLockProvider)
|
||||||
|
{
|
||||||
|
_distributedLockProvider = distributedLockProvider;
|
||||||
|
_studyRepository = studyRepository;
|
||||||
|
_patientRepository = patientRepository;
|
||||||
|
_seriesRepository = seriesRepository;
|
||||||
|
_instanceRepository = instanceRepository;
|
||||||
|
_dictionaryRepository = dictionaryRepository;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 单个文件接收 归档
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dataset"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="NotImplementedException"></exception>
|
||||||
|
public async Task<Guid> ArchiveDicomFileAsync(DicomDataset dataset, Guid trialId, Guid trialSiteId, string fileRelativePath, string callingAE, string calledAE)
|
||||||
|
{
|
||||||
|
string studyInstanceUid = dataset.GetString(DicomTag.StudyInstanceUID);
|
||||||
|
string seriesInstanceUid = dataset.GetString(DicomTag.SeriesInstanceUID);
|
||||||
|
string sopInstanceUid = dataset.GetString(DicomTag.SOPInstanceUID);
|
||||||
|
|
||||||
|
string patientIdStr = dataset.GetSingleValueOrDefault(DicomTag.PatientID,string.Empty);
|
||||||
|
|
||||||
|
//Guid patientId= IdentifierHelper.CreateGuid(patientIdStr);
|
||||||
|
Guid studyId = IdentifierHelper.CreateGuid(studyInstanceUid,trialId.ToString());
|
||||||
|
Guid seriesId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, trialId.ToString());
|
||||||
|
Guid instanceId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, sopInstanceUid, trialId.ToString());
|
||||||
|
|
||||||
|
var isStudyNeedAdd = false;
|
||||||
|
var isSeriesNeedAdd = false;
|
||||||
|
var isInstanceNeedAdd = false;
|
||||||
|
var isPatientNeedAdd = false;
|
||||||
|
|
||||||
|
//var @lock = _distributedLockProvider.CreateLock($"{studyInstanceUid}");
|
||||||
|
|
||||||
|
//using (@lock.Acquire())
|
||||||
|
{
|
||||||
|
var findPatient = await _patientRepository.FirstOrDefaultAsync(t => t.PatientIdStr == patientIdStr && t.TrialSiteId==trialSiteId );
|
||||||
|
var findStudy = await _studyRepository.FindAsync(studyId);
|
||||||
|
var findSerice = await _seriesRepository.FindAsync(seriesId);
|
||||||
|
var findInstance = await _instanceRepository.FindAsync(instanceId);
|
||||||
|
|
||||||
|
DateTime? studyTime = dataset.GetSingleValueOrDefault(DicomTag.StudyDate, string.Empty) == string.Empty ? null : dataset.GetSingleValue<DateTime>(DicomTag.StudyDate).Add(dataset.GetSingleValueOrDefault(DicomTag.StudyTime, string.Empty) == string.Empty ? TimeSpan.Zero : dataset.GetSingleValue<DateTime>(DicomTag.StudyTime).TimeOfDay);
|
||||||
|
|
||||||
|
//先传输了修改了患者编号的,又传输了没有修改患者编号的,导致后传输的没有修改患者编号的下面的检查为0
|
||||||
|
if (findPatient == null && findStudy==null)
|
||||||
|
{
|
||||||
|
isPatientNeedAdd = true;
|
||||||
|
|
||||||
|
|
||||||
|
findPatient = new SCPPatient()
|
||||||
|
{
|
||||||
|
Id = NewId.NextSequentialGuid(),
|
||||||
|
TrialId=trialId,
|
||||||
|
TrialSiteId=trialSiteId,
|
||||||
|
PatientIdStr = dataset.GetSingleValueOrDefault(DicomTag.PatientID, string.Empty),
|
||||||
|
PatientName = dataset.GetSingleValueOrDefault(DicomTag.PatientName, string.Empty),
|
||||||
|
PatientAge = dataset.GetSingleValueOrDefault(DicomTag.PatientAge, string.Empty),
|
||||||
|
PatientSex = dataset.GetSingleValueOrDefault(DicomTag.PatientSex, string.Empty),
|
||||||
|
PatientBirthDate = dataset.GetSingleValueOrDefault(DicomTag.PatientBirthDate, string.Empty),
|
||||||
|
|
||||||
|
EarliestStudyTime = studyTime,
|
||||||
|
LatestStudyTime = studyTime,
|
||||||
|
LatestPushTime = DateTime.Now,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (findPatient.PatientBirthDate.Length == 8)
|
||||||
|
{
|
||||||
|
var birthDateStr = $"{findPatient.PatientBirthDate[0]}{findPatient.PatientBirthDate[1]}{findPatient.PatientBirthDate[2]}{findPatient.PatientBirthDate[3]}-{findPatient.PatientBirthDate[4]}{findPatient.PatientBirthDate[5]}-{findPatient.PatientBirthDate[6]}{findPatient.PatientBirthDate[7]}";
|
||||||
|
|
||||||
|
var yearStr = $"{findPatient.PatientBirthDate[0]}{findPatient.PatientBirthDate[1]}{findPatient.PatientBirthDate[2]}{findPatient.PatientBirthDate[3]}";
|
||||||
|
|
||||||
|
int year = 0;
|
||||||
|
|
||||||
|
var canParse = int.TryParse(yearStr, out year);
|
||||||
|
|
||||||
|
if (canParse && year > 1900)
|
||||||
|
{
|
||||||
|
findPatient.PatientBirthDate = birthDateStr;
|
||||||
|
|
||||||
|
DateTime birthDate;
|
||||||
|
|
||||||
|
if (findPatient.PatientAge == string.Empty && studyTime.HasValue && DateTime.TryParse(findPatient.PatientBirthDate,out birthDate))
|
||||||
|
{
|
||||||
|
var patientAge = studyTime.Value.Year - birthDate.Year;
|
||||||
|
// 如果生日还未到,年龄减去一岁
|
||||||
|
if (studyTime.Value < birthDate.AddYears(patientAge))
|
||||||
|
{
|
||||||
|
patientAge--;
|
||||||
|
}
|
||||||
|
|
||||||
|
findPatient.PatientAge = patientAge.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
findPatient.PatientBirthDate = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (studyTime < findPatient.EarliestStudyTime)
|
||||||
|
{
|
||||||
|
findPatient.EarliestStudyTime = studyTime;
|
||||||
|
}
|
||||||
|
if (studyTime > findPatient.LatestStudyTime)
|
||||||
|
{
|
||||||
|
findPatient.LatestStudyTime = studyTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
findPatient.LatestPushTime = DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (findStudy == null)
|
||||||
|
{
|
||||||
|
isStudyNeedAdd = true;
|
||||||
|
findStudy = new SCPStudy
|
||||||
|
{
|
||||||
|
CalledAE = calledAE,
|
||||||
|
CallingAE = callingAE,
|
||||||
|
|
||||||
|
PatientId = findPatient.Id,
|
||||||
|
Id = studyId,
|
||||||
|
TrialId = trialId,
|
||||||
|
TrialSiteId = trialSiteId,
|
||||||
|
StudyInstanceUid = studyInstanceUid,
|
||||||
|
StudyTime = studyTime,
|
||||||
|
Modalities = dataset.GetSingleValueOrDefault(DicomTag.Modality, string.Empty),
|
||||||
|
//ModalityForEdit = modalityForEdit,
|
||||||
|
Description = dataset.GetSingleValueOrDefault(DicomTag.StudyDescription, string.Empty),
|
||||||
|
InstitutionName = dataset.GetSingleValueOrDefault(DicomTag.InstitutionName, string.Empty),
|
||||||
|
PatientIdStr = dataset.GetSingleValueOrDefault(DicomTag.PatientID, string.Empty),
|
||||||
|
PatientName = dataset.GetSingleValueOrDefault(DicomTag.PatientName, string.Empty),
|
||||||
|
PatientAge = dataset.GetSingleValueOrDefault(DicomTag.PatientAge, string.Empty),
|
||||||
|
PatientSex = dataset.GetSingleValueOrDefault(DicomTag.PatientSex, string.Empty),
|
||||||
|
BodyPartExamined = dataset.GetSingleValueOrDefault(DicomTag.BodyPartExamined, string.Empty),
|
||||||
|
|
||||||
|
StudyId = dataset.GetSingleValueOrDefault(DicomTag.StudyID, string.Empty),
|
||||||
|
AccessionNumber = dataset.GetSingleValueOrDefault(DicomTag.AccessionNumber, string.Empty),
|
||||||
|
|
||||||
|
//需要特殊处理
|
||||||
|
PatientBirthDate = dataset.GetSingleValueOrDefault(DicomTag.PatientBirthDate, string.Empty),
|
||||||
|
|
||||||
|
|
||||||
|
AcquisitionTime = dataset.GetSingleValueOrDefault(DicomTag.AcquisitionTime, string.Empty),
|
||||||
|
AcquisitionNumber = dataset.GetSingleValueOrDefault(DicomTag.AcquisitionNumber, string.Empty),
|
||||||
|
TriggerTime = dataset.GetSingleValueOrDefault(DicomTag.TriggerTime, string.Empty),
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//IsDoubleReview = addtionalInfo.IsDoubleReview,
|
||||||
|
SeriesCount = 0,
|
||||||
|
InstanceCount = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if (findStudy.PatientBirthDate.Length == 8)
|
||||||
|
{
|
||||||
|
findStudy.PatientBirthDate = $"{findStudy.PatientBirthDate[0]}{findStudy.PatientBirthDate[1]}{findStudy.PatientBirthDate[2]}{findStudy.PatientBirthDate[3]}-{findStudy.PatientBirthDate[4]}{findStudy.PatientBirthDate[5]}-{findStudy.PatientBirthDate[6]}{findStudy.PatientBirthDate[7]}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (findSerice == null)
|
||||||
|
{
|
||||||
|
isSeriesNeedAdd = true;
|
||||||
|
|
||||||
|
findSerice = new SCPSeries
|
||||||
|
{
|
||||||
|
Id = seriesId,
|
||||||
|
StudyId = findStudy.Id,
|
||||||
|
|
||||||
|
StudyInstanceUid = findStudy.StudyInstanceUid,
|
||||||
|
SeriesInstanceUid = seriesInstanceUid,
|
||||||
|
SeriesNumber = dataset.GetSingleValueOrDefault(DicomTag.SeriesNumber, 1),
|
||||||
|
//SeriesTime = dataset.GetSingleValueOrDefault(DicomTag.SeriesDate, DateTime.Now).Add(dataset.GetSingleValueOrDefault(DicomTag.SeriesTime, DateTime.Now).TimeOfDay),
|
||||||
|
//SeriesTime = DateTime.TryParse(dataset.GetSingleValue<string>(DicomTag.SeriesDate) + dataset.GetSingleValue<string>(DicomTag.SeriesTime), out DateTime dt) ? dt : null,
|
||||||
|
SeriesTime = dataset.GetSingleValueOrDefault(DicomTag.SeriesDate, string.Empty) == string.Empty ? null : dataset.GetSingleValue<DateTime>(DicomTag.SeriesDate).Add(dataset.GetSingleValueOrDefault(DicomTag.SeriesTime, string.Empty) == string.Empty ? TimeSpan.Zero : dataset.GetSingleValue<DateTime>(DicomTag.SeriesTime).TimeOfDay),
|
||||||
|
Modality = dataset.GetSingleValueOrDefault(DicomTag.Modality, string.Empty),
|
||||||
|
Description = dataset.GetSingleValueOrDefault(DicomTag.SeriesDescription, string.Empty),
|
||||||
|
SliceThickness = dataset.GetSingleValueOrDefault(DicomTag.SliceThickness, string.Empty),
|
||||||
|
|
||||||
|
ImagePositionPatient = dataset.GetSingleValueOrDefault(DicomTag.ImagePositionPatient, string.Empty),
|
||||||
|
ImageOrientationPatient = dataset.GetSingleValueOrDefault(DicomTag.ImageOrientationPatient, string.Empty),
|
||||||
|
BodyPartExamined = dataset.GetSingleValueOrDefault(DicomTag.BodyPartExamined, string.Empty),
|
||||||
|
SequenceName = dataset.GetSingleValueOrDefault(DicomTag.SequenceName, string.Empty),
|
||||||
|
ProtocolName = dataset.GetSingleValueOrDefault(DicomTag.ProtocolName, string.Empty),
|
||||||
|
ImagerPixelSpacing = dataset.GetSingleValueOrDefault(DicomTag.ImagerPixelSpacing, string.Empty),
|
||||||
|
|
||||||
|
AcquisitionTime = dataset.GetSingleValueOrDefault(DicomTag.AcquisitionTime, string.Empty),
|
||||||
|
AcquisitionNumber = dataset.GetSingleValueOrDefault(DicomTag.AcquisitionNumber, string.Empty),
|
||||||
|
TriggerTime = dataset.GetSingleValueOrDefault(DicomTag.TriggerTime, string.Empty),
|
||||||
|
|
||||||
|
|
||||||
|
InstanceCount = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
++findStudy.SeriesCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (findInstance == null)
|
||||||
|
{
|
||||||
|
isInstanceNeedAdd = true;
|
||||||
|
findInstance = new SCPInstance
|
||||||
|
{
|
||||||
|
Id = instanceId,
|
||||||
|
StudyId = findStudy.Id,
|
||||||
|
SeriesId = findSerice.Id,
|
||||||
|
StudyInstanceUid = findStudy.StudyInstanceUid,
|
||||||
|
SeriesInstanceUid = findSerice.SeriesInstanceUid,
|
||||||
|
|
||||||
|
SopInstanceUid = sopInstanceUid,
|
||||||
|
InstanceNumber = dataset.GetSingleValueOrDefault(DicomTag.InstanceNumber, 1),
|
||||||
|
InstanceTime = dataset.GetSingleValueOrDefault(DicomTag.ContentDate, string.Empty) == string.Empty ? null : dataset.GetSingleValue<DateTime>(DicomTag.ContentDate).Add(dataset.GetSingleValueOrDefault(DicomTag.ContentTime, string.Empty) == string.Empty ? TimeSpan.Zero : dataset.GetSingleValue<DateTime>(DicomTag.ContentTime).TimeOfDay),
|
||||||
|
//InstanceTime = DateTime.TryParse(dataset.GetSingleValue<string>(DicomTag.ContentDate) + dataset.GetSingleValue<string>(DicomTag.ContentTime), out DateTime dt) ? dt : null,
|
||||||
|
//InstanceTime = dataset.GetSingleValueOrDefault(DicomTag.ContentDate,(DateTime?)null)?.Add(dataset.GetSingleValueOrDefault(DicomTag.ContentTime, TimeSpan.Zero)),
|
||||||
|
//dataset.GetSingleValueOrDefault(DicomTag.ContentDate,DateTime.Now);//, DicomTag.ContentTime)
|
||||||
|
CPIStatus = false,
|
||||||
|
ImageRows = dataset.GetSingleValueOrDefault(DicomTag.Rows, 0),
|
||||||
|
ImageColumns = dataset.GetSingleValueOrDefault(DicomTag.Columns, 0),
|
||||||
|
SliceLocation = dataset.GetSingleValueOrDefault(DicomTag.SliceLocation, 0),
|
||||||
|
|
||||||
|
SliceThickness = dataset.GetSingleValueOrDefault(DicomTag.SliceThickness, string.Empty),
|
||||||
|
NumberOfFrames = dataset.GetSingleValueOrDefault(DicomTag.NumberOfFrames, 0),
|
||||||
|
PixelSpacing = dataset.GetSingleValueOrDefault(DicomTag.PixelSpacing, string.Empty),
|
||||||
|
ImagerPixelSpacing = dataset.GetSingleValueOrDefault(DicomTag.ImagerPixelSpacing, string.Empty),
|
||||||
|
FrameOfReferenceUID = dataset.GetSingleValueOrDefault(DicomTag.FrameOfReferenceUID, string.Empty),
|
||||||
|
WindowCenter = dataset.GetSingleValueOrDefault(DicomTag.WindowCenter, string.Empty),
|
||||||
|
WindowWidth = dataset.GetSingleValueOrDefault(DicomTag.WindowWidth, string.Empty),
|
||||||
|
|
||||||
|
Path = fileRelativePath
|
||||||
|
};
|
||||||
|
|
||||||
|
++findStudy.InstanceCount;
|
||||||
|
++findSerice.InstanceCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPatientNeedAdd)
|
||||||
|
{
|
||||||
|
var ss = await _patientRepository.AddAsync(findPatient);
|
||||||
|
}
|
||||||
|
if (isStudyNeedAdd)
|
||||||
|
{
|
||||||
|
var dd = await _studyRepository.AddAsync(findStudy);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await _studyRepository.BatchUpdateNoTrackingAsync(t => t.Id == findStudy.Id, t => new SCPStudy() { IsUploadFinished = false });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isSeriesNeedAdd)
|
||||||
|
{
|
||||||
|
await _seriesRepository.AddAsync(findSerice);
|
||||||
|
}
|
||||||
|
if (isInstanceNeedAdd)
|
||||||
|
{
|
||||||
|
await _instanceRepository.AddAsync(findInstance);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await _instanceRepository.BatchUpdateNoTrackingAsync(t => t.Id == instanceId, u => new SCPInstance() { Path = fileRelativePath });
|
||||||
|
}
|
||||||
|
|
||||||
|
//await _studyRepository.SaveChangesAsync();
|
||||||
|
|
||||||
|
return findStudy.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 从DICOM文件中获取使用的字符集
|
||||||
|
private string GetEncodingVaulueFromDicomFile(DicomDataset dataset, DicomTag dicomTag)
|
||||||
|
{
|
||||||
|
|
||||||
|
// 获取DICOM文件的特定元素,通常用于指示使用的字符集
|
||||||
|
var charset = dataset.GetSingleValueOrDefault(DicomTag.SpecificCharacterSet, string.Empty);
|
||||||
|
|
||||||
|
var dicomEncoding = DicomEncoding.GetEncoding(charset);
|
||||||
|
|
||||||
|
|
||||||
|
var dicomStringElement = dataset.GetDicomItem<DicomStringElement>(dicomTag);
|
||||||
|
|
||||||
|
var bytes = dicomStringElement.Buffer.Data;
|
||||||
|
|
||||||
|
|
||||||
|
return dicomEncoding.GetString(bytes);
|
||||||
|
|
||||||
|
|
||||||
|
//// 从DICOM文件中获取使用的字符集
|
||||||
|
//string filePath = "C:\\Users\\hang\\Documents\\WeChat Files\\wxid_r2imdzb7j3q922\\FileStorage\\File\\2024-05\\1.2.840.113619.2.80.169103990.5390.1271401378.4.dcm";
|
||||||
|
//DicomFile dicomFile = DicomFile.Open(filePath);
|
||||||
|
|
||||||
|
//// 获取DICOM文件的特定元素,通常用于指示使用的字符集
|
||||||
|
//var charset = dicomFile.Dataset.GetSingleValueOrDefault(DicomTag.SpecificCharacterSet, string.Empty);
|
||||||
|
|
||||||
|
//var dicomEncoding = DicomEncoding.GetEncoding(charset);
|
||||||
|
|
||||||
|
//var value = dicomFile.Dataset.GetSingleValueOrDefault(DicomTag.PatientName, string.Empty);
|
||||||
|
|
||||||
|
//var dicomStringElement = dicomFile.Dataset.GetDicomItem<DicomStringElement>(DicomTag.PatientName);
|
||||||
|
|
||||||
|
//var bytes = dicomStringElement.Buffer.Data;
|
||||||
|
|
||||||
|
//var aa= dicomEncoding.GetString(bytes);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using FellowOakDicom;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.SCP.Service
|
||||||
|
{
|
||||||
|
public interface IDicomArchiveService
|
||||||
|
{
|
||||||
|
Task<Guid> ArchiveDicomFileAsync(DicomDataset dicomDataset,Guid trialId,Guid trialSiteId, string fileRelativePath,string callingAE,string calledAE);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,442 @@
|
|||||||
|
using Aliyun.OSS;
|
||||||
|
using IRaCIS.Core.Infrastructure;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Minio.DataModel.Args;
|
||||||
|
using Minio;
|
||||||
|
using SharpCompress.Common;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security.AccessControl;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.SCP
|
||||||
|
{
|
||||||
|
public class MinIOOptions : AWSOptions
|
||||||
|
{
|
||||||
|
public int port { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AWSOptions
|
||||||
|
{
|
||||||
|
public string endPoint { get; set; }
|
||||||
|
public bool useSSL { get; set; }
|
||||||
|
public string accessKey { get; set; }
|
||||||
|
public string secretKey { get; set; }
|
||||||
|
public string bucketName { get; set; }
|
||||||
|
public string viewEndpoint { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AliyunOSSOptions
|
||||||
|
{
|
||||||
|
public string regionId { get; set; }
|
||||||
|
public string accessKeyId { get; set; }
|
||||||
|
public string accessKeySecret { get; set; }
|
||||||
|
|
||||||
|
public string internalEndpoint { get; set; }
|
||||||
|
|
||||||
|
public string endPoint { get; set; }
|
||||||
|
public string bucketName { get; set; }
|
||||||
|
|
||||||
|
public string roleArn { get; set; }
|
||||||
|
|
||||||
|
public string region { get; set; }
|
||||||
|
|
||||||
|
public string viewEndpoint { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ObjectStoreServiceOptions
|
||||||
|
{
|
||||||
|
public string ObjectStoreUse { get; set; }
|
||||||
|
public AliyunOSSOptions AliyunOSS { get; set; }
|
||||||
|
public MinIOOptions MinIO { get; set; }
|
||||||
|
|
||||||
|
public AWSOptions AWS { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ObjectStoreDTO
|
||||||
|
{
|
||||||
|
public string ObjectStoreUse { get; set; }
|
||||||
|
|
||||||
|
public AliyunOSSOptions AliyunOSS { get; set; }
|
||||||
|
|
||||||
|
public MinIOOptions MinIO { get; set; }
|
||||||
|
|
||||||
|
public AWSOptions AWS { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AliyunOSSTempToken
|
||||||
|
{
|
||||||
|
public string AccessKeyId { get; set; }
|
||||||
|
public string AccessKeySecret { get; set; }
|
||||||
|
public string SecurityToken { get; set; }
|
||||||
|
public string Expiration { get; set; }
|
||||||
|
|
||||||
|
public string Region { get; set; }
|
||||||
|
public string BucketName { get; set; }
|
||||||
|
public string ViewEndpoint { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public enum ObjectStoreUse
|
||||||
|
{
|
||||||
|
AliyunOSS = 0,
|
||||||
|
MinIO = 1,
|
||||||
|
AWS = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IOSSService
|
||||||
|
{
|
||||||
|
public Task<string> UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName, bool isFileNameAddGuid = true);
|
||||||
|
public Task<string> UploadToOSSAsync(string localFilePath, string oosFolderPath, bool isFileNameAddGuid = true);
|
||||||
|
|
||||||
|
public Task DownLoadFromOSSAsync(string ossRelativePath, string localFilePath);
|
||||||
|
|
||||||
|
public ObjectStoreServiceOptions ObjectStoreServiceOptions { get; set; }
|
||||||
|
|
||||||
|
public Task<string> GetSignedUrl(string ossRelativePath);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class OSSService : IOSSService
|
||||||
|
{
|
||||||
|
public ObjectStoreServiceOptions ObjectStoreServiceOptions { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public OSSService(IOptionsMonitor<ObjectStoreServiceOptions> options)
|
||||||
|
{
|
||||||
|
ObjectStoreServiceOptions = options.CurrentValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileStream"></param>
|
||||||
|
/// <param name="oosFolderPath"></param>
|
||||||
|
/// <param name="fileRealName"></param>
|
||||||
|
/// <param name="isFileNameAddGuid"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<string> UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName, bool isFileNameAddGuid = true)
|
||||||
|
{
|
||||||
|
var ossRelativePath = isFileNameAddGuid ? $"{oosFolderPath}/{Guid.NewGuid()}_{fileRealName}" : $"{oosFolderPath}/{fileRealName}";
|
||||||
|
//var ossRelativePath = $"{oosFolderPath}/{Guid.NewGuid()}_{fileRealName}";
|
||||||
|
//var ossRelativePath = oosFolderPath + "/" + fileRealName;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var memoryStream = new MemoryStream())
|
||||||
|
{
|
||||||
|
fileStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
|
||||||
|
fileStream.CopyTo(memoryStream);
|
||||||
|
|
||||||
|
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
|
||||||
|
|
||||||
|
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
|
||||||
|
{
|
||||||
|
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
|
||||||
|
|
||||||
|
var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.endPoint : aliConfig.internalEndpoint, aliConfig.accessKeyId, aliConfig.accessKeySecret);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 上传文件
|
||||||
|
var result = _ossClient.PutObject(aliConfig.bucketName, ossRelativePath, memoryStream);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
|
||||||
|
{
|
||||||
|
var minIOConfig = ObjectStoreServiceOptions.MinIO;
|
||||||
|
|
||||||
|
|
||||||
|
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.endPoint}:{minIOConfig.port}")
|
||||||
|
.WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var putObjectArgs = new PutObjectArgs()
|
||||||
|
.WithBucket(minIOConfig.bucketName)
|
||||||
|
.WithObject(ossRelativePath)
|
||||||
|
.WithStreamData(memoryStream)
|
||||||
|
.WithObjectSize(memoryStream.Length);
|
||||||
|
|
||||||
|
await minioClient.PutObjectAsync(putObjectArgs);
|
||||||
|
}
|
||||||
|
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
|
||||||
|
{
|
||||||
|
var minIOConfig = ObjectStoreServiceOptions.AWS;
|
||||||
|
|
||||||
|
|
||||||
|
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.endPoint}")
|
||||||
|
.WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var putObjectArgs = new PutObjectArgs()
|
||||||
|
.WithBucket(minIOConfig.bucketName)
|
||||||
|
.WithObject(ossRelativePath)
|
||||||
|
.WithStreamData(memoryStream)
|
||||||
|
.WithObjectSize(memoryStream.Length);
|
||||||
|
|
||||||
|
await minioClient.PutObjectAsync(putObjectArgs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new BusinessValidationFailedException("未定义的存储介质类型");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
|
||||||
|
throw new BusinessValidationFailedException($"上传发生异常:{ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return "/" + ossRelativePath;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localFilePath"></param>
|
||||||
|
/// <param name="oosFolderPath"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="BusinessValidationFailedException"></exception>
|
||||||
|
public async Task<string> UploadToOSSAsync(string localFilePath, string oosFolderPath, bool isFileNameAddGuid = true)
|
||||||
|
{
|
||||||
|
var localFileName = Path.GetFileName(localFilePath);
|
||||||
|
|
||||||
|
var ossRelativePath = isFileNameAddGuid ? $"{oosFolderPath}/{Guid.NewGuid()}_{localFileName}" : $"{oosFolderPath}/{localFileName}";
|
||||||
|
|
||||||
|
|
||||||
|
//var ossRelativePath = oosFolderPath + "/" + localFileName;
|
||||||
|
|
||||||
|
|
||||||
|
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
|
||||||
|
{
|
||||||
|
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
|
||||||
|
|
||||||
|
var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.endPoint : aliConfig.internalEndpoint, aliConfig.accessKeyId, aliConfig.accessKeySecret);
|
||||||
|
|
||||||
|
// 上传文件
|
||||||
|
var result = _ossClient.PutObject(aliConfig.bucketName, ossRelativePath, localFilePath);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
|
||||||
|
{
|
||||||
|
var minIOConfig = ObjectStoreServiceOptions.MinIO;
|
||||||
|
|
||||||
|
|
||||||
|
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.endPoint}:{minIOConfig.port}")
|
||||||
|
.WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var putObjectArgs = new PutObjectArgs()
|
||||||
|
.WithBucket(minIOConfig.bucketName)
|
||||||
|
.WithObject(ossRelativePath)
|
||||||
|
.WithFileName(localFilePath);
|
||||||
|
|
||||||
|
await minioClient.PutObjectAsync(putObjectArgs);
|
||||||
|
}
|
||||||
|
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
|
||||||
|
{
|
||||||
|
var minIOConfig = ObjectStoreServiceOptions.AWS;
|
||||||
|
|
||||||
|
|
||||||
|
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.endPoint}")
|
||||||
|
.WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var putObjectArgs = new PutObjectArgs()
|
||||||
|
.WithBucket(minIOConfig.bucketName)
|
||||||
|
.WithObject(ossRelativePath)
|
||||||
|
.WithFileName(localFilePath);
|
||||||
|
|
||||||
|
await minioClient.PutObjectAsync(putObjectArgs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new BusinessValidationFailedException("未定义的存储介质类型");
|
||||||
|
}
|
||||||
|
return "/" + ossRelativePath;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task DownLoadFromOSSAsync(string ossRelativePath, string localFilePath)
|
||||||
|
{
|
||||||
|
|
||||||
|
ossRelativePath = ossRelativePath.TrimStart('/');
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
|
||||||
|
{
|
||||||
|
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
|
||||||
|
|
||||||
|
var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.endPoint : aliConfig.internalEndpoint, aliConfig.accessKeyId, aliConfig.accessKeySecret);
|
||||||
|
|
||||||
|
// 上传文件
|
||||||
|
var result = _ossClient.GetObject(aliConfig.bucketName, ossRelativePath);
|
||||||
|
|
||||||
|
// 将下载的文件流保存到本地文件
|
||||||
|
using (var fs = File.OpenWrite(localFilePath))
|
||||||
|
{
|
||||||
|
result.Content.CopyTo(fs);
|
||||||
|
fs.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
|
||||||
|
{
|
||||||
|
var minIOConfig = ObjectStoreServiceOptions.MinIO;
|
||||||
|
|
||||||
|
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.endPoint}:{minIOConfig.port}")
|
||||||
|
.WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var getObjectArgs = new GetObjectArgs()
|
||||||
|
.WithBucket(minIOConfig.bucketName)
|
||||||
|
.WithObject(ossRelativePath)
|
||||||
|
.WithFile(localFilePath);
|
||||||
|
|
||||||
|
await minioClient.GetObjectAsync(getObjectArgs);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
|
||||||
|
{
|
||||||
|
var minIOConfig = ObjectStoreServiceOptions.AWS;
|
||||||
|
|
||||||
|
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.endPoint}")
|
||||||
|
.WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var getObjectArgs = new GetObjectArgs()
|
||||||
|
.WithBucket(minIOConfig.bucketName)
|
||||||
|
.WithObject(ossRelativePath)
|
||||||
|
.WithFile(localFilePath);
|
||||||
|
|
||||||
|
await minioClient.GetObjectAsync(getObjectArgs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new BusinessValidationFailedException("未定义的存储介质类型");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
|
||||||
|
throw new BusinessValidationFailedException("oss下载失败!" + ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> GetSignedUrl(string ossRelativePath)
|
||||||
|
{
|
||||||
|
ossRelativePath = ossRelativePath.TrimStart('/');
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
|
||||||
|
{
|
||||||
|
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
|
||||||
|
|
||||||
|
var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.endPoint : aliConfig.internalEndpoint, aliConfig.accessKeyId, aliConfig.accessKeySecret);
|
||||||
|
|
||||||
|
// 生成签名URL。
|
||||||
|
var req = new GeneratePresignedUriRequest(aliConfig.bucketName, ossRelativePath, SignHttpMethod.Get)
|
||||||
|
{
|
||||||
|
// 设置签名URL过期时间,默认值为3600秒。
|
||||||
|
Expiration = DateTime.Now.AddHours(1),
|
||||||
|
};
|
||||||
|
var uri = _ossClient.GeneratePresignedUri(req);
|
||||||
|
|
||||||
|
return uri.PathAndQuery;
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
|
||||||
|
{
|
||||||
|
var minIOConfig = ObjectStoreServiceOptions.MinIO;
|
||||||
|
|
||||||
|
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.endPoint}:{minIOConfig.port}")
|
||||||
|
.WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
|
||||||
|
var args = new PresignedGetObjectArgs()
|
||||||
|
.WithBucket(minIOConfig.bucketName)
|
||||||
|
.WithObject(ossRelativePath)
|
||||||
|
.WithExpiry(3600)
|
||||||
|
/*.WithHeaders(reqParams)*/;
|
||||||
|
|
||||||
|
var presignedUrl = await minioClient.PresignedGetObjectAsync(args);
|
||||||
|
|
||||||
|
Uri uri = new Uri(presignedUrl);
|
||||||
|
|
||||||
|
string relativePath = uri.PathAndQuery;
|
||||||
|
|
||||||
|
|
||||||
|
return relativePath;
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
|
||||||
|
{
|
||||||
|
var minIOConfig = ObjectStoreServiceOptions.AWS;
|
||||||
|
|
||||||
|
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.endPoint}")
|
||||||
|
.WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var args = new PresignedGetObjectArgs()
|
||||||
|
.WithBucket(minIOConfig.bucketName)
|
||||||
|
.WithObject(ossRelativePath)
|
||||||
|
.WithExpiry(3600);
|
||||||
|
|
||||||
|
var presignedUrl = await minioClient.PresignedGetObjectAsync(args);
|
||||||
|
|
||||||
|
Uri uri = new Uri(presignedUrl);
|
||||||
|
|
||||||
|
string relativePath = uri.PathAndQuery;
|
||||||
|
|
||||||
|
|
||||||
|
return relativePath;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new BusinessValidationFailedException("未定义的存储介质类型");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
|
||||||
|
throw new BusinessValidationFailedException("oss授权url失败!" + ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ObjectStoreService": {
|
||||||
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
|
"AliyunOSS": {
|
||||||
|
"regionId": "cn-shanghai",
|
||||||
|
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
|
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||||
|
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||||
|
"bucketName": "zy-irc-store",
|
||||||
|
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
||||||
|
"viewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"region": "oss-cn-shanghai"
|
||||||
|
},
|
||||||
|
|
||||||
|
"MinIO": {
|
||||||
|
"endpoint": "http://192.168.3.68",
|
||||||
|
"port": "8001",
|
||||||
|
"useSSL": false,
|
||||||
|
"accessKey": "IDFkwEpWej0b4DtiuThL",
|
||||||
|
"secretKey": "Lhuu83yMhVwu7c1SnjvGY6lq74jzpYqifK6Qtj4h",
|
||||||
|
"bucketName": "test"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"RemoteNew": "Server=us-prod-mssql-service,1433;Database=US_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||||
|
"Hangfire": "Server=us-prod-mssql-service,1433;Database=US_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||||
|
},
|
||||||
|
|
||||||
|
"BasicSystemConfig": {
|
||||||
|
|
||||||
|
"OpenUserComplexPassword": true,
|
||||||
|
|
||||||
|
"OpenSignDocumentBeforeWork": true,
|
||||||
|
|
||||||
|
"OpenTrialRelationDelete": true,
|
||||||
|
|
||||||
|
"OpenLoginLimit": true,
|
||||||
|
"LoginMaxFailCount": 5,
|
||||||
|
|
||||||
|
"LoginFailLockMinutes": 30
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
"SystemEmailSendConfig": {
|
||||||
|
"Port": 465,
|
||||||
|
"Host": "smtp.qiye.aliyun.com",
|
||||||
|
"FromEmail": "study@extimaging.com",
|
||||||
|
"FromName": "研究单位阅片系统",
|
||||||
|
"AuthorizationCode": "zhanying123",
|
||||||
|
"SiteUrl": "https://study.extimaging.com/login"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+30
-29
@@ -6,20 +6,11 @@
|
|||||||
"Microsoft.Hosting.Lifetime": "Information"
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ConnectionStrings": {
|
|
||||||
"RemoteNew": "Server=us-mssql-service,1433;Database=Prod_US_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
|
||||||
"Hangfire": "Server=us-mssql-service,1433;Database=Prod_US_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
|
||||||
|
|
||||||
//"RemoteNew": "Server=44.218.11.19,1435;Database=Prod_US_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
|
||||||
//"Hangfire": "Server=44.218.11.19,1435;Database=Prod_US_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
|
||||||
},
|
|
||||||
|
|
||||||
"ObjectStoreService": {
|
"ObjectStoreService": {
|
||||||
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
"ObjectStoreUse": "AWS",
|
|
||||||
|
|
||||||
"AliyunOSS": {
|
"AliyunOSS": {
|
||||||
"regionId": "cn-shanghai",
|
"regionId": "cn-shanghai",
|
||||||
|
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
"endPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
"endPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||||
@@ -30,24 +21,29 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"MinIO": {
|
"MinIO": {
|
||||||
"endPoint": "192.168.3.68",
|
"endPoint": "106.14.89.110",
|
||||||
"port": "8001",
|
"port": "9001",
|
||||||
"useSSL": false,
|
"useSSL": false,
|
||||||
"accessKey": "IDFkwEpWej0b4DtiuThL",
|
"accessKey": "fbStsVYCIPKHQneeqMwD",
|
||||||
"secretKey": "Lhuu83yMhVwu7c1SnjvGY6lq74jzpYqifK6Qtj4h",
|
"secretKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
|
||||||
"bucketName": "test",
|
"bucketName": "hir-test",
|
||||||
"viewEndpoint": "http://192.168.3.68:8001/test/"
|
"viewEndpoint": "http://106.14.89.110:9001/hir-test/"
|
||||||
},
|
},
|
||||||
|
|
||||||
"AWS": {
|
"AWS": {
|
||||||
"endPoint": "s3.us-east-1.amazonaws.com",
|
"endPoint": "s3.us-east-1.amazonaws.com",
|
||||||
"useSSL": true,
|
"useSSL": false,
|
||||||
"accessKey": "AKIAZQ3DRSOHFPJJ6FEU",
|
"accessKey": "AKIAZQ3DRSOHFPJJ6FEU",
|
||||||
"secretKey": "l+yjtvV7Z4jiwm/7xCYv30UeUj/SvuqqYzAwjJHf",
|
"secretKey": "l+yjtvV7Z4jiwm/7xCYv30UeUj/SvuqqYzAwjJHf",
|
||||||
"bucketName": "ei-irc-test-store",
|
"bucketName": "ei-irc-test-store",
|
||||||
"viewEndpoint": "https://ei-irc-test-store.s3.amazonaws.com/"
|
"viewEndpoint": "https://ei-irc-test-store.s3.amazonaws.com/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"RemoteNew": "Server=106.14.89.110,1435;Database=Test_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||||
|
"Hangfire": "Server=106.14.89.110,1435;Database=Test_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||||
|
},
|
||||||
"BasicSystemConfig": {
|
"BasicSystemConfig": {
|
||||||
|
|
||||||
"OpenUserComplexPassword": false,
|
"OpenUserComplexPassword": false,
|
||||||
@@ -57,23 +53,28 @@
|
|||||||
"OpenTrialRelationDelete": true,
|
"OpenTrialRelationDelete": true,
|
||||||
|
|
||||||
"OpenLoginLimit": false,
|
"OpenLoginLimit": false,
|
||||||
|
|
||||||
"LoginMaxFailCount": 5,
|
"LoginMaxFailCount": 5,
|
||||||
|
|
||||||
"LoginFailLockMinutes": 30,
|
"LoginFailLockMinutes": 30
|
||||||
"AutoLoginOutMinutes": 60
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"SystemEmailSendConfig": {
|
"SystemEmailSendConfig": {
|
||||||
"Port": 465,
|
"Port": 465,
|
||||||
"Host": "smtp.qiye.aliyun.com",
|
"Host": "smtp.qiye.aliyun.com",
|
||||||
"FromEmail": "test@extimaging.com",
|
"FromEmail": "test-study@extimaging.com",
|
||||||
"FromName": "Test_IRC",
|
"FromName": "Test_Study",
|
||||||
"AuthorizationCode": "SHzyyl2021",
|
"AuthorizationCode": "zhanying123",
|
||||||
"CompanyName": "Elevate Imaging",
|
|
||||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
|
||||||
"CompanyShortName": "Elevate Imaging",
|
|
||||||
"CompanyShortNameCN": "展影医疗"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
"SiteUrl": "http://study.test.extimaging.com/login"
|
||||||
|
},
|
||||||
|
"DicomSCPServiceConfig": {
|
||||||
|
"CalledAEList": [
|
||||||
|
"STORESCP",
|
||||||
|
"Value1",
|
||||||
|
"Value2",
|
||||||
|
"Value3"
|
||||||
|
],
|
||||||
|
"ServerPort": 11112
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ObjectStoreService": {
|
||||||
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
|
"AliyunOSS": {
|
||||||
|
"regionId": "cn-shanghai",
|
||||||
|
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
|
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||||
|
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||||
|
"bucketName": "zy-irc-uat-store",
|
||||||
|
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
||||||
|
"viewEndpoint": "https://zy-irc-uat-store.oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"region": "oss-cn-shanghai"
|
||||||
|
},
|
||||||
|
|
||||||
|
"AWS": {
|
||||||
|
"endPoint": "s3.us-east-1.amazonaws.com",
|
||||||
|
"useSSL": false,
|
||||||
|
"accessKey": "AKIAZQ3DRSOHFPJJ6FEU",
|
||||||
|
"secretKey": "l+yjtvV7Z4jiwm/7xCYv30UeUj/SvuqqYzAwjJHf",
|
||||||
|
"bucketName": "ei-irc-test-store",
|
||||||
|
"viewEndpoint": "https://ei-irc-test-store.s3.amazonaws.com/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"RemoteNew": "Server=47.117.164.182,1434;Database=Uat_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||||
|
"Hangfire": "Server=47.117.164.182,1434;Database=Uat_IRC.Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||||
|
},
|
||||||
|
"BasicSystemConfig": {
|
||||||
|
|
||||||
|
"OpenUserComplexPassword": false,
|
||||||
|
|
||||||
|
"OpenSignDocumentBeforeWork": false,
|
||||||
|
|
||||||
|
"OpenTrialRelationDelete": true,
|
||||||
|
|
||||||
|
"OpenLoginLimit": false,
|
||||||
|
"LoginMaxFailCount": 5,
|
||||||
|
|
||||||
|
"LoginFailLockMinutes": 30
|
||||||
|
},
|
||||||
|
|
||||||
|
"SystemEmailSendConfig": {
|
||||||
|
"Port": 465,
|
||||||
|
"Host": "smtp.qiye.aliyun.com",
|
||||||
|
"FromEmail": "uat-study@extimaging.com",
|
||||||
|
"FromName": "Uat_Study",
|
||||||
|
"AuthorizationCode": "zhanying123",
|
||||||
|
"SiteUrl": "http://study.uat.extimaging.com/login"
|
||||||
|
},
|
||||||
|
"DicomSCPServiceConfig": {
|
||||||
|
"CalledAEList": [
|
||||||
|
"STORESCP",
|
||||||
|
"Value1",
|
||||||
|
"Value2",
|
||||||
|
"Value3"
|
||||||
|
],
|
||||||
|
"ServerPort": 11112
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*"
|
||||||
|
}
|
||||||
@@ -17,6 +17,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRaCIS.Core.Infra.EFCore",
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRaCIS.Core.Infrastructure", "IRaCIS.Core.Infrastructure\IRaCIS.Core.Infrastructure.csproj", "{07EED0F8-08E6-46F3-ACBE-17BC1391BD4C}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRaCIS.Core.Infrastructure", "IRaCIS.Core.Infrastructure\IRaCIS.Core.Infrastructure.csproj", "{07EED0F8-08E6-46F3-ACBE-17BC1391BD4C}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IRC.Core.SCP", "IRC.Core.SCP\IRC.Core.SCP.csproj", "{ECD08F47-DC1A-484E-BB91-6CDDC8823CC5}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -51,6 +53,10 @@ Global
|
|||||||
{07EED0F8-08E6-46F3-ACBE-17BC1391BD4C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{07EED0F8-08E6-46F3-ACBE-17BC1391BD4C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{07EED0F8-08E6-46F3-ACBE-17BC1391BD4C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{07EED0F8-08E6-46F3-ACBE-17BC1391BD4C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{07EED0F8-08E6-46F3-ACBE-17BC1391BD4C}.Release|Any CPU.Build.0 = Release|Any CPU
|
{07EED0F8-08E6-46F3-ACBE-17BC1391BD4C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{ECD08F47-DC1A-484E-BB91-6CDDC8823CC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{ECD08F47-DC1A-484E-BB91-6CDDC8823CC5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{ECD08F47-DC1A-484E-BB91-6CDDC8823CC5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{ECD08F47-DC1A-484E-BB91-6CDDC8823CC5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ using IRaCIS.Core.Application.Contracts;
|
|||||||
using LoginReturnDTO = IRaCIS.Application.Contracts.LoginReturnDTO;
|
using LoginReturnDTO = IRaCIS.Application.Contracts.LoginReturnDTO;
|
||||||
using DocumentFormat.OpenXml.Spreadsheet;
|
using DocumentFormat.OpenXml.Spreadsheet;
|
||||||
using AutoMapper.QueryableExtensions;
|
using AutoMapper.QueryableExtensions;
|
||||||
|
using NetTopologySuite.Algorithm;
|
||||||
|
|
||||||
namespace IRaCIS.Api.Controllers
|
namespace IRaCIS.Api.Controllers
|
||||||
{
|
{
|
||||||
@@ -108,7 +109,7 @@ namespace IRaCIS.Api.Controllers
|
|||||||
{
|
{
|
||||||
|
|
||||||
//MFA 邮箱验证 前端传递用户Id 和MFACode
|
//MFA 邮箱验证 前端传递用户Id 和MFACode
|
||||||
if (loginUser.UserId != null && _verifyConfig.CurrentValue.OpenLoginMFA)
|
if (loginUser.UserId != null && _verifyConfig.CurrentValue.OpenLoginMFA)
|
||||||
{
|
{
|
||||||
Guid userId = (Guid)loginUser.UserId;
|
Guid userId = (Guid)loginUser.UserId;
|
||||||
|
|
||||||
@@ -226,23 +227,7 @@ namespace IRaCIS.Api.Controllers
|
|||||||
|
|
||||||
var email = returnModel.Data.BasicInfo.EMail;
|
var email = returnModel.Data.BasicInfo.EMail;
|
||||||
|
|
||||||
#region 隐藏Email
|
var hiddenEmail = EmailMaskHelper.MaskEmail(email);
|
||||||
// 找到 "@" 符号的位置
|
|
||||||
int atIndex = email.IndexOf('@');
|
|
||||||
|
|
||||||
// 替换 "@" 符号前的中间两位为星号
|
|
||||||
string visiblePart = email.Substring(0, atIndex);
|
|
||||||
|
|
||||||
int startIndex = (visiblePart.Length - 2) / 2;
|
|
||||||
|
|
||||||
// 替换中间两位字符为星号
|
|
||||||
string hiddenPartBeforeAt = visiblePart.Substring(0, startIndex) + "**" + visiblePart.Substring(startIndex + 2);
|
|
||||||
|
|
||||||
string afterAt = email.Substring(atIndex + 1);
|
|
||||||
|
|
||||||
// 组合隐藏和可见部分
|
|
||||||
string hiddenEmail = hiddenPartBeforeAt + "@" + afterAt;
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
returnModel.Data.BasicInfo.EMail = hiddenEmail;
|
returnModel.Data.BasicInfo.EMail = hiddenEmail;
|
||||||
|
|
||||||
|
|||||||
@@ -308,11 +308,28 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 提交结构化录入并签名
|
/// PM签名一致性分析临床数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="opt"></param>
|
/// <param name="opt"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
[HttpPost, Route("Inspection/ReadingClinicalData/SignConsistencyAnalysisReadingClinicalData")]
|
||||||
|
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||||
|
|
||||||
|
[UnitOfWork]
|
||||||
|
public async Task<IResponseOutput> SignConsistencyAnalysisReadingClinicalData(DataInspectionDto<SignConsistencyAnalysisReadingClinicalDataInDto> opt)
|
||||||
|
{
|
||||||
|
var singid = await _inspectionService.RecordSing(opt.SignInfo);
|
||||||
|
var result = await _readingClinicalDataService.SignConsistencyAnalysisReadingClinicalData(opt.Data);
|
||||||
|
await _inspectionService.CompletedSign(singid, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 提交结构化录入并签名
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opt"></param>
|
||||||
|
/// <returns></returns>
|
||||||
[HttpPost, Route("Inspection/ClinicalAnswer/SubmitClinicalFormAndSign")]
|
[HttpPost, Route("Inspection/ClinicalAnswer/SubmitClinicalFormAndSign")]
|
||||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||||
|
|
||||||
@@ -402,6 +419,19 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[HttpPost, Route("Inspection/configTrialBasicInfo/ConfigTrialPACSInfoConfirm")]
|
||||||
|
[UnitOfWork]
|
||||||
|
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "BeforeOngoingCantOpt" })]
|
||||||
|
public async Task<IResponseOutput> ConfigTrialPACSInfoConfirm(DataInspectionDto<TrialPACSConfig> opt)
|
||||||
|
{
|
||||||
|
opt.Data.IsTrialPACSConfirmed = true;
|
||||||
|
var singid = await _inspectionService.RecordSing(opt.SignInfo);
|
||||||
|
var result = await _trialConfigService.ConfigTrialPACSInfo(opt.Data);
|
||||||
|
await _inspectionService.CompletedSign(singid, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 签名确认
|
/// 签名确认
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -10,8 +10,7 @@ using IRaCIS.Core.Application.Contracts.Dicom;
|
|||||||
using IRaCIS.Core.Application.Contracts.Dicom.DTO;
|
using IRaCIS.Core.Application.Contracts.Dicom.DTO;
|
||||||
using IRaCIS.Core.Application.Filter;
|
using IRaCIS.Core.Application.Filter;
|
||||||
using IRaCIS.Core.Application.Helper;
|
using IRaCIS.Core.Application.Helper;
|
||||||
using IRaCIS.Core.Application.MediatR.CommandAndQueries;
|
using IRaCIS.Core.Application.MassTransit.Command;
|
||||||
using IRaCIS.Core.Application.MediatR.Handlers;
|
|
||||||
using IRaCIS.Core.Application.Service;
|
using IRaCIS.Core.Application.Service;
|
||||||
using IRaCIS.Core.Application.Service.ImageAndDoc;
|
using IRaCIS.Core.Application.Service.ImageAndDoc;
|
||||||
using IRaCIS.Core.Application.Service.Reading.Dto;
|
using IRaCIS.Core.Application.Service.Reading.Dto;
|
||||||
@@ -21,7 +20,7 @@ using IRaCIS.Core.Infra.EFCore;
|
|||||||
using IRaCIS.Core.Infrastructure;
|
using IRaCIS.Core.Infrastructure;
|
||||||
using IRaCIS.Core.Infrastructure.Extention;
|
using IRaCIS.Core.Infrastructure.Extention;
|
||||||
using MassTransit;
|
using MassTransit;
|
||||||
using MediatR;
|
using MassTransit.Mediator;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Cors.Infrastructure;
|
using Microsoft.AspNetCore.Cors.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
@@ -232,9 +231,12 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
{
|
{
|
||||||
public IMapper _mapper { get; set; }
|
public IMapper _mapper { get; set; }
|
||||||
public IUserInfo _userInfo { get; set; }
|
public IUserInfo _userInfo { get; set; }
|
||||||
|
|
||||||
|
|
||||||
private readonly IMediator _mediator;
|
private readonly IMediator _mediator;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public IStringLocalizer _localizer { get; set; }
|
public IStringLocalizer _localizer { get; set; }
|
||||||
|
|
||||||
|
|
||||||
@@ -266,11 +268,6 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
[FromServices] IRepository<StudyMonitor> _studyMonitorRepository)
|
[FromServices] IRepository<StudyMonitor> _studyMonitorRepository)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (_provider.Get<List<SystemAnonymization>>(StaticData.Anonymize.Anonymize_AddFixedFiled).Value == null)
|
|
||||||
{
|
|
||||||
await _mediator.Send(new AnonymizeCacheRequest());
|
|
||||||
}
|
|
||||||
|
|
||||||
var savedInfo = _studyService.GetSaveToDicomInfo(preArchiveStudyCommand.SubjectVisitId);
|
var savedInfo = _studyService.GetSaveToDicomInfo(preArchiveStudyCommand.SubjectVisitId);
|
||||||
|
|
||||||
var studyMonitor = new StudyMonitor()
|
var studyMonitor = new StudyMonitor()
|
||||||
@@ -530,6 +527,7 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
studyMonitor.StudyCode = noneDicomStudy.StudyCode;
|
studyMonitor.StudyCode = noneDicomStudy.StudyCode;
|
||||||
studyMonitor.ArchiveFinishedTime = DateTime.Now;
|
studyMonitor.ArchiveFinishedTime = DateTime.Now;
|
||||||
studyMonitor.IP = _userInfo.IP;
|
studyMonitor.IP = _userInfo.IP;
|
||||||
|
studyMonitor.IsSuccess = true;
|
||||||
|
|
||||||
await _repository.SaveChangesAsync();
|
await _repository.SaveChangesAsync();
|
||||||
|
|
||||||
@@ -742,11 +740,16 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
//---请保证上传数据符合模板文件中的样式,且存在有效数据。
|
//---请保证上传数据符合模板文件中的样式,且存在有效数据。
|
||||||
return ResponseOutput.NotOk(_localizer["UploadDownLoad_InvalidData"]);
|
return ResponseOutput.NotOk(_localizer["UploadDownLoad_InvalidData"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
await _mediator.Send(new ConsistencyVerificationRequest() { ETCList = etcCheckList, TrialId = trialId });
|
|
||||||
|
// 适合获取结果的
|
||||||
|
//var client = _mediator.CreateRequestClient<ConsistenCheckCommand>();
|
||||||
|
//await client.GetResponse<ConsistenCheckResult>(new ConsistenCheckCommand() { ETCList = etcCheckList, TrialId = trialId });
|
||||||
|
|
||||||
|
//不获取结果,不用定义返回类型
|
||||||
|
await _mediator.Send(new ConsistenCheckCommand() { ETCList = etcCheckList, TrialId = trialId });
|
||||||
|
|
||||||
return ResponseOutput.Ok();
|
return ResponseOutput.Ok();
|
||||||
|
|
||||||
@@ -888,89 +891,6 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region 废弃
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 下载多个医生的所有附件
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="doctorIds"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[Obsolete]
|
|
||||||
[HttpPost, Route("file/downloadDoctorAttachments")]
|
|
||||||
public async Task<IResponseOutput<UploadFileInfoDTO>> DownloadAttachment(Guid[] doctorIds)
|
|
||||||
{
|
|
||||||
|
|
||||||
var path = await _fileService.CreateDoctorsAllAttachmentZip(doctorIds);
|
|
||||||
|
|
||||||
return ResponseOutput.Ok(new UploadFileInfoDTO
|
|
||||||
{
|
|
||||||
FilePath = path,
|
|
||||||
FullFilePath = path + "?access_token=" + HttpContext.Request.Headers["Authorization"].ToString().Substring(7)
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 下载指定医生的指定附件
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="doctorId">医生Id</param>
|
|
||||||
/// <param name="attachmentIds">要下载的附件Id</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[HttpPost, Route("file/downloadByAttachmentId/{doctorId}")]
|
|
||||||
[Obsolete]
|
|
||||||
public async Task<IResponseOutput<UploadFileInfoDTO>> DownloadAttachmentById(Guid doctorId, Guid[] attachmentIds)
|
|
||||||
{
|
|
||||||
var path = await _fileService.CreateZipPackageByAttachment(doctorId, attachmentIds);
|
|
||||||
return ResponseOutput.Ok(new UploadFileInfoDTO
|
|
||||||
{
|
|
||||||
FilePath = await _fileService.CreateZipPackageByAttachment(doctorId, attachmentIds),
|
|
||||||
FullFilePath = path + "?access_token=" + HttpContext.Request.Headers["Authorization"].ToString().Substring(7)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 下载医生官方简历 首页 区分 中文和英文
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="language"></param>
|
|
||||||
/// <param name="doctorIds"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[HttpPost, Route("file/downloadOfficialCV/{language}")]
|
|
||||||
[Obsolete]
|
|
||||||
public async Task<IResponseOutput<UploadFileInfoDTO>> DownloadOfficialResume(int language, Guid[] doctorIds)
|
|
||||||
{
|
|
||||||
|
|
||||||
var path = await _fileService.CreateDoctorsAllAttachmentZip(doctorIds);
|
|
||||||
return ResponseOutput.Ok(new UploadFileInfoDTO
|
|
||||||
{
|
|
||||||
FilePath = await _fileService.CreateOfficialResumeZip(language, doctorIds),
|
|
||||||
FullFilePath = path + "?access_token=" + HttpContext.Request.Headers["Authorization"].ToString().Substring(7)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 入组 项目下载简历
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="language"></param>
|
|
||||||
/// <param name="trialId"></param>
|
|
||||||
/// <param name="doctorIdArray"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[HttpPost, Route("enroll/downloadResume/{trialId:guid}/{language}")]
|
|
||||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
|
||||||
[AllowAnonymous]
|
|
||||||
[Obsolete]
|
|
||||||
public async Task<IResponseOutput<string>> DownloadResume(int language, Guid trialId, Guid[] doctorIdArray)
|
|
||||||
{
|
|
||||||
var zipPath = await _fileService.CreateOfficialResumeZip(language, doctorIdArray);
|
|
||||||
|
|
||||||
return ResponseOutput.Ok(zipPath);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
@@ -64,23 +64,23 @@
|
|||||||
<PackageReference Include="aliyun-net-sdk-sts" Version="3.1.2" />
|
<PackageReference Include="aliyun-net-sdk-sts" Version="3.1.2" />
|
||||||
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
|
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
|
||||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="9.0.0" />
|
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="9.0.0" />
|
||||||
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
|
<PackageReference Include="ConfigMapFileProvider" Version="2.0.1" />
|
||||||
<PackageReference Include="EasyCaching.Interceptor.Castle" Version="1.9.2" />
|
<PackageReference Include="EasyCaching.Interceptor.Castle" Version="1.9.2" />
|
||||||
<PackageReference Include="EasyCaching.Serialization.MessagePack" Version="1.9.2">
|
<PackageReference Include="EasyCaching.Serialization.MessagePack" Version="1.9.2">
|
||||||
<TreatAsUsed>true</TreatAsUsed>
|
<TreatAsUsed>true</TreatAsUsed>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.12" />
|
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.14" />
|
||||||
<PackageReference Include="Hangfire.Dashboard.BasicAuthorization" Version="1.0.2" />
|
<PackageReference Include="Hangfire.Dashboard.BasicAuthorization" Version="1.0.2" />
|
||||||
<PackageReference Include="Hangfire.SqlServer" Version="1.8.12" />
|
<PackageReference Include="Hangfire.InMemory" Version="0.10.3" />
|
||||||
|
<PackageReference Include="Hangfire.SqlServer" Version="1.8.14" />
|
||||||
<PackageReference Include="Invio.Extensions.Authentication.JwtBearer" Version="2.0.1" />
|
<PackageReference Include="Invio.Extensions.Authentication.JwtBearer" Version="2.0.1" />
|
||||||
<PackageReference Include="LogDashboard" Version="1.4.8" />
|
<PackageReference Include="LogDashboard" Version="1.4.8" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.5" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.6" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.20.1" />
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.20.1" />
|
||||||
<PackageReference Include="Serilog.AspNetCore" Version="8.0.1" />
|
<PackageReference Include="Serilog.AspNetCore" Version="8.0.1" />
|
||||||
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.0.3" />
|
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.0.3" />
|
||||||
<PackageReference Include="Serilog.Sinks.Email" Version="3.0.0" />
|
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.6.2" />
|
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.6.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -167,6 +167,13 @@
|
|||||||
<param name="opt"></param>
|
<param name="opt"></param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="M:IRaCIS.Core.API.Controllers.InspectionController.SignConsistencyAnalysisReadingClinicalData(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Core.Application.Service.Reading.Dto.SignConsistencyAnalysisReadingClinicalDataInDto})">
|
||||||
|
<summary>
|
||||||
|
PM签名一致性分析临床数据
|
||||||
|
</summary>
|
||||||
|
<param name="opt"></param>
|
||||||
|
<returns></returns>
|
||||||
|
</member>
|
||||||
<member name="M:IRaCIS.Core.API.Controllers.InspectionController.SubmitClinicalFormAndSign(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Core.Application.Service.Reading.Dto.SubmitClinicalFormInDto})">
|
<member name="M:IRaCIS.Core.API.Controllers.InspectionController.SubmitClinicalFormAndSign(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Core.Application.Service.Reading.Dto.SubmitClinicalFormInDto})">
|
||||||
<summary>
|
<summary>
|
||||||
提交结构化录入并签名
|
提交结构化录入并签名
|
||||||
@@ -319,38 +326,6 @@
|
|||||||
<param name="_attachmentrepository"></param>
|
<param name="_attachmentrepository"></param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:IRaCIS.Core.API.Controllers.FileController.DownloadAttachment(System.Guid[])">
|
|
||||||
<summary>
|
|
||||||
下载多个医生的所有附件
|
|
||||||
</summary>
|
|
||||||
<param name="doctorIds"></param>
|
|
||||||
<returns></returns>
|
|
||||||
</member>
|
|
||||||
<member name="M:IRaCIS.Core.API.Controllers.FileController.DownloadAttachmentById(System.Guid,System.Guid[])">
|
|
||||||
<summary>
|
|
||||||
下载指定医生的指定附件
|
|
||||||
</summary>
|
|
||||||
<param name="doctorId">医生Id</param>
|
|
||||||
<param name="attachmentIds">要下载的附件Id</param>
|
|
||||||
<returns></returns>
|
|
||||||
</member>
|
|
||||||
<member name="M:IRaCIS.Core.API.Controllers.FileController.DownloadOfficialResume(System.Int32,System.Guid[])">
|
|
||||||
<summary>
|
|
||||||
下载医生官方简历 首页 区分 中文和英文
|
|
||||||
</summary>
|
|
||||||
<param name="language"></param>
|
|
||||||
<param name="doctorIds"></param>
|
|
||||||
<returns></returns>
|
|
||||||
</member>
|
|
||||||
<member name="M:IRaCIS.Core.API.Controllers.FileController.DownloadResume(System.Int32,System.Guid,System.Guid[])">
|
|
||||||
<summary>
|
|
||||||
入组 项目下载简历
|
|
||||||
</summary>
|
|
||||||
<param name="language"></param>
|
|
||||||
<param name="trialId"></param>
|
|
||||||
<param name="doctorIdArray"></param>
|
|
||||||
<returns></returns>
|
|
||||||
</member>
|
|
||||||
<member name="M:IRaCIS.Core.API.Controllers.UploadDownLoadController.DownloadCommonFile(System.String,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.CommonDocument})">
|
<member name="M:IRaCIS.Core.API.Controllers.UploadDownLoadController.DownloadCommonFile(System.String,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.CommonDocument})">
|
||||||
<summary> 通用文件下载 </summary>
|
<summary> 通用文件下载 </summary>
|
||||||
</member>
|
</member>
|
||||||
|
|||||||
+101
-22
@@ -4,8 +4,6 @@ using Microsoft.AspNetCore.Hosting;
|
|||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using MediatR;
|
|
||||||
using IRaCIS.Core.Application.MediatR.Handlers;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MassTransit;
|
using MassTransit;
|
||||||
using MassTransit.NewIdProviders;
|
using MassTransit.NewIdProviders;
|
||||||
@@ -28,6 +26,13 @@ using FellowOakDicom.Network;
|
|||||||
using IRaCIS.Core.Application.Service.ImageAndDoc;
|
using IRaCIS.Core.Application.Service.ImageAndDoc;
|
||||||
using IP2Region.Net.Abstractions;
|
using IP2Region.Net.Abstractions;
|
||||||
using IP2Region.Net.XDB;
|
using IP2Region.Net.XDB;
|
||||||
|
using IRaCIS.Core.Application.BusinessFilter;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using IRaCIS.Core.Infrastructure.Extention;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Microsoft.AspNetCore.Diagnostics;
|
||||||
|
using IRaCIS.Core.Application.MassTransit.Command;
|
||||||
|
using IRaCIS.Core.Application.MassTransit.Consumer;
|
||||||
|
|
||||||
|
|
||||||
#region 获取环境变量
|
#region 获取环境变量
|
||||||
@@ -76,8 +81,8 @@ if (urlsIndex > -1)
|
|||||||
|
|
||||||
NewId.SetProcessIdProvider(new CurrentProcessIdProvider());
|
NewId.SetProcessIdProvider(new CurrentProcessIdProvider());
|
||||||
|
|
||||||
builder.Configuration.AddJsonFile("appsettings.json", false, true)
|
builder.Configuration.AddJsonFile(ConfigMapFileProvider.FromRelativePath(""), "appsettings.json", false, true)
|
||||||
.AddJsonFile($"appsettings.{enviromentName}.json", false, true);
|
.AddJsonFile(ConfigMapFileProvider.FromRelativePath(""), $"appsettings.{enviromentName}.json", false, true);
|
||||||
|
|
||||||
builder.Host
|
builder.Host
|
||||||
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
|
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
|
||||||
@@ -104,11 +109,9 @@ builder.Services.AddControllers(options =>
|
|||||||
options.Filters.Add<ModelActionFilter>();
|
options.Filters.Add<ModelActionFilter>();
|
||||||
options.Filters.Add<ProjectExceptionFilter>();
|
options.Filters.Add<ProjectExceptionFilter>();
|
||||||
options.Filters.Add<UnitOfWorkFilter>();
|
options.Filters.Add<UnitOfWorkFilter>();
|
||||||
|
options.Filters.Add<EncreptApiResultFilter>(10);
|
||||||
|
options.Filters.Add<LimitUserRequestAuthorization>();
|
||||||
|
|
||||||
if (_configuration.GetSection("BasicSystemConfig").GetValue<bool>("OpenLoginLimit"))
|
|
||||||
{
|
|
||||||
options.Filters.Add<LimitUserRequestAuthorization>();
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
})
|
||||||
.AddNewtonsoftJsonSetup(builder.Services); // NewtonsoftJson 序列化 处理
|
.AddNewtonsoftJsonSetup(builder.Services); // NewtonsoftJson 序列化 处理
|
||||||
@@ -117,6 +120,8 @@ builder.Services.AddOptions().Configure<SystemEmailSendConfig>(_configuration.Ge
|
|||||||
builder.Services.AddOptions().Configure<ServiceVerifyConfigOption>(_configuration.GetSection("BasicSystemConfig"));
|
builder.Services.AddOptions().Configure<ServiceVerifyConfigOption>(_configuration.GetSection("BasicSystemConfig"));
|
||||||
builder.Services.AddOptions().Configure<AliyunOSSOptions>(_configuration.GetSection("AliyunOSS"));
|
builder.Services.AddOptions().Configure<AliyunOSSOptions>(_configuration.GetSection("AliyunOSS"));
|
||||||
builder.Services.AddOptions().Configure<ObjectStoreServiceOptions>(_configuration.GetSection("ObjectStoreService"));
|
builder.Services.AddOptions().Configure<ObjectStoreServiceOptions>(_configuration.GetSection("ObjectStoreService"));
|
||||||
|
builder.Services.AddOptions().Configure<EncreptResponseOption>(_configuration.GetSection("EncrypteResponseConfig"));
|
||||||
|
builder.Services.AddOptions().Configure<SystemPacsConfig>(_configuration.GetSection("SystemPacsConfig"));
|
||||||
|
|
||||||
|
|
||||||
//动态WebApi + UnifiedApiResultFilter 省掉控制器代码
|
//动态WebApi + UnifiedApiResultFilter 省掉控制器代码
|
||||||
@@ -133,7 +138,28 @@ builder.Services.AddSwaggerSetup();
|
|||||||
builder.Services.AddJWTAuthSetup(_configuration);
|
builder.Services.AddJWTAuthSetup(_configuration);
|
||||||
|
|
||||||
// MediatR 进程内消息 事件解耦 从程序集中 注册命令和handler对应关系
|
// MediatR 进程内消息 事件解耦 从程序集中 注册命令和handler对应关系
|
||||||
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<ConsistencyVerificationHandler>());
|
//builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<ConsistencyVerificationHandler>());
|
||||||
|
|
||||||
|
#region MassTransit
|
||||||
|
//masstransit组件 也支持MediatR 中介者模式,但是支持分布式,考虑后续,所以在次替代MediatR
|
||||||
|
builder.Services.AddMediator(cfg =>
|
||||||
|
{
|
||||||
|
cfg.AddConsumer<ConsistencyCheckConsumer>();
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.Services.AddMassTransit(cfg =>
|
||||||
|
{
|
||||||
|
cfg.UsingInMemory();
|
||||||
|
});
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region FusionCache
|
||||||
|
|
||||||
|
builder.Services.AddFusionCache();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
// EasyCaching 缓存
|
// EasyCaching 缓存
|
||||||
builder.Services.AddEasyCachingSetup(_configuration);
|
builder.Services.AddEasyCachingSetup(_configuration);
|
||||||
|
|
||||||
@@ -163,6 +189,8 @@ builder.Services.AddSingleton<IUserIdProvider, IRaCISUserIdProvider>();
|
|||||||
|
|
||||||
builder.Services.AddSingleton<ISearcher>(new Searcher(CachePolicy.Content, Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources, "ip2region.xdb")));
|
builder.Services.AddSingleton<ISearcher>(new Searcher(CachePolicy.Content, Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources, "ip2region.xdb")));
|
||||||
|
|
||||||
|
//builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
|
||||||
|
//builder.Services.AddProblemDetails();
|
||||||
|
|
||||||
#region 历史废弃配置
|
#region 历史废弃配置
|
||||||
//builder.Services.AddMemoryCache();
|
//builder.Services.AddMemoryCache();
|
||||||
@@ -189,6 +217,56 @@ var env = app.Environment;
|
|||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
// Configure the HTTP request pipeline.
|
||||||
|
|
||||||
|
#region 异常处理 全局业务异常已统一处理了,非业务错误会来到这里 400 -500状态码
|
||||||
|
|
||||||
|
|
||||||
|
//app.UseStatusCodePagesWithReExecute("/Error/{0}");
|
||||||
|
|
||||||
|
app.UseStatusCodePages(async context =>
|
||||||
|
{
|
||||||
|
var code = context.HttpContext.Response.StatusCode;
|
||||||
|
context.HttpContext.Response.ContentType = "application/json";
|
||||||
|
if (code < 500)
|
||||||
|
{
|
||||||
|
await context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk($"Client error, actual request error status code({code})")));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//ResultFilter 里面的异常并不会到这里
|
||||||
|
await context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject((ResponseOutput.NotOk($"Server error , actual request error status code({code})"))));
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
//app.UseExceptionHandler(o => { });
|
||||||
|
|
||||||
|
//这里没生效,原因未知,官方文档也是这种写法,也用了GlobalExceptionHandler 尝试,还是不行,怀疑框架bug
|
||||||
|
//app.UseExceptionHandler(configure =>
|
||||||
|
//{
|
||||||
|
// configure.Run(async context =>
|
||||||
|
// {
|
||||||
|
// var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>();
|
||||||
|
//var ex = exceptionHandlerPathFeature?.Error;
|
||||||
|
//context.Response.ContentType = "application/json";
|
||||||
|
|
||||||
|
//if (ex != null)
|
||||||
|
//{
|
||||||
|
// var errorInfo = $"Exception: {ex.Message}[{ex.StackTrace}]" + (ex.InnerException != null ? $" InnerException: {ex.InnerException.Message}[{ex.InnerException.StackTrace}]" : "");
|
||||||
|
|
||||||
|
// await context.Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk($"{ex?.Message}")));
|
||||||
|
|
||||||
|
// Log.Logger.Error(errorInfo);
|
||||||
|
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
// });
|
||||||
|
//});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
//本地化
|
//本地化
|
||||||
app.UseLocalization();
|
app.UseLocalization();
|
||||||
|
|
||||||
@@ -197,12 +275,11 @@ app.UseForwardedHeaders();
|
|||||||
//响应压缩
|
//响应压缩
|
||||||
app.UseResponseCompression();
|
app.UseResponseCompression();
|
||||||
|
|
||||||
//app.UseCors(t => t.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
|
|
||||||
|
|
||||||
//不需要 token 访问的静态文件 wwwroot css, JavaScript, and images don't require authentication.
|
//不需要 token 访问的静态文件 wwwroot css, JavaScript, and images don't require authentication.
|
||||||
app.UseStaticFiles();
|
app.UseStaticFiles();
|
||||||
|
|
||||||
app.UseMiddleware<MultiDiskStaticFilesMiddleware>();
|
|
||||||
|
|
||||||
//LogDashboard
|
//LogDashboard
|
||||||
app.UseLogDashboard("/LogDashboard");
|
app.UseLogDashboard("/LogDashboard");
|
||||||
@@ -210,22 +287,24 @@ app.UseLogDashboard("/LogDashboard");
|
|||||||
//hangfire
|
//hangfire
|
||||||
app.UseHangfireConfig(env);
|
app.UseHangfireConfig(env);
|
||||||
|
|
||||||
|
#region 暂时废弃
|
||||||
|
|
||||||
|
//app.UseMiddleware<MultiDiskStaticFilesMiddleware>();
|
||||||
////限流 中间件
|
////限流 中间件
|
||||||
//app.UseIpRateLimiting();
|
//app.UseIpRateLimiting();
|
||||||
|
//if (env.IsDevelopment())
|
||||||
|
//{
|
||||||
|
// app.UseDeveloperExceptionPage();
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// //app.UseHsts();
|
||||||
|
//}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (env.IsDevelopment())
|
|
||||||
{
|
|
||||||
app.UseDeveloperExceptionPage();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//app.UseHsts();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 特殊异常处理 比如 404
|
|
||||||
app.UseStatusCodePagesWithReExecute("/Error/{0}");
|
|
||||||
|
|
||||||
SwaggerSetup.Configure(app, env);
|
SwaggerSetup.Configure(app, env);
|
||||||
|
|
||||||
@@ -297,7 +376,7 @@ try
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
var server = DicomServerFactory.Create<CStoreSCPService>(11112,userState: app.Services);
|
var server = DicomServerFactory.Create<CStoreSCPService>(11112, userState: app.Services);
|
||||||
|
|
||||||
app.Run();
|
app.Run();
|
||||||
|
|
||||||
|
|||||||
@@ -54,11 +54,11 @@
|
|||||||
},
|
},
|
||||||
"applicationUrl": "http://localhost:6100"
|
"applicationUrl": "http://localhost:6100"
|
||||||
},
|
},
|
||||||
"IRaCIS.US_IRC": {
|
"IRaCIS.US_Uat_IRC": {
|
||||||
"commandName": "Project",
|
"commandName": "Project",
|
||||||
"launchBrowser": true,
|
"launchBrowser": true,
|
||||||
"environmentVariables": {
|
"environmentVariables": {
|
||||||
"ASPNETCORE_ENVIRONMENT": "US_IRC"
|
"ASPNETCORE_ENVIRONMENT": "US_Uat_IRC"
|
||||||
},
|
},
|
||||||
"applicationUrl": "http://localhost:6100"
|
"applicationUrl": "http://localhost:6100"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.AspNetCore.Builder;
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Localization;
|
using Microsoft.AspNetCore.Localization;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
@@ -12,8 +13,9 @@ namespace IRaCIS.Core.API
|
|||||||
{
|
{
|
||||||
var supportedCultures = new List<CultureInfo>
|
var supportedCultures = new List<CultureInfo>
|
||||||
{
|
{
|
||||||
new CultureInfo("en-US"),
|
|
||||||
new CultureInfo("zh-CN")
|
new CultureInfo(StaticData.CultureInfo.en_US),
|
||||||
|
new CultureInfo(StaticData.CultureInfo.zh_CN)
|
||||||
};
|
};
|
||||||
|
|
||||||
var options = new RequestLocalizationOptions
|
var options = new RequestLocalizationOptions
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using AutoMapper.EquivalencyExpression;
|
using AutoMapper.EquivalencyExpression;
|
||||||
using IRaCIS.Core.Application.Service;
|
using IRaCIS.Core.Application.Service;
|
||||||
|
using IRaCIS.Core.Domain.Models;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace IRaCIS.Core.API
|
namespace IRaCIS.Core.API
|
||||||
@@ -14,11 +15,15 @@ namespace IRaCIS.Core.API
|
|||||||
//AutoMapper.Collection.EntityFrameworkCore
|
//AutoMapper.Collection.EntityFrameworkCore
|
||||||
automapper.AddCollectionMappers();
|
automapper.AddCollectionMappers();
|
||||||
|
|
||||||
|
|
||||||
|
// 全局忽略 DomainEvents 属性
|
||||||
|
automapper.AddGlobalIgnore(nameof(Entity.DomainEvents));
|
||||||
|
|
||||||
#region 会使 IncludeMembers 失效 不能全局使用
|
#region 会使 IncludeMembers 失效 不能全局使用
|
||||||
//mapping an EntityFramework Core DbContext-object.
|
//mapping an EntityFramework Core DbContext-object.
|
||||||
//automapper.UseEntityFrameworkCoreModel<IRaCISDBContext>(services);
|
//automapper.UseEntityFrameworkCoreModel<IRaCISDBContext>(services);
|
||||||
|
|
||||||
|
|
||||||
//automapper.ForAllMaps((a, b) => b.ForAllMembers(opt => opt.Condition((src, dest, srcMember, desMenber) =>
|
//automapper.ForAllMaps((a, b) => b.ForAllMembers(opt => opt.Condition((src, dest, srcMember, desMenber) =>
|
||||||
//{
|
//{
|
||||||
// //// Can test When Guid? -> Guid if source is null will change to Guid.Empty
|
// //// Can test When Guid? -> Guid if source is null will change to Guid.Empty
|
||||||
@@ -27,7 +32,7 @@ namespace IRaCIS.Core.API
|
|||||||
// // not want to map a null Guid? value to db Guid value
|
// // not want to map a null Guid? value to db Guid value
|
||||||
//})));
|
//})));
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
}, typeof(QCConfig).Assembly);
|
}, typeof(QCConfig).Assembly);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ using System.Linq;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using IRaCIS.Core.Domain.Models;
|
using IRaCIS.Core.Domain.Models;
|
||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
using MediatR;
|
|
||||||
using IRaCIS.Application.Services;
|
using IRaCIS.Application.Services;
|
||||||
using IRaCIS.Application.Interfaces;
|
using IRaCIS.Application.Interfaces;
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
@@ -55,8 +54,8 @@ namespace IRaCIS.Core.API
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
containerBuilder.RegisterType<HttpContextAccessor>().As<IHttpContextAccessor>().SingleInstance();
|
//containerBuilder.RegisterType<HttpContextAccessor>().As<IHttpContextAccessor>().SingleInstance();
|
||||||
containerBuilder.RegisterType<UserInfo>().As<IUserInfo>().InstancePerLifetimeScope();
|
//containerBuilder.RegisterType<UserInfo>().As<IUserInfo>().InstancePerLifetimeScope();
|
||||||
|
|
||||||
|
|
||||||
//注册hangfire任务 依赖注入
|
//注册hangfire任务 依赖注入
|
||||||
|
|||||||
@@ -1,11 +1,17 @@
|
|||||||
using Hangfire.SqlServer;
|
using Castle.Core.Logging;
|
||||||
|
using EntityFramework.Exceptions.SqlServer;
|
||||||
|
using Hangfire.SqlServer;
|
||||||
using IRaCIS.Core.Application.Triggers;
|
using IRaCIS.Core.Application.Triggers;
|
||||||
|
using IRaCIS.Core.Domain.Share;
|
||||||
using IRaCIS.Core.Infra.EFCore;
|
using IRaCIS.Core.Infra.EFCore;
|
||||||
|
using IRaCIS.Core.Infra.EFCore.Interceptor;
|
||||||
using Medallion.Threading;
|
using Medallion.Threading;
|
||||||
using Medallion.Threading.SqlServer;
|
using Medallion.Threading.SqlServer;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using StackExchange.Redis;
|
using StackExchange.Redis;
|
||||||
|
|
||||||
namespace IRaCIS.Core.API
|
namespace IRaCIS.Core.API
|
||||||
@@ -14,18 +20,35 @@ namespace IRaCIS.Core.API
|
|||||||
{
|
{
|
||||||
public static void AddEFSetup( this IServiceCollection services, IConfiguration configuration)
|
public static void AddEFSetup( this IServiceCollection services, IConfiguration configuration)
|
||||||
{
|
{
|
||||||
//services.AddScoped<DbContext, IRaCISDBContext>();
|
|
||||||
|
services.AddHttpContextAccessor();
|
||||||
|
services.AddScoped<IUserInfo, UserInfo>();
|
||||||
|
services.AddScoped<ISaveChangesInterceptor, AuditEntityInterceptor>();
|
||||||
|
services.AddScoped<ISaveChangesInterceptor, DispatchDomainEventsInterceptor>();
|
||||||
|
|
||||||
|
|
||||||
|
// First, register a pooling context factory as a Singleton service, as usual:
|
||||||
|
|
||||||
//这个注入没有成功--注入是没问题的,构造函数也只是支持参数就好,错在注入的地方不能写DbContext
|
//这个注入没有成功--注入是没问题的,构造函数也只是支持参数就好,错在注入的地方不能写DbContext
|
||||||
//Web程序中通过重用池中DbContext实例可提高高并发场景下的吞吐量, 这在概念上类似于ADO.NET Provider原生的连接池操作方式,具有节省DbContext实例化成本的优点
|
//Web程序中通过重用池中DbContext实例可提高高并发场景下的吞吐量, 这在概念上类似于ADO.NET Provider原生的连接池操作方式,具有节省DbContext实例化成本的优点
|
||||||
services.AddDbContext<IRaCISDBContext>(options =>
|
services.AddDbContext<IRaCISDBContext>((sp, options) =>
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// 在控制台
|
||||||
|
//public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); });
|
||||||
|
var logFactory = LoggerFactory.Create(builder => { builder.AddDebug(); });
|
||||||
|
|
||||||
options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value,
|
options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value,
|
||||||
contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure());
|
contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure());
|
||||||
|
|
||||||
|
options.UseLoggerFactory(logFactory);
|
||||||
|
|
||||||
|
options.UseExceptionProcessor();
|
||||||
|
|
||||||
options.EnableSensitiveDataLogging();
|
options.EnableSensitiveDataLogging();
|
||||||
|
|
||||||
options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor());
|
options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor());
|
||||||
|
options.AddInterceptors(sp.GetServices<ISaveChangesInterceptor>());
|
||||||
|
|
||||||
options.UseProjectables();
|
options.UseProjectables();
|
||||||
|
|
||||||
@@ -62,6 +85,12 @@ namespace IRaCIS.Core.API
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Register an additional context factory as a Scoped service, which gets a pooled context from the Singleton factory we registered above,
|
||||||
|
//services.AddScoped<IRaCISDBScopedFactory>();
|
||||||
|
|
||||||
|
//// Finally, arrange for a context to get injected from our Scoped factory:
|
||||||
|
//services.AddScoped(sp => sp.GetRequiredService<IRaCISDBScopedFactory>().CreateDbContext());
|
||||||
|
|
||||||
//注意区分 easy caching 也有 IDistributedLockProvider
|
//注意区分 easy caching 也有 IDistributedLockProvider
|
||||||
services.AddSingleton<IDistributedLockProvider>(sp =>
|
services.AddSingleton<IDistributedLockProvider>(sp =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,18 +1,30 @@
|
|||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.ResponseCompression;
|
using Microsoft.AspNetCore.ResponseCompression;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using System.IO.Compression;
|
||||||
|
|
||||||
namespace IRaCIS.Core.API
|
namespace IRaCIS.Core.API
|
||||||
{
|
{
|
||||||
public static class ResponseCompressionSetup
|
public static class ResponseCompressionSetup
|
||||||
{
|
{
|
||||||
public static void AddResponseCompressionSetup(this IServiceCollection services)
|
public static void AddResponseCompressionSetup(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddResponseCompression(options =>
|
services.AddResponseCompression(options =>
|
||||||
{
|
{
|
||||||
|
options.EnableForHttps = true;
|
||||||
options.Providers.Add<BrotliCompressionProvider>();
|
options.Providers.Add<BrotliCompressionProvider>();
|
||||||
options.Providers.Add<GzipCompressionProvider>();
|
options.Providers.Add<GzipCompressionProvider>();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
services.Configure<BrotliCompressionProviderOptions>(options =>
|
||||||
|
{
|
||||||
|
options.Level = CompressionLevel.Optimal;
|
||||||
|
});
|
||||||
|
|
||||||
|
services.Configure<GzipCompressionProviderOptions>(options =>
|
||||||
|
{
|
||||||
|
options.Level = CompressionLevel.Optimal;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
using Serilog.Sinks.Email;
|
//using Serilog.Sinks.Email;
|
||||||
using System;
|
using System;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Hangfire.SqlServer;
|
|||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace IRaCIS.Core.API
|
namespace IRaCIS.Core.API
|
||||||
{
|
{
|
||||||
@@ -14,19 +15,29 @@ namespace IRaCIS.Core.API
|
|||||||
|
|
||||||
services.AddHangfire(hangFireConfig =>
|
services.AddHangfire(hangFireConfig =>
|
||||||
{
|
{
|
||||||
|
//本地window 调试 使用内存,服务器部署使用数据库,防止服务器任务调度到本地
|
||||||
//hangFireConfig.UseInMemoryStorage();
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
|
||||||
//指定存储介质
|
|
||||||
hangFireConfig.UseSqlServerStorage(hangFireConnStr, new SqlServerStorageOptions()
|
|
||||||
{
|
{
|
||||||
SchemaName = "dbo",
|
hangFireConfig.UseInMemoryStorage();
|
||||||
CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
|
|
||||||
SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
|
}
|
||||||
QueuePollInterval = TimeSpan.Zero,
|
else
|
||||||
UseRecommendedIsolationLevel = true,
|
{
|
||||||
DisableGlobalLocks = true
|
//指定存储介质
|
||||||
});
|
hangFireConfig.UseSqlServerStorage(hangFireConnStr, new SqlServerStorageOptions()
|
||||||
|
{
|
||||||
|
SchemaName = "dbo",
|
||||||
|
CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
|
||||||
|
SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
|
||||||
|
QueuePollInterval = TimeSpan.Zero,
|
||||||
|
UseRecommendedIsolationLevel = true,
|
||||||
|
DisableGlobalLocks = true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//hangFireConfig.UseTagsWithSql(); //nuget引入Hangfire.Tags.SqlServer
|
//hangFireConfig.UseTagsWithSql(); //nuget引入Hangfire.Tags.SqlServer
|
||||||
//.UseHangfireHttpJob();
|
//.UseHangfireHttpJob();
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
"ObjectStoreUse": "AliyunOSS",
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
"AliyunOSS": {
|
"AliyunOSS": {
|
||||||
"regionId": "cn-shanghai",
|
"regionId": "cn-shanghai",
|
||||||
|
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
|
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||||
@@ -42,7 +43,15 @@
|
|||||||
"LoginMaxFailCount": 5,
|
"LoginMaxFailCount": 5,
|
||||||
|
|
||||||
"LoginFailLockMinutes": 30,
|
"LoginFailLockMinutes": 30,
|
||||||
"AutoLoginOutMinutes": 60
|
"AutoLoginOutMinutes": 60,
|
||||||
|
|
||||||
|
"ContinuousReadingTimeMin": 120,
|
||||||
|
|
||||||
|
"ReadingRestTimeMin": 10,
|
||||||
|
|
||||||
|
"IsNeedChangePassWord": true,
|
||||||
|
|
||||||
|
"ChangePassWordDays": 90
|
||||||
},
|
},
|
||||||
"SystemEmailSendConfig": {
|
"SystemEmailSendConfig": {
|
||||||
"Port": 465,
|
"Port": 465,
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
"ObjectStoreUse": "AliyunOSS",
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
"AliyunOSS": {
|
"AliyunOSS": {
|
||||||
"regionId": "cn-shanghai",
|
"regionId": "cn-shanghai",
|
||||||
|
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
|
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||||
@@ -42,10 +43,16 @@
|
|||||||
"LoginMaxFailCount": 5,
|
"LoginMaxFailCount": 5,
|
||||||
"LoginFailLockMinutes": 30,
|
"LoginFailLockMinutes": 30,
|
||||||
|
|
||||||
"AutoLoginOutMinutes": 60,
|
"AutoLoginOutMinutes": 360,
|
||||||
|
|
||||||
"OpenLoginMFA": false
|
"OpenLoginMFA": false,
|
||||||
|
|
||||||
|
"ContinuousReadingTimeMin": 120,
|
||||||
|
|
||||||
|
"ReadingRestTimeMin": 10,
|
||||||
|
"IsNeedChangePassWord": true,
|
||||||
|
|
||||||
|
"ChangePassWordDays": 90
|
||||||
},
|
},
|
||||||
|
|
||||||
"SystemEmailSendConfig": {
|
"SystemEmailSendConfig": {
|
||||||
@@ -55,6 +62,8 @@
|
|||||||
"FromName": "IRC",
|
"FromName": "IRC",
|
||||||
"AuthorizationCode": "ExtImg@2022",
|
"AuthorizationCode": "ExtImg@2022",
|
||||||
"SiteUrl": "http://irc.extimaging.com/login",
|
"SiteUrl": "http://irc.extimaging.com/login",
|
||||||
|
"OrganizationName": "Extlmaging",
|
||||||
|
"OrganizationNameCN": "Extlmaging",
|
||||||
"CompanyName": "Extensive Imaging",
|
"CompanyName": "Extensive Imaging",
|
||||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||||
"CompanyShortName": "Extensive Imaging",
|
"CompanyShortName": "Extensive Imaging",
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"RemoteNew": "Server=106.14.89.110,1435;Database=Test_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
"RemoteNew": "Server=106.14.89.110,1435;Database=Test_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||||
"Hangfire": "Server=106.14.89.110,1435;Database=Test_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
"Hangfire": "Server=106.14.89.110,1435;Database=Test_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"ObjectStoreService": {
|
"ObjectStoreService": {
|
||||||
@@ -18,6 +17,7 @@
|
|||||||
|
|
||||||
"AliyunOSS": {
|
"AliyunOSS": {
|
||||||
"regionId": "cn-shanghai",
|
"regionId": "cn-shanghai",
|
||||||
|
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
"endPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
"endPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||||
@@ -35,7 +35,6 @@
|
|||||||
"bucketName": "irc-test",
|
"bucketName": "irc-test",
|
||||||
"viewEndpoint": "https://hir-oss.test.extimaging.com/irc-test"
|
"viewEndpoint": "https://hir-oss.test.extimaging.com/irc-test"
|
||||||
},
|
},
|
||||||
|
|
||||||
"AWS": {
|
"AWS": {
|
||||||
"endPoint": "s3.us-east-1.amazonaws.com",
|
"endPoint": "s3.us-east-1.amazonaws.com",
|
||||||
"useSSL": true,
|
"useSSL": true,
|
||||||
@@ -62,7 +61,14 @@
|
|||||||
|
|
||||||
"AutoLoginOutMinutes": 1,
|
"AutoLoginOutMinutes": 1,
|
||||||
|
|
||||||
"OpenLoginMFA": false
|
"OpenLoginMFA": false,
|
||||||
|
|
||||||
|
"ContinuousReadingTimeMin": 120,
|
||||||
|
|
||||||
|
"ReadingRestTimeMin": 10,
|
||||||
|
"IsNeedChangePassWord": true,
|
||||||
|
|
||||||
|
"ChangePassWordDays": 90
|
||||||
},
|
},
|
||||||
|
|
||||||
"SystemEmailSendConfig": {
|
"SystemEmailSendConfig": {
|
||||||
@@ -71,13 +77,18 @@
|
|||||||
"FromEmail": "test@extimaging.com",
|
"FromEmail": "test@extimaging.com",
|
||||||
"FromName": "Test_IRC",
|
"FromName": "Test_IRC",
|
||||||
"AuthorizationCode": "SHzyyl2021",
|
"AuthorizationCode": "SHzyyl2021",
|
||||||
|
|
||||||
"SiteUrl": "http://irc.test.extimaging.com/login",
|
"SiteUrl": "http://irc.test.extimaging.com/login",
|
||||||
|
|
||||||
|
"OrganizationName": "Extlmaging",
|
||||||
|
"OrganizationNameCN": "Extlmaging",
|
||||||
"CompanyName": "Extensive Imaging",
|
"CompanyName": "Extensive Imaging",
|
||||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||||
"CompanyShortName": "Extensive Imaging",
|
"CompanyShortName": "Extensive Imaging",
|
||||||
"CompanyShortNameCN": "展影医疗"
|
"CompanyShortNameCN": "展影医疗"
|
||||||
}
|
},
|
||||||
|
|
||||||
|
"SystemPacsConfig": {
|
||||||
|
"Port": "11113",
|
||||||
|
"IP": "106.14.89.110"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"RemoteNew": "Server=us-prod-mssql-service,1433;Database=US_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||||
|
"Hangfire": "Server=us-prod-mssql-service,1433;Database=US_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||||
|
//"RemoteNew": "Server=44.210.231.169,1435;Database=US_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||||
|
//"Hangfire": "Server=44.210.231.169,1435;Database=US_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||||
|
},
|
||||||
|
|
||||||
|
"ObjectStoreService": {
|
||||||
|
"ObjectStoreUse": "AWS",
|
||||||
|
"AliyunOSS": {
|
||||||
|
"regionId": "cn-shanghai",
|
||||||
|
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
|
"endPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"accessKeyId": "",
|
||||||
|
"accessKeySecret": "",
|
||||||
|
"bucketName": "zy-irc-test-store",
|
||||||
|
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
||||||
|
"viewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"region": "oss-cn-shanghai"
|
||||||
|
},
|
||||||
|
|
||||||
|
"MinIO": {
|
||||||
|
"endPoint": "44.210.231.169",
|
||||||
|
"port": "9001",
|
||||||
|
"useSSL": false,
|
||||||
|
"accessKey": "e9bT1isTOqSAUxb6wd4n",
|
||||||
|
"secretKey": "b5TaDzNdQCBtCvfm8eZ3dR6yY7tfZu2JYze2Po1i",
|
||||||
|
"bucketName": "prod-irc-us",
|
||||||
|
"viewEndpoint": "http://44.210.231.169:9001/prod-irc-us/"
|
||||||
|
},
|
||||||
|
|
||||||
|
"AWS": {
|
||||||
|
"endPoint": "s3.us-east-1.amazonaws.com",
|
||||||
|
"useSSL": true,
|
||||||
|
"accessKey": "AKIAW3MEAFJX5P32P6NA",
|
||||||
|
"secretKey": "soKfYlzZE11Zi4RyTjXp0myXN0U3U+ka8rT49+B/",
|
||||||
|
"bucketName": "ei-med-s3-lili-store",
|
||||||
|
"viewEndpoint": "https://ei-med-s3-lili-store.s3.amazonaws.com/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"BasicSystemConfig": {
|
||||||
|
|
||||||
|
"OpenUserComplexPassword": false,
|
||||||
|
|
||||||
|
"OpenSignDocumentBeforeWork": false,
|
||||||
|
|
||||||
|
"OpenTrialRelationDelete": true,
|
||||||
|
|
||||||
|
"OpenLoginLimit": false,
|
||||||
|
|
||||||
|
"LoginMaxFailCount": 5,
|
||||||
|
|
||||||
|
"LoginFailLockMinutes": 30,
|
||||||
|
"AutoLoginOutMinutes": 60,
|
||||||
|
|
||||||
|
"ContinuousReadingTimeMin": 120,
|
||||||
|
|
||||||
|
"ReadingRestTimeMin": 10,
|
||||||
|
"IsNeedChangePassWord": true,
|
||||||
|
|
||||||
|
"ChangePassWordDays": 90
|
||||||
|
},
|
||||||
|
|
||||||
|
"SystemEmailSendConfig": {
|
||||||
|
"Port": 587,
|
||||||
|
"Host": "smtp-mail.outlook.com",
|
||||||
|
"FromEmail": "donotreply@elevateimaging.ai",
|
||||||
|
"FromName": "LiLi",
|
||||||
|
"AuthorizationCode": "Q#669869497420ul",
|
||||||
|
|
||||||
|
"OrganizationName": "Elevate Imaging",
|
||||||
|
"OrganizationNameCN": "Elevate Imaging",
|
||||||
|
"CompanyName": "Elevate Imaging Inc.",
|
||||||
|
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||||
|
"CompanyShortName": "Elevate Imaging",
|
||||||
|
"CompanyShortNameCN": "展影医疗",
|
||||||
|
"SiteUrl": "https://lili.elevateimaging.ai/login"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"RemoteNew": "Server=106.14.89.110,1435;Database=Test_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||||
|
"Hangfire": "Server=106.14.89.110,1435;Database=Test_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||||
|
},
|
||||||
|
|
||||||
|
"ObjectStoreService": {
|
||||||
|
|
||||||
|
"ObjectStoreUse": "MinIO",
|
||||||
|
"AliyunOSS": {
|
||||||
|
"regionId": "cn-shanghai",
|
||||||
|
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
|
"endPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||||
|
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||||
|
"bucketName": "zy-irc-test-store",
|
||||||
|
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
||||||
|
"viewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"region": "oss-cn-shanghai"
|
||||||
|
},
|
||||||
|
|
||||||
|
"MinIO": {
|
||||||
|
//"endPoint": "hir-oss.uat.extimaging.com",
|
||||||
|
//"port": "443",
|
||||||
|
//"useSSL": true,
|
||||||
|
//"viewEndpoint": "https://hir-oss.uat.extimaging.com/hir-uat",
|
||||||
|
|
||||||
|
"endPoint": "47.117.164.182",
|
||||||
|
"port": "9001",
|
||||||
|
"useSSL": false,
|
||||||
|
"viewEndpoint": "http://47.117.164.182:9001/test-irc-us",
|
||||||
|
|
||||||
|
"accessKey": "b9Ul0e98xPzt6PwRXA1Q",
|
||||||
|
"secretKey": "DzMaU2L4OXl90uytwOmDXF2encN0Jf4Nxu2XkYqQ",
|
||||||
|
"bucketName": "test-irc-us"
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
"AWS": {
|
||||||
|
"endPoint": "s3.us-east-1.amazonaws.com",
|
||||||
|
"useSSL": true,
|
||||||
|
"accessKey": "AKIAZQ3DRSOHFPJJ6FEU",
|
||||||
|
"secretKey": "l+yjtvV7Z4jiwm/7xCYv30UeUj/SvuqqYzAwjJHf",
|
||||||
|
"bucketName": "ei-irc-test-store",
|
||||||
|
"viewEndpoint": "https://ei-irc-test-store.s3.amazonaws.com/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"BasicSystemConfig": {
|
||||||
|
|
||||||
|
"OpenUserComplexPassword": false,
|
||||||
|
|
||||||
|
"OpenSignDocumentBeforeWork": false,
|
||||||
|
|
||||||
|
"OpenTrialRelationDelete": true,
|
||||||
|
|
||||||
|
"OpenLoginLimit": false,
|
||||||
|
|
||||||
|
"LoginMaxFailCount": 5,
|
||||||
|
|
||||||
|
"LoginFailLockMinutes": 30,
|
||||||
|
"AutoLoginOutMinutes": 60,
|
||||||
|
|
||||||
|
"ContinuousReadingTimeMin": 120,
|
||||||
|
|
||||||
|
"ReadingRestTimeMin": 10,
|
||||||
|
"IsNeedChangePassWord": true,
|
||||||
|
|
||||||
|
"ChangePassWordDays": 90
|
||||||
|
},
|
||||||
|
|
||||||
|
"SystemEmailSendConfig": {
|
||||||
|
"Port": 587,
|
||||||
|
"Host": "smtp-mail.outlook.com",
|
||||||
|
"FromEmail": "donotreply@elevateimaging.ai",
|
||||||
|
"FromName": "LiLi",
|
||||||
|
"AuthorizationCode": "Q#669869497420ul",
|
||||||
|
|
||||||
|
"OrganizationName": "Elevate Imaging",
|
||||||
|
"OrganizationNameCN": "Elevate Imaging",
|
||||||
|
"CompanyName": "Elevate Imaging Inc.",
|
||||||
|
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||||
|
"CompanyShortName": "Elevate Imaging",
|
||||||
|
"CompanyShortNameCN": "展影医疗",
|
||||||
|
"SiteUrl": "https://lili.test.elevateimaging.ai/login"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"RemoteNew": "Server=us-mssql-service,1433;Database=US_Uat_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||||
|
"Hangfire": "Server=us-mssql-service,1433;Database=US_Uat_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||||
|
|
||||||
|
//"RemoteNew": "Server=3.226.182.187,1435;Database=US_Uat_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||||
|
//"Hangfire": "Server=3.226.182.187,1435;Database=US_Uat_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||||
|
},
|
||||||
|
|
||||||
|
"ObjectStoreService": {
|
||||||
|
|
||||||
|
"ObjectStoreUse": "AWS",
|
||||||
|
|
||||||
|
"MinIO": {
|
||||||
|
//"endPoint": "hir-minio.uat.elevateimaging.ai",
|
||||||
|
//"port": "443",
|
||||||
|
//"useSSL": true,
|
||||||
|
//"viewEndpoint": "https://hir-minio.uat.elevateimaging.ai/uat-irc-us",
|
||||||
|
|
||||||
|
"endPoint": "3.226.182.187",
|
||||||
|
"port": "9001",
|
||||||
|
"useSSL": false,
|
||||||
|
"viewEndpoint": "http://44.218.11.19:9001/uat-irc-us",
|
||||||
|
|
||||||
|
"accessKey": "lH8DkKskLuDqPaiubuSQ",
|
||||||
|
"secretKey": "pdPdicvvLeH7xAC5yFUrI7odMyBfOXxvVWMvKYV4",
|
||||||
|
"bucketName": "uat-irc-us"
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
"AWS": {
|
||||||
|
"endPoint": "s3.us-east-1.amazonaws.com",
|
||||||
|
"useSSL": true,
|
||||||
|
"accessKey": "AKIAW3MEAFJXUO6XYFYN",
|
||||||
|
"secretKey": "AeX5r4xHQH7tNJlTTFVv5/zBXie1Kj+mAayKrukp",
|
||||||
|
"bucketName": "ei-med-s3-lili-uat-store",
|
||||||
|
"viewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"BasicSystemConfig": {
|
||||||
|
|
||||||
|
"OpenUserComplexPassword": false,
|
||||||
|
|
||||||
|
"OpenSignDocumentBeforeWork": false,
|
||||||
|
|
||||||
|
"OpenTrialRelationDelete": true,
|
||||||
|
|
||||||
|
"OpenLoginLimit": false,
|
||||||
|
|
||||||
|
"LoginMaxFailCount": 5,
|
||||||
|
|
||||||
|
"LoginFailLockMinutes": 30,
|
||||||
|
"AutoLoginOutMinutes": 60,
|
||||||
|
|
||||||
|
"ContinuousReadingTimeMin": 120,
|
||||||
|
|
||||||
|
"ReadingRestTimeMin": 10,
|
||||||
|
"IsNeedChangePassWord": true,
|
||||||
|
|
||||||
|
"ChangePassWordDays": 90,
|
||||||
|
|
||||||
|
"OpenLoginMFA": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"SystemEmailSendConfig": {
|
||||||
|
"Port": 587,
|
||||||
|
"Host": "smtp-mail.outlook.com",
|
||||||
|
"FromEmail": "donotreply@elevateimaging.ai",
|
||||||
|
"FromName": "LiLi",
|
||||||
|
"AuthorizationCode": "Q#669869497420ul",
|
||||||
|
|
||||||
|
"OrganizationName": "Elevate Imaging",
|
||||||
|
"OrganizationNameCN": "Elevate Imaging",
|
||||||
|
"CompanyName": "Elevate Imaging Inc.",
|
||||||
|
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||||
|
"CompanyShortName": "Elevate Imaging",
|
||||||
|
"CompanyShortNameCN": "展影医疗",
|
||||||
|
"SiteUrl": "https://lili.test.elevateimaging.ai/login"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -12,10 +12,11 @@
|
|||||||
},
|
},
|
||||||
"ObjectStoreService": {
|
"ObjectStoreService": {
|
||||||
|
|
||||||
"ObjectStoreUse": "MinIO",
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
|
|
||||||
"AliyunOSS": {
|
"AliyunOSS": {
|
||||||
"regionId": "cn-shanghai",
|
"regionId": "cn-shanghai",
|
||||||
|
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
|
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||||
@@ -51,7 +52,14 @@
|
|||||||
|
|
||||||
"LoginFailLockMinutes": 30,
|
"LoginFailLockMinutes": 30,
|
||||||
"AutoLoginOutMinutes": 60,
|
"AutoLoginOutMinutes": 60,
|
||||||
"OpenLoginMFA": false
|
"OpenLoginMFA": false,
|
||||||
|
|
||||||
|
"ContinuousReadingTimeMin": 120,
|
||||||
|
|
||||||
|
"ReadingRestTimeMin": 10,
|
||||||
|
"IsNeedChangePassWord": true,
|
||||||
|
|
||||||
|
"ChangePassWordDays": 90
|
||||||
|
|
||||||
},
|
},
|
||||||
"SystemEmailSendConfig": {
|
"SystemEmailSendConfig": {
|
||||||
@@ -61,11 +69,17 @@
|
|||||||
"FromName": "UAT_IRC",
|
"FromName": "UAT_IRC",
|
||||||
"AuthorizationCode": "SHzyyl2021",
|
"AuthorizationCode": "SHzyyl2021",
|
||||||
"SiteUrl": "http://irc.uat.extimaging.com/login",
|
"SiteUrl": "http://irc.uat.extimaging.com/login",
|
||||||
|
"OrganizationName": "Extlmaging",
|
||||||
|
"OrganizationNameCN": "Extlmaging",
|
||||||
"CompanyName": "Extensive Imaging",
|
"CompanyName": "Extensive Imaging",
|
||||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||||
"CompanyShortName": "Extensive Imaging",
|
"CompanyShortName": "Extensive Imaging",
|
||||||
"CompanyShortNameCN": "展影医疗"
|
"CompanyShortNameCN": "展影医疗"
|
||||||
|
},
|
||||||
|
|
||||||
|
"SystemPacsConfig": {
|
||||||
|
"Port": "11113",
|
||||||
|
"IP": "47.117.164.182"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,7 +90,13 @@
|
|||||||
"DicomStudyCodePrefix": "ST",
|
"DicomStudyCodePrefix": "ST",
|
||||||
"SystemSiteCodePrefix": "S",
|
"SystemSiteCodePrefix": "S",
|
||||||
"DefaultPassword": "123456",
|
"DefaultPassword": "123456",
|
||||||
"DefaultInternalOrganizationName": "ExtImaging",
|
|
||||||
"ImageShareExpireDays": 10
|
"ImageShareExpireDays": 10
|
||||||
|
},
|
||||||
|
|
||||||
|
"EncrypteResponseConfig": {
|
||||||
|
"IsEnable": true,
|
||||||
|
"ApiPathList": [
|
||||||
|
"/test/get"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,7 @@ using Microsoft.Extensions.Configuration;
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using SharpCompress.Common;
|
using SharpCompress.Common;
|
||||||
|
using ZiggyCreatures.Caching.Fusion;
|
||||||
|
|
||||||
namespace IRaCIS.Application.Services.BackGroundJob
|
namespace IRaCIS.Application.Services.BackGroundJob
|
||||||
{
|
{
|
||||||
@@ -21,167 +22,48 @@ namespace IRaCIS.Application.Services.BackGroundJob
|
|||||||
Task InitHangfireJobTaskAsync();
|
Task InitHangfireJobTaskAsync();
|
||||||
|
|
||||||
}
|
}
|
||||||
public class IRaCISCHangfireJob : IIRaCISHangfireJob
|
public class IRaCISCHangfireJob(IRepository<Trial> _trialRepository,
|
||||||
|
IEasyCachingProvider _provider,
|
||||||
|
ILogger<IRaCISCHangfireJob> _logger,
|
||||||
|
IRepository<SystemAnonymization> _systemAnonymizationRepository,
|
||||||
|
IRepository<Internationalization> _internationalizationRepository,
|
||||||
|
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigRepository
|
||||||
|
) : IIRaCISHangfireJob
|
||||||
{
|
{
|
||||||
public static string JsonFileFolder = Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources);
|
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 readonly IRepository<Trial> _trialRepository;
|
|
||||||
private readonly IEasyCachingProvider _provider;
|
|
||||||
private readonly ILogger<IRaCISCHangfireJob> _logger;
|
|
||||||
private readonly IRepository<SystemAnonymization> _systemAnonymizationRepository;
|
|
||||||
private readonly IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigRepository;
|
|
||||||
private readonly IRepository<Internationalization> _internationalizationRepository;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public IRaCISCHangfireJob(IRepository<Trial> trialRepository, ILogger<IRaCISCHangfireJob> logger, IEasyCachingProvider provider, IRepository<TrialEmailNoticeConfig> trialEmailNoticeConfigRepository, IRepository<Internationalization> internationalizationRepository, IRepository<SystemAnonymization> systemAnonymizationRepository)
|
|
||||||
{
|
|
||||||
_trialRepository = trialRepository;
|
|
||||||
_provider = provider;
|
|
||||||
_logger = logger;
|
|
||||||
_trialEmailNoticeConfigRepository = trialEmailNoticeConfigRepository;
|
|
||||||
_internationalizationRepository = internationalizationRepository;
|
|
||||||
_systemAnonymizationRepository = systemAnonymizationRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task InitHangfireJobTaskAsync()
|
public async Task InitHangfireJobTaskAsync()
|
||||||
{
|
{
|
||||||
_logger.LogInformation("项目启动 hangfire 任务初始化 执行开始~");
|
_logger.LogInformation("项目启动 hangfire 任务初始化 执行开始~");
|
||||||
|
|
||||||
|
//初始化国际化
|
||||||
|
|
||||||
//项目状态 立即加载到缓存中
|
await InternationalizationHelper.InitInternationlizationDataAndWatchJsonFileAsync(_internationalizationRepository);
|
||||||
await MemoryCacheTrialStatusAsync();
|
|
||||||
|
|
||||||
await MemoryCacheAnonymizeData();
|
|
||||||
|
|
||||||
|
|
||||||
//创建项目缓存 定时任务
|
|
||||||
HangfireJobHelper.AddOrUpdateInitCronJob<IIRaCISHangfireJob>("RecurringJob_Cache_TrialState", t => t.MemoryCacheTrialStatusAsync(), Cron.Daily());
|
|
||||||
|
|
||||||
//初始化
|
|
||||||
|
|
||||||
await InitInternationlizationDataAndWatchJsonFileAsync();
|
|
||||||
|
|
||||||
//创建邮件定时任务
|
//创建邮件定时任务
|
||||||
await InitSysAndTrialCronJobAsync();
|
await InitSysAndTrialCronJobAsync();
|
||||||
|
|
||||||
|
#region 废弃
|
||||||
|
////项目状态 立即加载到缓存中
|
||||||
|
//await MemoryCacheTrialStatusAsync();
|
||||||
|
|
||||||
|
////await MemoryCacheAnonymizeData();
|
||||||
|
|
||||||
|
|
||||||
|
////创建项目缓存 定时任务
|
||||||
|
//HangfireJobHelper.AddOrUpdateInitCronJob<IIRaCISHangfireJob>("RecurringJob_Cache_TrialState", t => t.MemoryCacheTrialStatusAsync(), Cron.Daily());
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
_logger.LogInformation("项目启动 hangfire 任务初始化 执行结束");
|
_logger.LogInformation("项目启动 hangfire 任务初始化 执行结束");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 缓存项目状态
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task MemoryCacheTrialStatusAsync()
|
|
||||||
{
|
|
||||||
|
|
||||||
var list = await _trialRepository.Select(t => new { TrialId = t.Id, TrialStatusStr = t.TrialStatusStr })
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
list.ForEach(t => _provider.Set(t.TrialId.ToString(), t.TrialStatusStr, TimeSpan.FromDays(7)));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task MemoryCacheAnonymizeData()
|
|
||||||
{
|
|
||||||
var systemAnonymizationList = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
|
|
||||||
|
|
||||||
_provider.Set(StaticData.Anonymize.Anonymize_AddFixedFiled, systemAnonymizationList.Where(t => t.IsAdd && t.IsFixed).ToList(), TimeSpan.FromDays(7));
|
|
||||||
_provider.Set(StaticData.Anonymize.Anonymize_AddIRCInfoFiled, systemAnonymizationList.Where(t => t.IsAdd && t.IsFixed == false).ToList(), TimeSpan.FromDays(7));
|
|
||||||
_provider.Set(StaticData.Anonymize.Anonymize_FixedField, systemAnonymizationList.Where(t => t.IsAdd == false && t.IsFixed).ToList(), TimeSpan.FromDays(7));
|
|
||||||
_provider.Set(StaticData.Anonymize.Anonymize_IRCInfoField, systemAnonymizationList.Where(t => t.IsAdd == false && t.IsFixed == false).ToList(), TimeSpan.FromDays(7));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#region 国际化 初始化
|
|
||||||
|
|
||||||
|
|
||||||
public async Task InitInternationlizationDataAndWatchJsonFileAsync()
|
|
||||||
{
|
|
||||||
//查询数据库的数据
|
|
||||||
var toJsonList = await _internationalizationRepository.Where(t => t.InternationalizationType == 1).Select(t => new
|
|
||||||
{
|
|
||||||
t.Code,
|
|
||||||
t.Value,
|
|
||||||
t.ValueCN
|
|
||||||
}).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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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"));
|
|
||||||
}
|
|
||||||
|
|
||||||
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(usJsonPath);
|
|
||||||
|
|
||||||
|
|
||||||
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(cnJsonPath);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void LoadJsonFile(string filePath)
|
|
||||||
{
|
|
||||||
Console.WriteLine("刷新json内存数据");
|
|
||||||
IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile(filePath,false,true);
|
|
||||||
|
|
||||||
IConfigurationRoot enConfiguration = builder.Build();
|
|
||||||
|
|
||||||
foreach (IConfigurationSection section in enConfiguration.GetChildren())
|
|
||||||
{
|
|
||||||
if (filePath.Contains(StaticData.En_US_Json))
|
|
||||||
{
|
|
||||||
StaticData.En_US_Dic[section.Key] = section.Value;
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
StaticData.Zh_CN_Dic[section.Key] = section.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public async Task InitSysAndTrialCronJobAsync()
|
public async Task InitSysAndTrialCronJobAsync()
|
||||||
{
|
{
|
||||||
@@ -223,6 +105,36 @@ namespace IRaCIS.Application.Services.BackGroundJob
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#region 废弃 前端上传的时候获取
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 缓存项目状态--之前是启动的时候就获取所有的项目进行缓存,加上定时任务刷新,现在的话,改为是按照需要进行缓存请求数据库
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task MemoryCacheTrialStatusAsync()
|
||||||
|
{
|
||||||
|
|
||||||
|
var list = await _trialRepository.Select(t => new { TrialId = t.Id, TrialStatusStr = t.TrialStatusStr })
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
list.ForEach(t => _provider.Set(t.TrialId.ToString(), t.TrialStatusStr, TimeSpan.FromDays(7)));
|
||||||
|
|
||||||
|
}
|
||||||
|
public async Task MemoryCacheAnonymizeData()
|
||||||
|
{
|
||||||
|
var systemAnonymizationList = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
|
||||||
|
|
||||||
|
_provider.Set(StaticData.Anonymize.Anonymize_AddFixedFiled, systemAnonymizationList.Where(t => t.IsAdd && t.IsFixed).ToList(), TimeSpan.FromDays(7));
|
||||||
|
_provider.Set(StaticData.Anonymize.Anonymize_AddIRCInfoFiled, systemAnonymizationList.Where(t => t.IsAdd && t.IsFixed == false).ToList(), TimeSpan.FromDays(7));
|
||||||
|
_provider.Set(StaticData.Anonymize.Anonymize_FixedField, systemAnonymizationList.Where(t => t.IsAdd == false && t.IsFixed).ToList(), TimeSpan.FromDays(7));
|
||||||
|
_provider.Set(StaticData.Anonymize.Anonymize_IRCInfoField, systemAnonymizationList.Where(t => t.IsAdd == false && t.IsFixed == false).ToList(), TimeSpan.FromDays(7));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ using Panda.DynamicWebApi;
|
|||||||
using Panda.DynamicWebApi.Attributes;
|
using Panda.DynamicWebApi.Attributes;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using ZiggyCreatures.Caching.Fusion;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application
|
namespace IRaCIS.Core.Application
|
||||||
{
|
{
|
||||||
@@ -17,7 +19,8 @@ namespace IRaCIS.Core.Application
|
|||||||
|
|
||||||
#region 非泛型版本
|
#region 非泛型版本
|
||||||
|
|
||||||
[Authorize, DynamicWebApi, UnifiedApiResultFilter]
|
[TypeFilter(typeof(UnifiedApiResultFilter))]
|
||||||
|
[Authorize, DynamicWebApi]
|
||||||
public class BaseService : IBaseService, IDynamicWebApi
|
public class BaseService : IBaseService, IDynamicWebApi
|
||||||
{
|
{
|
||||||
public IMapper _mapper { get; set; }
|
public IMapper _mapper { get; set; }
|
||||||
@@ -30,7 +33,7 @@ namespace IRaCIS.Core.Application
|
|||||||
|
|
||||||
public IWebHostEnvironment _hostEnvironment { get; set; }
|
public IWebHostEnvironment _hostEnvironment { get; set; }
|
||||||
|
|
||||||
|
public IFusionCache _fusionCache { get; set; }
|
||||||
|
|
||||||
|
|
||||||
public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class
|
public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class
|
||||||
@@ -58,6 +61,9 @@ namespace IRaCIS.Core.Application
|
|||||||
[MemberNotNull(nameof(_hostEnvironment))]
|
[MemberNotNull(nameof(_hostEnvironment))]
|
||||||
public IWebHostEnvironment _hostEnvironment { get; set; }
|
public IWebHostEnvironment _hostEnvironment { get; set; }
|
||||||
|
|
||||||
|
[MemberNotNull(nameof(_fusionCache))]
|
||||||
|
public IFusionCache _fusionCache { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -79,12 +85,13 @@ namespace IRaCIS.Core.Application
|
|||||||
[MemberNotNull(nameof(_localizer))]
|
[MemberNotNull(nameof(_localizer))]
|
||||||
public IStringLocalizer _localizer { get; set; }
|
public IStringLocalizer _localizer { get; set; }
|
||||||
|
|
||||||
|
[MemberNotNull(nameof(_fusionCache))]
|
||||||
|
public IFusionCache _fusionCache { get; set; }
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TypeFilter(typeof(UnifiedApiResultFilter))]
|
||||||
[Authorize, DynamicWebApi, UnifiedApiResultFilter]
|
[Authorize, DynamicWebApi]
|
||||||
public class BaseServiceTest<T> : IBaseServiceTest<T>, IDynamicWebApi where T : Entity
|
public class BaseServiceTest<T> : IBaseServiceTest<T>, IDynamicWebApi where T : Entity
|
||||||
{
|
{
|
||||||
public IMapper _mapper { get; set; }
|
public IMapper _mapper { get; set; }
|
||||||
@@ -95,6 +102,8 @@ namespace IRaCIS.Core.Application
|
|||||||
|
|
||||||
public IStringLocalizer _localizer { get; set; }
|
public IStringLocalizer _localizer { get; set; }
|
||||||
|
|
||||||
|
public IFusionCache _fusionCache { get; set; }
|
||||||
|
|
||||||
public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class
|
public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class
|
||||||
{
|
{
|
||||||
return new ResponseOutput<string>()
|
return new ResponseOutput<string>()
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.Application.BusinessFilter
|
||||||
|
{
|
||||||
|
public class EncreptApiResultFilter : IAsyncResultFilter
|
||||||
|
{
|
||||||
|
|
||||||
|
private readonly IOptionsMonitor<EncreptResponseOption> _encreptResponseMonitor;
|
||||||
|
|
||||||
|
public EncreptApiResultFilter(IOptionsMonitor<EncreptResponseOption> encreptResponseMonitor)
|
||||||
|
{
|
||||||
|
_encreptResponseMonitor = encreptResponseMonitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(_encreptResponseMonitor.CurrentValue.IsEnable)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (context.Result is ObjectResult objectResult)
|
||||||
|
{
|
||||||
|
var statusCode = objectResult.StatusCode ?? context.HttpContext.Response.StatusCode;
|
||||||
|
|
||||||
|
var objectValue = objectResult.Value;
|
||||||
|
|
||||||
|
|
||||||
|
if (objectValue is IResponseOutput)
|
||||||
|
{
|
||||||
|
var responseOutput = objectValue as IResponseOutput<object>;
|
||||||
|
|
||||||
|
var path = context.HttpContext?.Request.Path.Value?.ToLower();
|
||||||
|
|
||||||
|
|
||||||
|
if(!string.IsNullOrEmpty(path) && path.Length>5 && _encreptResponseMonitor.CurrentValue.ApiPathList.Contains(path.ToLower()))
|
||||||
|
{
|
||||||
|
|
||||||
|
if(responseOutput.IsSuccess)
|
||||||
|
{
|
||||||
|
responseOutput.Code = ApiResponseCodeEnum.ResultEncrepted;
|
||||||
|
responseOutput.Data = JsonConvert.SerializeObject(Convert.ToBase64String(Encoding.UTF8.GetBytes(responseOutput.Data.ToString())));
|
||||||
|
|
||||||
|
objectResult.Value = responseOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
await next.Invoke();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
using Microsoft.AspNetCore.Diagnostics;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.Application.BusinessFilter
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <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)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
httpContext.Response.ContentType = "application/json";
|
||||||
|
|
||||||
|
|
||||||
|
var ex = exception;
|
||||||
|
var errorInfo = $"Exception: {ex.Message}[{ex.StackTrace}]" + (ex.InnerException != null ? $" InnerException: {ex.InnerException.Message}[{ex.InnerException.StackTrace}]" : "");
|
||||||
|
|
||||||
|
httpContext.Response.WriteAsJsonAsync(ResponseOutput.NotOk($"{ex?.Message}"));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
_logger.LogError(errorInfo);
|
||||||
|
|
||||||
|
// return true to signal that this exception is handled
|
||||||
|
return ValueTask.FromResult(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using IRaCIS.Core.Infrastructure;
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using IRaCIS.Core.Infrastructure;
|
||||||
using IRaCIS.Core.Infrastructure.Extention;
|
using IRaCIS.Core.Infrastructure.Extention;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
@@ -11,13 +12,13 @@ namespace IRaCIS.Core.Application.Filter
|
|||||||
{
|
{
|
||||||
private readonly ILogger<ProjectExceptionFilter> _logger;
|
private readonly ILogger<ProjectExceptionFilter> _logger;
|
||||||
|
|
||||||
public IStringLocalizer _localizer;
|
public IStringLocalizer _localizer;
|
||||||
|
|
||||||
public ProjectExceptionFilter(IStringLocalizer localizer, ILogger<ProjectExceptionFilter> logger)
|
public ProjectExceptionFilter(IStringLocalizer localizer, ILogger<ProjectExceptionFilter> logger)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_localizer = localizer;
|
_localizer = localizer;
|
||||||
}
|
}
|
||||||
public void OnException(ExceptionContext context)
|
public void OnException(ExceptionContext context)
|
||||||
{
|
{
|
||||||
//context.ExceptionHandled;//记录当前这个异常是否已经被处理过了
|
//context.ExceptionHandled;//记录当前这个异常是否已经被处理过了
|
||||||
@@ -26,7 +27,7 @@ namespace IRaCIS.Core.Application.Filter
|
|||||||
{
|
{
|
||||||
if (context.Exception.GetType().Name == "DbUpdateConcurrencyException")
|
if (context.Exception.GetType().Name == "DbUpdateConcurrencyException")
|
||||||
{
|
{
|
||||||
//---并发更新,当前不允许该操作
|
//---并发更新,当前不允许该操作
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ProjectException_ConcurrentUpdateNotAllowed"] + context.Exception.Message));
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ProjectException_ConcurrentUpdateNotAllowed"] + context.Exception.Message));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,28 +35,43 @@ namespace IRaCIS.Core.Application.Filter
|
|||||||
{
|
{
|
||||||
var error = context.Exception as BusinessValidationFailedException;
|
var error = context.Exception as BusinessValidationFailedException;
|
||||||
|
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, error!.Code));
|
var info = string.Empty;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(error!.LocalizedKey) && StaticData.Log_Locoalize_Dic.ContainsKey(error!.LocalizedKey))
|
||||||
|
{
|
||||||
|
info = $"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, "", error!.Code, localizedInfo: info));
|
||||||
|
|
||||||
|
|
||||||
|
//warning 级别记录
|
||||||
|
//_logger.LogWarning($"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}");
|
||||||
}
|
}
|
||||||
else if(context.Exception.GetType() == typeof(QueryBusinessObjectNotExistException))
|
else if (context.Exception.GetType() == typeof(QueryBusinessObjectNotExistException))
|
||||||
{
|
{
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk( context.Exception.Message, ApiResponseCodeEnum.DataNotExist));
|
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, ApiResponseCodeEnum.DataNotExist));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (context.Exception.InnerException is null ? (context.Exception.Message /*+ context.Exception.StackTrace*/)
|
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));
|
: (context.Exception.InnerException?.Message /*+ context.Exception.InnerException?.StackTrace*/)), ApiResponseCodeEnum.ProgramException));
|
||||||
|
|
||||||
|
_logger.LogError(context.Exception.InnerException is null ? (context.Exception.Message + context.Exception.StackTrace) : (context.Exception.InnerException?.Message + context.Exception.InnerException?.StackTrace));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context.ExceptionHandled = true;//标记当前异常已经被处理过了
|
||||||
|
|
||||||
_logger.LogError(context.Exception.InnerException is null ? (context.Exception.Message + context.Exception.StackTrace) : (context.Exception.InnerException?.Message + context.Exception.InnerException?.StackTrace));
|
|
||||||
|
|
||||||
|
//throw new Exception("test-result-exceptioin");
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//继续
|
//继续
|
||||||
}
|
}
|
||||||
context.ExceptionHandled = true;//标记当前异常已经被处理过了
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
using EasyCaching.Core;
|
using EasyCaching.Core;
|
||||||
|
using IRaCIS.Core.Application.Helper;
|
||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
using Microsoft.Extensions.Localization;
|
using Microsoft.Extensions.Localization;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
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
|
||||||
@@ -16,47 +18,36 @@ namespace IRaCIS.Core.Application.Filter
|
|||||||
{
|
{
|
||||||
private readonly IEasyCachingProvider _provider;
|
private readonly IEasyCachingProvider _provider;
|
||||||
private readonly IUserInfo _userInfo;
|
private readonly IUserInfo _userInfo;
|
||||||
|
private readonly IFusionCache _fusionCache;
|
||||||
public IStringLocalizer _localizer;
|
public IStringLocalizer _localizer;
|
||||||
private readonly List<string> _trialOptList=new List<string>();
|
private readonly IRepository<Trial> _trialRepository;
|
||||||
|
private readonly List<string> _trialOptList = new List<string>();
|
||||||
|
|
||||||
|
|
||||||
public TrialResourceFilter(IEasyCachingProvider provider, IStringLocalizer localizer , IUserInfo userInfo, string trialOpt = null, string trialOpt2 = null, string trialOpt3 = null)
|
public TrialResourceFilter(IFusionCache fusionCache, IRepository<Trial> trialRepository, IEasyCachingProvider provider, IStringLocalizer localizer, IUserInfo userInfo, string trialOpt = null, string trialOpt2 = null, string trialOpt3 = null)
|
||||||
{
|
{
|
||||||
|
_fusionCache = fusionCache;
|
||||||
_provider = provider;
|
_provider = provider;
|
||||||
_userInfo = userInfo;
|
_userInfo = userInfo;
|
||||||
_localizer = localizer;
|
_localizer = localizer;
|
||||||
//_trialOpt = trialOpt;
|
_trialRepository = trialRepository;
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(trialOpt)) _trialOptList.Add(trialOpt.Trim());
|
if (!string.IsNullOrWhiteSpace(trialOpt)) _trialOptList.Add(trialOpt.Trim());
|
||||||
if (!string.IsNullOrWhiteSpace(trialOpt2)) _trialOptList.Add(trialOpt2.Trim());
|
if (!string.IsNullOrWhiteSpace(trialOpt2)) _trialOptList.Add(trialOpt2.Trim());
|
||||||
if (!string.IsNullOrWhiteSpace(trialOpt3)) _trialOptList.Add(trialOpt3.Trim());
|
if (!string.IsNullOrWhiteSpace(trialOpt3)) _trialOptList.Add(trialOpt3.Trim());
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//public TrialResourceFilter(IEasyCachingProvider provider, IUserInfo userInfo)
|
|
||||||
//{
|
|
||||||
// _provider = provider;
|
|
||||||
// _userInfo = userInfo;
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//优先选择异步的方法
|
//优先选择异步的方法
|
||||||
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
|
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 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();
|
//var _trialOptList= typeFilter.Arguments.Select(t => t.ToString()).ToList();
|
||||||
|
|
||||||
#region 处理新的用户类型,不能操作项目相关接口
|
#region 处理新的用户类型,不能操作项目相关接口
|
||||||
|
|
||||||
// 后期列举出具体的类型,其他任何用户类型,都不允许操作
|
// 后期列举出具体的类型,其他任何用户类型,都不允许操作
|
||||||
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower()!= "TrialDocument/userConfirm".ToLower())
|
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower() != "TrialDocument/userConfirm".ToLower())
|
||||||
{
|
{
|
||||||
//---对不起,您的账户没有操作权限。
|
//---对不起,您的账户没有操作权限。
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"]));
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"]));
|
||||||
@@ -97,7 +88,7 @@ namespace IRaCIS.Core.Application.Filter
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,20 +119,20 @@ namespace IRaCIS.Core.Application.Filter
|
|||||||
if (matchResult.Success)
|
if (matchResult.Success)
|
||||||
{
|
{
|
||||||
//有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下
|
//有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下
|
||||||
var cacheResultDic = _provider.GetAll<string>(new[] { matchResult.Value });
|
|
||||||
|
|
||||||
var trialStatusStr = cacheResultDic[matchResult.Value.ToLower()].Value;
|
trialIdStr = matchResult.Value;
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(trialStatusStr))
|
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(trialStatusStr))
|
||||||
{
|
{
|
||||||
trialIdStr = matchResult.Value;
|
//数据库 检查该项目Id不对
|
||||||
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,34 +144,12 @@ namespace IRaCIS.Core.Application.Filter
|
|||||||
}
|
}
|
||||||
|
|
||||||
//通过path 或者body 找到trialId 了
|
//通过path 或者body 找到trialId 了
|
||||||
if ( !string.IsNullOrWhiteSpace(trialIdStr))
|
if (!string.IsNullOrWhiteSpace(trialIdStr))
|
||||||
{
|
{
|
||||||
|
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
|
||||||
//如果没缓存数据,可能定时任务没执行或者缓存丢失 在此重新缓存
|
|
||||||
if (_provider.GetCount() == 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
var _trialRepository = context.HttpContext.RequestServices.GetService(typeof(IRepository<Trial>)) as IRepository<Trial>;
|
|
||||||
|
|
||||||
var list = _trialRepository.IfNullThrowException().Select(t => new { TrialId = t.Id, TrialStatusStr = t.TrialStatusStr })
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
list.ForEach(t => _provider.Set(t.TrialId.ToString(), t.TrialStatusStr, TimeSpan.FromDays(7)));
|
|
||||||
}
|
|
||||||
|
|
||||||
var cacheResultDic = _provider.GetAll<string>(new[] { trialIdStr });
|
|
||||||
|
|
||||||
var trialStatusStr = cacheResultDic[trialIdStr].Value;
|
|
||||||
|
|
||||||
//意外 导致缓存过期,调整服务器时间,测试不想重启程序
|
|
||||||
if (string.IsNullOrWhiteSpace(trialStatusStr))
|
|
||||||
{
|
|
||||||
var trialRepository = context.HttpContext.RequestServices.GetService(typeof(IRepository<Trial>)) as IRepository<Trial>;
|
|
||||||
trialStatusStr = trialRepository?.Where(t => t.Id == Guid.Parse(trialIdStr)).Select(t => t.TrialStatusStr).FirstOrDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 这里是统一拦截 项目有关的操作允许情况(特殊的地方,比如项目配置(有的在多种状态(初始化,ongoing)都可以操作,有的仅仅在Initializing)还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口)
|
// 这里是统一拦截 项目有关的操作允许情况(特殊的地方,比如项目配置(有的在多种状态(初始化,ongoing)都可以操作,有的仅仅在Initializing)还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口)
|
||||||
if (trialStatusStr == StaticData.TrialState.TrialOngoing || _trialOptList.Any(t=>t== TrialOpt.BeforeOngoingCantOpt) )
|
if (trialStatusStr == StaticData.TrialState.TrialOngoing || _trialOptList.Any(t => t == TrialOpt.BeforeOngoingCantOpt))
|
||||||
{
|
{
|
||||||
|
|
||||||
await next.Invoke();
|
await next.Invoke();
|
||||||
@@ -189,14 +158,14 @@ namespace IRaCIS.Core.Application.Filter
|
|||||||
// 项目停止、或者完成 不允许操作
|
// 项目停止、或者完成 不允许操作
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改
|
//---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_InterceptedProjectStatusRule"]));
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_InterceptedProjectStatusRule"]));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
//添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截
|
//添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截
|
||||||
else if (_trialOptList.Any(t => t == TrialOpt.AddOrUpdateTrial ||t ==TrialOpt.SignSystemDocNoTrialId))
|
else if (_trialOptList.Any(t => t == TrialOpt.AddOrUpdateTrial || t == TrialOpt.SignSystemDocNoTrialId))
|
||||||
{
|
{
|
||||||
await next.Invoke();
|
await next.Invoke();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace IRaCIS.Application.Services.BusinessFilter
|
namespace IRaCIS.Application.Services.BusinessFilter
|
||||||
{
|
{
|
||||||
@@ -8,8 +9,15 @@ namespace IRaCIS.Application.Services.BusinessFilter
|
|||||||
/// 统一返回前端数据包装,之前在控制器包装,现在修改为动态Api 在ResultFilter这里包装,减少重复冗余代码
|
/// 统一返回前端数据包装,之前在控制器包装,现在修改为动态Api 在ResultFilter这里包装,减少重复冗余代码
|
||||||
/// by zhouhang 2021.09.12 周末
|
/// by zhouhang 2021.09.12 周末
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class UnifiedApiResultFilter : Attribute, IAsyncResultFilter
|
public class UnifiedApiResultFilter : Attribute, IAsyncResultFilter
|
||||||
{
|
{
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
|
public UnifiedApiResultFilter(ILogger<UnifiedApiResultFilter> logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 异步版本
|
/// 异步版本
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -26,25 +34,15 @@ namespace IRaCIS.Application.Services.BusinessFilter
|
|||||||
//是200 并且没有包装 那么包装结果
|
//是200 并且没有包装 那么包装结果
|
||||||
if (statusCode == 200 && !(objectResult.Value is IResponseOutput))
|
if (statusCode == 200 && !(objectResult.Value is IResponseOutput))
|
||||||
{
|
{
|
||||||
//if (objectResult.Value == null)
|
|
||||||
//{
|
|
||||||
// var apiResponse = ResponseOutput.DBNotExist();
|
|
||||||
|
|
||||||
// objectResult.Value = apiResponse;
|
|
||||||
// objectResult.DeclaredType = apiResponse.GetType();
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
|
|
||||||
var type = objectResult.Value?.GetType();
|
var type = objectResult.Value?.GetType();
|
||||||
|
|
||||||
|
|
||||||
if ( type!=null&& type.IsGenericType&&(type.GetGenericTypeDefinition()==typeof(ValueTuple<,>)|| type.GetGenericTypeDefinition()==typeof(Tuple<,>)))
|
if (type != null && type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(ValueTuple<,>) || type.GetGenericTypeDefinition() == typeof(Tuple<,>)))
|
||||||
{
|
{
|
||||||
|
|
||||||
//报错
|
//报错
|
||||||
//var tuple = (object, object))objectResult.Value;
|
//var tuple = (object, object))objectResult.Value;
|
||||||
|
|
||||||
//var (val1, val2) = ((dynamic, dynamic))objectResult.Value;
|
//var (val1, val2) = ((dynamic, dynamic))objectResult.Value;
|
||||||
//var apiResponse = ResponseOutput.Ok(val1, val2);
|
//var apiResponse = ResponseOutput.Ok(val1, val2);
|
||||||
|
|
||||||
@@ -64,18 +62,20 @@ namespace IRaCIS.Application.Services.BusinessFilter
|
|||||||
objectResult.DeclaredType = apiResponse.GetType();
|
objectResult.DeclaredType = apiResponse.GetType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
//如果不是200 是IResponseOutput 不处理
|
//如果是200 是IResponseOutput 记录下日志
|
||||||
else if (statusCode != 200 && (objectResult.Value is IResponseOutput))
|
else if (statusCode == 200 && (objectResult.Value is IResponseOutput))
|
||||||
{
|
{
|
||||||
|
var result = objectResult.Value as IResponseOutput;
|
||||||
|
|
||||||
|
//统一在这里记录国际化的日志信息
|
||||||
|
_logger.LogWarning($"{result.LocalizedInfo}");
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(statusCode != 200&&!(objectResult.Value is IResponseOutput))
|
else if (statusCode != 200 && !(objectResult.Value is IResponseOutput))
|
||||||
{
|
{
|
||||||
//---程序错误,请联系开发人员。
|
//---程序错误,请联系开发人员。
|
||||||
var apiResponse = ResponseOutput.NotOk(StaticData.International("UnifiedAPI_ProgramError"));
|
var apiResponse = ResponseOutput.NotOk(StaticData.International("UnifiedAPI_ProgramError"));
|
||||||
|
|
||||||
objectResult.Value = apiResponse;
|
objectResult.Value = apiResponse;
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.Application.Helper
|
||||||
|
{
|
||||||
|
|
||||||
|
public static class CacheKeys
|
||||||
|
{
|
||||||
|
public static string Trial(string trialIdStr) => $"TrialId:{trialIdStr}";
|
||||||
|
|
||||||
|
|
||||||
|
// 你可以为其他实体和模块定义更多的键
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
return statusStr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
using NPOI.SS.Formula.Functions;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.Application.Helper
|
||||||
|
{
|
||||||
|
public static class EmailMaskHelper
|
||||||
|
{
|
||||||
|
|
||||||
|
//显示位数:3分之2的位数,向上取整
|
||||||
|
//取哪几个个值:最后一位和前面几位
|
||||||
|
//其他:3个***。
|
||||||
|
//比如:hlj23@126.com
|
||||||
|
//为:hlj***3@126.com
|
||||||
|
|
||||||
|
//he@126.com
|
||||||
|
//为:h*** e@126.com
|
||||||
|
|
||||||
|
public static string MaskEmail(string email)
|
||||||
|
{
|
||||||
|
|
||||||
|
// 找到 "@" 符号的位置
|
||||||
|
int atIndex = email.IndexOf('@');
|
||||||
|
|
||||||
|
string visiblePartBefore = email.Substring(0, atIndex);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -117,7 +117,7 @@ public static class ExcelExportHelper
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
var (physicalPath, fileNmae) = await FileStoreHelper.GetCommonDocPhysicalFilePathAsync(_hostEnvironment, _commonDocumentRepository, code);
|
var (physicalPath, fileName) = await FileStoreHelper.GetCommonDocPhysicalFilePathAsync(_hostEnvironment, _commonDocumentRepository, code);
|
||||||
|
|
||||||
|
|
||||||
//模板路径
|
//模板路径
|
||||||
@@ -157,7 +157,7 @@ public static class ExcelExportHelper
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 文件名称 从sheet里面取
|
// 文件名称 从sheet里面取
|
||||||
fileNmae = workbook.GetSheetName(0);
|
//fileNmae = workbook.GetSheetName(0);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
@@ -181,7 +181,7 @@ public static class ExcelExportHelper
|
|||||||
|
|
||||||
return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
||||||
{
|
{
|
||||||
FileDownloadName = $"{exportFileNamePrefix}_{fileNmae/*.Substring(0, fileNmae.LastIndexOf('.'))*/}_{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx"
|
FileDownloadName = $"{(string.IsNullOrEmpty(exportFileNamePrefix) ? "" : exportFileNamePrefix+ "_") }{Path.GetFileNameWithoutExtension(fileName) }_{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx"
|
||||||
};
|
};
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -328,7 +328,7 @@ public static class ExcelExportHelper
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 文件名称 从sheet里面取
|
// 文件名称 从sheet里面取
|
||||||
fileName = workbook.GetSheetName(0);
|
//fileName = workbook.GetSheetName(0);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region MiniExcel
|
#region MiniExcel
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Hosting;
|
|||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using System.Configuration;
|
using System.Configuration;
|
||||||
|
using System.Globalization;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Helper;
|
namespace IRaCIS.Core.Application.Helper;
|
||||||
@@ -128,65 +129,6 @@ public static class FileStoreHelper
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="_hostEnvironment"></param>
|
|
||||||
/// <param name="_clinicalDataTrialSetRepository"></param>
|
|
||||||
/// <param name="id"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="BusinessValidationFailedException"></exception>
|
|
||||||
public static async Task<(string PhysicalPath, string FileName)> GetSystemClinicalPathAsync(IWebHostEnvironment _hostEnvironment, IRepository<ClinicalDataSystemSet> _clinicalDataTrialSetRepository, Guid id)
|
|
||||||
{
|
|
||||||
var systemClinicalData = await _clinicalDataTrialSetRepository.FirstOrDefaultAsync(t => t.Id == id);
|
|
||||||
|
|
||||||
if (systemClinicalData == null || systemClinicalData.Path == string.Empty)
|
|
||||||
{
|
|
||||||
//---数据库没有找到对应的数据模板文件,请联系系统运维人员。
|
|
||||||
throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileNotFound"));
|
|
||||||
}
|
|
||||||
|
|
||||||
var filePath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, systemClinicalData.Path);
|
|
||||||
|
|
||||||
if (!System.IO.File.Exists(filePath))
|
|
||||||
{
|
|
||||||
//---数据模板文件存储路径上未找对应文件,请联系系统运维人员。
|
|
||||||
throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileStoragePathInvalid"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return (filePath, systemClinicalData.FileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="_hostEnvironment"></param>
|
|
||||||
/// <param name="_clinicalDataTrialSetRepository"></param>
|
|
||||||
/// <param name="id"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="BusinessValidationFailedException"></exception>
|
|
||||||
public static async Task<(string PhysicalPath, string FileName)> GetTrialClinicalPathAsync(IWebHostEnvironment _hostEnvironment, IRepository<ClinicalDataTrialSet> _clinicalDataTrialSetRepository, Guid id)
|
|
||||||
{
|
|
||||||
var trialClinicalData = await _clinicalDataTrialSetRepository.FirstOrDefaultAsync(t => t.Id == id);
|
|
||||||
|
|
||||||
if (trialClinicalData == null|| trialClinicalData.Path==string.Empty)
|
|
||||||
{
|
|
||||||
//---数据库没有找到对应的数据模板文件,请联系系统运维人员。
|
|
||||||
throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileNotFound"));
|
|
||||||
}
|
|
||||||
|
|
||||||
var filePath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, trialClinicalData.Path);
|
|
||||||
|
|
||||||
if (!System.IO.File.Exists(filePath))
|
|
||||||
{
|
|
||||||
//---数据模板文件存储路径上未找对应文件,请联系系统运维人员。
|
|
||||||
throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileStoragePathInvalid"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return (filePath, trialClinicalData.FileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//通过编码获取通用文档具体物理路径
|
//通过编码获取通用文档具体物理路径
|
||||||
|
|
||||||
@@ -194,6 +136,7 @@ public static class FileStoreHelper
|
|||||||
{
|
{
|
||||||
var doc = await _commonDocumentRepository.FirstOrDefaultAsync(t => t.Code == code);
|
var doc = await _commonDocumentRepository.FirstOrDefaultAsync(t => t.Code == code);
|
||||||
|
|
||||||
|
var isEn_US = CultureInfo.CurrentCulture.Name!= "zh-CN";
|
||||||
if (doc == null)
|
if (doc == null)
|
||||||
{
|
{
|
||||||
//---数据库没有找到对应的数据模板文件,请联系系统运维人员。
|
//---数据库没有找到对应的数据模板文件,请联系系统运维人员。
|
||||||
@@ -208,7 +151,7 @@ public static class FileStoreHelper
|
|||||||
throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileStoragePathInvalid"));
|
throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileStoragePathInvalid"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (filePath, doc.Name.Trim('/'));
|
return (filePath, isEn_US? doc.Name.Trim('/'): doc.NameCN.Trim('/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -235,44 +178,6 @@ public static class FileStoreHelper
|
|||||||
return writeCount;
|
return writeCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取项目签名文档存放路径
|
|
||||||
|
|
||||||
public static (string PhysicalPath, string RelativePath) GetTrialSignDocPath(IWebHostEnvironment _hostEnvironment, Guid trialId, string fileName)
|
|
||||||
{
|
|
||||||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
|
||||||
|
|
||||||
//文件类型路径处理
|
|
||||||
var uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), StaticData.Folder.SignDocumentFolder);
|
|
||||||
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
|
|
||||||
|
|
||||||
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
|
|
||||||
|
|
||||||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{StaticData.Folder.SignDocumentFolder}/{trustedFileNameForFileStorage}";
|
|
||||||
|
|
||||||
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
|
|
||||||
|
|
||||||
return (serverFilePath, relativePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取系统签名文档存放路径
|
|
||||||
public static (string PhysicalPath, string RelativePath) GetSystemSignDocPath(IWebHostEnvironment _hostEnvironment, string fileName)
|
|
||||||
{
|
|
||||||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
|
||||||
|
|
||||||
|
|
||||||
//文件类型路径处理
|
|
||||||
var uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.SystemDataFolder, StaticData.Folder.SignDocumentFolder);
|
|
||||||
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
|
|
||||||
|
|
||||||
|
|
||||||
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
|
|
||||||
|
|
||||||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.SystemDataFolder}/{ StaticData.Folder.SignDocumentFolder}/{trustedFileNameForFileStorage}";
|
|
||||||
|
|
||||||
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
|
|
||||||
|
|
||||||
return (serverFilePath, relativePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取通用文档存放路径(excel模板 )
|
// 获取通用文档存放路径(excel模板 )
|
||||||
|
|
||||||
@@ -295,224 +200,6 @@ public static class FileStoreHelper
|
|||||||
return (serverFilePath, relativePath);
|
return (serverFilePath, relativePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
//获取系统通知文档存放路径
|
|
||||||
|
|
||||||
public static (string PhysicalPath, string RelativePath) GetSystemNoticePath(IWebHostEnvironment _hostEnvironment, string fileName)
|
|
||||||
{
|
|
||||||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
|
||||||
|
|
||||||
//文件类型路径处理
|
|
||||||
var uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.SystemDataFolder, StaticData.Folder.NoticeAttachment);
|
|
||||||
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
|
|
||||||
|
|
||||||
|
|
||||||
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.SystemDataFolder}/{StaticData.Folder.NoticeAttachment}/{trustedFileNameForFileStorage}";
|
|
||||||
|
|
||||||
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
|
|
||||||
|
|
||||||
return (serverFilePath, relativePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取一致性核查路径
|
|
||||||
public static (string PhysicalPath, string RelativePath) GetTrialCheckFilePath(IWebHostEnvironment _hostEnvironment, string fileName,Guid trialId)
|
|
||||||
{
|
|
||||||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
|
||||||
|
|
||||||
//上传根路径
|
|
||||||
string uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), StaticData.Folder.UploadEDCData);
|
|
||||||
|
|
||||||
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
|
|
||||||
|
|
||||||
|
|
||||||
//存放核对表
|
|
||||||
var (trustedFileNameForFileStorage, realFileName) = FileStoreHelper.GetStoreFileName(fileName);
|
|
||||||
|
|
||||||
|
|
||||||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{StaticData.Folder.UploadEDCData}/{trustedFileNameForFileStorage}";
|
|
||||||
|
|
||||||
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
|
|
||||||
|
|
||||||
return (serverFilePath, relativePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static (string PhysicalPath, string RelativePath, string FileRealName) GetClinicalTemplatePath(IWebHostEnvironment _hostEnvironment, string fileName,Guid trialId)
|
|
||||||
{
|
|
||||||
|
|
||||||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
|
||||||
|
|
||||||
string uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, "ClinicalTemplate", trialId.ToString(), StaticData.Folder.TreatmenthistoryFolder);
|
|
||||||
|
|
||||||
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
|
|
||||||
|
|
||||||
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
|
|
||||||
|
|
||||||
|
|
||||||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/ClinicalTemplate/{trialId}/{StaticData.Folder.TreatmenthistoryFolder}/{trustedFileNameForFileStorage}";
|
|
||||||
|
|
||||||
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
|
|
||||||
|
|
||||||
return (serverFilePath, relativePath, fileRealName);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static (string PhysicalPath, string RelativePath, string FileRealName) GetReadClinicalDataPath(IWebHostEnvironment _hostEnvironment, string fileName, Guid trialId, Guid siteId, Guid subjectId, Guid readingId)
|
|
||||||
{
|
|
||||||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
|
||||||
|
|
||||||
string uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), siteId.ToString(), subjectId.ToString(), StaticData.Folder.Reading, readingId.ToString());
|
|
||||||
|
|
||||||
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
|
|
||||||
|
|
||||||
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
|
|
||||||
|
|
||||||
|
|
||||||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{siteId}/{subjectId}/{StaticData.Folder.Reading}/{readingId}/{trustedFileNameForFileStorage}";
|
|
||||||
|
|
||||||
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
|
|
||||||
|
|
||||||
return (serverFilePath, relativePath, fileRealName);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//获取临床数据存放路径
|
|
||||||
public static (string PhysicalPath, string RelativePath,string FileRealName) GetClinicalDataPath(IWebHostEnvironment _hostEnvironment, string fileName,Guid trialId,Guid siteId,Guid subjectId,Guid subjectVisitId)
|
|
||||||
{
|
|
||||||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
|
||||||
|
|
||||||
string uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(),siteId.ToString(), subjectId.ToString(), subjectVisitId.ToString(), StaticData.Folder.TreatmenthistoryFolder);
|
|
||||||
|
|
||||||
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
|
|
||||||
|
|
||||||
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
|
|
||||||
|
|
||||||
|
|
||||||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{siteId}/{subjectId}/{subjectVisitId}/{StaticData.Folder.TreatmenthistoryFolder}/{trustedFileNameForFileStorage}";
|
|
||||||
|
|
||||||
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
|
|
||||||
|
|
||||||
return (serverFilePath, relativePath, fileRealName);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static (string PhysicalPath, string RelativePath, string FileRealName) GetClinicalDataPath(IWebHostEnvironment _hostEnvironment, string fileName, Guid trialId , Guid subjectId)
|
|
||||||
{
|
|
||||||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
|
||||||
|
|
||||||
string uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), subjectId.ToString(), StaticData.Folder.TreatmenthistoryFolder);
|
|
||||||
|
|
||||||
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
|
|
||||||
|
|
||||||
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
|
|
||||||
|
|
||||||
|
|
||||||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{subjectId}/{StaticData.Folder.TreatmenthistoryFolder}/{trustedFileNameForFileStorage}";
|
|
||||||
|
|
||||||
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
|
|
||||||
|
|
||||||
return (serverFilePath, relativePath, fileRealName);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 上传截图
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="_hostEnvironment"></param>
|
|
||||||
/// <param name="fileName"></param>
|
|
||||||
/// <param name="trialId"></param>
|
|
||||||
/// <param name="siteid"></param>
|
|
||||||
/// <param name="subjectId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static (string PhysicalPath, string RelativePath, string FileRealName) GetUploadPrintscreenFilePath(IWebHostEnvironment _hostEnvironment, string fileName, Guid trialId, Guid siteid, Guid subjectId)
|
|
||||||
{
|
|
||||||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
|
||||||
|
|
||||||
string uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), siteid.ToString(), subjectId.ToString());
|
|
||||||
|
|
||||||
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
|
|
||||||
|
|
||||||
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
|
|
||||||
|
|
||||||
|
|
||||||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{siteid}/{subjectId}/{trustedFileNameForFileStorage}";
|
|
||||||
|
|
||||||
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
|
|
||||||
|
|
||||||
return (serverFilePath, relativePath, fileRealName);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 通用获取文件路径
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="_hostEnvironment"></param>
|
|
||||||
/// <param name="fileName"></param>
|
|
||||||
/// <param name="trialId"></param>
|
|
||||||
/// <param name="id"></param>
|
|
||||||
/// <param name="type"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static (string PhysicalPath, string RelativePath, string FileRealName) GetFilePath(IWebHostEnvironment _hostEnvironment, string fileName, Guid trialId, Guid id,string type)
|
|
||||||
{
|
|
||||||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
|
||||||
|
|
||||||
string uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), id.ToString(), type);
|
|
||||||
|
|
||||||
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
|
|
||||||
|
|
||||||
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
|
|
||||||
|
|
||||||
|
|
||||||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{id}/{type}/{trustedFileNameForFileStorage}";
|
|
||||||
|
|
||||||
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
|
|
||||||
|
|
||||||
return (serverFilePath, relativePath, fileRealName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static (string PhysicalPath, string RelativePath, string FileRealName) GetMedicalReviewImage(IWebHostEnvironment _hostEnvironment, string fileName, Guid trialId, Guid taskMedicalReviewId)
|
|
||||||
{
|
|
||||||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
|
||||||
|
|
||||||
string uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), taskMedicalReviewId.ToString(), StaticData.Folder.MedicalReview);
|
|
||||||
|
|
||||||
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
|
|
||||||
|
|
||||||
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
|
|
||||||
|
|
||||||
|
|
||||||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{taskMedicalReviewId}/{StaticData.Folder.MedicalReview}/{trustedFileNameForFileStorage}";
|
|
||||||
|
|
||||||
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
|
|
||||||
|
|
||||||
return (serverFilePath, relativePath, fileRealName);
|
|
||||||
}
|
|
||||||
|
|
||||||
//获取非dicom文件存放路径
|
|
||||||
public static (string PhysicalPath, string RelativePath, string FileRealName) GetNoneDicomFilePath(IWebHostEnvironment _hostEnvironment, string fileName, Guid trialId, Guid siteId, Guid subjectId, Guid subjectVisitId)
|
|
||||||
{
|
|
||||||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
|
||||||
|
|
||||||
string uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), siteId.ToString(), subjectId.ToString(), subjectVisitId.ToString(), StaticData.Folder.NoneDicomFolder);
|
|
||||||
|
|
||||||
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
|
|
||||||
|
|
||||||
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
|
|
||||||
|
|
||||||
|
|
||||||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{siteId}/{subjectId}/{subjectVisitId}/{StaticData.Folder.NoneDicomFolder}/{trustedFileNameForFileStorage}";
|
|
||||||
|
|
||||||
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
|
|
||||||
|
|
||||||
return (serverFilePath, relativePath, fileRealName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取 入组确认 PD 进展发送邮件Word|PDF 存放路径
|
// 获取 入组确认 PD 进展发送邮件Word|PDF 存放路径
|
||||||
|
|
||||||
public static (string PhysicalPath, string RelativePath, string FileRealName) GetSubjectEnrollConfirmOrPDEmailPath(IWebHostEnvironment _hostEnvironment, string fileName, Guid trialId, Guid trialSiteId, Guid subjectId,bool isChangeToPdfFormat=false)
|
public static (string PhysicalPath, string RelativePath, string FileRealName) GetSubjectEnrollConfirmOrPDEmailPath(IWebHostEnvironment _hostEnvironment, string fileName, Guid trialId, Guid trialSiteId, Guid subjectId,bool isChangeToPdfFormat=false)
|
||||||
@@ -629,49 +316,7 @@ public static class FileStoreHelper
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 获取医生通用文件存放路径
|
|
||||||
|
|
||||||
public static (string PhysicalPath, string RelativePath) GetDoctorOrdinaryFilePath(IWebHostEnvironment _hostEnvironment, string fileName,Guid doctorId,string attachmentType)
|
|
||||||
{
|
|
||||||
|
|
||||||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
|
||||||
|
|
||||||
//文件类型路径处理
|
|
||||||
var uploadFolderPath = Path.Combine(rootPath, "UploadFile", doctorId.ToString(), attachmentType);
|
|
||||||
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
|
|
||||||
|
|
||||||
|
|
||||||
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.UploadFileFolder}/{doctorId}/{attachmentType}/{trustedFileNameForFileStorage}";
|
|
||||||
|
|
||||||
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
|
|
||||||
|
|
||||||
return (serverFilePath, relativePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static (string PhysicalPath, string RelativePath) GetNonDoctorFilePath(IWebHostEnvironment _hostEnvironment, string fileName, string attachmentType)
|
|
||||||
{
|
|
||||||
|
|
||||||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
|
||||||
|
|
||||||
//文件类型路径处理
|
|
||||||
var uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.UploadFileFolder, attachmentType);
|
|
||||||
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
|
|
||||||
|
|
||||||
|
|
||||||
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.UploadFileFolder}/{attachmentType}/{trustedFileNameForFileStorage}";
|
|
||||||
|
|
||||||
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
|
|
||||||
|
|
||||||
return (serverFilePath, relativePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using static BeetleX.Redis.Commands.HSCAN;
|
|
||||||
using static IRaCIS.Core.Application.Service.Common.SystemMonitor;
|
using static IRaCIS.Core.Application.Service.Common.SystemMonitor;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Helper
|
namespace IRaCIS.Core.Application.Helper
|
||||||
@@ -18,6 +17,9 @@ namespace IRaCIS.Core.Application.Helper
|
|||||||
{
|
{
|
||||||
public static string JsonFileFolder = Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources);
|
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()
|
private static void VerifyFolder()
|
||||||
{
|
{
|
||||||
if (!Directory.Exists(JsonFileFolder) ||
|
if (!Directory.Exists(JsonFileFolder) ||
|
||||||
@@ -51,6 +53,9 @@ namespace IRaCIS.Core.Application.Helper
|
|||||||
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
|
else
|
||||||
@@ -69,7 +74,7 @@ namespace IRaCIS.Core.Application.Helper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task AddOrUpdateJsonKeyValueAsync(string key, string value, string valueCN)
|
public static async Task AddOrUpdateJsonKeyValueAsync(string key, string value, string valueCN,string description)
|
||||||
{
|
{
|
||||||
|
|
||||||
VerifyFolder();
|
VerifyFolder();
|
||||||
@@ -92,6 +97,9 @@ namespace IRaCIS.Core.Application.Helper
|
|||||||
jsonObject[key] = value;
|
jsonObject[key] = value;
|
||||||
|
|
||||||
StaticData.En_US_Dic[key] = value;
|
StaticData.En_US_Dic[key] = value;
|
||||||
|
|
||||||
|
//日志记录该信息方便自己人看, 返回给客户的是配置的
|
||||||
|
StaticData.Log_Locoalize_Dic[key] = description;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -107,14 +115,16 @@ namespace IRaCIS.Core.Application.Helper
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task InitInternationlizationDataAndWatchJsonFileAsync(IRepository _repository)
|
|
||||||
|
public static async Task InitInternationlizationDataAndWatchJsonFileAsync(IRepository<Internationalization> _internationalizationRepository)
|
||||||
{
|
{
|
||||||
//查询数据库的数据
|
//查询数据库的数据
|
||||||
var toJsonList = await _repository.Where<Internationalization>(t => t.InternationalizationType == 1).Select(t => new
|
var toJsonList = await _internationalizationRepository.Where(t => t.InternationalizationType == 1).Select(t => new
|
||||||
{
|
{
|
||||||
t.Code,
|
t.Code,
|
||||||
t.Value,
|
t.Value,
|
||||||
t.ValueCN
|
t.ValueCN,
|
||||||
|
t.Description
|
||||||
}).ToListAsync();
|
}).ToListAsync();
|
||||||
|
|
||||||
//组织成json 文件
|
//组织成json 文件
|
||||||
@@ -128,6 +138,9 @@ namespace IRaCIS.Core.Application.Helper
|
|||||||
{
|
{
|
||||||
StaticData.En_US_Dic[tojsonItem.Code] = tojsonItem.Value;
|
StaticData.En_US_Dic[tojsonItem.Code] = tojsonItem.Value;
|
||||||
StaticData.Zh_CN_Dic[tojsonItem.Code] = tojsonItem.ValueCN;
|
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(usJsonPath, JsonConvert.SerializeObject(StaticData.En_US_Dic));
|
||||||
@@ -136,29 +149,45 @@ namespace IRaCIS.Core.Application.Helper
|
|||||||
|
|
||||||
//监测Json文件变更 实时刷新数据
|
//监测Json文件变更 实时刷新数据
|
||||||
|
|
||||||
WatchJsonFile(usJsonPath);
|
if (!File.Exists(usJsonPath) || !File.Exists(cnJsonPath))
|
||||||
WatchJsonFile(cnJsonPath);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void WatchJsonFile(string filePath)
|
|
||||||
{
|
|
||||||
if (!File.Exists(filePath))
|
|
||||||
{
|
{
|
||||||
throw new BusinessValidationFailedException("国际化Json文件不存在");
|
throw new BusinessValidationFailedException(StaticData.International("IRaCISCHangfireJob_FileNotFound"));
|
||||||
}
|
}
|
||||||
|
|
||||||
FileSystemWatcher watcher = new FileSystemWatcher(Path.GetDirectoryName(filePath), Path.GetFileName(filePath));
|
|
||||||
watcher.Changed += (sender, e) => LoadJsonFile(filePath);
|
// //监测Json文件变更 实时刷新数据
|
||||||
watcher.EnableRaisingEvents = true;
|
|
||||||
|
|
||||||
|
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)
|
private static void LoadJsonFile(string filePath)
|
||||||
{
|
{
|
||||||
|
Console.WriteLine("刷新json内存数据");
|
||||||
IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile(filePath);
|
IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile(filePath, false, false);
|
||||||
|
|
||||||
IConfigurationRoot enConfiguration = builder.Build();
|
IConfigurationRoot enConfiguration = builder.Build();
|
||||||
|
|
||||||
@@ -175,5 +204,11 @@ namespace IRaCIS.Core.Application.Helper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
using Aliyun.OSS;
|
using Aliyun.OSS;
|
||||||
using IRaCIS.Core.Application.Contracts;
|
|
||||||
using IRaCIS.Core.Infrastructure;
|
using IRaCIS.Core.Infrastructure;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Minio.DataModel.Args;
|
using Minio.DataModel.Args;
|
||||||
using Minio;
|
using Minio;
|
||||||
using NPOI.HPSF;
|
|
||||||
using SharpCompress.Common;
|
using SharpCompress.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -15,6 +13,7 @@ using System.Linq;
|
|||||||
using System.Security.AccessControl;
|
using System.Security.AccessControl;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Helper
|
namespace IRaCIS.Core.Application.Helper
|
||||||
{
|
{
|
||||||
@@ -39,6 +38,9 @@ namespace IRaCIS.Core.Application.Helper
|
|||||||
public string regionId { get; set; }
|
public string regionId { get; set; }
|
||||||
public string accessKeyId { get; set; }
|
public string accessKeyId { get; set; }
|
||||||
public string accessKeySecret { get; set; }
|
public string accessKeySecret { get; set; }
|
||||||
|
|
||||||
|
public string internalEndpoint { get; set; }
|
||||||
|
|
||||||
public string endPoint { get; set; }
|
public string endPoint { get; set; }
|
||||||
public string bucketName { get; set; }
|
public string bucketName { get; set; }
|
||||||
|
|
||||||
@@ -131,66 +133,76 @@ namespace IRaCIS.Core.Application.Helper
|
|||||||
//var ossRelativePath = $"{oosFolderPath}/{Guid.NewGuid()}_{fileRealName}";
|
//var ossRelativePath = $"{oosFolderPath}/{Guid.NewGuid()}_{fileRealName}";
|
||||||
//var ossRelativePath = oosFolderPath + "/" + fileRealName;
|
//var ossRelativePath = oosFolderPath + "/" + fileRealName;
|
||||||
|
|
||||||
using (var memoryStream = new MemoryStream())
|
try
|
||||||
{
|
{
|
||||||
fileStream.Seek(0, SeekOrigin.Begin);
|
using (var memoryStream = new MemoryStream())
|
||||||
|
|
||||||
fileStream.CopyTo(memoryStream);
|
|
||||||
|
|
||||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
|
||||||
|
|
||||||
|
|
||||||
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
|
|
||||||
{
|
{
|
||||||
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
|
fileStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
|
||||||
var _ossClient = new OssClient(aliConfig.endPoint, aliConfig.accessKeyId, aliConfig.accessKeySecret);
|
fileStream.CopyTo(memoryStream);
|
||||||
|
|
||||||
|
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
|
||||||
|
|
||||||
|
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
|
||||||
|
{
|
||||||
|
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
|
||||||
|
|
||||||
|
var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.endPoint : aliConfig.internalEndpoint, aliConfig.accessKeyId, aliConfig.accessKeySecret);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 上传文件
|
// 上传文件
|
||||||
var result = _ossClient.PutObject(aliConfig.bucketName, ossRelativePath, memoryStream);
|
var result = _ossClient.PutObject(aliConfig.bucketName, ossRelativePath, memoryStream);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
|
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
|
||||||
{
|
{
|
||||||
var minIOConfig = ObjectStoreServiceOptions.MinIO;
|
var minIOConfig = ObjectStoreServiceOptions.MinIO;
|
||||||
|
|
||||||
|
|
||||||
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.endPoint}:{minIOConfig.port}")
|
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.endPoint}:{minIOConfig.port}")
|
||||||
.WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL)
|
.WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var putObjectArgs = new PutObjectArgs()
|
var putObjectArgs = new PutObjectArgs()
|
||||||
.WithBucket(minIOConfig.bucketName)
|
.WithBucket(minIOConfig.bucketName)
|
||||||
.WithObject(ossRelativePath)
|
.WithObject(ossRelativePath)
|
||||||
.WithStreamData(memoryStream)
|
.WithStreamData(memoryStream)
|
||||||
.WithObjectSize(memoryStream.Length);
|
.WithObjectSize(memoryStream.Length);
|
||||||
|
|
||||||
await minioClient.PutObjectAsync(putObjectArgs);
|
await minioClient.PutObjectAsync(putObjectArgs);
|
||||||
}
|
}
|
||||||
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
|
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
|
||||||
{
|
{
|
||||||
var minIOConfig = ObjectStoreServiceOptions.AWS;
|
var minIOConfig = ObjectStoreServiceOptions.AWS;
|
||||||
|
|
||||||
|
|
||||||
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.endPoint}")
|
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.endPoint}")
|
||||||
.WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL)
|
.WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var putObjectArgs = new PutObjectArgs()
|
var putObjectArgs = new PutObjectArgs()
|
||||||
.WithBucket(minIOConfig.bucketName)
|
.WithBucket(minIOConfig.bucketName)
|
||||||
.WithObject(ossRelativePath)
|
.WithObject(ossRelativePath)
|
||||||
.WithStreamData(memoryStream)
|
.WithStreamData(memoryStream)
|
||||||
.WithObjectSize(memoryStream.Length);
|
.WithObjectSize(memoryStream.Length);
|
||||||
|
|
||||||
await minioClient.PutObjectAsync(putObjectArgs);
|
await minioClient.PutObjectAsync(putObjectArgs);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new BusinessValidationFailedException("未定义的存储介质类型");
|
throw new BusinessValidationFailedException("未定义的存储介质类型");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
|
||||||
|
throw new BusinessValidationFailedException($"上传发生异常:{ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return "/" + ossRelativePath;
|
return "/" + ossRelativePath;
|
||||||
@@ -220,7 +232,7 @@ namespace IRaCIS.Core.Application.Helper
|
|||||||
{
|
{
|
||||||
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
|
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
|
||||||
|
|
||||||
var _ossClient = new OssClient(aliConfig.endPoint, aliConfig.accessKeyId, aliConfig.accessKeySecret);
|
var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows)? aliConfig.endPoint: aliConfig.internalEndpoint, aliConfig.accessKeyId, aliConfig.accessKeySecret);
|
||||||
|
|
||||||
// 上传文件
|
// 上传文件
|
||||||
var result = _ossClient.PutObject(aliConfig.bucketName, ossRelativePath, localFilePath);
|
var result = _ossClient.PutObject(aliConfig.bucketName, ossRelativePath, localFilePath);
|
||||||
@@ -279,7 +291,7 @@ namespace IRaCIS.Core.Application.Helper
|
|||||||
{
|
{
|
||||||
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
|
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
|
||||||
|
|
||||||
var _ossClient = new OssClient(aliConfig.endPoint, aliConfig.accessKeyId, aliConfig.accessKeySecret);
|
var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.endPoint : aliConfig.internalEndpoint, aliConfig.accessKeyId, aliConfig.accessKeySecret);
|
||||||
|
|
||||||
// 上传文件
|
// 上传文件
|
||||||
var result = _ossClient.GetObject(aliConfig.bucketName, ossRelativePath);
|
var result = _ossClient.GetObject(aliConfig.bucketName, ossRelativePath);
|
||||||
@@ -351,7 +363,7 @@ namespace IRaCIS.Core.Application.Helper
|
|||||||
{
|
{
|
||||||
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
|
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
|
||||||
|
|
||||||
var _ossClient = new OssClient(aliConfig.endPoint, aliConfig.accessKeyId, aliConfig.accessKeySecret);
|
var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.endPoint : aliConfig.internalEndpoint, aliConfig.accessKeyId, aliConfig.accessKeySecret);
|
||||||
|
|
||||||
// 生成签名URL。
|
// 生成签名URL。
|
||||||
var req = new GeneratePresignedUriRequest(aliConfig.bucketName, ossRelativePath, SignHttpMethod.Get)
|
var req = new GeneratePresignedUriRequest(aliConfig.bucketName, ossRelativePath, SignHttpMethod.Get)
|
||||||
@@ -372,10 +384,6 @@ namespace IRaCIS.Core.Application.Helper
|
|||||||
.WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL)
|
.WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
//var reqParams = new Dictionary<string, string>(StringComparer.Ordinal)
|
|
||||||
// {
|
|
||||||
// { "response-content-type", "application/json" }
|
|
||||||
// };
|
|
||||||
|
|
||||||
var args = new PresignedGetObjectArgs()
|
var args = new PresignedGetObjectArgs()
|
||||||
.WithBucket(minIOConfig.bucketName)
|
.WithBucket(minIOConfig.bucketName)
|
||||||
@@ -401,7 +409,19 @@ namespace IRaCIS.Core.Application.Helper
|
|||||||
.WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL)
|
.WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
return string.Empty;
|
var args = new PresignedGetObjectArgs()
|
||||||
|
.WithBucket(minIOConfig.bucketName)
|
||||||
|
.WithObject(ossRelativePath)
|
||||||
|
.WithExpiry(3600);
|
||||||
|
|
||||||
|
var presignedUrl = await minioClient.PresignedGetObjectAsync(args);
|
||||||
|
|
||||||
|
Uri uri = new Uri(presignedUrl);
|
||||||
|
|
||||||
|
string relativePath = uri.PathAndQuery;
|
||||||
|
|
||||||
|
|
||||||
|
return relativePath;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Org.BouncyCastle.Crypto;
|
||||||
|
using Org.BouncyCastle.Crypto.Encodings;
|
||||||
|
using Org.BouncyCastle.Crypto.Engines;
|
||||||
|
using Org.BouncyCastle.Crypto.Generators;
|
||||||
|
using Org.BouncyCastle.OpenSsl;
|
||||||
|
using Org.BouncyCastle.Security;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.Application.Helper
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// https://www.cnblogs.com/NBDWDYS2214143926/p/13329231.html
|
||||||
|
/// </summary>
|
||||||
|
public class RSAHelper
|
||||||
|
{
|
||||||
|
|
||||||
|
public static AsymmetricCipherKeyPair GenerateRSAKeyPair(int keySize)
|
||||||
|
{
|
||||||
|
var keyGenerationParameters = new KeyGenerationParameters(new SecureRandom(), keySize);
|
||||||
|
var keyPairGenerator = new RsaKeyPairGenerator();
|
||||||
|
keyPairGenerator.Init(keyGenerationParameters);
|
||||||
|
return keyPairGenerator.GenerateKeyPair();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ExportPublicKey(AsymmetricKeyParameter publicKey)
|
||||||
|
{
|
||||||
|
using (StringWriter sw = new StringWriter())
|
||||||
|
{
|
||||||
|
PemWriter pw = new PemWriter(sw);
|
||||||
|
pw.WriteObject(publicKey);
|
||||||
|
pw.Writer.Flush();
|
||||||
|
return sw.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ExportPrivateKey(AsymmetricKeyParameter privateKey)
|
||||||
|
{
|
||||||
|
using (StringWriter sw = new StringWriter())
|
||||||
|
{
|
||||||
|
PemWriter pw = new PemWriter(sw);
|
||||||
|
pw.WriteObject(privateKey);
|
||||||
|
pw.Writer.Flush();
|
||||||
|
return sw.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// RSA解密
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="privateKey">私钥</param>
|
||||||
|
/// <param name="decryptstring">待解密的字符串(Base64)</param>
|
||||||
|
/// <returns>解密后的字符串</returns>
|
||||||
|
public static string Decrypt(string privateKey, string decryptstring)
|
||||||
|
{
|
||||||
|
using (TextReader reader = new StringReader(privateKey))
|
||||||
|
{
|
||||||
|
dynamic key = new PemReader(reader).ReadObject();
|
||||||
|
var rsaDecrypt = new Pkcs1Encoding(new RsaEngine());
|
||||||
|
if (key is AsymmetricKeyParameter)
|
||||||
|
{
|
||||||
|
key = (AsymmetricKeyParameter)key;
|
||||||
|
}
|
||||||
|
else if (key is AsymmetricCipherKeyPair)
|
||||||
|
{
|
||||||
|
key = ((AsymmetricCipherKeyPair)key).Private;
|
||||||
|
}
|
||||||
|
rsaDecrypt.Init(false, key); //这里加密是true;解密是false
|
||||||
|
|
||||||
|
byte[] entData = Convert.FromBase64String(decryptstring);
|
||||||
|
entData = rsaDecrypt.ProcessBlock(entData, 0, entData.Length);
|
||||||
|
return Encoding.UTF8.GetString(entData);
|
||||||
|
}
|
||||||
|
}/// <summary>
|
||||||
|
|
||||||
|
/// 加密
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="publicKey">公钥</param>
|
||||||
|
/// <param name="encryptstring">待加密的字符串</param>
|
||||||
|
/// <returns>加密后的Base64</returns>
|
||||||
|
public static string Encrypt(string publicKey, string encryptstring)
|
||||||
|
{
|
||||||
|
using (TextReader reader = new StringReader(publicKey))
|
||||||
|
{
|
||||||
|
AsymmetricKeyParameter key = new PemReader(reader).ReadObject() as AsymmetricKeyParameter;
|
||||||
|
Pkcs1Encoding pkcs1 = new Pkcs1Encoding(new RsaEngine());
|
||||||
|
pkcs1.Init(true, key);//加密是true;解密是false;
|
||||||
|
byte[] entData = Encoding.UTF8.GetBytes(encryptstring);
|
||||||
|
entData = pkcs1.ProcessBlock(entData, 0, entData.Length);
|
||||||
|
return Convert.ToBase64String(entData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -29,7 +29,7 @@ public static class SendEmailHelper
|
|||||||
|
|
||||||
//await smtp.AuthenticateAsync("zhou941003@qq.com", "sqfhlpfdvnexbcab");
|
//await smtp.AuthenticateAsync("zhou941003@qq.com", "sqfhlpfdvnexbcab");
|
||||||
|
|
||||||
await smtp.ConnectAsync(_systemEmailConfig.Host, _systemEmailConfig.Port, SecureSocketOptions.SslOnConnect);
|
await smtp.ConnectAsync(_systemEmailConfig.Host, _systemEmailConfig.Port, SecureSocketOptions.Auto);
|
||||||
|
|
||||||
await smtp.AuthenticateAsync(_systemEmailConfig.FromEmail, _systemEmailConfig.AuthorizationCode);
|
await smtp.AuthenticateAsync(_systemEmailConfig.FromEmail, _systemEmailConfig.AuthorizationCode);
|
||||||
|
|
||||||
@@ -52,15 +52,19 @@ public static class SendEmailHelper
|
|||||||
|
|
||||||
public static async Task<bool> TestEmailConfigAsync(SystemEmailSendConfig _systemEmailConfig)
|
public static async Task<bool> TestEmailConfigAsync(SystemEmailSendConfig _systemEmailConfig)
|
||||||
{
|
{
|
||||||
using (var client = new MailKit.Net.Smtp.SmtpClient())
|
using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5)))
|
||||||
{
|
{
|
||||||
|
using (var client = new MailKit.Net.Smtp.SmtpClient())
|
||||||
|
{
|
||||||
|
|
||||||
await client.ConnectAsync(_systemEmailConfig.Host, _systemEmailConfig.Port, SecureSocketOptions.SslOnConnect);
|
await client.ConnectAsync(_systemEmailConfig.Host, _systemEmailConfig.Port, SecureSocketOptions.Auto, cts.Token);
|
||||||
|
|
||||||
await client.AuthenticateAsync(_systemEmailConfig.FromEmail, _systemEmailConfig.AuthorizationCode);
|
await client.AuthenticateAsync(_systemEmailConfig.FromEmail, _systemEmailConfig.AuthorizationCode, cts.Token);
|
||||||
|
|
||||||
await client.DisconnectAsync(true);
|
await client.DisconnectAsync(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -133,7 +137,7 @@ public static class SendEmailHelper
|
|||||||
|
|
||||||
smtp.ServerCertificateValidationCallback = (s, c, h, e) => true;
|
smtp.ServerCertificateValidationCallback = (s, c, h, e) => true;
|
||||||
|
|
||||||
await smtp.ConnectAsync(sMTPEmailConfig.Host, sMTPEmailConfig.Port, SecureSocketOptions.SslOnConnect);
|
await smtp.ConnectAsync(sMTPEmailConfig.Host, sMTPEmailConfig.Port, SecureSocketOptions.Auto);
|
||||||
|
|
||||||
await smtp.AuthenticateAsync(sMTPEmailConfig.UserName, sMTPEmailConfig.AuthorizationCode);
|
await smtp.AuthenticateAsync(sMTPEmailConfig.UserName, sMTPEmailConfig.AuthorizationCode);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,101 @@
|
|||||||
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using NPOI.XWPF.UserModel;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Xceed.Document.NET;
|
||||||
|
using Xceed.Words.NET;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.Application.Helper
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 利用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);
|
||||||
|
|
||||||
|
if (bookmarkEn_Start != null)
|
||||||
|
{
|
||||||
|
// 获取书签的起始位置
|
||||||
|
//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)
|
||||||
|
{
|
||||||
|
paragraphsToRemove.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var paragraph in paragraphsToRemove)
|
||||||
|
{
|
||||||
|
document.RemoveParagraph(paragraph);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存修改
|
||||||
|
document.SaveAs(memoryStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void Npoi_GetInternationalTempleteStream(string filePath, Stream memoryStream)
|
||||||
|
{
|
||||||
|
|
||||||
|
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
||||||
|
|
||||||
|
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
|
||||||
|
{
|
||||||
|
XWPFDocument doc = new XWPFDocument(fs);
|
||||||
|
|
||||||
|
// 查找包含指定书签的段落及其索引
|
||||||
|
var bookmarkParagraph = doc.Paragraphs
|
||||||
|
.FirstOrDefault(p => p.GetCTP().GetBookmarkStartList().Any(b => b.name == StaticData.CultureInfo.en_US_bookMark));
|
||||||
|
|
||||||
|
if (bookmarkParagraph != null)
|
||||||
|
{
|
||||||
|
int bookmarkIndex = doc.Paragraphs.IndexOf(bookmarkParagraph);
|
||||||
|
|
||||||
|
if (isEn_US)
|
||||||
|
{
|
||||||
|
// 从书签所在段落开始,删除之前的所有段落
|
||||||
|
for (int i = bookmarkIndex - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
doc.RemoveBodyElement(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 删除书签之后的所有段落
|
||||||
|
for (int i = doc.Paragraphs.Count - 1; i >= bookmarkIndex; i--)
|
||||||
|
{
|
||||||
|
doc.RemoveBodyElement(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
doc.Write(memoryStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="IRaCIS.Core.Application.xml" />
|
<None Remove="IRaCIS.Core.Application.xml" />
|
||||||
<None Remove="Resources\en-US.json" />
|
<None Remove="Resources\en-US.json" />
|
||||||
<None Remove="Resources\zh-CN.json" />
|
<None Remove="Resources\zh_ch.json" />
|
||||||
<None Remove="Service\Allocation\TaskConsistentRuleService.cs~RF1603d47.TMP" />
|
<None Remove="Service\Allocation\TaskConsistentRuleService.cs~RF1603d47.TMP" />
|
||||||
<None Remove="Service\Reading\ReadingImageTask\ReadingImageTaskService.cs~RF2f9323.TMP" />
|
<None Remove="Service\Reading\ReadingImageTask\ReadingImageTaskService.cs~RF2f9323.TMP" />
|
||||||
<None Remove="Service\Reading\ReadingImageTask\ReadingJudgeTaskService.cs~RF198afd23.TMP" />
|
<None Remove="Service\Reading\ReadingImageTask\ReadingJudgeTaskService.cs~RF198afd23.TMP" />
|
||||||
@@ -50,11 +50,6 @@
|
|||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="Resources\zh-CN.json">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="Resources\en-US.json">
|
<Content Include="Resources\en-US.json">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||||
@@ -63,10 +58,10 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.13.0" />
|
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.13.0" />
|
||||||
|
<PackageReference Include="DocX" Version="3.0.1" />
|
||||||
<PackageReference Include="FreeSpire.Doc" Version="12.2.0" />
|
<PackageReference Include="FreeSpire.Doc" Version="12.2.0" />
|
||||||
<PackageReference Include="Hangfire.Core" Version="1.8.12" />
|
<PackageReference Include="Hangfire.Core" Version="1.8.14" />
|
||||||
<PackageReference Include="BeetleX.BNR" Version="1.0.1" />
|
|
||||||
<PackageReference Include="Castle.Core.AsyncInterceptor" Version="2.1.0" />
|
<PackageReference Include="Castle.Core.AsyncInterceptor" Version="2.1.0" />
|
||||||
<PackageReference Include="EasyCaching.Redis" Version="1.9.2" />
|
<PackageReference Include="EasyCaching.Redis" Version="1.9.2" />
|
||||||
<PackageReference Include="EasyCaching.InMemory" Version="1.9.2" />
|
<PackageReference Include="EasyCaching.InMemory" Version="1.9.2" />
|
||||||
@@ -74,24 +69,24 @@
|
|||||||
<PackageReference Include="ExcelDataReader.DataSet" Version="3.6.0" />
|
<PackageReference Include="ExcelDataReader.DataSet" Version="3.6.0" />
|
||||||
<PackageReference Include="DistributedLock.Redis" Version="1.0.3" />
|
<PackageReference Include="DistributedLock.Redis" Version="1.0.3" />
|
||||||
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.4" />
|
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.4" />
|
||||||
<PackageReference Include="fo-dicom" Version="5.1.2" />
|
<PackageReference Include="fo-dicom" Version="5.1.3" />
|
||||||
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.1.2" />
|
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.1.3" />
|
||||||
<PackageReference Include="fo-dicom.Codecs" Version="5.12.0" />
|
<PackageReference Include="fo-dicom.Codecs" Version="5.14.4" />
|
||||||
<PackageReference Include="IP2Region.Net" Version="2.0.2" />
|
<PackageReference Include="IP2Region.Net" Version="2.0.2" />
|
||||||
<PackageReference Include="MailKit" Version="4.5.0" />
|
<PackageReference Include="MailKit" Version="4.2.0" />
|
||||||
<PackageReference Include="MediatR" Version="12.2.0" />
|
<PackageReference Include="MimeKit" Version="4.2.0" />
|
||||||
<PackageReference Include="MimeKit" Version="4.5.0" />
|
|
||||||
<PackageReference Include="MiniExcel" Version="1.32.0" />
|
<PackageReference Include="MiniExcel" Version="1.32.0" />
|
||||||
<PackageReference Include="Minio" Version="6.0.2" />
|
<PackageReference Include="Minio" Version="6.0.3" />
|
||||||
<PackageReference Include="MiniWord" Version="0.8.0" />
|
<PackageReference Include="MiniWord" Version="0.8.0" />
|
||||||
<PackageReference Include="My.Extensions.Localization.Json" Version="3.3.0">
|
<PackageReference Include="My.Extensions.Localization.Json" Version="3.3.0">
|
||||||
<TreatAsUsed>true</TreatAsUsed>
|
<TreatAsUsed>true</TreatAsUsed>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="NPOI" Version="2.7.0" />
|
<PackageReference Include="NPOI" Version="2.7.1" />
|
||||||
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" />
|
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" />
|
||||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.4" />
|
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.5" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.2" />
|
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.2" />
|
||||||
<PackageReference Include="WinSCP" Version="6.3.3" />
|
<PackageReference Include="MassTransit.AspNetCore" Version="7.3.1" />
|
||||||
|
<PackageReference Include="ZiggyCreatures.FusionCache" Version="1.3.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,96 @@
|
|||||||
|
using MiniExcelLibs.Attributes;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.Application.MassTransit.Command
|
||||||
|
{
|
||||||
|
public record ConsistenCheckCommand
|
||||||
|
{
|
||||||
|
public List<CheckViewModel> ETCList { get; set; } = new List<CheckViewModel>();
|
||||||
|
|
||||||
|
public Guid TrialId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public record ConsistenCheckResult
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CheckDBModel : CheckViewModel
|
||||||
|
{
|
||||||
|
|
||||||
|
public Guid SubjectVisitId { get; set; }
|
||||||
|
|
||||||
|
public Guid StudyId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//[ExcelImporter(/*ImportResultFilter = typeof(ImportResultFilteTest),*/ IsLabelingError = true)]
|
||||||
|
|
||||||
|
public class CheckViewModel
|
||||||
|
{
|
||||||
|
//[Required(ErrorMessage = "中心编号不能为空")]
|
||||||
|
//[ImporterHeader(Name = "Site ID", AutoTrim = true)]
|
||||||
|
[ExcelColumnName("Site ID")]
|
||||||
|
public string SiteCode { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
|
||||||
|
//[Required(ErrorMessage = "受试者筛选号不能为空")]
|
||||||
|
//[ImporterHeader(Name = "Subject ID", AutoTrim = true)]
|
||||||
|
[ExcelColumnName("Subject ID")]
|
||||||
|
public string SubjectCode { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
//[Required(ErrorMessage = "访视名称不能为空")]
|
||||||
|
//[ImporterHeader(Name = "Visit Name", AutoTrim = true)]
|
||||||
|
[ExcelColumnName("Visit Name")]
|
||||||
|
public string VisitName { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//[Required(ErrorMessage = "检查日期不能为空")]
|
||||||
|
[CanConvertToTime(ErrorMessage = "Does not conform to Study Date format")]
|
||||||
|
|
||||||
|
//[ImporterHeader(Name = "Study Date", AutoTrim = true)]
|
||||||
|
[ExcelColumnName("Study Date")]
|
||||||
|
public string StudyDate { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//[Required(ErrorMessage = "Modality不能为空")]
|
||||||
|
//[ImporterHeader(Name = "Modality", AutoTrim = true)]
|
||||||
|
[ExcelColumnName("Modality")]
|
||||||
|
public string Modality { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public override bool Equals(object? obj)
|
||||||
|
{
|
||||||
|
if (obj == null) return false;
|
||||||
|
|
||||||
|
var checkModel = obj as CheckViewModel;
|
||||||
|
|
||||||
|
if (checkModel is not null)
|
||||||
|
{
|
||||||
|
return SiteCode == checkModel.SiteCode && SubjectCode == checkModel.SubjectCode && VisitName == checkModel.VisitName && StudyDate == checkModel.StudyDate && Modality == checkModel.Modality;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return (SiteCode + SubjectCode + VisitName + StudyDate + Modality).GetHashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+27
-16
@@ -1,16 +1,22 @@
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using IRaCIS.Core.Application.MediatR.CommandAndQueries;
|
using IRaCIS.Core.Application.Contracts.DTO;
|
||||||
|
using IRaCIS.Core.Application.MassTransit.Command;
|
||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using MassTransit;
|
||||||
|
using Microsoft.Extensions.Localization;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using MediatR;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Microsoft.Extensions.Localization;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.MediatR.Handlers
|
namespace IRaCIS.Core.Application.MassTransit.Consumer
|
||||||
{
|
{
|
||||||
public class ConsistencyVerificationHandler : IRequestHandler<ConsistencyVerificationRequest, string>
|
public class ConsistencyCheckConsumer : IConsumer<ConsistenCheckCommand>
|
||||||
{
|
{
|
||||||
|
|
||||||
private readonly IRepository<DicomStudy> _studyRepository;
|
private readonly IRepository<DicomStudy> _studyRepository;
|
||||||
private readonly IUserInfo _userInfo;
|
private readonly IUserInfo _userInfo;
|
||||||
private readonly IRepository<Subject> _subjectRepository;
|
private readonly IRepository<Subject> _subjectRepository;
|
||||||
@@ -24,7 +30,7 @@ namespace IRaCIS.Core.Application.MediatR.Handlers
|
|||||||
/// 构造函数注入
|
/// 构造函数注入
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
||||||
public ConsistencyVerificationHandler(IRepository<DicomStudy> studyRepository, IUserInfo userInfo,
|
public ConsistencyCheckConsumer(IRepository<DicomStudy> studyRepository, IUserInfo userInfo,
|
||||||
IRepository<Subject> subjectRepository, IRepository<SubjectVisit> subjectVisitRepository,
|
IRepository<Subject> subjectRepository, IRepository<SubjectVisit> subjectVisitRepository,
|
||||||
IRepository<TrialSite> trialSiteRepository, IRepository<NoneDicomStudy> noneDicomStudyRepository,
|
IRepository<TrialSite> trialSiteRepository, IRepository<NoneDicomStudy> noneDicomStudyRepository,
|
||||||
IMapper mapper, IStringLocalizer localizer)
|
IMapper mapper, IStringLocalizer localizer)
|
||||||
@@ -39,19 +45,22 @@ namespace IRaCIS.Core.Application.MediatR.Handlers
|
|||||||
_localizer = localizer;
|
_localizer = localizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
async Task<string> IRequestHandler<ConsistencyVerificationRequest, string>.Handle(ConsistencyVerificationRequest request, CancellationToken cancellationToken)
|
|
||||||
|
|
||||||
|
public async Task Consume(ConsumeContext<ConsistenCheckCommand> context)
|
||||||
{
|
{
|
||||||
var trialId = request.TrialId;
|
|
||||||
|
var trialId = context.Message.TrialId;
|
||||||
|
|
||||||
//处理Excel大小写
|
//处理Excel大小写
|
||||||
request.ETCList.ForEach(t => { t.Modality = t.Modality.ToUpper().Trim(); t.StudyDate = Convert.ToDateTime(t.StudyDate).ToString("yyyy-MM-dd"); t.SiteCode = t.SiteCode.ToUpper().Trim(); t.VisitName = t.VisitName.ToUpper().Trim(); t.SubjectCode = t.SubjectCode.ToUpper().Trim(); });
|
context.Message.ETCList.ForEach(t => { t.Modality = t.Modality.ToUpper().Trim(); t.StudyDate = Convert.ToDateTime(t.StudyDate).ToString("yyyy-MM-dd"); t.SiteCode = t.SiteCode.ToUpper().Trim(); t.VisitName = t.VisitName.ToUpper().Trim(); t.SubjectCode = t.SubjectCode.ToUpper().Trim(); });
|
||||||
var etcList = request.ETCList;
|
var etcList = context.Message.ETCList;
|
||||||
|
|
||||||
//Expression<Func<SubjectVisit, bool>> subjectVisitLambda2 = x => x.TrialId == request.TrialId;
|
//Expression<Func<SubjectVisit, bool>> subjectVisitLambda2 = x => x.TrialId == request.TrialId;
|
||||||
|
|
||||||
//subjectVisitLambda2= subjectVisitLambda2.And(x => x.CheckState == CheckStateEnum.ToCheck && x.AuditState == AuditStateEnum.QCPassed || (x.CheckState == CheckStateEnum.CVIng && x.AuditState == AuditStateEnum.QCPassed));
|
//subjectVisitLambda2= subjectVisitLambda2.And(x => x.CheckState == CheckStateEnum.ToCheck && x.AuditState == AuditStateEnum.QCPassed || (x.CheckState == CheckStateEnum.CVIng && x.AuditState == AuditStateEnum.QCPassed));
|
||||||
|
|
||||||
Expression<Func<SubjectVisit, bool>> subjectVisitLambda = x => x.TrialId == request.TrialId &&
|
Expression<Func<SubjectVisit, bool>> subjectVisitLambda = x => x.TrialId == trialId &&
|
||||||
(x.CheckState == CheckStateEnum.ToCheck && x.AuditState == AuditStateEnum.QCPassed || (x.CheckState == CheckStateEnum.CVIng && x.AuditState == AuditStateEnum.QCPassed));
|
(x.CheckState == CheckStateEnum.ToCheck && x.AuditState == AuditStateEnum.QCPassed || (x.CheckState == CheckStateEnum.CVIng && x.AuditState == AuditStateEnum.QCPassed));
|
||||||
|
|
||||||
var dicomQuery = from sv in _subjectVisitRepository.Where(subjectVisitLambda)
|
var dicomQuery = from sv in _subjectVisitRepository.Where(subjectVisitLambda)
|
||||||
@@ -190,7 +199,7 @@ namespace IRaCIS.Core.Application.MediatR.Handlers
|
|||||||
dbSV.CheckUserId = _userInfo.Id;
|
dbSV.CheckUserId = _userInfo.Id;
|
||||||
dbSV.CheckPassedTime = DateTime.Now;
|
dbSV.CheckPassedTime = DateTime.Now;
|
||||||
dbSV.CheckChallengeState = CheckChanllengeTypeEnum.Closed;
|
dbSV.CheckChallengeState = CheckChanllengeTypeEnum.Closed;
|
||||||
|
|
||||||
//---核对EDC数据,完全一致
|
//---核对EDC数据,完全一致
|
||||||
dbSV.CheckResult = _localizer["ConsistencyVerification_EDCB"];
|
dbSV.CheckResult = _localizer["ConsistencyVerification_EDCB"];
|
||||||
//---自动核查通过
|
//---自动核查通过
|
||||||
@@ -213,7 +222,7 @@ namespace IRaCIS.Core.Application.MediatR.Handlers
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
//"Problems are as follows:
|
//"Problems are as follows:
|
||||||
dialogMsg.AppendLine($"<br/><div style='color: yellow'>{_localizer["ConsistencyVerification_Prob"]}</div>");
|
dialogMsg.AppendLine($"<br/><div style='color: red'>{_localizer["ConsistencyVerification_Prob"]}</div>");
|
||||||
|
|
||||||
num = 0;
|
num = 0;
|
||||||
foreach (var item in dbExceptExcel)
|
foreach (var item in dbExceptExcel)
|
||||||
@@ -274,11 +283,13 @@ namespace IRaCIS.Core.Application.MediatR.Handlers
|
|||||||
|
|
||||||
}
|
}
|
||||||
await _subjectVisitRepository.SaveChangesAsync();
|
await _subjectVisitRepository.SaveChangesAsync();
|
||||||
return "OK";
|
|
||||||
|
|
||||||
|
//await context.RespondAsync<ConsistenCheckResult>(new
|
||||||
|
//{
|
||||||
|
|
||||||
|
//});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -107,7 +107,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
|
|
||||||
public class DoctorSelfConsistentSubjectView: ConsistentCommonView
|
public class DoctorSelfConsistentSubjectView: ConsistentCommonView
|
||||||
{
|
{
|
||||||
|
public string FirstGlobalVisitName { get; set; } = string.Empty;
|
||||||
public string? BlindSubjectCode { get; set; }
|
public string? BlindSubjectCode { get; set; }
|
||||||
|
|
||||||
public List<VisitTaskSimpleDTO> VisitTaskList { get; set; }
|
public List<VisitTaskSimpleDTO> VisitTaskList { get; set; }
|
||||||
@@ -183,7 +183,8 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
|
|
||||||
public string TaskCode { get; set; }
|
public string TaskCode { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
//可以不查询
|
//可以不查询
|
||||||
public List<VisitTaskSimpleDTO> GlobalVisitTaskList { get; set; }
|
public List<VisitTaskSimpleDTO> GlobalVisitTaskList { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -201,6 +201,8 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
public Guid? SourceSubjectVisitId { get; set; }
|
public Guid? SourceSubjectVisitId { get; set; }
|
||||||
public Guid? SouceReadModuleId { get; set; }
|
public Guid? SouceReadModuleId { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public bool IsHaveFeedBack { get; set; }
|
||||||
//public bool IsAfterConvertedTask { get; set; }
|
//public bool IsAfterConvertedTask { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,7 +211,9 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
{
|
{
|
||||||
public bool? IsSelfAnalysis { get; set; }
|
public bool? IsSelfAnalysis { get; set; }
|
||||||
|
|
||||||
public bool IsReReadingOrBackInfluenceAnalysis { get; set; }
|
public int ConsistentClinicalDataCount { get; set; } = 0;
|
||||||
|
|
||||||
|
public bool IsReReadingOrBackInfluenceAnalysis { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ using Medallion.Threading;
|
|||||||
using IRaCIS.Core.Infrastructure.Extention;
|
using IRaCIS.Core.Infrastructure.Extention;
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using NPOI.SS.Formula.Functions;
|
||||||
|
using IRaCIS.Core.Application.Service.Reading.Dto;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Service
|
namespace IRaCIS.Core.Application.Service
|
||||||
{
|
{
|
||||||
@@ -31,6 +33,8 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
private readonly IRepository<TaskConsistentRule> _taskConsistentRuleRepository;
|
private readonly IRepository<TaskConsistentRule> _taskConsistentRuleRepository;
|
||||||
private readonly IRepository<VisitTask> _visitTaskRepository;
|
private readonly IRepository<VisitTask> _visitTaskRepository;
|
||||||
|
private readonly IRepository<ReadingConsistentClinicalData> _readingConsistentClinicalDataRepository;
|
||||||
|
private readonly IReadingClinicalDataService _readingClinicalDataService;
|
||||||
private readonly IRepository<SubjectUser> _subjectUserRepository;
|
private readonly IRepository<SubjectUser> _subjectUserRepository;
|
||||||
private readonly IRepository<Subject> _subjectRepository;
|
private readonly IRepository<Subject> _subjectRepository;
|
||||||
private readonly IRepository<Enroll> _enrollRepository;
|
private readonly IRepository<Enroll> _enrollRepository;
|
||||||
@@ -43,11 +47,16 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
private readonly IVisitTaskHelpeService _visitTaskCommonService;
|
private readonly IVisitTaskHelpeService _visitTaskCommonService;
|
||||||
|
|
||||||
|
|
||||||
public TaskConsistentRuleService(IRepository<VisitTask> visitTaskRepository, IRepository<Enroll> enrollRepository, IRepository<TaskConsistentRule> taskConsistentRuleRepository, IRepository<SubjectUser> subjectUserRepository, IRepository<Subject> subjectRepository, IDistributedLockProvider distributedLockProvider,
|
public TaskConsistentRuleService(IRepository<VisitTask> visitTaskRepository,
|
||||||
|
IRepository<ReadingConsistentClinicalData> readingConsistentClinicalDataRepository,
|
||||||
|
IReadingClinicalDataService readingClinicalDataService,
|
||||||
|
IRepository<Enroll> enrollRepository, IRepository<TaskConsistentRule> taskConsistentRuleRepository, IRepository<SubjectUser> subjectUserRepository, IRepository<Subject> subjectRepository, IDistributedLockProvider distributedLockProvider,
|
||||||
IRepository<Trial> trialRepository, IRepository<TrialSite> trialSiteRepository, IRepository<TrialVirtualSiteCodeUpdate> trialVirtualSiteCodeUpdateRepository, IVisitTaskHelpeService visitTaskCommonService)
|
IRepository<Trial> trialRepository, IRepository<TrialSite> trialSiteRepository, IRepository<TrialVirtualSiteCodeUpdate> trialVirtualSiteCodeUpdateRepository, IVisitTaskHelpeService visitTaskCommonService)
|
||||||
{
|
{
|
||||||
_taskConsistentRuleRepository = taskConsistentRuleRepository;
|
_taskConsistentRuleRepository = taskConsistentRuleRepository;
|
||||||
_visitTaskRepository = visitTaskRepository;
|
_visitTaskRepository = visitTaskRepository;
|
||||||
|
this._readingConsistentClinicalDataRepository = readingConsistentClinicalDataRepository;
|
||||||
|
this._readingClinicalDataService = readingClinicalDataService;
|
||||||
_subjectUserRepository = subjectUserRepository;
|
_subjectUserRepository = subjectUserRepository;
|
||||||
_subjectRepository = subjectRepository;
|
_subjectRepository = subjectRepository;
|
||||||
_enrollRepository = enrollRepository;
|
_enrollRepository = enrollRepository;
|
||||||
@@ -87,7 +96,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
/// <param name="queryVisitTask"></param>
|
/// <param name="queryVisitTask"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<IResponseOutput<PageOutput<AnalysisTaskView>>> GetAnalysisTaskList(VisitTaskQuery queryVisitTask )
|
public async Task<IResponseOutput<PageOutput<AnalysisTaskView>>> GetAnalysisTaskList(VisitTaskQuery queryVisitTask)
|
||||||
{
|
{
|
||||||
var visitTaskQueryable = _visitTaskRepository.Where(t => t.TrialId == queryVisitTask.TrialId)
|
var visitTaskQueryable = _visitTaskRepository.Where(t => t.TrialId == queryVisitTask.TrialId)
|
||||||
.Where(t => t.IsAnalysisCreate)
|
.Where(t => t.IsAnalysisCreate)
|
||||||
@@ -106,7 +115,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
.WhereIf(queryVisitTask.ArmEnum != null, t => t.ArmEnum == queryVisitTask.ArmEnum)
|
.WhereIf(queryVisitTask.ArmEnum != null, t => t.ArmEnum == queryVisitTask.ArmEnum)
|
||||||
.WhereIf(!string.IsNullOrEmpty(queryVisitTask.TrialSiteCode), t => /*(t.BlindTrialSiteCode.Contains(queryVisitTask.TrialSiteCode!) && t.IsAnalysisCreate) ||*/ (t.Subject.TrialSite.TrialSiteCode.Contains(queryVisitTask.TrialSiteCode!) /*&& t.IsAnalysisCreate == false*/))
|
.WhereIf(!string.IsNullOrEmpty(queryVisitTask.TrialSiteCode), t => /*(t.BlindTrialSiteCode.Contains(queryVisitTask.TrialSiteCode!) && t.IsAnalysisCreate) ||*/ (t.Subject.TrialSite.TrialSiteCode.Contains(queryVisitTask.TrialSiteCode!) /*&& t.IsAnalysisCreate == false*/))
|
||||||
.WhereIf(!string.IsNullOrEmpty(queryVisitTask.TaskName), t => t.TaskName.Contains(queryVisitTask.TaskName) || t.TaskBlindName.Contains(queryVisitTask.TaskName))
|
.WhereIf(!string.IsNullOrEmpty(queryVisitTask.TaskName), t => t.TaskName.Contains(queryVisitTask.TaskName) || t.TaskBlindName.Contains(queryVisitTask.TaskName))
|
||||||
.WhereIf(!string.IsNullOrEmpty(queryVisitTask.SubjectCode), t => ((t.Subject.Code.Contains(queryVisitTask.SubjectCode)||t.Subject.MedicalNo.Contains(queryVisitTask.SubjectCode)) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(queryVisitTask.SubjectCode) && t.IsAnalysisCreate))
|
.WhereIf(!string.IsNullOrEmpty(queryVisitTask.SubjectCode), t => ((t.Subject.Code.Contains(queryVisitTask.SubjectCode) || t.Subject.MedicalNo.Contains(queryVisitTask.SubjectCode)) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(queryVisitTask.SubjectCode) && t.IsAnalysisCreate))
|
||||||
.WhereIf(queryVisitTask.BeginAllocateDate != null, t => t.AllocateTime >= queryVisitTask.BeginAllocateDate)
|
.WhereIf(queryVisitTask.BeginAllocateDate != null, t => t.AllocateTime >= queryVisitTask.BeginAllocateDate)
|
||||||
.WhereIf(queryVisitTask.EndAllocateDate != null, t => t.AllocateTime <= queryVisitTask.EndAllocateDate)
|
.WhereIf(queryVisitTask.EndAllocateDate != null, t => t.AllocateTime <= queryVisitTask.EndAllocateDate)
|
||||||
.WhereIf(queryVisitTask.BeginSignTime != null, t => t.SignTime >= queryVisitTask.BeginSignTime)
|
.WhereIf(queryVisitTask.BeginSignTime != null, t => t.SignTime >= queryVisitTask.BeginSignTime)
|
||||||
@@ -116,8 +125,22 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
var defalutSortArray = new string[] { nameof(VisitTask.IsUrgent) + " desc", nameof(VisitTask.SubjectId), nameof(VisitTask.VisitTaskNum) };
|
var defalutSortArray = new string[] { nameof(VisitTask.IsUrgent) + " desc", nameof(VisitTask.SubjectId), nameof(VisitTask.VisitTaskNum) };
|
||||||
|
|
||||||
var pageList = await visitTaskQueryable.ToPagedListAsync(queryVisitTask.PageIndex, queryVisitTask.PageSize, queryVisitTask.SortField, queryVisitTask.Asc, string.IsNullOrWhiteSpace(queryVisitTask.SortField), defalutSortArray);
|
var pageList = await visitTaskQueryable.ToPagedListAsync(queryVisitTask.PageIndex, queryVisitTask.PageSize, queryVisitTask.SortField, queryVisitTask.Asc, string.IsNullOrWhiteSpace(queryVisitTask.SortField), defalutSortArray);
|
||||||
|
#region 统计一致性分析临床数据数量
|
||||||
|
|
||||||
var trialTaskConfig = _repository.Where<Trial>(t => t.Id == queryVisitTask.TrialId).Select(t => new { IsHaveDoubleReadCriterion=t.TrialReadingCriterionList.Any(t=>t.IsSigned && t.IsConfirm && t.ReadingType==ReadingMethod.Double), t.VitrualSiteCode }).FirstOrDefault();
|
foreach (var item in pageList.CurrentPageData)
|
||||||
|
{
|
||||||
|
item.ConsistentClinicalDataCount = (await _readingClinicalDataService.GetClinicalDataList(new GetReadingOrTaskClinicalDataListInDto()
|
||||||
|
{
|
||||||
|
SubjectId = item.SubjectId,
|
||||||
|
TrialId = item.TrialId,
|
||||||
|
SelectIsSign = false,
|
||||||
|
IsGetAllConsistencyAnalysis = false,
|
||||||
|
VisitTaskId = item.Id,
|
||||||
|
})).Count();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
var trialTaskConfig = _repository.Where<Trial>(t => t.Id == queryVisitTask.TrialId).Select(t => new { IsHaveDoubleReadCriterion = t.TrialReadingCriterionList.Any(t => t.IsSigned && t.IsConfirm && t.ReadingType == ReadingMethod.Double), t.VitrualSiteCode }).FirstOrDefault();
|
||||||
|
|
||||||
return ResponseOutput.Ok(pageList, trialTaskConfig);
|
return ResponseOutput.Ok(pageList, trialTaskConfig);
|
||||||
}
|
}
|
||||||
@@ -153,7 +176,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
var filterObj = await _taskConsistentRuleRepository.FirstOrDefaultAsync(t => t.Id == inCommand.TaskConsistentRuleId);
|
var filterObj = await _taskConsistentRuleRepository.Where(t => t.Id == inCommand.TaskConsistentRuleId).Include(t => t.TrialReadingCriterion).FirstOrDefaultAsync();
|
||||||
var doctorUserId = inCommand.DoctorUserId;
|
var doctorUserId = inCommand.DoctorUserId;
|
||||||
var trialReadingCriterionId = filterObj.TrialReadingCriterionId;
|
var trialReadingCriterionId = filterObj.TrialReadingCriterionId;
|
||||||
|
|
||||||
@@ -168,19 +191,17 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
throw new BusinessValidationFailedException(_localizer["TaskConsistent_NotAllowedGenerate"]);
|
throw new BusinessValidationFailedException(_localizer["TaskConsistent_NotAllowedGenerate"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subjectList.Count<2 * filterObj.PlanSubjectCount)
|
if (subjectList.Count < 2 * filterObj.PlanSubjectCount)
|
||||||
{
|
{
|
||||||
throw new BusinessValidationFailedException(_localizer["TaskConsistent_NotAllowedGenerate1"]);
|
throw new BusinessValidationFailedException(_localizer["TaskConsistent_NotAllowedGenerate1"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
inCommand.SubejctIdList = GetRandomSubjectIdList(subjectList.Select(t => t.SubjectId).ToList(), filterObj.PlanSubjectCount);
|
inCommand.SubejctIdList = subjectList.Select(t => t.SubjectId).ToList().GetRandomCountList(filterObj.PlanSubjectCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
var list = await GetIQueryableDoctorSelfConsistentSubjectView(filterObj, doctorUserId, inCommand.SubejctIdList).ToListAsync();
|
var list = await GetIQueryableDoctorSelfConsistentSubjectView(filterObj, doctorUserId, inCommand.SubejctIdList).ToListAsync();
|
||||||
|
|
||||||
//var (group, query) = GetIQueryableDoctorSelfConsistentRuleSubjectView(filterObj, inCommand.SubejctIdList);
|
|
||||||
|
|
||||||
//var list = query.OrderByDescending(t => t.IsHaveGeneratedTask).ToList();
|
|
||||||
|
|
||||||
var @lock = _distributedLockProvider.CreateLock($"VisitTaskCode");
|
var @lock = _distributedLockProvider.CreateLock($"VisitTaskCode");
|
||||||
|
|
||||||
@@ -213,7 +234,18 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
blindSubjectCode = filterObj.BlindTrialSiteCode + (maxCodeInt + 1).ToString($"D{filterObj.BlindSubjectNumberOfPlaces}");
|
blindSubjectCode = filterObj.BlindTrialSiteCode + (maxCodeInt + 1).ToString($"D{filterObj.BlindSubjectNumberOfPlaces}");
|
||||||
}
|
}
|
||||||
|
|
||||||
subject.VisitTaskList = subject.VisitTaskList.Take(filterObj.PlanVisitCount).ToList();
|
//有序阅片
|
||||||
|
if (filterObj.TrialReadingCriterion.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
|
||||||
|
{
|
||||||
|
subject.VisitTaskList = subject.VisitTaskList.Take(filterObj.PlanVisitCount).ToList();
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//完全随机 和受试者随机,都是随机挑选访视
|
||||||
|
subject.VisitTaskList = subject.VisitTaskList.GetRandomCountList(filterObj.PlanVisitCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
subject.VisitTaskList.ForEach(t =>
|
subject.VisitTaskList.ForEach(t =>
|
||||||
{
|
{
|
||||||
@@ -243,7 +275,19 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
TaskName = lastTask.TaskName + "_Global",
|
TaskName = lastTask.TaskName + "_Global",
|
||||||
TaskBlindName = lastTask.TaskBlindName + "_Global",
|
TaskBlindName = lastTask.TaskBlindName + "_Global",
|
||||||
TrialReadingCriterionId = trialReadingCriterionId,
|
TrialReadingCriterionId = trialReadingCriterionId,
|
||||||
|
VisitTaskNum= lastTask.VisitTaskNum + ReadingCommon.TaskNumDic[ReadingCategory.Global]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var afterGlobal = _visitTaskRepository.Where(t => t.SubjectId == lastTask.SubjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.TaskState == TaskState.Effect && t.ReadingCategory == ReadingCategory.Global && t.VisitTaskNum > lastTask.VisitTaskNum).ProjectTo<VisitTaskSimpleDTO>(_mapper.ConfigurationProvider).FirstOrDefault();
|
||||||
|
|
||||||
|
if (afterGlobal == null)
|
||||||
|
{
|
||||||
|
throw new BusinessValidationFailedException("联系后台排查数据,没找到后续全局");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
existGlobal.SouceReadModuleId = afterGlobal.SouceReadModuleId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -284,7 +328,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
/// <param name="inQuery"></param>
|
/// <param name="inQuery"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<IResponseOutput<PageOutput<DoctorGroupConsistentSubjectView>> > GetGroupConsistentRuleSubjectList(GroupConsistentQuery inQuery)
|
public async Task<IResponseOutput<PageOutput<DoctorGroupConsistentSubjectView>>> GetGroupConsistentRuleSubjectList(GroupConsistentQuery inQuery)
|
||||||
{
|
{
|
||||||
var trialId = inQuery.TrialId;
|
var trialId = inQuery.TrialId;
|
||||||
|
|
||||||
@@ -294,7 +338,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
if (filterObj == null)
|
if (filterObj == null)
|
||||||
{
|
{
|
||||||
object tt = null;
|
object tt = null;
|
||||||
return ResponseOutput.Ok(new PageOutput<DoctorGroupConsistentSubjectView>(), new { Rule = tt, IsAllowAutoAllocate = false }) ;
|
return ResponseOutput.Ok(new PageOutput<DoctorGroupConsistentSubjectView>(), new { Rule = tt, IsAllowAutoAllocate = false });
|
||||||
}
|
}
|
||||||
|
|
||||||
var query = await GetGroupConsistentQueryAsync(filterObj);
|
var query = await GetGroupConsistentQueryAsync(filterObj);
|
||||||
@@ -306,9 +350,9 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
var list = await GetGroupConsistentRuleMatchSubjectIdListAsync(new GroupConsistentSimpleQuery() { TrialId = inQuery.TrialId, TrialReadingCriterionId = inQuery.TrialReadingCriterionId });
|
var list = await GetGroupConsistentRuleMatchSubjectIdListAsync(new GroupConsistentSimpleQuery() { TrialId = inQuery.TrialId, TrialReadingCriterionId = inQuery.TrialReadingCriterionId });
|
||||||
|
|
||||||
var isAllowAutoAllocate = !list.Any(t => t.IsHaveGeneratedTask) && list.Count() > 2*(rule?.PlanSubjectCount??0);
|
var isAllowAutoAllocate = !list.Any(t => t.IsHaveGeneratedTask) && list.Count() > 2 * (rule?.PlanSubjectCount ?? 0);
|
||||||
|
|
||||||
return ResponseOutput.Ok(pagedList, new {Rule=rule, IsAllowAutoAllocate = isAllowAutoAllocate });
|
return ResponseOutput.Ok(pagedList, new { Rule = rule, IsAllowAutoAllocate = isAllowAutoAllocate });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -326,10 +370,12 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
{
|
{
|
||||||
var trialId = inCommand.TrialId;
|
var trialId = inCommand.TrialId;
|
||||||
|
|
||||||
var filterObj = await _taskConsistentRuleRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.TrialReadingCriterionId == inCommand.TrialReadingCriterionId && t.IsSelfAnalysis == false);
|
var filterObj = await _taskConsistentRuleRepository.Where(t => t.TrialId == trialId && t.TrialReadingCriterionId == inCommand.TrialReadingCriterionId && t.IsSelfAnalysis == false).Include(t => t.TrialReadingCriterion).FirstNotNullAsync();
|
||||||
|
|
||||||
var trialReadingCriterionId = filterObj.TrialReadingCriterionId;
|
var trialReadingCriterionId = filterObj.TrialReadingCriterionId;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//随机分配
|
//随机分配
|
||||||
if (inCommand.IsAutoAllocateGenerateTask)
|
if (inCommand.IsAutoAllocateGenerateTask)
|
||||||
{
|
{
|
||||||
@@ -341,12 +387,12 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
throw new BusinessValidationFailedException(_localizer["TaskConsistent_NotAllowedGenerate"]);
|
throw new BusinessValidationFailedException(_localizer["TaskConsistent_NotAllowedGenerate"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subjectSelectList.Count< 2 * filterObj.PlanSubjectCount)
|
if (subjectSelectList.Count < 2 * filterObj.PlanSubjectCount)
|
||||||
{
|
{
|
||||||
throw new BusinessValidationFailedException(_localizer["TaskConsistent_NotAllowedGenerate1"]);
|
throw new BusinessValidationFailedException(_localizer["TaskConsistent_NotAllowedGenerate1"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
inCommand.SubejctIdList = GetRandomSubjectIdList(subjectSelectList.Select(t => t.SubjectId).ToList(), filterObj.PlanSubjectCount);
|
inCommand.SubejctIdList = subjectSelectList.Select(t => t.SubjectId).ToList().GetRandomCountList(filterObj.PlanSubjectCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -416,6 +462,11 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
foreach (var needAddDoctorUserId in needAddDoctorUserIdList)
|
foreach (var needAddDoctorUserId in needAddDoctorUserIdList)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
//if(filterObj.TrialReadingCriterion.IsReadingTaskViewInOrder== ReadingOrder.InOrder)
|
||||||
|
//{
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
//每个医生 都生成处理的任务
|
//每个医生 都生成处理的任务
|
||||||
foreach (var task in subject.SubjectTaskVisitList.Take(filterObj.PlanVisitCount))
|
foreach (var task in subject.SubjectTaskVisitList.Take(filterObj.PlanVisitCount))
|
||||||
{
|
{
|
||||||
@@ -468,7 +519,9 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
TrialReadingCriterionId = trialReadingCriterionId,
|
TrialReadingCriterionId = trialReadingCriterionId,
|
||||||
|
|
||||||
BlindSubjectCode = blindSubjectCode,
|
BlindSubjectCode = blindSubjectCode,
|
||||||
BlindTrialSiteCode = filterObj.BlindTrialSiteCode
|
BlindTrialSiteCode = filterObj.BlindTrialSiteCode,
|
||||||
|
|
||||||
|
VisitTaskNum = lastTask.VisitTaskNum + ReadingCommon.TaskNumDic[ReadingCategory.Global]
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -524,10 +577,13 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
var trialReadingCriterionId = filterObj.TrialReadingCriterionId;
|
var trialReadingCriterionId = filterObj.TrialReadingCriterionId;
|
||||||
|
|
||||||
|
//防止生成sql生成GETDATE() 时区导致的问题
|
||||||
|
var appDateTimeNow = DateTime.Now;
|
||||||
|
|
||||||
#region Subejct 维度
|
#region Subejct 维度
|
||||||
|
|
||||||
Expression<Func<VisitTask, bool>> comonTaskFilter = u => u.TrialId == trialId && u.IsAnalysisCreate == false && u.TaskState == TaskState.Effect && u.ReadingTaskState == ReadingTaskState.HaveSigned && u.TrialReadingCriterionId == trialReadingCriterionId &&
|
Expression<Func<VisitTask, bool>> comonTaskFilter = u => u.TrialId == trialId && u.IsAnalysisCreate == false && u.TaskState == TaskState.Effect && u.ReadingTaskState == ReadingTaskState.HaveSigned && u.TrialReadingCriterionId == trialReadingCriterionId &&
|
||||||
u.SignTime!.Value.AddDays(filterObj.IntervalWeeks * 7) < DateTime.Now && (u.ReReadingApplyState == ReReadingApplyState.Default || u.ReReadingApplyState == ReReadingApplyState.Reject) && u.DoctorUserId == doctorUserId;
|
u.SignTime!.Value.AddDays(filterObj.IntervalWeeks * 7) < appDateTimeNow && (u.ReReadingApplyState == ReReadingApplyState.Default || u.ReReadingApplyState == ReReadingApplyState.Reject) && u.DoctorUserId == doctorUserId;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -545,14 +601,15 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
//{
|
//{
|
||||||
// //这里的过滤条件 不能用 where(comonTaskFilter) 会报错,奇怪的问题 只能重新写一遍
|
// //这里的过滤条件 不能用 where(comonTaskFilter) 会报错,奇怪的问题 只能重新写一遍
|
||||||
// visitTaskFilter = visitTaskFilter.And(c => c.Subject.SubjectVisitTaskList.Any(t => t.VisitTaskNum == c.VisitTaskNum + ReadingCommon.TaskNumDic[ReadingCategory.Global] && t.ReadingCategory == ReadingCategory.Global && t.IsAnalysisCreate == false && t.TaskState == TaskState.Effect && t.ReadingTaskState == ReadingTaskState.HaveSigned &&
|
// visitTaskFilter = visitTaskFilter.And(c => c.Subject.SubjectVisitTaskList.Any(t => t.VisitTaskNum == c.VisitTaskNum + ReadingCommon.TaskNumDic[ReadingCategory.Global] && t.ReadingCategory == ReadingCategory.Global && t.IsAnalysisCreate == false && t.TaskState == TaskState.Effect && t.ReadingTaskState == ReadingTaskState.HaveSigned &&
|
||||||
// t.SignTime!.Value.AddDays(filterObj.IntervalWeeks * 7) < DateTime.Now && (t.ReReadingApplyState == ReReadingApplyState.Default || t.ReReadingApplyState == ReReadingApplyState.Reject)));
|
// t.SignTime!.Value.AddDays(filterObj.IntervalWeeks * 7) < appDateTimeNow && (t.ReReadingApplyState == ReReadingApplyState.Default || t.ReReadingApplyState == ReReadingApplyState.Reject)));
|
||||||
|
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
|
||||||
var subjectQuery = _subjectRepository.Where(t => t.TrialId == trialId &&
|
var subjectQuery = _subjectRepository.Where(t => t.TrialId == trialId &&
|
||||||
t.SubjectVisitTaskList.AsQueryable().Where(visitTaskFilter).Count() >= filterObj.PlanVisitCount)
|
t.SubjectVisitTaskList.AsQueryable().Where(visitTaskFilter).Count() >= filterObj.PlanVisitCount)
|
||||||
.WhereIf(filterObj.IsHaveReadingPeriod == true, u => u.SubjectVisitTaskList.AsQueryable().Where(comonTaskFilter).Where(t => t.ReadingCategory == ReadingCategory.Visit || t.ReadingCategory == ReadingCategory.Global).OrderBy(t => t.VisitTaskNum).Take(filterObj.PlanVisitCount + 1).Any(t => t.ReadingCategory == ReadingCategory.Global))
|
.WhereIf(filterObj.IsHaveReadingPeriod == true, u => u.SubjectVisitTaskList.AsQueryable().Where(comonTaskFilter)
|
||||||
|
.Where(t => t.ReadingCategory == ReadingCategory.Visit || t.ReadingCategory == ReadingCategory.Global).Any(t => t.ReadingCategory == ReadingCategory.Global && t.VisitTaskNum > filterObj.PlanVisitCount - 1))
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
@@ -567,6 +624,8 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
IsReReadingOrBackInfluenceAnalysis = t.IsReReadingOrBackInfluenceAnalysis,
|
IsReReadingOrBackInfluenceAnalysis = t.IsReReadingOrBackInfluenceAnalysis,
|
||||||
|
|
||||||
|
FirstGlobalVisitName= t.ReadModuleList.Where(c=>c.TrialReadingCriterionId== trialReadingCriterionId && c.ModuleType== ModuleTypeEnum.Global).OrderBy(k=>k.SubjectVisit.VisitNum).Select(u=>u.SubjectVisit.VisitName).FirstOrDefault(),
|
||||||
|
|
||||||
BlindSubjectCode = t.SubjectVisitTaskList.Where(t => t.IsAnalysisCreate && t.TrialReadingCriterionId == trialReadingCriterionId).OrderByDescending(t => t.BlindSubjectCode).Select(t => t.BlindSubjectCode).FirstOrDefault(),
|
BlindSubjectCode = t.SubjectVisitTaskList.Where(t => t.IsAnalysisCreate && t.TrialReadingCriterionId == trialReadingCriterionId).OrderByDescending(t => t.BlindSubjectCode).Select(t => t.BlindSubjectCode).FirstOrDefault(),
|
||||||
|
|
||||||
IsHaveGeneratedTask = t.SubjectVisitTaskList.Any(c => c.DoctorUserId == doctorUserId && c.IsSelfAnalysis == true && c.TrialReadingCriterionId == trialReadingCriterionId),
|
IsHaveGeneratedTask = t.SubjectVisitTaskList.Any(c => c.DoctorUserId == doctorUserId && c.IsSelfAnalysis == true && c.TrialReadingCriterionId == trialReadingCriterionId),
|
||||||
@@ -596,29 +655,27 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
IsClinicalDataSign = c.IsClinicalDataSign,
|
IsClinicalDataSign = c.IsClinicalDataSign,
|
||||||
IsNeedClinicalDataSign = c.IsNeedClinicalDataSign,
|
IsNeedClinicalDataSign = c.IsNeedClinicalDataSign,
|
||||||
|
|
||||||
//自身一致性才有意义
|
|
||||||
//IsHaveGeneratedTask = c.Subject.SubjectVisitTaskList.Any(t => t.ConsistentAnalysisOriginalTaskId == c.Id),
|
|
||||||
|
|
||||||
GlobalVisitTaskList = c.Subject.SubjectVisitTaskList.AsQueryable().Where(comonTaskFilter).Where(t => t.VisitTaskNum == c.VisitTaskNum + ReadingCommon.TaskNumDic[ReadingCategory.Global]).Select(c => new VisitTaskSimpleDTO()
|
//GlobalVisitTaskList = c.Subject.SubjectVisitTaskList.AsQueryable().Where(comonTaskFilter).Where(t => t.VisitTaskNum == c.VisitTaskNum + ReadingCommon.TaskNumDic[ReadingCategory.Global]).Select(c => new VisitTaskSimpleDTO()
|
||||||
{
|
//{
|
||||||
Id = c.Id,
|
// Id = c.Id,
|
||||||
ReadingCategory = c.ReadingCategory,
|
// ReadingCategory = c.ReadingCategory,
|
||||||
ReadingTaskState = c.ReadingTaskState,
|
// ReadingTaskState = c.ReadingTaskState,
|
||||||
TaskBlindName = c.TaskBlindName,
|
// TaskBlindName = c.TaskBlindName,
|
||||||
TaskCode = c.TaskCode,
|
// TaskCode = c.TaskCode,
|
||||||
TaskName = c.TaskName,
|
// TaskName = c.TaskName,
|
||||||
TaskState = c.TaskState,
|
// TaskState = c.TaskState,
|
||||||
ArmEnum = c.ArmEnum,
|
// ArmEnum = c.ArmEnum,
|
||||||
SubjectId = c.SubjectId,
|
// SubjectId = c.SubjectId,
|
||||||
VisitTaskNum = c.VisitTaskNum,
|
// VisitTaskNum = c.VisitTaskNum,
|
||||||
TrialId = c.TrialId,
|
// TrialId = c.TrialId,
|
||||||
SourceSubjectVisitId = c.SourceSubjectVisitId,
|
// SourceSubjectVisitId = c.SourceSubjectVisitId,
|
||||||
SouceReadModuleId = c.SouceReadModuleId,
|
// SouceReadModuleId = c.SouceReadModuleId,
|
||||||
|
|
||||||
TrialReadingCriterionId = c.TrialReadingCriterionId,
|
// TrialReadingCriterionId = c.TrialReadingCriterionId,
|
||||||
IsClinicalDataSign = c.IsClinicalDataSign,
|
// IsClinicalDataSign = c.IsClinicalDataSign,
|
||||||
IsNeedClinicalDataSign = c.IsNeedClinicalDataSign,
|
// IsNeedClinicalDataSign = c.IsNeedClinicalDataSign,
|
||||||
}).ToList(),
|
//}).ToList(),
|
||||||
|
|
||||||
}).ToList()
|
}).ToList()
|
||||||
});
|
});
|
||||||
@@ -638,13 +695,11 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private async Task<IQueryable<DoctorGroupConsistentSubjectView>> GetGroupConsistentQueryAsync(TaskConsistentRule filterObj, List<Guid>? subejctIdList = null)
|
private async Task<IQueryable<DoctorGroupConsistentSubjectView>> GetGroupConsistentQueryAsync(TaskConsistentRule filterObj, List<Guid>? subejctIdList = null)
|
||||||
{
|
{
|
||||||
|
//单重阅片没有组件一致性
|
||||||
|
|
||||||
var trialId = filterObj.TrialId;
|
var trialId = filterObj.TrialId;
|
||||||
var trialReadingCriterionId = filterObj.TrialReadingCriterionId;
|
var trialReadingCriterionId = filterObj.TrialReadingCriterionId;
|
||||||
|
|
||||||
//var trialConfig = (await _repository.Where<Trial>(t => t.Id == trialId).Select(t => new { TrialId = t.Id, t.ReadingType, t.IsReadingTaskViewInOrder }).FirstOrDefaultAsync()).IfNullThrowException();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Expression<Func<VisitTask, bool>> comonTaskFilter = u => u.TrialId == trialId && u.IsAnalysisCreate == false && u.TaskState == TaskState.Effect && u.ReadingTaskState == ReadingTaskState.HaveSigned && u.TrialReadingCriterionId == trialReadingCriterionId
|
Expression<Func<VisitTask, bool>> comonTaskFilter = u => u.TrialId == trialId && u.IsAnalysisCreate == false && u.TaskState == TaskState.Effect && u.ReadingTaskState == ReadingTaskState.HaveSigned && u.TrialReadingCriterionId == trialReadingCriterionId
|
||||||
&& (u.ReReadingApplyState == ReReadingApplyState.Default || u.ReReadingApplyState == ReReadingApplyState.Reject);
|
&& (u.ReReadingApplyState == ReReadingApplyState.Default || u.ReReadingApplyState == ReReadingApplyState.Reject);
|
||||||
@@ -658,28 +713,16 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
Expression<Func<VisitTask, bool>> visitTaskFilter = comonTaskFilter.And(t => t.ReadingCategory == ReadingCategory.Visit);
|
Expression<Func<VisitTask, bool>> visitTaskFilter = comonTaskFilter.And(t => t.ReadingCategory == ReadingCategory.Visit);
|
||||||
|
|
||||||
|
|
||||||
////所选访视数量 的访视 其中必有一个访视后有全局任务
|
|
||||||
//if (filterObj.IsHaveReadingPeriod == true)
|
|
||||||
//{
|
|
||||||
// //visitTaskFilter = visitTaskFilter.And(t => t.Subject.SubjectVisitTaskList.AsQueryable().Where(comonTaskFilter).Any(u => u.VisitTaskNum == t.VisitTaskNum + ReadingCommon.TaskNumDic[ReadingCategory.Global] && u.ReadingCategory == ReadingCategory.Global));
|
|
||||||
|
|
||||||
// //这里的过滤条件 不能用 where(comonTaskFilter) 会报错,奇怪的问题 只能重新写一遍
|
|
||||||
// visitTaskFilter = visitTaskFilter.And(c => c.Subject.SubjectVisitTaskList.Any(t => t.VisitTaskNum == c.VisitTaskNum + ReadingCommon.TaskNumDic[ReadingCategory.Global] && t.ReadingCategory == ReadingCategory.Global && t.IsAnalysisCreate == false && t.TaskState == TaskState.Effect && t.ReadingTaskState == ReadingTaskState.HaveSigned &&
|
|
||||||
// t.SignTime!.Value.AddDays(filterObj.IntervalWeeks * 7) < DateTime.Now && (t.ReReadingApplyState == ReReadingApplyState.Default || t.ReReadingApplyState == ReReadingApplyState.Reject)));
|
|
||||||
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
IQueryable<Subject> subjectQuery = default;
|
IQueryable<Subject> subjectQuery = default;
|
||||||
|
|
||||||
//单重阅片没有组件一致性
|
|
||||||
|
|
||||||
|
//双重阅片,并且都阅片完成
|
||||||
subjectQuery = _subjectRepository.Where(t => t.TrialId == trialId &&
|
subjectQuery = _subjectRepository.Where(t => t.TrialId == trialId &&
|
||||||
t.SubjectVisitTaskList.AsQueryable().Where(comonTaskFilter).Where(t => t.ReadingCategory == ReadingCategory.Visit || t.ReadingCategory == ReadingCategory.Global).Select(t => t.DoctorUserId).Distinct().Count() == 2 &&
|
t.SubjectVisitTaskList.AsQueryable().Where(comonTaskFilter).Where(t => t.ReadingCategory == ReadingCategory.Visit || t.ReadingCategory == ReadingCategory.Global).Select(t => t.DoctorUserId).Distinct().Count() == 2 &&
|
||||||
t.SubjectVisitTaskList.AsQueryable().Where(visitTaskFilter).GroupBy(t => new { t.SubjectId, t.VisitTaskNum }).Where(g => g.Count() == 2).Count() >= filterObj.PlanVisitCount
|
t.SubjectVisitTaskList.AsQueryable().Where(visitTaskFilter).GroupBy(t => new { t.SubjectId, t.VisitTaskNum }).Where(g => g.Count() == 2).Count() >= filterObj.PlanVisitCount
|
||||||
)
|
)
|
||||||
.WhereIf(filterObj.IsHaveReadingPeriod == true, u => u.SubjectVisitTaskList.AsQueryable().Where(comonTaskFilter).Where(t => t.ReadingCategory == ReadingCategory.Visit || t.ReadingCategory == ReadingCategory.Global).OrderBy(t => t.VisitTaskNum).Take(filterObj.PlanVisitCount * 2 + 2).Any(t => t.ReadingCategory == ReadingCategory.Global))
|
//.WhereIf(filterObj.IsHaveReadingPeriod == true, u => u.SubjectVisitTaskList.AsQueryable().Where(comonTaskFilter).Where(t => t.ReadingCategory == ReadingCategory.Visit || t.ReadingCategory == ReadingCategory.Global).OrderBy(t => t.VisitTaskNum).Take(filterObj.PlanVisitCount * 2 + 2).Any(t => t.ReadingCategory == ReadingCategory.Global))
|
||||||
|
.WhereIf(filterObj.IsHaveReadingPeriod == true, u => u.SubjectVisitTaskList.AsQueryable().Where(comonTaskFilter).Where(t => t.ReadingCategory == ReadingCategory.Global && t.VisitTaskNum > filterObj.PlanVisitCount - 1).Select(t => t.DoctorUserId).Distinct().Count() == 2)
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
@@ -695,7 +738,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
IsHaveGeneratedTask = t.SubjectVisitTaskList.Any(c => c.IsSelfAnalysis == false && c.TrialReadingCriterionId == trialReadingCriterionId),
|
IsHaveGeneratedTask = t.SubjectVisitTaskList.Any(c => c.IsSelfAnalysis == false && c.TrialReadingCriterionId == trialReadingCriterionId),
|
||||||
|
|
||||||
DoctorUserList = t.SubjectDoctorList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId && t.IsConfirmed).Select(t => new UserSimpleInfo()
|
DoctorUserList = t.SubjectDoctorList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId && t.IsConfirmed && t.ArmEnum <= Arm.DoubleReadingArm2).Select(t => new UserSimpleInfo()
|
||||||
{
|
{
|
||||||
UserId = t.Id,
|
UserId = t.Id,
|
||||||
FullName = t.DoctorUser.FullName,
|
FullName = t.DoctorUser.FullName,
|
||||||
@@ -756,9 +799,12 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
var trialId = inQuery.TrialId;
|
var trialId = inQuery.TrialId;
|
||||||
|
|
||||||
|
//防止生成sql生成GETDATE() 时区导致的问题
|
||||||
|
var appDateTimeNow = DateTime.Now;
|
||||||
|
|
||||||
Expression<Func<VisitTask, bool>> comonTaskFilter = u => u.TrialId == trialId && u.IsAnalysisCreate == false && u.TaskState == TaskState.Effect && u.ReadingTaskState == ReadingTaskState.HaveSigned && (u.ReReadingApplyState == ReReadingApplyState.Default || u.ReReadingApplyState == ReReadingApplyState.Reject);
|
Expression<Func<VisitTask, bool>> comonTaskFilter = u => u.TrialId == trialId && u.IsAnalysisCreate == false && u.TaskState == TaskState.Effect && u.ReadingTaskState == ReadingTaskState.HaveSigned && (u.ReReadingApplyState == ReReadingApplyState.Default || u.ReReadingApplyState == ReReadingApplyState.Reject);
|
||||||
|
|
||||||
//&& u.TrialReadingCriterionId == trialReadingCriterionId &&u.SignTime!.Value.AddDays(filterObj.IntervalWeeks * 7) < DateTime.Now && u.DoctorUserId == doctorUserId;
|
//&& u.TrialReadingCriterionId == trialReadingCriterionId &&u.SignTime!.Value.AddDays(filterObj.IntervalWeeks * 7) < appDateTimeNow && u.DoctorUserId == doctorUserId;
|
||||||
|
|
||||||
Expression<Func<VisitTask, bool>> visitTaskFilter = comonTaskFilter.And(t => t.ReadingCategory == ReadingCategory.Visit);
|
Expression<Func<VisitTask, bool>> visitTaskFilter = comonTaskFilter.And(t => t.ReadingCategory == ReadingCategory.Visit);
|
||||||
|
|
||||||
@@ -790,12 +836,20 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
MatchSubejctCount = taskConsistentRule.Trial.SubjectList.AsQueryable()
|
MatchSubejctCount = taskConsistentRule.Trial.SubjectList.AsQueryable()
|
||||||
.Where(t => taskConsistentRule.IsHaveReadingPeriod == false ? t.SubjectVisitTaskList.AsQueryable()
|
.Where(t => taskConsistentRule.IsHaveReadingPeriod == false ? t.SubjectVisitTaskList.AsQueryable()
|
||||||
.Where(visitTaskFilter).Where(t => t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId && t.SignTime!.Value.AddDays(taskConsistentRule.IntervalWeeks * 7) < DateTime.Now && t.DoctorUserId == user.Id)
|
.Where(visitTaskFilter).Where(t => t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId && t.SignTime!.Value.AddDays(taskConsistentRule.IntervalWeeks * 7) < appDateTimeNow && t.DoctorUserId == user.Id)
|
||||||
.Count() >= taskConsistentRule.PlanVisitCount :
|
.Count() >= taskConsistentRule.PlanVisitCount :
|
||||||
|
|
||||||
|
//全局要>计划访视数量后面
|
||||||
t.SubjectVisitTaskList.AsQueryable().Where(comonTaskFilter)
|
t.SubjectVisitTaskList.AsQueryable().Where(comonTaskFilter)
|
||||||
.Where(t => t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId && t.SignTime!.Value.AddDays(taskConsistentRule.IntervalWeeks * 7) < DateTime.Now && t.DoctorUserId == user.Id)
|
.Where(t => t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId && t.SignTime!.Value.AddDays(taskConsistentRule.IntervalWeeks * 7) < appDateTimeNow && t.DoctorUserId == user.Id)
|
||||||
.Where(t => t.ReadingCategory == ReadingCategory.Visit || t.ReadingCategory == ReadingCategory.Global).OrderBy(t => t.VisitTaskNum).Take(taskConsistentRule.PlanVisitCount + 1).Any(t => t.ReadingCategory == ReadingCategory.Global))
|
.Where(t => t.ReadingCategory == ReadingCategory.Visit || t.ReadingCategory == ReadingCategory.Global).Any(t => t.ReadingCategory == ReadingCategory.Global && t.VisitTaskNum > taskConsistentRule.PlanVisitCount - 1)
|
||||||
|
&&
|
||||||
|
t.SubjectVisitTaskList.AsQueryable().Where(visitTaskFilter)
|
||||||
|
.Where(t => t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId && t.SignTime!.Value.AddDays(taskConsistentRule.IntervalWeeks * 7) < appDateTimeNow && t.DoctorUserId == user.Id)
|
||||||
|
.Count() >= taskConsistentRule.PlanVisitCount
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
.Count(),
|
.Count(),
|
||||||
|
|
||||||
|
|
||||||
@@ -825,9 +879,9 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
//var taskConsistentRuleQueryable = _taskConsistentRuleRepository.Where(t => t.TrialId == inQuery.TrialId)
|
//var taskConsistentRuleQueryable = _taskConsistentRuleRepository.Where(t => t.TrialId == inQuery.TrialId)
|
||||||
// .ProjectTo<TaskConsistentRuleView>(_mapper.ConfigurationProvider);
|
// .ProjectTo<TaskConsistentRuleView>(_mapper.ConfigurationProvider);
|
||||||
|
|
||||||
var list= await taskConsistentRuleQueryable.ToListAsync();
|
var list = await taskConsistentRuleQueryable.ToListAsync();
|
||||||
|
|
||||||
var rule= await _taskConsistentRuleRepository.Where(t => t.TrialId == inQuery.TrialId && t.IsSelfAnalysis == true && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId).ProjectTo<TaskConsistentRuleBasic>(_mapper.ConfigurationProvider).FirstOrDefaultAsync();
|
var rule = await _taskConsistentRuleRepository.Where(t => t.TrialId == inQuery.TrialId && t.IsSelfAnalysis == true && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId).ProjectTo<TaskConsistentRuleBasic>(_mapper.ConfigurationProvider).FirstOrDefaultAsync();
|
||||||
return ResponseOutput.Ok(list, rule);
|
return ResponseOutput.Ok(list, rule);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -864,7 +918,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
public async Task<List<UpdateTrialSiteCodeCommandView>> GetUpdateVirtualSiteCodeList(Guid trialId)
|
public async Task<List<UpdateTrialSiteCodeCommandView>> GetUpdateVirtualSiteCodeList(Guid trialId)
|
||||||
{
|
{
|
||||||
var list = await _trialVirtualSiteCodeUpdateRepository.Where(t => t.TrialId == trialId).Select(t => new UpdateTrialSiteCodeCommandView() { TrialId = trialId, VirtualSiteCode = t.VirturalSiteCode, Creatime = t.CreateTime }).OrderByDescending(t=>t.Creatime).ToListAsync();
|
var list = await _trialVirtualSiteCodeUpdateRepository.Where(t => t.TrialId == trialId).Select(t => new UpdateTrialSiteCodeCommandView() { TrialId = trialId, VirtualSiteCode = t.VirturalSiteCode, Creatime = t.CreateTime }).OrderByDescending(t => t.Creatime).ToListAsync();
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -960,35 +1014,10 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 随机算法,选择指定数量的 subject
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="matchSubjectIdList"></param>
|
|
||||||
/// <param name="countToSelect"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public List<Guid> GetRandomSubjectIdList(List<Guid> matchSubjectIdList, int countToSelect)
|
|
||||||
{
|
|
||||||
|
|
||||||
// 使用 Fisher-Yates 随机置换算法来选择指定数量的 GUID
|
|
||||||
Random random = new Random();
|
|
||||||
|
|
||||||
for (int i = 0; i < countToSelect; i++)
|
|
||||||
{
|
|
||||||
// 生成一个随机索引
|
|
||||||
int randomIndex = random.Next(i, matchSubjectIdList.Count);
|
|
||||||
|
|
||||||
// 将选中的元素与当前元素交换位置
|
|
||||||
Guid temp = matchSubjectIdList[randomIndex];
|
|
||||||
matchSubjectIdList[randomIndex] = matchSubjectIdList[i];
|
|
||||||
matchSubjectIdList[i] = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
return matchSubjectIdList.Take(countToSelect).ToList();
|
|
||||||
|
|
||||||
// 使用洗牌算法来随机选择指定数量的GUID
|
|
||||||
//Random random = new Random();
|
|
||||||
//return matchSubjectIdList.OrderBy(g => random.Next()).Take(countToSelect).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,9 +56,6 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
var taskMedicalReviewQueryable = _taskMedicalReviewRepository.Where(t => t.VisitTask.TrialId == inQuery.TrialId)
|
var taskMedicalReviewQueryable = _taskMedicalReviewRepository.Where(t => t.VisitTask.TrialId == inQuery.TrialId)
|
||||||
|
|
||||||
.WhereIf(inQuery.IsEffect == true, t => t.VisitTask.TaskState == TaskState.Effect || t.VisitTask.TaskState == TaskState.Freeze)
|
|
||||||
.WhereIf(inQuery.IsEffect == false, t => t.VisitTask.TaskState == TaskState.Adbandon || t.VisitTask.TaskState == TaskState.HaveReturned)
|
|
||||||
|
|
||||||
.WhereIf(inQuery.TrialSiteId != null, t => t.VisitTask.Subject.TrialSiteId == inQuery.TrialSiteId)
|
.WhereIf(inQuery.TrialSiteId != null, t => t.VisitTask.Subject.TrialSiteId == inQuery.TrialSiteId)
|
||||||
.WhereIf(inQuery.SubjectId != null, t => t.VisitTask.SubjectId == inQuery.SubjectId)
|
.WhereIf(inQuery.SubjectId != null, t => t.VisitTask.SubjectId == inQuery.SubjectId)
|
||||||
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => t.VisitTask.Subject.Code.Contains(inQuery.SubjectCode) || t.VisitTask.Subject.MedicalNo.Contains(inQuery.SubjectCode))
|
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => t.VisitTask.Subject.Code.Contains(inQuery.SubjectCode) || t.VisitTask.Subject.MedicalNo.Contains(inQuery.SubjectCode))
|
||||||
@@ -259,7 +256,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
.ProjectTo<TaskMedicalReviewView>(_mapper.ConfigurationProvider);
|
.ProjectTo<TaskMedicalReviewView>(_mapper.ConfigurationProvider);
|
||||||
|
|
||||||
|
|
||||||
var defalutSortArray = new string[] { nameof(TaskMedicalReviewView.AuditState), nameof(TaskMedicalReviewView.SubjectId), nameof(TaskMedicalReviewView.ArmEnum), nameof(TaskMedicalReviewView.VisitTaskNum) };
|
var defalutSortArray = new string[] { nameof(TaskMedicalReviewView.SubjectId), nameof(TaskMedicalReviewView.ArmEnum), nameof(TaskMedicalReviewView.VisitTaskNum) };
|
||||||
var pageList = await taskMedicalReviewQueryable.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField, inQuery.Asc, string.IsNullOrWhiteSpace(inQuery.SortField), defalutSortArray);
|
var pageList = await taskMedicalReviewQueryable.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField, inQuery.Asc, string.IsNullOrWhiteSpace(inQuery.SortField), defalutSortArray);
|
||||||
|
|
||||||
return ResponseOutput.Ok(pageList, new
|
return ResponseOutput.Ok(pageList, new
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ using IRaCIS.Core.Infra.EFCore.Common;
|
|||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using IRaCIS.Core.Domain.Share.Reading;
|
using IRaCIS.Core.Domain.Share.Reading;
|
||||||
using IRaCIS.Core.Application.Service.Reading.Dto;
|
using IRaCIS.Core.Application.Service.Reading.Dto;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Service
|
namespace IRaCIS.Core.Application.Service
|
||||||
{
|
{
|
||||||
@@ -26,7 +27,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
/// 访视读片任务
|
/// 访视读片任务
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ApiExplorerSettings(GroupName = "Trial")]
|
[ApiExplorerSettings(GroupName = "Trial")]
|
||||||
public class VisitTaskHelpeService : IVisitTaskHelpeService
|
public class VisitTaskHelpeService : BaseService, IVisitTaskHelpeService
|
||||||
{
|
{
|
||||||
|
|
||||||
private readonly IRepository<VisitTask> _visitTaskRepository;
|
private readonly IRepository<VisitTask> _visitTaskRepository;
|
||||||
@@ -51,6 +52,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
private readonly IRepository<ClinicalDataTrialSet> _trialClinicalDataSetRepository;
|
private readonly IRepository<ClinicalDataTrialSet> _trialClinicalDataSetRepository;
|
||||||
private readonly IRepository<ReadingClinicalData> _readingClinicalDataRepository;
|
private readonly IRepository<ReadingClinicalData> _readingClinicalDataRepository;
|
||||||
|
private readonly IRepository<ReadingConsistentClinicalData> _readingConsistentClinicalDataRepository;
|
||||||
|
|
||||||
private readonly IRepository<SubjectCriteriaEvaluation> _subjectCriteriaEvaluationRepository;
|
private readonly IRepository<SubjectCriteriaEvaluation> _subjectCriteriaEvaluationRepository;
|
||||||
|
|
||||||
@@ -67,8 +69,9 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
IRepository<ReadingJudgeInfo> readingJudgeInfoRepository,
|
IRepository<ReadingJudgeInfo> readingJudgeInfoRepository,
|
||||||
IRepository<TaskAllocationRule> taskAllocationRuleRepository, IMapper mapper, IUserInfo userInfo, IRepository<VisitTaskReReading> visitTaskReReadingRepository,
|
IRepository<TaskAllocationRule> taskAllocationRuleRepository, IMapper mapper, IUserInfo userInfo, IRepository<VisitTaskReReading> visitTaskReReadingRepository,
|
||||||
IRepository<ReadingQuestionCriterionTrial> trialReadingCriterionRepository, IRepository<ClinicalDataTrialSet> trialClinicalDataSetRepository, IRepository<ReadingClinicalData> readingClinicalDataRepository,
|
IRepository<ReadingQuestionCriterionTrial> trialReadingCriterionRepository, IRepository<ClinicalDataTrialSet> trialClinicalDataSetRepository, IRepository<ReadingClinicalData> readingClinicalDataRepository,
|
||||||
IRepository<SubjectCriteriaEvaluation> subjectCriteriaEvaluationRepository)
|
IRepository<SubjectCriteriaEvaluation> subjectCriteriaEvaluationRepository, IRepository<ReadingConsistentClinicalData> readingConsistentClinicalDataRepository)
|
||||||
{
|
{
|
||||||
|
_readingConsistentClinicalDataRepository = readingConsistentClinicalDataRepository;
|
||||||
_readingClinicalDataRepository = readingClinicalDataRepository;
|
_readingClinicalDataRepository = readingClinicalDataRepository;
|
||||||
_trialClinicalDataSetRepository = trialClinicalDataSetRepository;
|
_trialClinicalDataSetRepository = trialClinicalDataSetRepository;
|
||||||
|
|
||||||
@@ -207,7 +210,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
if (trialReadingCriterionConfig.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
|
if (trialReadingCriterionConfig.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
|
||||||
{
|
{
|
||||||
if (visitNumList.IndexOf(subjectVisit.VisitNum) == 0 && subjectVisit.VisitNum==0)
|
if (visitNumList.IndexOf(subjectVisit.VisitNum) == 0 && subjectVisit.VisitNum == 0)
|
||||||
{
|
{
|
||||||
blindTaskName = visitBlindConfig.BlindBaseLineName;
|
blindTaskName = visitBlindConfig.BlindBaseLineName;
|
||||||
}
|
}
|
||||||
@@ -217,9 +220,9 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
blindTaskName ="Timepoint";
|
blindTaskName = "Timepoint";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -448,6 +451,19 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取GetIsClinicalDataSignTest
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="visitTask"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<bool> GetIsClinicalDataSignTest(Guid visitTask)
|
||||||
|
{
|
||||||
|
var taskinfo = await _visitTaskRepository.Where(x => x.Id == visitTask).FirstNotNullAsync();
|
||||||
|
var clinicalDataConfirmList = _trialClinicalDataSetRepository.Where(t => t.TrialId == taskinfo.TrialId && t.IsConfirm).Include(t => t.TrialClinicalDataSetCriteriaList).ToList();
|
||||||
|
|
||||||
|
Guid readingid = taskinfo.SourceSubjectVisitId == null ? taskinfo.SouceReadModuleId!.Value : taskinfo.SourceSubjectVisitId.Value;
|
||||||
|
return IsClinicalDataSign(taskinfo.ReadingCategory, taskinfo.VisitTaskNum == 0m, taskinfo.TrialReadingCriterionId, clinicalDataConfirmList, readingid, taskinfo.TrialId); ;
|
||||||
|
}
|
||||||
|
|
||||||
// 有可能在任务生成之前 就签名完了临床数据
|
// 有可能在任务生成之前 就签名完了临床数据
|
||||||
private bool IsClinicalDataSign(ReadingCategory readingCategory, bool isbaseLine, Guid trialReadingCriterionId, List<ClinicalDataTrialSet> trialClinicalDataSetList, Guid readingId, Guid trialId)
|
private bool IsClinicalDataSign(ReadingCategory readingCategory, bool isbaseLine, Guid trialReadingCriterionId, List<ClinicalDataTrialSet> trialClinicalDataSetList, Guid readingId, Guid trialId)
|
||||||
@@ -466,7 +482,9 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
//CRC 的自动签名 不用管 只用处理PM的就好
|
//CRC 的自动签名 不用管 只用处理PM的就好
|
||||||
var haveSignedCount = _readingClinicalDataRepository
|
var haveSignedCount = _readingClinicalDataRepository
|
||||||
.Where(t => t.TrialId == trialId && t.IsSign && t.ReadingClinicalDataState == ReadingClinicalDataStatus.HaveSigned && t.ReadingId == readingId && t.ClinicalDataTrialSet.UploadRole == UploadRole.PM).Count();
|
.Where(t => t.TrialId == trialId && t.IsSign
|
||||||
|
&& t.ClinicalDataTrialSet.TrialClinicalDataSetCriteriaList.Any(x=>x.TrialReadingCriterionId== trialReadingCriterionId)
|
||||||
|
&& t.ReadingClinicalDataState == ReadingClinicalDataStatus.HaveSigned && t.ReadingId == readingId && t.ClinicalDataTrialSet.UploadRole == UploadRole.PM).Count();
|
||||||
|
|
||||||
|
|
||||||
var readModule = _readModuleRepository.Where(t => t.Id == readingId).FirstOrDefault();
|
var readModule = _readModuleRepository.Where(t => t.Id == readingId).FirstOrDefault();
|
||||||
@@ -701,8 +719,8 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
&& t.TrialReadingCriterionId == trialReadingCriterionId && t.TaskState == TaskState.Effect
|
&& t.TrialReadingCriterionId == trialReadingCriterionId && t.TaskState == TaskState.Effect
|
||||||
/* && t.TaskAllocationState == TaskAllocationState.NotAllocate && t.DoctorUserId == null*/ && t.SourceSubjectVisitId == subjectVisit.Id).ToList();
|
/* && t.TaskAllocationState == TaskAllocationState.NotAllocate && t.DoctorUserId == null*/ && t.SourceSubjectVisitId == subjectVisit.Id).ToList();
|
||||||
|
|
||||||
VisitTask? task1 = null;
|
VisitTask? task1 = existCurrentVisitTaskList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm1);
|
||||||
VisitTask? task2 = null;
|
VisitTask? task2 = existCurrentVisitTaskList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm2);
|
||||||
|
|
||||||
|
|
||||||
if (!existCurrentVisitTaskList.Any(t => t.ArmEnum == Arm.DoubleReadingArm1))
|
if (!existCurrentVisitTaskList.Any(t => t.ArmEnum == Arm.DoubleReadingArm1))
|
||||||
@@ -734,6 +752,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!existCurrentVisitTaskList.Any(t => t.ArmEnum == Arm.DoubleReadingArm2))
|
if (!existCurrentVisitTaskList.Any(t => t.ArmEnum == Arm.DoubleReadingArm2))
|
||||||
{
|
{
|
||||||
currentMaxCodeInt = currentMaxCodeInt + 1;
|
currentMaxCodeInt = currentMaxCodeInt + 1;
|
||||||
@@ -1411,8 +1430,62 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
break;
|
break;
|
||||||
case GenerateTaskCategory.SelfConsistent:
|
case GenerateTaskCategory.SelfConsistent:
|
||||||
|
|
||||||
|
var readingCriterionId = generateTaskCommand.GenerataConsistentTaskList.First().TrialReadingCriterionId;
|
||||||
|
var isReadingTaskViewInOrder = await _trialReadingCriterionRepository.Where(t => t.Id == readingCriterionId).Select(x => x.IsReadingTaskViewInOrder).FirstNotNullAsync();
|
||||||
|
var subjectId = generateTaskCommand.GenerataConsistentTaskList.First().SubjectId;
|
||||||
|
//var trialReadingCriterion=_trialReadingCriterionRepository.Where(t=>t.Id== trialReadingCriterionId).FirstOrDefault();
|
||||||
|
|
||||||
|
//判断是否存在传输方式为Pdf得临床数据
|
||||||
|
|
||||||
|
var firsttask = generateTaskCommand.GenerataConsistentTaskList[0];
|
||||||
|
var clinicalDataList = _readingClinicalDataRepository.Where(t => t.SubjectId == subjectId
|
||||||
|
&& t.ClinicalDataTrialSet.TrialClinicalDataSetCriteriaList.Any(y => y.TrialReadingCriterionId == firsttask.TrialReadingCriterionId)
|
||||||
|
&& t.ClinicalDataTrialSet.ClinicalDataLevel!= ClinicalLevel.Study
|
||||||
|
&& t.ClinicalDataTrialSet.ClinicalUploadType == ClinicalUploadType.PDF)
|
||||||
|
// crc受试者和访视的临床数据没上传 一致性分析的时候也不用显示
|
||||||
|
.Where(x=>x.ClinicalDataTrialSet.UploadRole == UploadRole.PM||x.FileCount>0)
|
||||||
|
.Include(t => t.ReadingClinicalDataPDFList).Include(t => t.ClinicalDataTrialSet).ToList();
|
||||||
|
|
||||||
|
|
||||||
|
foreach (var clinicalData in clinicalDataList)
|
||||||
|
{
|
||||||
|
var consistnentClinicalData = _mapper.Map<ReadingConsistentClinicalData>(clinicalData);
|
||||||
|
var id = NewId.NextSequentialGuid();
|
||||||
|
consistnentClinicalData.Id = id;
|
||||||
|
|
||||||
|
if (consistnentClinicalData.ClinicalDataTrialSet.ClinicalUploadType == ClinicalUploadType.PDF)
|
||||||
|
{
|
||||||
|
consistnentClinicalData.IsSign = false;
|
||||||
|
consistnentClinicalData.IsBlind = false;
|
||||||
|
consistnentClinicalData.IsComplete = true;
|
||||||
|
consistnentClinicalData.ReadingClinicalDataState = ReadingClinicalDataStatus.HaveUploaded;
|
||||||
|
consistnentClinicalData.ClinicalDataTrialSet = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var consistanClinicalDataPdfList = _mapper.Map<List<ReadingConsistentClinicalDataPDF>>(clinicalData.ReadingClinicalDataPDFList);
|
||||||
|
|
||||||
|
consistanClinicalDataPdfList.ForEach(t => { t.ReadingConsistentClinicalDataId = id; t.Id = Guid.Empty; });
|
||||||
|
|
||||||
|
consistnentClinicalData.ReadingClinicalDataPDFList = consistanClinicalDataPdfList;
|
||||||
|
|
||||||
|
await _readingConsistentClinicalDataRepository.AddAsync(consistnentClinicalData);
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var task in generateTaskCommand.GenerataConsistentTaskList)
|
foreach (var task in generateTaskCommand.GenerataConsistentTaskList)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var exsitPDF = await _readingClinicalDataRepository
|
||||||
|
.WhereIf(isReadingTaskViewInOrder== ReadingOrder.Random,t=>t.ReadingId== task.SouceReadModuleId|| t.ReadingId == task.SourceSubjectVisitId)
|
||||||
|
.AnyAsync(t => t.TrialId == trialId &&
|
||||||
|
t.SubjectId== task.SubjectId&&
|
||||||
|
|
||||||
|
t.ClinicalDataTrialSet.TrialClinicalDataSetCriteriaList.Any(c => c.TrialReadingCriterionId == readingCriterionId)
|
||||||
|
&& t.ClinicalDataTrialSet.ClinicalDataLevel != ClinicalLevel.Study
|
||||||
|
&& t.ClinicalDataTrialSet.ClinicalUploadType == ClinicalUploadType.PDF);
|
||||||
|
|
||||||
|
var taskState = exsitPDF ? TaskState.NotEffect : TaskState.Effect;
|
||||||
var consistentTask = new VisitTask()
|
var consistentTask = new VisitTask()
|
||||||
{
|
{
|
||||||
TrialId = task.TrialId,
|
TrialId = task.TrialId,
|
||||||
@@ -1424,7 +1497,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
VisitTaskNum = task.VisitTaskNum,
|
VisitTaskNum = task.VisitTaskNum,
|
||||||
ReadingCategory = task.ReadingCategory,
|
ReadingCategory = task.ReadingCategory,
|
||||||
|
|
||||||
TaskState = TaskState.Effect,
|
TaskState = taskState,
|
||||||
Code = currentMaxCodeInt + 1,
|
Code = currentMaxCodeInt + 1,
|
||||||
TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)),
|
TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)),
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ using DocumentFormat.OpenXml.Office2010.Word;
|
|||||||
using System.Linq.Dynamic.Core;
|
using System.Linq.Dynamic.Core;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using DocumentFormat.OpenXml.Bibliography;
|
using DocumentFormat.OpenXml.Bibliography;
|
||||||
using Org.BouncyCastle.Crypto;
|
|
||||||
using IRaCIS.Core.Domain.Share.Reading;
|
using IRaCIS.Core.Domain.Share.Reading;
|
||||||
using MassTransit;
|
using MassTransit;
|
||||||
using System.Reactive.Subjects;
|
using System.Reactive.Subjects;
|
||||||
@@ -291,7 +290,7 @@ namespace IRaCIS.Core.Application.Service.Allocation
|
|||||||
{
|
{
|
||||||
foreach (var command in cancelCommand.CancelList.Where(t => t.IsCancelAssign))
|
foreach (var command in cancelCommand.CancelList.Where(t => t.IsCancelAssign))
|
||||||
{
|
{
|
||||||
if (await _visitTaskRepository.AnyAsync(t => t.TrialReadingCriterionId == cancelCommand.TrialReadingCriterionId && t.SubjectId == command.SubjectId && t.DoctorUserId == command.DoctorUserId && t.ArmEnum == command.ArmEnum && t.ReadingTaskState != ReadingTaskState.WaitReading))
|
if (await _visitTaskRepository.AnyAsync(t => t.TaskState==TaskState.Effect && t.TrialReadingCriterionId == cancelCommand.TrialReadingCriterionId && t.SubjectId == command.SubjectId && t.DoctorUserId == command.DoctorUserId && t.ArmEnum == command.ArmEnum && t.ReadingTaskState != ReadingTaskState.WaitReading))
|
||||||
{
|
{
|
||||||
//---当前医生已开始做该Subject 该标准的任务,不允许取消分配
|
//---当前医生已开始做该Subject 该标准的任务,不允许取消分配
|
||||||
throw new BusinessValidationFailedException(_localizer["VisitTask_DoctorConfigNotFound"]);
|
throw new BusinessValidationFailedException(_localizer["VisitTask_DoctorConfigNotFound"]);
|
||||||
@@ -787,7 +786,7 @@ namespace IRaCIS.Core.Application.Service.Allocation
|
|||||||
.WhereIf(!string.IsNullOrEmpty(queryVisitTask.SubjectCode), t => (t.Subject.Code.Contains(queryVisitTask.SubjectCode) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(queryVisitTask.SubjectCode) && t.IsAnalysisCreate))
|
.WhereIf(!string.IsNullOrEmpty(queryVisitTask.SubjectCode), t => (t.Subject.Code.Contains(queryVisitTask.SubjectCode) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(queryVisitTask.SubjectCode) && t.IsAnalysisCreate))
|
||||||
.WhereIf(queryVisitTask.BeginAllocateDate != null, t => t.AllocateTime > queryVisitTask.BeginAllocateDate)
|
.WhereIf(queryVisitTask.BeginAllocateDate != null, t => t.AllocateTime > queryVisitTask.BeginAllocateDate)
|
||||||
.WhereIf(queryVisitTask.EndAllocateDate != null, t => t.AllocateTime < queryVisitTask.EndAllocateDate)
|
.WhereIf(queryVisitTask.EndAllocateDate != null, t => t.AllocateTime < queryVisitTask.EndAllocateDate)
|
||||||
.WhereIf(queryVisitTask.BeginSignTime != null, t => t.SignTime > queryVisitTask.BeginSignTime)
|
.WhereIf(queryVisitTask.BeginSignTime != null, t => t.SignTime > queryVisitTask.BeginSignTime)
|
||||||
.WhereIf(queryVisitTask.EndSignTime != null, t => t.SignTime < queryVisitTask.EndSignTime)
|
.WhereIf(queryVisitTask.EndSignTime != null, t => t.SignTime < queryVisitTask.EndSignTime)
|
||||||
.ProjectTo<ReadingTaskView>(_mapper.ConfigurationProvider);
|
.ProjectTo<ReadingTaskView>(_mapper.ConfigurationProvider);
|
||||||
|
|
||||||
@@ -804,43 +803,43 @@ namespace IRaCIS.Core.Application.Service.Allocation
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// PM 重阅追踪
|
/// PM 重阅追踪
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="queryVisitTask"></param>
|
/// <param name="inQuery"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<PageOutput<ReReadingTaskView>> GetReReadingTaskList(VisitTaskQuery queryVisitTask)
|
public async Task<PageOutput<ReReadingTaskView>> GetReReadingTaskList(VisitTaskQuery inQuery)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
var visitTaskQueryable = _visitTaskReReadingRepository
|
var visitTaskQueryable = _visitTaskReReadingRepository
|
||||||
.Where(t => t.OriginalReReadingTask.TrialId == queryVisitTask.TrialId /*&& t.OriginalReReadingTask.IsAnalysisCreate == false*/)
|
.Where(t => t.OriginalReReadingTask.TrialId == inQuery.TrialId /*&& t.OriginalReReadingTask.IsAnalysisCreate == false*/)
|
||||||
.WhereIf(queryVisitTask.RootReReadingTaskId != null, t => t.RootReReadingTaskId == queryVisitTask.RootReReadingTaskId || t.OriginalReReadingTaskId == queryVisitTask.RootReReadingTaskId)
|
.WhereIf(inQuery.RootReReadingTaskId != null, t => t.RootReReadingTaskId == inQuery.RootReReadingTaskId || t.OriginalReReadingTaskId == inQuery.RootReReadingTaskId)
|
||||||
.WhereIf(!string.IsNullOrEmpty(queryVisitTask.TaskCode), t => t.OriginalReReadingTask.TaskCode.Contains(queryVisitTask.TaskCode!) || t.RootReReadingTask.TaskCode.Contains(queryVisitTask.TaskCode!))
|
.WhereIf(!string.IsNullOrEmpty(inQuery.TaskCode), t => t.OriginalReReadingTask.TaskCode.Contains(inQuery.TaskCode!) || t.RootReReadingTask.TaskCode.Contains(inQuery.TaskCode!))
|
||||||
.WhereIf(queryVisitTask.TrialSiteId != null, t => t.OriginalReReadingTask.Subject.TrialSiteId == queryVisitTask.TrialSiteId)
|
.WhereIf(inQuery.TrialSiteId != null, t => t.OriginalReReadingTask.Subject.TrialSiteId == inQuery.TrialSiteId)
|
||||||
.WhereIf(queryVisitTask.TaskState != null, t => t.OriginalReReadingTask.TaskState == queryVisitTask.TaskState)
|
.WhereIf(inQuery.TaskState != null, t => t.OriginalReReadingTask.TaskState == inQuery.TaskState)
|
||||||
.WhereIf(queryVisitTask.ReReadingApplyState != null, t => t.OriginalReReadingTask.ReReadingApplyState == queryVisitTask.ReReadingApplyState)
|
.WhereIf(inQuery.ReReadingApplyState != null, t => t.OriginalReReadingTask.ReReadingApplyState == inQuery.ReReadingApplyState)
|
||||||
.WhereIf(queryVisitTask.RequestReReadingType != null, t => t.RequestReReadingType == queryVisitTask.RequestReReadingType)
|
.WhereIf(inQuery.RequestReReadingType != null, t => t.RequestReReadingType == inQuery.RequestReReadingType)
|
||||||
.WhereIf(queryVisitTask.SubjectId != null, t => t.OriginalReReadingTask.SubjectId == queryVisitTask.SubjectId)
|
.WhereIf(inQuery.SubjectId != null, t => t.OriginalReReadingTask.SubjectId == inQuery.SubjectId)
|
||||||
.WhereIf(queryVisitTask.IsUrgent != null, t => t.OriginalReReadingTask.IsUrgent == queryVisitTask.IsUrgent)
|
.WhereIf(inQuery.IsUrgent != null, t => t.OriginalReReadingTask.IsUrgent == inQuery.IsUrgent)
|
||||||
.WhereIf(queryVisitTask.DoctorUserId != null, t => t.OriginalReReadingTask.DoctorUserId == queryVisitTask.DoctorUserId)
|
.WhereIf(inQuery.DoctorUserId != null, t => t.OriginalReReadingTask.DoctorUserId == inQuery.DoctorUserId)
|
||||||
.WhereIf(queryVisitTask.ArmEnum != null, t => t.OriginalReReadingTask.ArmEnum == queryVisitTask.ArmEnum)
|
.WhereIf(inQuery.ArmEnum != null, t => t.OriginalReReadingTask.ArmEnum == inQuery.ArmEnum)
|
||||||
.WhereIf(queryVisitTask.ReadingTaskState != null, t => t.OriginalReReadingTask.ReadingTaskState == queryVisitTask.ReadingTaskState)
|
.WhereIf(inQuery.ReadingTaskState != null, t => t.OriginalReReadingTask.ReadingTaskState == inQuery.ReadingTaskState)
|
||||||
.WhereIf(queryVisitTask.TaskAllocationState != null, t => t.OriginalReReadingTask.TaskAllocationState == queryVisitTask.TaskAllocationState)
|
.WhereIf(inQuery.TaskAllocationState != null, t => t.OriginalReReadingTask.TaskAllocationState == inQuery.TaskAllocationState)
|
||||||
.WhereIf(queryVisitTask.TrialReadingCriterionId != null, t => t.OriginalReReadingTask.TrialReadingCriterionId == queryVisitTask.TrialReadingCriterionId)
|
.WhereIf(inQuery.TrialReadingCriterionId != null, t => t.OriginalReReadingTask.TrialReadingCriterionId == inQuery.TrialReadingCriterionId)
|
||||||
.WhereIf(queryVisitTask.ReadingCategory != null, t => t.OriginalReReadingTask.ReadingCategory == queryVisitTask.ReadingCategory)
|
.WhereIf(inQuery.ReadingCategory != null, t => t.OriginalReReadingTask.ReadingCategory == inQuery.ReadingCategory)
|
||||||
|
|
||||||
.WhereIf(!string.IsNullOrEmpty(queryVisitTask.RequestReReadingReason), t => t.RequestReReadingReason.Contains(queryVisitTask.RequestReReadingReason))
|
.WhereIf(!string.IsNullOrEmpty(inQuery.RequestReReadingReason), t => t.RequestReReadingReason.Contains(inQuery.RequestReReadingReason))
|
||||||
|
|
||||||
.WhereIf(queryVisitTask.RequestReReadingResultEnum != null, t => t.RequestReReadingResultEnum == queryVisitTask.RequestReReadingResultEnum)
|
.WhereIf(inQuery.RequestReReadingResultEnum != null, t => t.RequestReReadingResultEnum == inQuery.RequestReReadingResultEnum)
|
||||||
|
|
||||||
|
|
||||||
.WhereIf(!string.IsNullOrEmpty(queryVisitTask.TrialSiteCode), t => (t.OriginalReReadingTask.BlindTrialSiteCode.Contains(queryVisitTask.TrialSiteCode!) && t.OriginalReReadingTask.IsAnalysisCreate) || (t.OriginalReReadingTask.Subject.TrialSite.TrialSiteCode.Contains(queryVisitTask.TrialSiteCode!) && t.OriginalReReadingTask.IsAnalysisCreate == false))
|
.WhereIf(!string.IsNullOrEmpty(inQuery.TrialSiteCode), t => (t.OriginalReReadingTask.BlindTrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.OriginalReReadingTask.IsAnalysisCreate) || (t.OriginalReReadingTask.Subject.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.OriginalReReadingTask.IsAnalysisCreate == false))
|
||||||
.WhereIf(!string.IsNullOrEmpty(queryVisitTask.TaskName), t => t.OriginalReReadingTask.TaskName.Contains(queryVisitTask.TaskName) || t.OriginalReReadingTask.TaskBlindName.Contains(queryVisitTask.TaskName))
|
.WhereIf(!string.IsNullOrEmpty(inQuery.TaskName), t => t.OriginalReReadingTask.TaskName.Contains(inQuery.TaskName) || t.OriginalReReadingTask.TaskBlindName.Contains(inQuery.TaskName))
|
||||||
.WhereIf(!string.IsNullOrEmpty(queryVisitTask.SubjectCode), t => ((t.OriginalReReadingTask.Subject.Code.Contains(queryVisitTask.SubjectCode) || t.OriginalReReadingTask.Subject.MedicalNo.Contains(queryVisitTask.SubjectCode)) && t.OriginalReReadingTask.IsAnalysisCreate == false) || (t.OriginalReReadingTask.BlindSubjectCode.Contains(queryVisitTask.SubjectCode) && t.OriginalReReadingTask.IsAnalysisCreate))
|
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => ((t.OriginalReReadingTask.Subject.Code.Contains(inQuery.SubjectCode) || t.OriginalReReadingTask.Subject.MedicalNo.Contains(inQuery.SubjectCode)) && t.OriginalReReadingTask.IsAnalysisCreate == false) || (t.OriginalReReadingTask.BlindSubjectCode.Contains(inQuery.SubjectCode) && t.OriginalReReadingTask.IsAnalysisCreate))
|
||||||
.WhereIf(queryVisitTask.BeginAllocateDate != null, t => t.OriginalReReadingTask.AllocateTime > queryVisitTask.BeginAllocateDate)
|
.WhereIf(inQuery.BeginAllocateDate != null, t => t.OriginalReReadingTask.AllocateTime > inQuery.BeginAllocateDate)
|
||||||
.WhereIf(queryVisitTask.EndAllocateDate != null, t => t.OriginalReReadingTask.AllocateTime < queryVisitTask.EndAllocateDate!.Value.AddDays(1))
|
.WhereIf(inQuery.EndAllocateDate != null, t => t.OriginalReReadingTask.AllocateTime < inQuery.EndAllocateDate!.Value.AddDays(1))
|
||||||
|
|
||||||
.WhereIf(queryVisitTask.BeginRequestReReadingTime != null, t => t.RequestReReadingTime >= queryVisitTask.BeginRequestReReadingTime)
|
.WhereIf(inQuery.BeginRequestReReadingTime != null, t => t.RequestReReadingTime >= inQuery.BeginRequestReReadingTime)
|
||||||
.WhereIf(queryVisitTask.EndRequestReReadingTime != null, t => t.RequestReReadingTime <= queryVisitTask.EndRequestReReadingTime!.Value.AddDays(1))
|
.WhereIf(inQuery.EndRequestReReadingTime != null, t => t.RequestReReadingTime <= inQuery.EndRequestReReadingTime!.Value.AddDays(1))
|
||||||
|
|
||||||
.ProjectTo<ReReadingTaskView>(_mapper.ConfigurationProvider);
|
.ProjectTo<ReReadingTaskView>(_mapper.ConfigurationProvider);
|
||||||
|
|
||||||
@@ -854,7 +853,7 @@ namespace IRaCIS.Core.Application.Service.Allocation
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
var pageList = await visitTaskQueryable.ToPagedListAsync(queryVisitTask.PageIndex, queryVisitTask.PageSize, queryVisitTask.SortField, queryVisitTask.Asc, string.IsNullOrWhiteSpace(queryVisitTask.SortField), defalutSortArray);
|
var pageList = await visitTaskQueryable.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField, inQuery.Asc, string.IsNullOrWhiteSpace(inQuery.SortField), defalutSortArray);
|
||||||
|
|
||||||
return pageList;
|
return pageList;
|
||||||
}
|
}
|
||||||
@@ -1374,7 +1373,7 @@ namespace IRaCIS.Core.Application.Service.Allocation
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager)
|
if (IsPMOrAPm())
|
||||||
{
|
{
|
||||||
if (criterionConfig.IsAutoCreate == false)
|
if (criterionConfig.IsAutoCreate == false)
|
||||||
{
|
{
|
||||||
@@ -1416,6 +1415,13 @@ namespace IRaCIS.Core.Application.Service.Allocation
|
|||||||
{
|
{
|
||||||
task.ReReadingApplyState = ReReadingApplyState.DocotorHaveApplyed;
|
task.ReReadingApplyState = ReReadingApplyState.DocotorHaveApplyed;
|
||||||
|
|
||||||
|
|
||||||
|
//在PM 的申请重阅的影响列表里也不能申请重阅
|
||||||
|
|
||||||
|
var pmApply = await _visitTaskReReadingRepository.Where(t => t.OriginalReReadingTask.TrialId == task.TrialId && t.OriginalReReadingTask.SubjectId == task.SubjectId && t.OriginalReReadingTask.TaskState == TaskState.Effect && t.OriginalReReadingTask.ReadingCategory == ReadingCategory.Visit
|
||||||
|
&& t.OriginalReReadingTask.ReadingTaskState == ReadingTaskState.HaveSigned && t.RequestReReadingType == RequestReReadingType.TrialGroupApply && t.RequestReReadingResultEnum == RequestReReadingResult.Default).Include(t => t.OriginalReReadingTask).FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
|
||||||
// 有序
|
// 有序
|
||||||
if (criterionConfig.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
|
if (criterionConfig.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
|
||||||
{
|
{
|
||||||
@@ -1429,10 +1435,6 @@ namespace IRaCIS.Core.Application.Service.Allocation
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//在PM 的申请重阅的影响列表里也不能申请重阅
|
|
||||||
|
|
||||||
var pmApply = await _visitTaskReReadingRepository.Where(t => t.OriginalReReadingTask.TrialId == task.TrialId && t.OriginalReReadingTask.SubjectId == task.SubjectId && t.OriginalReReadingTask.TaskState == TaskState.Effect && t.OriginalReReadingTask.ReadingCategory == ReadingCategory.Visit
|
|
||||||
&& t.OriginalReReadingTask.ReadingTaskState == ReadingTaskState.HaveSigned && t.RequestReReadingType == RequestReReadingType.TrialGroupApply && t.RequestReReadingResultEnum == RequestReReadingResult.Default).Include(t => t.OriginalReReadingTask).FirstOrDefaultAsync();
|
|
||||||
|
|
||||||
if (pmApply != null)
|
if (pmApply != null)
|
||||||
{
|
{
|
||||||
@@ -1461,13 +1463,13 @@ namespace IRaCIS.Core.Application.Service.Allocation
|
|||||||
throw new BusinessValidationFailedException(_localizer["VisitTask_LastReading"]);
|
throw new BusinessValidationFailedException(_localizer["VisitTask_LastReading"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task.ReadingCategory == ReadingCategory.Oncology && await _visitTaskRepository.AnyAsync(filterExpression.And(t => t.ReadingCategory == ReadingCategory.Oncology)))
|
if (task.ReadingCategory == ReadingCategory.Oncology && await _visitTaskRepository.AnyAsync(filterExpression.And(t => t.ReadingCategory == ReadingCategory.Oncology && t.ReadingTaskState==ReadingTaskState.HaveSigned)))
|
||||||
{
|
{
|
||||||
//---有序阅片,只允许申请该受试者阅片人最后一次完成肿瘤学任务重阅
|
//---有序阅片,只允许申请该受试者阅片人最后一次完成肿瘤学任务重阅
|
||||||
throw new BusinessValidationFailedException(_localizer["VisitTask_LastOncologistRecheck"]);
|
throw new BusinessValidationFailedException(_localizer["VisitTask_LastOncologistRecheck"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task.ReadingCategory == ReadingCategory.Judge && await _visitTaskRepository.AnyAsync(filterExpression.And(t => t.ReadingCategory == ReadingCategory.Judge)))
|
if (task.ReadingCategory == ReadingCategory.Judge && await _visitTaskRepository.AnyAsync(filterExpression.And(t => t.ReadingCategory == ReadingCategory.Judge && t.ReadingTaskState == ReadingTaskState.HaveSigned)))
|
||||||
{
|
{
|
||||||
//---有序阅片,只允许申请该受试者阅片人最后一次完成裁判的任务重阅
|
//---有序阅片,只允许申请该受试者阅片人最后一次完成裁判的任务重阅
|
||||||
throw new BusinessValidationFailedException(_localizer["VisitTask_LastAdjudicatorRecheck"]);
|
throw new BusinessValidationFailedException(_localizer["VisitTask_LastAdjudicatorRecheck"]);
|
||||||
@@ -1476,9 +1478,27 @@ namespace IRaCIS.Core.Application.Service.Allocation
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (task.ReadingCategory != ReadingCategory.Visit && task.ReadingCategory != ReadingCategory.Global)
|
|
||||||
|
if (pmApply != null)
|
||||||
{
|
{
|
||||||
//---无序阅片,仅仅允许IR 申请 全局和访视类型类别的任务进行重阅
|
var originalTask = pmApply.OriginalReReadingTask;
|
||||||
|
|
||||||
|
//PM 无序影响列表
|
||||||
|
if (await _visitTaskRepository.Where(t => t.TrialId == originalTask.TrialId && t.SubjectId == originalTask.SubjectId && t.TaskState == TaskState.Effect && t.TaskAllocationState == TaskAllocationState.Allocated && t.IsAnalysisCreate == false && t.TrialReadingCriterionId == originalTask.TrialReadingCriterionId )
|
||||||
|
.Where(t=>t.Id==originalTask.Id||t.Id==originalTask.JudgeVisitTaskId)
|
||||||
|
.AnyAsync(t => t.VisitTaskNum == task.VisitTaskNum))
|
||||||
|
{
|
||||||
|
//---当前为无序阅片,影像存在问题,项目组已申请回退,暂不能申请重阅
|
||||||
|
throw new BusinessValidationFailedException(_localizer["VisitTask_RandomInvalidRereading"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//也要支持裁判重阅240701
|
||||||
|
|
||||||
|
if (task.ReadingCategory != ReadingCategory.Visit && task.ReadingCategory != ReadingCategory.Judge)
|
||||||
|
{
|
||||||
|
//---无序阅片,仅仅允许IR 申请 访视、裁判类型类别的任务进行重阅
|
||||||
throw new BusinessValidationFailedException(_localizer["VisitTask_IRGlobalRecheck"]);
|
throw new BusinessValidationFailedException(_localizer["VisitTask_IRGlobalRecheck"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1606,8 +1626,10 @@ namespace IRaCIS.Core.Application.Service.Allocation
|
|||||||
|
|
||||||
if ((origenalTask.TaskState != TaskState.Effect && origenalTask.TaskState != TaskState.Freeze))
|
if ((origenalTask.TaskState != TaskState.Effect && origenalTask.TaskState != TaskState.Freeze))
|
||||||
{
|
{
|
||||||
|
await _visitTaskReReadingRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Id, u => new VisitTaskReReading() { RequestReReadingConfirmUserId = _userInfo.Id, RequestReReadingResultEnum = RequestReReadingResult.Invalid });
|
||||||
|
|
||||||
//---当前申请重阅任务的状态,已被其他任务重阅已影响,不允许对该状态下的任务进行重阅同意与否操作
|
//---当前申请重阅任务的状态,已被其他任务重阅已影响,不允许对该状态下的任务进行重阅同意与否操作
|
||||||
return ResponseOutput.NotOk(_localizer["VisitTask_ReapplyStatusConflict"]);
|
return ResponseOutput.Ok(string.Empty, msg:_localizer["VisitTask_ReapplyStatusConflict"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1634,7 +1656,7 @@ namespace IRaCIS.Core.Application.Service.Allocation
|
|||||||
if (criterionConfig.CriterionType == CriterionType.RECIST1Point1 && criterionConfig.IsAdditionalAssessment)
|
if (criterionConfig.CriterionType == CriterionType.RECIST1Point1 && criterionConfig.IsAdditionalAssessment)
|
||||||
{
|
{
|
||||||
// PM申请 SPM / CPM审批
|
// PM申请 SPM / CPM审批
|
||||||
if (visitTaskReReadingAppply.RequestReReadingType == RequestReReadingType.TrialGroupApply && (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.SPM || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CPM))
|
if (visitTaskReReadingAppply.RequestReReadingType == RequestReReadingType.TrialGroupApply && (IsSpmOrCPM()))
|
||||||
{
|
{
|
||||||
filterExpression = filterExpression.And(t => t.TrialReadingCriterionId == origenalTask.TrialReadingCriterionId || t.TrialReadingCriterion.CriterionType == CriterionType.RECIST1Pointt1_MB);
|
filterExpression = filterExpression.And(t => t.TrialReadingCriterionId == origenalTask.TrialReadingCriterionId || t.TrialReadingCriterion.CriterionType == CriterionType.RECIST1Pointt1_MB);
|
||||||
}
|
}
|
||||||
@@ -1643,7 +1665,7 @@ namespace IRaCIS.Core.Application.Service.Allocation
|
|||||||
{
|
{
|
||||||
|
|
||||||
// 1.1 基线任务影响BM任务
|
// 1.1 基线任务影响BM任务
|
||||||
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager && _subjectVisitRepository.Any(t => t.Id == origenalTask.SourceSubjectVisitId && t.IsBaseLine == true))
|
if ((IsPMOrAPm()) && _subjectVisitRepository.Any(t => t.Id == origenalTask.SourceSubjectVisitId && t.IsBaseLine == true))
|
||||||
{
|
{
|
||||||
|
|
||||||
isIR1Point1AdditionalAssessmentBaseline = true;
|
isIR1Point1AdditionalAssessmentBaseline = true;
|
||||||
@@ -1666,7 +1688,7 @@ namespace IRaCIS.Core.Application.Service.Allocation
|
|||||||
if (agreeReReadingCommand.RequestReReadingResultEnum == RequestReReadingResult.Agree)
|
if (agreeReReadingCommand.RequestReReadingResultEnum == RequestReReadingResult.Agree)
|
||||||
{
|
{
|
||||||
//PM申请 SPM / CPM审批 回退访视,因此这里不生成访视任务 影响多个标准的任务
|
//PM申请 SPM / CPM审批 回退访视,因此这里不生成访视任务 影响多个标准的任务
|
||||||
if (visitTaskReReadingAppply.RequestReReadingType == RequestReReadingType.TrialGroupApply && (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.SPM || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CPM))
|
if (visitTaskReReadingAppply.RequestReReadingType == RequestReReadingType.TrialGroupApply && (IsSpmOrCPM()))
|
||||||
{
|
{
|
||||||
|
|
||||||
// 不管有序 无序 都会 回退访视
|
// 不管有序 无序 都会 回退访视
|
||||||
@@ -1786,7 +1808,7 @@ namespace IRaCIS.Core.Application.Service.Allocation
|
|||||||
|
|
||||||
}
|
}
|
||||||
//IR申请 PM 审批 注意这里有一致性分析的申请同意 不会回退访视,在此要生成影响的访视任务
|
//IR申请 PM 审批 注意这里有一致性分析的申请同意 不会回退访视,在此要生成影响的访视任务
|
||||||
else if (visitTaskReReadingAppply.RequestReReadingType == RequestReReadingType.DocotorApply && (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.AIR))
|
else if (visitTaskReReadingAppply.RequestReReadingType == RequestReReadingType.DocotorApply && (IsPMOrAPm() || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.AIR))
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
@@ -2291,7 +2313,7 @@ namespace IRaCIS.Core.Application.Service.Allocation
|
|||||||
|
|
||||||
|
|
||||||
//PM 才允许操作
|
//PM 才允许操作
|
||||||
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager)
|
if (IsPMOrAPm())
|
||||||
{
|
{
|
||||||
|
|
||||||
#region 有序 无序公用流程
|
#region 有序 无序公用流程
|
||||||
@@ -2556,6 +2578,16 @@ namespace IRaCIS.Core.Application.Service.Allocation
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private bool IsPMOrAPm()
|
||||||
|
{
|
||||||
|
return _userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.APM;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsSpmOrCPM()
|
||||||
|
{
|
||||||
|
return _userInfo.UserTypeEnumInt == (int)UserTypeEnum.SPM || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CPM;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 影响提示列表 重阅仅仅针对已完成的任务申请 退回针对的是未完成的(退回仅仅针对是访视类型的)
|
/// 影响提示列表 重阅仅仅针对已完成的任务申请 退回针对的是未完成的(退回仅仅针对是访视类型的)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -2587,12 +2619,12 @@ namespace IRaCIS.Core.Application.Service.Allocation
|
|||||||
{
|
{
|
||||||
|
|
||||||
// IR 申请 PM 同意
|
// IR 申请 PM 同意
|
||||||
if (((_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager && applyId != null && await _visitTaskReReadingRepository.AnyAsync(t => t.Id == applyId && t.CreateUser.UserTypeEnum == UserTypeEnum.IndependentReviewer))
|
if ((( IsPMOrAPm() && applyId != null && await _visitTaskReReadingRepository.AnyAsync(t => t.Id == applyId && t.CreateUser.UserTypeEnum == UserTypeEnum.IndependentReviewer))
|
||||||
|| (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.IndependentReviewer && applyId == null)))
|
|| (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.IndependentReviewer && applyId == null)))
|
||||||
{
|
{
|
||||||
|
|
||||||
// 1.1 基线任务影响BM任务
|
// 1.1 基线任务影响BM任务
|
||||||
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager && _subjectVisitRepository.Any(t => t.Id == filterObj.SourceSubjectVisitId && t.IsBaseLine == true))
|
if (IsPMOrAPm() && _subjectVisitRepository.Any(t => t.Id == filterObj.SourceSubjectVisitId && t.IsBaseLine == true))
|
||||||
{
|
{
|
||||||
|
|
||||||
isIR1Point1AdditionalAssessmentBaseline = true;
|
isIR1Point1AdditionalAssessmentBaseline = true;
|
||||||
@@ -2630,7 +2662,7 @@ namespace IRaCIS.Core.Application.Service.Allocation
|
|||||||
|
|
||||||
//IR 申请 PM 同意 仅仅影响自己
|
//IR 申请 PM 同意 仅仅影响自己
|
||||||
|
|
||||||
if ((_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager && applyId != null && await _visitTaskReReadingRepository.AnyAsync(t => t.Id == applyId && t.CreateUser.UserTypeEnum == UserTypeEnum.IndependentReviewer))
|
if ((IsPMOrAPm() && applyId != null && await _visitTaskReReadingRepository.AnyAsync(t => t.Id == applyId && t.CreateUser.UserTypeEnum == UserTypeEnum.IndependentReviewer))
|
||||||
|| (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.IndependentReviewer && applyId == null))
|
|| (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.IndependentReviewer && applyId == null))
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -2748,8 +2780,9 @@ namespace IRaCIS.Core.Application.Service.Allocation
|
|||||||
}
|
}
|
||||||
//PM 影响所有阅片人 仅仅针对访视 SPM CPM 调用
|
//PM 影响所有阅片人 仅仅针对访视 SPM CPM 调用
|
||||||
|
|
||||||
else if (((_userInfo.UserTypeEnumInt == (int)UserTypeEnum.SPM || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CPM) && applyId != null && await _visitTaskReReadingRepository.AnyAsync(t => t.Id == applyId && t.CreateUser.UserTypeEnum == UserTypeEnum.ProjectManager) && filterObj.IsAnalysisCreate == false && filterObj.ReadingCategory == ReadingCategory.Visit)
|
else if (((IsSpmOrCPM()) && applyId != null &&
|
||||||
|| (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager && applyId == null))
|
await _visitTaskReReadingRepository.AnyAsync(t => t.Id == applyId && (t.CreateUser.UserTypeEnum == UserTypeEnum.ProjectManager || t.CreateUser.UserTypeEnum == UserTypeEnum.APM)) && filterObj.IsAnalysisCreate == false && filterObj.ReadingCategory == ReadingCategory.Visit)
|
||||||
|
|| (IsPMOrAPm() && applyId == null))
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
@@ -2812,7 +2845,7 @@ namespace IRaCIS.Core.Application.Service.Allocation
|
|||||||
throw new BusinessValidationFailedException(_localizer["VisitTask_NoConsistencyReturn"]);
|
throw new BusinessValidationFailedException(_localizer["VisitTask_NoConsistencyReturn"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filterObj.ReadingCategory == ReadingCategory.Visit && _userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager)
|
if (filterObj.ReadingCategory == ReadingCategory.Visit && IsPMOrAPm())
|
||||||
{
|
{
|
||||||
//有序
|
//有序
|
||||||
if (criterionConfig.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
|
if (criterionConfig.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
|
|
||||||
CreateMap<SubjectUser, SubjectUserDTO>().IncludeBase<SubjectUser, SubjectUserView>()
|
CreateMap<SubjectUser, SubjectUserDTO>().IncludeBase<SubjectUser, SubjectUserView>()
|
||||||
.ForMember(o => o.IsHaveReading, t => t.MapFrom(u => u.Subject.SubjectVisitTaskList.Any(t => t.ReadingTaskState != ReadingTaskState.WaitReading && t.TrialReadingCriterionId==u.TrialReadingCriterionId && t.DoctorUserId==u.DoctorUserId)));
|
.ForMember(o => o.IsHaveReading, t => t.MapFrom(u => u.Subject.SubjectVisitTaskList.Any(t => t.ReadingTaskState != ReadingTaskState.WaitReading && t.TrialReadingCriterionId==u.TrialReadingCriterionId && t.DoctorUserId==u.DoctorUserId && t.TaskState == TaskState.Effect)));
|
||||||
|
|
||||||
|
|
||||||
CreateMap<SubjectVisit, VisitGenerataTaskDTO>();
|
CreateMap<SubjectVisit, VisitGenerataTaskDTO>();
|
||||||
@@ -145,7 +145,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
.ForMember(o => o.HistoryReadingDoctorUserList, t => t.MapFrom(u => u.JudgeVisitList));
|
.ForMember(o => o.HistoryReadingDoctorUserList, t => t.MapFrom(u => u.JudgeVisitList));
|
||||||
|
|
||||||
CreateMap<VisitTask, ReadingTaskView>().IncludeBase<VisitTask, VisitTaskView>()
|
CreateMap<VisitTask, ReadingTaskView>().IncludeBase<VisitTask, VisitTaskView>()
|
||||||
|
.ForMember(o => o.IsHaveFeedBack, t => t.MapFrom(u => u.UserFeedBackList.Any(t=>t.State==0)))
|
||||||
;
|
;
|
||||||
|
|
||||||
CreateMap<VisitTask, AnalysisTaskView>().IncludeBase<VisitTask, VisitTaskView>()
|
CreateMap<VisitTask, AnalysisTaskView>().IncludeBase<VisitTask, VisitTaskView>()
|
||||||
@@ -238,7 +238,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
.ForMember(o => o.TrialReadingCriterionName, t => t.MapFrom(u => u.TrialReadingCriterion.CriterionName))
|
.ForMember(o => o.TrialReadingCriterionName, t => t.MapFrom(u => u.TrialReadingCriterion.CriterionName))
|
||||||
.ForMember(o => o.TrialSiteCode, t => t.MapFrom(u => /*u.IsAnalysisCreate == true ? u.BlindTrialSiteCode :*/ u.Subject.TrialSite.TrialSiteCode))
|
.ForMember(o => o.TrialSiteCode, t => t.MapFrom(u => /*u.IsAnalysisCreate == true ? u.BlindTrialSiteCode :*/ u.Subject.TrialSite.TrialSiteCode))
|
||||||
.ForMember(o => o.SubjectCode, t => t.MapFrom(u => /*u.IsAnalysisCreate == true ? u.BlindSubjectCode :*/ u.Subject.Code))
|
.ForMember(o => o.SubjectCode, t => t.MapFrom(u => /*u.IsAnalysisCreate == true ? u.BlindSubjectCode :*/ u.Subject.Code))
|
||||||
.ForMember(o => o.GeneratedMedicalReviewCount, t => t.MapFrom(u => u.TaskMedicalReviewList.Count()))
|
.ForMember(o => o.GeneratedMedicalReviewCount, t => t.MapFrom(u => u.TaskMedicalReviewList.Count(t=>t.MedicalManagerUserId!=null)))
|
||||||
.ForMember(o => o.MedicalNo, t => t.MapFrom(u => u.Subject.MedicalNo))
|
.ForMember(o => o.MedicalNo, t => t.MapFrom(u => u.Subject.MedicalNo))
|
||||||
.ForMember(o => o.IsGeneratedJudge, t => t.MapFrom(u => u.JudgeVisitTaskId != null))
|
.ForMember(o => o.IsGeneratedJudge, t => t.MapFrom(u => u.JudgeVisitTaskId != null))
|
||||||
.ForMember(o => o.ReadingDurationTimeSpan, t => t.MapFrom(u => u.SignTime - u.FirstReadingTime))
|
.ForMember(o => o.ReadingDurationTimeSpan, t => t.MapFrom(u => u.SignTime - u.FirstReadingTime))
|
||||||
@@ -318,6 +318,9 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CreateMap<ReadingClinicalData, ReadingConsistentClinicalData>().ReverseMap();
|
||||||
|
CreateMap<ReadingClinicalDataPDF, ReadingConsistentClinicalDataPDF>().ReverseMap();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,11 +37,11 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
.WhereIf(queryCommonDocument.CriterionTypeEnum != null, t => t.CriterionTypeEnum == queryCommonDocument.CriterionTypeEnum)
|
.WhereIf(queryCommonDocument.CriterionTypeEnum != null, t => t.CriterionTypeEnum == queryCommonDocument.CriterionTypeEnum)
|
||||||
.WhereIf(queryCommonDocument.BusinessScenarioEnum != null, t => t.BusinessScenarioEnum == queryCommonDocument.BusinessScenarioEnum)
|
.WhereIf(queryCommonDocument.BusinessScenarioEnum != null, t => t.BusinessScenarioEnum == queryCommonDocument.BusinessScenarioEnum)
|
||||||
.WhereIf(string.IsNullOrEmpty(queryCommonDocument.Code), t => t.Code.Contains(queryCommonDocument.Code))
|
.WhereIf(!string.IsNullOrEmpty(queryCommonDocument.Code), t => t.Code.Contains(queryCommonDocument.Code))
|
||||||
.WhereIf(string.IsNullOrEmpty(queryCommonDocument.Name), t => t.Name.Contains(queryCommonDocument.Name))
|
.WhereIf(!string.IsNullOrEmpty(queryCommonDocument.Name), t => t.Name.Contains(queryCommonDocument.Name))
|
||||||
.ProjectTo<CommonDocumentView>(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken, userId = _userInfo.Id });
|
.ProjectTo<CommonDocumentView>(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken, userId = _userInfo.Id });
|
||||||
|
|
||||||
return await commonDocumentQueryable.ToPagedListAsync(queryCommonDocument.PageIndex, queryCommonDocument.PageSize, String.IsNullOrEmpty(queryCommonDocument.SortField) ? nameof(CommonDocument.Code) : queryCommonDocument.SortField, queryCommonDocument.Asc); ;
|
return await commonDocumentQueryable.ToPagedListAsync(queryCommonDocument);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
var filePath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, dbbeforeEntity.Path);
|
var filePath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, dbbeforeEntity.Path);
|
||||||
|
|
||||||
if (File.Exists(filePath))
|
if (File.Exists(filePath) && dbbeforeEntity.Path!=addOrEditCommonDocument.Path)
|
||||||
{
|
{
|
||||||
File.Delete(filePath);
|
File.Delete(filePath);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
{
|
{
|
||||||
public Guid? Id { get; set; }
|
public Guid? Id { get; set; }
|
||||||
public string Name { get; set; } = String.Empty;
|
public string Name { get; set; } = String.Empty;
|
||||||
|
|
||||||
|
public string NameCN { get; set; } = String.Empty;
|
||||||
public string Path { get; set; } = String.Empty;
|
public string Path { get; set; } = String.Empty;
|
||||||
public string Description { get; set; } = String.Empty;
|
public string Description { get; set; } = String.Empty;
|
||||||
public bool IsDeleted { get; set; }
|
public bool IsDeleted { get; set; }
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ namespace IRaCIS.Core.Application.Contracts
|
|||||||
|
|
||||||
public bool? IsDistinguishCriteria { get; set; }
|
public bool? IsDistinguishCriteria { get; set; }
|
||||||
|
|
||||||
|
public SysEmailLevel? SystemLevel { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///<summary> EmailNoticeConfigAddOrEdit 列表查询参数模型</summary>
|
///<summary> EmailNoticeConfigAddOrEdit 列表查询参数模型</summary>
|
||||||
@@ -126,6 +128,9 @@ namespace IRaCIS.Core.Application.Contracts
|
|||||||
public List<UserTypeEnum> ToUserTypeList { get; set; }
|
public List<UserTypeEnum> ToUserTypeList { get; set; }
|
||||||
public List<UserTypeEnum> CopyUserTypeList { get; set; }
|
public List<UserTypeEnum> CopyUserTypeList { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public SysEmailLevel SystemLevel { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
//--------------------------------------------------------------------
|
||||||
|
// 此代码由T4模板自动生成 byzhouhang 20210918
|
||||||
|
// 生成时间 2024-07-02 09:29:36
|
||||||
|
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
using System;
|
||||||
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
namespace IRaCIS.Core.Application.ViewModel
|
||||||
|
{
|
||||||
|
/// <summary> ExploreRecommendView 列表视图模型 </summary>
|
||||||
|
public class ExploreRecommendView: ExploreRecommendAddOrEdit
|
||||||
|
{
|
||||||
|
|
||||||
|
public DateTime CreateTime { get; set; }
|
||||||
|
public Guid CreateUserId { get; set; }
|
||||||
|
public Guid UpdateUserId { get; set; }
|
||||||
|
public DateTime UpdateTime { get; set; }
|
||||||
|
|
||||||
|
public DateTime? DeleteTime { get; set; }
|
||||||
|
public Guid? DeleteUserId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
///<summary>ExploreRecommendQuery 列表查询参数模型</summary>
|
||||||
|
public class ExploreRecommendQuery:PageInput
|
||||||
|
{
|
||||||
|
|
||||||
|
public string? Version { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public string? Title { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public string? DownloadUrl { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public string? FileName { get; set; }
|
||||||
|
|
||||||
|
public bool? IsDeleted { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
///<summary> ExploreRecommendAddOrEdit 列表查询参数模型</summary>
|
||||||
|
public class ExploreRecommendAddOrEdit
|
||||||
|
{
|
||||||
|
public Guid? Id { get; set; }
|
||||||
|
public string ExploreType { get; set; }
|
||||||
|
|
||||||
|
public string Version { get; set; }
|
||||||
|
public string Title { get; set; }
|
||||||
|
|
||||||
|
public bool IsDeleted { get; set; }
|
||||||
|
public string DownloadUrl { get; set; }
|
||||||
|
public string Path { get; set; }
|
||||||
|
public string FileName { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -17,6 +17,9 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
public DateTime UpdateTime { get; set; }
|
public DateTime UpdateTime { get; set; }
|
||||||
public Guid UpdateUserId { get; set; }
|
public Guid UpdateUserId { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public string Version { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///<summary>InternationalizationQuery 列表查询参数模型</summary>
|
///<summary>InternationalizationQuery 列表查询参数模型</summary>
|
||||||
@@ -30,6 +33,10 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
|
|
||||||
public string? ValueCN { get; set; }
|
public string? ValueCN { get; set; }
|
||||||
|
|
||||||
|
public string? Module { get; set; }
|
||||||
|
//关联版本历史记录表Id
|
||||||
|
public Guid? PublishLogId { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///<summary> InternationalizationAddOrEdit 列表查询参数模型</summary>
|
///<summary> InternationalizationAddOrEdit 列表查询参数模型</summary>
|
||||||
@@ -45,6 +52,9 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
public string FrontType { get; set; } = string.Empty;
|
public string FrontType { get; set; } = string.Empty;
|
||||||
|
|
||||||
public int InternationalizationType { get; set; }
|
public int InternationalizationType { get; set; }
|
||||||
|
public string Module { get; set; } = string.Empty;
|
||||||
|
//关联版本历史记录表Id
|
||||||
|
public Guid? PublishLogId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BatchAddInternationalization
|
public class BatchAddInternationalization
|
||||||
@@ -64,16 +74,28 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
public string Value { get; set; } = string.Empty;
|
public string Value { get; set; } = string.Empty;
|
||||||
public string FrontType { get; set; } = string.Empty;
|
public string FrontType { get; set; } = string.Empty;
|
||||||
public string ValueCN { get; set; } = string.Empty;
|
public string ValueCN { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public string Module { get; set; } = string.Empty;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BatchAddInternationalizationDto : BatchInternationalizationDto
|
public class BatchAddInternationalizationDto : BatchInternationalizationDto
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class InternationalizationSimpleDto: BatchInternationalizationDto
|
public class InternationalizationSimpleDto : BatchInternationalizationDto
|
||||||
{
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BatchUpdateInfoCommand
|
||||||
|
{
|
||||||
|
public List<Guid> IdList { get; set; }
|
||||||
|
|
||||||
|
public Guid? PublishLogId { get; set; }
|
||||||
|
|
||||||
|
public int State { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
|
|
||||||
public string? UpdateContent { get; set; }
|
public string? UpdateContent { get; set; }
|
||||||
|
|
||||||
|
public int? State { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///<summary> PublishLogAddOrEdit 列表查询参数模型</summary>
|
///<summary> PublishLogAddOrEdit 列表查询参数模型</summary>
|
||||||
@@ -33,9 +35,24 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
{
|
{
|
||||||
public Guid? Id { get; set; }
|
public Guid? Id { get; set; }
|
||||||
public string Version { get; set; }
|
public string Version { get; set; }
|
||||||
public DateTime PublishTime { get; set; }
|
public DateTime? PublishTime { get; set; }
|
||||||
public string UpdateContent { get; set; }
|
public string UpdateContent { get; set; }
|
||||||
|
|
||||||
|
//0 开发中 ,已发布
|
||||||
|
public int State { get; set; }
|
||||||
|
|
||||||
|
public bool IsCurrentVersion { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class PublishVersionSelect
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string Version { get; set; }
|
||||||
|
public int State { get; set; }
|
||||||
|
public DateTime? PublishTime { get; set; }
|
||||||
|
public bool IsCurrentVersion { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ namespace IRaCIS.Core.Application.Contracts
|
|||||||
public async Task<PageOutput<EmailNoticeConfigView>> GetEmailNoticeConfigList(EmailNoticeConfigQuery queryEmailNoticeConfig)
|
public async Task<PageOutput<EmailNoticeConfigView>> GetEmailNoticeConfigList(EmailNoticeConfigQuery queryEmailNoticeConfig)
|
||||||
{
|
{
|
||||||
var emailNoticeConfigQueryable = _emailNoticeConfigrepository
|
var emailNoticeConfigQueryable = _emailNoticeConfigrepository
|
||||||
|
.WhereIf(queryEmailNoticeConfig.SystemLevel == null, t => t.SystemLevel == SysEmailLevel.not_sys)
|
||||||
|
.WhereIf(queryEmailNoticeConfig.SystemLevel!=null, t =>t.SystemLevel == queryEmailNoticeConfig.SystemLevel)
|
||||||
.WhereIf(queryEmailNoticeConfig.IsDistinguishCriteria != null, t => t.IsDistinguishCriteria == queryEmailNoticeConfig.IsDistinguishCriteria)
|
.WhereIf(queryEmailNoticeConfig.IsDistinguishCriteria != null, t => t.IsDistinguishCriteria == queryEmailNoticeConfig.IsDistinguishCriteria)
|
||||||
.WhereIf(queryEmailNoticeConfig.CriterionTypeEnum != null, t => t.CriterionTypeEnum == queryEmailNoticeConfig.CriterionTypeEnum)
|
.WhereIf(queryEmailNoticeConfig.CriterionTypeEnum != null, t => t.CriterionTypeEnum == queryEmailNoticeConfig.CriterionTypeEnum)
|
||||||
.WhereIf(queryEmailNoticeConfig.BusinessScenarioEnum != null, t => t.BusinessScenarioEnum == queryEmailNoticeConfig.BusinessScenarioEnum)
|
.WhereIf(queryEmailNoticeConfig.BusinessScenarioEnum != null, t => t.BusinessScenarioEnum == queryEmailNoticeConfig.BusinessScenarioEnum)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,93 @@
|
|||||||
|
//--------------------------------------------------------------------
|
||||||
|
// 此代码由T4模板自动生成 byzhouhang 20210918
|
||||||
|
// 生成时间 2024-07-02 09:26:59
|
||||||
|
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
using IRaCIS.Core.Domain.Models;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using IRaCIS.Core.Application.Interfaces;
|
||||||
|
using IRaCIS.Core.Application.ViewModel;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
namespace IRaCIS.Core.Application.Service
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// ExploreRecommendService
|
||||||
|
/// </summary>
|
||||||
|
[ApiExplorerSettings(GroupName = "Common")]
|
||||||
|
public class ExploreRecommendService : BaseService, IExploreRecommendService
|
||||||
|
{
|
||||||
|
|
||||||
|
private readonly IRepository<ExploreRecommend> _exploreRecommendRepository;
|
||||||
|
|
||||||
|
public ExploreRecommendService(IRepository<ExploreRecommend> exploreRecommendRepository)
|
||||||
|
{
|
||||||
|
_exploreRecommendRepository = exploreRecommendRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<PageOutput<ExploreRecommendView>> GetExploreRecommendList(ExploreRecommendQuery inQuery)
|
||||||
|
{
|
||||||
|
|
||||||
|
var exploreRecommendQueryable =
|
||||||
|
|
||||||
|
_exploreRecommendRepository.Where().IgnoreQueryFilters()
|
||||||
|
.WhereIf(string.IsNullOrEmpty(inQuery.Title), t => t.Title.Contains(inQuery.Title))
|
||||||
|
.WhereIf(string.IsNullOrEmpty(inQuery.FileName), t => t.Title.Contains(inQuery.FileName))
|
||||||
|
.WhereIf(string.IsNullOrEmpty(inQuery.DownloadUrl), t => t.Title.Contains(inQuery.DownloadUrl))
|
||||||
|
.WhereIf(string.IsNullOrEmpty(inQuery.Version), t => t.Title.Contains(inQuery.Version))
|
||||||
|
.WhereIf(inQuery.IsDeleted != null, t => t.IsDeleted == t.IsDeleted)
|
||||||
|
.ProjectTo<ExploreRecommendView>(_mapper.ConfigurationProvider);
|
||||||
|
|
||||||
|
var pageList = await exploreRecommendQueryable
|
||||||
|
.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrWhiteSpace(inQuery.SortField) ? nameof(ExploreRecommendView.Id) : inQuery.SortField,
|
||||||
|
inQuery.Asc);
|
||||||
|
|
||||||
|
return pageList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<IResponseOutput> AddOrUpdateExploreRecommend(ExploreRecommendAddOrEdit addOrEditExploreRecommend)
|
||||||
|
{
|
||||||
|
var verifyExp2 = new EntityVerifyExp<ExploreRecommend>()
|
||||||
|
{
|
||||||
|
VerifyExp = u => u.IsDeleted == addOrEditExploreRecommend.IsDeleted && u.ExploreType == addOrEditExploreRecommend.ExploreType,
|
||||||
|
|
||||||
|
// "当前类型浏览器启用版本只允许有一个"
|
||||||
|
VerifyMsg = _localizer["ExploreRecommend_OnlyOneTypePerType"] ,
|
||||||
|
|
||||||
|
IsVerify = addOrEditExploreRecommend.IsDeleted == false
|
||||||
|
};
|
||||||
|
|
||||||
|
var entity = await _exploreRecommendRepository.InsertOrUpdateAsync(addOrEditExploreRecommend, true, verifyExp2);
|
||||||
|
|
||||||
|
return ResponseOutput.Ok(entity.Id.ToString());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[HttpDelete("{exploreRecommendId:guid}")]
|
||||||
|
public async Task<IResponseOutput> DeleteExploreRecommend(Guid exploreRecommendId)
|
||||||
|
{
|
||||||
|
var success = await _exploreRecommendRepository.DeleteFromQueryAsync(t => t.Id == exploreRecommendId, true,true);
|
||||||
|
return ResponseOutput.Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
[AllowAnonymous]
|
||||||
|
public async Task<List<ExploreRecommendView> > GetExploreRecommentInfo()
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
var result = await _exploreRecommendRepository.Where(t => t.IsDeleted == false).ProjectTo<ExploreRecommendView>(_mapper.ConfigurationProvider).ToListAsync();
|
||||||
|
|
||||||
|
if (result .Count==0)
|
||||||
|
{ //"系统浏览器版本推荐未维护,请联系维护人员"
|
||||||
|
throw new QueryBusinessObjectNotExistException(_localizer["ExploreRecommend_NoExporeRecord"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
//--------------------------------------------------------------------
|
||||||
|
// 此代码由T4模板自动生成 byzhouhang 20210918
|
||||||
|
// 生成时间 2024-07-02 09:27:36
|
||||||
|
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
using IRaCIS.Core.Application.ViewModel;
|
||||||
|
namespace IRaCIS.Core.Application.Interfaces
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// IExploreRecommendService
|
||||||
|
/// </summary>
|
||||||
|
public interface IExploreRecommendService
|
||||||
|
{
|
||||||
|
|
||||||
|
Task<PageOutput<ExploreRecommendView>> GetExploreRecommendList(ExploreRecommendQuery inQuery);
|
||||||
|
|
||||||
|
Task<IResponseOutput> AddOrUpdateExploreRecommend(ExploreRecommendAddOrEdit addOrEditExploreRecommend);
|
||||||
|
|
||||||
|
Task<IResponseOutput> DeleteExploreRecommend(Guid exploreRecommendId);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -81,7 +81,9 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
{
|
{
|
||||||
var mapItem = _mapper.Map<Internationalization>(item);
|
var mapItem = _mapper.Map<Internationalization>(item);
|
||||||
mapItem.InternationalizationType = 0;
|
mapItem.InternationalizationType = 0;
|
||||||
mapItem.State = 1;
|
|
||||||
|
// 0 是预翻译 1是已确认 2是后端废弃
|
||||||
|
mapItem.State = 0;
|
||||||
|
|
||||||
await _internationalizationRepository.AddAsync(mapItem);
|
await _internationalizationRepository.AddAsync(mapItem);
|
||||||
}
|
}
|
||||||
@@ -100,6 +102,8 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
var internationalizationQueryable = _internationalizationRepository
|
var internationalizationQueryable = _internationalizationRepository
|
||||||
.WhereIf(inQuery.Description != null, t => t.Description.Contains(inQuery.Description))
|
.WhereIf(inQuery.Description != null, t => t.Description.Contains(inQuery.Description))
|
||||||
|
.WhereIf(inQuery.Module != null, t => t.Module.Contains(inQuery.Module))
|
||||||
|
.WhereIf(inQuery.PublishLogId != null, t => t.PublishLogId==inQuery.PublishLogId)
|
||||||
.WhereIf(inQuery.Code != null, t => t.Code.Contains(inQuery.Code))
|
.WhereIf(inQuery.Code != null, t => t.Code.Contains(inQuery.Code))
|
||||||
.WhereIf(inQuery.State != null, t => t.State == inQuery.State)
|
.WhereIf(inQuery.State != null, t => t.State == inQuery.State)
|
||||||
.WhereIf(inQuery.InternationalizationType != null, t => t.InternationalizationType == inQuery.InternationalizationType)
|
.WhereIf(inQuery.InternationalizationType != null, t => t.InternationalizationType == inQuery.InternationalizationType)
|
||||||
@@ -180,7 +184,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
if (addOrEditInternationalization.InternationalizationType == 1)
|
if (addOrEditInternationalization.InternationalizationType == 1)
|
||||||
{
|
{
|
||||||
await InternationalizationHelper.AddOrUpdateJsonKeyValueAsync(entity.Code, addOrEditInternationalization.Value, addOrEditInternationalization.ValueCN);
|
await InternationalizationHelper.AddOrUpdateJsonKeyValueAsync(entity.Code, addOrEditInternationalization.Value, addOrEditInternationalization.ValueCN,addOrEditInternationalization.Description);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -202,6 +206,19 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
return ResponseOutput.Ok();
|
return ResponseOutput.Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 批量更新状态和发布版本
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inCommand"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPut]
|
||||||
|
public async Task<IResponseOutput> BatchUpdateInternationalInfo(BatchUpdateInfoCommand inCommand)
|
||||||
|
{
|
||||||
|
await _internationalizationRepository.BatchUpdateNoTrackingAsync(t => inCommand.IdList.Contains(t.Id), t => new Internationalization() { State = inCommand.State, PublishLogId = inCommand.PublishLogId });
|
||||||
|
|
||||||
|
return ResponseOutput.Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,19 @@ using IRaCIS.Application.Contracts;
|
|||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Medallion.Threading;
|
using Medallion.Threading;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using IRaCIS.Core.Infrastructure;
|
||||||
|
using DocumentFormat.OpenXml.Spreadsheet;
|
||||||
|
using IRaCIS.Core.Application.Service.Reading.Dto;
|
||||||
|
using NPOI.SS.Formula.Functions;
|
||||||
|
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||||
|
using IRaCIS.Core.Domain.Models;
|
||||||
|
using DocumentFormat.OpenXml.Office2013.Excel;
|
||||||
|
using IRaCIS.Core.Application.Contracts;
|
||||||
|
using DocumentFormat.OpenXml.Vml;
|
||||||
|
using System.Net.Mail;
|
||||||
|
using IP2Region.Net.XDB;
|
||||||
|
using NPOI.SS.Formula.Eval;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace IRaCIS.Application.Services
|
namespace IRaCIS.Application.Services
|
||||||
{
|
{
|
||||||
@@ -19,7 +32,7 @@ namespace IRaCIS.Application.Services
|
|||||||
|
|
||||||
Task SendEmailVerification(string emailAddress, int verificationCode);
|
Task SendEmailVerification(string emailAddress, int verificationCode);
|
||||||
|
|
||||||
Task SiteSurveyRejectEmail(MimeMessage messageToSend);
|
Task SiteSurveyRejectEmail(MimeMessage messageToSend, TrialSiteSurvey trialSiteSurvey, string routeUrl, User? user = null);
|
||||||
|
|
||||||
Task SenMFAVerifyEmail(Guid userId, string userName, string emailAddress, int verificationCode, UserMFAType mfaType = UserMFAType.Login);
|
Task SenMFAVerifyEmail(Guid userId, string userName, string emailAddress, int verificationCode, UserMFAType mfaType = UserMFAType.Login);
|
||||||
|
|
||||||
@@ -37,10 +50,10 @@ namespace IRaCIS.Application.Services
|
|||||||
|
|
||||||
Task<Guid> DoctorJoinTrialEmail(Guid trialId, Guid doctorId, string baseUrl, string rootUrl);
|
Task<Guid> DoctorJoinTrialEmail(Guid trialId, Guid doctorId, string baseUrl, string rootUrl);
|
||||||
|
|
||||||
|
Task UserFeedBackMail(Guid feedBackId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MailVerificationService : BaseService, IMailVerificationService
|
public class MailVerificationService : BaseService, IMailVerificationService
|
||||||
{
|
{
|
||||||
private readonly IRepository<VerificationCode> _verificationCodeRepository;
|
private readonly IRepository<VerificationCode> _verificationCodeRepository;
|
||||||
|
|
||||||
@@ -59,15 +72,16 @@ namespace IRaCIS.Application.Services
|
|||||||
|
|
||||||
private readonly SystemEmailSendConfig _systemEmailConfig;
|
private readonly SystemEmailSendConfig _systemEmailConfig;
|
||||||
|
|
||||||
|
private readonly IRepository<EmailNoticeConfig> _emailNoticeConfigrepository;
|
||||||
|
|
||||||
|
public MailVerificationService(IRepository<VerificationCode> verificationCodeRepository,
|
||||||
public MailVerificationService(IRepository<VerificationCode> verificationCodeRepository,
|
|
||||||
IRepository<SystemBasicData> systemBasicDatarepository,
|
IRepository<SystemBasicData> systemBasicDatarepository,
|
||||||
IRepository<User> userRepository,
|
IRepository<User> userRepository,
|
||||||
ITokenService tokenService,
|
ITokenService tokenService,
|
||||||
IRepository<Trial> trialRepository,
|
IRepository<Trial> trialRepository,
|
||||||
IRepository<UserType> userTypeRepository,
|
IRepository<UserType> userTypeRepository,
|
||||||
IRepository<Doctor> doctorTypeRepository,
|
IRepository<Doctor> doctorTypeRepository,
|
||||||
|
IRepository<EmailNoticeConfig> emailNoticeConfigRepository,
|
||||||
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig, IDistributedLockProvider distributedLockProvider)
|
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig, IDistributedLockProvider distributedLockProvider)
|
||||||
{
|
{
|
||||||
_systemEmailConfig = systemEmailConfig.CurrentValue;
|
_systemEmailConfig = systemEmailConfig.CurrentValue;
|
||||||
@@ -80,16 +94,85 @@ namespace IRaCIS.Application.Services
|
|||||||
_userTypeRepository = userTypeRepository;
|
_userTypeRepository = userTypeRepository;
|
||||||
_doctorTypeRepository = doctorTypeRepository;
|
_doctorTypeRepository = doctorTypeRepository;
|
||||||
_distributedLockProvider = distributedLockProvider;
|
_distributedLockProvider = distributedLockProvider;
|
||||||
|
_emailNoticeConfigrepository = emailNoticeConfigRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async Task<EmailNoticeConfig> GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario scenario, MimeMessage messageToSend,
|
||||||
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailFunc)
|
||||||
|
{
|
||||||
|
var configInfo = await _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario).FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
if (configInfo == null)
|
||||||
|
{
|
||||||
|
throw new BusinessValidationFailedException("系统未找到当前场景邮件配置信息,请联系运维人员核查");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var (topicStr, htmlBodyStr) = _userInfo.IsEn_Us ? (configInfo.EmailTopic, configInfo.EmailHtmlContent) : (configInfo.EmailTopicCN, configInfo.EmailHtmlContentCN);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//每个场景修改主题 和body的逻辑不一样
|
||||||
|
(topicStr, htmlBodyStr) = emailFunc((topicStr, htmlBodyStr));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
|
||||||
|
throw new BusinessValidationFailedException("邮件模板内容有误,填充内容出现问题,请联系运维人员核查");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
messageToSend.Subject = topicStr;
|
||||||
|
|
||||||
|
var builder = new BodyBuilder();
|
||||||
|
|
||||||
|
builder.HtmlBody = htmlBodyStr;
|
||||||
|
|
||||||
|
messageToSend.Body = builder.ToMessageBody();
|
||||||
|
|
||||||
|
return configInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<EmailNoticeConfig> GetEmailConfigInfoAsync(EmailBusinessScenario scenario)
|
||||||
|
{
|
||||||
|
var configInfo = await _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario).Include(t=>t.EmailNoticeUserTypeList).FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
if (configInfo == null)
|
||||||
|
{
|
||||||
|
throw new BusinessValidationFailedException("系统未找到当前场景邮件配置信息,请联系运维人员核查");
|
||||||
|
}
|
||||||
|
|
||||||
|
return configInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private EventHandler<MessageSentEventArgs> GetEmailSuccessHandle(Guid userId, int verificationCode, string email = "")
|
||||||
|
{
|
||||||
|
EventHandler<MessageSentEventArgs> sucessHandle = (sender, args) =>
|
||||||
|
{
|
||||||
|
// args.Response
|
||||||
|
var code = verificationCode.ToString();
|
||||||
|
_ = _verificationCodeRepository.AddAsync(new VerificationCode()
|
||||||
|
{
|
||||||
|
CodeType = VerifyType.Email,
|
||||||
|
HasSend = true,
|
||||||
|
Code = code,
|
||||||
|
UserId = userId,
|
||||||
|
EmailOrPhone = email,
|
||||||
|
ExpirationTime = DateTime.Now.AddMinutes(3)
|
||||||
|
}).Result;
|
||||||
|
_ = _verificationCodeRepository.SaveChangesAsync().Result;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return sucessHandle;
|
||||||
|
}
|
||||||
|
|
||||||
private string ReplaceCompanyName(string needDealtxt)
|
private string ReplaceCompanyName(string needDealtxt)
|
||||||
{
|
{
|
||||||
var str= needDealtxt.Replace("{company}", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyName : _systemEmailConfig.CompanyNameCN)
|
var str = needDealtxt.Replace("{company}", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyName : _systemEmailConfig.CompanyNameCN)
|
||||||
.Replace("{company abbreviation}", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN);
|
.Replace("{company abbreviation}", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN);
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,120 +184,65 @@ namespace IRaCIS.Application.Services
|
|||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
//收件地址
|
//收件地址
|
||||||
messageToSend.To.Add(new MailboxAddress(userName, emailAddress));
|
messageToSend.To.Add(new MailboxAddress(userName, emailAddress));
|
||||||
//主题
|
//主题---[来自{0}] 关于MFA邮箱验证的提醒
|
||||||
//---[来自{0}] 关于MFA邮箱验证的提醒
|
|
||||||
messageToSend.Subject = _localizer[mfaType == UserMFAType.Login? "Mail_EmailMFALoginTopic":"Mail_EmailMFAUnlockTopic", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN];
|
|
||||||
|
|
||||||
var builder = new BodyBuilder();
|
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
var pathToFile = _hostEnvironment.WebRootPath
|
|
||||||
+ Path.DirectorySeparatorChar.ToString()
|
|
||||||
+ "EmailTemplate"
|
|
||||||
+ Path.DirectorySeparatorChar.ToString()
|
|
||||||
//+ "UserOptCommon.html";
|
|
||||||
+ (_userInfo.IsEn_Us ? "UserOptCommon_US.html" : "UserOptCommon.html");
|
|
||||||
|
|
||||||
using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
|
|
||||||
{
|
{
|
||||||
var templateInfo = SourceReader.ReadToEnd();
|
var topicStr = string.Format(input.topicStr, companyName);
|
||||||
|
|
||||||
|
|
||||||
builder.HtmlBody = string.Format(ReplaceCompanyName(templateInfo),
|
|
||||||
|
|
||||||
|
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
||||||
userName,
|
userName,
|
||||||
_localizer[mfaType == UserMFAType.Login ? "Mail_EmailMFALoginEmail": "Mail_EmailMFAUnlockEmail"],
|
|
||||||
verificationCode
|
verificationCode
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
messageToSend.Body = builder.ToMessageBody();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EventHandler<MessageSentEventArgs> sucessHandle = (sender, args) =>
|
|
||||||
{
|
|
||||||
// args.Response
|
|
||||||
var code = verificationCode.ToString();
|
|
||||||
_ = _verificationCodeRepository.AddAsync(new VerificationCode()
|
|
||||||
{
|
|
||||||
CodeType = 0,
|
|
||||||
HasSend = true,
|
|
||||||
Code = code,
|
|
||||||
UserId = userId,
|
|
||||||
ExpirationTime = DateTime.Now.AddMinutes(3)
|
|
||||||
}).Result;
|
|
||||||
_ = _verificationCodeRepository.SaveChangesAsync().Result;
|
|
||||||
|
|
||||||
|
return (topicStr, htmlBodyStr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(mfaType == UserMFAType.Login ? EmailBusinessScenario.MFALogin : EmailBusinessScenario.MFAUnlock, messageToSend, emailConfigFunc);
|
||||||
|
|
||||||
|
|
||||||
|
var sucessHandle = GetEmailSuccessHandle(userId, verificationCode, emailAddress);
|
||||||
|
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, sucessHandle);
|
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, sucessHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
//重置邮箱
|
//用户重置邮箱
|
||||||
public async Task SendMailEditEmail(Guid userId, string userName, string emailAddress, int verificationCode)
|
public async Task SendMailEditEmail(Guid userId, string userName, string emailAddress, int verificationCode)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
//发件地址
|
//发件地址
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
//收件地址
|
//收件地址
|
||||||
messageToSend.To.Add(new MailboxAddress(userName, emailAddress));
|
messageToSend.To.Add(new MailboxAddress(userName, emailAddress));
|
||||||
//主题
|
//主题
|
||||||
//---[来自展影IRC] 关于重置邮箱的提醒
|
//---[来自展影IRC] 关于重置邮箱的提醒
|
||||||
messageToSend.Subject = _localizer["Mail_EmailResetReminder", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN];
|
|
||||||
|
|
||||||
var builder = new BodyBuilder();
|
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
var pathToFile = _hostEnvironment.WebRootPath
|
|
||||||
+ Path.DirectorySeparatorChar.ToString()
|
|
||||||
+ "EmailTemplate"
|
|
||||||
+ Path.DirectorySeparatorChar.ToString()
|
|
||||||
//+ "UserOptCommon.html";
|
|
||||||
+(_userInfo.IsEn_Us ? "UserOptCommon_US.html" : "UserOptCommon.html");
|
|
||||||
|
|
||||||
using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
|
|
||||||
{
|
{
|
||||||
var templateInfo = SourceReader.ReadToEnd();
|
var topicStr = string.Format(input.topicStr, companyName);
|
||||||
|
|
||||||
|
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
||||||
builder.HtmlBody = string.Format(ReplaceCompanyName(templateInfo),
|
|
||||||
|
|
||||||
userName,
|
userName,
|
||||||
//---尊敬的
|
//---您正在进行邮箱重置操作
|
||||||
//_localizer["Mail_Dear", userName],
|
|
||||||
//---您正在进行邮箱重置操作
|
|
||||||
_localizer["Mail_ResettingEmail"],
|
|
||||||
verificationCode
|
verificationCode
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
return (topicStr, htmlBodyStr);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
messageToSend.Body = builder.ToMessageBody();
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.UserResetEmail, messageToSend, emailConfigFunc);
|
||||||
|
|
||||||
|
|
||||||
|
var sucessHandle = GetEmailSuccessHandle(userId, verificationCode, emailAddress);
|
||||||
EventHandler<MessageSentEventArgs> sucessHandle = (sender, args) =>
|
|
||||||
{
|
|
||||||
// args.Response
|
|
||||||
var code = verificationCode.ToString();
|
|
||||||
_ = _verificationCodeRepository.AddAsync(new VerificationCode()
|
|
||||||
{
|
|
||||||
CodeType = 0,
|
|
||||||
HasSend = true,
|
|
||||||
Code = code,
|
|
||||||
UserId = userId,
|
|
||||||
ExpirationTime = DateTime.Now.AddMinutes(3)
|
|
||||||
}).Result;
|
|
||||||
_ = _verificationCodeRepository.SaveChangesAsync().Result;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, sucessHandle);
|
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, sucessHandle);
|
||||||
|
|
||||||
@@ -231,61 +259,36 @@ namespace IRaCIS.Application.Services
|
|||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
//收件地址
|
//收件地址
|
||||||
messageToSend.To.Add(new MailboxAddress(String.Empty, emailAddress));
|
messageToSend.To.Add(new MailboxAddress(String.Empty, emailAddress));
|
||||||
//主题
|
|
||||||
//---[来自展影IRC] 关于重置密码的提醒
|
|
||||||
messageToSend.Subject = _localizer["Mail_IRCResettingPassword", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN];
|
|
||||||
|
|
||||||
|
|
||||||
|
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
var builder = new BodyBuilder();
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
|
|
||||||
var pathToFile = _hostEnvironment.WebRootPath
|
|
||||||
+ Path.DirectorySeparatorChar.ToString()
|
|
||||||
+ "EmailTemplate"
|
|
||||||
+ Path.DirectorySeparatorChar.ToString()
|
|
||||||
//+ "UserOptCommon.html";
|
|
||||||
+ (_userInfo.IsEn_Us ? "UserOptCommon_US.html" : "UserOptCommon.html");
|
|
||||||
|
|
||||||
using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
|
|
||||||
{
|
{
|
||||||
var templateInfo = SourceReader.ReadToEnd();
|
var topicStr = string.Format(input.topicStr, companyName);
|
||||||
|
|
||||||
|
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
||||||
|
|
||||||
builder.HtmlBody = string.Format(ReplaceCompanyName(templateInfo),
|
"Sir/Madam",
|
||||||
"",
|
|
||||||
//---您正在进行邮箱重置密码操作
|
//---您正在进行邮箱重置密码操作
|
||||||
_localizer["Mail_ResettingPassword"],
|
|
||||||
verificationCode
|
verificationCode
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
return (topicStr, htmlBodyStr);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.UnloginUseEmailResetPassword, messageToSend, emailConfigFunc);
|
||||||
|
|
||||||
messageToSend.Body = builder.ToMessageBody();
|
////此时不知道用户
|
||||||
|
var sucessHandle = GetEmailSuccessHandle(Guid.Empty, verificationCode, emailAddress);
|
||||||
|
|
||||||
EventHandler<MessageSentEventArgs> sucessHandle = (sender, args) =>
|
|
||||||
{
|
|
||||||
var code = verificationCode.ToString();
|
|
||||||
_ = _verificationCodeRepository.AddAsync(new VerificationCode()
|
|
||||||
{
|
|
||||||
CodeType = Core.Domain.Share.VerifyType.Email,
|
|
||||||
HasSend = true,
|
|
||||||
Code = code,
|
|
||||||
UserId = Guid.Empty,//此时不知道用户
|
|
||||||
EmailOrPhone = emailAddress,
|
|
||||||
ExpirationTime = DateTime.Now.AddMinutes(3)
|
|
||||||
}).Result;
|
|
||||||
_ = _verificationCodeRepository.SaveChangesAsync().Result;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, sucessHandle);
|
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, sucessHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 发送验证码
|
/// Reviewer简历录入 发送验证码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="emailAddress"></param>
|
/// <param name="emailAddress"></param>
|
||||||
/// <param name="verificationCode"></param>
|
/// <param name="verificationCode"></param>
|
||||||
@@ -293,61 +296,37 @@ namespace IRaCIS.Application.Services
|
|||||||
public async Task SendEmailVerification(string emailAddress, int verificationCode)
|
public async Task SendEmailVerification(string emailAddress, int verificationCode)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
//发件地址
|
//发件地址
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
//收件地址
|
//收件地址
|
||||||
messageToSend.To.Add(new MailboxAddress(String.Empty, emailAddress));
|
messageToSend.To.Add(new MailboxAddress(String.Empty, emailAddress));
|
||||||
//主题
|
//主题
|
||||||
//---[来自展影IRC]的提醒
|
//---[来自展影IRC]的提醒
|
||||||
messageToSend.Subject = _localizer["Mail_ImagingIRCReminder", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN];
|
|
||||||
|
|
||||||
|
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
|
|
||||||
var builder = new BodyBuilder();
|
|
||||||
|
|
||||||
var pathToFile = _hostEnvironment.WebRootPath
|
|
||||||
+ Path.DirectorySeparatorChar.ToString()
|
|
||||||
+ "EmailTemplate"
|
|
||||||
+ Path.DirectorySeparatorChar.ToString()
|
|
||||||
+ (_userInfo.IsEn_Us ? "UserOptCommon_US.html": "UserOptCommon.html" );
|
|
||||||
|
|
||||||
using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
|
|
||||||
{
|
{
|
||||||
var templateInfo = SourceReader.ReadToEnd();
|
var topicStr = string.Format(input.topicStr, companyName);
|
||||||
|
|
||||||
|
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
||||||
|
|
||||||
builder.HtmlBody = string.Format(ReplaceCompanyName(templateInfo),
|
"Sir/Madam",
|
||||||
"Sir or Madam",
|
|
||||||
//---您正在参与展影医疗IRC项目
|
//---您正在参与展影医疗IRC项目
|
||||||
_localizer["Mail_IRCProject", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN],
|
companyName,
|
||||||
verificationCode
|
verificationCode
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
messageToSend.Body = builder.ToMessageBody();
|
return (topicStr, htmlBodyStr);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EventHandler<MessageSentEventArgs> sucessHandle = (sender, args) =>
|
|
||||||
{
|
|
||||||
// args.Response
|
|
||||||
var code = verificationCode.ToString();
|
|
||||||
_ = _verificationCodeRepository.AddAsync(new VerificationCode()
|
|
||||||
{
|
|
||||||
CodeType = VerifyType.Email,
|
|
||||||
HasSend = true,
|
|
||||||
Code = code,
|
|
||||||
UserId = Guid.Empty,//此时不知道用户
|
|
||||||
EmailOrPhone = emailAddress,
|
|
||||||
ExpirationTime = DateTime.Now.AddMinutes(3)
|
|
||||||
}).Result;
|
|
||||||
_ = _verificationCodeRepository.SaveChangesAsync().Result;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.ReviewerLogin, messageToSend, emailConfigFunc);
|
||||||
|
|
||||||
|
//此时不知道用户
|
||||||
|
var sucessHandle = GetEmailSuccessHandle(Guid.Empty, verificationCode, emailAddress);
|
||||||
|
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, sucessHandle);
|
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, sucessHandle);
|
||||||
|
|
||||||
@@ -359,7 +338,6 @@ namespace IRaCIS.Application.Services
|
|||||||
public async Task AnolymousSendEmail(string researchProgramNo, string emailAddress, int verificationCode)
|
public async Task AnolymousSendEmail(string researchProgramNo, string emailAddress, int verificationCode)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
//发件地址
|
//发件地址
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
@@ -367,67 +345,74 @@ namespace IRaCIS.Application.Services
|
|||||||
messageToSend.To.Add(new MailboxAddress(String.Empty, emailAddress));
|
messageToSend.To.Add(new MailboxAddress(String.Empty, emailAddress));
|
||||||
//主题
|
//主题
|
||||||
//$"[来自展影IRC] [{researchProgramNo}] 关于中心调研的提醒";
|
//$"[来自展影IRC] [{researchProgramNo}] 关于中心调研的提醒";
|
||||||
messageToSend.Subject = _localizer["Mail_ProjectParticipationReminder", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN, researchProgramNo];
|
|
||||||
|
|
||||||
|
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
|
|
||||||
var builder = new BodyBuilder();
|
|
||||||
|
|
||||||
var pathToFile = _hostEnvironment.WebRootPath
|
|
||||||
+ Path.DirectorySeparatorChar.ToString()
|
|
||||||
+ "EmailTemplate"
|
|
||||||
+ Path.DirectorySeparatorChar.ToString()
|
|
||||||
//+ "UserOptCommon.html";
|
|
||||||
+ (_userInfo.IsEn_Us ? "UserOptCommon_US.html" : "UserOptCommon.html");
|
|
||||||
|
|
||||||
using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
|
|
||||||
{
|
{
|
||||||
var templateInfo = SourceReader.ReadToEnd();
|
var topicStr = string.Format(input.topicStr, companyName, researchProgramNo);
|
||||||
|
|
||||||
|
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
||||||
|
|
||||||
builder.HtmlBody = string.Format(ReplaceCompanyName(templateInfo),
|
"Sir/Madam",
|
||||||
"Sir or Madam",
|
|
||||||
//---您正在参与展影医疗IRC项目中心调研工作
|
//---您正在参与展影医疗IRC项目中心调研工作
|
||||||
_localizer["Mail_CenterResearchReminder", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN],
|
companyName,
|
||||||
verificationCode
|
verificationCode
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
messageToSend.Body = builder.ToMessageBody();
|
return (topicStr, htmlBodyStr);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EventHandler<MessageSentEventArgs> sucessHandle = (sender, args) =>
|
|
||||||
{
|
|
||||||
// args.Response
|
|
||||||
var code = verificationCode.ToString();
|
|
||||||
_ = _verificationCodeRepository.AddAsync(new VerificationCode()
|
|
||||||
{
|
|
||||||
CodeType = VerifyType.Email,
|
|
||||||
HasSend = true,
|
|
||||||
Code = code,
|
|
||||||
UserId = Guid.Empty,//此时不知道用户
|
|
||||||
EmailOrPhone = emailAddress,
|
|
||||||
ExpirationTime = DateTime.Now.AddMinutes(3)
|
|
||||||
}).Result;
|
|
||||||
_ = _verificationCodeRepository.SaveChangesAsync().Result;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SiteSurveyLogin, messageToSend, emailConfigFunc);
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig,sucessHandle);
|
//此时不知道用户
|
||||||
|
var sucessHandle = GetEmailSuccessHandle(Guid.Empty, verificationCode, emailAddress);
|
||||||
|
|
||||||
|
|
||||||
|
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, sucessHandle);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SiteSurveyRejectEmail(MimeMessage messageToSend)
|
public async Task SiteSurveyRejectEmail(MimeMessage messageToSend, TrialSiteSurvey trialSiteSurvey, string routeUrl, User? user)
|
||||||
{
|
{
|
||||||
|
|
||||||
//发件地址
|
//发件地址
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
|
|
||||||
|
|
||||||
|
var trialInfo = await _repository.FirstOrDefaultAsync<Trial>(t => t.Id == trialSiteSurvey.TrialId);
|
||||||
|
|
||||||
|
var siteInfo = await _repository.FirstOrDefaultAsync<TrialSite>(t => t.TrialId == trialSiteSurvey.TrialId && t.Id == trialSiteSurvey.TrialSiteId, true);
|
||||||
|
|
||||||
|
|
||||||
|
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
|
|
||||||
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
|
{
|
||||||
|
var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);
|
||||||
|
|
||||||
|
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
||||||
|
|
||||||
|
(user == null ? trialSiteSurvey.UserName : user.LastName + "/ " + user.FirstName),
|
||||||
|
trialInfo.TrialCode,
|
||||||
|
trialInfo.ResearchProgramNo,
|
||||||
|
trialInfo.ExperimentName,
|
||||||
|
siteInfo.TrialSiteCode,
|
||||||
|
siteInfo.TrialSiteAliasName,
|
||||||
|
trialSiteSurvey.LatestBackReason,
|
||||||
|
routeUrl,
|
||||||
|
(trialSiteSurvey.State == TrialSiteSurveyEnum.ToSubmit ? "inline - block" : "none")
|
||||||
|
);
|
||||||
|
|
||||||
|
return (topicStr, htmlBodyStr);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SiteSurveyReject, messageToSend, emailConfigFunc);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||||
|
|
||||||
@@ -446,49 +431,42 @@ namespace IRaCIS.Application.Services
|
|||||||
//收件地址
|
//收件地址
|
||||||
messageToSend.To.Add(new MailboxAddress(sysUserInfo.FullName, sysUserInfo.EMail));
|
messageToSend.To.Add(new MailboxAddress(sysUserInfo.FullName, sysUserInfo.EMail));
|
||||||
//主题
|
//主题
|
||||||
//---[来自展影IRC] 关于创建账户的提醒
|
//---[来自展影IRC] 关于创建账户的提醒
|
||||||
messageToSend.Subject = _localizer["Mail_AccountCreationReminder", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN];
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var builder = new BodyBuilder();
|
|
||||||
|
|
||||||
var pathToFile = _hostEnvironment.WebRootPath
|
|
||||||
+ Path.DirectorySeparatorChar.ToString()
|
|
||||||
+ "EmailTemplate"
|
|
||||||
+ Path.DirectorySeparatorChar.ToString()
|
|
||||||
//+ "AdminAddUser.html";
|
|
||||||
+ (_userInfo.IsEn_Us ? "AdminAddUser_US.html" : "AdminAddUser.html");
|
|
||||||
|
|
||||||
var token = _tokenService.GetToken(IRaCISClaims.Create(_mapper.Map<UserBasicInfo>(sysUserInfo)));
|
var token = _tokenService.GetToken(IRaCISClaims.Create(_mapper.Map<UserBasicInfo>(sysUserInfo)));
|
||||||
|
|
||||||
await _userRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new User() { EmailToken = token });
|
await _userRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new User() { EmailToken = token });
|
||||||
|
|
||||||
routeUrl = routeUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&UserName=" + sysUserInfo.UserName + "&UserType=" + sysUserInfo.UserTypeRole.UserTypeShortName + "&lang=" + (_userInfo.IsEn_Us?"en":"zh") + "&access_token=" + token;
|
routeUrl = routeUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&UserName=" + sysUserInfo.UserName + "&UserType=" + sysUserInfo.UserTypeRole.UserTypeShortName + "&lang=" + (_userInfo.IsEn_Us ? "en" : "zh") + "&access_token=" + token;
|
||||||
|
|
||||||
var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login"));
|
var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login"));
|
||||||
|
|
||||||
var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}";
|
var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}";
|
||||||
|
|
||||||
using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
|
|
||||||
|
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
{
|
{
|
||||||
var templateInfo = SourceReader.ReadToEnd();
|
var topicStr = string.Format(input.topicStr, companyName);
|
||||||
|
|
||||||
|
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
||||||
|
|
||||||
builder.HtmlBody = string.Format(ReplaceCompanyName(templateInfo),
|
sysUserInfo.FullName,
|
||||||
sysUserInfo.FullName,
|
|
||||||
sysUserInfo.UserName,
|
sysUserInfo.UserName,
|
||||||
sysUserInfo.UserTypeRole.UserTypeShortName,
|
sysUserInfo.UserTypeRole.UserTypeShortName,
|
||||||
redirectUrl
|
redirectUrl
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
return (topicStr, htmlBodyStr);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SysCreateUser, messageToSend, emailConfigFunc);
|
||||||
messageToSend.Body = builder.ToMessageBody();
|
|
||||||
|
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend,_systemEmailConfig);
|
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
//管理员重置密码发送邮件
|
//管理员重置密码发送邮件
|
||||||
@@ -502,38 +480,27 @@ namespace IRaCIS.Application.Services
|
|||||||
//收件地址
|
//收件地址
|
||||||
messageToSend.To.Add(new MailboxAddress(sysUserInfo.FullName, sysUserInfo.EMail));
|
messageToSend.To.Add(new MailboxAddress(sysUserInfo.FullName, sysUserInfo.EMail));
|
||||||
//主题
|
//主题
|
||||||
//---[来自展影IRC] 关于重置账户密码的提醒
|
//---[来自展影IRC] 关于重置账户密码的提醒
|
||||||
messageToSend.Subject = _localizer["Mail_AccountPasswordResetReminder", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN];
|
|
||||||
|
|
||||||
|
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
var builder = new BodyBuilder();
|
|
||||||
|
|
||||||
var pathToFile = _hostEnvironment.WebRootPath
|
|
||||||
+ Path.DirectorySeparatorChar.ToString()
|
|
||||||
+ "EmailTemplate"
|
|
||||||
+ Path.DirectorySeparatorChar.ToString()
|
|
||||||
//+ "AdminResetUser.html";
|
|
||||||
+ (_userInfo.IsEn_Us ? "AdminResetUser_US.html" : "AdminResetUser.html");
|
|
||||||
|
|
||||||
|
|
||||||
using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
|
|
||||||
{
|
{
|
||||||
var templateInfo = SourceReader.ReadToEnd();
|
var topicStr = string.Format(input.topicStr, companyName);
|
||||||
|
|
||||||
|
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
||||||
|
|
||||||
builder.HtmlBody = string.Format(ReplaceCompanyName(templateInfo),
|
sysUserInfo.FullName,
|
||||||
sysUserInfo.FullName,
|
|
||||||
sysUserInfo.UserName,
|
sysUserInfo.UserName,
|
||||||
sysUserInfo.UserTypeRole.UserTypeShortName,
|
sysUserInfo.UserTypeRole.UserTypeShortName,
|
||||||
pwdNotMd5
|
pwdNotMd5
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
return (topicStr, htmlBodyStr);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SysResetPassword, messageToSend, emailConfigFunc);
|
||||||
messageToSend.Body = builder.ToMessageBody();
|
|
||||||
|
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||||
}
|
}
|
||||||
@@ -553,11 +520,6 @@ namespace IRaCIS.Application.Services
|
|||||||
messageToSend.To.Add(new MailboxAddress(sysUserInfo.FullName, sysUserInfo.EMail));
|
messageToSend.To.Add(new MailboxAddress(sysUserInfo.FullName, sysUserInfo.EMail));
|
||||||
//主题
|
//主题
|
||||||
// $"[来自展影IRC] [{trialInfo.ResearchProgramNo}]邀请信";
|
// $"[来自展影IRC] [{trialInfo.ResearchProgramNo}]邀请信";
|
||||||
messageToSend.Subject = _localizer["Mail_InvitationEmail", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN, trialInfo.ResearchProgramNo];
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var builder = new BodyBuilder();
|
|
||||||
|
|
||||||
|
|
||||||
var token = _tokenService.GetToken(IRaCISClaims.Create(_mapper.Map<UserBasicInfo>(sysUserInfo)));
|
var token = _tokenService.GetToken(IRaCISClaims.Create(_mapper.Map<UserBasicInfo>(sysUserInfo)));
|
||||||
@@ -567,24 +529,21 @@ namespace IRaCIS.Application.Services
|
|||||||
await _userRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new User() { EmailToken = token });
|
await _userRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new User() { EmailToken = token });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var routeUrl = rootUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&UserName=" + sysUserInfo.UserName + "&UserType=" + sysUserInfo.UserTypeRole.UserTypeShortName + "&lang=" + (_userInfo.IsEn_Us ? "en" : "zh") + "&access_token=" + token;
|
||||||
|
|
||||||
var pathToFile = _hostEnvironment.WebRootPath
|
var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login"));
|
||||||
+ Path.DirectorySeparatorChar.ToString()
|
|
||||||
+ "EmailTemplate"
|
|
||||||
+ Path.DirectorySeparatorChar.ToString()
|
|
||||||
+ (sysUserInfo.IsFirstAdd ? (_userInfo.IsEn_Us ? "TrialUserFirstJoin_US.html" : "TrialUserFirstJoin.html") : (_userInfo.IsEn_Us ? "TrialUserExistJoin_US.html" : "TrialUserExistJoin.html"));
|
|
||||||
|
|
||||||
using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
|
var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}";
|
||||||
|
|
||||||
|
|
||||||
|
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
{
|
{
|
||||||
var templateInfo = SourceReader.ReadToEnd();
|
var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);
|
||||||
|
|
||||||
var routeUrl = rootUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&UserName=" + sysUserInfo.UserName + "&UserType=" + sysUserInfo.UserTypeRole.UserTypeShortName + "&lang=" + (_userInfo.IsEn_Us ? "en" : "zh") + "&access_token=" + token;
|
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
||||||
|
|
||||||
var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login"));
|
|
||||||
|
|
||||||
var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}";
|
|
||||||
|
|
||||||
builder.HtmlBody = string.Format(ReplaceCompanyName(templateInfo),
|
|
||||||
sysUserInfo.FullName,
|
sysUserInfo.FullName,
|
||||||
trialInfo.ExperimentName,
|
trialInfo.ExperimentName,
|
||||||
trialInfo.ResearchProgramNo,
|
trialInfo.ResearchProgramNo,
|
||||||
@@ -593,11 +552,15 @@ namespace IRaCIS.Application.Services
|
|||||||
sysUserInfo.UserTypeRole.UserTypeShortName,
|
sysUserInfo.UserTypeRole.UserTypeShortName,
|
||||||
sysUserInfo.IsFirstAdd ? redirectUrl : baseUrl
|
sysUserInfo.IsFirstAdd ? redirectUrl : baseUrl
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
messageToSend.Body = builder.ToMessageBody();
|
return (topicStr, htmlBodyStr);
|
||||||
|
};
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig,null);
|
|
||||||
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(sysUserInfo.IsFirstAdd ? EmailBusinessScenario.SiteUseOrExternalUserFirstrJoinTrial : EmailBusinessScenario.SiteUserOrExternalUserExistJoinTrial, messageToSend, emailConfigFunc);
|
||||||
|
|
||||||
|
|
||||||
|
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -617,10 +580,6 @@ namespace IRaCIS.Application.Services
|
|||||||
messageToSend.To.Add(new MailboxAddress(String.Empty, sysUserInfo.EMail));
|
messageToSend.To.Add(new MailboxAddress(String.Empty, sysUserInfo.EMail));
|
||||||
//主题
|
//主题
|
||||||
// $"[来自展影IRC] [{trialInfo.ResearchProgramNo}]邀请信";
|
// $"[来自展影IRC] [{trialInfo.ResearchProgramNo}]邀请信";
|
||||||
messageToSend.Subject = _localizer["Mail_InvitationEmail", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN,trialInfo.ResearchProgramNo];
|
|
||||||
|
|
||||||
|
|
||||||
var builder = new BodyBuilder();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -630,23 +589,21 @@ namespace IRaCIS.Application.Services
|
|||||||
await _userRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new User() { EmailToken = token });
|
await _userRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new User() { EmailToken = token });
|
||||||
}
|
}
|
||||||
|
|
||||||
var pathToFile = _hostEnvironment.WebRootPath
|
var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login"));
|
||||||
+ Path.DirectorySeparatorChar.ToString()
|
|
||||||
+ "EmailTemplate"
|
|
||||||
+ Path.DirectorySeparatorChar.ToString()
|
|
||||||
+ (sysUserInfo.IsFirstAdd ? (_userInfo.IsEn_Us ? "TrialUserFirstJoin_US.html" : "TrialUserFirstJoin.html") : (_userInfo.IsEn_Us ? "TrialUserExistJoin_US.html" : "TrialUserExistJoin.html") );
|
|
||||||
|
|
||||||
using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
|
var routeUrl = rootUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&UserName=" + sysUserInfo.UserName + "&UserType=" + sysUserInfo.UserTypeRole.UserTypeShortName + "&lang=" + (_userInfo.IsEn_Us ? "en" : "zh") + "&access_token=" + token;
|
||||||
|
|
||||||
|
var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}";
|
||||||
|
|
||||||
|
|
||||||
|
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
{
|
{
|
||||||
var templateInfo = SourceReader.ReadToEnd();
|
var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);
|
||||||
|
|
||||||
var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login"));
|
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
||||||
|
|
||||||
var routeUrl = rootUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&UserName=" + sysUserInfo.UserName + "&UserType=" + sysUserInfo.UserTypeRole.UserTypeShortName + "&lang=" + (_userInfo.IsEn_Us ? "en" : "zh") + "&access_token=" + token;
|
|
||||||
|
|
||||||
var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}";
|
|
||||||
|
|
||||||
builder.HtmlBody = string.Format(ReplaceCompanyName(templateInfo),
|
|
||||||
sysUserInfo.FullName,
|
sysUserInfo.FullName,
|
||||||
trialInfo.ExperimentName,
|
trialInfo.ExperimentName,
|
||||||
trialInfo.ResearchProgramNo,
|
trialInfo.ResearchProgramNo,
|
||||||
@@ -655,11 +612,12 @@ namespace IRaCIS.Application.Services
|
|||||||
sysUserInfo.UserTypeRole.UserTypeShortName,
|
sysUserInfo.UserTypeRole.UserTypeShortName,
|
||||||
sysUserInfo.IsFirstAdd ? redirectUrl : baseUrl
|
sysUserInfo.IsFirstAdd ? redirectUrl : baseUrl
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
return (topicStr, htmlBodyStr);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(sysUserInfo.IsFirstAdd ? EmailBusinessScenario.SiteUseOrExternalUserFirstrJoinTrial : EmailBusinessScenario.SiteUserOrExternalUserExistJoinTrial, messageToSend, emailConfigFunc);
|
||||||
messageToSend.Body = builder.ToMessageBody();
|
|
||||||
|
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, null);
|
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, null);
|
||||||
@@ -730,13 +688,8 @@ namespace IRaCIS.Application.Services
|
|||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
//收件地址
|
//收件地址
|
||||||
messageToSend.To.Add(new MailboxAddress(doctor.FullName, doctor.EMail));
|
messageToSend.To.Add(new MailboxAddress(doctor.FullName, doctor.EMail));
|
||||||
//主题
|
|
||||||
// $"[来自展影IRC] [{trialInfo.ResearchProgramNo}]邀请信";
|
|
||||||
messageToSend.Subject = _localizer["Mail_InvitationEmail", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN, trialInfo.ResearchProgramNo];
|
|
||||||
|
|
||||||
|
|
||||||
var builder = new BodyBuilder();
|
|
||||||
|
|
||||||
|
|
||||||
var basicInfo = IRaCISClaims.Create(_mapper.Map<UserBasicInfo>(sysUserInfo));
|
var basicInfo = IRaCISClaims.Create(_mapper.Map<UserBasicInfo>(sysUserInfo));
|
||||||
|
|
||||||
@@ -751,25 +704,25 @@ namespace IRaCIS.Application.Services
|
|||||||
await _userRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new User() { EmailToken = token });
|
await _userRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new User() { EmailToken = token });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var routeUrl = rootUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&UserName=" + sysUserInfo.UserName + "&UserType=" + userType.UserTypeShortName + "&lang=" + (_userInfo.IsEn_Us ? "en" : "zh") + "&access_token=" + token;
|
||||||
|
|
||||||
var pathToFile = _hostEnvironment.WebRootPath
|
var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login"));
|
||||||
+ Path.DirectorySeparatorChar.ToString()
|
|
||||||
+ "EmailTemplate"
|
|
||||||
+ Path.DirectorySeparatorChar.ToString()
|
|
||||||
+ (sysUserInfo.IsFirstAdd ? (_userInfo.IsEn_Us ? "TrialDoctorFirstJoin_US.html" : "TrialDoctorFirstJoin.html") : (_userInfo.IsEn_Us ? "TrialDoctorExistJoin_US.html" : "TrialDoctorExistJoin.html") );
|
|
||||||
|
|
||||||
using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
|
var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}";
|
||||||
|
|
||||||
|
//主题
|
||||||
|
// $"[来自展影IRC] [{trialInfo.ResearchProgramNo}]邀请信";
|
||||||
|
|
||||||
|
|
||||||
|
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
{
|
{
|
||||||
var templateInfo = SourceReader.ReadToEnd();
|
var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);
|
||||||
|
|
||||||
var routeUrl = rootUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&UserName=" + sysUserInfo.UserName + "&UserType=" + userType.UserTypeShortName + "&lang=" + (_userInfo.IsEn_Us ? "en" : "zh") + "&access_token=" + token;
|
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
||||||
|
|
||||||
var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login"));
|
sysUserInfo.FullName,
|
||||||
|
|
||||||
var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}";
|
|
||||||
|
|
||||||
builder.HtmlBody = string.Format(ReplaceCompanyName(templateInfo),
|
|
||||||
sysUserInfo.FullName,
|
|
||||||
trialInfo.ExperimentName,
|
trialInfo.ExperimentName,
|
||||||
trialInfo.ResearchProgramNo,
|
trialInfo.ResearchProgramNo,
|
||||||
trialInfo.TrialCode,
|
trialInfo.TrialCode,
|
||||||
@@ -777,9 +730,13 @@ namespace IRaCIS.Application.Services
|
|||||||
userType.UserTypeShortName,
|
userType.UserTypeShortName,
|
||||||
sysUserInfo.IsFirstAdd ? redirectUrl : baseUrl
|
sysUserInfo.IsFirstAdd ? redirectUrl : baseUrl
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
messageToSend.Body = builder.ToMessageBody();
|
return (topicStr, htmlBodyStr);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(sysUserInfo.IsFirstAdd ? EmailBusinessScenario.DoctorUserFirstJoinTrial : EmailBusinessScenario.DoctorUserExistJoinTrial, messageToSend, emailConfigFunc);
|
||||||
|
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, null);
|
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, null);
|
||||||
|
|
||||||
@@ -787,6 +744,124 @@ namespace IRaCIS.Application.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//用户反馈邮件
|
||||||
|
|
||||||
|
public async Task UserFeedBackMail(Guid feedBackId)
|
||||||
|
{
|
||||||
|
var feedBack = await _repository.Where<UserFeedBack>(t => t.Id == feedBackId).Include(t => t.CreateUser).ThenInclude(t => t.UserTypeRole).FirstNotNullAsync();
|
||||||
|
|
||||||
|
var messageToSend = new MimeMessage();
|
||||||
|
//发件地址
|
||||||
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
|
|
||||||
|
var isHaveTrialId = feedBack.TrialId != null;
|
||||||
|
|
||||||
|
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
|
var emailConfigInfo = await GetEmailConfigInfoAsync(feedBack.VisitTaskId != null? EmailBusinessScenario.IRImageError:(feedBack.TrialId != null? EmailBusinessScenario.TrialFeedBack: EmailBusinessScenario.SysFeedBack));
|
||||||
|
|
||||||
|
var userTypeEnumList = emailConfigInfo.EmailNoticeUserTypeList.Where(t => t.EmailUserType == EmailUserType.To).Select(t => t.UserType).ToList();
|
||||||
|
|
||||||
|
var emailList = await _repository.Where<User>(t => userTypeEnumList.Contains(t.UserTypeEnum) &&
|
||||||
|
(isHaveTrialId ? t.UserTrials.Any(t => t.TrialId == feedBack.TrialId) : true)).Select(t => new { t.EMail, t.UserTypeEnum, t.FullName }).ToListAsync();
|
||||||
|
|
||||||
|
|
||||||
|
foreach (var email in emailList)
|
||||||
|
{
|
||||||
|
messageToSend.To.Add(new MailboxAddress(email.FullName, email.EMail));
|
||||||
|
}
|
||||||
|
|
||||||
|
//影像阅片反馈 pm
|
||||||
|
if (feedBack.VisitTaskId != null)
|
||||||
|
{
|
||||||
|
var userNames = string.Join(',', emailList.Where(email => email.UserTypeEnum == UserTypeEnum.ProjectManager).Select(t => t.FullName));
|
||||||
|
|
||||||
|
var emailType = await _repository.Where<Dictionary>(t => t.Parent.Code == "Email_BusinessScenario" && t.ParentId != null && t.Code == ((int)EmailBusinessScenario.IRImageError).ToString()).Select(t => _userInfo.IsEn_Us ? t.Value : t.ValueCN).FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
|
||||||
|
var info = await _repository.Where<VisitTask>(t => t.Id == feedBack.VisitTaskId).Select(t => new { t.Trial.ResearchProgramNo, t.Trial.TrialCode, SubejctCode = t.Subject.Code, t.SourceSubjectVisit.VisitName }).FirstNotNullAsync();
|
||||||
|
|
||||||
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
|
{
|
||||||
|
var topicStr = string.Format(input.topicStr, info.SubejctCode, info.VisitName, info.ResearchProgramNo);
|
||||||
|
|
||||||
|
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
||||||
|
userNames,
|
||||||
|
info.TrialCode,
|
||||||
|
info.SubejctCode,
|
||||||
|
info.VisitName,
|
||||||
|
feedBack.CreateUser.UserTypeRole.UserTypeShortName,
|
||||||
|
feedBack.CreateUser.FullName,
|
||||||
|
emailType,
|
||||||
|
feedBack.QuestionDescription,
|
||||||
|
_systemEmailConfig.SiteUrl
|
||||||
|
);
|
||||||
|
|
||||||
|
return (topicStr, htmlBodyStr);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.IRImageError, messageToSend, emailConfigFunc);
|
||||||
|
|
||||||
|
}
|
||||||
|
//项目相关的反馈 pm admin
|
||||||
|
else if (feedBack.TrialId != null)
|
||||||
|
{
|
||||||
|
var userNames = string.Join(',', emailList.Where(email => email.UserTypeEnum == UserTypeEnum.ProjectManager || email.UserTypeEnum == UserTypeEnum.Admin).Select(t => t.FullName));
|
||||||
|
|
||||||
|
var emailType = await _repository.Where<Dictionary>(t => t.Parent.Code == "Email_BusinessScenario" && t.ParentId != null && t.Code == ((int)EmailBusinessScenario.TrialFeedBack).ToString()).Select(t => _userInfo.IsEn_Us ? t.Value : t.ValueCN).FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
|
||||||
|
var info = await _repository.Where<Trial>(t => t.Id == feedBack.TrialId).Select(t => new { t.ResearchProgramNo, t.TrialCode }).FirstNotNullAsync();
|
||||||
|
|
||||||
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
|
{
|
||||||
|
var topicStr = string.Format(input.topicStr, info.ResearchProgramNo);
|
||||||
|
|
||||||
|
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
||||||
|
userNames,
|
||||||
|
info.TrialCode,
|
||||||
|
feedBack.CreateUser.UserTypeRole.UserTypeShortName,
|
||||||
|
feedBack.CreateUser.FullName,
|
||||||
|
emailType,
|
||||||
|
feedBack.QuestionDescription,
|
||||||
|
_systemEmailConfig.SiteUrl
|
||||||
|
);
|
||||||
|
|
||||||
|
return (topicStr, htmlBodyStr);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.TrialFeedBack, messageToSend, emailConfigFunc);
|
||||||
|
|
||||||
|
}
|
||||||
|
//项目无关的反馈 admin zyss
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
var userNames = string.Join(',', emailList.Where(email => email.UserTypeEnum == UserTypeEnum.ZYSS || email.UserTypeEnum == UserTypeEnum.Admin).Select(t => t.FullName));
|
||||||
|
|
||||||
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
|
{
|
||||||
|
var topicStr = string.Format(input.topicStr);
|
||||||
|
|
||||||
|
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
||||||
|
userNames,
|
||||||
|
feedBack.CreateUser.UserTypeRole.UserTypeShortName,
|
||||||
|
feedBack.CreateUser.FullName,
|
||||||
|
feedBack.QuestionDescription,
|
||||||
|
_systemEmailConfig.SiteUrl
|
||||||
|
);
|
||||||
|
|
||||||
|
return (topicStr, htmlBodyStr);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SysFeedBack, messageToSend, emailConfigFunc);
|
||||||
|
}
|
||||||
|
|
||||||
|
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Mvc;
|
|||||||
using IRaCIS.Core.Application.Interfaces;
|
using IRaCIS.Core.Application.Interfaces;
|
||||||
using IRaCIS.Core.Application.ViewModel;
|
using IRaCIS.Core.Application.ViewModel;
|
||||||
using IRaCIS.Application.Contracts;
|
using IRaCIS.Application.Contracts;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Service
|
namespace IRaCIS.Core.Application.Service
|
||||||
{
|
{
|
||||||
@@ -31,8 +32,9 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
{
|
{
|
||||||
|
|
||||||
var publishLogQueryable = _publishLogRepository
|
var publishLogQueryable = _publishLogRepository
|
||||||
.WhereIf(!string.IsNullOrEmpty(inQuery.Version) , t => t.Version.Contains(inQuery.Version))
|
.WhereIf(!string.IsNullOrEmpty(inQuery.Version), t => t.Version.Contains(inQuery.Version))
|
||||||
.WhereIf(!string.IsNullOrEmpty(inQuery.UpdateContent), t => t.UpdateContent.Contains(inQuery.UpdateContent))
|
.WhereIf(!string.IsNullOrEmpty(inQuery.UpdateContent), t => t.UpdateContent.Contains(inQuery.UpdateContent))
|
||||||
|
.WhereIf(inQuery.State != null, t => t.State == inQuery.State)
|
||||||
.ProjectTo<PublishLogView>(_mapper.ConfigurationProvider);
|
.ProjectTo<PublishLogView>(_mapper.ConfigurationProvider);
|
||||||
|
|
||||||
var pageList = await publishLogQueryable
|
var pageList = await publishLogQueryable
|
||||||
@@ -48,19 +50,29 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
if (!Version.TryParse(addOrEditPublishLog.Version, out version))
|
if (!Version.TryParse(addOrEditPublishLog.Version, out version))
|
||||||
{
|
{
|
||||||
return ResponseOutput.NotOk("版本号不符合要求");
|
//"版本号不符合要求"
|
||||||
|
return ResponseOutput.NotOk(_localizer["PublishLog_NotValidVersion"] );
|
||||||
}
|
}
|
||||||
|
|
||||||
var verifyExp1 = new EntityVerifyExp<PublishLog>()
|
var verifyExp1 = new EntityVerifyExp<PublishLog>()
|
||||||
{
|
{
|
||||||
VerifyExp = u => u.Version == addOrEditPublishLog.Version ,
|
VerifyExp = u => u.Version == addOrEditPublishLog.Version,
|
||||||
|
|
||||||
VerifyMsg = "发布编号不能重复"
|
//"发布编号不能重复"
|
||||||
|
VerifyMsg = _localizer["PublishLog_RepeatVersion"]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var verifyExp2 = new EntityVerifyExp<PublishLog>()
|
||||||
|
{
|
||||||
|
VerifyExp = u => u.IsCurrentVersion == addOrEditPublishLog.IsCurrentVersion,
|
||||||
|
|
||||||
|
//"当前发布版本只允许有一个"
|
||||||
|
VerifyMsg = _localizer["PublishLog_OnlyOneCurrentVersion"] ,
|
||||||
|
|
||||||
var entity = await _publishLogRepository.InsertOrUpdateAsync(addOrEditPublishLog, true, verifyExp1);
|
IsVerify=addOrEditPublishLog.IsCurrentVersion==true
|
||||||
|
};
|
||||||
|
|
||||||
|
var entity = await _publishLogRepository.InsertOrUpdateAsync(addOrEditPublishLog, true, verifyExp1, verifyExp2);
|
||||||
|
|
||||||
return ResponseOutput.Ok(entity.Id.ToString());
|
return ResponseOutput.Ok(entity.Id.ToString());
|
||||||
|
|
||||||
@@ -74,6 +86,25 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
return ResponseOutput.Ok();
|
return ResponseOutput.Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[AllowAnonymous]
|
||||||
|
public async Task<PublishLogView> GetCurrentPublishInfo()
|
||||||
|
{
|
||||||
|
var result = await _publishLogRepository.Where(t => t.IsCurrentVersion == true).ProjectTo<PublishLogView>(_mapper.ConfigurationProvider).FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
//"系统当前版本未标记,请联系维护人员"
|
||||||
|
throw new QueryBusinessObjectNotExistException(_localizer["PublishLog_NoCurrentVersion"] );
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<List<PublishVersionSelect>> GetPublishVersionSelect()
|
||||||
|
{
|
||||||
|
return await _publishLogRepository.ProjectTo<PublishVersionSelect>(_mapper.ConfigurationProvider).OrderByDescending(t => t.Version).ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,8 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
CreateMap<CommonDocument, CommonDocumentAddOrEdit>().ReverseMap();
|
CreateMap<CommonDocument, CommonDocumentAddOrEdit>().ReverseMap();
|
||||||
|
|
||||||
CreateMap<Internationalization, InternationalizationView>();
|
CreateMap<Internationalization, InternationalizationView>()
|
||||||
|
.ForMember(o => o.Version, t => t.MapFrom(u => u.PublishLog.Version));
|
||||||
CreateMap<Internationalization, InternationalizationAddOrEdit>().ReverseMap();
|
CreateMap<Internationalization, InternationalizationAddOrEdit>().ReverseMap();
|
||||||
|
|
||||||
CreateMap<Internationalization, BatchInternationalizationDto>().ReverseMap();
|
CreateMap<Internationalization, BatchInternationalizationDto>().ReverseMap();
|
||||||
@@ -78,6 +79,10 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
CreateMap<PublishLog, PublishLogView>();
|
CreateMap<PublishLog, PublishLogView>();
|
||||||
CreateMap<PublishLog, PublishLogAddOrEdit>().ReverseMap();
|
CreateMap<PublishLog, PublishLogAddOrEdit>().ReverseMap();
|
||||||
|
|
||||||
|
CreateMap<PublishLog, PublishVersionSelect>();
|
||||||
|
|
||||||
|
CreateMap<ExploreRecommend, ExploreRecommendView>();
|
||||||
|
CreateMap<ExploreRecommend, ExploreRecommendAddOrEdit>().ReverseMap();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -536,10 +536,13 @@ namespace IRaCIS.Application.Services
|
|||||||
[HttpGet("{doctorId:guid}")]
|
[HttpGet("{doctorId:guid}")]
|
||||||
public async Task<ResumeConfirmDTO> GetAuditState(Guid doctorId)
|
public async Task<ResumeConfirmDTO> GetAuditState(Guid doctorId)
|
||||||
{
|
{
|
||||||
|
//防止生成sql生成GETDATE() 时区导致的问题
|
||||||
|
var appDateTimeNow = DateTime.Now;
|
||||||
|
|
||||||
var doctor = (await _doctorRepository
|
var doctor = (await _doctorRepository
|
||||||
.ProjectTo<ResumeConfirmDTO>(_mapper.ConfigurationProvider).FirstOrDefaultAsync(t => t.Id == doctorId)).IfNullThrowException();
|
.ProjectTo<ResumeConfirmDTO>(_mapper.ConfigurationProvider).FirstOrDefaultAsync(t => t.Id == doctorId)).IfNullThrowException();
|
||||||
|
|
||||||
doctor.InHoliday = (await _repository.CountAsync<Vacation>(x => x.DoctorId == doctorId && x.EndDate <= DateTime.Now && x.StartDate <= DateTime.Now)) > 0;
|
doctor.InHoliday = (await _repository.CountAsync<Vacation>(x => x.DoctorId == doctorId && x.EndDate <= appDateTimeNow && x.StartDate <= appDateTimeNow)) > 0;
|
||||||
|
|
||||||
return doctor;
|
return doctor;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,10 @@ namespace IRaCIS.Application.Services
|
|||||||
[NonDynamicMethod]
|
[NonDynamicMethod]
|
||||||
public async Task<IResponseOutput> OnVacation(Guid doctorId)
|
public async Task<IResponseOutput> OnVacation(Guid doctorId)
|
||||||
{
|
{
|
||||||
var count = await _vacationRepository.CountAsync(u => u.DoctorId == doctorId && u.EndDate >= DateTime.Now && u.StartDate <= DateTime.Now);
|
//防止生成sql生成GETDATE() 时区导致的问题
|
||||||
|
var appDateTimeNow = DateTime.Now;
|
||||||
|
|
||||||
|
var count = await _vacationRepository.CountAsync(u => u.DoctorId == doctorId && u.EndDate >= appDateTimeNow && u.StartDate <= appDateTimeNow);
|
||||||
|
|
||||||
return ResponseOutput.Result(count > 0);
|
return ResponseOutput.Result(count > 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace IRaCIS.Core.Application.Contracts
|
|||||||
Task<List<TrialUserDto>> GetTrialUserSelect(Guid trialId);
|
Task<List<TrialUserDto>> GetTrialUserSelect(Guid trialId);
|
||||||
|
|
||||||
|
|
||||||
PageOutput<DocumentUnionWithUserStatView> GetTrialSystemDocumentList(DocumentTrialUnionQuery querySystemDocument);
|
Task<PageOutput<DocumentUnionWithUserStatView>> GetTrialSystemDocumentList(DocumentTrialUnionQuery querySystemDocument);
|
||||||
List<TrialUserUnionDocumentView> GetTrialUserDocumentList(Guid trialId);
|
List<TrialUserUnionDocumentView> GetTrialUserDocumentList(Guid trialId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -26,8 +26,8 @@ namespace IRaCIS.Core.Application.Services
|
|||||||
private readonly IRepository<TrialDocument> _trialDocumentRepository;
|
private readonly IRepository<TrialDocument> _trialDocumentRepository;
|
||||||
private readonly IRepository<TrialDocConfirmedUser> _trialDocUserTypeConfirmedUserRepository;
|
private readonly IRepository<TrialDocConfirmedUser> _trialDocUserTypeConfirmedUserRepository;
|
||||||
private readonly IRepository<Trial> _trialRepository;
|
private readonly IRepository<Trial> _trialRepository;
|
||||||
private readonly ISystemDocumentService _systemDocumentService;
|
private readonly ISystemDocumentService _systemDocumentService;
|
||||||
private readonly IRepository<SystemDocConfirmedUser> _systemDocConfirmedUserRepository;
|
private readonly IRepository<SystemDocConfirmedUser> _systemDocConfirmedUserRepository;
|
||||||
private readonly IRepository<SystemDocument> _systemDocumentRepository;
|
private readonly IRepository<SystemDocument> _systemDocumentRepository;
|
||||||
private readonly IRepository<TrialCriterionAdditionalAssessmentType> _trialCriterionAdditionalAssessmentTypeRepository;
|
private readonly IRepository<TrialCriterionAdditionalAssessmentType> _trialCriterionAdditionalAssessmentTypeRepository;
|
||||||
private readonly IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository;
|
private readonly IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository;
|
||||||
@@ -36,8 +36,8 @@ namespace IRaCIS.Core.Application.Services
|
|||||||
public TrialDocumentService(IRepository<TrialDocument> trialDocumentRepository,
|
public TrialDocumentService(IRepository<TrialDocument> trialDocumentRepository,
|
||||||
IRepository<TrialDocConfirmedUser> trialDocUserTypeConfirmedUserRepository,
|
IRepository<TrialDocConfirmedUser> trialDocUserTypeConfirmedUserRepository,
|
||||||
IRepository<Trial> trialRepository,
|
IRepository<Trial> trialRepository,
|
||||||
ISystemDocumentService systemDocumentService,
|
ISystemDocumentService systemDocumentService,
|
||||||
IRepository<SystemDocConfirmedUser> systemDocConfirmedUserRepository,
|
IRepository<SystemDocConfirmedUser> systemDocConfirmedUserRepository,
|
||||||
IRepository<TrialCriterionAdditionalAssessmentType> trialCriterionAdditionalAssessmentTypeRepository,
|
IRepository<TrialCriterionAdditionalAssessmentType> trialCriterionAdditionalAssessmentTypeRepository,
|
||||||
IRepository<ReadingQuestionCriterionTrial> readingQuestionCriterionTrialRepository
|
IRepository<ReadingQuestionCriterionTrial> readingQuestionCriterionTrialRepository
|
||||||
, IRepository<SystemDocument> systemDocumentRepository)
|
, IRepository<SystemDocument> systemDocumentRepository)
|
||||||
@@ -45,8 +45,8 @@ namespace IRaCIS.Core.Application.Services
|
|||||||
_trialDocumentRepository = trialDocumentRepository;
|
_trialDocumentRepository = trialDocumentRepository;
|
||||||
this._trialDocUserTypeConfirmedUserRepository = trialDocUserTypeConfirmedUserRepository;
|
this._trialDocUserTypeConfirmedUserRepository = trialDocUserTypeConfirmedUserRepository;
|
||||||
this._trialRepository = trialRepository;
|
this._trialRepository = trialRepository;
|
||||||
this._systemDocumentService = systemDocumentService;
|
this._systemDocumentService = systemDocumentService;
|
||||||
this._systemDocConfirmedUserRepository = systemDocConfirmedUserRepository;
|
this._systemDocConfirmedUserRepository = systemDocConfirmedUserRepository;
|
||||||
_systemDocumentRepository = systemDocumentRepository;
|
_systemDocumentRepository = systemDocumentRepository;
|
||||||
_readingQuestionCriterionTrialRepository = readingQuestionCriterionTrialRepository;
|
_readingQuestionCriterionTrialRepository = readingQuestionCriterionTrialRepository;
|
||||||
_trialCriterionAdditionalAssessmentTypeRepository = trialCriterionAdditionalAssessmentTypeRepository;
|
_trialCriterionAdditionalAssessmentTypeRepository = trialCriterionAdditionalAssessmentTypeRepository;
|
||||||
@@ -64,7 +64,7 @@ namespace IRaCIS.Core.Application.Services
|
|||||||
var trialDocumentQueryable = _trialDocumentRepository.AsQueryable(true).Where(t => t.TrialId == queryTrialDocument.TrialId)
|
var trialDocumentQueryable = _trialDocumentRepository.AsQueryable(true).Where(t => t.TrialId == queryTrialDocument.TrialId)
|
||||||
.WhereIf(!string.IsNullOrEmpty(queryTrialDocument.Name), t => t.Name.Contains(queryTrialDocument.Name))
|
.WhereIf(!string.IsNullOrEmpty(queryTrialDocument.Name), t => t.Name.Contains(queryTrialDocument.Name))
|
||||||
.WhereIf(queryTrialDocument.FileTypeId != null, t => t.FileTypeId == queryTrialDocument.FileTypeId)
|
.WhereIf(queryTrialDocument.FileTypeId != null, t => t.FileTypeId == queryTrialDocument.FileTypeId)
|
||||||
.WhereIf(queryTrialDocument.UserTypeId != null, t => t.NeedConfirmedUserTypeList.Any(t=>t.NeedConfirmUserTypeId== queryTrialDocument.UserTypeId) )
|
.WhereIf(queryTrialDocument.UserTypeId != null, t => t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == queryTrialDocument.UserTypeId))
|
||||||
.WhereIf(queryTrialDocument.IsDeleted != null, t => t.IsDeleted == queryTrialDocument.IsDeleted)
|
.WhereIf(queryTrialDocument.IsDeleted != null, t => t.IsDeleted == queryTrialDocument.IsDeleted)
|
||||||
.ProjectTo<TrialDocumentView>(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken, isEn_Us = _userInfo.IsEn_Us });
|
.ProjectTo<TrialDocumentView>(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken, isEn_Us = _userInfo.IsEn_Us });
|
||||||
|
|
||||||
@@ -75,17 +75,17 @@ namespace IRaCIS.Core.Application.Services
|
|||||||
public async Task<PageOutput<TrialSignDocView>> GetTrialSignDocumentList(TrialDocQuery querySystemDocument)
|
public async Task<PageOutput<TrialSignDocView>> GetTrialSignDocumentList(TrialDocQuery querySystemDocument)
|
||||||
{
|
{
|
||||||
var trialDocQueryable = from trialDoc in _trialDocumentRepository.AsQueryable(true)
|
var trialDocQueryable = from trialDoc in _trialDocumentRepository.AsQueryable(true)
|
||||||
.WhereIf(querySystemDocument.TrialId!=null,t=>t.TrialId==querySystemDocument.TrialId)
|
.WhereIf(querySystemDocument.TrialId != null, t => t.TrialId == querySystemDocument.TrialId)
|
||||||
.Where(t => t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == _userInfo.UserTypeId) )
|
.Where(t => t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == _userInfo.UserTypeId))
|
||||||
|
|
||||||
join trialUser in _repository.Where<TrialUser>(t=>t.UserId==_userInfo.Id) on trialDoc.TrialId equals trialUser.TrialId
|
join trialUser in _repository.Where<TrialUser>(t => t.UserId == _userInfo.Id) on trialDoc.TrialId equals trialUser.TrialId
|
||||||
join confirm in _repository.Where<TrialDocConfirmedUser>() on
|
join confirm in _repository.Where<TrialDocConfirmedUser>() on
|
||||||
new { trialUser.UserId, TrialDocumentId = trialDoc.Id } equals new { UserId = confirm.ConfirmUserId, confirm.TrialDocumentId } into cc
|
new { trialUser.UserId, TrialDocumentId = trialDoc.Id } equals new { UserId = confirm.ConfirmUserId, confirm.TrialDocumentId } into cc
|
||||||
|
|
||||||
from confirm in cc.DefaultIfEmpty()
|
from confirm in cc.DefaultIfEmpty()
|
||||||
select new TrialSignDocView()
|
select new TrialSignDocView()
|
||||||
{
|
{
|
||||||
TrialCode=trialDoc.Trial.TrialCode,
|
TrialCode = trialDoc.Trial.TrialCode,
|
||||||
ResearchProgramNo = trialDoc.Trial.ResearchProgramNo,
|
ResearchProgramNo = trialDoc.Trial.ResearchProgramNo,
|
||||||
ExperimentName = trialDoc.Trial.ExperimentName,
|
ExperimentName = trialDoc.Trial.ExperimentName,
|
||||||
Id = trialDoc.Id,
|
Id = trialDoc.Id,
|
||||||
@@ -116,7 +116,7 @@ namespace IRaCIS.Core.Application.Services
|
|||||||
.WhereIf(querySystemDocument.IsSigned == false, t => t.ConfirmTime == null);
|
.WhereIf(querySystemDocument.IsSigned == false, t => t.ConfirmTime == null);
|
||||||
|
|
||||||
|
|
||||||
return await trialDocQueryable.ToPagedListAsync(querySystemDocument.PageIndex, querySystemDocument.PageSize, querySystemDocument.SortField, querySystemDocument.Asc);
|
return await trialDocQueryable.ToPagedListAsync(querySystemDocument.PageIndex, querySystemDocument.PageSize, querySystemDocument.SortField, querySystemDocument.Asc);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,19 +142,19 @@ namespace IRaCIS.Core.Application.Services
|
|||||||
PageSize = 1,
|
PageSize = 1,
|
||||||
})).Data;
|
})).Data;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = await _systemDocumentService.getWaitSignSysDocList(new SystemDocumentQuery()
|
result = await _systemDocumentService.getWaitSignSysDocList(new SystemDocumentQuery()
|
||||||
{
|
{
|
||||||
PageIndex=1,
|
PageIndex = 1,
|
||||||
IsSigned = false,
|
IsSigned = false,
|
||||||
PageSize=1,
|
PageSize = 1,
|
||||||
Asc=false,
|
Asc = false,
|
||||||
SortField="UpdateTime",
|
SortField = "UpdateTime",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (result.CurrentPageData.Count > 0)
|
if (result.CurrentPageData.Count > 0)
|
||||||
{
|
{
|
||||||
@@ -369,10 +369,10 @@ namespace IRaCIS.Core.Application.Services
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取确认列表情况 项目文档+系统文档+具体的人
|
/// 获取确认列表情况 项目文档+系统文档+具体的人
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="querySystemDocument"></param>
|
/// <param name="inQuery"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<(PageOutput<UnionDocumentWithConfirmInfoView>, object)> GetDocumentConfirmList(DocumentTrialUnionQuery querySystemDocument)
|
public async Task<(PageOutput<UnionDocumentWithConfirmInfoView>, object)> GetDocumentConfirmList(DocumentTrialUnionQuery inQuery)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
@@ -409,15 +409,15 @@ namespace IRaCIS.Core.Application.Services
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
var trialInfo = (await _repository.Where<Trial>(t => t.Id == querySystemDocument.TrialId).Select(t => new { t.TrialFinishedTime, t.TrialStatusStr }).FirstNotNullAsync());
|
var trialInfo = (await _repository.Where<Trial>(t => t.Id == inQuery.TrialId).Select(t => new { t.TrialFinishedTime, t.TrialStatusStr }).FirstNotNullAsync());
|
||||||
|
|
||||||
var trialDocQuery = from trialDocumentNeedConfirmedUserType in _repository.Where<TrialDocNeedConfirmedUserType>(t => t.TrialDocument.TrialId == querySystemDocument.TrialId)
|
var trialDocQuery = from trialDocumentNeedConfirmedUserType in _repository.Where<TrialDocNeedConfirmedUserType>(t => t.TrialDocument.TrialId == inQuery.TrialId)
|
||||||
join trialUser in _repository.Where<TrialUser>(t => t.TrialId == querySystemDocument.TrialId)
|
join trialUser in _repository.Where<TrialUser>(t => t.TrialId == inQuery.TrialId)
|
||||||
.WhereIf(querySystemDocument.UserId != null, t => t.UserId == querySystemDocument.UserId)
|
.WhereIf(inQuery.UserId != null, t => t.UserId == inQuery.UserId)
|
||||||
.WhereIf(querySystemDocument.UserTypeId != null, t => t.User.UserTypeId == querySystemDocument.UserTypeId)
|
.WhereIf(inQuery.UserTypeId != null, t => t.User.UserTypeId == inQuery.UserTypeId)
|
||||||
on trialDocumentNeedConfirmedUserType.NeedConfirmUserTypeId equals trialUser.User.UserTypeId
|
on trialDocumentNeedConfirmedUserType.NeedConfirmUserTypeId equals trialUser.User.UserTypeId
|
||||||
|
|
||||||
join confirm in _repository.Where<TrialDocConfirmedUser>(t => t.TrialDocument.TrialId == querySystemDocument.TrialId) on
|
join confirm in _repository.Where<TrialDocConfirmedUser>(t => t.TrialDocument.TrialId == inQuery.TrialId) on
|
||||||
new { trialUser.UserId, TrialDocumentId = trialDocumentNeedConfirmedUserType.TrialDocumentId } equals new { UserId = confirm.ConfirmUserId, confirm.TrialDocumentId } into cc
|
new { trialUser.UserId, TrialDocumentId = trialDocumentNeedConfirmedUserType.TrialDocumentId } equals new { UserId = confirm.ConfirmUserId, confirm.TrialDocumentId } into cc
|
||||||
from confirm in cc.DefaultIfEmpty()
|
from confirm in cc.DefaultIfEmpty()
|
||||||
select new UnionDocumentWithConfirmInfoView()
|
select new UnionDocumentWithConfirmInfoView()
|
||||||
@@ -451,8 +451,8 @@ namespace IRaCIS.Core.Application.Services
|
|||||||
|
|
||||||
var systemDocQuery = from needConfirmEdUserType in _repository.WhereIf<SystemDocNeedConfirmedUserType>(trialInfo.TrialFinishedTime != null, u => u.SystemDocument.CreateTime < trialInfo.TrialFinishedTime)
|
var systemDocQuery = from needConfirmEdUserType in _repository.WhereIf<SystemDocNeedConfirmedUserType>(trialInfo.TrialFinishedTime != null, u => u.SystemDocument.CreateTime < trialInfo.TrialFinishedTime)
|
||||||
|
|
||||||
join trialUser in _repository.Where<TrialUser>(t => t.TrialId == querySystemDocument.TrialId)
|
join trialUser in _repository.Where<TrialUser>(t => t.TrialId == inQuery.TrialId)
|
||||||
.WhereIf(querySystemDocument.UserId != null, t => t.UserId == querySystemDocument.UserId)
|
.WhereIf(inQuery.UserId != null, t => t.UserId == inQuery.UserId)
|
||||||
on needConfirmEdUserType.NeedConfirmUserTypeId equals trialUser.User.UserTypeId
|
on needConfirmEdUserType.NeedConfirmUserTypeId equals trialUser.User.UserTypeId
|
||||||
join confirm in _repository.GetQueryable<SystemDocConfirmedUser>() on new { ConfirmUserId = trialUser.UserId, SystemDocumentId = needConfirmEdUserType.SystemDocumentId } equals new { confirm.ConfirmUserId, confirm.SystemDocumentId } into cc
|
join confirm in _repository.GetQueryable<SystemDocConfirmedUser>() on new { ConfirmUserId = trialUser.UserId, SystemDocumentId = needConfirmEdUserType.SystemDocumentId } equals new { confirm.ConfirmUserId, confirm.SystemDocumentId } into cc
|
||||||
from confirm in cc.DefaultIfEmpty()
|
from confirm in cc.DefaultIfEmpty()
|
||||||
@@ -482,14 +482,14 @@ namespace IRaCIS.Core.Application.Services
|
|||||||
};
|
};
|
||||||
|
|
||||||
var unionQuery = trialDocQuery.Union(systemDocQuery)
|
var unionQuery = trialDocQuery.Union(systemDocQuery)
|
||||||
.WhereIf(!string.IsNullOrEmpty(querySystemDocument.Name), t => t.Name.Contains(querySystemDocument.Name))
|
.WhereIf(!string.IsNullOrEmpty(inQuery.Name), t => t.Name.Contains(inQuery.Name))
|
||||||
.WhereIf(querySystemDocument.FileTypeId != null, t => t.FileTypeId == querySystemDocument.FileTypeId)
|
.WhereIf(inQuery.FileTypeId != null, t => t.FileTypeId == inQuery.FileTypeId)
|
||||||
.WhereIf(querySystemDocument.IsConfirmed == true, t => t.ConfirmTime != null)
|
.WhereIf(inQuery.IsConfirmed == true, t => t.ConfirmTime != null)
|
||||||
.WhereIf(querySystemDocument.IsConfirmed == false, t => t.ConfirmTime == null)
|
.WhereIf(inQuery.IsConfirmed == false, t => t.ConfirmTime == null)
|
||||||
.WhereIf(querySystemDocument.IsDeleted != null, t => t.IsDeleted == querySystemDocument.IsDeleted)
|
.WhereIf(inQuery.IsDeleted != null, t => t.IsDeleted == inQuery.IsDeleted)
|
||||||
.WhereIf(querySystemDocument.UserTypeId != null, t => t.UserTypeId == querySystemDocument.UserTypeId);
|
.WhereIf(inQuery.UserTypeId != null, t => t.UserTypeId == inQuery.UserTypeId);
|
||||||
|
|
||||||
var result = await unionQuery.ToPagedListAsync(querySystemDocument.PageIndex, querySystemDocument.PageSize, querySystemDocument.SortField, querySystemDocument.Asc);
|
var result = await unionQuery.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField, inQuery.Asc);
|
||||||
|
|
||||||
var needSignTrialDocCount = await _trialDocumentRepository.AsQueryable(true)
|
var needSignTrialDocCount = await _trialDocumentRepository.AsQueryable(true)
|
||||||
.Where(t => t.Trial.TrialUserList.Any(t => t.UserId == _userInfo.Id))
|
.Where(t => t.Trial.TrialUserList.Any(t => t.UserId == _userInfo.Id))
|
||||||
@@ -823,7 +823,7 @@ namespace IRaCIS.Core.Application.Services
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[Obsolete]
|
[Obsolete]
|
||||||
public PageOutput<DocumentUnionWithUserStatView> GetTrialSystemDocumentList(DocumentTrialUnionQuery querySystemDocument)
|
public async Task<PageOutput<DocumentUnionWithUserStatView>> GetTrialSystemDocumentList(DocumentTrialUnionQuery querySystemDocument)
|
||||||
{
|
{
|
||||||
var systemDocumentQueryable = _repository
|
var systemDocumentQueryable = _repository
|
||||||
.WhereIf<SystemDocument>(!_userInfo.IsAdmin, t => t.IsDeleted == false)
|
.WhereIf<SystemDocument>(!_userInfo.IsAdmin, t => t.IsDeleted == false)
|
||||||
@@ -867,7 +867,7 @@ namespace IRaCIS.Core.Application.Services
|
|||||||
.WhereIf(!string.IsNullOrEmpty(querySystemDocument.Name), t => t.Name.Contains(querySystemDocument.Name))
|
.WhereIf(!string.IsNullOrEmpty(querySystemDocument.Name), t => t.Name.Contains(querySystemDocument.Name))
|
||||||
.WhereIf(querySystemDocument.FileTypeId != null, t => t.FileTypeId == querySystemDocument.FileTypeId);
|
.WhereIf(querySystemDocument.FileTypeId != null, t => t.FileTypeId == querySystemDocument.FileTypeId);
|
||||||
|
|
||||||
return unionQuery.ToPagedList(querySystemDocument.PageIndex, querySystemDocument.PageSize, querySystemDocument.SortField, querySystemDocument.Asc);
|
return await unionQuery.ToPagedListAsync(querySystemDocument.PageIndex, querySystemDocument.PageSize, querySystemDocument.SortField, querySystemDocument.Asc);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
@@ -1272,6 +1272,8 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
public async Task<PageOutput<TrialSelectEmailNoticeConfigView>> GetSysEmailNoticeConfigList(EmailNoticeConfigQuery queryEmailNoticeConfig)
|
public async Task<PageOutput<TrialSelectEmailNoticeConfigView>> GetSysEmailNoticeConfigList(EmailNoticeConfigQuery queryEmailNoticeConfig)
|
||||||
{
|
{
|
||||||
var emailNoticeConfigQueryable = _emailNoticeConfigRepository
|
var emailNoticeConfigQueryable = _emailNoticeConfigRepository
|
||||||
|
.WhereIf(queryEmailNoticeConfig.SystemLevel == null, t => t.SystemLevel == SysEmailLevel.not_sys)
|
||||||
|
.WhereIf(queryEmailNoticeConfig.SystemLevel != null, t => t.SystemLevel == queryEmailNoticeConfig.SystemLevel)
|
||||||
.WhereIf(queryEmailNoticeConfig.BusinessScenarioEnum != null, t => t.BusinessScenarioEnum == queryEmailNoticeConfig.BusinessScenarioEnum)
|
.WhereIf(queryEmailNoticeConfig.BusinessScenarioEnum != null, t => t.BusinessScenarioEnum == queryEmailNoticeConfig.BusinessScenarioEnum)
|
||||||
.WhereIf(queryEmailNoticeConfig.IsReturnRequired != null, t => t.IsReturnRequired == queryEmailNoticeConfig.IsReturnRequired)
|
.WhereIf(queryEmailNoticeConfig.IsReturnRequired != null, t => t.IsReturnRequired == queryEmailNoticeConfig.IsReturnRequired)
|
||||||
.WhereIf(queryEmailNoticeConfig.IsEnable != null, t => t.IsEnable == queryEmailNoticeConfig.IsEnable)
|
.WhereIf(queryEmailNoticeConfig.IsEnable != null, t => t.IsEnable == queryEmailNoticeConfig.IsEnable)
|
||||||
@@ -1477,7 +1479,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
{
|
{
|
||||||
|
|
||||||
//---发件人配置错误,请核对服务器地址或者授权码是否填写有误
|
//---发件人配置错误,请核对服务器地址或者授权码是否填写有误
|
||||||
throw new BusinessValidationFailedException(_localizer["TrialEmailN_InvalidSenderEmailConfig"] + ex.Message);
|
throw new BusinessValidationFailedException(_localizer["TrialEmailN_InvalidSenderEmailConfig"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
{
|
{
|
||||||
GroupId=gropId,
|
GroupId=gropId,
|
||||||
LimitEdit=LimitEdit.OnlyBaseLine,
|
LimitEdit=LimitEdit.OnlyBaseLine,
|
||||||
DictionaryCode="YesOrNoOrNa",
|
DictionaryCode="YesOrNoOrNE",
|
||||||
IsJudgeQuestion=false,
|
IsJudgeQuestion=false,
|
||||||
IsShowInDicom=false,
|
IsShowInDicom=false,
|
||||||
GlobalReadingShowType=GlobalReadingShowType.NotShow,
|
GlobalReadingShowType=GlobalReadingShowType.NotShow,
|
||||||
|
|||||||
@@ -52,6 +52,21 @@ namespace IRaCIS.Core.Application.Contracts.Dicom.DTO
|
|||||||
public string ImageResizePath { get; set; }
|
public string ImageResizePath { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class StudyInstanceInfo
|
||||||
|
{
|
||||||
|
|
||||||
|
public int ShowOrder { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public decimal RowIndex { get; set; }
|
||||||
|
|
||||||
|
public Guid? SeriesId { get; set; }
|
||||||
|
|
||||||
|
public Guid? StudyId { get; set; }
|
||||||
|
public Guid? InstanceId { get; set; }
|
||||||
|
|
||||||
|
public int? NumberOfFrames { get; set; }
|
||||||
|
}
|
||||||
public class InstanceBasicInfo
|
public class InstanceBasicInfo
|
||||||
{
|
{
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
@@ -64,6 +79,10 @@ namespace IRaCIS.Core.Application.Contracts.Dicom.DTO
|
|||||||
|
|
||||||
public int InstanceNumber { get; set; }
|
public int InstanceNumber { get; set; }
|
||||||
|
|
||||||
|
public Guid? StudyId { get; set; }
|
||||||
|
|
||||||
|
public Guid? SeriesId { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public int ShowOrder { get; set; }
|
public int ShowOrder { get; set; }
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
|
|||||||
@@ -44,6 +44,9 @@ namespace IRaCIS.Core.Application.Contracts
|
|||||||
|
|
||||||
public string RecordPath { get; set; } = string.Empty;
|
public string RecordPath { get; set; } = string.Empty;
|
||||||
public bool IsDicom { get; set; }
|
public bool IsDicom { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UnionStudyMonitorModel : UnionStudyBaseModel
|
public class UnionStudyMonitorModel : UnionStudyBaseModel
|
||||||
@@ -124,7 +127,7 @@ namespace IRaCIS.Core.Application.Contracts
|
|||||||
|
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
|
public bool IsFromPACS { get; set; }
|
||||||
|
|
||||||
public int? Count { get; set; }
|
public int? Count { get; set; }
|
||||||
|
|
||||||
@@ -164,6 +167,8 @@ namespace IRaCIS.Core.Application.Contracts
|
|||||||
public bool? IsSuccess { get; set; }
|
public bool? IsSuccess { get; set; }
|
||||||
|
|
||||||
public string? StudyCode { get; set; }
|
public string? StudyCode { get; set; }
|
||||||
|
|
||||||
|
public bool? IsFromPACS { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -209,6 +214,20 @@ namespace IRaCIS.Core.Application.Contracts
|
|||||||
public int FileCount { get; set; }
|
public int FileCount { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class SubejctZipInfoQuery
|
||||||
|
{
|
||||||
|
public Guid? SubejctId { get; set; }
|
||||||
|
|
||||||
|
public string? SubjectCode { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public Guid? SubejectVisitId { get; set; }
|
||||||
|
|
||||||
|
public Guid? TrialReadingCriterionId { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public class TaskArchiveStudyCommand
|
public class TaskArchiveStudyCommand
|
||||||
{
|
{
|
||||||
[NotDefault]
|
[NotDefault]
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using IRaCIS.Core.Application.Contracts;
|
|||||||
using IRaCIS.Core.Application.Filter;
|
using IRaCIS.Core.Application.Filter;
|
||||||
using IRaCIS.Core.Application.Helper;
|
using IRaCIS.Core.Application.Helper;
|
||||||
using IRaCIS.Core.Application.Service.ImageAndDoc.DTO;
|
using IRaCIS.Core.Application.Service.ImageAndDoc.DTO;
|
||||||
|
using IRaCIS.Core.Domain.Models;
|
||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
using IRaCIS.Core.Infrastructure;
|
using IRaCIS.Core.Infrastructure;
|
||||||
using IRaCIS.Core.Infrastructure.Extention;
|
using IRaCIS.Core.Infrastructure.Extention;
|
||||||
@@ -11,6 +12,8 @@ using MassTransit;
|
|||||||
using MathNet.Numerics;
|
using MathNet.Numerics;
|
||||||
using Medallion.Threading;
|
using Medallion.Threading;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
@@ -18,12 +21,13 @@ using System.IO.Compression;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Web;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
||||||
{
|
{
|
||||||
public interface IDownloadAndUploadService
|
public interface IDownloadAndUploadService
|
||||||
{
|
{
|
||||||
Task PackageAndAnonymizImage(Guid trialId, Guid subjectVisitId, bool isAnonymize = true);
|
Task PackageAndAnonymizImage(Guid trialId, Guid subjectVisitId, bool isDicom, bool isAnonymize = true);
|
||||||
}
|
}
|
||||||
[ApiExplorerSettings(GroupName = "Trial")]
|
[ApiExplorerSettings(GroupName = "Trial")]
|
||||||
public class DownloadAndUploadService : BaseService, IDownloadAndUploadService
|
public class DownloadAndUploadService : BaseService, IDownloadAndUploadService
|
||||||
@@ -107,8 +111,8 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
|||||||
{
|
{
|
||||||
await SubejctRandomReadingTaskNameDeal(subjectId, trialReadingCriterionId);
|
await SubejctRandomReadingTaskNameDeal(subjectId, trialReadingCriterionId);
|
||||||
|
|
||||||
var query = _repository.Where<VisitTask>(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.SourceSubjectVisitId != null
|
var query = _repository.Where<VisitTask>(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.SourceSubjectVisitId != null
|
||||||
&& t.DoctorUserId == _userInfo.Id && t.TaskState==TaskState.Effect)
|
&& t.DoctorUserId == _userInfo.Id && t.TaskState == TaskState.Effect)
|
||||||
.Select(u => new SubjectImageUploadDTO()
|
.Select(u => new SubjectImageUploadDTO()
|
||||||
{
|
{
|
||||||
VisitTaskId = u.Id,
|
VisitTaskId = u.Id,
|
||||||
@@ -129,7 +133,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
|||||||
PackState = u.SourceSubjectVisit.PackState,
|
PackState = u.SourceSubjectVisit.PackState,
|
||||||
|
|
||||||
OrginalStudyList = u.SourceSubjectVisit.StudyList
|
OrginalStudyList = u.SourceSubjectVisit.StudyList
|
||||||
.Where(t => u.TrialReadingCriterion.IsImageFilter ?("|"+u.TrialReadingCriterion.CriterionModalitys+"|").Contains("|"+t.ModalityForEdit+"|" ) : true)
|
.Where(t => u.TrialReadingCriterion.IsImageFilter ? ("|" + u.TrialReadingCriterion.CriterionModalitys + "|").Contains("|" + t.ModalityForEdit + "|") : true)
|
||||||
.Select(t => new StudyBasicInfo()
|
.Select(t => new StudyBasicInfo()
|
||||||
{
|
{
|
||||||
Id = t.Id,
|
Id = t.Id,
|
||||||
@@ -484,36 +488,195 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="trialId"></param>
|
/// <param name="trialId"></param>
|
||||||
/// <param name="subjectVisitId"></param>
|
/// <param name="subjectVisitId"></param>
|
||||||
|
/// <param name="isDicom"></param>
|
||||||
/// <param name="isAnonymize"></param>
|
/// <param name="isAnonymize"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
|
||||||
public async Task<IResponseOutput> RequestPackageAndAnonymizImage(Guid trialId, Guid subjectVisitId, bool isAnonymize = true)
|
public async Task<IResponseOutput> RequestPackageAndAnonymizImage(Guid trialId, Guid subjectVisitId, bool isDicom, bool isAnonymize = true)
|
||||||
{
|
{
|
||||||
var subjectVisit = await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId);
|
|
||||||
|
|
||||||
if (subjectVisit.PackState == PackState.WaitPack)
|
|
||||||
|
var extralConfig = _repository.Where<Trial>(t => t.Id == trialId).Select(t => t.TrialExtraConfigJsonStr).FirstOrDefault() ?? string.Empty;
|
||||||
|
|
||||||
|
var config = JsonConvert.DeserializeObject<TrialExtraConfig>(extralConfig) ?? new TrialExtraConfig();
|
||||||
|
|
||||||
|
if (config.IsSupportQCDownloadImage == false)
|
||||||
{
|
{
|
||||||
HangfireJobHelper.NotImmediatelyOnceOnlyJob<IDownloadAndUploadService>(t => t.PackageAndAnonymizImage(trialId, subjectVisitId, isAnonymize), TimeSpan.FromSeconds(1));
|
throw new BusinessValidationFailedException("该项目不支持QC下载影像");
|
||||||
|
|
||||||
subjectVisit.PackState = PackState.Packing;
|
|
||||||
|
|
||||||
await _subjectVisitRepository.SaveChangesAsync();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResponseOutput.Ok(subjectVisit.VisitImageZipPath);
|
var subjectVisit = await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId);
|
||||||
|
|
||||||
|
var sujectCode = await _subjectVisitRepository.Where(t => t.Id == subjectVisitId).Select(t => t.Subject.Code).FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
var packState = isDicom ? subjectVisit.PackState : subjectVisit.NoDicomPackState;
|
||||||
|
|
||||||
|
if (packState == PackState.WaitPack)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (isDicom)
|
||||||
|
{
|
||||||
|
subjectVisit.PackState = PackState.Packing;
|
||||||
|
HangfireJobHelper.NotImmediatelyOnceOnlyJob<IDownloadAndUploadService>(t => t.PackageAndAnonymizImage(trialId, subjectVisitId, true, isAnonymize), TimeSpan.FromSeconds(1));
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
subjectVisit.NoDicomPackState = PackState.Packing;
|
||||||
|
|
||||||
|
HangfireJobHelper.NotImmediatelyOnceOnlyJob<IDownloadAndUploadService>(t => t.PackageAndAnonymizImage(trialId, subjectVisitId, false, isAnonymize), TimeSpan.FromSeconds(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
await _subjectVisitRepository.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResponseOutput.Ok(isDicom ? subjectVisit.VisitImageZipPath : subjectVisit.VisitNoDicomImageZipPath,
|
||||||
|
new { FileName = $"{sujectCode}_{subjectVisit.VisitName}_ImageStudy_{(isDicom ? "Dicom" : "NoneDicom")}.zip" });
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 受试者级别所有的影像
|
||||||
|
/// 访视级别的影响 传递subjectVisitId
|
||||||
|
/// 标准Id是可选的 不同标准有些检查可能有过滤
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="_subjectRepository"></param>
|
||||||
|
/// <param name="inQuery"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<IResponseOutput> GetSubejectOrVisitZipInfo([FromServices] IRepository<Subject> _subjectRepository, SubejctZipInfoQuery inQuery)
|
||||||
|
{
|
||||||
|
var isImageFilter = false;
|
||||||
|
|
||||||
|
var criterionModalitys = string.Empty;
|
||||||
|
|
||||||
|
if (inQuery.TrialReadingCriterionId != null)
|
||||||
|
{
|
||||||
|
var criterionInfo = await _repository.Where<ReadingQuestionCriterionTrial>(t => t.Id == inQuery.TrialReadingCriterionId).Select(t => new { t.IsImageFilter, t.CriterionModalitys }).FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
if (criterionInfo != null)
|
||||||
|
{
|
||||||
|
isImageFilter = criterionInfo.IsImageFilter;
|
||||||
|
criterionModalitys = criterionInfo.CriterionModalitys;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inQuery.SubejectVisitId != null)
|
||||||
|
{
|
||||||
|
var query = from sv in _subjectVisitRepository.Where(t => t.Id == inQuery.SubejectVisitId)
|
||||||
|
|
||||||
|
|
||||||
|
select new
|
||||||
|
{
|
||||||
|
SubjectCode = sv.Subject.Code,
|
||||||
|
VisitName = sv.VisitName,
|
||||||
|
StudyList = sv.StudyList.AsQueryable().WhereIf(isImageFilter, t => ("|" + criterionModalitys + "|").Contains("|" + t.ModalityForEdit + "|"))
|
||||||
|
.Select(u => new
|
||||||
|
{
|
||||||
|
u.PatientId,
|
||||||
|
u.StudyTime,
|
||||||
|
u.StudyCode,
|
||||||
|
|
||||||
|
SeriesList = u.SeriesList.Select(z => new
|
||||||
|
{
|
||||||
|
z.Modality,
|
||||||
|
|
||||||
|
InstancePathList = z.DicomInstanceList.Select(k => new
|
||||||
|
{
|
||||||
|
k.Path
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
}),
|
||||||
|
|
||||||
|
NoneDicomStudyList = sv.NoneDicomStudyList.AsQueryable().WhereIf(isImageFilter, t => ("|" + criterionModalitys + "|").Contains("|" + t.Modality + "|"))
|
||||||
|
.Select(nd => new
|
||||||
|
{
|
||||||
|
nd.Modality,
|
||||||
|
nd.StudyCode,
|
||||||
|
nd.ImageDate,
|
||||||
|
|
||||||
|
FileList = nd.NoneDicomFileList.Select(file => new
|
||||||
|
{
|
||||||
|
file.FileName,
|
||||||
|
file.Path,
|
||||||
|
file.FileType
|
||||||
|
})
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = query.ToList();
|
||||||
|
|
||||||
|
return ResponseOutput.Ok(result);
|
||||||
|
}
|
||||||
|
else if (inQuery.SubejctId != null)
|
||||||
|
{
|
||||||
|
var query = from sv in _subjectRepository.Where(t => t.Id == inQuery.SubejctId).SelectMany(t=>t.SubjectVisitList)
|
||||||
|
|
||||||
|
|
||||||
|
select new
|
||||||
|
{
|
||||||
|
SubjectCode = sv.Subject.Code,
|
||||||
|
VisitName = sv.VisitName,
|
||||||
|
StudyList = sv.StudyList.AsQueryable().WhereIf(isImageFilter, t => ("|" + criterionModalitys + "|").Contains("|" + t.ModalityForEdit + "|"))
|
||||||
|
.Select(u => new
|
||||||
|
{
|
||||||
|
u.PatientId,
|
||||||
|
u.StudyTime,
|
||||||
|
u.StudyCode,
|
||||||
|
|
||||||
|
SeriesList = u.SeriesList.Select(z => new
|
||||||
|
{
|
||||||
|
z.Modality,
|
||||||
|
|
||||||
|
InstancePathList = z.DicomInstanceList.Select(k => new
|
||||||
|
{
|
||||||
|
k.Path
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
}),
|
||||||
|
|
||||||
|
NoneDicomStudyList = sv.NoneDicomStudyList.AsQueryable().WhereIf(isImageFilter, t => ("|" + criterionModalitys + "|").Contains("|" + t.Modality + "|"))
|
||||||
|
.Select(nd => new
|
||||||
|
{
|
||||||
|
nd.Modality,
|
||||||
|
nd.StudyCode,
|
||||||
|
nd.ImageDate,
|
||||||
|
|
||||||
|
FileList = nd.NoneDicomFileList.Select(file => new
|
||||||
|
{
|
||||||
|
file.FileName,
|
||||||
|
file.Path,
|
||||||
|
file.FileType
|
||||||
|
})
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = query.ToList();
|
||||||
|
|
||||||
|
return ResponseOutput.Ok(result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ResponseOutput.NotOk("不允许 subjectId subjectId 都不传递");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 后台任务调用,前端忽略该接口
|
/// 后台任务调用,前端忽略该接口
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="trialId"></param>
|
/// <param name="trialId"></param>
|
||||||
/// <param name="subjectVisitId"></param>
|
/// <param name="subjectVisitId"></param>
|
||||||
|
/// <param name="isDicom"></param>
|
||||||
/// <param name="isAnonymize"></param>
|
/// <param name="isAnonymize"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task PackageAndAnonymizImage(Guid trialId, Guid subjectVisitId, bool isAnonymize = true)
|
public async Task PackageAndAnonymizImage(Guid trialId, Guid subjectVisitId, bool isDicom, bool isAnonymize = true)
|
||||||
{
|
{
|
||||||
|
|
||||||
var subjectVisit = await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId);
|
var subjectVisit = await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId);
|
||||||
@@ -557,6 +720,20 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
}),
|
||||||
|
|
||||||
|
NoneDicomStudyList = sv.NoneDicomStudyList.Select(nd => new
|
||||||
|
{
|
||||||
|
nd.Modality,
|
||||||
|
nd.StudyCode,
|
||||||
|
nd.ImageDate,
|
||||||
|
|
||||||
|
FileList = nd.NoneDicomFileList.Select(file => new
|
||||||
|
{
|
||||||
|
file.FileName,
|
||||||
|
file.Path,
|
||||||
|
file.FileType
|
||||||
|
})
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -568,107 +745,146 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
|||||||
string tempFolderPath = Path.Combine(Directory.GetCurrentDirectory(), $"DownloadTemp_{NewId.NextGuid()}");
|
string tempFolderPath = Path.Combine(Directory.GetCurrentDirectory(), $"DownloadTemp_{NewId.NextGuid()}");
|
||||||
Directory.CreateDirectory(tempFolderPath);
|
Directory.CreateDirectory(tempFolderPath);
|
||||||
|
|
||||||
// 遍历查询结果
|
//dicom 处理
|
||||||
foreach (var studyInfo in info.StudyList)
|
|
||||||
|
if (isDicom)
|
||||||
{
|
{
|
||||||
// 遍历 Series
|
// 遍历查询结果
|
||||||
foreach (var seriesInfo in studyInfo.SeriesList)
|
foreach (var studyInfo in info.StudyList)
|
||||||
{
|
{
|
||||||
string studyFolderPath = Path.Combine(tempFolderPath, $"{info.SubjectCode}_{info.VisitName}", $"{studyInfo.StudyCode}_{studyInfo.StudyTime?.ToString("yyyy-MM-dd")}_{seriesInfo.Modality}");
|
// 遍历 Series
|
||||||
|
foreach (var seriesInfo in studyInfo.SeriesList)
|
||||||
// 创建 影像 文件夹
|
|
||||||
Directory.CreateDirectory(studyFolderPath);
|
|
||||||
|
|
||||||
// 遍历 InstancePathList
|
|
||||||
foreach (var instanceInfo in seriesInfo.InstancePathList)
|
|
||||||
{
|
{
|
||||||
// 复制文件到相应的文件夹
|
string studyDicomFolderPath = Path.Combine(tempFolderPath, "Dicom",/* $"{info.SubjectCode}_{info.VisitName}",*/ $"{studyInfo.StudyCode}_{studyInfo.StudyTime?.ToString("yyyy-MM-dd")}_{seriesInfo.Modality}");
|
||||||
string destinationPath = Path.Combine(studyFolderPath, Path.GetFileName(instanceInfo.Path));
|
|
||||||
|
|
||||||
//下载到当前目录
|
// 创建 影像 文件夹
|
||||||
await _oSSService.DownLoadFromOSSAsync(instanceInfo.Path, destinationPath);
|
Directory.CreateDirectory(studyDicomFolderPath);
|
||||||
|
|
||||||
#region 匿名化逻辑
|
// 遍历 InstancePathList
|
||||||
|
foreach (var instanceInfo in seriesInfo.InstancePathList)
|
||||||
|
|
||||||
if (isAnonymize)
|
|
||||||
{
|
{
|
||||||
//受试者随机阅片,需要匿名化检查时间
|
// 复制文件到相应的文件夹
|
||||||
DicomFile dicomFile = await DicomFile.OpenAsync(destinationPath, Encoding.Default);
|
string destinationPath = Path.Combine(studyDicomFolderPath, Path.GetFileName(instanceInfo.Path));
|
||||||
DicomDataset dataset = dicomFile.Dataset;
|
|
||||||
dataset.AddOrUpdate(DicomTag.StudyDate, string.Empty);
|
|
||||||
dataset.AddOrUpdate(DicomTag.StudyTime, string.Empty);
|
|
||||||
|
|
||||||
#region 前端已经匿名化,不需要做相关tag匿名化
|
//下载到当前目录
|
||||||
//DicomFile dicomFile = await DicomFile.OpenAsync(destinationPath, Encoding.Default);
|
await _oSSService.DownLoadFromOSSAsync(instanceInfo.Path, destinationPath);
|
||||||
|
|
||||||
//DicomDataset dataset = dicomFile.Dataset;
|
#region 匿名化逻辑
|
||||||
|
|
||||||
//foreach (var item in addOrUpdateFixedFieldList)
|
|
||||||
//{
|
|
||||||
|
|
||||||
// var dicomTag = new DicomTag(Convert.ToUInt16(item.Group, 16), Convert.ToUInt16(item.Element, 16));
|
if (isAnonymize)
|
||||||
|
{
|
||||||
|
//受试者随机阅片,需要匿名化检查时间
|
||||||
|
DicomFile dicomFile = await DicomFile.OpenAsync(destinationPath, Encoding.Default);
|
||||||
|
DicomDataset dataset = dicomFile.Dataset;
|
||||||
|
dataset.AddOrUpdate(DicomTag.StudyDate, string.Empty);
|
||||||
|
dataset.AddOrUpdate(DicomTag.StudyTime, string.Empty);
|
||||||
|
|
||||||
// dataset.AddOrUpdate(dicomTag, item.ReplaceValue);
|
#region 前端已经匿名化,不需要做相关tag匿名化
|
||||||
//}
|
//DicomFile dicomFile = await DicomFile.OpenAsync(destinationPath, Encoding.Default);
|
||||||
|
|
||||||
//foreach (var item in ircFieldList)
|
//DicomDataset dataset = dicomFile.Dataset;
|
||||||
//{
|
|
||||||
|
|
||||||
// var dicomTag = new DicomTag(Convert.ToUInt16(item.Group, 16), Convert.ToUInt16(item.Element, 16));
|
//foreach (var item in addOrUpdateFixedFieldList)
|
||||||
|
//{
|
||||||
|
|
||||||
// if (dicomTag == DicomTag.ClinicalTrialProtocolID)
|
// var dicomTag = new DicomTag(Convert.ToUInt16(item.Group, 16), Convert.ToUInt16(item.Element, 16));
|
||||||
// {
|
|
||||||
// dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.TrialCode);
|
|
||||||
|
|
||||||
// }
|
// dataset.AddOrUpdate(dicomTag, item.ReplaceValue);
|
||||||
// if (dicomTag == DicomTag.ClinicalTrialSiteID)
|
//}
|
||||||
// {
|
|
||||||
// //dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.TrialSiteCode);
|
|
||||||
|
|
||||||
// }
|
//foreach (var item in ircFieldList)
|
||||||
// if (dicomTag == DicomTag.ClinicalTrialSubjectID)
|
//{
|
||||||
// {
|
|
||||||
// dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.SubjectCode);
|
|
||||||
|
|
||||||
// }
|
// var dicomTag = new DicomTag(Convert.ToUInt16(item.Group, 16), Convert.ToUInt16(item.Element, 16));
|
||||||
// if (dicomTag == DicomTag.ClinicalTrialTimePointID)
|
|
||||||
// {
|
|
||||||
// dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.VisitNum.ToString());
|
|
||||||
|
|
||||||
// }
|
// if (dicomTag == DicomTag.ClinicalTrialProtocolID)
|
||||||
// if (dicomTag == DicomTag.PatientID)
|
// {
|
||||||
// {
|
// dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.TrialCode);
|
||||||
// dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.TrialCode + "_" + subjectAndVisitInfo.SubjectCode);
|
|
||||||
|
|
||||||
// }
|
// }
|
||||||
|
// if (dicomTag == DicomTag.ClinicalTrialSiteID)
|
||||||
|
// {
|
||||||
|
// //dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.TrialSiteCode);
|
||||||
|
|
||||||
//}
|
// }
|
||||||
|
// if (dicomTag == DicomTag.ClinicalTrialSubjectID)
|
||||||
|
// {
|
||||||
|
// dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.SubjectCode);
|
||||||
|
|
||||||
|
// }
|
||||||
|
// if (dicomTag == DicomTag.ClinicalTrialTimePointID)
|
||||||
|
// {
|
||||||
|
// dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.VisitNum.ToString());
|
||||||
|
|
||||||
|
// }
|
||||||
|
// if (dicomTag == DicomTag.PatientID)
|
||||||
|
// {
|
||||||
|
// dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.TrialCode + "_" + subjectAndVisitInfo.SubjectCode);
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
//}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var zipDicomPath = Path.Combine(Directory.GetCurrentDirectory(), $"{info.SubjectCode}_{info.VisitName}_ImageStudy_Dicom.zip");
|
||||||
|
ZipFile.CreateFromDirectory(Path.Combine(tempFolderPath, "Dicom"), zipDicomPath);
|
||||||
|
//上传到Oss
|
||||||
|
var relativeDicomPath = await _oSSService.UploadToOSSAsync(zipDicomPath, $"download_zip", false);
|
||||||
|
|
||||||
|
await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.Id == subjectVisitId, u => new SubjectVisit() { PackState = PackState.Packed, VisitImageZipPath = relativeDicomPath });
|
||||||
|
|
||||||
|
|
||||||
|
File.Delete(zipDicomPath);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var relativeNoneDicomPath = string.Empty;
|
||||||
|
|
||||||
var zipPath = Path.Combine(Directory.GetCurrentDirectory(), $"{info.SubjectCode}_{info.VisitName}_ImageStudy.zip");
|
if (info.NoneDicomStudyList.Count() == 1 && info.NoneDicomStudyList.SelectMany(t => t.FileList).Count() == 1)
|
||||||
|
{
|
||||||
|
relativeNoneDicomPath = info.NoneDicomStudyList.First().FileList.First().Path;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//非dicom 处理
|
||||||
|
|
||||||
ZipFile.CreateFromDirectory(tempFolderPath, zipPath);
|
foreach (var noneDicomStudy in info.NoneDicomStudyList)
|
||||||
|
{
|
||||||
|
string studyNoneDicomFolderPath = Path.Combine(tempFolderPath, "NoneDicom", /*$"{info.SubjectCode}_{info.VisitName}",*/ $"{noneDicomStudy.StudyCode}_{noneDicomStudy.ImageDate.ToString("yyyy-MM-dd")}_{noneDicomStudy.Modality}");
|
||||||
|
|
||||||
//上传到Oss
|
Directory.CreateDirectory(studyNoneDicomFolderPath);
|
||||||
var relativePath = await _oSSService.UploadToOSSAsync(zipPath, $"download_zip", false);
|
|
||||||
|
foreach (var file in noneDicomStudy.FileList)
|
||||||
|
{
|
||||||
|
string destinationPath = Path.Combine(studyNoneDicomFolderPath, Path.GetFileName(file.FileName));
|
||||||
|
|
||||||
|
//下载到当前目录
|
||||||
|
await _oSSService.DownLoadFromOSSAsync(HttpUtility.UrlDecode(file.Path), destinationPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var zipNoneDicomPath = Path.Combine(Directory.GetCurrentDirectory(), $"{info.SubjectCode}_{info.VisitName}_ImageStudy_NoneDicom.zip");
|
||||||
|
ZipFile.CreateFromDirectory(Path.Combine(tempFolderPath, "NoneDicom"), zipNoneDicomPath);
|
||||||
|
relativeNoneDicomPath = await _oSSService.UploadToOSSAsync(zipNoneDicomPath, $"download_zip", false);
|
||||||
|
|
||||||
|
File.Delete(zipNoneDicomPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.Id == subjectVisitId, u => new SubjectVisit() { PackState = PackState.Packed, VisitNoDicomImageZipPath = relativeNoneDicomPath });
|
||||||
|
|
||||||
|
|
||||||
//subjectVisit.PackState = PackState.Packed;
|
}
|
||||||
//subjectVisit.VisitImageZipPath = relativePath;
|
|
||||||
//await _subjectVisitRepository.SaveChangesAsync();
|
|
||||||
await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.Id == subjectVisitId, u => new SubjectVisit() { PackState = PackState.Packed, VisitImageZipPath = relativePath });
|
|
||||||
|
|
||||||
|
|
||||||
//清理文件夹
|
//清理文件夹
|
||||||
Directory.Delete(tempFolderPath, true);
|
Directory.Delete(tempFolderPath, true);
|
||||||
File.Delete(zipPath);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ using IRaCIS.Core.Infrastructure;
|
|||||||
using DocumentFormat.OpenXml.Presentation;
|
using DocumentFormat.OpenXml.Presentation;
|
||||||
using IRaCIS.Core.Domain.Models;
|
using IRaCIS.Core.Domain.Models;
|
||||||
using IRaCIS.Core.Application.Filter;
|
using IRaCIS.Core.Application.Filter;
|
||||||
using IRaCIS.Core.Application.MediatR.Handlers;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@@ -145,6 +144,23 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
|||||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||||
public async Task<IResponseOutput> AddOrUpdateArchiveStudy(NewArchiveStudyCommand incommand)
|
public async Task<IResponseOutput> AddOrUpdateArchiveStudy(NewArchiveStudyCommand incommand)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
var @uploadLock = _distributedLockProvider.CreateLock($"UploadDicom");
|
||||||
|
|
||||||
|
using (await @uploadLock.AcquireAsync())
|
||||||
|
{
|
||||||
|
if (_provider.Exists($"{incommand.TrialId}_{incommand.Study.StudyInstanceUid}"))
|
||||||
|
{
|
||||||
|
//---当前已有人正在上传和归档该检查!
|
||||||
|
return ResponseOutput.NotOk(StaticData.International("UploadDownLoad_ArchiveInProgress"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//在事务未完成前 防止前端重复提交
|
||||||
|
_provider.Set($"{incommand.TrialId}_{incommand.Study.StudyInstanceUid}", _userInfo.Id, TimeSpan.FromMinutes(3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var modalitys = string.Empty;
|
var modalitys = string.Empty;
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -189,9 +205,10 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
|||||||
study.TrialId = incommand.TrialId;
|
study.TrialId = incommand.TrialId;
|
||||||
study.SubjectId = incommand.SubjectId;
|
study.SubjectId = incommand.SubjectId;
|
||||||
study.SubjectVisitId = incommand.SubjectVisitId;
|
study.SubjectVisitId = incommand.SubjectVisitId;
|
||||||
|
study.IsFromPACS = false;
|
||||||
|
|
||||||
//如果因为意外情况,连续点击两次,导致第一次插入了,第二次进来也会插入,在此判断一下
|
//如果因为意外情况,连续点击两次,导致第一次插入了,第二次进来也会插入,在此判断一下
|
||||||
var findStudy = await _dicomstudyRepository.FirstOrDefaultAsync(t => t.Id == study.Id);
|
var findStudy = await _dicomstudyRepository.FirstOrDefaultAsync(t => t.Id == study.Id);
|
||||||
|
|
||||||
if (findStudy != null)
|
if (findStudy != null)
|
||||||
{
|
{
|
||||||
@@ -263,6 +280,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
|||||||
studyMonitor.StudyCode = study.StudyCode;
|
studyMonitor.StudyCode = study.StudyCode;
|
||||||
|
|
||||||
//特殊处理逻辑
|
//特殊处理逻辑
|
||||||
|
study.IsFromPACS = false;
|
||||||
study.Modalities = string.Join("、", incommand.Study.SeriesList.Select(t => t.Modality).Union(study.Modalities.Split("、", StringSplitOptions.RemoveEmptyEntries)).Distinct());
|
study.Modalities = string.Join("、", incommand.Study.SeriesList.Select(t => t.Modality).Union(study.Modalities.Split("、", StringSplitOptions.RemoveEmptyEntries)).Distinct());
|
||||||
SpecialArchiveStudyDeal(study);
|
SpecialArchiveStudyDeal(study);
|
||||||
modalitys = study.Modalities;
|
modalitys = study.Modalities;
|
||||||
@@ -339,6 +357,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
|||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
_provider.Remove($"StudyUid_{incommand.TrialId}_{incommand.Study.StudyInstanceUid}");
|
_provider.Remove($"StudyUid_{incommand.TrialId}_{incommand.Study.StudyInstanceUid}");
|
||||||
|
_provider.Remove($"{incommand.TrialId}_{incommand.Study.StudyInstanceUid}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -372,6 +391,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
|||||||
VisitNum = t.SubjectVisit.VisitNum,
|
VisitNum = t.SubjectVisit.VisitNum,
|
||||||
|
|
||||||
IsDicom = true,
|
IsDicom = true,
|
||||||
|
IsFromPACS = t.IsFromPACS,
|
||||||
|
|
||||||
SubjectCode = t.Subject.Code,
|
SubjectCode = t.Subject.Code,
|
||||||
|
|
||||||
@@ -421,6 +441,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
|||||||
VisitNum = t.SubjectVisit.VisitNum,
|
VisitNum = t.SubjectVisit.VisitNum,
|
||||||
|
|
||||||
IsDicom = false,
|
IsDicom = false,
|
||||||
|
IsFromPACS = false,
|
||||||
|
|
||||||
SubjectCode = t.Subject.Code,
|
SubjectCode = t.Subject.Code,
|
||||||
|
|
||||||
@@ -455,28 +476,29 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
|||||||
var unionQuery = dicomStudyQuery.Union(nodeDicomStudyQuery)
|
var unionQuery = dicomStudyQuery.Union(nodeDicomStudyQuery)
|
||||||
.WhereIf(studyQuery.SubjectId != null, t => t.SubjectId == studyQuery.SubjectId)
|
.WhereIf(studyQuery.SubjectId != null, t => t.SubjectId == studyQuery.SubjectId)
|
||||||
.WhereIf(studyQuery.SubjectVisitId != null, t => t.SubjectId == studyQuery.SubjectVisitId)
|
.WhereIf(studyQuery.SubjectVisitId != null, t => t.SubjectId == studyQuery.SubjectVisitId)
|
||||||
.WhereIf(studyQuery.TrialSiteId != null, t => t.TrialSiteId == studyQuery.TrialSiteId);
|
.WhereIf(studyQuery.TrialSiteId != null, t => t.TrialSiteId == studyQuery.TrialSiteId)
|
||||||
|
.WhereIf(studyQuery.IsFromPACS != null, t => t.IsFromPACS == studyQuery.IsFromPACS);
|
||||||
|
|
||||||
return await unionQuery.ToPagedListAsync(studyQuery.PageIndex, studyQuery.PageSize, studyQuery.SortField, studyQuery.Asc);
|
return await unionQuery.ToPagedListAsync(studyQuery.PageIndex, studyQuery.PageSize, studyQuery.SortField, studyQuery.Asc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<PageOutput<UnionStudyMonitorModel>> GetDicomAndNoneDicomStudyMonitorList(StudyQuery studyQuery)
|
public async Task<PageOutput<UnionStudyMonitorModel>> GetDicomAndNoneDicomStudyMonitorList(StudyQuery inQuery)
|
||||||
{
|
{
|
||||||
var svExpression = QCCommon.GetStudyMonitorSubjectVisitFilter(studyQuery.VisitPlanArray);
|
var svExpression = QCCommon.GetStudyMonitorSubjectVisitFilter(inQuery.VisitPlanArray);
|
||||||
var StudyMonitorQuery = _repository.Where<StudyMonitor>(t => t.TrialId == studyQuery.TrialId, ignoreQueryFilters: true)
|
var StudyMonitorQuery = _repository.Where<StudyMonitor>(t => t.TrialId == inQuery.TrialId, ignoreQueryFilters: true)
|
||||||
.WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA, t => t.Subject.TrialSite.CRCUserList.Any(t => t.UserId == _userInfo.Id))
|
.WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA, t => t.Subject.TrialSite.CRCUserList.Any(t => t.UserId == _userInfo.Id))
|
||||||
//.WhereIf(!string.IsNullOrEmpty(studyQuery.VisitPlanInfo), studyQuery.VisitPlanInfo.Contains('.') ? t => t.SubjectVisit.VisitNum.ToString().Contains(".") : t => t.SubjectVisit.VisitNum == decimal.Parse(studyQuery.VisitPlanInfo))
|
//.WhereIf(!string.IsNullOrEmpty(studyQuery.VisitPlanInfo), studyQuery.VisitPlanInfo.Contains('.') ? t => t.SubjectVisit.VisitNum.ToString().Contains(".") : t => t.SubjectVisit.VisitNum == decimal.Parse(studyQuery.VisitPlanInfo))
|
||||||
.WhereIf(studyQuery.VisitPlanArray != null && studyQuery.VisitPlanArray?.Length > 0, svExpression)
|
.WhereIf(inQuery.VisitPlanArray != null && inQuery.VisitPlanArray?.Length > 0, svExpression)
|
||||||
.WhereIf(!string.IsNullOrWhiteSpace(studyQuery.SubjectInfo), t => t.Subject.Code.Contains(studyQuery.SubjectInfo))
|
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectInfo), t => t.Subject.Code.Contains(inQuery.SubjectInfo))
|
||||||
.WhereIf(studyQuery.SubjectId != null, t => t.SubjectId == studyQuery.SubjectId)
|
.WhereIf(inQuery.SubjectId != null, t => t.SubjectId == inQuery.SubjectId)
|
||||||
.WhereIf(studyQuery.SubjectVisitId != null, t => t.SubjectId == studyQuery.SubjectVisitId)
|
.WhereIf(inQuery.SubjectVisitId != null, t => t.SubjectId == inQuery.SubjectVisitId)
|
||||||
.WhereIf(studyQuery.TrialSiteId != null, t => t.Subject.TrialSiteId == studyQuery.TrialSiteId)
|
.WhereIf(inQuery.TrialSiteId != null, t => t.Subject.TrialSiteId == inQuery.TrialSiteId)
|
||||||
.WhereIf(studyQuery.IsDicom != null, t => t.IsDicom == studyQuery.IsDicom)
|
.WhereIf(inQuery.IsDicom != null, t => t.IsDicom == inQuery.IsDicom)
|
||||||
.WhereIf(!string.IsNullOrWhiteSpace(studyQuery.Uploader), t => t.Uploader.UserName.Contains(studyQuery.Uploader))
|
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.Uploader), t => t.Uploader.UserName.Contains(inQuery.Uploader))
|
||||||
.WhereIf(studyQuery.IsSuccess != null, t => t.IsSuccess == studyQuery.IsSuccess)
|
.WhereIf(inQuery.IsSuccess != null, t => t.IsSuccess == inQuery.IsSuccess)
|
||||||
.WhereIf(!string.IsNullOrWhiteSpace(studyQuery.StudyCode), t => t.StudyCode.Contains(studyQuery.StudyCode))
|
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.StudyCode), t => t.StudyCode.Contains(inQuery.StudyCode))
|
||||||
.Select(t => new UnionStudyMonitorModel()
|
.Select(t => new UnionStudyMonitorModel()
|
||||||
{
|
{
|
||||||
TrialId = t.TrialId,
|
TrialId = t.TrialId,
|
||||||
@@ -520,7 +542,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return await StudyMonitorQuery.ToPagedListAsync(studyQuery.PageIndex, studyQuery.PageSize, string.IsNullOrEmpty(studyQuery.SortField) ? "UploadTime" : studyQuery.SortField, studyQuery.Asc);
|
return await StudyMonitorQuery.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrEmpty(inQuery.SortField) ? "UploadTime" : inQuery.SortField, inQuery.Asc);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -540,7 +562,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
|||||||
|
|
||||||
path = (await _dicomInstanceRepository.Where(s => s.StudyId == studyId).Select(t => t.Path).FirstOrDefaultAsync()).IfNullThrowException();
|
path = (await _dicomInstanceRepository.Where(s => s.StudyId == studyId).Select(t => t.Path).FirstOrDefaultAsync()).IfNullThrowException();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
using (var sw = ImageHelper.RenderPreviewJpeg(path))
|
using (var sw = ImageHelper.RenderPreviewJpeg(path))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,10 +5,8 @@
|
|||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
using IRaCIS.Core.Application.Interfaces;
|
using IRaCIS.Core.Application.Interfaces;
|
||||||
using IRaCIS.Core.Application.MediatR.Handlers;
|
|
||||||
using IRaCIS.Core.Application.ViewModel;
|
using IRaCIS.Core.Application.ViewModel;
|
||||||
using IRaCIS.Core.Infra.EFCore;
|
using IRaCIS.Core.Infra.EFCore;
|
||||||
using MediatR;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
namespace IRaCIS.Core.Application.Service
|
namespace IRaCIS.Core.Application.Service
|
||||||
{
|
{
|
||||||
@@ -18,12 +16,10 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
[ApiExplorerSettings(GroupName = "Image")]
|
[ApiExplorerSettings(GroupName = "Image")]
|
||||||
public class SystemAnonymizationService : BaseService, ISystemAnonymizationService
|
public class SystemAnonymizationService : BaseService, ISystemAnonymizationService
|
||||||
{
|
{
|
||||||
private readonly IMediator _mediator;
|
|
||||||
private readonly IRepository<SystemAnonymization> systemAnonymizationRepository;
|
private readonly IRepository<SystemAnonymization> systemAnonymizationRepository;
|
||||||
|
|
||||||
public SystemAnonymizationService(IMediator mediator, IRepository<SystemAnonymization> systemAnonymizationRepository)
|
public SystemAnonymizationService( IRepository<SystemAnonymization> systemAnonymizationRepository)
|
||||||
{
|
{
|
||||||
_mediator = mediator;
|
|
||||||
this.systemAnonymizationRepository = systemAnonymizationRepository;
|
this.systemAnonymizationRepository = systemAnonymizationRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +43,6 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
var entity = await _repository.InsertOrUpdateAsync<SystemAnonymization, SystemAnonymizationAddOrEdit>(addOrEditSystemAnonymization, true);
|
var entity = await _repository.InsertOrUpdateAsync<SystemAnonymization, SystemAnonymizationAddOrEdit>(addOrEditSystemAnonymization, true);
|
||||||
|
|
||||||
await _mediator.Send(new AnonymizeCacheRequest());
|
|
||||||
|
|
||||||
return ResponseOutput.Ok(entity.Id.ToString());
|
return ResponseOutput.Ok(entity.Id.ToString());
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Castle.Core.Internal;
|
using IRaCIS.Application.Contracts;
|
||||||
using IRaCIS.Application.Contracts;
|
|
||||||
using IRaCIS.Core.Application.Contracts;
|
using IRaCIS.Core.Application.Contracts;
|
||||||
using IRaCIS.Core.Application.Contracts.DTO;
|
using IRaCIS.Core.Application.Contracts.DTO;
|
||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using IRaCIS.Core.Application.Contracts;
|
|||||||
using IRaCIS.Core.Application.Service.Inspection.DTO;
|
using IRaCIS.Core.Application.Service.Inspection.DTO;
|
||||||
using IRaCIS.Core.Application.Service.Inspection.Interface;
|
using IRaCIS.Core.Application.Service.Inspection.Interface;
|
||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using IRaCIS.Core.Infra.EFCore.Common;
|
||||||
using IRaCIS.Core.Infrastructure;
|
using IRaCIS.Core.Infrastructure;
|
||||||
using Panda.DynamicWebApi.Attributes;
|
using Panda.DynamicWebApi.Attributes;
|
||||||
|
|
||||||
@@ -58,8 +59,11 @@ namespace IRaCIS.Core.Application.Service.Inspection
|
|||||||
join usertype in _repository.GetQueryable<UserType>().IgnoreQueryFilters() on leftuser.UserTypeId equals usertype.Id into usertypetemp
|
join usertype in _repository.GetQueryable<UserType>().IgnoreQueryFilters() on leftuser.UserTypeId equals usertype.Id into usertypetemp
|
||||||
from leftusertype in usertypetemp.DefaultIfEmpty()
|
from leftusertype in usertypetemp.DefaultIfEmpty()
|
||||||
|
|
||||||
//join trialCriterion in _repository.GetQueryable<ReadingQuestionCriterionTrial>().IgnoreQueryFilters() on data.TrialReadingCriterionId equals trialCriterion.Id into criterion
|
join visttask in _repository.GetQueryable<VisitTask>().IgnoreQueryFilters() on data.VisitTaskId equals visttask.Id into visttasktemp
|
||||||
//from leftCriterion in criterion.DefaultIfEmpty()
|
from leftvisttask in visttasktemp.DefaultIfEmpty()
|
||||||
|
|
||||||
|
//join trialCriterion in _repository.GetQueryable<ReadingQuestionCriterionTrial>().IgnoreQueryFilters() on data.TrialReadingCriterionId equals trialCriterion.Id into criterion
|
||||||
|
//from leftCriterion in criterion.DefaultIfEmpty()
|
||||||
|
|
||||||
//join moduleTyped in _repository.GetQueryable<Dictionary>().Where(x => x.Code == "ModuleType") on 1 equals 1
|
//join moduleTyped in _repository.GetQueryable<Dictionary>().Where(x => x.Code == "ModuleType") on 1 equals 1
|
||||||
//join moduleTypec in _repository.GetQueryable<Dictionary>() on new { ParentId = moduleTyped.Id, ModuleType = data.ModuleType } equals new { ParentId = moduleTypec.ParentId.Value, ModuleType = moduleTypec.Value } into moduleTypectemp
|
//join moduleTypec in _repository.GetQueryable<Dictionary>() on new { ParentId = moduleTyped.Id, ModuleType = data.ModuleType } equals new { ParentId = moduleTypec.ParentId.Value, ModuleType = moduleTypec.Value } into moduleTypectemp
|
||||||
@@ -131,7 +135,7 @@ namespace IRaCIS.Core.Application.Service.Inspection
|
|||||||
ExperimentName = leftrial.ExperimentName,
|
ExperimentName = leftrial.ExperimentName,
|
||||||
|
|
||||||
|
|
||||||
SubjectCode = leftsubject.Code,
|
SubjectCode = leftvisttask.BlindSubjectCode.IsNullOrEmpty()? leftsubject.Code: leftvisttask.BlindSubjectCode,
|
||||||
SiteCode = lefttrialSite.TrialSiteCode,
|
SiteCode = lefttrialSite.TrialSiteCode,
|
||||||
|
|
||||||
ResearchProgramNo = leftrial.ResearchProgramNo,
|
ResearchProgramNo = leftrial.ResearchProgramNo,
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user