Compare commits
107 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6f43535cf7 | |||
| 0697003b78 | |||
| e4b9a570d5 | |||
| 9f775df00c | |||
| 62757d7506 | |||
| 1822e201b7 | |||
| b25c72c153 | |||
| c64b826266 | |||
| fb2d2f7b2f | |||
| 92fe7bbaa9 | |||
| 75f4d5696a | |||
| 509f5ff2fc | |||
| 4f6a42aff5 | |||
| be42f52867 | |||
| 2519ad0f7a | |||
| ad4dcd294c | |||
| c251486267 | |||
| ee4fede7af | |||
| 92430c93b3 | |||
| d093c172a4 | |||
| 2740ed109a | |||
| 92facb02e8 | |||
| 718234f631 | |||
| 7be63f08b5 | |||
| 127e124993 | |||
| fbd9280b22 | |||
| b8481207fc | |||
| b1b82a016e | |||
| 768345616a | |||
| 1feb985eb7 | |||
| 496f47a4e8 | |||
| bd3d6ffe12 | |||
| 08daea6a92 | |||
| e9d720e1a5 | |||
| 5cd1454949 | |||
| d9a85b6825 | |||
| 424026866f | |||
| e5081ff568 | |||
| 3ca7d6f21b | |||
| 4faa15a219 | |||
| d61f4e89a3 | |||
| 712a1312f4 | |||
| e38739381e | |||
| ae05b73ffd | |||
| 87c9f423c9 | |||
| 2d44da15f1 | |||
| d7d7a0af55 | |||
| b3e187b53c | |||
| b0ef2dc8ab | |||
| ccf4bbdff9 | |||
| c3e36991b8 | |||
| 81f6c10f23 | |||
| 719ca071e1 | |||
| dad420a7e8 | |||
| d84aedf135 | |||
| 34f3b1607e | |||
| 7fa73e0054 | |||
| c146c2bfd2 | |||
| 2a1220899e | |||
| 874d36de28 | |||
| 0283052555 | |||
| effef5ad65 | |||
| 43d260e036 | |||
| 19708240b2 | |||
| 0999bae749 | |||
| e6bd35ae04 | |||
| 102e193ae8 | |||
| 20d557e795 | |||
| 593ab42882 | |||
| b56d256e10 | |||
| 614a3bd70e | |||
| 2eb3b04365 | |||
| 1fa3a5a181 | |||
| cd2007c4fd | |||
| 67e710eac0 | |||
| ef451d82ec | |||
| 899ebf2a30 | |||
| f233d27f96 | |||
| 9e8ab8acca | |||
| 2265387f47 | |||
| baf8f39bc6 | |||
| 3fa14d92ae | |||
| e6c577e68b | |||
| bb111dbbeb | |||
| 0df0b10a72 | |||
| 0a7ba9f0f5 | |||
| cd88990c32 | |||
| d53a1300fc | |||
| 07332ff3e1 | |||
| 8195a1cf3e | |||
| f5e5a47624 | |||
| 28608f3ecb | |||
| bb2da7ca81 | |||
| 713518a68c | |||
| bc448da297 | |||
| 8447878cb2 | |||
| 1b5a9673f6 | |||
| 27711f4184 | |||
| bb9bac1edf | |||
| 41ae2febc7 | |||
| c072c526e2 | |||
| d6bb98b84f | |||
| 42587ee59f | |||
| 62a964a3ea | |||
| 72447eb82f | |||
| 2f83c27fde | |||
| b219593f61 |
@@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Mvc;
|
|||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
using IRaCIS.Core.Infrastructure.Extention;
|
using IRaCIS.Core.Infrastructure.Extention;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Service.BusinessFilter
|
namespace IRaCIS.Application.Services.BusinessFilter
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 统一返回前端数据包装,之前在控制器包装,现在修改为动态Api 在ResultFilter这里包装,减少重复冗余代码
|
/// 统一返回前端数据包装,之前在控制器包装,现在修改为动态Api 在ResultFilter这里包装,减少重复冗余代码
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ 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 IRaCIS.Core.Application.Service;
|
using IRaCIS.Application.Services;
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using IRaCIS.Core.SCP.Service;
|
using IRaCIS.Core.SCP.Service;
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using IRaCIS.Core.Infra.EFCore;
|
|||||||
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;
|
||||||
|
|
||||||
@@ -16,12 +15,11 @@ namespace IRaCIS.Core.SCP
|
|||||||
{
|
{
|
||||||
services.AddHttpContextAccessor();
|
services.AddHttpContextAccessor();
|
||||||
services.AddScoped<IUserInfo, UserInfo>();
|
services.AddScoped<IUserInfo, UserInfo>();
|
||||||
services.AddScoped<ISaveChangesInterceptor, AuditEntityInterceptor>();
|
|
||||||
|
|
||||||
|
|
||||||
//这个注入没有成功--注入是没问题的,构造函数也只是支持参数就好,错在注入的地方不能写DbContext
|
//这个注入没有成功--注入是没问题的,构造函数也只是支持参数就好,错在注入的地方不能写DbContext
|
||||||
//Web程序中通过重用池中DbContext实例可提高高并发场景下的吞吐量, 这在概念上类似于ADO.NET Provider原生的连接池操作方式,具有节省DbContext实例化成本的优点
|
//Web程序中通过重用池中DbContext实例可提高高并发场景下的吞吐量, 这在概念上类似于ADO.NET Provider原生的连接池操作方式,具有节省DbContext实例化成本的优点
|
||||||
services.AddDbContext<IRaCISDBContext>((sp, options) =>
|
services.AddDbContextPool<IRaCISDBContext>(options =>
|
||||||
{
|
{
|
||||||
// 在控制台
|
// 在控制台
|
||||||
//public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); });
|
//public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); });
|
||||||
@@ -37,7 +35,6 @@ namespace IRaCIS.Core.SCP
|
|||||||
options.EnableSensitiveDataLogging();
|
options.EnableSensitiveDataLogging();
|
||||||
|
|
||||||
options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor());
|
options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor());
|
||||||
options.AddInterceptors(sp.GetServices<ISaveChangesInterceptor>());
|
|
||||||
|
|
||||||
options.UseProjectables();
|
options.UseProjectables();
|
||||||
|
|
||||||
|
|||||||
@@ -7,28 +7,27 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.1.4" />
|
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.13.0" />
|
||||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" />
|
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="9.0.0" />
|
||||||
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" />
|
<PackageReference Include="DistributedLock.Core" Version="1.0.6" />
|
||||||
<PackageReference Include="AWSSDK.S3" Version="3.7.402.7" />
|
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.4" />
|
||||||
<PackageReference Include="AWSSDK.SecurityToken" Version="3.7.400.16" />
|
<PackageReference Include="fo-dicom" Version="5.1.2" />
|
||||||
<PackageReference Include="DistributedLock.Core" Version="1.0.7" />
|
<PackageReference Include="fo-dicom.Codecs" Version="5.12.0" />
|
||||||
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.5" />
|
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.1.2" />
|
||||||
<PackageReference Include="fo-dicom" Version="5.1.3" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.4" />
|
||||||
<PackageReference Include="fo-dicom.Codecs" Version="5.14.5" />
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.20.1" />
|
||||||
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.1.3" />
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.8" />
|
|
||||||
<PackageReference Include="AutoMapper" Version="13.0.1" />
|
<PackageReference Include="AutoMapper" Version="13.0.1" />
|
||||||
<PackageReference Include="Minio" Version="6.0.3" />
|
<PackageReference Include="Minio" Version="6.0.2" />
|
||||||
<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="NewId" Version="4.0.1" />
|
||||||
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" />
|
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" />
|
||||||
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.1.1" />
|
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.0.3" />
|
||||||
<PackageReference Include="Serilog.Extensions.Hosting" Version="8.0.0" />
|
<PackageReference Include="Serilog.Extensions.Hosting" Version="8.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
|
||||||
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.7.3" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ builder.Services.AddJsonLocalization(options => options.ResourcesPath = "Resourc
|
|||||||
// 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim()
|
// 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim()
|
||||||
builder.Services.AddControllers(options =>
|
builder.Services.AddControllers(options =>
|
||||||
{
|
{
|
||||||
|
//options.Filters.Add<LogActionFilter>();
|
||||||
options.Filters.Add<ModelActionFilter>();
|
options.Filters.Add<ModelActionFilter>();
|
||||||
options.Filters.Add<ProjectExceptionFilter>();
|
options.Filters.Add<ProjectExceptionFilter>();
|
||||||
options.Filters.Add<UnitOfWorkFilter>();
|
options.Filters.Add<UnitOfWorkFilter>();
|
||||||
@@ -113,11 +114,6 @@ builder.Services.AddAutoMapper(automapper =>
|
|||||||
//EF ORM QueryWithNoLock
|
//EF ORM QueryWithNoLock
|
||||||
builder.Services.AddEFSetup(_configuration);
|
builder.Services.AddEFSetup(_configuration);
|
||||||
|
|
||||||
builder.Services.AddMediator(cfg =>
|
|
||||||
{
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
//转发头设置 获取真实IP
|
//转发头设置 获取真实IP
|
||||||
builder.Services.Configure<ForwardedHeadersOptions>(options =>
|
builder.Services.Configure<ForwardedHeadersOptions>(options =>
|
||||||
|
|||||||
@@ -10,16 +10,5 @@
|
|||||||
"environmentVariables": {
|
"environmentVariables": {
|
||||||
"ASPNETCORE_ENVIRONMENT": "Test_IRC_SCP"
|
"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"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using IRaCIS.Core.Application.Service.BusinessFilter;
|
using IRaCIS.Application.Services.BusinessFilter;
|
||||||
using IRaCIS.Core.Infra.EFCore;
|
using IRaCIS.Core.Infra.EFCore;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
@@ -26,6 +26,7 @@ namespace IRaCIS.Core.SCP.Service
|
|||||||
|
|
||||||
public IUserInfo _userInfo { get; set; }
|
public IUserInfo _userInfo { get; set; }
|
||||||
|
|
||||||
|
public IRepository _repository { get; set; }
|
||||||
|
|
||||||
public IStringLocalizer _localizer { get; set; }
|
public IStringLocalizer _localizer { get; set; }
|
||||||
|
|
||||||
@@ -50,6 +51,9 @@ namespace IRaCIS.Core.SCP.Service
|
|||||||
[MemberNotNull(nameof(_userInfo))]
|
[MemberNotNull(nameof(_userInfo))]
|
||||||
public IUserInfo _userInfo { get; set; }
|
public IUserInfo _userInfo { get; set; }
|
||||||
|
|
||||||
|
[MemberNotNull(nameof(_repository))]
|
||||||
|
public IRepository _repository { get; set; }
|
||||||
|
|
||||||
[MemberNotNull(nameof(_localizer))]
|
[MemberNotNull(nameof(_localizer))]
|
||||||
public IStringLocalizer _localizer { get; set; }
|
public IStringLocalizer _localizer { get; set; }
|
||||||
|
|
||||||
@@ -71,7 +75,8 @@ namespace IRaCIS.Core.SCP.Service
|
|||||||
[MemberNotNull(nameof(_userInfo))]
|
[MemberNotNull(nameof(_userInfo))]
|
||||||
public IUserInfo _userInfo { get; set; }
|
public IUserInfo _userInfo { get; set; }
|
||||||
|
|
||||||
|
[MemberNotNull(nameof(_repository))]
|
||||||
|
public IRepository _repository { get; set; }
|
||||||
|
|
||||||
[MemberNotNull(nameof(_localizer))]
|
[MemberNotNull(nameof(_localizer))]
|
||||||
public IStringLocalizer _localizer { get; set; }
|
public IStringLocalizer _localizer { get; set; }
|
||||||
@@ -88,6 +93,8 @@ namespace IRaCIS.Core.SCP.Service
|
|||||||
|
|
||||||
public IUserInfo _userInfo { get; set; }
|
public IUserInfo _userInfo { get; set; }
|
||||||
|
|
||||||
|
public IRepository _repository { get; set; }
|
||||||
|
|
||||||
public IStringLocalizer _localizer { get; set; }
|
public IStringLocalizer _localizer { get; set; }
|
||||||
|
|
||||||
public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class
|
public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class
|
||||||
|
|||||||
@@ -176,13 +176,6 @@ namespace IRaCIS.Core.SCP.Service
|
|||||||
|
|
||||||
await _SCPImageUploadRepository.AddAsync(_upload, true);
|
await _SCPImageUploadRepository.AddAsync(_upload, true);
|
||||||
|
|
||||||
|
|
||||||
var _studyRepository = _serviceProvider.GetService<IRepository<SCPStudy>>();
|
|
||||||
//将检查设置为传输结束
|
|
||||||
await _studyRepository.BatchUpdateNoTrackingAsync(t => _SCPStudyIdList.Contains(t.Id), u => new SCPStudy() { IsUploadFinished = true });
|
|
||||||
|
|
||||||
await _studyRepository.SaveChangesAndClearAllTrackingAsync();
|
|
||||||
|
|
||||||
await SendAssociationReleaseResponseAsync();
|
await SendAssociationReleaseResponseAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,11 +236,11 @@ namespace IRaCIS.Core.SCP.Service
|
|||||||
//奇怪的bug 上传的时候,用王捷修改的影像,会关闭,重新连接,导致检查id 丢失,然后状态不一致
|
//奇怪的bug 上传的时候,用王捷修改的影像,会关闭,重新连接,导致检查id 丢失,然后状态不一致
|
||||||
if (exception == null)
|
if (exception == null)
|
||||||
{
|
{
|
||||||
//var _studyRepository = _serviceProvider.GetService<IRepository<SCPStudy>>();
|
var _studyRepository = _serviceProvider.GetService<IRepository<SCPStudy>>();
|
||||||
////将检查设置为传输结束
|
//将检查设置为传输结束
|
||||||
//await _studyRepository.BatchUpdateNoTrackingAsync(t => _SCPStudyIdList.Contains(t.Id), u => new SCPStudy() { IsUploadFinished = true });
|
await _studyRepository.BatchUpdateNoTrackingAsync(t => _SCPStudyIdList.Contains(t.Id), u => new SCPStudy() { IsUploadFinished = true });
|
||||||
|
|
||||||
//await _studyRepository.SaveChangesAndClearAllTrackingAsync();
|
await _studyRepository.SaveChangesAndClearAllTrackingAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Logger.Warning($"连接关闭 {exception?.Message} {exception?.InnerException?.Message}");
|
Log.Logger.Warning($"连接关闭 {exception?.Message} {exception?.InnerException?.Message}");
|
||||||
@@ -308,7 +301,7 @@ namespace IRaCIS.Core.SCP.Service
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var scpStudyId = await dicomArchiveService.ArchiveDicomFileAsync(request.Dataset, _trialId, _trialSiteId, storeRelativePath, Association.CallingAE, Association.CalledAE,fileSize);
|
var scpStudyId = await dicomArchiveService.ArchiveDicomFileAsync(request.Dataset, _trialId, _trialSiteId, storeRelativePath, Association.CallingAE, Association.CalledAE);
|
||||||
|
|
||||||
if (!_SCPStudyIdList.Contains(scpStudyId))
|
if (!_SCPStudyIdList.Contains(scpStudyId))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ using IRaCIS.Core.SCP.Service;
|
|||||||
using IRaCIS.Core.Infra.EFCore;
|
using IRaCIS.Core.Infra.EFCore;
|
||||||
using MassTransit;
|
using MassTransit;
|
||||||
using System.Runtime.Intrinsics.X86;
|
using System.Runtime.Intrinsics.X86;
|
||||||
using Serilog.Sinks.File;
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.SCP.Service
|
namespace IRaCIS.Core.SCP.Service
|
||||||
{
|
{
|
||||||
@@ -52,7 +51,7 @@ namespace IRaCIS.Core.SCP.Service
|
|||||||
/// <param name="dataset"></param>
|
/// <param name="dataset"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
/// <exception cref="NotImplementedException"></exception>
|
/// <exception cref="NotImplementedException"></exception>
|
||||||
public async Task<Guid> ArchiveDicomFileAsync(DicomDataset dataset, Guid trialId, Guid trialSiteId, string fileRelativePath, string callingAE, string calledAE,long fileSize)
|
public async Task<Guid> ArchiveDicomFileAsync(DicomDataset dataset, Guid trialId, Guid trialSiteId, string fileRelativePath, string callingAE, string calledAE)
|
||||||
{
|
{
|
||||||
string studyInstanceUid = dataset.GetString(DicomTag.StudyInstanceUID);
|
string studyInstanceUid = dataset.GetString(DicomTag.StudyInstanceUID);
|
||||||
string seriesInstanceUid = dataset.GetString(DicomTag.SeriesInstanceUID);
|
string seriesInstanceUid = dataset.GetString(DicomTag.SeriesInstanceUID);
|
||||||
@@ -271,10 +270,7 @@ namespace IRaCIS.Core.SCP.Service
|
|||||||
WindowCenter = dataset.GetSingleValueOrDefault(DicomTag.WindowCenter, string.Empty),
|
WindowCenter = dataset.GetSingleValueOrDefault(DicomTag.WindowCenter, string.Empty),
|
||||||
WindowWidth = dataset.GetSingleValueOrDefault(DicomTag.WindowWidth, string.Empty),
|
WindowWidth = dataset.GetSingleValueOrDefault(DicomTag.WindowWidth, string.Empty),
|
||||||
|
|
||||||
Path = fileRelativePath,
|
Path = fileRelativePath
|
||||||
|
|
||||||
FileSize= fileSize,
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
++findStudy.InstanceCount;
|
++findStudy.InstanceCount;
|
||||||
@@ -304,7 +300,7 @@ namespace IRaCIS.Core.SCP.Service
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await _instanceRepository.BatchUpdateNoTrackingAsync(t => t.Id == instanceId, u => new SCPInstance() { Path = fileRelativePath,FileSize=fileSize });
|
await _instanceRepository.BatchUpdateNoTrackingAsync(t => t.Id == instanceId, u => new SCPInstance() { Path = fileRelativePath });
|
||||||
}
|
}
|
||||||
|
|
||||||
//await _studyRepository.SaveChangesAsync();
|
//await _studyRepository.SaveChangesAsync();
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace IRaCIS.Core.SCP.Service
|
|||||||
{
|
{
|
||||||
public interface IDicomArchiveService
|
public interface IDicomArchiveService
|
||||||
{
|
{
|
||||||
Task<Guid> ArchiveDicomFileAsync(DicomDataset dicomDataset,Guid trialId,Guid trialSiteId, string fileRelativePath,string callingAE,string calledAE,long fileSize);
|
Task<Guid> ArchiveDicomFileAsync(DicomDataset dicomDataset,Guid trialId,Guid trialSiteId, string fileRelativePath,string callingAE,string calledAE);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+364
-692
File diff suppressed because it is too large
Load Diff
@@ -9,29 +9,54 @@
|
|||||||
"ObjectStoreService": {
|
"ObjectStoreService": {
|
||||||
"ObjectStoreUse": "AliyunOSS",
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
"AliyunOSS": {
|
"AliyunOSS": {
|
||||||
"RegionId": "cn-shanghai",
|
"regionId": "cn-shanghai",
|
||||||
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
"AccessKeyId": "LTAI5tNRTsqL6aWmHkDmTwoH",
|
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||||
"AccessKeySecret": "7mtGz3qrYWI6JMMBZiLeC119VWicZH",
|
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||||
"RoleArn": "acs:ram::1899121822495495:role/irc-oss-access",
|
"bucketName": "zy-irc-store",
|
||||||
"BucketName": "zy-irc-store",
|
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
||||||
"ViewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com",
|
"viewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com",
|
||||||
"Region": "oss-cn-shanghai",
|
"region": "oss-cn-shanghai"
|
||||||
"DurationSeconds": 7200
|
},
|
||||||
|
|
||||||
|
"MinIO": {
|
||||||
|
"endpoint": "http://192.168.3.68",
|
||||||
|
"port": "8001",
|
||||||
|
"useSSL": false,
|
||||||
|
"accessKey": "IDFkwEpWej0b4DtiuThL",
|
||||||
|
"secretKey": "Lhuu83yMhVwu7c1SnjvGY6lq74jzpYqifK6Qtj4h",
|
||||||
|
"bucketName": "test"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"RemoteNew": "Server=prod_mssql_standard,1433;Database=Prod_IRC;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true",
|
"RemoteNew": "Server=us-prod-mssql-service,1433;Database=US_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||||
"Hangfire": "Server=prod_mssql_standard,1433;Database=Prod_IRC_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true"
|
"Hangfire": "Server=us-prod-mssql-service,1433;Database=US_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||||
},
|
},
|
||||||
|
|
||||||
"DicomSCPServiceConfig": {
|
"BasicSystemConfig": {
|
||||||
"CalledAEList": [
|
|
||||||
"STORESCP"
|
"OpenUserComplexPassword": true,
|
||||||
],
|
|
||||||
"ServerPort": 11112
|
"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"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,22 +6,48 @@
|
|||||||
"Microsoft.Hosting.Lifetime": "Information"
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
<<<<<<<< HEAD:IRaCIS.Core.API/appsettings.US_Test_IRC.json
|
||||||
|
"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",
|
||||||
|
========
|
||||||
"ObjectStoreService": {
|
"ObjectStoreService": {
|
||||||
"ObjectStoreUse": "AliyunOSS",
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
|
>>>>>>>> Test_IRC_Net8:IRC.Core.SCP/appsettings.Test_IRC_SCP.json
|
||||||
"AliyunOSS": {
|
"AliyunOSS": {
|
||||||
"RegionId": "cn-shanghai",
|
"regionId": "cn-shanghai",
|
||||||
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
"endPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
|
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||||
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
|
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||||
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
|
"bucketName": "zy-irc-test-store",
|
||||||
"BucketName": "zy-irc-test-store",
|
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
||||||
"ViewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
|
"viewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
|
||||||
"Region": "oss-cn-shanghai",
|
"region": "oss-cn-shanghai"
|
||||||
"DurationSeconds": 7200
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"MinIO": {
|
"MinIO": {
|
||||||
|
<<<<<<<< HEAD:IRaCIS.Core.API/appsettings.US_Test_IRC.json
|
||||||
|
//"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"
|
||||||
|
|
||||||
|
========
|
||||||
"endPoint": "106.14.89.110",
|
"endPoint": "106.14.89.110",
|
||||||
"port": "9001",
|
"port": "9001",
|
||||||
"useSSL": false,
|
"useSSL": false,
|
||||||
@@ -29,20 +55,80 @@
|
|||||||
"secretKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
|
"secretKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
|
||||||
"bucketName": "hir-test",
|
"bucketName": "hir-test",
|
||||||
"viewEndpoint": "http://106.14.89.110:9001/hir-test/"
|
"viewEndpoint": "http://106.14.89.110:9001/hir-test/"
|
||||||
}
|
>>>>>>>> Test_IRC_Net8:IRC.Core.SCP/appsettings.Test_IRC_SCP.json
|
||||||
|
},
|
||||||
|
|
||||||
|
"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": {
|
"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"
|
||||||
},
|
},
|
||||||
|
"BasicSystemConfig": {
|
||||||
|
|
||||||
|
"OpenUserComplexPassword": false,
|
||||||
|
|
||||||
|
"OpenSignDocumentBeforeWork": false,
|
||||||
|
|
||||||
|
"OpenTrialRelationDelete": true,
|
||||||
|
|
||||||
|
"OpenLoginLimit": false,
|
||||||
|
"LoginMaxFailCount": 5,
|
||||||
|
|
||||||
|
<<<<<<<< HEAD:IRaCIS.Core.API/appsettings.US_Test_IRC.json
|
||||||
|
"LoginFailLockMinutes": 30,
|
||||||
|
"AutoLoginOutMinutes": 60,
|
||||||
|
|
||||||
|
"ContinuousReadingTimeMin": 120,
|
||||||
|
|
||||||
|
"ReadingRestTimeMin": 10
|
||||||
|
},
|
||||||
|
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
========
|
||||||
|
"LoginFailLockMinutes": 30
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
"SystemEmailSendConfig": {
|
||||||
|
"Port": 465,
|
||||||
|
"Host": "smtp.qiye.aliyun.com",
|
||||||
|
"FromEmail": "test-study@extimaging.com",
|
||||||
|
"FromName": "Test_Study",
|
||||||
|
"AuthorizationCode": "zhanying123",
|
||||||
|
>>>>>>>> Test_IRC_Net8:IRC.Core.SCP/appsettings.Test_IRC_SCP.json
|
||||||
|
|
||||||
|
"SiteUrl": "http://study.test.extimaging.com/login"
|
||||||
|
},
|
||||||
"DicomSCPServiceConfig": {
|
"DicomSCPServiceConfig": {
|
||||||
"CalledAEList": [
|
"CalledAEList": [
|
||||||
"STORESCP"
|
"STORESCP",
|
||||||
|
"Value1",
|
||||||
|
"Value2",
|
||||||
|
"Value3"
|
||||||
],
|
],
|
||||||
"ServerPort": 11112
|
"ServerPort": 11112
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"Logging": {
|
|
||||||
"LogLevel": {
|
|
||||||
"Default": "Information",
|
|
||||||
"Microsoft": "Warning",
|
|
||||||
"Microsoft.Hosting.Lifetime": "Information"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ObjectStoreService": {
|
|
||||||
"ObjectStoreUse": "AWS",
|
|
||||||
"AWS": {
|
|
||||||
"Region": "us-east-1",
|
|
||||||
"EndPoint": "s3.us-east-1.amazonaws.com",
|
|
||||||
"UseSSL": true,
|
|
||||||
"RoleArn": "arn:aws:iam::471112624751:role/lili_s3_access",
|
|
||||||
"AccessKeyId": "AKIAW3MEAFJXZ2TZK7GM",
|
|
||||||
"SecretAccessKey": "9MLQCQ1HifEVW1gf068zBRAOb4wNnfrOkvBVByth",
|
|
||||||
"BucketName": "ei-med-s3-lili-store",
|
|
||||||
"ViewEndpoint": "https://ei-med-s3-lili-store.s3.amazonaws.com",
|
|
||||||
"DurationSeconds": 7200
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"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"
|
|
||||||
},
|
|
||||||
"DicomSCPServiceConfig": {
|
|
||||||
"CalledAEList": [
|
|
||||||
"STORESCP"
|
|
||||||
],
|
|
||||||
"ServerPort": 11112
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"Logging": {
|
|
||||||
"LogLevel": {
|
|
||||||
"Default": "Information",
|
|
||||||
"Microsoft": "Warning",
|
|
||||||
"Microsoft.Hosting.Lifetime": "Information"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ObjectStoreService": {
|
|
||||||
"ObjectStoreUse": "AWS",
|
|
||||||
"AWS": {
|
|
||||||
"Region": "us-east-1",
|
|
||||||
"EndPoint": "s3.us-east-1.amazonaws.com",
|
|
||||||
"UseSSL": true,
|
|
||||||
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
|
|
||||||
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
|
|
||||||
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
|
|
||||||
"BucketName": "ei-med-s3-lili-uat-store",
|
|
||||||
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com/",
|
|
||||||
"DurationSeconds": 7200
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"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"
|
|
||||||
},
|
|
||||||
"DicomSCPServiceConfig": {
|
|
||||||
"CalledAEList": [
|
|
||||||
"STORESCP"
|
|
||||||
],
|
|
||||||
"ServerPort": 11112
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -7,29 +7,61 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ObjectStoreService": {
|
"ObjectStoreService": {
|
||||||
"ObjectStoreUse": "AliyunOSS",
|
"ObjectStoreUse": "MinIO",
|
||||||
"AliyunOSS": {
|
"AliyunOSS": {
|
||||||
"RegionId": "cn-shanghai",
|
"regionId": "cn-shanghai",
|
||||||
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
|
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||||
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
|
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||||
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
|
"bucketName": "zy-irc-uat-store",
|
||||||
"BucketName": "zy-irc-uat-store",
|
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
||||||
"ViewEndpoint": "https://zy-irc-uat-store.oss-cn-shanghai.aliyuncs.com",
|
"viewEndpoint": "https://zy-irc-uat-store.oss-cn-shanghai.aliyuncs.com",
|
||||||
"Region": "oss-cn-shanghai",
|
"region": "oss-cn-shanghai"
|
||||||
"DurationSeconds": 7200
|
},
|
||||||
|
|
||||||
|
"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": {
|
"ConnectionStrings": {
|
||||||
"RemoteNew": "Server=47.117.164.182,1434;Database=Uat_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
"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"
|
"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": {
|
"DicomSCPServiceConfig": {
|
||||||
"CalledAEList": [
|
"CalledAEList": [
|
||||||
"STORESCP"
|
"STORESCP",
|
||||||
|
"Value1",
|
||||||
|
"Value2",
|
||||||
|
"Value3"
|
||||||
],
|
],
|
||||||
"ServerPort": 11112
|
"ServerPort": 11112
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -17,7 +17,7 @@ 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("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRC.Core.SCP", "IRC.Core.SCP\IRC.Core.SCP.csproj", "{ECD08F47-DC1A-484E-BB91-6CDDC8823CC5}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IRC.Core.SCP", "IRC.Core.SCP\IRC.Core.SCP.csproj", "{ECD08F47-DC1A-484E-BB91-6CDDC8823CC5}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
|||||||
@@ -0,0 +1,99 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace EFSaving.Concurrency
|
||||||
|
{
|
||||||
|
public class Sample
|
||||||
|
{
|
||||||
|
public static void Run()
|
||||||
|
{
|
||||||
|
// Ensure database is created and has a person in it
|
||||||
|
using (var setupContext = new PersonContext())
|
||||||
|
{
|
||||||
|
setupContext.Database.EnsureDeleted();
|
||||||
|
setupContext.Database.EnsureCreated();
|
||||||
|
|
||||||
|
setupContext.People.Add(new Person { FirstName = "John", LastName = "Doe" });
|
||||||
|
setupContext.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region ConcurrencyHandlingCode
|
||||||
|
using var context = new PersonContext();
|
||||||
|
// Fetch a person from database and change phone number
|
||||||
|
var person = context.People.Single(p => p.PersonId == 1);
|
||||||
|
person.PhoneNumber = "555-555-5555";
|
||||||
|
|
||||||
|
// Change the person's name in the database to simulate a concurrency conflict
|
||||||
|
context.Database.ExecuteSqlRaw(
|
||||||
|
"UPDATE dbo.People SET FirstName = 'Jane' WHERE PersonId = 1");
|
||||||
|
|
||||||
|
var saved = false;
|
||||||
|
while (!saved)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Attempt to save changes to the database
|
||||||
|
context.SaveChanges();
|
||||||
|
saved = true;
|
||||||
|
}
|
||||||
|
catch (DbUpdateConcurrencyException ex)
|
||||||
|
{
|
||||||
|
foreach (var entry in ex.Entries)
|
||||||
|
{
|
||||||
|
if (entry.Entity is Person)
|
||||||
|
{
|
||||||
|
var proposedValues = entry.CurrentValues;
|
||||||
|
var databaseValues = entry.GetDatabaseValues();
|
||||||
|
|
||||||
|
foreach (var property in proposedValues.Properties)
|
||||||
|
{
|
||||||
|
var proposedValue = proposedValues[property];
|
||||||
|
var databaseValue = databaseValues[property];
|
||||||
|
|
||||||
|
// TODO: decide which value should be written to database
|
||||||
|
// proposedValues[property] = <value to be saved>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Refresh original values to bypass next concurrency check
|
||||||
|
entry.OriginalValues.SetValues(databaseValues);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new NotSupportedException(
|
||||||
|
"Don't know how to handle concurrency conflicts for "
|
||||||
|
+ entry.Metadata.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PersonContext : DbContext
|
||||||
|
{
|
||||||
|
public DbSet<Person> People { get; set; }
|
||||||
|
|
||||||
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
|
{
|
||||||
|
// Requires NuGet package Microsoft.EntityFrameworkCore.SqlServer
|
||||||
|
optionsBuilder.UseSqlServer(
|
||||||
|
@"Server=(localdb)\mssqllocaldb;Database=EFSaving.Concurrency;Trusted_Connection=True");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Person
|
||||||
|
{
|
||||||
|
public int PersonId { get; set; }
|
||||||
|
|
||||||
|
[ConcurrencyCheck]
|
||||||
|
public string FirstName { get; set; }
|
||||||
|
|
||||||
|
[ConcurrencyCheck]
|
||||||
|
public string LastName { get; set; }
|
||||||
|
|
||||||
|
public string PhoneNumber { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using EasyCaching.Core;
|
||||||
using IRaCIS.Application.Interfaces;
|
using IRaCIS.Application.Interfaces;
|
||||||
using IRaCIS.Application.Contracts;
|
using IRaCIS.Application.Contracts;
|
||||||
using IRaCIS.Core.Application.Auth;
|
using IRaCIS.Core.Application.Auth;
|
||||||
@@ -14,7 +15,7 @@ using System.Text;
|
|||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using IRaCIS.Core.Application.Interfaces;
|
using IRaCIS.Core.Application.Interfaces;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using IRaCIS.Core.Application.Service;
|
using IRaCIS.Application.Services;
|
||||||
using IRaCIS.Core.Infra.EFCore;
|
using IRaCIS.Core.Infra.EFCore;
|
||||||
using IRaCIS.Core.Domain.Models;
|
using IRaCIS.Core.Domain.Models;
|
||||||
using IRaCIS.Core.Infrastructure;
|
using IRaCIS.Core.Infrastructure;
|
||||||
@@ -22,6 +23,9 @@ using System.Linq;
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using MassTransit;
|
using MassTransit;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Aliyun.Acs.Core.Profile;
|
||||||
|
using Aliyun.Acs.Core.Auth.Sts;
|
||||||
|
using Aliyun.Acs.Core;
|
||||||
using IRaCIS.Core.Application.Helper;
|
using IRaCIS.Core.Application.Helper;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using IRaCIS.Core.Application.Contracts;
|
using IRaCIS.Core.Application.Contracts;
|
||||||
@@ -29,15 +33,6 @@ using LoginReturnDTO = IRaCIS.Application.Contracts.LoginReturnDTO;
|
|||||||
using DocumentFormat.OpenXml.Spreadsheet;
|
using DocumentFormat.OpenXml.Spreadsheet;
|
||||||
using AutoMapper.QueryableExtensions;
|
using AutoMapper.QueryableExtensions;
|
||||||
using NetTopologySuite.Algorithm;
|
using NetTopologySuite.Algorithm;
|
||||||
using ZiggyCreatures.Caching.Fusion;
|
|
||||||
using AlibabaCloud.SDK.Sts20150401;
|
|
||||||
using AlibabaCloud.SDK.Sts20150401.Models;
|
|
||||||
using Org.BouncyCastle.Tls;
|
|
||||||
using Amazon.SecurityToken.Model;
|
|
||||||
using Amazon.SecurityToken;
|
|
||||||
using Amazon;
|
|
||||||
using AssumeRoleRequest = Amazon.SecurityToken.Model.AssumeRoleRequest;
|
|
||||||
using AutoMapper;
|
|
||||||
|
|
||||||
namespace IRaCIS.Api.Controllers
|
namespace IRaCIS.Api.Controllers
|
||||||
{
|
{
|
||||||
@@ -105,17 +100,13 @@ namespace IRaCIS.Api.Controllers
|
|||||||
[HttpPost, Route("user/login")]
|
[HttpPost, Route("user/login")]
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
public async Task<IResponseOutput> Login(UserLoginDTO loginUser,
|
public async Task<IResponseOutput> Login(UserLoginDTO loginUser,
|
||||||
[FromServices] IFusionCache _fusionCache,
|
[FromServices] IEasyCachingProvider provider,
|
||||||
[FromServices] IUserService _userService,
|
[FromServices] IUserService _userService,
|
||||||
[FromServices] ITokenService _tokenService,
|
[FromServices] ITokenService _tokenService,
|
||||||
[FromServices] IReadingImageTaskService readingImageTaskService,
|
[FromServices] IReadingImageTaskService readingImageTaskService,
|
||||||
[FromServices] IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig,
|
IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig,
|
||||||
[FromServices] IOptionsMonitor<SystemEmailSendConfig> _emailConfig,
|
IMailVerificationService _mailVerificationService)
|
||||||
|
|
||||||
[FromServices] IMailVerificationService _mailVerificationService)
|
|
||||||
{
|
{
|
||||||
var emailConfig = _emailConfig.CurrentValue;
|
|
||||||
var companyInfo = new SystemEmailSendConfigView() { CompanyName = emailConfig.CompanyName, CompanyNameCN = emailConfig.CompanyNameCN, CompanyShortName = emailConfig.CompanyShortName, CompanyShortNameCN = emailConfig.CompanyShortNameCN };
|
|
||||||
|
|
||||||
//MFA 邮箱验证 前端传递用户Id 和MFACode
|
//MFA 邮箱验证 前端传递用户Id 和MFACode
|
||||||
if (loginUser.UserId != null && _verifyConfig.CurrentValue.OpenLoginMFA)
|
if (loginUser.UserId != null && _verifyConfig.CurrentValue.OpenLoginMFA)
|
||||||
@@ -148,11 +139,10 @@ namespace IRaCIS.Api.Controllers
|
|||||||
// 验证阅片休息时间
|
// 验证阅片休息时间
|
||||||
await readingImageTaskService.ResetReadingRestTime(userId);
|
await readingImageTaskService.ResetReadingRestTime(userId);
|
||||||
|
|
||||||
await _fusionCache.SetAsync(CacheKeys.UserToken(userId), loginReturn.JWTStr, TimeSpan.FromDays(7));
|
await provider.SetAsync(userId.ToString(), loginReturn.JWTStr, TimeSpan.FromDays(7));
|
||||||
|
|
||||||
await _fusionCache.SetAsync(CacheKeys.UserAutoLoginOut(userId), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(_verifyConfig.CurrentValue.AutoLoginOutMinutes));
|
await provider.SetAsync($"{userId.ToString()}_Online", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(_verifyConfig.CurrentValue.AutoLoginOutMinutes));
|
||||||
|
|
||||||
loginReturn.CompanyInfo = companyInfo;
|
|
||||||
return ResponseOutput.Ok(loginReturn);
|
return ResponseOutput.Ok(loginReturn);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -227,9 +217,9 @@ namespace IRaCIS.Api.Controllers
|
|||||||
|
|
||||||
if (_verifyConfig.CurrentValue.OpenLoginMFA)
|
if (_verifyConfig.CurrentValue.OpenLoginMFA)
|
||||||
{
|
{
|
||||||
|
//发版屏蔽
|
||||||
|
|
||||||
|
//returnModel.Data.JWTStr = _tokenService.GetToken(IRaCISClaims.Create(returnModel.Data.BasicInfo));
|
||||||
|
|
||||||
|
|
||||||
//MFA 发送邮件
|
//MFA 发送邮件
|
||||||
|
|
||||||
@@ -237,21 +227,11 @@ namespace IRaCIS.Api.Controllers
|
|||||||
|
|
||||||
var email = returnModel.Data.BasicInfo.EMail;
|
var email = returnModel.Data.BasicInfo.EMail;
|
||||||
|
|
||||||
var hiddenEmail = IRCEmailPasswordHelper.MaskEmail(email);
|
var hiddenEmail = EmailMaskHelper.MaskEmail(email);
|
||||||
|
|
||||||
returnModel.Data.BasicInfo.EMail = hiddenEmail;
|
returnModel.Data.BasicInfo.EMail = hiddenEmail;
|
||||||
|
|
||||||
//修改密码
|
await _userService.SendMFAEmail(userId);
|
||||||
if (returnModel.Data.BasicInfo.IsFirstAdd || returnModel.Data.BasicInfo.LoginState == 1)
|
|
||||||
{
|
|
||||||
returnModel.Data.JWTStr = _tokenService.GetToken(IRaCISClaims.Create(returnModel.Data.BasicInfo));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//正常登录才发送邮件
|
|
||||||
await _userService.SendMFAEmail(userId);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -274,14 +254,12 @@ namespace IRaCIS.Api.Controllers
|
|||||||
// 验证阅片休息时间
|
// 验证阅片休息时间
|
||||||
await readingImageTaskService.ResetReadingRestTime(returnModel.Data.BasicInfo.Id);
|
await readingImageTaskService.ResetReadingRestTime(returnModel.Data.BasicInfo.Id);
|
||||||
|
|
||||||
await _fusionCache.SetAsync(CacheKeys.UserToken(userId), returnModel.Data.JWTStr, TimeSpan.FromDays(7));
|
await provider.SetAsync(userId.ToString(), returnModel.Data.JWTStr, TimeSpan.FromDays(7));
|
||||||
|
|
||||||
await _fusionCache.SetAsync(CacheKeys.UserAutoLoginOut(userId), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(_verifyConfig.CurrentValue.AutoLoginOutMinutes));
|
await provider.SetAsync($"{userId.ToString()}_Online", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(_verifyConfig.CurrentValue.AutoLoginOutMinutes));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
returnModel.Data.CompanyInfo = companyInfo;
|
|
||||||
return returnModel;
|
return returnModel;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -291,14 +269,8 @@ namespace IRaCIS.Api.Controllers
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[AllowAnonymous]
|
|
||||||
[HttpGet, Route("user/getPublicKey")]
|
|
||||||
public IResponseOutput GetPublicKey([FromServices] IOptionsMonitor<IRCEncreptOption> _IRCEncreptOption)
|
|
||||||
{
|
|
||||||
//var pemPublicKey = Encoding.UTF8.GetString(Convert.FromBase64String(_IRCEncreptOption.CurrentValue.Base64RSAPublicKey));
|
|
||||||
|
|
||||||
return ResponseOutput.Ok(_IRCEncreptOption.CurrentValue.Base64RSAPublicKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[HttpGet, Route("imageShare/ShareImage")]
|
[HttpGet, Route("imageShare/ShareImage")]
|
||||||
@@ -321,100 +293,107 @@ namespace IRaCIS.Api.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("user/GetObjectStoreToken")]
|
[HttpGet("user/GetObjectStoreToken")]
|
||||||
public async Task<IResponseOutput> GetObjectStoreTokenAsync([FromServices] IOptionsMonitor<ObjectStoreServiceOptions> options, [FromServices] IOSSService _oSSService)
|
public IResponseOutput GetObjectStoreToken([FromServices] IOptionsMonitor<ObjectStoreServiceOptions> options)
|
||||||
{
|
{
|
||||||
|
var serviceOption = options.CurrentValue;
|
||||||
|
|
||||||
var result = _oSSService.GetObjectStoreTempToken();
|
if (Enum.TryParse<ObjectStoreUse>(serviceOption.ObjectStoreUse, out var parsedEnum) && parsedEnum == ObjectStoreUse.AliyunOSS)
|
||||||
|
{
|
||||||
|
|
||||||
//result.AWS = await GetAWSTemToken(options.CurrentValue);
|
var ossOptions = serviceOption.AliyunOSS;
|
||||||
|
|
||||||
return ResponseOutput.Ok(result);
|
return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse = serviceOption.ObjectStoreUse, MinIO = serviceOption.MinIO, AliyunOSS = serviceOption.AliyunOSS, AWS = serviceOption.AWS });
|
||||||
|
|
||||||
|
#region 临时token 屏蔽
|
||||||
|
//IClientProfile profile = DefaultProfile.GetProfile(ossOptions.RegionId, ossOptions.AccessKeyId, ossOptions.AccessKeySecret);
|
||||||
|
//DefaultAcsClient client = new DefaultAcsClient(profile);
|
||||||
|
|
||||||
|
|
||||||
|
//// 创建一个STS请求
|
||||||
|
//AssumeRoleRequest request = new AssumeRoleRequest
|
||||||
|
//{
|
||||||
|
// RoleArn = ossOptions.RoleArn, // 角色ARN,需要替换为你的角色ARN
|
||||||
|
// RoleSessionName = $"session-name-{NewId.NextGuid()}", // 角色会话名称,可自定义
|
||||||
|
// DurationSeconds = 900, // 令牌有效期(单位:秒),这里设置为1小时
|
||||||
|
//};
|
||||||
|
|
||||||
|
|
||||||
|
//AssumeRoleResponse response = client.GetAcsResponse(request);
|
||||||
|
|
||||||
|
//// 返回STS令牌信息给前端
|
||||||
|
//var stsToken = new ObjectStoreDTO()
|
||||||
|
//{
|
||||||
|
// ObjectStoreUse = serviceOption.ObjectStoreUse,
|
||||||
|
// AliyunOSS = new AliyunOSSTempToken()
|
||||||
|
// {
|
||||||
|
// AccessKeyId = response.Credentials.AccessKeyId,
|
||||||
|
// AccessKeySecret = response.Credentials.AccessKeySecret,
|
||||||
|
// SecurityToken = response.Credentials.SecurityToken,
|
||||||
|
// Expiration = response.Credentials.Expiration,
|
||||||
|
|
||||||
|
// Region = ossOptions.Region,
|
||||||
|
// BucketName = ossOptions.BucketName,
|
||||||
|
// ViewEndpoint = ossOptions.ViewEndpoint,
|
||||||
|
|
||||||
|
// },
|
||||||
|
// MinIO = serviceOption.MinIO
|
||||||
|
//};
|
||||||
|
//return ResponseOutput.Ok(stsToken);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (Enum.TryParse<ObjectStoreUse>(serviceOption.ObjectStoreUse, out var parsedValue) && parsedValue == ObjectStoreUse.MinIO)
|
||||||
|
{
|
||||||
|
return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse = serviceOption.ObjectStoreUse, MinIO = serviceOption.MinIO, AWS = serviceOption.AWS });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse = serviceOption.ObjectStoreUse, MinIO = serviceOption.MinIO, AWS = serviceOption.AWS });
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("user/GenerateSTS")]
|
||||||
private async Task<AWSTempToken> GetAWSTemToken(ObjectStoreServiceOptions serviceOption)
|
public IResponseOutput GenerateSTS([FromServices] IOptionsMonitor<AliyunOSSOptions> options)
|
||||||
{
|
{
|
||||||
var awsOptions = serviceOption.AWS;
|
var ossOptions = options.CurrentValue;
|
||||||
|
|
||||||
//aws 临时凭证
|
|
||||||
// 创建 STS 客户端
|
|
||||||
var stsClient = new AmazonSecurityTokenServiceClient(awsOptions.AccessKeyId, awsOptions.SecretAccessKey);
|
|
||||||
|
|
||||||
// 使用 AssumeRole 请求临时凭证
|
IClientProfile profile = DefaultProfile.GetProfile(ossOptions.regionId, ossOptions.accessKeyId, ossOptions.accessKeySecret);
|
||||||
var assumeRoleRequest = new AssumeRoleRequest
|
DefaultAcsClient client = new DefaultAcsClient(profile);
|
||||||
|
|
||||||
|
|
||||||
|
// 创建一个STS请求
|
||||||
|
AssumeRoleRequest request = new AssumeRoleRequest
|
||||||
{
|
{
|
||||||
|
RoleArn = ossOptions.roleArn, // 角色ARN,需要替换为你的角色ARN
|
||||||
RoleArn = awsOptions.RoleArn, // 角色 ARN
|
RoleSessionName = $"session-name-{NewId.NextGuid()}", // 角色会话名称,可自定义
|
||||||
RoleSessionName = $"session-name-{NewId.NextGuid()}",
|
DurationSeconds = 900, // 令牌有效期(单位:秒),这里设置为1小时
|
||||||
DurationSeconds = awsOptions.DurationSeconds // 临时凭证有效期
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var assumeRoleResponse = await stsClient.AssumeRoleAsync(assumeRoleRequest);
|
|
||||||
|
|
||||||
var credentials = assumeRoleResponse.Credentials;
|
AssumeRoleResponse response = client.GetAcsResponse(request);
|
||||||
|
|
||||||
var tempToken = new AWSTempToken()
|
// 返回STS令牌信息给前端
|
||||||
|
var stsToken = new
|
||||||
{
|
{
|
||||||
AccessKeyId = credentials.AccessKeyId,
|
AccessKeyId = response.Credentials.AccessKeyId,
|
||||||
SecretAccessKey = credentials.SecretAccessKey,
|
AccessKeySecret = response.Credentials.AccessKeySecret,
|
||||||
SessionToken = credentials.SessionToken,
|
SecurityToken = response.Credentials.SecurityToken,
|
||||||
Expiration = credentials.Expiration,
|
Expiration = response.Credentials.Expiration,
|
||||||
Region = awsOptions.Region,
|
|
||||||
BucketName = awsOptions.BucketName,
|
Region = ossOptions.region,
|
||||||
EndPoint = awsOptions.EndPoint,
|
BucketName = ossOptions.bucketName,
|
||||||
ViewEndpoint = awsOptions.ViewEndpoint,
|
ViewEndpoint = ossOptions.viewEndpoint,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return tempToken;
|
return ResponseOutput.Ok(stsToken);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#region aliyun-net-sdk-sts 之前
|
|
||||||
//[HttpGet("user/GenerateSTS")]
|
|
||||||
//public IResponseOutput GenerateSTS([FromServices] IOptionsMonitor<AliyunOSSOptions> options)
|
|
||||||
//{
|
|
||||||
// var ossOptions = options.CurrentValue;
|
|
||||||
|
|
||||||
|
|
||||||
// IClientProfile profile = DefaultProfile.GetProfile(ossOptions.regionId, ossOptions.accessKeyId, ossOptions.accessKeySecret);
|
|
||||||
// DefaultAcsClient client = new DefaultAcsClient(profile);
|
|
||||||
|
|
||||||
|
|
||||||
// // 创建一个STS请求
|
|
||||||
// AssumeRoleRequest request = new AssumeRoleRequest
|
|
||||||
// {
|
|
||||||
// RoleArn = ossOptions.roleArn, // 角色ARN,需要替换为你的角色ARN
|
|
||||||
// RoleSessionName = $"session-name-{NewId.NextGuid()}", // 角色会话名称,可自定义
|
|
||||||
// DurationSeconds = 900, // 令牌有效期(单位:秒),这里设置为1小时
|
|
||||||
// };
|
|
||||||
|
|
||||||
|
|
||||||
// AssumeRoleResponse response = client.GetAcsResponse(request);
|
|
||||||
|
|
||||||
// // 返回STS令牌信息给前端
|
|
||||||
// var stsToken = new
|
|
||||||
// {
|
|
||||||
// AccessKeyId = response.Credentials.AccessKeyId,
|
|
||||||
// AccessKeySecret = response.Credentials.AccessKeySecret,
|
|
||||||
// SecurityToken = response.Credentials.SecurityToken,
|
|
||||||
// Expiration = response.Credentials.Expiration,
|
|
||||||
|
|
||||||
// Region = ossOptions.region,
|
|
||||||
// BucketName = ossOptions.bucketName,
|
|
||||||
// ViewEndpoint = ossOptions.viewEndpoint,
|
|
||||||
|
|
||||||
// };
|
|
||||||
|
|
||||||
// return ResponseOutput.Ok(stsToken);
|
|
||||||
|
|
||||||
//}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[HttpGet("User/UserRedirect")]
|
[HttpGet("User/UserRedirect")]
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
@@ -448,7 +427,7 @@ namespace IRaCIS.Api.Controllers
|
|||||||
|
|
||||||
[HttpGet, Route("ip")]
|
[HttpGet, Route("ip")]
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
public IResponseOutput Get([FromServices] IHttpContextAccessor _context)
|
public IResponseOutput Get([FromServices] IHttpContextAccessor _context/*, [FromServices] IUserService _userService*/)
|
||||||
{
|
{
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
@@ -469,7 +448,7 @@ namespace IRaCIS.Api.Controllers
|
|||||||
|
|
||||||
[HttpGet, Route("ip2")]
|
[HttpGet, Route("ip2")]
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
public IResponseOutput Get2([FromServices] IHttpContextAccessor _context)
|
public IResponseOutput Get2([FromServices] IHttpContextAccessor _context, [FromServices] IRepository _userService)
|
||||||
{
|
{
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ using IRaCIS.Core.Application.Filter;
|
|||||||
using IRaCIS.Core.Infrastructure.Extention;
|
using IRaCIS.Core.Infrastructure.Extention;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using IRaCIS.Core.Application.Service;
|
using IRaCIS.Application.Services;
|
||||||
using IRaCIS.Core.Application.Service.Inspection.DTO;
|
using IRaCIS.Core.Application.Service.Inspection.DTO;
|
||||||
using IRaCIS.Core.Infra.EFCore;
|
using IRaCIS.Core.Infra.EFCore;
|
||||||
using IRaCIS.Core.Domain.Models;
|
using IRaCIS.Core.Domain.Models;
|
||||||
@@ -19,12 +19,18 @@ namespace IRaCIS.Core.API.Controllers.Special
|
|||||||
//谨慎修改 涉及到财务模块
|
//谨慎修改 涉及到财务模块
|
||||||
|
|
||||||
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Financial")]
|
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Financial")]
|
||||||
public class FinancialChangeController(
|
public class FinancialChangeController : ControllerBase
|
||||||
ITrialService _trialService,
|
|
||||||
ICalculateService _calculateService,
|
|
||||||
IStringLocalizer _localizer) : ControllerBase
|
|
||||||
{
|
{
|
||||||
|
private readonly ITrialService _trialService;
|
||||||
|
private readonly ICalculateService _calculateService;
|
||||||
|
private IStringLocalizer _localizer { get; set; }
|
||||||
|
public FinancialChangeController(ITrialService trialService, ICalculateService calculateService, IStringLocalizer localizer
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_localizer = localizer;
|
||||||
|
_trialService = trialService;
|
||||||
|
_calculateService = calculateService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//[TrialAudit(AuditType.TrialAudit, AuditOptType.AddOrUpdateTrial)]
|
//[TrialAudit(AuditType.TrialAudit, AuditOptType.AddOrUpdateTrial)]
|
||||||
|
|||||||
@@ -26,18 +26,77 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
|
|
||||||
[ApiController, ApiExplorerSettings(GroupName = "Reviewer")]
|
[ApiController, ApiExplorerSettings(GroupName = "Reviewer")]
|
||||||
[UnitOfWork]
|
[UnitOfWork]
|
||||||
public class InspectionController(
|
public class InspectionController : ControllerBase
|
||||||
ITrialDocumentService _trialDocumentService,
|
|
||||||
IReadingImageTaskService _iReadingImageTaskService,
|
|
||||||
ITrialConfigService _trialConfigService,
|
|
||||||
IClinicalAnswerService _clinicalAnswerService,
|
|
||||||
IReadingClinicalDataService _readingClinicalDataService,
|
|
||||||
IQCOperationService _qCOperationService,
|
|
||||||
IInspectionService _inspectionService,
|
|
||||||
IReadingMedicalReviewService _readingMedicalReviewService,
|
|
||||||
IReadingMedicineQuestionService _readingMedicineQuestionService
|
|
||||||
) : ControllerBase
|
|
||||||
{
|
{
|
||||||
|
private readonly IRepository _repository;
|
||||||
|
private readonly IMapper _mapper;
|
||||||
|
private readonly IUserInfo _userInfo;
|
||||||
|
private readonly ITrialDocumentService _trialDocumentService;
|
||||||
|
private readonly IQCListService _qCListService;
|
||||||
|
private readonly IReadingImageTaskService _iReadingImageTaskService;
|
||||||
|
private readonly IHttpContextAccessor _httpContext;
|
||||||
|
private readonly ITrialConfigService _trialConfigService;
|
||||||
|
private readonly INoneDicomStudyService _noneDicomStudyService;
|
||||||
|
private readonly IClinicalAnswerService _clinicalAnswerService;
|
||||||
|
private readonly ISubjectService _subjectService;
|
||||||
|
private readonly IReadingClinicalDataService _readingClinicalDataService;
|
||||||
|
private readonly ISubjectVisitService _subjectVisitService;
|
||||||
|
private readonly IQCOperationService _qCOperationService;
|
||||||
|
private readonly IClinicalDataService _clinicalDataService;
|
||||||
|
private readonly IVisitPlanService _visitPlanService;
|
||||||
|
|
||||||
|
private readonly IInspectionService _inspectionService;
|
||||||
|
private readonly IReadingMedicalReviewService _readingMedicalReviewService;
|
||||||
|
private readonly IReadingMedicineQuestionService _readingMedicineQuestionService;
|
||||||
|
private readonly IRepository<DataInspection> _dataInspectionRepository;
|
||||||
|
private delegate Task<IResponseOutput> executionFun(dynamic data);
|
||||||
|
|
||||||
|
public InspectionController(IRepository repository,
|
||||||
|
IRepository<DataInspection> _repositoryDataInspection,
|
||||||
|
IMapper mapper, IUserInfo userInfo,
|
||||||
|
ITrialDocumentService trialDocumentService,
|
||||||
|
IRepository<DataInspection> dataInspectionRepository,
|
||||||
|
IQCListService _qCListService,
|
||||||
|
IReadingImageTaskService _iReadingImageTaskService,
|
||||||
|
IHttpContextAccessor httpContext,
|
||||||
|
IInspectionService sinspectionService,
|
||||||
|
IReadingMedicalReviewService readingMedicalReviewService,
|
||||||
|
IReadingMedicineQuestionService readingMedicineQuestionService,
|
||||||
|
ITrialConfigService _trialConfigService,
|
||||||
|
INoneDicomStudyService noneDicomStudyService,
|
||||||
|
IClinicalAnswerService clinicalAnswerService,
|
||||||
|
ISubjectService _subjectService,
|
||||||
|
IReadingClinicalDataService _readingClinicalDataService,
|
||||||
|
ISubjectVisitService subjectVisitService,
|
||||||
|
IQCOperationService qCOperationService,
|
||||||
|
IClinicalDataService clinicalDataService,
|
||||||
|
IVisitPlanService visitPlanService
|
||||||
|
)
|
||||||
|
{
|
||||||
|
this._repository = repository;
|
||||||
|
this._mapper = mapper;
|
||||||
|
this._userInfo = userInfo;
|
||||||
|
this._inspectionService = sinspectionService;
|
||||||
|
this._readingMedicalReviewService = readingMedicalReviewService;
|
||||||
|
this._readingMedicineQuestionService = readingMedicineQuestionService;
|
||||||
|
this._trialDocumentService = trialDocumentService;
|
||||||
|
this._qCListService = _qCListService;
|
||||||
|
this._iReadingImageTaskService = _iReadingImageTaskService;
|
||||||
|
this._httpContext = httpContext;
|
||||||
|
this._trialConfigService = _trialConfigService;
|
||||||
|
this._noneDicomStudyService = noneDicomStudyService;
|
||||||
|
this._clinicalAnswerService = clinicalAnswerService;
|
||||||
|
this._subjectService = _subjectService;
|
||||||
|
this._readingClinicalDataService = _readingClinicalDataService;
|
||||||
|
this._subjectVisitService = subjectVisitService;
|
||||||
|
this._qCOperationService = qCOperationService;
|
||||||
|
this._clinicalDataService = clinicalDataService;
|
||||||
|
this._visitPlanService = visitPlanService;
|
||||||
|
this._dataInspectionRepository = dataInspectionRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region 获取稽查数据
|
#region 获取稽查数据
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using DocumentFormat.OpenXml.Drawing;
|
using DocumentFormat.OpenXml.Drawing;
|
||||||
|
using EasyCaching.Core;
|
||||||
using ExcelDataReader;
|
using ExcelDataReader;
|
||||||
using IRaCIS.Application.Contracts;
|
using IRaCIS.Application.Contracts;
|
||||||
using IRaCIS.Application.Interfaces;
|
using IRaCIS.Application.Interfaces;
|
||||||
@@ -9,7 +10,8 @@ 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.MassTransit.Command;
|
using IRaCIS.Core.Application.MediatR.CommandAndQueries;
|
||||||
|
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;
|
||||||
@@ -19,7 +21,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 MassTransit.Mediator;
|
using MediatR;
|
||||||
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;
|
||||||
@@ -38,14 +40,12 @@ using Newtonsoft.Json;
|
|||||||
using SharpCompress.Archives;
|
using SharpCompress.Archives;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using ZiggyCreatures.Caching.Fusion;
|
|
||||||
using Path = System.IO.Path;
|
using Path = System.IO.Path;
|
||||||
|
|
||||||
namespace IRaCIS.Core.API.Controllers
|
namespace IRaCIS.Core.API.Controllers
|
||||||
@@ -228,17 +228,69 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
|
|
||||||
[ApiExplorerSettings(GroupName = "Image")]
|
[ApiExplorerSettings(GroupName = "Image")]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
public class StudyController(
|
public class StudyController : UploadBaseController
|
||||||
IMediator _mediator,
|
|
||||||
QCCommon _qCCommon,
|
|
||||||
IUserInfo _userInfo,
|
|
||||||
IRepository<SubjectVisit> _subjectVisitRepository,
|
|
||||||
IStringLocalizer _localizer) : UploadBaseController
|
|
||||||
{
|
{
|
||||||
|
public IMapper _mapper { get; set; }
|
||||||
|
public IUserInfo _userInfo { get; set; }
|
||||||
|
private readonly IMediator _mediator;
|
||||||
|
|
||||||
|
|
||||||
|
public IStringLocalizer _localizer { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
private readonly IWebHostEnvironment _hostEnvironment;
|
||||||
|
|
||||||
|
private readonly IRepository _repository;
|
||||||
|
|
||||||
|
private readonly IEasyCachingProvider _provider;
|
||||||
|
private readonly QCCommon _qCCommon;
|
||||||
|
public StudyController(IMapper mapper, IStringLocalizer localizer, IUserInfo userInfo, IWebHostEnvironment hostEnvironment, IMediator mediator, IEasyCachingProvider provider,
|
||||||
|
QCCommon qCCommon,
|
||||||
|
IRepository repository)
|
||||||
|
{
|
||||||
|
_qCCommon = qCCommon;
|
||||||
|
_provider = provider;
|
||||||
|
_hostEnvironment = hostEnvironment;
|
||||||
|
_mediator = mediator;
|
||||||
|
_localizer = localizer;
|
||||||
|
_mapper = mapper;
|
||||||
|
_userInfo = userInfo;
|
||||||
|
_repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[HttpPost, Route("Study/PreArchiveStudy")]
|
||||||
|
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||||
|
public async Task<IResponseOutput> PreArchiveStudy(PreArchiveStudyCommand preArchiveStudyCommand,
|
||||||
|
[FromServices] IStudyService _studyService,
|
||||||
|
[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 studyMonitor = new StudyMonitor()
|
||||||
|
{
|
||||||
|
TrialId = savedInfo.TrialId,
|
||||||
|
SubjectId = savedInfo.SubjectId,
|
||||||
|
SubjectVisitId = savedInfo.SubjectVisitId,
|
||||||
|
|
||||||
|
IsSuccess = false,
|
||||||
|
UploadStartTime = DateTime.Now,
|
||||||
|
IsDicom = preArchiveStudyCommand.IsDicom,
|
||||||
|
IP = _userInfo.IP
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var addEntity = await _studyMonitorRepository.AddAsync(studyMonitor, true);
|
||||||
|
|
||||||
|
return ResponseOutput.Ok(addEntity.Id);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>Dicom 归档</summary>
|
/// <summary>Dicom 归档</summary>
|
||||||
@@ -246,8 +298,9 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
[DisableFormValueModelBinding]
|
[DisableFormValueModelBinding]
|
||||||
[DisableRequestSizeLimit]
|
[DisableRequestSizeLimit]
|
||||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||||
public async Task<IResponseOutput> ArchiveStudyNew(Guid trialId, Guid subjectVisitId, string studyInstanceUid, Guid? abandonStudyId, Guid studyMonitorId,
|
public async Task<IResponseOutput> ArchiveStudyNew(/*[FromForm] ArchiveStudyCommand archiveStudyCommand,*/ Guid trialId, Guid subjectVisitId, string studyInstanceUid, Guid? abandonStudyId, Guid studyMonitorId,
|
||||||
[FromServices] ILogger<UploadDownLoadController> _logger,
|
[FromServices] ILogger<UploadDownLoadController> _logger,
|
||||||
|
[FromServices] IEasyCachingProvider _provider,
|
||||||
[FromServices] IStudyService _studyService,
|
[FromServices] IStudyService _studyService,
|
||||||
[FromServices] IHubContext<UploadHub, IUploadClient> _uploadHub,
|
[FromServices] IHubContext<UploadHub, IUploadClient> _uploadHub,
|
||||||
[FromServices] IDicomArchiveService _dicomArchiveService,
|
[FromServices] IDicomArchiveService _dicomArchiveService,
|
||||||
@@ -272,6 +325,22 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
var startTime = DateTime.Now;
|
var startTime = DateTime.Now;
|
||||||
|
|
||||||
|
|
||||||
|
if (_provider.Exists($"StudyUid_{trialId}_{archiveStudyCommand.StudyInstanceUid}") && _provider.Get<Guid>($"StudyUid_{trialId}_{studyInstanceUid}").Value == _userInfo.Id)
|
||||||
|
{
|
||||||
|
_provider.Set($"StudyUid_{trialId}_{archiveStudyCommand.StudyInstanceUid}", _userInfo.Id, TimeSpan.FromMinutes(30));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//if (_provider.Exists($"StudyUid_{trialId}_{archiveStudyCommand.StudyInstanceUid}"))
|
||||||
|
//{
|
||||||
|
// //---当前已有人正在上传和归档该检查!
|
||||||
|
// return ResponseOutput.NotOk(StaticData.International("UploadDownLoad_ArchiveInProgress"));
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// _provider.Set($"StudyUid_{trialId}_{archiveStudyCommand.StudyInstanceUid}", _userInfo.Id, TimeSpan.FromMinutes(30));
|
||||||
|
//}
|
||||||
|
|
||||||
//到了接口,代表上传结束了
|
//到了接口,代表上传结束了
|
||||||
|
|
||||||
@@ -337,12 +406,13 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
|
_provider.Remove($"StudyUid_{trialId}_{archiveStudyCommand.StudyInstanceUid}");
|
||||||
|
|
||||||
//---请求异常,请重试!
|
//---请求异常,请重试!
|
||||||
throw new BusinessValidationFailedException(_localizer["UploadDownLoad_RequestError"]);
|
throw new BusinessValidationFailedException(_localizer["UploadDownLoad_RequestError"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
studyMonitor.FileSize = (long)HttpContext.Request.ContentLength;
|
studyMonitor.FileSize = (decimal)HttpContext.Request.ContentLength;
|
||||||
studyMonitor.FileCount = archiveResult.ReceivedFileCount;
|
studyMonitor.FileCount = archiveResult.ReceivedFileCount;
|
||||||
studyMonitor.FailedFileCount = archiveResult.ErrorFiles.Count;
|
studyMonitor.FailedFileCount = archiveResult.ErrorFiles.Count;
|
||||||
studyMonitor.IsDicomReUpload = archiveStudyCommand.AbandonStudyId != null;
|
studyMonitor.IsDicomReUpload = archiveStudyCommand.AbandonStudyId != null;
|
||||||
@@ -375,6 +445,7 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
_provider.Remove($"StudyUid_{trialId}_{archiveStudyCommand.StudyInstanceUid}");
|
||||||
|
|
||||||
studyMonitor.StudyId = archiveResult.ArchivedDicomStudies.FirstOrDefault()?.Id ?? Guid.Empty;
|
studyMonitor.StudyId = archiveResult.ArchivedDicomStudies.FirstOrDefault()?.Id ?? Guid.Empty;
|
||||||
studyMonitor.StudyCode = archiveResult.ArchivedDicomStudies.FirstOrDefault()?.StudyCode;
|
studyMonitor.StudyCode = archiveResult.ArchivedDicomStudies.FirstOrDefault()?.StudyCode;
|
||||||
@@ -394,26 +465,12 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
|
|
||||||
public class UploadNoneDicomFileCommand
|
public class UploadNoneDicomFileCommand
|
||||||
{
|
{
|
||||||
[NotDefault]
|
public Guid TrialId { get; set; }
|
||||||
public Guid SubjectVisitId { get; set; }
|
public Guid SubjectVisitId { get; set; }
|
||||||
|
public Guid NoneDicomStudyId { get; set; }
|
||||||
|
|
||||||
[NotDefault]
|
|
||||||
public Guid StudyMonitorId { get; set; }
|
public Guid StudyMonitorId { get; set; }
|
||||||
|
|
||||||
|
|
||||||
public Guid? NoneDicomStudyId { get; set; }
|
|
||||||
|
|
||||||
//IR 上传的时候跟任务绑定
|
|
||||||
public Guid? VisitTaskId { get; set; }
|
|
||||||
|
|
||||||
public string RecordPath { get; set; }
|
|
||||||
|
|
||||||
public int FailedFileCount { get; set; }
|
|
||||||
|
|
||||||
public long FileSize { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
public List<OSSFileDTO> UploadedFileList { get; set; } = new List<OSSFileDTO>();
|
public List<OSSFileDTO> UploadedFileList { get; set; } = new List<OSSFileDTO>();
|
||||||
|
|
||||||
|
|
||||||
@@ -427,56 +484,18 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 非dicom 上传预上传接口
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="preArchiveStudyCommand"></param>
|
|
||||||
/// <param name="_studyService"></param>
|
|
||||||
/// <param name="_studyMonitorRepository"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[HttpPost, Route("Study/PreArchiveStudy")]
|
|
||||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
|
||||||
public async Task<IResponseOutput> PreArchiveStudy(PreArchiveStudyCommand preArchiveStudyCommand,
|
|
||||||
[FromServices] IStudyService _studyService,
|
|
||||||
[FromServices] IRepository<StudyMonitor> _studyMonitorRepository)
|
|
||||||
{
|
|
||||||
|
|
||||||
var savedInfo = _studyService.GetSaveToDicomInfo(preArchiveStudyCommand.SubjectVisitId);
|
|
||||||
|
|
||||||
var studyMonitor = new StudyMonitor()
|
|
||||||
{
|
|
||||||
TrialId = savedInfo.TrialId,
|
|
||||||
SubjectId = savedInfo.SubjectId,
|
|
||||||
SubjectVisitId = savedInfo.SubjectVisitId,
|
|
||||||
|
|
||||||
IsSuccess = false,
|
|
||||||
UploadStartTime = DateTime.Now,
|
|
||||||
FileCount=preArchiveStudyCommand.FileCount,
|
|
||||||
IsDicom = preArchiveStudyCommand.IsDicom,
|
|
||||||
IP = _userInfo.IP
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var addEntity = await _studyMonitorRepository.AddAsync(studyMonitor, true);
|
|
||||||
|
|
||||||
return ResponseOutput.Ok(addEntity.Id);
|
|
||||||
|
|
||||||
}
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 上传非Dicom 文件 支持压缩包 多文件上传
|
/// 上传非Dicom 文件 支持压缩包 多文件上传
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="incommand"></param>
|
/// <param name="incommand"></param>
|
||||||
/// <param name="_noneDicomStudyRepository"></param>
|
/// <param name="_noneDicomStudyRepository"></param>
|
||||||
/// <param name="_studyMonitorRepository"></param>
|
/// <param name="_studyMonitorRepository"></param>
|
||||||
/// <param name="_noneDicomStudyFileRepository"></param>
|
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPost("NoneDicomStudy/UploadNoneDicomFile")]
|
[HttpPost("NoneDicomStudy/UploadNoneDicomFile")]
|
||||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||||
|
|
||||||
public async Task<IResponseOutput> UploadNoneDicomFile(UploadNoneDicomFileCommand incommand,
|
public async Task<IResponseOutput> UploadNoneDicomFile(UploadNoneDicomFileCommand incommand,
|
||||||
[FromServices] IRepository<NoneDicomStudy> _noneDicomStudyRepository,
|
[FromServices] IRepository<NoneDicomStudy> _noneDicomStudyRepository, [FromServices] IRepository<StudyMonitor> _studyMonitorRepository)
|
||||||
[FromServices] IRepository<StudyMonitor> _studyMonitorRepository,
|
|
||||||
[FromServices] IRepository<NoneDicomStudyFile> _noneDicomStudyFileRepository)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
var subjectVisitId = incommand.SubjectVisitId;
|
var subjectVisitId = incommand.SubjectVisitId;
|
||||||
@@ -484,9 +503,9 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
var noneDicomStudyId = incommand.NoneDicomStudyId;
|
var noneDicomStudyId = incommand.NoneDicomStudyId;
|
||||||
|
|
||||||
|
|
||||||
await _qCCommon.VerifyIsCRCSubmmitAsync(_subjectVisitRepository, _userInfo, subjectVisitId);
|
await _qCCommon.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId);
|
||||||
|
|
||||||
var sv = (await _subjectVisitRepository.Where(t => t.Id == subjectVisitId).Select(t => new { t.TrialId, t.TrialSiteId, t.SubjectId }).FirstOrDefaultAsync()).IfNullThrowConvertException();
|
var sv = (await _repository.Where<SubjectVisit>(t => t.Id == subjectVisitId).Select(t => new { t.TrialId, t.TrialSiteId, t.SubjectId }).FirstOrDefaultAsync()).IfNullThrowConvertException();
|
||||||
|
|
||||||
var studyMonitor = await _studyMonitorRepository.FirstOrDefaultAsync(t => t.Id == studyMonitorId);
|
var studyMonitor = await _studyMonitorRepository.FirstOrDefaultAsync(t => t.Id == studyMonitorId);
|
||||||
|
|
||||||
@@ -494,39 +513,26 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
|
|
||||||
foreach (var item in incommand.UploadedFileList)
|
foreach (var item in incommand.UploadedFileList)
|
||||||
{
|
{
|
||||||
//如果是跟任务绑,那么NoneDicomStudyId 设置为空,不影响之前的检查,同时设置 OriginNoneDicomStudyId 保证关系
|
await _repository.AddAsync(new NoneDicomStudyFile() { FileName = item.FileName, Path = item.FilePath, NoneDicomStudyId = noneDicomStudyId,FileType=item.FileType });
|
||||||
|
|
||||||
if (incommand.VisitTaskId != null && incommand.VisitTaskId != Guid.Empty)
|
|
||||||
{
|
|
||||||
await _noneDicomStudyFileRepository.AddAsync(new NoneDicomStudyFile() { FileName = item.FileName, Path = item.FilePath, OriginNoneDicomStudyId = noneDicomStudyId.Value, VisitTaskId = incommand.VisitTaskId, FileType = item.FileType, FileSize = item.FileFize });
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await _noneDicomStudyFileRepository.AddAsync(new NoneDicomStudyFile() { FileName = item.FileName, Path = item.FilePath, NoneDicomStudyId = noneDicomStudyId.Value, FileType = item.FileType, FileSize = item.FileFize });
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
var uploadFinishedTime = DateTime.Now;
|
var uploadFinishedTime = DateTime.Now;
|
||||||
|
|
||||||
var noneDicomStudy = await _noneDicomStudyRepository.FirstOrDefaultAsync((t => t.Id == noneDicomStudyId));
|
var noneDicomStudy = await _noneDicomStudyRepository.FirstOrDefaultAsync((t => t.Id == noneDicomStudyId));
|
||||||
|
|
||||||
noneDicomStudy.FileCount = noneDicomStudy.FileCount + (incommand.VisitTaskId != null ? 0 : incommand.UploadedFileList.Count);
|
noneDicomStudy.FileCount = noneDicomStudy.FileCount + incommand.UploadedFileList.Count;
|
||||||
|
|
||||||
studyMonitor.RecordPath = incommand.RecordPath;
|
studyMonitor.FileCount = incommand.UploadedFileList.Count;
|
||||||
studyMonitor.FailedFileCount = incommand.FailedFileCount;
|
|
||||||
studyMonitor.IsSuccess = incommand.FailedFileCount == 0;
|
|
||||||
studyMonitor.FileSize = incommand.UploadedFileList.Sum(t => t.FileFize);
|
studyMonitor.FileSize = incommand.UploadedFileList.Sum(t => t.FileFize);
|
||||||
studyMonitor.IsDicom = false;
|
studyMonitor.IsDicom = false;
|
||||||
studyMonitor.IsDicomReUpload = false;
|
studyMonitor.IsDicomReUpload = false;
|
||||||
studyMonitor.StudyId = noneDicomStudyId.Value;
|
studyMonitor.StudyId = noneDicomStudyId;
|
||||||
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 _noneDicomStudyRepository.SaveChangesAsync();
|
await _repository.SaveChangesAsync();
|
||||||
|
|
||||||
return ResponseOutput.Ok();
|
return ResponseOutput.Ok();
|
||||||
}
|
}
|
||||||
@@ -540,13 +546,12 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="trialId"></param>
|
/// <param name="trialId"></param>
|
||||||
/// <param name="oSSService"></param>
|
/// <param name="oSSService"></param>
|
||||||
/// <param name="_inspectionFileRepository"></param>
|
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
/// <exception cref="BusinessValidationFailedException"></exception>
|
/// <exception cref="BusinessValidationFailedException"></exception>
|
||||||
[HttpPost("QCOperation/UploadVisitCheckExcel/{trialId:guid}")]
|
[HttpPost("QCOperation/UploadVisitCheckExcel/{trialId:guid}")]
|
||||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||||
|
|
||||||
public async Task<IResponseOutput> UploadVisitCheckExcel(Guid trialId, [FromServices] IOSSService oSSService, [FromServices] IRepository<InspectionFile> _inspectionFileRepository)
|
public async Task<IResponseOutput> UploadVisitCheckExcel(Guid trialId, [FromServices] IOSSService oSSService)
|
||||||
{
|
{
|
||||||
|
|
||||||
var fileName = string.Empty;
|
var fileName = string.Empty;
|
||||||
@@ -556,9 +561,9 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
{
|
{
|
||||||
fileName = realFileName;
|
fileName = realFileName;
|
||||||
|
|
||||||
if (!fileName.EndsWith(".xlsx") && !fileName.EndsWith(".xls"))
|
if (!fileName.EndsWith(".xlsx") && !fileName.EndsWith(".csv") && !fileName.EndsWith(".xls"))
|
||||||
{
|
{
|
||||||
//---支持.xlsx、.xls格式的文件上传。
|
//---支持.xlsx、.xls、.csv格式的文件上传。
|
||||||
throw new BusinessValidationFailedException(_localizer["UploadDownLoad_SupportedFormats"]);
|
throw new BusinessValidationFailedException(_localizer["UploadDownLoad_SupportedFormats"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -568,7 +573,7 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
|
|
||||||
var ossRelativePath = await oSSService.UploadToOSSAsync(fileStream, "InspectionUpload/Check", realFileName);
|
var ossRelativePath = await oSSService.UploadToOSSAsync(fileStream, "InspectionUpload/Check", realFileName);
|
||||||
|
|
||||||
await _inspectionFileRepository.AddAsync(new InspectionFile() { FileName = realFileName, RelativePath = ossRelativePath, TrialId = trialId });
|
await _repository.AddAsync(new InspectionFile() { FileName = realFileName, RelativePath = ossRelativePath, TrialId = trialId });
|
||||||
|
|
||||||
return ossRelativePath;
|
return ossRelativePath;
|
||||||
|
|
||||||
@@ -738,16 +743,11 @@ 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();
|
||||||
|
|
||||||
@@ -889,6 +889,89 @@ 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
|
||||||
|
|
||||||
@@ -981,18 +1064,18 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
}
|
}
|
||||||
var generateUserTypeList = new List<string>() { "CRC", "CRA" };
|
var generateUserTypeList = new List<string>() { "CRC", "CRA" };
|
||||||
|
|
||||||
//if (excelList.Any(t => !generateUserTypeList.Contains(t.UserTypeStr.ToUpper())))
|
if (excelList.Any(t => !generateUserTypeList.Contains(t.UserTypeStr.ToUpper())))
|
||||||
//{
|
{
|
||||||
// //用户类型仅能为 CRC,SR,CRA 请核查Excel数据
|
//用户类型仅能为 CRC,SR,CRA 请核查Excel数据
|
||||||
// throw new BusinessValidationFailedException(_localizer["UploadDownLoad_InvalidUserType"]);
|
throw new BusinessValidationFailedException(_localizer["UploadDownLoad_InvalidUserType"]);
|
||||||
//}
|
}
|
||||||
if (excelList.Count == 0)
|
if (excelList.Count == 0)
|
||||||
{
|
{
|
||||||
throw new BusinessValidationFailedException(_localizer["UploadDownLoad_NoValiddata"]);
|
throw new BusinessValidationFailedException(_localizer["UploadDownLoad_NoValiddata"]);
|
||||||
}
|
}
|
||||||
//处理好 用户类型 和用户类型枚举
|
//处理好 用户类型 和用户类型枚举
|
||||||
var sysUserTypeList = _usertypeRepository.Where(t => t.UserTypeEnum == UserTypeEnum.CRA || t.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Select(t => new { UserTypeId = t.Id, t.UserTypeEnum }).ToList();
|
var sysUserTypeList = _usertypeRepository.Where(t => t.UserTypeEnum == UserTypeEnum.CRA || t.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Select(t => new { UserTypeId = t.Id, t.UserTypeEnum }).ToList();
|
||||||
var siteList = _trialSiteRepository.Where(t => t.TrialId == trialId && siteCodeList.Contains(t.TrialSiteCode)).Select(t => new { t.TrialSiteCode, TrialSiteId = t.Id }).ToList();
|
var siteList = _trialSiteRepository.Where(t => t.TrialId == trialId && siteCodeList.Contains(t.TrialSiteCode)).Select(t => new { t.TrialSiteCode, TrialSiteId= t.Id }).ToList();
|
||||||
|
|
||||||
foreach (var item in excelList)
|
foreach (var item in excelList)
|
||||||
{
|
{
|
||||||
@@ -1016,9 +1099,9 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
item.TrialSiteId = siteList.FirstOrDefault(t => t.TrialSiteCode.ToUpper() == item.TrialSiteCode.ToUpper()).TrialSiteId;
|
item.TrialSiteId = siteList.FirstOrDefault(t => t.TrialSiteCode.ToUpper() == item.TrialSiteCode.ToUpper()).TrialSiteId;
|
||||||
}
|
}
|
||||||
|
|
||||||
var list = excelList.Where(t => t.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator || t.UserTypeEnum == UserTypeEnum.CRA).ToList();
|
|
||||||
|
|
||||||
await _trialSiteSurveyService.ImportGenerateAccountAndJoinTrialAsync(trialId, baseUrl, routeUrl, list);
|
|
||||||
|
await _trialSiteSurveyService.ImportGenerateAccountAndJoinTrialAsync(trialId, baseUrl, routeUrl, excelList.ToList());
|
||||||
|
|
||||||
return ResponseOutput.Ok();
|
return ResponseOutput.Ok();
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,107 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<SignAssembly>false</SignAssembly>
|
||||||
|
<UserSecretsId>354572d4-9e15-4099-807c-63a2d29ff9f2</UserSecretsId>
|
||||||
|
<LangVersion>default</LangVersion>
|
||||||
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
<DocumentationFile>.\IRaCIS.Core.API.xml</DocumentationFile>
|
||||||
|
<NoWarn>1701;1702;1591;</NoWarn>
|
||||||
|
<OutputPath>..\bin\</OutputPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
|
<DocumentationFile>bin\Release\IRaCIS.Core.API.xml</DocumentationFile>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<NoWarn>1701;1702;1591</NoWarn>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="Controllers\ReviewerApi\**" />
|
||||||
|
<Compile Remove="UploadFile\**" />
|
||||||
|
<Content Remove="Controllers\ReviewerApi\**" />
|
||||||
|
<Content Remove="UploadFile\**" />
|
||||||
|
<EmbeddedResource Remove="Controllers\ReviewerApi\**" />
|
||||||
|
<EmbeddedResource Remove="UploadFile\**" />
|
||||||
|
<None Remove="Controllers\ReviewerApi\**" />
|
||||||
|
<None Remove="UploadFile\**" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Remove="web.config" />
|
||||||
|
<Content Remove="wwwroot\swagger\ui\abp.js" />
|
||||||
|
<Content Remove="wwwroot\swagger\ui\abp.swagger.js" />
|
||||||
|
<Content Remove="wwwroot\swagger\ui\Index.html" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove=".preview.jpg" />
|
||||||
|
<None Remove="GrpcToken.proto" />
|
||||||
|
<None Remove="IRaCIS.Core.API.xml" />
|
||||||
|
<None Remove="Protos\GrpcToken.proto" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ApplicationDefinition Include="GrpcToken.proto" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="wwwroot\swagger\ui\abp.js" />
|
||||||
|
<EmbeddedResource Include="wwwroot\swagger\ui\abp.swagger.js" />
|
||||||
|
<EmbeddedResource Include="wwwroot\swagger\ui\Index.html" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Protobuf Include="Protos\GrpcToken.proto">
|
||||||
|
<GrpcServices>Client</GrpcServices>
|
||||||
|
</Protobuf>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="AspNetCoreRateLimit" Version="4.0.1" />
|
||||||
|
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="7.2.0" />
|
||||||
|
<PackageReference Include="EasyCaching.InMemory" Version="1.4.1" />
|
||||||
|
<PackageReference Include="EasyCaching.Interceptor.Castle" Version="1.4.1" />
|
||||||
|
<PackageReference Include="Google.Protobuf" Version="3.19.1" />
|
||||||
|
<PackageReference Include="Grpc.Net.Client" Version="2.41.0" />
|
||||||
|
<PackageReference Include="Grpc.Tools" Version="2.42.0">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Hangfire.Tags.SqlServer" Version="1.8.0" />
|
||||||
|
<PackageReference Include="Invio.Extensions.Authentication.JwtBearer" Version="2.0.1" />
|
||||||
|
<PackageReference Include="LogDashboard" Version="1.4.8" />
|
||||||
|
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="9.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.14.0" />
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="6.0.1" />
|
||||||
|
<PackageReference Include="Serilog.AspNetCore" Version="4.1.0" />
|
||||||
|
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="1.1.4" />
|
||||||
|
<PackageReference Include="Serilog.Sinks.Email" Version="2.4.0" />
|
||||||
|
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\IRaCIS.Core.Application\IRaCIS.Core.Application.csproj" />
|
||||||
|
<ProjectReference Include="..\IRaCIS.Core.Infra.EFCore\IRaCIS.Core.Infra.EFCore.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Properties\PublishProfiles\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Update="NLog.config">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ProjectExtensions><VisualStudio><UserProperties anonymizetagsetting_1json__JsonSchema="http://json.schemastore.org/jovo-language-model" /></VisualStudio></ProjectExtensions>
|
||||||
|
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -1,112 +1,160 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<SignAssembly>false</SignAssembly>
|
<SignAssembly>false</SignAssembly>
|
||||||
<UserSecretsId>354572d4-9e15-4099-807c-63a2d29ff9f2</UserSecretsId>
|
<UserSecretsId>354572d4-9e15-4099-807c-63a2d29ff9f2</UserSecretsId>
|
||||||
<LangVersion>default</LangVersion>
|
<LangVersion>default</LangVersion>
|
||||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
<Version>1.0.1.001</Version>
|
<Version>1.0.1.001</Version>
|
||||||
<Company>上海展影医疗科技有限公司</Company>
|
<Company>上海展影医疗科技有限公司</Company>
|
||||||
<Product>IRC影像系统 (EICS)</Product>
|
<Product>IRC影像系统 (EICS)</Product>
|
||||||
<Copyright>上海展影医疗科技有限公司版权所有</Copyright>
|
<Copyright>上海展影医疗科技有限公司版权所有</Copyright>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
<DocumentationFile>.\IRaCIS.Core.API.xml</DocumentationFile>
|
<DocumentationFile>.\IRaCIS.Core.API.xml</DocumentationFile>
|
||||||
<NoWarn>1701;1702;1591;1570;</NoWarn>
|
<NoWarn>1701;1702;1591;1570;</NoWarn>
|
||||||
<OutputPath>..\bin\</OutputPath>
|
<OutputPath>..\bin\</OutputPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
<DocumentationFile>bin\Release\IRaCIS.Core.API.xml</DocumentationFile>
|
<DocumentationFile>bin\Release\IRaCIS.Core.API.xml</DocumentationFile>
|
||||||
<OutputPath>bin\Release\</OutputPath>
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
<NoWarn>1701;1702;1591</NoWarn>
|
<NoWarn>1701;1702;1591</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Remove="web.config" />
|
<Content Remove="web.config" />
|
||||||
<Content Remove="wwwroot\swagger\ui\abp.js" />
|
<Content Remove="wwwroot\swagger\ui\abp.js" />
|
||||||
<Content Remove="wwwroot\swagger\ui\abp.swagger.js" />
|
<Content Remove="wwwroot\swagger\ui\abp.swagger.js" />
|
||||||
<Content Remove="wwwroot\swagger\ui\Index.html" />
|
<Content Remove="wwwroot\swagger\ui\Index.html" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove=".preview.jpg" />
|
<None Remove=".preview.jpg" />
|
||||||
<None Remove="GrpcToken.proto" />
|
<None Remove="GrpcToken.proto" />
|
||||||
<None Remove="IRaCIS.Core.API.xml" />
|
<None Remove="IRaCIS.Core.API.xml" />
|
||||||
<None Remove="Protos\GrpcToken.proto" />
|
<None Remove="Protos\GrpcToken.proto" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ApplicationDefinition Include="GrpcToken.proto" />
|
<ApplicationDefinition Include="GrpcToken.proto" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="wwwroot\swagger\ui\abp.js">
|
<EmbeddedResource Include="wwwroot\swagger\ui\abp.js">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
<EmbeddedResource Include="wwwroot\swagger\ui\abp.swagger.js">
|
<EmbeddedResource Include="wwwroot\swagger\ui\abp.swagger.js">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
<EmbeddedResource Include="wwwroot\swagger\ui\Index.html">
|
<EmbeddedResource Include="wwwroot\swagger\ui\Index.html">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Protobuf Include="Protos\GrpcToken.proto">
|
<Protobuf Include="Protos\GrpcToken.proto">
|
||||||
<GrpcServices>Client</GrpcServices>
|
<GrpcServices>Client</GrpcServices>
|
||||||
</Protobuf>
|
</Protobuf>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
|
<PackageReference Include="aliyun-net-sdk-sts" Version="3.1.2" />
|
||||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" />
|
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
|
||||||
|
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="9.0.0" />
|
||||||
|
<PackageReference Include="ConfigMapFileProvider" Version="2.0.1" />
|
||||||
|
<PackageReference Include="EasyCaching.Interceptor.Castle" Version="1.9.2" />
|
||||||
|
<PackageReference Include="EasyCaching.Serialization.MessagePack" Version="1.9.2">
|
||||||
|
<TreatAsUsed>true</TreatAsUsed>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.14" />
|
||||||
|
<PackageReference Include="Hangfire.Dashboard.BasicAuthorization" Version="1.0.2" />
|
||||||
|
<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="LogDashboard" Version="1.4.8" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.6" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.20.1" />
|
||||||
|
<PackageReference Include="Serilog.AspNetCore" Version="8.0.1" />
|
||||||
|
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.0.3" />
|
||||||
|
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.6.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.8">
|
<ItemGroup>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<ProjectReference Include="..\IRaCIS.Core.Application\IRaCIS.Core.Application.csproj" />
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<ProjectReference Include="..\IRaCIS.Core.Infra.EFCore\IRaCIS.Core.Infra.EFCore.csproj" />
|
||||||
</PackageReference>
|
</ItemGroup>
|
||||||
<PackageReference Include="ConfigMapFileProvider" Version="2.0.1" />
|
|
||||||
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.14" />
|
|
||||||
<PackageReference Include="Hangfire.Dashboard.BasicAuthorization" Version="1.0.2" />
|
|
||||||
<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="LogDashboard" Version="1.4.8" />
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.8" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
|
|
||||||
<PackageReference Include="Serilog.AspNetCore" Version="8.0.2" />
|
|
||||||
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.1.1" />
|
|
||||||
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.7.3" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\IRaCIS.Core.Application\IRaCIS.Core.Application.csproj" />
|
<None Include="..\.editorconfig" Link=".editorconfig" />
|
||||||
<ProjectReference Include="..\IRaCIS.Core.Infra.EFCore\IRaCIS.Core.Infra.EFCore.csproj" />
|
</ItemGroup>
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\.editorconfig" Link=".editorconfig" />
|
<Content Update="wwwroot\EmailTemplate\AdminAddUser_US.html">
|
||||||
</ItemGroup>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Update="wwwroot\EmailTemplate\AdminResetUser_US.html">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Update="wwwroot\EmailTemplate\AdminResetUser.html">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Update="wwwroot\EmailTemplate\SubjectEnrollConfirmOrPDProgress_US.html">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Update="wwwroot\EmailTemplate\TrialDoctorExistJoin_US.html">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Update="wwwroot\EmailTemplate\TrialDoctorFirstJoin.html">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Update="wwwroot\EmailTemplate\TrialSiteSurveyReject.html">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Update="wwwroot\EmailTemplate\TrialSiteSurveyReject_US.html">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Update="wwwroot\EmailTemplate\TrialDoctorExistJoin.html">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Update="wwwroot\EmailTemplate\TrialUserExistJoin_US.html">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Update="wwwroot\EmailTemplate\TrialUserExistJoin.html">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Update="wwwroot\EmailTemplate\AdminAddUser.html">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Update="wwwroot\EmailTemplate\TrialDoctorFirstJoin_US.html">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Update="wwwroot\EmailTemplate\SubjectEnrollConfirmOrPDProgress.html">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Update="wwwroot\EmailTemplate\TrialUserFirstJoin_US.html">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Update="wwwroot\EmailTemplate\UserOptCommon_US.html">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Update="wwwroot\EmailTemplate\UserOptCommon.html">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Update="wwwroot\EmailTemplate\TrialUserFirstJoin.html">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Properties\PublishProfiles\" />
|
<Folder Include="Properties\PublishProfiles\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ProjectExtensions><VisualStudio><UserProperties properties_4launchsettings_1json__JsonSchema="" /></VisualStudio></ProjectExtensions>
|
||||||
<Content Update="appsettings.json">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ProjectExtensions>
|
|
||||||
<VisualStudio>
|
|
||||||
<UserProperties properties_4launchsettings_1json__JsonSchema="" />
|
|
||||||
</VisualStudio>
|
|
||||||
</ProjectExtensions>
|
|
||||||
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
<param name="doctorId"></param>
|
<param name="doctorId"></param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:IRaCIS.Api.Controllers.ExtraController.Login(IRaCIS.Application.Contracts.UserLoginDTO,ZiggyCreatures.Caching.Fusion.IFusionCache,IRaCIS.Core.Application.Service.IUserService,IRaCIS.Core.Application.Auth.ITokenService,IRaCIS.Core.Application.Contracts.IReadingImageTaskService,Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.ServiceVerifyConfigOption},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig},IRaCIS.Core.Application.Service.IMailVerificationService)">
|
<member name="M:IRaCIS.Api.Controllers.ExtraController.Login(IRaCIS.Application.Contracts.UserLoginDTO,EasyCaching.Core.IEasyCachingProvider,IRaCIS.Application.Services.IUserService,IRaCIS.Core.Application.Auth.ITokenService,IRaCIS.Core.Application.Contracts.IReadingImageTaskService,Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.ServiceVerifyConfigOption},IRaCIS.Application.Services.IMailVerificationService)">
|
||||||
<summary> 系统用户登录接口[New] </summary>
|
<summary> 系统用户登录接口[New] </summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.AddOrUpdateTrialInspection(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Application.Contracts.TrialCommand})">
|
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.AddOrUpdateTrialInspection(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Application.Contracts.TrialCommand})">
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
<param name="param"></param>
|
<param name="param"></param>
|
||||||
<returns>新记录Id</returns>
|
<returns>新记录Id</returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.WorkLoadAddOrUpdate(IRaCIS.Core.Application.Service.IDoctorWorkloadService,IRaCIS.Application.Contracts.WorkloadCommand)">
|
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.WorkLoadAddOrUpdate(IRaCIS.Application.Services.IDoctorWorkloadService,IRaCIS.Application.Contracts.WorkloadCommand)">
|
||||||
<summary>
|
<summary>
|
||||||
添加或更新工作量[AUTH]
|
添加或更新工作量[AUTH]
|
||||||
</summary>
|
</summary>
|
||||||
@@ -278,35 +278,24 @@
|
|||||||
<member name="M:IRaCIS.Core.API.Controllers.UploadBaseController.DicomFileUploadAsync(System.Func{System.String,System.IO.Stream,System.Int32,System.Threading.Tasks.Task},System.String)">
|
<member name="M:IRaCIS.Core.API.Controllers.UploadBaseController.DicomFileUploadAsync(System.Func{System.String,System.IO.Stream,System.Int32,System.Threading.Tasks.Task},System.String)">
|
||||||
<summary> 流式上传 Dicom上传 </summary>
|
<summary> 流式上传 Dicom上传 </summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:IRaCIS.Core.API.Controllers.StudyController.ArchiveStudyNew(System.Guid,System.Guid,System.String,System.Nullable{System.Guid},System.Guid,Microsoft.Extensions.Logging.ILogger{IRaCIS.Core.API.Controllers.UploadDownLoadController},IRaCIS.Core.Application.Contracts.IStudyService,Microsoft.AspNetCore.SignalR.IHubContext{IRaCIS.Core.API.UploadHub,IRaCIS.Core.API.IUploadClient},IRaCIS.Core.Application.Contracts.Dicom.IDicomArchiveService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.StudyMonitor})">
|
<member name="M:IRaCIS.Core.API.Controllers.StudyController.ArchiveStudyNew(System.Guid,System.Guid,System.String,System.Nullable{System.Guid},System.Guid,Microsoft.Extensions.Logging.ILogger{IRaCIS.Core.API.Controllers.UploadDownLoadController},EasyCaching.Core.IEasyCachingProvider,IRaCIS.Core.Application.Contracts.IStudyService,Microsoft.AspNetCore.SignalR.IHubContext{IRaCIS.Core.API.UploadHub,IRaCIS.Core.API.IUploadClient},IRaCIS.Core.Application.Contracts.Dicom.IDicomArchiveService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.StudyMonitor})">
|
||||||
<summary>Dicom 归档</summary>
|
<summary>Dicom 归档</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:IRaCIS.Core.API.Controllers.StudyController.PreArchiveStudy(IRaCIS.Core.Application.Contracts.PreArchiveStudyCommand,IRaCIS.Core.Application.Contracts.IStudyService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.StudyMonitor})">
|
<member name="M:IRaCIS.Core.API.Controllers.StudyController.UploadNoneDicomFile(IRaCIS.Core.API.Controllers.StudyController.UploadNoneDicomFileCommand,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.StudyMonitor})">
|
||||||
<summary>
|
|
||||||
非dicom 上传预上传接口
|
|
||||||
</summary>
|
|
||||||
<param name="preArchiveStudyCommand"></param>
|
|
||||||
<param name="_studyService"></param>
|
|
||||||
<param name="_studyMonitorRepository"></param>
|
|
||||||
<returns></returns>
|
|
||||||
</member>
|
|
||||||
<member name="M:IRaCIS.Core.API.Controllers.StudyController.UploadNoneDicomFile(IRaCIS.Core.API.Controllers.StudyController.UploadNoneDicomFileCommand,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.StudyMonitor},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudyFile})">
|
|
||||||
<summary>
|
<summary>
|
||||||
上传非Dicom 文件 支持压缩包 多文件上传
|
上传非Dicom 文件 支持压缩包 多文件上传
|
||||||
</summary>
|
</summary>
|
||||||
<param name="incommand"></param>
|
<param name="incommand"></param>
|
||||||
<param name="_noneDicomStudyRepository"></param>
|
<param name="_noneDicomStudyRepository"></param>
|
||||||
<param name="_studyMonitorRepository"></param>
|
<param name="_studyMonitorRepository"></param>
|
||||||
<param name="_noneDicomStudyFileRepository"></param>
|
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:IRaCIS.Core.API.Controllers.StudyController.UploadVisitCheckExcel(System.Guid,IRaCIS.Core.Application.Helper.IOSSService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.InspectionFile})">
|
<member name="M:IRaCIS.Core.API.Controllers.StudyController.UploadVisitCheckExcel(System.Guid,IRaCIS.Core.Application.Helper.IOSSService)">
|
||||||
<summary>
|
<summary>
|
||||||
一致性核查 excel上传 支持三种格式
|
一致性核查 excel上传 支持三种格式
|
||||||
</summary>
|
</summary>
|
||||||
<param name="trialId"></param>
|
<param name="trialId"></param>
|
||||||
<param name="oSSService"></param>
|
<param name="oSSService"></param>
|
||||||
<param name="_inspectionFileRepository"></param>
|
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
<exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception>
|
<exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception>
|
||||||
</member>
|
</member>
|
||||||
@@ -337,6 +326,38 @@
|
|||||||
<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>
|
||||||
@@ -362,11 +383,6 @@
|
|||||||
序列化,反序列化的时候,处理时间 时区转换
|
序列化,反序列化的时候,处理时间 时区转换
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:IRaCIS.Core.API.JSONTimeZoneConverter.#ctor(Microsoft.AspNetCore.Http.IHttpContextAccessor)">
|
|
||||||
<summary>
|
|
||||||
序列化,反序列化的时候,处理时间 时区转换
|
|
||||||
</summary>
|
|
||||||
</member>
|
|
||||||
<member name="M:IRaCIS.Core.API.NullToEmptyStringResolver.CreateProperties(System.Type,Newtonsoft.Json.MemberSerialization)">
|
<member name="M:IRaCIS.Core.API.NullToEmptyStringResolver.CreateProperties(System.Type,Newtonsoft.Json.MemberSerialization)">
|
||||||
<summary>
|
<summary>
|
||||||
创建属性
|
创建属性
|
||||||
@@ -375,6 +391,18 @@
|
|||||||
<param name="memberSerialization">序列化成员</param>
|
<param name="memberSerialization">序列化成员</param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="M:IRaCIS.WX.CoreApi.Auth.AuthMiddleware.Invoke(Microsoft.AspNetCore.Http.HttpContext)">
|
||||||
|
<summary>
|
||||||
|
为了前端 一段时间无操作,需要重新登陆
|
||||||
|
</summary>
|
||||||
|
<param name="httpContext"></param>
|
||||||
|
<returns></returns>
|
||||||
|
</member>
|
||||||
|
<member name="T:TimeZoneAdjustmentMiddleware">
|
||||||
|
<summary>
|
||||||
|
废弃,没用
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
<member name="T:ZhaoXi._001.NET5Demo.Practice.WebApi.Utility.Jwt.CustomHSJWTService">
|
<member name="T:ZhaoXi._001.NET5Demo.Practice.WebApi.Utility.Jwt.CustomHSJWTService">
|
||||||
<summary>
|
<summary>
|
||||||
对称可逆加密
|
对称可逆加密
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.Primitives;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 废弃,没用
|
||||||
|
/// </summary>
|
||||||
|
public class TimeZoneAdjustmentMiddleware
|
||||||
|
{
|
||||||
|
private readonly RequestDelegate _next;
|
||||||
|
|
||||||
|
public TimeZoneAdjustmentMiddleware(RequestDelegate next)
|
||||||
|
{
|
||||||
|
_next = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Invoke(HttpContext context)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(context.Request.ContentType))
|
||||||
|
{
|
||||||
|
// 请求没有内容体,可能是一个没有请求体的请求,比如 GET 请求
|
||||||
|
await _next(context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var timeZoneId = "Asia/Shanghai"; // 客户端默认时区
|
||||||
|
|
||||||
|
var timeZoneIdHeaderValue = context.Request.Headers["TimeZoneId"];
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(timeZoneIdHeaderValue))
|
||||||
|
{
|
||||||
|
timeZoneId = timeZoneIdHeaderValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var timeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 处理 JSON 请求体中的时间字段
|
||||||
|
if (context.Request.ContentType.StartsWith("application/json"))
|
||||||
|
{
|
||||||
|
var requestBody = await new StreamReader(context.Request.Body).ReadToEndAsync();
|
||||||
|
|
||||||
|
// 使用 JSON.NET 或 System.Text.Json 解析 JSON 请求体
|
||||||
|
// 假设请求体中有一个名为 "dateTime" 的时间字段
|
||||||
|
dynamic jsonData = JsonConvert.DeserializeObject(requestBody);
|
||||||
|
|
||||||
|
if (jsonData.dateTime != null)
|
||||||
|
{
|
||||||
|
if (DateTime.TryParse((string)jsonData.dateTime, out DateTime dateTime))
|
||||||
|
{
|
||||||
|
// 将 JSON 请求体中的时间字段转换为服务器时区的时间
|
||||||
|
var serverTime = TimeZoneInfo.ConvertTime(dateTime, timeZone);
|
||||||
|
jsonData.dateTime = serverTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将修改后的 JSON 请求体重新写入请求流中
|
||||||
|
var jsonBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(jsonData));
|
||||||
|
context.Request.Body = new MemoryStream(jsonBytes);
|
||||||
|
context.Request.ContentLength = jsonBytes.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 处理 URL 表单参数
|
||||||
|
var modifiedQuery = new Dictionary<string, StringValues>();
|
||||||
|
|
||||||
|
foreach (var key in context.Request.Query.Keys)
|
||||||
|
{
|
||||||
|
if (DateTime.TryParse(context.Request.Query[key], out DateTime dateTime))
|
||||||
|
{
|
||||||
|
// 将 URL 表单参数中的时间转换为服务器时区的时间
|
||||||
|
var serverTime = TimeZoneInfo.ConvertTime(dateTime, timeZone);
|
||||||
|
modifiedQuery[key] = new StringValues(serverTime.ToString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
modifiedQuery[key] = context.Request.Query[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Request.Query = new QueryCollection(modifiedQuery);
|
||||||
|
|
||||||
|
// 处理Form请求体中的参数
|
||||||
|
if (context.Request.HasFormContentType)
|
||||||
|
{
|
||||||
|
var modifiedForm = new Dictionary<string, StringValues>();
|
||||||
|
|
||||||
|
foreach (var key in context.Request.Form.Keys)
|
||||||
|
{
|
||||||
|
if (DateTime.TryParse(context.Request.Form[key], out DateTime dateTime))
|
||||||
|
{
|
||||||
|
// 将请求体中的时间转换为服务器时区的时间
|
||||||
|
var serverTime = TimeZoneInfo.ConvertTime(dateTime, timeZone);
|
||||||
|
modifiedForm[key] = new StringValues(serverTime.ToString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
modifiedForm[key] = context.Request.Form[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var newFormCollection = new FormCollection(modifiedForm);
|
||||||
|
|
||||||
|
// 将新的表单集合设置回请求对象
|
||||||
|
context.Request.Form = newFormCollection;
|
||||||
|
}
|
||||||
|
|
||||||
|
await _next(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+25
-121
@@ -4,6 +4,8 @@ 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;
|
||||||
@@ -20,24 +22,15 @@ using Microsoft.AspNetCore.SignalR;
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using IRaCIS.Core.Application.Filter;
|
using IRaCIS.Core.Application.Filter;
|
||||||
using Microsoft.AspNetCore.HttpOverrides;
|
using Microsoft.AspNetCore.HttpOverrides;
|
||||||
using IRaCIS.Core.Application.Service.BackGroundJob;
|
using IRaCIS.Application.Services.BackGroundJob;
|
||||||
using LogDashboard;
|
using LogDashboard;
|
||||||
using FellowOakDicom.Network;
|
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 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;
|
|
||||||
using DocumentFormat.OpenXml.InkML;
|
|
||||||
using IRaCIS.Core.Domain;
|
|
||||||
|
|
||||||
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
|
|
||||||
AppContext.SetSwitch("Npgsql.DisableDateTimeInfinityConversions", true);
|
|
||||||
#region 获取环境变量
|
#region 获取环境变量
|
||||||
//以配置文件为准,否则 从url中取环境值(服务以命令行传递参数启动,配置文件配置了就不需要传递环境参数)
|
//以配置文件为准,否则 从url中取环境值(服务以命令行传递参数启动,配置文件配置了就不需要传递环境参数)
|
||||||
var config = new ConfigurationBuilder()
|
var config = new ConfigurationBuilder()
|
||||||
@@ -112,7 +105,7 @@ 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<EncreptApiResultFilter>(10);
|
||||||
options.Filters.Add<LimitUserRequestAuthorization>();
|
options.Filters.Add<LimitUserRequestAuthorization>();
|
||||||
|
|
||||||
|
|
||||||
@@ -123,18 +116,16 @@ 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<IRCEncreptOption>(_configuration.GetSection("EncrypteResponseConfig"));
|
builder.Services.AddOptions().Configure<EncreptResponseOption>(_configuration.GetSection("EncrypteResponseConfig"));
|
||||||
builder.Services.AddOptions().Configure<SystemPacsConfig>(_configuration.GetSection("SystemPacsConfig"));
|
builder.Services.AddOptions().Configure<SystemPacsConfig>(_configuration.GetSection("SystemPacsConfig"));
|
||||||
|
|
||||||
builder.Services.Configure<IRaCISBasicConfigOption>(_configuration.GetSection("IRaCISBasicConfig"));
|
|
||||||
|
|
||||||
|
|
||||||
//动态WebApi + UnifiedApiResultFilter 省掉控制器代码
|
//动态WebApi + UnifiedApiResultFilter 省掉控制器代码
|
||||||
builder.Services.AddDynamicWebApiSetup();
|
builder.Services.AddDynamicWebApiSetup();
|
||||||
//AutoMapper
|
//AutoMapper
|
||||||
builder.Services.AddAutoMapperSetup();
|
builder.Services.AddAutoMapperSetup();
|
||||||
//EF ORM QueryWithNoLock
|
//EF ORM QueryWithNoLock
|
||||||
builder.Services.AddEFSetup(_configuration, enviromentName);
|
builder.Services.AddEFSetup(_configuration);
|
||||||
//Http 响应压缩
|
//Http 响应压缩
|
||||||
builder.Services.AddResponseCompressionSetup();
|
builder.Services.AddResponseCompressionSetup();
|
||||||
//Swagger Api 文档
|
//Swagger Api 文档
|
||||||
@@ -143,45 +134,9 @@ 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
|
|
||||||
//参考链接:https://masstransit.io/documentation/concepts/mediator#scoped-mediator
|
|
||||||
builder.Services.AddMediator(cfg =>
|
|
||||||
{
|
|
||||||
cfg.AddConsumer<ConsistencyCheckConsumer>();
|
|
||||||
cfg.AddConsumer<AddSubjectTriggerConsumer>();
|
|
||||||
cfg.AddConsumer<AddSubjectTriggerConsumer2>();
|
|
||||||
//cfg.ConfigureMediator((context, cfg) => cfg.UseHttpContextScopeFilter(context));
|
|
||||||
});
|
|
||||||
|
|
||||||
//添加 MassTransit 和 InMemory 传输
|
|
||||||
builder.Services.AddMassTransit(cfg =>
|
|
||||||
{
|
|
||||||
// 注册消费者
|
|
||||||
cfg.AddConsumer<AddSubjectTriggerConsumer>(); // 替换为你的消费者类
|
|
||||||
cfg.AddConsumer<AddSubjectTriggerConsumer2>();
|
|
||||||
|
|
||||||
// 使用 InMemory 作为消息传递机制
|
|
||||||
cfg.UsingInMemory((context, cfg) =>
|
|
||||||
{
|
|
||||||
// 这里可以进行额外的配置
|
|
||||||
cfg.ConfigureEndpoints(context); // 自动配置所有消费者的端点
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region FusionCache
|
|
||||||
|
|
||||||
builder.Services.AddFusionCache();
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
// EasyCaching 缓存
|
// EasyCaching 缓存
|
||||||
//builder.Services.AddEasyCachingSetup(_configuration);
|
builder.Services.AddEasyCachingSetup(_configuration);
|
||||||
|
|
||||||
// hangfire 定时任务框架 有界面,更友好~
|
// hangfire 定时任务框架 有界面,更友好~
|
||||||
builder.Services.AddhangfireSetup(_configuration);
|
builder.Services.AddhangfireSetup(_configuration);
|
||||||
@@ -209,9 +164,6 @@ 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();
|
||||||
@@ -235,60 +187,9 @@ var env = app.Environment;
|
|||||||
|
|
||||||
#region 配置中间件
|
#region 配置中间件
|
||||||
|
|
||||||
app.UseMiddleware<EncryptionRequestMiddleware>();
|
|
||||||
|
|
||||||
// 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();
|
||||||
|
|
||||||
@@ -297,11 +198,12 @@ 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");
|
||||||
@@ -309,24 +211,22 @@ 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);
|
||||||
|
|
||||||
@@ -396,6 +296,10 @@ try
|
|||||||
//Log.Logger.Warning($"ContentRootPath——xx:{Path.GetDirectoryName(Path.GetDirectoryName(env.ContentRootPath))}");
|
//Log.Logger.Warning($"ContentRootPath——xx:{Path.GetDirectoryName(Path.GetDirectoryName(env.ContentRootPath))}");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var server = DicomServerFactory.Create<CStoreSCPService>(11112, userState: app.Services);
|
||||||
|
|
||||||
app.Run();
|
app.Run();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,14 +24,6 @@
|
|||||||
},
|
},
|
||||||
"applicationUrl": "http://localhost:6100"
|
"applicationUrl": "http://localhost:6100"
|
||||||
},
|
},
|
||||||
"IRaCIS.Test_IRC_PGSQL": {
|
|
||||||
"commandName": "Project",
|
|
||||||
"launchBrowser": true,
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Test_IRC_PGSQL"
|
|
||||||
},
|
|
||||||
"applicationUrl": "http://localhost:6100"
|
|
||||||
},
|
|
||||||
"IRaCIS.Event_IRC": {
|
"IRaCIS.Event_IRC": {
|
||||||
"commandName": "Project",
|
"commandName": "Project",
|
||||||
"launchBrowser": true,
|
"launchBrowser": true,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using IRaCIS.Core.Domain.Share;
|
using EasyCaching.Core;
|
||||||
|
using IRaCIS.Core.Domain.Share;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Cors;
|
using Microsoft.AspNetCore.Cors;
|
||||||
using Microsoft.AspNetCore.SignalR;
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
using System;
|
||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using System.Net;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using EasyCaching.Core;
|
||||||
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using Microsoft.AspNetCore.Authentication;
|
||||||
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
|
namespace IRaCIS.WX.CoreApi.Auth
|
||||||
|
{
|
||||||
|
public class AuthMiddleware
|
||||||
|
{
|
||||||
|
private readonly RequestDelegate _next;
|
||||||
|
private readonly IEasyCachingProvider _provider;
|
||||||
|
public AuthMiddleware(RequestDelegate next, IEasyCachingProvider provider)
|
||||||
|
{
|
||||||
|
_next = next;
|
||||||
|
_provider = provider;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
///为了前端 一段时间无操作,需要重新登陆
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="httpContext"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task Invoke(HttpContext httpContext)
|
||||||
|
{
|
||||||
|
|
||||||
|
var isLogin = httpContext.Request.Path.ToString().ToLower().Contains("login");
|
||||||
|
|
||||||
|
var result = await httpContext.AuthenticateAsync(JwtBearerDefaults.AuthenticationScheme);
|
||||||
|
|
||||||
|
if (!isLogin)
|
||||||
|
{
|
||||||
|
if (!result.Succeeded)
|
||||||
|
{
|
||||||
|
httpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
|
||||||
|
await httpContext.Response.WriteAsync("Unauthorized");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var toekn = result.Properties.Items[".Token.access_token"];
|
||||||
|
var jwtHandler = new JwtSecurityTokenHandler();
|
||||||
|
JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(toekn);
|
||||||
|
object userId;
|
||||||
|
jwtToken.Payload.TryGetValue("id", out userId);
|
||||||
|
|
||||||
|
var cacheValueExist = await _provider.ExistsAsync(userId.ToString()); //Get<string>(userId.ToString()).ToString();
|
||||||
|
if (!cacheValueExist)
|
||||||
|
{
|
||||||
|
httpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
|
||||||
|
await httpContext.Response.WriteAsync("Unauthorized");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await _provider.SetAsync(userId.ToString(), userId.ToString(), TimeSpan.FromMinutes(15));
|
||||||
|
httpContext.User = result.Principal;
|
||||||
|
await _next.Invoke(httpContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else await _next.Invoke(httpContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using Hangfire;
|
using Hangfire;
|
||||||
using Hangfire.Dashboard;
|
using Hangfire.Dashboard;
|
||||||
using Hangfire.Dashboard.BasicAuthorization;
|
using Hangfire.Dashboard.BasicAuthorization;
|
||||||
using IRaCIS.Core.Application.Service.BackGroundJob;
|
using IRaCIS.Application.Services.BackGroundJob;
|
||||||
using IRaCIS.Core.API.Filter;
|
using IRaCIS.Core.API.Filter;
|
||||||
using IRaCIS.Core.Application.Helper;
|
using IRaCIS.Core.Application.Helper;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
|||||||
@@ -20,20 +20,18 @@ namespace IRaCIS.Core.API
|
|||||||
// Set all the common properties available for every request
|
// Set all the common properties available for every request
|
||||||
diagnosticContext.Set("Host", request.Host);
|
diagnosticContext.Set("Host", request.Host);
|
||||||
|
|
||||||
diagnosticContext.Set("Protocol", request.Protocol);
|
|
||||||
diagnosticContext.Set("Scheme", request.Scheme);
|
|
||||||
|
|
||||||
#region old 未用
|
|
||||||
//这种获取的Ip不准 配置服务才行
|
//这种获取的Ip不准 配置服务才行
|
||||||
//diagnosticContext.Set("RequestIP", httpContext.Connection.RemoteIpAddress.ToString());
|
//diagnosticContext.Set("RequestIP", httpContext.Connection.RemoteIpAddress.ToString());
|
||||||
|
|
||||||
//这种方式可以,但是serilog提供了 就不用了
|
//这种方式可以,但是serilog提供了 就不用了
|
||||||
//diagnosticContext.Set("TestIP", httpContext.GetUserIp());
|
//diagnosticContext.Set("TestIP", httpContext.GetUserIp());
|
||||||
|
|
||||||
|
diagnosticContext.Set("Protocol", request.Protocol);
|
||||||
|
diagnosticContext.Set("Scheme", request.Scheme);
|
||||||
|
|
||||||
//这种方式不行 读取的body为空字符串 必须在中间件中读取
|
//这种方式不行 读取的body为空字符串 必须在中间件中读取
|
||||||
//diagnosticContext.Set("RequestBody", await ReadRequestBody(httpContext.Request));
|
//diagnosticContext.Set("RequestBody", await ReadRequestBody(httpContext.Request));
|
||||||
//diagnosticContext.Set("RequestBody", RequestPayload);
|
//diagnosticContext.Set("RequestBody", RequestPayload);
|
||||||
#endregion
|
|
||||||
|
|
||||||
// Only set it if available. You're not sending sensitive data in a querystring right?!
|
// Only set it if available. You're not sending sensitive data in a querystring right?!
|
||||||
if (request.QueryString.HasValue)
|
if (request.QueryString.HasValue)
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
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
|
||||||
@@ -15,11 +14,6 @@ namespace IRaCIS.Core.API
|
|||||||
//AutoMapper.Collection.EntityFrameworkCore
|
//AutoMapper.Collection.EntityFrameworkCore
|
||||||
automapper.AddCollectionMappers();
|
automapper.AddCollectionMappers();
|
||||||
|
|
||||||
|
|
||||||
// 全局忽略 DomainEvents 属性
|
|
||||||
automapper.AddGlobalIgnore(nameof(Entity.DomainEvents));
|
|
||||||
automapper.AddGlobalIgnore(nameof(Entity.DomainCommands));
|
|
||||||
|
|
||||||
#region 会使 IncludeMembers 失效 不能全局使用
|
#region 会使 IncludeMembers 失效 不能全局使用
|
||||||
//mapping an EntityFramework Core DbContext-object.
|
//mapping an EntityFramework Core DbContext-object.
|
||||||
//automapper.UseEntityFrameworkCoreModel<IRaCISDBContext>(services);
|
//automapper.UseEntityFrameworkCoreModel<IRaCISDBContext>(services);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Autofac;
|
using Autofac;
|
||||||
|
using Autofac.Extras.DynamicProxy;
|
||||||
using IRaCIS.Core.Application;
|
using IRaCIS.Core.Application;
|
||||||
using IRaCIS.Core.Application.BackGroundJob;
|
using IRaCIS.Core.Application.BackGroundJob;
|
||||||
using IRaCIS.Core.Infra.EFCore;
|
using IRaCIS.Core.Infra.EFCore;
|
||||||
@@ -9,7 +10,8 @@ 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 IRaCIS.Core.Application.Service;
|
using MediatR;
|
||||||
|
using IRaCIS.Application.Services;
|
||||||
using IRaCIS.Application.Interfaces;
|
using IRaCIS.Application.Interfaces;
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
|
|
||||||
@@ -49,7 +51,7 @@ namespace IRaCIS.Core.API
|
|||||||
|
|
||||||
Assembly application = Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory + "IRaCIS.Core.Application.dll");
|
Assembly application = Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory + "IRaCIS.Core.Application.dll");
|
||||||
containerBuilder.RegisterAssemblyTypes(application).Where(t => t.FullName.Contains("Service"))
|
containerBuilder.RegisterAssemblyTypes(application).Where(t => t.FullName.Contains("Service"))
|
||||||
.PropertiesAutowired().AsImplementedInterfaces();
|
.PropertiesAutowired().AsImplementedInterfaces().EnableClassInterceptors();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,59 +1,40 @@
|
|||||||
using EntityFramework.Exceptions.SqlServer;
|
using Castle.Core.Logging;
|
||||||
|
using EntityFramework.Exceptions.SqlServer;
|
||||||
using Hangfire.SqlServer;
|
using Hangfire.SqlServer;
|
||||||
using IRaCIS.Core.Application.Triggers;
|
using IRaCIS.Core.Application.Triggers;
|
||||||
using IRaCIS.Core.Domain.Share;
|
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.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
using StackExchange.Redis;
|
using StackExchange.Redis;
|
||||||
|
|
||||||
namespace IRaCIS.Core.API
|
namespace IRaCIS.Core.API
|
||||||
{
|
{
|
||||||
public static class EFSetup
|
public static class EFSetup
|
||||||
{
|
{
|
||||||
public static void AddEFSetup( this IServiceCollection services, IConfiguration configuration,string envName)
|
public static void AddEFSetup( this IServiceCollection services, IConfiguration configuration)
|
||||||
{
|
{
|
||||||
|
|
||||||
services.AddHttpContextAccessor();
|
services.AddHttpContextAccessor();
|
||||||
services.AddScoped<IUserInfo, UserInfo>();
|
services.AddScoped<IUserInfo, UserInfo>();
|
||||||
services.AddScoped<ISaveChangesInterceptor, AuditEntityInterceptor>();
|
|
||||||
services.AddScoped<ISaveChangesInterceptor, DispatchDomainEventsInterceptor>();
|
|
||||||
|
|
||||||
|
|
||||||
// First, register a pooling context factory as a Singleton service, as usual:
|
// 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>((sp, options) =>
|
services.AddDbContext<IRaCISDBContext>(options =>
|
||||||
{
|
{
|
||||||
|
|
||||||
// 在控制台
|
// 在控制台
|
||||||
//public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); });
|
//public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); });
|
||||||
var logFactory = LoggerFactory.Create(builder => { builder.AddDebug(); });
|
var logFactory = LoggerFactory.Create(builder => { builder.AddDebug(); });
|
||||||
|
|
||||||
var dbType = configuration.GetSection("ConnectionStrings:Db_Type").Value ;
|
options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value,
|
||||||
if (!string.IsNullOrWhiteSpace(dbType) && dbType == "pgsql")
|
contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure());
|
||||||
{
|
|
||||||
options.UseNpgsql(configuration.GetSection("ConnectionStrings:RemoteNew").Value, contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure());
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value, contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//迁移的时候,不生成外键
|
|
||||||
options.ReplaceService<IMigrationsSqlGenerator, NoForeignKeyMigrationsSqlGenerator>();
|
|
||||||
|
|
||||||
|
|
||||||
options.UseLoggerFactory(logFactory);
|
options.UseLoggerFactory(logFactory);
|
||||||
|
|
||||||
@@ -62,7 +43,6 @@ namespace IRaCIS.Core.API
|
|||||||
options.EnableSensitiveDataLogging();
|
options.EnableSensitiveDataLogging();
|
||||||
|
|
||||||
options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor());
|
options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor());
|
||||||
options.AddInterceptors(sp.GetServices<ISaveChangesInterceptor>());
|
|
||||||
|
|
||||||
options.UseProjectables();
|
options.UseProjectables();
|
||||||
|
|
||||||
@@ -75,15 +55,18 @@ namespace IRaCIS.Core.API
|
|||||||
|
|
||||||
options.UseTriggers(triggerOptions =>
|
options.UseTriggers(triggerOptions =>
|
||||||
{
|
{
|
||||||
triggerOptions.AddTrigger<SubjectTrigger>();
|
triggerOptions.AddTrigger<AddSubjectTrigger>();
|
||||||
triggerOptions.AddTrigger<ChallengeStateTrigger>();
|
triggerOptions.AddTrigger<ChallengeStateTrigger>();
|
||||||
|
triggerOptions.AddTrigger<SubjectStateTrigger>();
|
||||||
|
triggerOptions.AddTrigger<AddCRCCliniaclDataTrigger>();
|
||||||
|
triggerOptions.AddTrigger<SubjectVisitCheckPassedTrigger>();
|
||||||
|
triggerOptions.AddTrigger<SubjectVisitFinalVisitTrigger>();
|
||||||
triggerOptions.AddTrigger<SubjectVisitTrigger>();
|
triggerOptions.AddTrigger<SubjectVisitTrigger>();
|
||||||
triggerOptions.AddTrigger<SubjectVisitScanDateTrigger>();
|
|
||||||
triggerOptions.AddTrigger<TrialCriterionSignTrigger>();
|
triggerOptions.AddTrigger<TrialCriterionSignTrigger>();
|
||||||
triggerOptions.AddTrigger<TableQuestionRowTrigger>();
|
triggerOptions.AddTrigger<TableQuestionRowTrigger>();
|
||||||
//triggerOptions.AddTrigger<AddlTrialUserTrigger>();
|
//triggerOptions.AddTrigger<AddlTrialUserTrigger>();
|
||||||
triggerOptions.AddTrigger<VisitTaskIsFrontTaskNeedSignButNotSignTrigger>();
|
triggerOptions.AddTrigger<VisitTaskIsFrontTaskNeedSignButNotSignTrigger>();
|
||||||
triggerOptions.AddTrigger<JudgeVisitTaskTrigger>();
|
triggerOptions.AddTrigger<VisitTaskIbeforeTrigger>();
|
||||||
|
|
||||||
triggerOptions.AddTrigger<UserLogTrigger>();
|
triggerOptions.AddTrigger<UserLogTrigger>();
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
using Microsoft.Extensions.Configuration;
|
using EasyCaching.Core;
|
||||||
|
using EasyCaching.Core.Configurations;
|
||||||
|
using EasyCaching.Interceptor.Castle;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace IRaCIS.Core.API
|
namespace IRaCIS.Core.API
|
||||||
@@ -7,18 +10,18 @@ namespace IRaCIS.Core.API
|
|||||||
{
|
{
|
||||||
public static void AddEasyCachingSetup(this IServiceCollection services, IConfiguration configuration)
|
public static void AddEasyCachingSetup(this IServiceCollection services, IConfiguration configuration)
|
||||||
{
|
{
|
||||||
//services.AddEasyCaching(options =>
|
services.AddEasyCaching(options =>
|
||||||
//{
|
{
|
||||||
// options.UseInMemory();
|
options.UseInMemory();
|
||||||
|
|
||||||
// //options.UseRedis(configuration, EasyCachingConstValue.DefaultRedisName).WithMessagePack(EasyCachingConstValue.DefaultRedisName);
|
//options.UseRedis(configuration, EasyCachingConstValue.DefaultRedisName).WithMessagePack(EasyCachingConstValue.DefaultRedisName);
|
||||||
|
|
||||||
|
|
||||||
//});
|
});
|
||||||
|
|
||||||
////services.ConfigureCastleInterceptor(options => options.CacheProviderName = EasyCachingConstValue.DefaultRedisName);
|
//services.ConfigureCastleInterceptor(options => options.CacheProviderName = EasyCachingConstValue.DefaultRedisName);
|
||||||
|
|
||||||
//services.ConfigureCastleInterceptor(options => options.CacheProviderName = EasyCachingConstValue.DefaultInMemoryName);
|
services.ConfigureCastleInterceptor(options => options.CacheProviderName = EasyCachingConstValue.DefaultInMemoryName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,41 +11,19 @@ namespace IRaCIS.Core.API
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 序列化,反序列化的时候,处理时间 时区转换
|
/// 序列化,反序列化的时候,处理时间 时区转换
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class JSONTimeZoneConverter(IHttpContextAccessor _httpContextAccessor) : DateTimeConverterBase
|
public class JSONTimeZoneConverter : DateTimeConverterBase
|
||||||
{
|
{
|
||||||
|
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||||
|
|
||||||
private TimeZoneInfo _clientTimeZone;
|
private readonly TimeZoneInfo _clientTimeZone;
|
||||||
|
public JSONTimeZoneConverter(IHttpContextAccessor httpContextAccessor)
|
||||||
private string _dateFormat;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public override bool CanConvert(Type objectType)
|
|
||||||
{
|
{
|
||||||
#region 设置语言格式化方式,放在构造函数里面做不到动态切换
|
_httpContextAccessor = httpContextAccessor;
|
||||||
|
|
||||||
|
|
||||||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
|
||||||
|
|
||||||
if (!isEn_US)
|
|
||||||
{
|
|
||||||
// Chinese date format
|
|
||||||
_dateFormat = "yyyy-MM-dd HH:mm:ss";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Default or English date format
|
|
||||||
//_dateFormat = "MM/dd/yyyy HH:mm:ss";
|
|
||||||
|
|
||||||
_dateFormat = "yyyy-MM-dd HH:mm:ss";
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 获取当前请求的客户端时区
|
|
||||||
|
|
||||||
|
//默认是UTC
|
||||||
//var timeZoneId = "Etc/UTC";
|
//var timeZoneId = "Etc/UTC";
|
||||||
var timeZoneId = "Asia/Shanghai";
|
var timeZoneId = "Asia/Shanghai";
|
||||||
|
|
||||||
var timeZoneIdHeader = _httpContextAccessor?.HttpContext?.Request?.Headers["TimeZoneId"];
|
var timeZoneIdHeader = _httpContextAccessor?.HttpContext?.Request?.Headers["TimeZoneId"];
|
||||||
|
|
||||||
if (timeZoneIdHeader is not null && !string.IsNullOrEmpty(timeZoneIdHeader.Value))
|
if (timeZoneIdHeader is not null && !string.IsNullOrEmpty(timeZoneIdHeader.Value))
|
||||||
@@ -55,12 +33,12 @@ namespace IRaCIS.Core.API
|
|||||||
|
|
||||||
_clientTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
|
_clientTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
|
||||||
|
|
||||||
#endregion
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override bool CanConvert(Type objectType)
|
||||||
|
{
|
||||||
// 仅支持 DateTime 类型的转换
|
// 仅支持 DateTime 类型的转换
|
||||||
return objectType == typeof(DateTime)|| objectType == typeof(DateTime?);
|
return objectType == typeof(DateTime)|| objectType == typeof(DateTime?);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||||
@@ -113,10 +91,7 @@ namespace IRaCIS.Core.API
|
|||||||
{
|
{
|
||||||
//第一个参数默认使用系统本地时区 也就是应用服务器的时区
|
//第一个参数默认使用系统本地时区 也就是应用服务器的时区
|
||||||
DateTime clientZoneTime = TimeZoneInfo.ConvertTime(nullableDateTime.Value, _clientTimeZone);
|
DateTime clientZoneTime = TimeZoneInfo.ConvertTime(nullableDateTime.Value, _clientTimeZone);
|
||||||
|
writer.WriteValue(clientZoneTime);
|
||||||
//writer.WriteValue(clientZoneTime);
|
|
||||||
|
|
||||||
writer.WriteValue(clientZoneTime.ToString(_dateFormat));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,99 +0,0 @@
|
|||||||
using IRaCIS.Core.Domain.Share;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Serialization;
|
|
||||||
using System;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.API
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
//public class CustomContractResolver : DefaultContractResolver
|
|
||||||
//{
|
|
||||||
// protected override JsonContract CreateContract(Type objectType)
|
|
||||||
// {
|
|
||||||
// var contract = base.CreateContract(objectType);
|
|
||||||
|
|
||||||
// // 检查类是否有 LowercaseJsonAttribute 标记
|
|
||||||
// if (objectType.GetCustomAttribute<LowerCamelCaseJsonAttribute>() != null)
|
|
||||||
// {
|
|
||||||
// contract.NamingStrategy = new IRCCamelCaseNamingStrategy();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return contract;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region 废弃
|
|
||||||
|
|
||||||
public class MyDateTimeConverter : JsonConverter<DateTime>
|
|
||||||
{
|
|
||||||
public override DateTime ReadJson(JsonReader reader, Type objectType, DateTime existingValue, bool hasExistingValue, JsonSerializer serializer)
|
|
||||||
{
|
|
||||||
return reader.ReadAsDateTime().Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void WriteJson(JsonWriter writer, DateTime value, JsonSerializer serializer)
|
|
||||||
{
|
|
||||||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
|
||||||
|
|
||||||
string dateFormat;
|
|
||||||
if (!isEn_US)
|
|
||||||
{
|
|
||||||
// Chinese date format
|
|
||||||
dateFormat = "yyyy-MM-dd HH:mm:ss";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Default or English date format
|
|
||||||
dateFormat = "MM/dd/yyyy HH:mm:ss";
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.WriteValue(value.ToString(dateFormat));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class MyNullableDateTimeConverter : JsonConverter<DateTime?>
|
|
||||||
{
|
|
||||||
public override DateTime? ReadJson(JsonReader reader, Type objectType, DateTime? existingValue, bool hasExistingValue, JsonSerializer serializer)
|
|
||||||
{
|
|
||||||
var val = reader.ReadAsDateTime();
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void WriteJson(JsonWriter writer, DateTime? value, JsonSerializer serializer)
|
|
||||||
{
|
|
||||||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
|
||||||
|
|
||||||
string dateFormat;
|
|
||||||
if (!isEn_US)
|
|
||||||
{
|
|
||||||
// Chinese date format
|
|
||||||
dateFormat = "yyyy-MM-dd HH:mm:ss";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Default or English date format
|
|
||||||
dateFormat = "MM/dd/yyyy HH:mm:ss";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value.HasValue)
|
|
||||||
{
|
|
||||||
writer.WriteValue(value.Value.ToString(dateFormat));
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
writer.WriteValue(default(DateTime?));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
@@ -1,16 +1,10 @@
|
|||||||
|
|
||||||
using IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson;
|
using IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson;
|
||||||
using IRaCIS.Core.Application.Helper;
|
using IRaCIS.Core.Application.Helper;
|
||||||
using IRaCIS.Core.Domain.Share;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Converters;
|
using Newtonsoft.Json.Converters;
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
|
||||||
using System.Text.Json;
|
|
||||||
using Newtonsoft.Json.Serialization;
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.API
|
namespace IRaCIS.Core.API
|
||||||
{
|
{
|
||||||
@@ -18,43 +12,34 @@ namespace IRaCIS.Core.API
|
|||||||
{
|
{
|
||||||
public static void AddNewtonsoftJsonSetup(this IMvcBuilder builder, IServiceCollection services)
|
public static void AddNewtonsoftJsonSetup(this IMvcBuilder builder, IServiceCollection services)
|
||||||
{
|
{
|
||||||
|
|
||||||
services.AddHttpContextAccessor();
|
services.AddHttpContextAccessor();
|
||||||
services.AddScoped<JSONTimeZoneConverter>();
|
services.AddScoped<JSONTimeZoneConverter>();
|
||||||
services.AddScoped<ObjectStorePathConvert>();
|
services.AddScoped<CustomStringConverter>();
|
||||||
services.AddScoped<IOSSService, OSSService>();
|
services.AddScoped<IOSSService,OSSService>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
builder.AddNewtonsoftJson(options =>
|
builder.AddNewtonsoftJson(options =>
|
||||||
{
|
{
|
||||||
|
//options.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
|
||||||
//大驼峰
|
|
||||||
//options.SerializerSettings.ContractResolver = new DefaultContractResolver();
|
|
||||||
//小驼峰
|
|
||||||
//options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 忽略循环引用
|
// 忽略循环引用
|
||||||
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
|
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
|
||||||
|
//options.SerializerSettings.TypeNameHandling = TypeNameHandling.All;
|
||||||
|
|
||||||
//处理返回给前端 可空类型 给出默认值 比如in? 为null 设置 默认值0
|
//处理返回给前端 可空类型 给出默认值 比如in? 为null 设置 默认值0
|
||||||
options.SerializerSettings.ContractResolver = new NullToEmptyStringResolver();
|
options.SerializerSettings.ContractResolver = new NullToEmptyStringResolver(); //new DefaultContractResolver();// new NullToEmptyStringResolver();
|
||||||
|
// 设置时间格式
|
||||||
// 设置时间格式 isEn_US? "MM/dd/yyyy HH:mm:ss" :
|
options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
|
||||||
//options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
|
|
||||||
|
|
||||||
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
|
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
|
||||||
|
|
||||||
|
//options.SerializerSettings.Converters.Add(new JSONCustomDateConverter()) ;
|
||||||
|
|
||||||
//二者只能取其一
|
|
||||||
//options.SerializerSettings.Converters.Add(new MyDateTimeConverter());
|
|
||||||
//options.SerializerSettings.Converters.Add(new MyNullableDateTimeConverter());
|
|
||||||
|
|
||||||
//必须放在后面
|
|
||||||
options.SerializerSettings.Converters.Add(services.BuildServiceProvider().GetService<JSONTimeZoneConverter>());
|
options.SerializerSettings.Converters.Add(services.BuildServiceProvider().GetService<JSONTimeZoneConverter>());
|
||||||
|
|
||||||
|
//options.SerializerSettings.Converters.Add(services.BuildServiceProvider().GetService<CustomStringConverter>());
|
||||||
|
|
||||||
|
|
||||||
|
//IsoDateTimeConverter
|
||||||
|
//options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
|
||||||
|
|
||||||
})
|
})
|
||||||
.AddControllersAsServices()//动态webApi属性注入需要
|
.AddControllersAsServices()//动态webApi属性注入需要
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
using IRaCIS.Core.Infrastructure.NewtonsoftJson;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Serialization;
|
using Newtonsoft.Json.Serialization;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.API
|
namespace IRaCIS.Core.API
|
||||||
{
|
{
|
||||||
@@ -32,20 +30,8 @@ namespace IRaCIS.Core.API
|
|||||||
|
|
||||||
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
|
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
|
||||||
{
|
{
|
||||||
// 检查类是否有 LowerCamelCaseJsonAttribute 标记 有的话,属性名小写
|
|
||||||
if (type.GetCustomAttribute<LowerCamelCaseJsonAttribute>() != null)
|
|
||||||
{
|
|
||||||
base.NamingStrategy= new LowerCamelCaseNamingStrategy();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
base.NamingStrategy = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
|
IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
|
||||||
|
|
||||||
|
|
||||||
var list= type.GetProperties()
|
var list= type.GetProperties()
|
||||||
.Select(p =>
|
.Select(p =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,13 +9,15 @@ using System.Text.RegularExpressions;
|
|||||||
|
|
||||||
namespace IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson
|
namespace IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson
|
||||||
{
|
{
|
||||||
public class ObjectStorePathConvert : JsonConverter<string>
|
public class CustomStringConverter : JsonConverter<string>
|
||||||
{
|
{
|
||||||
|
//private readonly IHttpContextAccessor _httpContextAccessor;
|
||||||
private readonly IOSSService _oSSService;
|
private readonly IOSSService _oSSService;
|
||||||
|
|
||||||
// 构造函数
|
// 构造函数
|
||||||
public ObjectStorePathConvert( IOSSService oSSService)
|
public CustomStringConverter(/*IHttpContextAccessor httpContextAccessor*/ IOSSService oSSService)
|
||||||
{
|
{
|
||||||
|
//_httpContextAccessor = httpContextAccessor;
|
||||||
_oSSService = oSSService;
|
_oSSService = oSSService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,13 +31,13 @@ namespace IRaCIS.Core.API
|
|||||||
|
|
||||||
logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("LocalIP", httpContext.Connection.LocalIpAddress.MapToIPv4().ToString()));
|
logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("LocalIP", httpContext.Connection.LocalIpAddress.MapToIPv4().ToString()));
|
||||||
|
|
||||||
logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("TokenUserRealName", httpContext?.User?.FindFirst(ClaimAttributes.RealName)?.Value));
|
|
||||||
logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("TokenUserType", httpContext?.User?.FindFirst(JwtIRaCISClaimType.UserTypeShortName)?.Value));
|
|
||||||
|
|
||||||
|
|
||||||
//这样读取没用
|
//这样读取没用
|
||||||
//logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("RequestBody", await ReadRequestBody(httpContext.Request)));
|
//logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("RequestBody", await ReadRequestBody(httpContext.Request)));
|
||||||
//logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("RequestIP", IPHelper.GetIP(httpContext.Request) ));
|
//logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("RequestIP", IPHelper.GetIP(httpContext.Request) ));
|
||||||
|
logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("TokenUserRealName", httpContext?.User?.FindFirst(ClaimAttributes.RealName)?.Value));
|
||||||
|
logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("TokenUserType", httpContext?.User?.FindFirst(JwtIRaCISClaimType.UserTypeShortName)?.Value));
|
||||||
|
|
||||||
//logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("Referer", httpContext.Request.Headers["Referer"].ToString()));
|
//logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("Referer", httpContext.Request.Headers["Referer"].ToString()));
|
||||||
//logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("request_path", httpContext.Request.Path));
|
//logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("request_path", httpContext.Request.Path));
|
||||||
//logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("request_method", httpContext.Request.Method));
|
//logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("request_method", httpContext.Request.Method));
|
||||||
|
|||||||
@@ -13,16 +13,15 @@
|
|||||||
"ObjectStoreService": {
|
"ObjectStoreService": {
|
||||||
"ObjectStoreUse": "AliyunOSS",
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
"AliyunOSS": {
|
"AliyunOSS": {
|
||||||
"RegionId": "cn-shanghai",
|
"regionId": "cn-shanghai",
|
||||||
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
"AccessKeyId": "LTAI5tNRTsqL6aWmHkDmTwoH",
|
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||||
"AccessKeySecret": "7mtGz3qrYWI6JMMBZiLeC119VWicZH",
|
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||||
"RoleArn": "acs:ram::1899121822495495:role/irc-oss-access",
|
"bucketName": "zy-irc-store",
|
||||||
"BucketName": "zy-irc-store",
|
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
||||||
"ViewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com",
|
"viewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com",
|
||||||
"Region": "oss-cn-shanghai",
|
"region": "oss-cn-shanghai"
|
||||||
"DurationSeconds": 7200
|
|
||||||
},
|
},
|
||||||
"MinIO": {
|
"MinIO": {
|
||||||
"endpoint": "http://192.168.3.68",
|
"endpoint": "http://192.168.3.68",
|
||||||
@@ -64,8 +63,7 @@
|
|||||||
"CompanyName": "Extensive Imaging",
|
"CompanyName": "Extensive Imaging",
|
||||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||||
"CompanyShortName": "Extensive Imaging",
|
"CompanyShortName": "Extensive Imaging",
|
||||||
"CompanyShortNameCN": "展影医疗",
|
"CompanyShortNameCN": "展影医疗"
|
||||||
"IsEnv_US": false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -15,16 +15,15 @@
|
|||||||
"ObjectStoreService": {
|
"ObjectStoreService": {
|
||||||
"ObjectStoreUse": "AliyunOSS",
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
"AliyunOSS": {
|
"AliyunOSS": {
|
||||||
"RegionId": "cn-shanghai",
|
"regionId": "cn-shanghai",
|
||||||
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
"AccessKeyId": "LTAI5tNRTsqL6aWmHkDmTwoH",
|
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||||
"AccessKeySecret": "7mtGz3qrYWI6JMMBZiLeC119VWicZH",
|
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||||
"RoleArn": "acs:ram::1899121822495495:role/irc-oss-access",
|
"bucketName": "zy-irc-store",
|
||||||
"BucketName": "zy-irc-store",
|
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
||||||
"ViewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com",
|
"viewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com",
|
||||||
"Region": "oss-cn-shanghai",
|
"region": "oss-cn-shanghai"
|
||||||
"DurationSeconds": 7200
|
|
||||||
},
|
},
|
||||||
"MinIO": {
|
"MinIO": {
|
||||||
"endpoint": "http://192.168.3.68",
|
"endpoint": "http://192.168.3.68",
|
||||||
@@ -68,8 +67,7 @@
|
|||||||
"CompanyName": "Extensive Imaging",
|
"CompanyName": "Extensive Imaging",
|
||||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||||
"CompanyShortName": "Extensive Imaging",
|
"CompanyShortName": "Extensive Imaging",
|
||||||
"CompanyShortNameCN": "展影医疗",
|
"CompanyShortNameCN": "展影医疗"
|
||||||
"IsEnv_US": false
|
|
||||||
},
|
},
|
||||||
"SystemPacsConfig": {
|
"SystemPacsConfig": {
|
||||||
"Port": "11113",
|
"Port": "11113",
|
||||||
|
|||||||
@@ -16,36 +16,32 @@
|
|||||||
"ObjectStoreUse": "AliyunOSS",
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
|
|
||||||
"AliyunOSS": {
|
"AliyunOSS": {
|
||||||
"RegionId": "cn-shanghai",
|
"regionId": "cn-shanghai",
|
||||||
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
"endPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
|
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||||
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
|
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||||
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
|
"bucketName": "zy-irc-test-store",
|
||||||
"BucketName": "zy-irc-test-store",
|
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
||||||
"ViewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
|
"viewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
|
||||||
"Region": "oss-cn-shanghai",
|
"region": "oss-cn-shanghai"
|
||||||
"DurationSeconds": 7200
|
|
||||||
},
|
},
|
||||||
"MinIO": {
|
"MinIO": {
|
||||||
"EndPoint": "hir-oss.test.extimaging.com",
|
"endPoint": "hir-oss.test.extimaging.com",
|
||||||
"Port": "443",
|
"port": "443",
|
||||||
"UseSSL": true,
|
"useSSL": true,
|
||||||
"AccessKey": "fbStsVYCIPKHQneeqMwD",
|
"accessKey": "fbStsVYCIPKHQneeqMwD",
|
||||||
"SecretKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
|
"secretKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
|
||||||
"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": {
|
||||||
"Region": "us-east-1",
|
"endPoint": "s3.us-east-1.amazonaws.com",
|
||||||
"EndPoint": "s3.us-east-1.amazonaws.com",
|
"useSSL": true,
|
||||||
"UseSSL": true,
|
"accessKey": "AKIAZQ3DRSOHFPJJ6FEU",
|
||||||
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
|
"secretKey": "l+yjtvV7Z4jiwm/7xCYv30UeUj/SvuqqYzAwjJHf",
|
||||||
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
|
"bucketName": "ei-irc-test-store",
|
||||||
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
|
"viewEndpoint": "https://ei-irc-test-store.s3.amazonaws.com/"
|
||||||
"BucketName": "ei-med-s3-lili-uat-store",
|
|
||||||
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com",
|
|
||||||
"DurationSeconds": 7200
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -88,8 +84,7 @@
|
|||||||
"CompanyName": "Extensive Imaging",
|
"CompanyName": "Extensive Imaging",
|
||||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||||
"CompanyShortName": "Extensive Imaging",
|
"CompanyShortName": "Extensive Imaging",
|
||||||
"CompanyShortNameCN": "展影医疗",
|
"CompanyShortNameCN": "展影医疗"
|
||||||
"IsEnv_US": false
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"SystemPacsConfig": {
|
"SystemPacsConfig": {
|
||||||
|
|||||||
@@ -1,95 +0,0 @@
|
|||||||
{
|
|
||||||
"Logging": {
|
|
||||||
"LogLevel": {
|
|
||||||
"Default": "Information",
|
|
||||||
"Microsoft": "Warning",
|
|
||||||
"Microsoft.Hosting.Lifetime": "Information"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ConnectionStrings": {
|
|
||||||
"Db_Type": "pgsql",
|
|
||||||
"RemoteNew": "Host=106.14.89.110;Port=5432;Username=sa;Password=pgsql_pwd;Database=Test2_PG",
|
|
||||||
"Hangfire": "Server=106.14.89.110,1435;Database=Test_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
|
||||||
},
|
|
||||||
|
|
||||||
"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-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.test.extimaging.com",
|
|
||||||
"port": "443",
|
|
||||||
"useSSL": true,
|
|
||||||
"accessKey": "fbStsVYCIPKHQneeqMwD",
|
|
||||||
"secretKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
|
|
||||||
"bucketName": "irc-test",
|
|
||||||
"viewEndpoint": "https://hir-oss.test.extimaging.com/irc-test"
|
|
||||||
},
|
|
||||||
"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": 1,
|
|
||||||
|
|
||||||
"AutoLoginOutMinutes": 1,
|
|
||||||
|
|
||||||
"OpenLoginMFA": false,
|
|
||||||
|
|
||||||
"ContinuousReadingTimeMin": 120,
|
|
||||||
|
|
||||||
"ReadingRestTimeMin": 10,
|
|
||||||
"IsNeedChangePassWord": true,
|
|
||||||
|
|
||||||
"ChangePassWordDays": 90
|
|
||||||
},
|
|
||||||
|
|
||||||
"SystemEmailSendConfig": {
|
|
||||||
"Port": 465,
|
|
||||||
"Host": "smtp.qiye.aliyun.com",
|
|
||||||
"FromEmail": "test@extimaging.com",
|
|
||||||
"FromName": "Test_IRC",
|
|
||||||
"AuthorizationCode": "SHzyyl2021",
|
|
||||||
"SiteUrl": "http://irc.test.extimaging.com/login",
|
|
||||||
|
|
||||||
"OrganizationName": "Extlmaging",
|
|
||||||
"OrganizationNameCN": "Extlmaging",
|
|
||||||
"CompanyName": "Extensive Imaging",
|
|
||||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
|
||||||
"CompanyShortName": "Extensive Imaging",
|
|
||||||
"CompanyShortNameCN": "展影医疗"
|
|
||||||
},
|
|
||||||
|
|
||||||
"SystemPacsConfig": {
|
|
||||||
"Port": "11113",
|
|
||||||
"IP": "106.14.89.110"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -15,6 +15,18 @@
|
|||||||
|
|
||||||
"ObjectStoreService": {
|
"ObjectStoreService": {
|
||||||
"ObjectStoreUse": "AWS",
|
"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": {
|
"MinIO": {
|
||||||
"endPoint": "44.210.231.169",
|
"endPoint": "44.210.231.169",
|
||||||
"port": "9001",
|
"port": "9001",
|
||||||
@@ -26,15 +38,12 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"AWS": {
|
"AWS": {
|
||||||
"Region": "us-east-1",
|
"endPoint": "s3.us-east-1.amazonaws.com",
|
||||||
"EndPoint": "s3.us-east-1.amazonaws.com",
|
"useSSL": true,
|
||||||
"UseSSL": true,
|
"accessKey": "AKIAW3MEAFJX5P32P6NA",
|
||||||
"RoleArn": "arn:aws:iam::471112624751:role/lili_s3_access",
|
"secretKey": "soKfYlzZE11Zi4RyTjXp0myXN0U3U+ka8rT49+B/",
|
||||||
"AccessKeyId": "AKIAW3MEAFJXZ2TZK7GM",
|
"bucketName": "ei-med-s3-lili-store",
|
||||||
"SecretAccessKey": "9MLQCQ1HifEVW1gf068zBRAOb4wNnfrOkvBVByth",
|
"viewEndpoint": "https://ei-med-s3-lili-store.s3.amazonaws.com/"
|
||||||
"BucketName": "ei-med-s3-lili-store",
|
|
||||||
"ViewEndpoint": "https://ei-med-s3-lili-store.s3.amazonaws.com",
|
|
||||||
"DurationSeconds": 7200
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"BasicSystemConfig": {
|
"BasicSystemConfig": {
|
||||||
@@ -73,13 +82,7 @@
|
|||||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||||
"CompanyShortName": "Elevate Imaging",
|
"CompanyShortName": "Elevate Imaging",
|
||||||
"CompanyShortNameCN": "展影医疗",
|
"CompanyShortNameCN": "展影医疗",
|
||||||
"SiteUrl": "https://lili.elevateimaging.ai/login",
|
"SiteUrl": "https://lili.elevateimaging.ai/login"
|
||||||
"IsEnv_US": true
|
|
||||||
},
|
|
||||||
|
|
||||||
"SystemPacsConfig": {
|
|
||||||
"Port": "104",
|
|
||||||
"IP": "44.210.231.169"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,19 @@
|
|||||||
|
|
||||||
"ObjectStoreService": {
|
"ObjectStoreService": {
|
||||||
|
|
||||||
"ObjectStoreUse": "AWS",
|
"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": {
|
"MinIO": {
|
||||||
//"endPoint": "hir-oss.uat.extimaging.com",
|
//"endPoint": "hir-oss.uat.extimaging.com",
|
||||||
//"port": "443",
|
//"port": "443",
|
||||||
@@ -32,26 +44,23 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"AWS": {
|
"AWS": {
|
||||||
"Region": "us-east-1",
|
"endPoint": "s3.us-east-1.amazonaws.com",
|
||||||
"EndPoint": "s3.us-east-1.amazonaws.com",
|
"useSSL": true,
|
||||||
"UseSSL": true,
|
"accessKey": "AKIAZQ3DRSOHFPJJ6FEU",
|
||||||
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
|
"secretKey": "l+yjtvV7Z4jiwm/7xCYv30UeUj/SvuqqYzAwjJHf",
|
||||||
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
|
"bucketName": "ei-irc-test-store",
|
||||||
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
|
"viewEndpoint": "https://ei-irc-test-store.s3.amazonaws.com/"
|
||||||
"BucketName": "ei-med-s3-lili-uat-store",
|
|
||||||
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com",
|
|
||||||
"DurationSeconds": 7200
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"BasicSystemConfig": {
|
"BasicSystemConfig": {
|
||||||
|
|
||||||
"OpenUserComplexPassword": true,
|
"OpenUserComplexPassword": false,
|
||||||
|
|
||||||
"OpenSignDocumentBeforeWork": true,
|
"OpenSignDocumentBeforeWork": false,
|
||||||
|
|
||||||
"OpenTrialRelationDelete": true,
|
"OpenTrialRelationDelete": true,
|
||||||
|
|
||||||
"OpenLoginLimit": true,
|
"OpenLoginLimit": false,
|
||||||
|
|
||||||
"LoginMaxFailCount": 5,
|
"LoginMaxFailCount": 5,
|
||||||
|
|
||||||
@@ -63,9 +72,7 @@
|
|||||||
"ReadingRestTimeMin": 10,
|
"ReadingRestTimeMin": 10,
|
||||||
"IsNeedChangePassWord": true,
|
"IsNeedChangePassWord": true,
|
||||||
|
|
||||||
"ChangePassWordDays": 90,
|
"ChangePassWordDays": 90
|
||||||
|
|
||||||
"OpenLoginMFA": true
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"SystemEmailSendConfig": {
|
"SystemEmailSendConfig": {
|
||||||
@@ -81,13 +88,7 @@
|
|||||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||||
"CompanyShortName": "Elevate Imaging",
|
"CompanyShortName": "Elevate Imaging",
|
||||||
"CompanyShortNameCN": "展影医疗",
|
"CompanyShortNameCN": "展影医疗",
|
||||||
"SiteUrl": "https://lili.test.elevateimaging.ai/login",
|
"SiteUrl": "https://lili.test.elevateimaging.ai/login"
|
||||||
"IsEnv_US": true
|
|
||||||
},
|
|
||||||
|
|
||||||
"SystemPacsConfig": {
|
|
||||||
"Port": "104",
|
|
||||||
"IP": "3.226.182.187"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
//"RemoteNew": "Server=us-mssql-service,1433;Database=US_Uat_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
"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"
|
"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",
|
//"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"
|
//"Hangfire": "Server=3.226.182.187,1435;Database=US_Uat_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||||
},
|
},
|
||||||
|
|
||||||
"ObjectStoreService": {
|
"ObjectStoreService": {
|
||||||
@@ -36,22 +36,19 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"AWS": {
|
"AWS": {
|
||||||
"Region": "us-east-1",
|
"endPoint": "s3.us-east-1.amazonaws.com",
|
||||||
"EndPoint": "s3.us-east-1.amazonaws.com",
|
"useSSL": true,
|
||||||
"UseSSL": true,
|
"accessKey": "AKIAW3MEAFJXUO6XYFYN",
|
||||||
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
|
"secretKey": "AeX5r4xHQH7tNJlTTFVv5/zBXie1Kj+mAayKrukp",
|
||||||
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
|
"bucketName": "ei-med-s3-lili-uat-store",
|
||||||
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
|
"viewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com/"
|
||||||
"BucketName": "ei-med-s3-lili-uat-store",
|
|
||||||
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com/",
|
|
||||||
"DurationSeconds": 7200
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"BasicSystemConfig": {
|
"BasicSystemConfig": {
|
||||||
|
|
||||||
"OpenUserComplexPassword": true,
|
"OpenUserComplexPassword": false,
|
||||||
|
|
||||||
"OpenSignDocumentBeforeWork": true,
|
"OpenSignDocumentBeforeWork": false,
|
||||||
|
|
||||||
"OpenTrialRelationDelete": true,
|
"OpenTrialRelationDelete": true,
|
||||||
|
|
||||||
@@ -69,7 +66,7 @@
|
|||||||
|
|
||||||
"ChangePassWordDays": 90,
|
"ChangePassWordDays": 90,
|
||||||
|
|
||||||
"OpenLoginMFA": false
|
"OpenLoginMFA": true
|
||||||
},
|
},
|
||||||
|
|
||||||
"SystemEmailSendConfig": {
|
"SystemEmailSendConfig": {
|
||||||
@@ -85,13 +82,7 @@
|
|||||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||||
"CompanyShortName": "Elevate Imaging",
|
"CompanyShortName": "Elevate Imaging",
|
||||||
"CompanyShortNameCN": "展影医疗",
|
"CompanyShortNameCN": "展影医疗",
|
||||||
"SiteUrl": "https://lili.test.elevateimaging.ai/login",
|
"SiteUrl": "https://lili.test.elevateimaging.ai/login"
|
||||||
"IsEnv_US": true
|
|
||||||
},
|
|
||||||
|
|
||||||
"SystemPacsConfig": {
|
|
||||||
"Port": "104",
|
|
||||||
"IP": "3.226.182.187"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,16 +15,15 @@
|
|||||||
"ObjectStoreUse": "AliyunOSS",
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
|
|
||||||
"AliyunOSS": {
|
"AliyunOSS": {
|
||||||
"RegionId": "cn-shanghai",
|
"regionId": "cn-shanghai",
|
||||||
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
|
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||||
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
|
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||||
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
|
"bucketName": "zy-irc-uat-store",
|
||||||
"BucketName": "zy-irc-uat-store",
|
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
||||||
"ViewEndpoint": "https://zy-irc-uat-store.oss-cn-shanghai.aliyuncs.com",
|
"viewEndpoint": "https://zy-irc-uat-store.oss-cn-shanghai.aliyuncs.com",
|
||||||
"Region": "oss-cn-shanghai",
|
"region": "oss-cn-shanghai"
|
||||||
"DurationSeconds": 7200
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"MinIO": {
|
"MinIO": {
|
||||||
@@ -39,17 +38,6 @@
|
|||||||
"secretKey": "DzMaU2L4OXl90uytwOmDXF2encN0Jf4Nxu2XkYqQ",
|
"secretKey": "DzMaU2L4OXl90uytwOmDXF2encN0Jf4Nxu2XkYqQ",
|
||||||
"bucketName": "irc-uat"
|
"bucketName": "irc-uat"
|
||||||
|
|
||||||
},
|
|
||||||
"AWS": {
|
|
||||||
"Region": "us-east-1",
|
|
||||||
"EndPoint": "s3.us-east-1.amazonaws.com",
|
|
||||||
"UseSSL": true,
|
|
||||||
"RoleArn": "arn:aws:iam::471112624751:role/sts_s3_upload",
|
|
||||||
"AccessKeyId": "AKIAW3MEAFJXWRCGSX5Z",
|
|
||||||
"SecretAccessKey": "miais4jQGSd37A+TfBEP11AQM5u/CvotSmznJd8k",
|
|
||||||
"BucketName": "ei-med-s3-lili-uat-store",
|
|
||||||
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com/",
|
|
||||||
"DurationSeconds": 7200
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -86,8 +74,7 @@
|
|||||||
"CompanyName": "Extensive Imaging",
|
"CompanyName": "Extensive Imaging",
|
||||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||||
"CompanyShortName": "Extensive Imaging",
|
"CompanyShortName": "Extensive Imaging",
|
||||||
"CompanyShortNameCN": "展影医疗",
|
"CompanyShortNameCN": "展影医疗"
|
||||||
"IsEnv_US": false
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"SystemPacsConfig": {
|
"SystemPacsConfig": {
|
||||||
|
|||||||
@@ -43,6 +43,40 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"easycaching": {
|
||||||
|
"inmemory": {
|
||||||
|
"MaxRdSecond": 120,
|
||||||
|
"EnableLogging": false,
|
||||||
|
"LockMs": 5000,
|
||||||
|
"SleepMs": 300,
|
||||||
|
"DBConfig": {
|
||||||
|
"SizeLimit": 10000,
|
||||||
|
"ExpirationScanFrequency": 60,
|
||||||
|
"EnableReadDeepClone": true,
|
||||||
|
"EnableWriteDeepClone": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"redis": {
|
||||||
|
"MaxRdSecond": 120,
|
||||||
|
"EnableLogging": false,
|
||||||
|
"LockMs": 5000,
|
||||||
|
"SleepMs": 300,
|
||||||
|
"dbconfig": {
|
||||||
|
"Password": "xc@123456",
|
||||||
|
"IsSsl": false,
|
||||||
|
"SslHost": null,
|
||||||
|
"ConnectionTimeout": 5000,
|
||||||
|
"AllowAdmin": true,
|
||||||
|
"Endpoints": [
|
||||||
|
{
|
||||||
|
"Host": "47.117.164.182",
|
||||||
|
"Port": 6379
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Database": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"IRaCISImageStore": {
|
"IRaCISImageStore": {
|
||||||
"SwitchingMode": "RemainingDiskCapacity",
|
"SwitchingMode": "RemainingDiskCapacity",
|
||||||
"SwitchingRatio": 80,
|
"SwitchingRatio": 80,
|
||||||
@@ -54,15 +88,13 @@
|
|||||||
"QCChallengeCodePrefix": "Q",
|
"QCChallengeCodePrefix": "Q",
|
||||||
"NoneDicomStudyCodePrefix": "NST",
|
"NoneDicomStudyCodePrefix": "NST",
|
||||||
"DicomStudyCodePrefix": "ST",
|
"DicomStudyCodePrefix": "ST",
|
||||||
"TaskStudyCodePrefix": "P-ST",
|
|
||||||
"SystemSiteCodePrefix": "S",
|
"SystemSiteCodePrefix": "S",
|
||||||
"DefaultPassword": "123456",
|
"DefaultPassword": "123456",
|
||||||
"ImageShareExpireDays": 10
|
"ImageShareExpireDays": 10
|
||||||
},
|
},
|
||||||
|
|
||||||
"EncrypteResponseConfig": {
|
"EncrypteResponseConfig": {
|
||||||
"Base64RSAPublicKey": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0NCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBaHp3T1hYTWYyaEFkS1ZoWHczYUYNCmNaT3QycE1lcmdEaFVrOUdQK2s4VDBrUjFTRVlGVGtzNlkzaEVvL0dRTExqMHZFYVV3bTNhSFNuTTl5NmdLRWoNCmY5cTN6dkoyZzRSQjE4Z0UrTnNWWi9DMkVRZ3k5OWFiWGc5TitGREVlT0NmSjlSRTJPV3JBQ2s0V0RPbFFUdXYNCnhvR2JmcnkwVElSaFBrOGtuYkFmVkZ1and1VXJGblpJZ0ExYXhKZVZ6aDhwcmV1SEgreW1jdHp6NVo4V1pSV3kNCi9ISURHUy90dkg2NUMra2l6cUxRYUpKNHYwODMrRGpaVTBmNzNCdkk5eWt1dW1saXFzY1pvU2preDFOUFJwSkUNCkFtMVFNQ0hMRCtFdzlHT2Vsc2Mwa1ZxdjdaeEF1TkFrMkZuUURNRk1BUmZuUFd0aGVhOGZYVTJsMW9ROWs3WDcNCmN3SURBUUFCDQotLS0tLUVORCBQVUJMSUMgS0VZLS0tLS0NCg==",
|
"IsEnable": true,
|
||||||
"Base64RSAPrivateKey": "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRW9nSUJBQUtDQVFFQWh6d09YWE1mMmhBZEtWaFh3M2FGY1pPdDJwTWVyZ0RoVWs5R1ArazhUMGtSMVNFWQ0KRlRrczZZM2hFby9HUUxMajB2RWFVd20zYUhTbk05eTZnS0VqZjlxM3p2SjJnNFJCMThnRStOc1ZaL0MyRVFneQ0KOTlhYlhnOU4rRkRFZU9DZko5UkUyT1dyQUNrNFdET2xRVHV2eG9HYmZyeTBUSVJoUGs4a25iQWZWRnVqd3VVcg0KRm5aSWdBMWF4SmVWemg4cHJldUhIK3ltY3R6ejVaOFdaUld5L0hJREdTL3R2SDY1QytraXpxTFFhSko0djA4Mw0KK0RqWlUwZjczQnZJOXlrdXVtbGlxc2Nab1Nqa3gxTlBScEpFQW0xUU1DSExEK0V3OUdPZWxzYzBrVnF2N1p4QQ0KdU5BazJGblFETUZNQVJmblBXdGhlYThmWFUybDFvUTlrN1g3Y3dJREFRQUJBb0lCQUNDRFoxNi9XWWFYZmpOZA0KQ29pemU2VFJZU2llVzI5eFJic0ExVDV6YUcwVmY4U1NsdFF2Y1dWYmw2UGJUa3BxMkF4MHJDUVB2M2xOSm8vNA0KL3h3QzRlS1E1c1ZLRlFWTXJIbmhISlRxTTJ6UWVpMkJINlBuaEdZcVh0QVhOdzFxejhrSEoyQlFZM3IvN2d5Qw0KcWpZVFVCRDFRem5HeThCanlXOXVIcnNNeDVPRHRRZWxBM3B1TFd1bXZNb3Z1L2JhaDZvTGtOSHY4b0VTdzhGSQ0KTllyTUtscHhFTjZaWUdwSTl2VTZnYUhuTmhEa2ExTHlvUnZ5NnA2dTRLR0FsRTc1VXk4T0dsdncydU5uay9sdg0KSEMyYnY5TnlCRGJpSFNDY0MyK1JXUXMrN0tNWFlwYnBvTVFCR0hqV01GRHVBODFaUCs1TWYxUm9yQUpRNGxrRw0KQnRDQThva0NnWUVBeWY4alBjcFIvQ3dJNU5MYnlwb3ZUWEFHVkFKMmtWRlJVUC9HT2ZOMkFyYWMvL20wdDJ5NA0KemNYVkJZc0pJeHkvVWYxRTFJNFg3VFg3V3NBNGxVNGlPTkwzTnN4dDBEbk1PV2tKUlBPZlF1bW1JaWw5QVRiYQ0KTnRVWFNlTmRoUFFGMGlCb21acFFJYWpSN1RmUnVBbzR6dmpTLzkzeXZZY0lIWU1zM0tjR00ya0NnWUVBcTJPbg0KZlp0RmhLTElGanVlRzRrNklGTWdjbytEUUh5TTFWSUp5Tk05K1o2TEgybzI5eDJCaSs2Qm82M2NKUjQ2STZncQ0KNWUrSTBvdzZRYmNQeTZUNHFSQ0o3Ujd6MllkdEw4eXdJTkNYS3U0cC9qaFNqNWJ1TzFJWlI3ZStSV29CakNtUQ0KWFd0ZVBCbldqWVlLdVRCazROc2FXV09GTXg1QndKdUp2MjBnQ0hzQ2dZQlV4QnFYM1lWV0cyeUlDZXh1TXhIUw0KbjBZb2p2Z090MTgyYkg5VTVsUUpnM1NTL3NqVmlHeHMvYTROSzNGa0tMWW93KzNVZk9TUmlPdTRBNTQ3R1pURw0KMzlFYVQrTnRWRFBkaTdSMkdQNG1hRUp0WjVlcm9NY2w1M3BrYVdOZlhiL3JrK29STzI2UkVYVTI1UXUrL1pzbA0KVDhuTDBlb0JtdDdPODdNcHpYV09zUUtCZ0ZxVGFQSGx2RUNUY3FEbFV2S0VmRmFXOTkvelhrOFhRNnA5RjdTdA0KaHVSRDJJeDZxcC9BVlRWcGo5Tzd6MHRDaFVGUTM1THpHMkVDUU10My9uNEdLbS9XMEwyakRRWWFIeWNTeXNZYw0KMXJjV2ROVG9XU0dQaDBtTVl0WFhFbFJHNkpoMVl0a3NJL29wUVkwN21MRTBGU3dNUHdtY29jbFpKVEN3UW9VTA0KRzlHL0FvR0FWM25kcWcydnUyR0x4TlRUbm1UTWRJNFB3UzBmN0V4VnVNUnRicGZyOWhKNzlDakVNTGFXQ1FsNg0KeE43TElMTnArNVQwQW1DZVBqcitkbnJkRUNidFZPTDFybDc3Z0krRkwzaVVqYmZmMVZqa0N3M0x6K3cyb1FFdA0KbGE4aTZrL1NRK01iYkRPaWRJOVczdlN6MmlJRlZobWJiK1Q2SlZwakxqNjlkblM3eUxZPQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg==",
|
|
||||||
"IsResponseEncreptEnable": true,
|
|
||||||
"ApiPathList": [
|
"ApiPathList": [
|
||||||
"/test/get"
|
"/test/get"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang='en'>
|
||||||
|
<head>
|
||||||
|
<meta charset='UTF-8'>
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||||
|
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||||
|
<div style='padding-top: 20px;'>
|
||||||
|
<div style='line-height: 40px;font-size: 18px'>
|
||||||
|
尊敬的 {0} ,您好:
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
{company abbreviation}为您添加了账户,账户信息如下:
|
||||||
|
</div>
|
||||||
|
<span style="color: #00D1B2"></span>
|
||||||
|
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
|
||||||
|
<div>
|
||||||
|
用户名: {1}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
角色: {2}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
首次登陆前,请通过该链接修改您的账户信息:
|
||||||
|
<a href='{3}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
|
||||||
|
初始化账号信息
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||||
|
<div>祝您顺利!</div>
|
||||||
|
<div style="font-size: 14px;">{company}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang='en'>
|
||||||
|
<head>
|
||||||
|
<meta charset='UTF-8'>
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||||
|
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||||
|
<div style='padding-top: 20px;'>
|
||||||
|
<div style='line-height: 40px;font-size: 18px'>
|
||||||
|
Dear {0} ,
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
{company abbreviation} has created an account for you. The account information is as follows:
|
||||||
|
</div>
|
||||||
|
<span style="color: #00D1B2"></span>
|
||||||
|
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
|
||||||
|
<div>
|
||||||
|
User ID: {1}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Role: {2}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Before logging in for the first time, please modify the account information through this link:
|
||||||
|
<a href='{3}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
|
||||||
|
Initialize account information
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||||
|
<div>Best regards,</div>
|
||||||
|
<div style="font-size: 14px;">{company}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang='en'>
|
||||||
|
<head>
|
||||||
|
<meta charset='UTF-8'>
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||||
|
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||||
|
<div style='padding-top: 20px;'>
|
||||||
|
<div style='line-height: 40px;font-size: 18px'>
|
||||||
|
尊敬的 {0} ,您好:
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
{company abbreviation}将您的账户密码已重置,账户信息如下:
|
||||||
|
</div>
|
||||||
|
<span style="color: #00D1B2"></span>
|
||||||
|
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
|
||||||
|
<div>
|
||||||
|
用户名: {1}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
角色: {2}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
密码: {3}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||||
|
<div>祝您顺利!</div>
|
||||||
|
<div style="font-size: 14px;">{company}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang='en'>
|
||||||
|
<head>
|
||||||
|
<meta charset='UTF-8'>
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||||
|
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||||
|
<div style='padding-top: 20px;'>
|
||||||
|
<div style='line-height: 40px;font-size: 18px'>
|
||||||
|
Dear {0} ,
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
{company abbreviation} has reset your account password, and the account information is as follows:
|
||||||
|
</div>
|
||||||
|
<span style="color: #00D1B2"></span>
|
||||||
|
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
|
||||||
|
<div>
|
||||||
|
User ID: {1}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Role: {2}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Password: {3}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||||
|
<div>Best regards,</div>
|
||||||
|
<div style="font-size: 14px;">{company}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang='en'>
|
||||||
|
<head>
|
||||||
|
<meta charset='UTF-8'>
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||||
|
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||||
|
<div style='padding-top: 20px;'>
|
||||||
|
<div style='line-height: 40px;font-size: 18px'>
|
||||||
|
您好:
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
感谢您使用展影云平台。
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
{0}。
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||||
|
<div>祝您顺利!</div>
|
||||||
|
<div style="font-size: 14px;">{company}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang='en'>
|
||||||
|
<head>
|
||||||
|
<meta charset='UTF-8'>
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||||
|
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||||
|
<div style='padding-top: 20px;'>
|
||||||
|
<div style='line-height: 40px;font-size: 18px'>
|
||||||
|
Dear:
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
Thank you for using {company abbreviation} Cloud System.
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
{0}。
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||||
|
<div>Best regards,</div>
|
||||||
|
<div style="font-size: 14px;">{company}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang='en'>
|
||||||
|
<head>
|
||||||
|
<meta charset='UTF-8'>
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||||
|
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||||
|
<div style='padding-top: 20px;'>
|
||||||
|
<div style='line-height: 40px;font-size: 18px'>
|
||||||
|
尊敬的 {0} ,您好:
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
{company abbreviation}作为 [{1} (试验方案号:{2 })] 项目的供应商,诚邀您参加该项目阅片相关工作。
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
该项目采用电子化工作流,系统及您的账号信息如下:
|
||||||
|
</div>
|
||||||
|
<span style="color: #00D1B2"></span>
|
||||||
|
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
|
||||||
|
<div>
|
||||||
|
项目编号: {3}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
试验方案号: {2}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
试验名称: {1}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
用户名: {4}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
角色: {5}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
系统登录地址:
|
||||||
|
<a href='{6}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
|
||||||
|
点击跳转
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||||
|
<div>祝您顺利!</div>
|
||||||
|
<div style="font-size: 14px;">{company}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang='en'>
|
||||||
|
<head>
|
||||||
|
<meta charset='UTF-8'>
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||||
|
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||||
|
<div style='padding-top: 20px;'>
|
||||||
|
<div style='line-height: 40px;font-size: 18px'>
|
||||||
|
Dear {0},
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
|
||||||
|
{company abbreviation} invites you to participate in the IRC work of a trial ({1} , {2}).
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
Your account information is as follows:
|
||||||
|
</div>
|
||||||
|
<span style="color: #00D1B2"></span>
|
||||||
|
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
|
||||||
|
<div>
|
||||||
|
Trial ID: {3}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Protocol ID: {2}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Study Name: {1}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
User ID: {4}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Role: {5}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Login URL:
|
||||||
|
<a href='{6}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
|
||||||
|
Click to login
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||||
|
<div>Best regards,</div>
|
||||||
|
<div style="font-size: 14px;">{company}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang='en'>
|
||||||
|
<head>
|
||||||
|
<meta charset='UTF-8'>
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||||
|
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||||
|
<div style='padding-top: 20px;'>
|
||||||
|
<div style='line-height: 40px;font-size: 18px'>
|
||||||
|
尊敬的 {0} ,您好:
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
{company abbreviation}作为 [{1} (试验方案号:{2 })] 项目的IRC供应商,诚邀您参加该项目IRC阅片相关工作,欢迎您提供指导和建议,非常感谢!
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
该项目采用电子化工作流,系统及您的账号信息如下:
|
||||||
|
</div>
|
||||||
|
<span style="color: #00D1B2"></span>
|
||||||
|
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
|
||||||
|
<div>
|
||||||
|
项目编号: {3}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
试验方案号: {2}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
试验名称: {1}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
用户名: {4}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
角色: {5}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
首次登陆前,请通过该链接修改您的账户信息:
|
||||||
|
<a href='{6}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
|
||||||
|
初始化账号信息
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||||
|
<div>祝您顺利!</div>
|
||||||
|
<div style="font-size: 14px;">{company}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang='en'>
|
||||||
|
<head>
|
||||||
|
<meta charset='UTF-8'>
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||||
|
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||||
|
<div style='padding-top: 20px;'>
|
||||||
|
<div style='line-height: 40px;font-size: 18px'>
|
||||||
|
Dear {0},
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
{company abbreviation} invites you to participate in the IRC work of a trial ({1}, {2}).
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
Your account information is as follows:
|
||||||
|
</div>
|
||||||
|
<span style="color: #00D1B2"></span>
|
||||||
|
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
|
||||||
|
<div>
|
||||||
|
Trial ID: {3}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Protocol ID: {2}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Study Name: {1}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
User ID: {4}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Role: {5}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Before logging in for the first time, please modify the account information through this link:
|
||||||
|
<a href='{6}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
|
||||||
|
Initialize account information
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||||
|
<div>Best regards,</div>
|
||||||
|
<div style="font-size: 14px;">{company}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang='en'>
|
||||||
|
<head>
|
||||||
|
<meta charset='UTF-8'>
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||||
|
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||||
|
<div style='padding-top: 20px;'>
|
||||||
|
<div style='line-height: 40px;font-size: 18px'>
|
||||||
|
尊敬的 {0} ,您好:
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
您填写的中心调研表被驳回,详细信息如下:
|
||||||
|
</div>
|
||||||
|
<span style="color: #00D1B2"></span>
|
||||||
|
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
|
||||||
|
<div>
|
||||||
|
项目编号: {1}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
试验方案号: {2}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
试验名称: {3}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
中心编号: {4}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
中心名称: {5}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
驳回原因: {6}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<a href='{7}' style='margin-left:60px;font-size:14px;padding: 10px;text-decoration: none;display:{8} ;height: 40px;width: 140px;background: #00D1B2;color:#fff;border-radius: 5px;line-height: 40px;text-align: center;margin-bottom: 100px;'>
|
||||||
|
登陆并查看
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||||
|
<div>祝您顺利!</div>
|
||||||
|
<div style="font-size: 14px;">{company}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang='en'>
|
||||||
|
<head>
|
||||||
|
<meta charset='UTF-8'>
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||||
|
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||||
|
<div style='padding-top: 20px;'>
|
||||||
|
<div style='line-height: 40px;font-size: 18px'>
|
||||||
|
Dear {0} ,
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
The site survey form you filled in has been rejected. The details are as follows:
|
||||||
|
</div>
|
||||||
|
<span style="color: #00D1B2"></span>
|
||||||
|
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
|
||||||
|
<div>
|
||||||
|
Trial ID: {1}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Protocol ID: {2}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Study Name: {3}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Site ID: {4}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Site name: {5}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Reason for rejection: {6}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<a href='{7}' style='margin-left:60px;font-size:14px;padding: 10px;text-decoration: none;display:{8} ;height: 40px;width: 140px;background: #00D1B2;color:#fff;border-radius: 5px;line-height: 40px;text-align: center;margin-bottom: 100px;'>
|
||||||
|
Login and view
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||||
|
<div>Best regards,</div>
|
||||||
|
<div style="font-size: 14px;">{company}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang='en'>
|
||||||
|
<head>
|
||||||
|
<meta charset='UTF-8'>
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||||
|
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||||
|
<div style='padding-top: 20px;'>
|
||||||
|
<div style='line-height: 40px;font-size: 18px'>
|
||||||
|
尊敬的 {0} ,您好:
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
{company abbreviation}作为 [{1} (试验方案号:{2 })] 项目的供应商,诚邀您参加该项目相关工作,欢迎您提供指导和建议,非常感谢!
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
该项目采用电子化工作流,系统及您的账号信息如下:
|
||||||
|
</div>
|
||||||
|
<span style="color: #00D1B2"></span>
|
||||||
|
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
|
||||||
|
<div>
|
||||||
|
项目编号: {3}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
试验方案号: {2}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
试验名称: {1}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
用户名: {4}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
角色: {5}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
系统登录地址:
|
||||||
|
<a href='{6}' style='margin-left:5px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
|
||||||
|
点击跳转
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||||
|
<div>祝您顺利!</div>
|
||||||
|
<div style="font-size: 14px;">{company}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang='en'>
|
||||||
|
<head>
|
||||||
|
<meta charset='UTF-8'>
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||||
|
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||||
|
<div style='padding-top: 20px;'>
|
||||||
|
<div style='line-height: 40px;font-size: 18px'>
|
||||||
|
Dear {0},
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
|
||||||
|
{company abbreviation} invites you to participate in the IRC work of a trial ({1}, {2}).
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
Your account information is as follows:
|
||||||
|
</div>
|
||||||
|
<span style="color: #00D1B2"></span>
|
||||||
|
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
|
||||||
|
<div>
|
||||||
|
Trial ID: {3}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Protocol ID: {2}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Study Name: {1}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
User ID: {4}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Role: {5}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Login URL:
|
||||||
|
<a href='{6}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
|
||||||
|
Click to login
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||||
|
<div>Best regards,</div>
|
||||||
|
<div style="font-size: 14px;">{company}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang='en'>
|
||||||
|
<head>
|
||||||
|
<meta charset='UTF-8'>
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||||
|
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||||
|
<div style='padding-top: 20px;'>
|
||||||
|
<div style='line-height: 40px;font-size: 18px'>
|
||||||
|
尊敬的 {0} ,您好:
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
{company abbreviation}作为 [{1} (试验方案号:{2 })] 项目的IRC供应商,诚邀您参加该项目IRC相关工作,欢迎您提供指导和建议,非常感谢!
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
该项目采用电子化工作流,系统及您的账号信息如下:
|
||||||
|
</div>
|
||||||
|
<span style="color: #00D1B2"></span>
|
||||||
|
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
|
||||||
|
<div>
|
||||||
|
项目编号: {3}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
试验方案号: {2}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
试验名称: {1}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
用户名: {4}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
角色: {5}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
首次登陆前,请通过该链接修改您的账户信息:
|
||||||
|
<a href='{6}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
|
||||||
|
初始化账号信息
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||||
|
<div>祝您顺利!</div>
|
||||||
|
<div style="font-size: 14px;">{company}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang='en'>
|
||||||
|
<head>
|
||||||
|
<meta charset='UTF-8'>
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||||
|
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||||
|
<div style='padding-top: 20px;'>
|
||||||
|
<div style='line-height: 40px;font-size: 18px'>
|
||||||
|
Dear {0},
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
{company abbreviation} invites you to participate in the IRC work of a trial ({1}, {2}).
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
Your account information is as follows:
|
||||||
|
</div>
|
||||||
|
<span style="color: #00D1B2"></span>
|
||||||
|
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
|
||||||
|
<div>
|
||||||
|
Trial ID: {3}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Protocol ID: {2}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Study Name: {1}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
User ID: {4}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Role: {5}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Before logging in for the first time, please modify the account information through this link:
|
||||||
|
<a href='{6}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
|
||||||
|
Initialize the account information
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||||
|
<div>Best regards,</div>
|
||||||
|
<div style="font-size: 14px;">{company}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang='en'>
|
||||||
|
<head>
|
||||||
|
<meta charset='UTF-8'>
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||||
|
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||||
|
<div style='padding-top: 20px;'>
|
||||||
|
<div style='line-height: 40px;font-size: 18px'>
|
||||||
|
{0}您好,
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
感谢您使用展影云平台。
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
{1},验证码是: <span style="font-weight:bold">{2}</span>。
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
请在3分钟内输入该验证码,进行后续操作
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||||
|
<div>祝您顺利!</div>
|
||||||
|
<div style="font-size: 14px;">{company}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang='en'>
|
||||||
|
<head>
|
||||||
|
<meta charset='UTF-8'>
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||||
|
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||||
|
<div style='padding-top: 20px;'>
|
||||||
|
<div style='line-height: 40px;font-size: 18px'>
|
||||||
|
Dear {0},
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
{1}
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
The verification code is <span style="font-weight:bold">{2}</span>.
|
||||||
|
</div>
|
||||||
|
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||||
|
This code will expire in 3 minutes.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||||
|
<div>Best regards,</div>
|
||||||
|
<div style="font-size: 14px;">{company}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -31,9 +31,9 @@ namespace IRaCIS.Core.Application.Auth
|
|||||||
Id = user.Id,
|
Id = user.Id,
|
||||||
FullName = user.UserName,
|
FullName = user.UserName,
|
||||||
RealName = user.RealName,
|
RealName = user.RealName,
|
||||||
UserTypeEnum = user.UserTypeEnum,
|
UserTypeEnum=user.UserTypeEnum,
|
||||||
UserTypeId = user.UserTypeId,
|
UserTypeId=user.UserTypeId,
|
||||||
IsTestUser = user.IsTestUser,
|
IsTestUser=user.IsTestUser,
|
||||||
Code = user.Code,
|
Code = user.Code,
|
||||||
PermissionStr = user.PermissionStr,
|
PermissionStr = user.PermissionStr,
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
namespace IRaCIS.Core.Application.Auth
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.Application.Auth
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
@@ -7,7 +13,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public const string CRC = "CRC";
|
public const string CRC = "CRC";
|
||||||
|
|
||||||
public const string PM = "PM";
|
public const string PM = "PM";
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Microsoft.IdentityModel.Tokens;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Auth
|
namespace IRaCIS.Core.Application.Auth
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using IRaCIS.Core.Domain.Share;
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
using System.IdentityModel.Tokens.Jwt;
|
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Auth
|
namespace IRaCIS.Core.Application.Auth
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,56 +1,97 @@
|
|||||||
using Hangfire;
|
using EasyCaching.Core;
|
||||||
|
using Hangfire;
|
||||||
using Hangfire.Storage;
|
using Hangfire.Storage;
|
||||||
using IRaCIS.Core.Application.Helper;
|
using IRaCIS.Core.Application.Helper;
|
||||||
|
using IRaCIS.Core.Application.Service;
|
||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using IRaCIS.Core.Infrastructure;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using SharpCompress.Common;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Service.BackGroundJob
|
namespace IRaCIS.Application.Services.BackGroundJob
|
||||||
{
|
{
|
||||||
|
|
||||||
public interface IIRaCISHangfireJob
|
public interface IIRaCISHangfireJob
|
||||||
{
|
{
|
||||||
|
|
||||||
//Task MemoryCacheTrialStatusAsync();
|
Task MemoryCacheTrialStatusAsync();
|
||||||
|
|
||||||
Task InitHangfireJobTaskAsync();
|
Task InitHangfireJobTaskAsync();
|
||||||
|
|
||||||
}
|
}
|
||||||
public class IRaCISCHangfireJob(ILogger<IRaCISCHangfireJob> _logger,
|
public class IRaCISCHangfireJob : IIRaCISHangfireJob
|
||||||
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);
|
||||||
|
|
||||||
|
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 MemoryCacheTrialStatusAsync();
|
||||||
|
|
||||||
|
await MemoryCacheAnonymizeData();
|
||||||
|
|
||||||
|
|
||||||
|
//创建项目缓存 定时任务
|
||||||
|
HangfireJobHelper.AddOrUpdateInitCronJob<IIRaCISHangfireJob>("RecurringJob_Cache_TrialState", t => t.MemoryCacheTrialStatusAsync(), Cron.Daily());
|
||||||
|
|
||||||
|
//初始化
|
||||||
|
|
||||||
await InternationalizationHelper.InitInternationlizationDataAndWatchJsonFileAsync(_internationalizationRepository);
|
await InternationalizationHelper.InitInternationlizationDataAndWatchJsonFileAsync(_internationalizationRepository);
|
||||||
|
|
||||||
//创建邮件定时任务
|
//创建邮件定时任务
|
||||||
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -95,9 +136,6 @@ namespace IRaCIS.Core.Application.Service.BackGroundJob
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
using Microsoft.Extensions.Logging;
|
using IRaCIS.Core.Infra.EFCore;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.BackGroundJob
|
namespace IRaCIS.Core.Application.BackGroundJob
|
||||||
{
|
{
|
||||||
public interface IObtainTaskAutoCancelJob
|
public interface IObtainTaskAutoCancelJob
|
||||||
{
|
{
|
||||||
Task CancelQCObtaion(Guid subjectVisitId, DateTime startTime);
|
Task CancelQCObtaion(Guid subjectVisitId,DateTime startTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ObtainTaskAutoCancelJob : IObtainTaskAutoCancelJob
|
public class ObtainTaskAutoCancelJob : IObtainTaskAutoCancelJob
|
||||||
@@ -12,7 +13,7 @@ namespace IRaCIS.Core.Application.BackGroundJob
|
|||||||
private readonly IRepository<SubjectVisit> _subjectVisitRepository;
|
private readonly IRepository<SubjectVisit> _subjectVisitRepository;
|
||||||
private readonly ILogger<ObtainTaskAutoCancelJob> _logger;
|
private readonly ILogger<ObtainTaskAutoCancelJob> _logger;
|
||||||
|
|
||||||
public ObtainTaskAutoCancelJob(IRepository<SubjectVisit> subjectVisitRepository, ILogger<ObtainTaskAutoCancelJob> logger)
|
public ObtainTaskAutoCancelJob(IRepository<SubjectVisit> subjectVisitRepository, ILogger<ObtainTaskAutoCancelJob> logger)
|
||||||
{
|
{
|
||||||
_subjectVisitRepository = subjectVisitRepository;
|
_subjectVisitRepository = subjectVisitRepository;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
@@ -29,7 +30,7 @@ namespace IRaCIS.Core.Application.BackGroundJob
|
|||||||
|
|
||||||
var success = await _subjectVisitRepository.SaveChangesAsync();
|
var success = await _subjectVisitRepository.SaveChangesAsync();
|
||||||
|
|
||||||
_logger.LogWarning($"任务建立时间:{startTime} 取消时间:{DateTime.Now} 取消 受试者访视:{subjectVisitId}success:{success}");
|
_logger.LogWarning($"任务建立时间:{startTime} 取消时间:{DateTime.Now} 取消 受试者访视:{ subjectVisitId }success:{success}");
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using IRaCIS.Core.Application.Service.BusinessFilter;
|
using IRaCIS.Application.Services.BusinessFilter;
|
||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Infra.EFCore;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.Extensions.Localization;
|
using Microsoft.Extensions.Localization;
|
||||||
using Panda.DynamicWebApi;
|
using Panda.DynamicWebApi;
|
||||||
using Panda.DynamicWebApi.Attributes;
|
using Panda.DynamicWebApi.Attributes;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using ZiggyCreatures.Caching.Fusion;
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Service
|
namespace IRaCIS.Core.Application
|
||||||
{
|
{
|
||||||
|
|
||||||
#pragma warning disable CS8618
|
#pragma warning disable CS8618
|
||||||
@@ -26,13 +26,13 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
public IUserInfo _userInfo { get; set; }
|
public IUserInfo _userInfo { get; set; }
|
||||||
|
|
||||||
|
public IRepository _repository { get; set; }
|
||||||
|
|
||||||
public IStringLocalizer _localizer { get; set; }
|
public IStringLocalizer _localizer { get; set; }
|
||||||
|
|
||||||
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
|
||||||
@@ -51,6 +51,8 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
[MemberNotNull(nameof(_userInfo))]
|
[MemberNotNull(nameof(_userInfo))]
|
||||||
public IUserInfo _userInfo { get; set; }
|
public IUserInfo _userInfo { get; set; }
|
||||||
|
|
||||||
|
[MemberNotNull(nameof(_repository))]
|
||||||
|
public IRepository _repository { get; set; }
|
||||||
|
|
||||||
[MemberNotNull(nameof(_localizer))]
|
[MemberNotNull(nameof(_localizer))]
|
||||||
public IStringLocalizer _localizer { get; set; }
|
public IStringLocalizer _localizer { get; set; }
|
||||||
@@ -58,9 +60,6 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
[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
|
||||||
|
|
||||||
@@ -76,11 +75,13 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
[MemberNotNull(nameof(_userInfo))]
|
[MemberNotNull(nameof(_userInfo))]
|
||||||
public IUserInfo _userInfo { get; set; }
|
public IUserInfo _userInfo { get; set; }
|
||||||
|
|
||||||
|
[MemberNotNull(nameof(_repository))]
|
||||||
|
public IRepository _repository { get; set; }
|
||||||
|
|
||||||
[MemberNotNull(nameof(_localizer))]
|
[MemberNotNull(nameof(_localizer))]
|
||||||
public IStringLocalizer _localizer { get; set; }
|
public IStringLocalizer _localizer { get; set; }
|
||||||
|
|
||||||
[MemberNotNull(nameof(_fusionCache))]
|
|
||||||
public IFusionCache _fusionCache { get; set; }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,9 +93,9 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
public IUserInfo _userInfo { get; set; }
|
public IUserInfo _userInfo { get; set; }
|
||||||
|
|
||||||
public IStringLocalizer _localizer { get; set; }
|
public IRepository _repository { get; set; }
|
||||||
|
|
||||||
public IFusionCache _fusionCache { get; set; }
|
public IStringLocalizer _localizer { get; set; }
|
||||||
|
|
||||||
public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class
|
public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
using IRaCIS.Core.Domain.Share;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.BusinessFilter;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 测试加密API 返回的结果
|
|
||||||
/// </summary>
|
|
||||||
public class EncreptApiResultFilter : IAsyncResultFilter
|
|
||||||
{
|
|
||||||
private readonly IOptionsMonitor<IRCEncreptOption> _encreptResponseMonitor;
|
|
||||||
|
|
||||||
public EncreptApiResultFilter(IOptionsMonitor<IRCEncreptOption> encreptResponseMonitor)
|
|
||||||
{
|
|
||||||
_encreptResponseMonitor = encreptResponseMonitor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (_encreptResponseMonitor.CurrentValue.IsResponseEncreptEnable)
|
|
||||||
{
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,130 +0,0 @@
|
|||||||
using IRaCIS.Core.Domain.Share;
|
|
||||||
using IRaCIS.Core.Infrastructure.Encryption;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.BusinessFilter;
|
|
||||||
|
|
||||||
public class EncryptionRequestMiddleware
|
|
||||||
{
|
|
||||||
private readonly RequestDelegate _next;
|
|
||||||
|
|
||||||
private readonly IRCEncreptOption _IRCEncreptOption;
|
|
||||||
|
|
||||||
public EncryptionRequestMiddleware(RequestDelegate next, IOptionsMonitor<IRCEncreptOption> encreptResponseMonitor)
|
|
||||||
{
|
|
||||||
_next = next;
|
|
||||||
|
|
||||||
_IRCEncreptOption = encreptResponseMonitor.CurrentValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task InvokeAsync(HttpContext context)
|
|
||||||
{
|
|
||||||
//模拟前端已经设置该请求头
|
|
||||||
//context.Request.Headers["X-Encrypted-Key"] = "hW8JuJocBzIPWSHURUnYJMZ0l68g6uP9rEdMho8ioFO8amD6GIH+R6RIX5jVFzOwO+lmgBi+4gaVJGGkWJMTcoDTfzzzT1EmfPV+UhFLE9HWvCkEXmDOLE9xCHrbG8TrR1I9+Qd3cvo9HLmrQ58n13cJsM82FBw+reUgiWeklPCkEWM9br2qc9VkCp6gKzimTldNTWBezV86S6j3qHbZpVZm0atdDtGb+zSC9LLA3+oHQwRLJAAGSOAi8CUiRmIQsygRd824wBndkaH2ImEeRjBMs7PqCeK3KsoDp13yHdj2AE751gsfNzf4SF547UPf72m0F2/rBFgrSNy+Jz0T9w==";
|
|
||||||
|
|
||||||
// 检查请求头中是否包含加密的对称密钥
|
|
||||||
if (context.Request.Headers.ContainsKey("X-Encrypted-Key"))
|
|
||||||
{
|
|
||||||
|
|
||||||
var encryptedSymmetricKeyStr = context.Request.Headers["X-Encrypted-Key"].ToString();
|
|
||||||
|
|
||||||
var pemSecretKey = Encoding.UTF8.GetString(Convert.FromBase64String(_IRCEncreptOption.Base64RSAPrivateKey));
|
|
||||||
|
|
||||||
// 使用私钥解密对称密钥
|
|
||||||
var decryptedSymmetricKey = RSAEncryption.Decrypt(pemSecretKey, encryptedSymmetricKeyStr);
|
|
||||||
|
|
||||||
|
|
||||||
#region 处理路径传递参数
|
|
||||||
|
|
||||||
// 处理路径参数解密
|
|
||||||
var path = context.Request.Path.Value;
|
|
||||||
|
|
||||||
// 假设加密的参数在路径中,按照顺序解密路径中的每个部分
|
|
||||||
var pathSegments = path.Split('/', StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
for (int i = 2; i < pathSegments.Length; i++)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(pathSegments[i]))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var decryptedSegment = AesEncryption.Decrypt(pathSegments[i], decryptedSymmetricKey);
|
|
||||||
pathSegments[i] = decryptedSegment;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// 如果不能解密该部分,保持原值
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将解密后的路径重新拼接并设置到请求的Path
|
|
||||||
context.Request.Path = "/" + string.Join("/", pathSegments);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 处理url 传递参数
|
|
||||||
|
|
||||||
// 处理 URL 查询参数的解密
|
|
||||||
var queryParams = context.Request.Query.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.ToString());
|
|
||||||
var decryptedQueryParams = new Dictionary<string, string>();
|
|
||||||
|
|
||||||
foreach (var param in queryParams)
|
|
||||||
{
|
|
||||||
var encryptedValue = param.Value;
|
|
||||||
var decryptedValue = AesEncryption.Decrypt(encryptedValue, decryptedSymmetricKey);
|
|
||||||
decryptedQueryParams[param.Key] = decryptedValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构造解密后的查询字符串
|
|
||||||
var decryptedQueryString = new QueryString("?" + string.Join("&", decryptedQueryParams.Select(kvp => $"{kvp.Key}={kvp.Value}")));
|
|
||||||
context.Request.QueryString = decryptedQueryString;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 处理body传参
|
|
||||||
|
|
||||||
// 读取并解密请求体中的JSON数据
|
|
||||||
context.Request.EnableBuffering();
|
|
||||||
using (var reader = new StreamReader(context.Request.Body, Encoding.UTF8, leaveOpen: true))
|
|
||||||
{
|
|
||||||
var encryptedBody = await reader.ReadToEndAsync();
|
|
||||||
context.Request.Body.Position = 0;
|
|
||||||
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(encryptedBody))
|
|
||||||
{
|
|
||||||
// 尝试解析为JObject
|
|
||||||
var encryptedJson = JObject.Parse(encryptedBody);
|
|
||||||
var decryptedJson = new JObject();
|
|
||||||
|
|
||||||
// 解密每个字段的值
|
|
||||||
foreach (var property in encryptedJson.Properties())
|
|
||||||
{
|
|
||||||
var encryptedValue = property.Value.ToString();
|
|
||||||
var decryptedValue = AesEncryption.Decrypt(encryptedValue, decryptedSymmetricKey);
|
|
||||||
decryptedJson[property.Name] = decryptedValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将解密后的JSON对象转换回字符串,并替换原始请求体
|
|
||||||
var decryptedBody = decryptedJson.ToString();
|
|
||||||
var bodyStream = new MemoryStream(Encoding.UTF8.GetBytes(decryptedBody));
|
|
||||||
context.Request.Body = bodyStream;
|
|
||||||
context.Request.ContentLength = bodyStream.Length;
|
|
||||||
bodyStream.Seek(0, SeekOrigin.Begin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
// 调用下一个中间件
|
|
||||||
await _next(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Diagnostics;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
|
|
||||||
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,12 +1,13 @@
|
|||||||
using IRaCIS.Core.Application.Helper;
|
using EasyCaching.Core;
|
||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using Microsoft.AspNetCore.Authentication;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
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 Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using ZiggyCreatures.Caching.Fusion;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Filter;
|
namespace IRaCIS.Core.Application.Filter;
|
||||||
|
|
||||||
@@ -17,15 +18,15 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter
|
|||||||
{
|
{
|
||||||
public IStringLocalizer _localizer { get; set; }
|
public IStringLocalizer _localizer { get; set; }
|
||||||
|
|
||||||
private readonly IFusionCache _fusionCache;
|
private readonly IEasyCachingProvider _provider;
|
||||||
|
|
||||||
private readonly IUserInfo _userInfo;
|
private readonly IUserInfo _userInfo;
|
||||||
|
|
||||||
private readonly IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig;
|
private readonly IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig;
|
||||||
|
|
||||||
public LimitUserRequestAuthorization(IFusionCache fusionCache, IUserInfo userInfo, IStringLocalizer localizer, IOptionsMonitor<ServiceVerifyConfigOption> verifyConfig)
|
public LimitUserRequestAuthorization(IEasyCachingProvider provider, IUserInfo userInfo, IStringLocalizer localizer ,IOptionsMonitor<ServiceVerifyConfigOption> verifyConfig)
|
||||||
{
|
{
|
||||||
_fusionCache = fusionCache;
|
_provider = provider;
|
||||||
_userInfo = userInfo;
|
_userInfo = userInfo;
|
||||||
_verifyConfig = verifyConfig;
|
_verifyConfig = verifyConfig;
|
||||||
_localizer = localizer;
|
_localizer = localizer;
|
||||||
@@ -53,7 +54,7 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter
|
|||||||
{
|
{
|
||||||
context.HttpContext.Response.ContentType = "application/json";
|
context.HttpContext.Response.ContentType = "application/json";
|
||||||
context.HttpContext.Response.StatusCode = StatusCodes.Status200OK;
|
context.HttpContext.Response.StatusCode = StatusCodes.Status200OK;
|
||||||
//---当前请求未从Header/Url取到用户Token,请联系开发者
|
//---当前请求未从Header/Url取到用户Token,请联系开发者
|
||||||
//await context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk(_localizer["LimitUser_AuthTokenMissing"])));
|
//await context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk(_localizer["LimitUser_AuthTokenMissing"])));
|
||||||
|
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["LimitUser_AuthTokenMissing"]));
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["LimitUser_AuthTokenMissing"]));
|
||||||
@@ -62,7 +63,7 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter
|
|||||||
|
|
||||||
|
|
||||||
//2、在这里取缓存 进行比较 看是否有其他人进行了登陆,如果其他人登陆了,就把之前用户挤掉
|
//2、在这里取缓存 进行比较 看是否有其他人进行了登陆,如果其他人登陆了,就把之前用户挤掉
|
||||||
var cacheUserToken = await _fusionCache.GetOrDefaultAsync<string>(CacheKeys.UserToken(_userInfo.Id));
|
var cacheUserToken = (await _provider.GetAsync<string>(_userInfo.Id.ToString())).Value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -72,17 +73,17 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter
|
|||||||
cacheUserToken = _userInfo.UserToken;
|
cacheUserToken = _userInfo.UserToken;
|
||||||
|
|
||||||
//设置当前用户最新Token
|
//设置当前用户最新Token
|
||||||
await _fusionCache.SetAsync(CacheKeys.UserToken(_userInfo.Id), _userInfo.UserToken, TimeSpan.FromDays(7));
|
await _provider.SetAsync(_userInfo.Id.ToString(), _userInfo.UserToken, TimeSpan.FromDays(7));
|
||||||
|
|
||||||
//重启应用程序,所有人续期,不一下子踢出所有人
|
//重启应用程序,所有人续期,不一下子踢出所有人
|
||||||
await _fusionCache.SetAsync(CacheKeys.UserAutoLoginOut(_userInfo.Id), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(minutes));
|
await _provider.SetAsync($"{_userInfo.Id.ToString()}_Online", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(minutes));
|
||||||
|
|
||||||
}
|
}
|
||||||
//是同一个人
|
//是同一个人
|
||||||
else if (cacheUserToken == _userInfo.UserToken)
|
else if (cacheUserToken == _userInfo.UserToken)
|
||||||
{
|
{
|
||||||
|
|
||||||
var cacheTime = await _fusionCache.GetOrDefaultAsync<string>(CacheKeys.UserAutoLoginOut(_userInfo.Id));
|
var cacheTime = (await _provider.GetAsync<string>($"{_userInfo.Id.ToString()}_Online")).Value;
|
||||||
|
|
||||||
//过期了 需要自动退出
|
//过期了 需要自动退出
|
||||||
if (string.IsNullOrEmpty(cacheTime))
|
if (string.IsNullOrEmpty(cacheTime))
|
||||||
@@ -91,22 +92,32 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter
|
|||||||
context.HttpContext.Response.StatusCode = StatusCodes.Status403Forbidden;
|
context.HttpContext.Response.StatusCode = StatusCodes.Status403Forbidden;
|
||||||
|
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["LimitUser_AccountAuto_LoginOut"], ApiResponseCodeEnum.AutoLoginOut));
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["LimitUser_AccountAuto_LoginOut"], ApiResponseCodeEnum.AutoLoginOut));
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await _fusionCache.SetAsync(CacheKeys.UserAutoLoginOut(_userInfo.Id), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(minutes));
|
await _provider.SetAsync($"{_userInfo.Id.ToString()}_Online", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(minutes));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
context.HttpContext.Response.ContentType = "application/json";
|
context.HttpContext.Response.ContentType = "application/json";
|
||||||
context.HttpContext.Response.StatusCode = StatusCodes.Status403Forbidden;
|
context.HttpContext.Response.StatusCode = StatusCodes.Status403Forbidden;
|
||||||
//---您的账户在其他地方已登陆,您被迫下线。
|
//---您的账户在其他地方已登陆,您被迫下线。
|
||||||
|
|
||||||
|
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["LimitUser_AccountLoggedInElsewhere"], ApiResponseCodeEnum.LoginInOtherPlace));
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["LimitUser_AccountLoggedInElsewhere"], ApiResponseCodeEnum.LoginInOtherPlace));
|
||||||
|
|
||||||
|
|
||||||
|
//await context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk(_localizer["LimitUser_AccountLoggedInElsewhere"], ApiResponseCodeEnum.LoginInOtherPlace)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,3 +125,52 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//public class UserTypeRequirement : IAuthorizationRequirement
|
||||||
|
//{
|
||||||
|
//}
|
||||||
|
|
||||||
|
//public class UserTypeHandler : AuthorizationHandler<UserTypeRequirement>
|
||||||
|
//{
|
||||||
|
|
||||||
|
// private IUserInfo _userInfo;
|
||||||
|
|
||||||
|
// public UserTypeHandler(IUserInfo userInfo)
|
||||||
|
// {
|
||||||
|
// _userInfo = userInfo;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, UserTypeRequirement requirement)
|
||||||
|
// {
|
||||||
|
|
||||||
|
// //if (context.User.Claims.Count() == 0)
|
||||||
|
// //{
|
||||||
|
// // return Task.CompletedTask;
|
||||||
|
// //}
|
||||||
|
|
||||||
|
// //string userId = context.User.Claims.First(c => c.Type == "Userid").Value;
|
||||||
|
// //string qq = context.User.Claims.First(c => c.Type == "QQ").Value;
|
||||||
|
|
||||||
|
// //if (_UserService.Validata(userId, qq))
|
||||||
|
// //{
|
||||||
|
// // context.Succeed(requirement); //验证通过了
|
||||||
|
// //}
|
||||||
|
// ////在这里就可以做验证
|
||||||
|
|
||||||
|
// return Task.CompletedTask;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
|||||||
@@ -1,34 +1,37 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using IRaCIS.Core.Infrastructure.Extention;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
using Microsoft.Extensions.Localization;
|
using Microsoft.Extensions.Localization;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Filter;
|
namespace IRaCIS.Core.Application.Filter
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class ModelActionFilter : ActionFilterAttribute, IActionFilter
|
|
||||||
{
|
{
|
||||||
public IStringLocalizer _localizer;
|
|
||||||
public ModelActionFilter(IStringLocalizer localizer)
|
|
||||||
{
|
|
||||||
_localizer = localizer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnActionExecuting(ActionExecutingContext context)
|
|
||||||
|
public class ModelActionFilter : ActionFilterAttribute, IActionFilter
|
||||||
{
|
{
|
||||||
if (!context.ModelState.IsValid)
|
public IStringLocalizer _localizer;
|
||||||
|
public ModelActionFilter(IStringLocalizer localizer)
|
||||||
{
|
{
|
||||||
|
_localizer = localizer;
|
||||||
|
}
|
||||||
|
|
||||||
var validationErrors = context.ModelState
|
public override void OnActionExecuting(ActionExecutingContext context)
|
||||||
.Keys
|
{
|
||||||
.SelectMany(k => context.ModelState[k]!.Errors)
|
if (!context.ModelState.IsValid)
|
||||||
.Select(e => e.ErrorMessage)
|
{
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
//---提供给接口的参数无效。
|
var validationErrors = context.ModelState
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ModelAction_InvalidAPIParameter"] + JsonConvert.SerializeObject(validationErrors)));
|
.Keys
|
||||||
|
.SelectMany(k => context.ModelState[k]!.Errors)
|
||||||
|
.Select(e => e.ErrorMessage)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
//---提供给接口的参数无效。
|
||||||
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ModelAction_InvalidAPIParameter"] + JsonConvert.SerializeObject( validationErrors)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,28 @@
|
|||||||
|
using System;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Filter;
|
namespace IRaCIS.Core.Application.Filter
|
||||||
|
|
||||||
#region snippet_DisableFormValueModelBindingAttribute
|
|
||||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
|
||||||
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
|
|
||||||
{
|
{
|
||||||
public void OnResourceExecuting(ResourceExecutingContext context)
|
#region snippet_DisableFormValueModelBindingAttribute
|
||||||
|
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
||||||
|
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
|
||||||
{
|
{
|
||||||
|
public void OnResourceExecuting(ResourceExecutingContext context)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
var factories = context.ValueProviderFactories;
|
var factories = context.ValueProviderFactories;
|
||||||
//factories.RemoveType<FormValueProviderFactory>();
|
//factories.RemoveType<FormValueProviderFactory>();
|
||||||
factories.RemoveType<FormFileValueProviderFactory>();
|
factories.RemoveType<FormFileValueProviderFactory>();
|
||||||
factories.RemoveType<JQueryFormValueProviderFactory>();
|
factories.RemoveType<JQueryFormValueProviderFactory>();
|
||||||
context.HttpContext.Request.EnableBuffering();
|
context.HttpContext.Request.EnableBuffering();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnResourceExecuted(ResourceExecutedContext context)
|
public void OnResourceExecuted(ResourceExecutedContext context)
|
||||||
{
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
#endregion
|
|
||||||
|
|||||||
@@ -1,75 +1,71 @@
|
|||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
using IRaCIS.Core.Infrastructure;
|
using IRaCIS.Core.Infrastructure;
|
||||||
|
using IRaCIS.Core.Infrastructure.Extention;
|
||||||
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 Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Filter;
|
namespace IRaCIS.Core.Application.Filter
|
||||||
|
|
||||||
public class ProjectExceptionFilter : Attribute, IExceptionFilter
|
|
||||||
{
|
{
|
||||||
private readonly ILogger<ProjectExceptionFilter> _logger;
|
public class ProjectExceptionFilter : Attribute, IExceptionFilter
|
||||||
|
|
||||||
public IStringLocalizer _localizer;
|
|
||||||
|
|
||||||
public ProjectExceptionFilter(IStringLocalizer localizer, ILogger<ProjectExceptionFilter> logger)
|
|
||||||
{
|
{
|
||||||
_logger = logger;
|
private readonly ILogger<ProjectExceptionFilter> _logger;
|
||||||
_localizer = localizer;
|
|
||||||
}
|
|
||||||
public void OnException(ExceptionContext context)
|
|
||||||
{
|
|
||||||
//context.ExceptionHandled;//记录当前这个异常是否已经被处理过了
|
|
||||||
|
|
||||||
if (!context.ExceptionHandled)
|
public IStringLocalizer _localizer;
|
||||||
|
|
||||||
|
public ProjectExceptionFilter(IStringLocalizer localizer, ILogger<ProjectExceptionFilter> logger)
|
||||||
{
|
{
|
||||||
if (context.Exception.GetType().Name == "DbUpdateConcurrencyException")
|
_logger = logger;
|
||||||
|
_localizer = localizer;
|
||||||
|
}
|
||||||
|
public void OnException(ExceptionContext context)
|
||||||
|
{
|
||||||
|
//context.ExceptionHandled;//记录当前这个异常是否已经被处理过了
|
||||||
|
|
||||||
|
if (!context.ExceptionHandled)
|
||||||
{
|
{
|
||||||
//---并发更新,当前不允许该操作
|
if (context.Exception.GetType().Name == "DbUpdateConcurrencyException")
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ProjectException_ConcurrentUpdateNotAllowed"] + context.Exception.Message));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context.Exception.GetType() == typeof(BusinessValidationFailedException))
|
|
||||||
{
|
|
||||||
var error = context.Exception as BusinessValidationFailedException;
|
|
||||||
|
|
||||||
var info = string.Empty;
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(error!.LocalizedKey) && StaticData.Log_Locoalize_Dic.ContainsKey(error!.LocalizedKey))
|
|
||||||
{
|
{
|
||||||
info = $"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}";
|
//---并发更新,当前不允许该操作
|
||||||
|
context.Result = new JsonResult(ResponseOutput.NotOk(_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, localizedInfo: info));
|
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]}";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//warning 级别记录
|
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, "", error!.Code, localizedInfo: info));
|
||||||
//_logger.LogWarning($"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}");
|
|
||||||
}
|
//warning 级别记录
|
||||||
else if (context.Exception.GetType() == typeof(QueryBusinessObjectNotExistException))
|
//_logger.LogWarning($"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}");
|
||||||
{
|
}
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, ApiResponseCodeEnum.DataNotExist));
|
else if (context.Exception.GetType() == typeof(QueryBusinessObjectNotExistException))
|
||||||
|
{
|
||||||
|
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, ApiResponseCodeEnum.DataNotExist));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (context.Exception.InnerException is null ? (context.Exception.Message /*+ context.Exception.StackTrace*/)
|
||||||
|
: (context.Exception.InnerException?.Message /*+ context.Exception.InnerException?.StackTrace*/)), ApiResponseCodeEnum.ProgramException));
|
||||||
|
|
||||||
|
_logger.LogError(context.Exception.InnerException is null ? (context.Exception.Message + context.Exception.StackTrace) : (context.Exception.InnerException?.Message + context.Exception.InnerException?.StackTrace));
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (context.Exception.InnerException is null ? (context.Exception.Message /*+ context.Exception.StackTrace*/)
|
//继续
|
||||||
: (context.Exception.InnerException?.Message /*+ context.Exception.InnerException?.StackTrace*/)), ApiResponseCodeEnum.ProgramException));
|
|
||||||
|
|
||||||
_logger.LogError(context.Exception.InnerException is null ? (context.Exception.Message + context.Exception.StackTrace) : (context.Exception.InnerException?.Message + context.Exception.InnerException?.StackTrace));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
context.ExceptionHandled = true;//标记当前异常已经被处理过了
|
context.ExceptionHandled = true;//标记当前异常已经被处理过了
|
||||||
|
|
||||||
|
|
||||||
//throw new Exception("test-result-exceptioin");
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//继续
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,196 +1,203 @@
|
|||||||
using IRaCIS.Core.Application.Helper;
|
using EasyCaching.Core;
|
||||||
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
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 主要为了 处理项目结束 锁库,不允许操作
|
|
||||||
/// </summary>
|
|
||||||
public class TrialResourceFilter : Attribute, IAsyncResourceFilter
|
|
||||||
{
|
{
|
||||||
private readonly IUserInfo _userInfo;
|
/// <summary>
|
||||||
private readonly IFusionCache _fusionCache;
|
/// 主要为了 处理项目结束 锁库,不允许操作
|
||||||
public IStringLocalizer _localizer;
|
/// </summary>
|
||||||
private readonly IRepository<Trial> _trialRepository;
|
public class TrialResourceFilter : Attribute, IAsyncResourceFilter
|
||||||
private readonly List<string> _trialOptList = new List<string>();
|
|
||||||
|
|
||||||
|
|
||||||
public TrialResourceFilter(IFusionCache fusionCache, IRepository<Trial> trialRepository, IStringLocalizer localizer, IUserInfo userInfo, string trialOpt = null, string trialOpt2 = null, string trialOpt3 = null)
|
|
||||||
{
|
{
|
||||||
_fusionCache = fusionCache;
|
private readonly IEasyCachingProvider _provider;
|
||||||
_userInfo = userInfo;
|
private readonly IUserInfo _userInfo;
|
||||||
_localizer = localizer;
|
|
||||||
_trialRepository = trialRepository;
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(trialOpt)) _trialOptList.Add(trialOpt.Trim());
|
public IStringLocalizer _localizer;
|
||||||
if (!string.IsNullOrWhiteSpace(trialOpt2)) _trialOptList.Add(trialOpt2.Trim());
|
private readonly List<string> _trialOptList=new List<string>();
|
||||||
if (!string.IsNullOrWhiteSpace(trialOpt3)) _trialOptList.Add(trialOpt3.Trim());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//优先选择异步的方法
|
public TrialResourceFilter(IEasyCachingProvider provider, IStringLocalizer localizer , IUserInfo userInfo, string trialOpt = null, string trialOpt2 = null, string trialOpt3 = null)
|
||||||
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
|
|
||||||
{
|
|
||||||
// var typeFilter = context.ActionDescriptor.EndpointMetadata.Where(t => t.GetType() == typeof(TypeFilterAttribute)).Select(t => (TypeFilterAttribute)t).ToList().FirstOrDefault();
|
|
||||||
//var _trialOptList= typeFilter.Arguments.Select(t => t.ToString()).ToList();
|
|
||||||
|
|
||||||
// 获取当前请求的 Host 信息
|
|
||||||
var requestHost = context.HttpContext.Request.Host;
|
|
||||||
|
|
||||||
// 检查请求是否来自 localhost:6100
|
|
||||||
if (requestHost.Host == "localhost" && (requestHost.Port == 6100|| requestHost.Port==3305))
|
|
||||||
{
|
{
|
||||||
await next.Invoke();
|
_provider = provider;
|
||||||
|
_userInfo = userInfo;
|
||||||
|
_localizer = localizer;
|
||||||
|
//_trialOpt = trialOpt;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(trialOpt)) _trialOptList.Add(trialOpt.Trim());
|
||||||
|
if (!string.IsNullOrWhiteSpace(trialOpt2)) _trialOptList.Add(trialOpt2.Trim());
|
||||||
|
if (!string.IsNullOrWhiteSpace(trialOpt3)) _trialOptList.Add(trialOpt3.Trim());
|
||||||
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region 处理新的用户类型,不能操作项目相关接口
|
//优先选择异步的方法
|
||||||
|
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
|
||||||
// 后期列举出具体的类型,其他任何用户类型,都不允许操作
|
|
||||||
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower() != "TrialDocument/userConfirm".ToLower())
|
|
||||||
{
|
{
|
||||||
//---对不起,您的账户没有操作权限。
|
// var typeFilter = context.ActionDescriptor.EndpointMetadata.Where(t => t.GetType() == typeof(TypeFilterAttribute)).Select(t => (TypeFilterAttribute)t).ToList().FirstOrDefault();
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"]));
|
//var _trialOptList= typeFilter.Arguments.Select(t => t.ToString()).ToList();
|
||||||
|
|
||||||
return;
|
#region 处理新的用户类型,不能操作项目相关接口
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
// 后期列举出具体的类型,其他任何用户类型,都不允许操作
|
||||||
|
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower()!= "TrialDocument/userConfirm".ToLower())
|
||||||
|
|
||||||
|
|
||||||
//TrialId 传递的途径多种,可能在path 可能在body 可能在数组中,也可能在对象中,可能就在url
|
|
||||||
var trialIdStr = string.Empty;
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(context.HttpContext.Request.Query["trialId"]))
|
|
||||||
{
|
|
||||||
trialIdStr = context.HttpContext.Request.Query["trialId"];
|
|
||||||
}
|
|
||||||
|
|
||||||
//先尝试从path中取TrialId
|
|
||||||
else if (context.RouteData.Values.Keys.Any(t => t.Contains("trialId")))
|
|
||||||
{
|
|
||||||
var index = context.RouteData.Values.Keys.ToList().IndexOf("trialId");
|
|
||||||
trialIdStr = context.RouteData.Values.Values.ToList()[index] as string;
|
|
||||||
}
|
|
||||||
else if (context.HttpContext.Request.Headers["Referer"].ToString().Contains("trialId"))
|
|
||||||
{
|
|
||||||
var headerStr = context.HttpContext.Request.Headers["Referer"].ToString();
|
|
||||||
|
|
||||||
var trialIdIndex = headerStr.IndexOf("trialId");
|
|
||||||
|
|
||||||
|
|
||||||
var matchResult = Regex.Match(headerStr.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
|
|
||||||
|
|
||||||
if (matchResult.Success)
|
|
||||||
{
|
{
|
||||||
trialIdStr = matchResult.Value;
|
//---对不起,您的账户没有操作权限。
|
||||||
}
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"]));
|
||||||
else
|
|
||||||
{
|
|
||||||
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
return;
|
||||||
else
|
|
||||||
{
|
|
||||||
#region body 中取数据
|
|
||||||
|
|
||||||
//设置可以多次读
|
|
||||||
context.HttpContext.Request.EnableBuffering();
|
|
||||||
var reader = new StreamReader(context.HttpContext.Request.Body);
|
|
||||||
var contentFromBody = await reader.ReadToEndAsync();
|
|
||||||
//读取后,流的位置还原
|
|
||||||
context.HttpContext.Request.Body.Seek(0, SeekOrigin.Begin);
|
|
||||||
//context.HttpContext.Request.Body.Position = 0;
|
|
||||||
|
|
||||||
//找到参数位置在字符串中的索引
|
|
||||||
var trialIdIndex = contentFromBody.IndexOf("\"TrialId\"", StringComparison.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
if (trialIdIndex > -1)
|
|
||||||
{
|
|
||||||
// (?<="trialId" *: *").*?(?=",)
|
|
||||||
|
|
||||||
//使用正则 [0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}
|
|
||||||
|
|
||||||
var matchResult = Regex.Match(contentFromBody.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
|
|
||||||
|
|
||||||
if (matchResult.Success)
|
|
||||||
{
|
|
||||||
//有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下
|
|
||||||
|
|
||||||
trialIdStr = matchResult.Value;
|
|
||||||
|
|
||||||
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(trialStatusStr))
|
|
||||||
{
|
|
||||||
|
|
||||||
//数据库 检查该项目Id不对
|
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//使用字符串取 如果是swagger 可能有时取的不对 因为空格的原因
|
|
||||||
//trialIdStr = contentFromBody.Substring(trialIdIndex + "TrialId".Length + 4, 3
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
|
||||||
|
|
||||||
//通过path 或者body 找到trialId 了
|
|
||||||
if (!string.IsNullOrWhiteSpace(trialIdStr))
|
|
||||||
{
|
|
||||||
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
|
|
||||||
|
|
||||||
// 这里是统一拦截 项目有关的操作允许情况(特殊的地方,比如项目配置(有的在多种状态(初始化,ongoing)都可以操作,有的仅仅在Initializing)还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口)
|
|
||||||
if (trialStatusStr == StaticData.TrialState.TrialOngoing || _trialOptList.Any(t => t == TrialOpt.BeforeOngoingCantOpt))
|
//TrialId 传递的途径多种,可能在path 可能在body 可能在数组中,也可能在对象中,可能就在url
|
||||||
|
var trialIdStr = string.Empty;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(context.HttpContext.Request.Query["trialId"]))
|
||||||
{
|
{
|
||||||
|
trialIdStr = context.HttpContext.Request.Query["trialId"];
|
||||||
|
}
|
||||||
|
|
||||||
await next.Invoke();
|
//先尝试从path中取TrialId
|
||||||
|
else if (context.RouteData.Values.Keys.Any(t => t.Contains("trialId")))
|
||||||
|
{
|
||||||
|
var index = context.RouteData.Values.Keys.ToList().IndexOf("trialId");
|
||||||
|
trialIdStr = context.RouteData.Values.Values.ToList()[index] as string;
|
||||||
|
}
|
||||||
|
else if (context.HttpContext.Request.Headers["Referer"].ToString().Contains("trialId"))
|
||||||
|
{
|
||||||
|
var headerStr = context.HttpContext.Request.Headers["Referer"].ToString();
|
||||||
|
|
||||||
|
var trialIdIndex = headerStr.IndexOf("trialId");
|
||||||
|
|
||||||
|
|
||||||
|
var matchResult = Regex.Match(headerStr.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
|
||||||
|
|
||||||
|
if (matchResult.Success)
|
||||||
|
{
|
||||||
|
trialIdStr = matchResult.Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
||||||
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// 项目停止、或者完成 不允许操作
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改
|
#region body 中取数据
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_InterceptedProjectStatusRule"]));
|
|
||||||
|
|
||||||
|
//设置可以多次读
|
||||||
|
context.HttpContext.Request.EnableBuffering();
|
||||||
|
var reader = new StreamReader(context.HttpContext.Request.Body);
|
||||||
|
var contentFromBody = await reader.ReadToEndAsync();
|
||||||
|
//读取后,流的位置还原
|
||||||
|
context.HttpContext.Request.Body.Seek(0, SeekOrigin.Begin);
|
||||||
|
//context.HttpContext.Request.Body.Position = 0;
|
||||||
|
|
||||||
|
//找到参数位置在字符串中的索引
|
||||||
|
var trialIdIndex = contentFromBody.IndexOf("\"TrialId\"", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
if (trialIdIndex > -1)
|
||||||
|
{
|
||||||
|
// (?<="trialId" *: *").*?(?=",)
|
||||||
|
|
||||||
|
//使用正则 [0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}
|
||||||
|
|
||||||
|
var matchResult = Regex.Match(contentFromBody.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
|
||||||
|
|
||||||
|
if (matchResult.Success)
|
||||||
|
{
|
||||||
|
//有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下
|
||||||
|
var cacheResultDic = _provider.GetAll<string>(new[] { matchResult.Value });
|
||||||
|
|
||||||
|
var trialStatusStr = cacheResultDic[matchResult.Value.ToLower()].Value;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(trialStatusStr))
|
||||||
|
{
|
||||||
|
trialIdStr = matchResult.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
||||||
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||||
|
}
|
||||||
|
|
||||||
|
//使用字符串取 如果是swagger 可能有时取的不对 因为空格的原因
|
||||||
|
//trialIdStr = contentFromBody.Substring(trialIdIndex + "TrialId".Length + 4, 3
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//通过path 或者body 找到trialId 了
|
||||||
|
if ( !string.IsNullOrWhiteSpace(trialIdStr))
|
||||||
|
{
|
||||||
|
|
||||||
|
//如果没缓存数据,可能定时任务没执行或者缓存丢失 在此重新缓存
|
||||||
|
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)还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口)
|
||||||
|
if (trialStatusStr == StaticData.TrialState.TrialOngoing || _trialOptList.Any(t=>t== TrialOpt.BeforeOngoingCantOpt) )
|
||||||
|
{
|
||||||
|
|
||||||
|
await next.Invoke();
|
||||||
|
|
||||||
|
}
|
||||||
|
// 项目停止、或者完成 不允许操作
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改
|
||||||
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_InterceptedProjectStatusRule"]));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
//添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截
|
||||||
|
else if (_trialOptList.Any(t => t == TrialOpt.AddOrUpdateTrial ||t ==TrialOpt.SignSystemDocNoTrialId))
|
||||||
|
{
|
||||||
|
await next.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//如果项目相关接口没有传递trialId 会来到这里,提醒,以便修改
|
||||||
|
|
||||||
|
//---该接口参数中,没有传递项目编号,请核对。
|
||||||
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_MissingProjectNumber"]));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
//添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截
|
|
||||||
else if (_trialOptList.Any(t => t == TrialOpt.AddOrUpdateTrial || t == TrialOpt.SignSystemDocNoTrialId))
|
|
||||||
{
|
|
||||||
await next.Invoke();
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//如果项目相关接口没有传递trialId 会来到这里,提醒,以便修改
|
|
||||||
|
|
||||||
//---该接口参数中,没有传递项目编号,请核对。
|
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_MissingProjectNumber"]));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,122 +1,123 @@
|
|||||||
using IRaCIS.Core.Domain.Share;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using IRaCIS.Core.Domain.Share;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Service.BusinessFilter;
|
namespace IRaCIS.Application.Services.BusinessFilter
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 统一返回前端数据包装,之前在控制器包装,现在修改为动态Api 在ResultFilter这里包装,减少重复冗余代码
|
|
||||||
/// by zhouhang 2021.09.12 周末
|
|
||||||
/// </summary>
|
|
||||||
public class UnifiedApiResultFilter : Attribute, IAsyncResultFilter
|
|
||||||
{
|
{
|
||||||
private readonly ILogger _logger;
|
|
||||||
|
|
||||||
public UnifiedApiResultFilter(ILogger<UnifiedApiResultFilter> logger)
|
|
||||||
{
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 异步版本
|
/// 统一返回前端数据包装,之前在控制器包装,现在修改为动态Api 在ResultFilter这里包装,减少重复冗余代码
|
||||||
|
/// by zhouhang 2021.09.12 周末
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context"></param>
|
public class UnifiedApiResultFilter : Attribute, IAsyncResultFilter
|
||||||
/// <param name="next"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
|
|
||||||
{
|
{
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
if (context.Result is ObjectResult objectResult)
|
public UnifiedApiResultFilter(ILogger<UnifiedApiResultFilter> logger)
|
||||||
{
|
{
|
||||||
var statusCode = objectResult.StatusCode ?? context.HttpContext.Response.StatusCode;
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
//是200 并且没有包装 那么包装结果
|
/// <summary>
|
||||||
if (statusCode == 200 && !(objectResult.Value is IResponseOutput))
|
/// 异步版本
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="context"></param>
|
||||||
|
/// <param name="next"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (context.Result is ObjectResult objectResult)
|
||||||
{
|
{
|
||||||
|
var statusCode = objectResult.StatusCode ?? context.HttpContext.Response.StatusCode;
|
||||||
|
|
||||||
var type = objectResult.Value?.GetType();
|
//是200 并且没有包装 那么包装结果
|
||||||
|
if (statusCode == 200 && !(objectResult.Value is IResponseOutput))
|
||||||
|
|
||||||
if (type != null && type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(ValueTuple<,>) || type.GetGenericTypeDefinition() == typeof(Tuple<,>)))
|
|
||||||
{
|
{
|
||||||
|
|
||||||
//报错
|
var type = objectResult.Value?.GetType();
|
||||||
//var tuple = (object, object))objectResult.Value;
|
|
||||||
//var (val1, val2) = ((dynamic, dynamic))objectResult.Value;
|
|
||||||
//var apiResponse = ResponseOutput.Ok(val1, val2);
|
if (type != null && type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(ValueTuple<,>) || type.GetGenericTypeDefinition() == typeof(Tuple<,>)))
|
||||||
|
{
|
||||||
//OK
|
|
||||||
var tuple = (dynamic)objectResult.Value;
|
//报错
|
||||||
var apiResponse = ResponseOutput.Ok(tuple!.Item1, tuple!.Item2);
|
//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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
objectResult.Value = apiResponse;
|
|
||||||
objectResult.DeclaredType = apiResponse.GetType();
|
|
||||||
}
|
}
|
||||||
else
|
//如果是200 是IResponseOutput 记录下日志
|
||||||
|
else if (statusCode == 200 && (objectResult.Value is IResponseOutput))
|
||||||
{
|
{
|
||||||
var apiResponse = ResponseOutput.Ok(objectResult.Value);
|
var result = objectResult.Value as IResponseOutput;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(result.LocalizedInfo))
|
||||||
|
{
|
||||||
|
//统一在这里记录国际化的日志信息
|
||||||
|
_logger.LogWarning($"{result.LocalizedInfo}");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (statusCode != 200 && !(objectResult.Value is IResponseOutput))
|
||||||
|
{
|
||||||
|
//---程序错误,请联系开发人员。
|
||||||
|
var apiResponse = ResponseOutput.NotOk(StaticData.International("UnifiedAPI_ProgramError"));
|
||||||
|
|
||||||
objectResult.Value = apiResponse;
|
objectResult.Value = apiResponse;
|
||||||
objectResult.DeclaredType = apiResponse.GetType();
|
objectResult.DeclaredType = apiResponse.GetType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
//如果是200 是IResponseOutput 记录下日志
|
|
||||||
else if (statusCode == 200 && (objectResult.Value is IResponseOutput))
|
|
||||||
{
|
|
||||||
var result = objectResult.Value as IResponseOutput;
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(result.LocalizedInfo))
|
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();
|
||||||
_logger.LogWarning($"{result.LocalizedInfo}");
|
if (genType == typeof(Tuple<>)
|
||||||
|
|| genType == typeof(Tuple<,>)
|
||||||
|
|| genType == typeof(Tuple<,>))
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!checkBaseTypes)
|
||||||
|
break;
|
||||||
|
|
||||||
|
type = type.BaseType;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (statusCode != 200 && !(objectResult.Value is IResponseOutput))
|
return false;
|
||||||
{
|
|
||||||
//---程序错误,请联系开发人员。
|
|
||||||
var apiResponse = ResponseOutput.NotOk(StaticData.International("UnifiedAPI_ProgramError"));
|
|
||||||
|
|
||||||
objectResult.Value = apiResponse;
|
|
||||||
objectResult.DeclaredType = apiResponse.GetType();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await next.Invoke();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsTupleType(Type type, bool checkBaseTypes = false)
|
|
||||||
{
|
|
||||||
if (type == null)
|
|
||||||
throw new ArgumentNullException(nameof(type));
|
|
||||||
|
|
||||||
if (type == typeof(Tuple))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
while (type != null)
|
|
||||||
{
|
|
||||||
if (type.IsGenericType)
|
|
||||||
{
|
|
||||||
var genType = type.GetGenericTypeDefinition();
|
|
||||||
if (genType == typeof(Tuple<>)
|
|
||||||
|| genType == typeof(Tuple<,>)
|
|
||||||
|| genType == typeof(Tuple<,>))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!checkBaseTypes)
|
|
||||||
break;
|
|
||||||
|
|
||||||
type = type.BaseType;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,164 +0,0 @@
|
|||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.Extensions.Configuration.Json;
|
|
||||||
using System.ComponentModel;
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.Domain.Share;
|
|
||||||
|
|
||||||
[Description("多环境 配置环境实体")]
|
|
||||||
public class ServiceVerifyConfigOption
|
|
||||||
{
|
|
||||||
public bool OpenUserComplexPassword { get; set; }
|
|
||||||
|
|
||||||
public bool OpenSignDocumentBeforeWork { get; set; }
|
|
||||||
|
|
||||||
public bool OpenTrialRelationDelete { get; set; }
|
|
||||||
|
|
||||||
public bool OpenLoginLimit { get; set; }
|
|
||||||
|
|
||||||
public int LoginMaxFailCount { get; set; }
|
|
||||||
|
|
||||||
public int LoginFailLockMinutes { get; set; }
|
|
||||||
|
|
||||||
public int AutoLoginOutMinutes { get; set; }
|
|
||||||
|
|
||||||
public bool OpenLoginMFA { get; set; }
|
|
||||||
|
|
||||||
[Description("连续阅片时间 (min)")]
|
|
||||||
public int ContinuousReadingTimeMin { get; set; }
|
|
||||||
|
|
||||||
[Description("休息时间 (min)")]
|
|
||||||
public int ReadingRestTimeMin { get; set; }
|
|
||||||
[Description("是否需要修改密码")]
|
|
||||||
public bool IsNeedChangePassWord { get; set; }
|
|
||||||
|
|
||||||
[Description("修改密码的天数")]
|
|
||||||
public int ChangePassWordDays { get; set; }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SystemEmailSendConfig
|
|
||||||
{
|
|
||||||
public int Port { get; set; }
|
|
||||||
|
|
||||||
public string Host { get; set; } = string.Empty;
|
|
||||||
public string FromEmail { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
public string FromName { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
public string AuthorizationCode { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
public string SiteUrl { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
public string OrganizationName { get; set; } = string.Empty;
|
|
||||||
public string OrganizationNameCN { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
public string CompanyName { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
public string CompanyNameCN { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
public string CompanyShortName { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
public string CompanyShortNameCN { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
public bool IsEnv_US { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SystemEmailSendConfigView
|
|
||||||
{
|
|
||||||
public string CompanyName { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
public string CompanyNameCN { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
public string CompanyShortName { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
public string CompanyShortNameCN { get; set; } = string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SystemPacsConfig
|
|
||||||
{
|
|
||||||
public int Port { get; set; }
|
|
||||||
|
|
||||||
public string IP { get; set; } = string.Empty;
|
|
||||||
}
|
|
||||||
public class IRCEncreptOption
|
|
||||||
{
|
|
||||||
public string Base64RSAPublicKey { get; set; }
|
|
||||||
|
|
||||||
public string Base64RSAPrivateKey { get; set; }
|
|
||||||
public bool IsResponseEncreptEnable { get; set; }
|
|
||||||
|
|
||||||
public List<string> ApiPathList { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class IRaCISBasicConfigOption
|
|
||||||
{
|
|
||||||
public string DoctorCodePrefix { get; set; }
|
|
||||||
public string UserCodePrefix { get; set; }
|
|
||||||
public string QCChallengeCodePrefix { get; set; }
|
|
||||||
public string DicomStudyCodePrefix { get; set; }
|
|
||||||
public string TaskStudyCodePrefix { get; set; }
|
|
||||||
public string NoneDicomStudyCodePrefix { get; set; }
|
|
||||||
public int ImageShareExpireDays { get; set; }
|
|
||||||
public string SystemSiteCodePrefix { get; set; }
|
|
||||||
public string BlindTaskPrefix { get; set; }
|
|
||||||
public string DefaultPassword { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[Description("项目基础配置规则")]
|
|
||||||
public static class AppSettings
|
|
||||||
{
|
|
||||||
|
|
||||||
public static IRaCISBasicConfigOption IRaCISBasicConfig { get; set; }
|
|
||||||
|
|
||||||
static AppSettings()
|
|
||||||
{
|
|
||||||
var configuration = new ConfigurationBuilder()
|
|
||||||
.Add(new JsonConfigurationSource
|
|
||||||
{
|
|
||||||
Path = "appsettings.json",
|
|
||||||
ReloadOnChange = true
|
|
||||||
})
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
// 手动绑定配置
|
|
||||||
var appSettings = new IRaCISBasicConfigOption();
|
|
||||||
configuration.GetSection("IRaCISBasicConfig").Bind(appSettings);
|
|
||||||
|
|
||||||
IRaCISBasicConfig = appSettings;
|
|
||||||
}
|
|
||||||
//获取实体编码字符串
|
|
||||||
public static string GetCodeStr(int codeInt, string typeStr)
|
|
||||||
{
|
|
||||||
switch (typeStr)
|
|
||||||
{
|
|
||||||
case nameof(Doctor):
|
|
||||||
return IRaCISBasicConfig.DoctorCodePrefix + codeInt.ToString("D4");
|
|
||||||
|
|
||||||
case nameof(User):
|
|
||||||
return IRaCISBasicConfig.UserCodePrefix + codeInt.ToString("D4");
|
|
||||||
|
|
||||||
case nameof(QCChallenge):
|
|
||||||
return IRaCISBasicConfig.QCChallengeCodePrefix + codeInt.ToString("D5");
|
|
||||||
|
|
||||||
case nameof(NoneDicomStudy):
|
|
||||||
return IRaCISBasicConfig.NoneDicomStudyCodePrefix + codeInt.ToString("D5");
|
|
||||||
|
|
||||||
case nameof(DicomStudy):
|
|
||||||
return IRaCISBasicConfig.DicomStudyCodePrefix + codeInt.ToString("D5");
|
|
||||||
|
|
||||||
case nameof(TaskStudy):
|
|
||||||
return IRaCISBasicConfig.TaskStudyCodePrefix + codeInt.ToString("D5");
|
|
||||||
|
|
||||||
case nameof(VisitTask):
|
|
||||||
return "W" + codeInt.ToString("D5");
|
|
||||||
|
|
||||||
case nameof(Site):
|
|
||||||
return IRaCISBasicConfig.SystemSiteCodePrefix + codeInt.ToString("D4");
|
|
||||||
|
|
||||||
default:
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
global using AutoMapper.QueryableExtensions;
|
|
||||||
global using IRaCIS.Core.Application.Service;
|
|
||||||
global using IRaCIS.Core.Domain.Models;
|
|
||||||
global using IRaCIS.Core.Infra.EFCore;
|
|
||||||
global using IRaCIS.Core.Infrastructure.Extention;
|
|
||||||
global using Microsoft.EntityFrameworkCore;
|
|
||||||
global using System.Linq.Expressions;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,4 +1,9 @@
|
|||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Helper
|
namespace IRaCIS.Core.Application.Helper
|
||||||
{
|
{
|
||||||
@@ -14,9 +19,9 @@ namespace IRaCIS.Core.Application.Helper
|
|||||||
|
|
||||||
|
|
||||||
//是否翻译依赖其他属性
|
//是否翻译依赖其他属性
|
||||||
public bool IsTranslateDenpendOtherProperty => !string.IsNullOrWhiteSpace(DependPropertyName);
|
public bool IsTranslateDenpendOtherProperty =>!string.IsNullOrWhiteSpace(DependPropertyName);
|
||||||
|
|
||||||
public string DependPropertyName { get; set; } = string.Empty;
|
public string DependPropertyName { get; set; }=string.Empty;
|
||||||
|
|
||||||
public string DependPropertyValueStr { get; set; } = string.Empty;
|
public string DependPropertyValueStr { get; set; } = string.Empty;
|
||||||
|
|
||||||
@@ -28,7 +33,7 @@ namespace IRaCIS.Core.Application.Helper
|
|||||||
}
|
}
|
||||||
|
|
||||||
//针对不同的标准 翻译的字典不一样
|
//针对不同的标准 翻译的字典不一样
|
||||||
public DictionaryTranslateAttribute(string dicParentCode, CriterionType criterionType)
|
public DictionaryTranslateAttribute(string dicParentCode, CriterionType criterionType )
|
||||||
{
|
{
|
||||||
DicParentCode = dicParentCode;
|
DicParentCode = dicParentCode;
|
||||||
|
|
||||||
@@ -37,7 +42,7 @@ namespace IRaCIS.Core.Application.Helper
|
|||||||
|
|
||||||
//针对业务某个属性的值 不一样 用的翻译字典不一样
|
//针对业务某个属性的值 不一样 用的翻译字典不一样
|
||||||
|
|
||||||
public DictionaryTranslateAttribute(string dicParentCode, string dependPropertyName, string dependPropertyValueStr)
|
public DictionaryTranslateAttribute(string dicParentCode,string dependPropertyName, string dependPropertyValueStr)
|
||||||
{
|
{
|
||||||
DicParentCode = dicParentCode;
|
DicParentCode = dicParentCode;
|
||||||
|
|
||||||
|
|||||||
@@ -1,69 +0,0 @@
|
|||||||
namespace IRaCIS.Core.Application.Helper;
|
|
||||||
|
|
||||||
|
|
||||||
public static class CacheKeys
|
|
||||||
{
|
|
||||||
//项目缓存
|
|
||||||
public static string Trial(string trialIdStr) => $"TrialId:{trialIdStr}";
|
|
||||||
|
|
||||||
//检查编号递增锁
|
|
||||||
public static string TrialStudyMaxCode(Guid trialId) => $"TrialStudyMaxCode:{trialId}";
|
|
||||||
|
|
||||||
public static string TrialStudyUidUploading(Guid trialId, string studyUid) => $"TrialStudyUid:{trialId}_{studyUid}";
|
|
||||||
//CRC上传影像提交锁key
|
|
||||||
public static string TrialStudyUidDBLock(Guid trialId, string studyUid) => $"TrialStudyUidDBLock:{trialId}_{studyUid}";
|
|
||||||
|
|
||||||
public static string TrialTaskStudyUidUploading(Guid trialId, Guid visiTaskId, string studyUid) => $"TrialStudyUid:{trialId}_{visiTaskId}_{studyUid}";
|
|
||||||
//影像后处理上传提交锁key
|
|
||||||
public static string TrialTaskStudyUidDBLock(Guid trialId, Guid visiTaskId, string studyUid) => $"TrialTaskStudyUidDBLock:{trialId}_{visiTaskId}_{studyUid}";
|
|
||||||
//系统匿名化
|
|
||||||
public static string SystemAnonymization => $"SystemAnonymization";
|
|
||||||
//前端国际化
|
|
||||||
public static string FrontInternational => $"FrontInternationalList";
|
|
||||||
|
|
||||||
//登录挤账号
|
|
||||||
public static string UserToken(Guid userId) => $"UserToken:{userId}";
|
|
||||||
|
|
||||||
//超时没请求接口自动退出
|
|
||||||
public static string UserAutoLoginOut(Guid userId) => $"UserAutoLoginOut:{userId}";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 跳过阅片
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="userId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static string SkipReadingCacheKey(Guid userId) => $"{userId}SkipReadingCache";
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 开始阅片时间
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="userId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static string StartReadingTimeKey(Guid userId) => $"{userId}StartReadingTime";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 开始休息时间
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="userId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static string StartRestTime(Guid userId) => $"{userId}StartRestTime";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<List<SystemAnonymization>> GetSystemAnonymizationListAsync(IRepository<SystemAnonymization> _systemAnonymizationRepository)
|
|
||||||
{
|
|
||||||
var list = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,46 +1,41 @@
|
|||||||
using IRaCIS.Application.Contracts;
|
using DocumentFormat.OpenXml.Drawing.Diagrams;
|
||||||
|
using DocumentFormat.OpenXml.Spreadsheet;
|
||||||
|
using DocumentFormat.OpenXml.Wordprocessing;
|
||||||
|
using IRaCIS.Application.Contracts;
|
||||||
using IRaCIS.Application.Interfaces;
|
using IRaCIS.Application.Interfaces;
|
||||||
using IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson;
|
|
||||||
using IRaCIS.Core.Application.Helper;
|
using IRaCIS.Core.Application.Helper;
|
||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Hosting;
|
|
||||||
using MiniExcelLibs;
|
using MiniExcelLibs;
|
||||||
using MiniExcelLibs.OpenXml;
|
using MiniExcelLibs.OpenXml;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
using NPOI.HSSF.UserModel;
|
using NPOI.HSSF.UserModel;
|
||||||
using NPOI.SS.Formula.Functions;
|
|
||||||
using NPOI.SS.UserModel;
|
|
||||||
using NPOI.XSSF.UserModel;
|
using NPOI.XSSF.UserModel;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Globalization;
|
using System.IO;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Service;
|
namespace IRaCIS.Core.Application.Service;
|
||||||
|
|
||||||
public static class ExcelExportHelper
|
public static class ExcelExportHelper
|
||||||
{
|
{
|
||||||
//MiniExcel_Export
|
//MiniExcel_Export
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="code"></param>
|
|
||||||
/// <param name="data"></param>
|
|
||||||
/// <param name="exportFileNamePrefix">文件名前缀</param>
|
|
||||||
/// <param name="_commonDocumentRepository"></param>
|
|
||||||
/// <param name="_hostEnvironment"></param>
|
|
||||||
/// <param name="_dictionaryService"></param>
|
|
||||||
/// <param name="translateType"></param>
|
|
||||||
/// <param name="criterionType"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static async Task<IActionResult> DataExportAsync(string code, ExcelExportInfo data, string exportFileNamePrefix, IRepository<CommonDocument> _commonDocumentRepository, IWebHostEnvironment _hostEnvironment, IDictionaryService? _dictionaryService = null, Type? translateType = null, CriterionType? criterionType = null)
|
public static async Task<IActionResult> DataExportAsync(string code, ExcelExportInfo data, string exportFileNamePrefix, IRepository<CommonDocument> _commonDocumentRepository, IWebHostEnvironment _hostEnvironment, IDictionaryService? _dictionaryService = null, Type? translateType = null, CriterionType? criterionType = null)
|
||||||
{
|
{
|
||||||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
|
||||||
|
|
||||||
//判断是否有字典翻译
|
//判断是否有字典翻译
|
||||||
|
|
||||||
object translateData = data;
|
object translateData = data;
|
||||||
|
|
||||||
if (_dictionaryService != null && translateType != null)
|
if (_dictionaryService != null && translateType != null)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
////只标注单个的时候
|
||||||
|
//var needTranslatePropertyList = translateType.GetProperties().Where(t => t.IsDefined(typeof(DictionaryTranslateAttribute), true))
|
||||||
|
// .Select(c => new { c.Name, DicParentCode = ((DictionaryTranslateAttribute?)c.GetCustomAttributes(typeof(DictionaryTranslateAttribute), false)[0])?.DicParentCode }).ToList();
|
||||||
|
|
||||||
|
|
||||||
//一个值 对应不同的字典翻译
|
//一个值 对应不同的字典翻译
|
||||||
var needTranslatePropertyList = translateType.GetProperties().Where(t => t.IsDefined(typeof(DictionaryTranslateAttribute), true))
|
var needTranslatePropertyList = translateType.GetProperties().Where(t => t.IsDefined(typeof(DictionaryTranslateAttribute), true))
|
||||||
.SelectMany(c =>
|
.SelectMany(c =>
|
||||||
@@ -67,18 +62,12 @@ public static class ExcelExportHelper
|
|||||||
var newObjList = new List<object>();
|
var newObjList = new List<object>();
|
||||||
var no = 1;
|
var no = 1;
|
||||||
|
|
||||||
foreach (var item in dic[key] as IList)
|
foreach (var item in dic[key] as IList )
|
||||||
{
|
{
|
||||||
|
//var itemDic = JsonConvert.DeserializeObject<IDictionary<string, object>>(item.ToJsonNotIgnoreNull());
|
||||||
|
|
||||||
var itemDic = item.ConvertToDictionary();
|
var itemDic = item.ConvertToDictionary();
|
||||||
|
|
||||||
//处理集合里面时间类型,根据当前语言将时间转变为字符串
|
|
||||||
foreach (var itemValuePair in itemDic)
|
|
||||||
{
|
|
||||||
if (DateTime.TryParse(itemValuePair.Value?.ToString(), out DateTime result))
|
|
||||||
{
|
|
||||||
itemDic[itemValuePair.Key] = ExportExcelConverterDate.DateTimeInternationalToString(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
foreach (var needTranslateProperty in needTranslatePropertyList)
|
foreach (var needTranslateProperty in needTranslatePropertyList)
|
||||||
@@ -90,7 +79,7 @@ public static class ExcelExportHelper
|
|||||||
{
|
{
|
||||||
var beforeValue = itemDic[needTranslateProperty.Name]?.ToString();
|
var beforeValue = itemDic[needTranslateProperty.Name]?.ToString();
|
||||||
|
|
||||||
itemDic[needTranslateProperty.Name] = translateDataList[needTranslateProperty.DicParentCode].Where(t => t.Code.ToLower() == beforeValue?.ToLower()).Select(t => isEn_US ? t.Value : t.ValueCN).FirstOrDefault() ?? String.Empty;
|
itemDic[needTranslateProperty.Name] = translateDataList[needTranslateProperty.DicParentCode].Where(t => t.Code.ToLower() == beforeValue?.ToLower()).Select(t=>data.IsEn_US?t.Value:t.ValueCN).FirstOrDefault() ?? String.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//普通翻译 或者某一标准翻译
|
//普通翻译 或者某一标准翻译
|
||||||
@@ -99,7 +88,7 @@ public static class ExcelExportHelper
|
|||||||
var beforeValue = itemDic[needTranslateProperty.Name]?.ToString();
|
var beforeValue = itemDic[needTranslateProperty.Name]?.ToString();
|
||||||
|
|
||||||
|
|
||||||
itemDic[needTranslateProperty.Name] = translateDataList[needTranslateProperty.DicParentCode].Where(t => t.Code.ToLower() == beforeValue?.ToLower()).Select(t => isEn_US ? t.Value : t.ValueCN).FirstOrDefault() ?? String.Empty;
|
itemDic[needTranslateProperty.Name] = translateDataList[needTranslateProperty.DicParentCode].Where(t => t.Code.ToLower() == beforeValue?.ToLower()).Select(t => data.IsEn_US ? t.Value : t.ValueCN).FirstOrDefault() ?? String.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -115,7 +104,6 @@ public static class ExcelExportHelper
|
|||||||
dic[key] = newObjList;
|
dic[key] = newObjList;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -151,7 +139,7 @@ public static class ExcelExportHelper
|
|||||||
|
|
||||||
if (sheetCount == 2)
|
if (sheetCount == 2)
|
||||||
{
|
{
|
||||||
if (isEn_US)
|
if (data.IsEn_US)
|
||||||
{
|
{
|
||||||
workbook.RemoveSheetAt(0);
|
workbook.RemoveSheetAt(0);
|
||||||
}
|
}
|
||||||
@@ -161,7 +149,7 @@ public static class ExcelExportHelper
|
|||||||
}
|
}
|
||||||
|
|
||||||
var memoryStream2 = new MemoryStream();
|
var memoryStream2 = new MemoryStream();
|
||||||
workbook.Write(memoryStream2, true);
|
workbook.Write(memoryStream2,true);
|
||||||
|
|
||||||
memoryStream2.Seek(0, SeekOrigin.Begin);
|
memoryStream2.Seek(0, SeekOrigin.Begin);
|
||||||
|
|
||||||
@@ -172,9 +160,14 @@ public static class ExcelExportHelper
|
|||||||
//fileNmae = workbook.GetSheetName(0);
|
//fileNmae = workbook.GetSheetName(0);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region MiniExcel
|
#region MiniExcel
|
||||||
|
|
||||||
var memoryStream = new MemoryStream();
|
var memoryStream = new MemoryStream();
|
||||||
|
|
||||||
var config = new OpenXmlConfiguration()
|
var config = new OpenXmlConfiguration()
|
||||||
{
|
{
|
||||||
@@ -188,18 +181,29 @@ 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 = $"{(string.IsNullOrEmpty(exportFileNamePrefix) ? "" : exportFileNamePrefix + "_")}{Path.GetFileNameWithoutExtension(fileName)}_{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx"
|
FileDownloadName = $"{(string.IsNullOrEmpty(exportFileNamePrefix) ? "" : exportFileNamePrefix+ "_") }{Path.GetFileNameWithoutExtension(fileName) }_{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx"
|
||||||
};
|
};
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Magicodes 模板规则不一样
|
||||||
|
|
||||||
|
////创建Excel导出对象
|
||||||
|
//IExportFileByTemplate exporter = new ExcelExporter();
|
||||||
|
|
||||||
|
////根据模板导出
|
||||||
|
//var result = await exporter.ExportBytesByTemplate(exportInfo, tplPath);
|
||||||
|
|
||||||
|
|
||||||
|
//return new XlsxFileResult(bytes: result, fileDownloadName: $"{doc.Name}_{DateTime.Now.ToString("yyyy-MM-dd:hh:mm:ss")}.xlsx");
|
||||||
|
#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static async Task<(MemoryStream, string)> DataExport_NpoiTestAsync(string code, ExcelExportInfo data, IRepository<CommonDocument> _commonDocumentRepository, IWebHostEnvironment _hostEnvironment, IDictionaryService? _dictionaryService = null, Type? translateType = null, CriterionType? criterionType = null)
|
public static async Task<(MemoryStream, string)> DataExport_NpoiTestAsync(string code, ExcelExportInfo data, IRepository<CommonDocument> _commonDocumentRepository, IWebHostEnvironment _hostEnvironment, IDictionaryService? _dictionaryService = null, Type? translateType = null, CriterionType? criterionType = null)
|
||||||
{
|
{
|
||||||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
|
||||||
//判断是否有字典翻译
|
//判断是否有字典翻译
|
||||||
|
|
||||||
object translateData = data;
|
object translateData = data;
|
||||||
@@ -207,6 +211,11 @@ public static class ExcelExportHelper
|
|||||||
if (_dictionaryService != null && translateType != null)
|
if (_dictionaryService != null && translateType != null)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
////只标注单个的时候
|
||||||
|
//var needTranslatePropertyList = translateType.GetProperties().Where(t => t.IsDefined(typeof(DictionaryTranslateAttribute), true))
|
||||||
|
// .Select(c => new { c.Name, DicParentCode = ((DictionaryTranslateAttribute?)c.GetCustomAttributes(typeof(DictionaryTranslateAttribute), false)[0])?.DicParentCode }).ToList();
|
||||||
|
|
||||||
|
|
||||||
//一个值 对应不同的字典翻译
|
//一个值 对应不同的字典翻译
|
||||||
var needTranslatePropertyList = translateType.GetProperties().Where(t => t.IsDefined(typeof(DictionaryTranslateAttribute), true))
|
var needTranslatePropertyList = translateType.GetProperties().Where(t => t.IsDefined(typeof(DictionaryTranslateAttribute), true))
|
||||||
.SelectMany(c =>
|
.SelectMany(c =>
|
||||||
@@ -238,15 +247,6 @@ public static class ExcelExportHelper
|
|||||||
//var itemDic = JsonConvert.DeserializeObject<IDictionary<string, object>>(item.ToJsonNotIgnoreNull());
|
//var itemDic = JsonConvert.DeserializeObject<IDictionary<string, object>>(item.ToJsonNotIgnoreNull());
|
||||||
var itemDic = item.ConvertToDictionary();
|
var itemDic = item.ConvertToDictionary();
|
||||||
|
|
||||||
//处理集合里面时间类型,根据当前语言将时间转变为字符串
|
|
||||||
foreach (var itemValuePair in itemDic)
|
|
||||||
{
|
|
||||||
if (DateTime.TryParse(itemValuePair.Value?.ToString(), out DateTime result))
|
|
||||||
{
|
|
||||||
itemDic[itemValuePair.Key] = ExportExcelConverterDate.DateTimeInternationalToString(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var needTranslateProperty in needTranslatePropertyList)
|
foreach (var needTranslateProperty in needTranslatePropertyList)
|
||||||
{
|
{
|
||||||
//翻译的属性依赖其他属性
|
//翻译的属性依赖其他属性
|
||||||
@@ -256,7 +256,7 @@ public static class ExcelExportHelper
|
|||||||
{
|
{
|
||||||
var beforeValue = itemDic[needTranslateProperty.Name]?.ToString();
|
var beforeValue = itemDic[needTranslateProperty.Name]?.ToString();
|
||||||
|
|
||||||
itemDic[needTranslateProperty.Name] = translateDataList[needTranslateProperty.DicParentCode].Where(t => t.Code.ToLower() == beforeValue?.ToLower()).Select(t => isEn_US ? t.Value : t.ValueCN).FirstOrDefault() ?? String.Empty;
|
itemDic[needTranslateProperty.Name] = translateDataList[needTranslateProperty.DicParentCode].Where(t => t.Code.ToLower() == beforeValue?.ToLower()).Select(t => data.IsEn_US ? t.Value : t.ValueCN).FirstOrDefault() ?? String.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//普通翻译 或者某一标准翻译
|
//普通翻译 或者某一标准翻译
|
||||||
@@ -265,7 +265,7 @@ public static class ExcelExportHelper
|
|||||||
var beforeValue = itemDic[needTranslateProperty.Name]?.ToString();
|
var beforeValue = itemDic[needTranslateProperty.Name]?.ToString();
|
||||||
|
|
||||||
|
|
||||||
itemDic[needTranslateProperty.Name] = translateDataList[needTranslateProperty.DicParentCode].Where(t => t.Code.ToLower() == beforeValue?.ToLower()).Select(t => isEn_US ? t.Value : t.ValueCN).FirstOrDefault() ?? String.Empty;
|
itemDic[needTranslateProperty.Name] = translateDataList[needTranslateProperty.DicParentCode].Where(t => t.Code.ToLower() == beforeValue?.ToLower()).Select(t => data.IsEn_US ? t.Value : t.ValueCN).FirstOrDefault() ?? String.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -310,7 +310,7 @@ public static class ExcelExportHelper
|
|||||||
|
|
||||||
if (sheetCount == 2)
|
if (sheetCount == 2)
|
||||||
{
|
{
|
||||||
if (isEn_US)
|
if (data.IsEn_US)
|
||||||
{
|
{
|
||||||
workbook.RemoveSheetAt(0);
|
workbook.RemoveSheetAt(0);
|
||||||
}
|
}
|
||||||
@@ -320,7 +320,7 @@ public static class ExcelExportHelper
|
|||||||
}
|
}
|
||||||
|
|
||||||
var memoryStream2 = new MemoryStream();
|
var memoryStream2 = new MemoryStream();
|
||||||
workbook.Write(memoryStream2, true);
|
workbook.Write(memoryStream2,true);
|
||||||
|
|
||||||
memoryStream2.Seek(0, SeekOrigin.Begin);
|
memoryStream2.Seek(0, SeekOrigin.Begin);
|
||||||
|
|
||||||
@@ -355,86 +355,4 @@ public static class ExcelExportHelper
|
|||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 导出文件模板
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="inDto"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static async Task<FileResult> ExportTemplateAsync(ExportTemplateServiceDto inDto)
|
|
||||||
{
|
|
||||||
var (physicalPath, fileName) = await FileStoreHelper.GetCommonDocPhysicalFilePathAsync(inDto.hostEnvironment, inDto.commonDocumentRepository, inDto.TemplateCode);
|
|
||||||
|
|
||||||
|
|
||||||
//模板路径
|
|
||||||
var tplPath = physicalPath;
|
|
||||||
|
|
||||||
#region 根据中英文 删除模板sheet
|
|
||||||
|
|
||||||
// 打开模板文件
|
|
||||||
var templateFile = new FileStream(tplPath, FileMode.Open, FileAccess.Read);
|
|
||||||
|
|
||||||
// 获取文件流
|
|
||||||
var templateStream = new MemoryStream();
|
|
||||||
templateFile.CopyTo(templateStream);
|
|
||||||
templateStream.Seek(0, SeekOrigin.Begin);
|
|
||||||
|
|
||||||
var workbook = new XSSFWorkbook(templateStream);
|
|
||||||
|
|
||||||
int sheetCount = workbook.NumberOfSheets;
|
|
||||||
|
|
||||||
if (sheetCount == 2)
|
|
||||||
{
|
|
||||||
if (inDto.IsEnglish)
|
|
||||||
{
|
|
||||||
workbook.RemoveSheetAt(0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
workbook.RemoveSheetAt(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
ISheet sheet = workbook.GetSheetAt(0); // 获取第一个工作表
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < sheet.LastRowNum + 1; i++)
|
|
||||||
{
|
|
||||||
IRow row = sheet.GetRow(i);
|
|
||||||
for (int j = 0; j < sheet.LastRowNum; j++)
|
|
||||||
{
|
|
||||||
ICell cell = row.GetCell(j);
|
|
||||||
foreach (var property in inDto.Data.GetType().GetProperties())
|
|
||||||
{
|
|
||||||
var value = property.GetValue(inDto.Data);
|
|
||||||
if (cell!=null&&cell.ToString() == "{{" + property.Name + "}}")
|
|
||||||
{
|
|
||||||
sheet.GetRow(i).GetCell(j).SetCellValue(value.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var memoryStream2 = new MemoryStream();
|
|
||||||
workbook.Write(memoryStream2, true);
|
|
||||||
|
|
||||||
memoryStream2.Seek(0, SeekOrigin.Begin);
|
|
||||||
|
|
||||||
templateStream = memoryStream2;
|
|
||||||
|
|
||||||
|
|
||||||
return new FileStreamResult(templateStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
|
||||||
{
|
|
||||||
FileDownloadName = $"{(string.IsNullOrEmpty(inDto.ExportFileName) ? "" : inDto.ExportFileName + "_")}{Path.GetFileNameWithoutExtension(fileName)}_{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,33 +1,39 @@
|
|||||||
using System.Diagnostics;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Helper;
|
namespace IRaCIS.Core.Application.Helper
|
||||||
|
|
||||||
public class FileConvertHelper
|
|
||||||
{
|
{
|
||||||
|
public class FileConvertHelper
|
||||||
|
|
||||||
static public void ConvertWordToPdf(string inputWordFilePath, string outputPdfDir)
|
|
||||||
{
|
{
|
||||||
// 设置 libreoffice 命令行参数
|
|
||||||
string arguments = $"--headless --invisible --convert-to pdf \"{inputWordFilePath}\" --outdir \"{outputPdfDir}\"";
|
|
||||||
|
|
||||||
// 启动 libreoffice 进程
|
|
||||||
using (Process process = new Process())
|
static public void ConvertWordToPdf(string inputWordFilePath, string outputPdfDir)
|
||||||
{
|
{
|
||||||
process.StartInfo.FileName = "libreoffice";
|
// 设置 libreoffice 命令行参数
|
||||||
process.StartInfo.Arguments = arguments;
|
string arguments = $"--headless --invisible --convert-to pdf \"{inputWordFilePath}\" --outdir \"{outputPdfDir}\"";
|
||||||
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
|
||||||
process.StartInfo.RedirectStandardOutput = true;
|
|
||||||
process.StartInfo.RedirectStandardError = true;
|
|
||||||
process.StartInfo.UseShellExecute = false;
|
|
||||||
process.StartInfo.CreateNoWindow = true;
|
|
||||||
|
|
||||||
process.Start();
|
// 启动 libreoffice 进程
|
||||||
|
using (Process process = new Process())
|
||||||
|
{
|
||||||
|
process.StartInfo.FileName = "libreoffice";
|
||||||
|
process.StartInfo.Arguments = arguments;
|
||||||
|
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
||||||
|
process.StartInfo.RedirectStandardOutput = true;
|
||||||
|
process.StartInfo.RedirectStandardError = true;
|
||||||
|
process.StartInfo.UseShellExecute = false;
|
||||||
|
process.StartInfo.CreateNoWindow = true;
|
||||||
|
|
||||||
// 等待进程结束
|
process.Start();
|
||||||
process.WaitForExit();
|
|
||||||
|
// 等待进程结束
|
||||||
|
process.WaitForExit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
using IRaCIS.Core.Domain.Share;
|
|
||||||
|
|
||||||
|
using Aliyun.OSS;
|
||||||
|
using IRaCIS.Core.Domain.Share;
|
||||||
using IRaCIS.Core.Infrastructure;
|
using IRaCIS.Core.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System.Configuration;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
@@ -11,7 +16,7 @@ public static class FileStoreHelper
|
|||||||
{
|
{
|
||||||
|
|
||||||
//处理文件名 压缩包,或者目录类的 会带上相对路径
|
//处理文件名 压缩包,或者目录类的 会带上相对路径
|
||||||
public static (string TrustedFileNameForFileStorage, string RealName) GetStoreFileName(string fileName, bool isChangeToPdfFormat = false)
|
public static (string TrustedFileNameForFileStorage, string RealName) GetStoreFileName(string fileName,bool isChangeToPdfFormat=false)
|
||||||
{
|
{
|
||||||
|
|
||||||
//带目录层级,需要后端处理前端的路径
|
//带目录层级,需要后端处理前端的路径
|
||||||
@@ -36,14 +41,14 @@ public static class FileStoreHelper
|
|||||||
|
|
||||||
var trustedFileNameForFileStorage = string.Empty;
|
var trustedFileNameForFileStorage = string.Empty;
|
||||||
|
|
||||||
if (isChangeToPdfFormat == false)
|
if (isChangeToPdfFormat==false)
|
||||||
{
|
{
|
||||||
trustedFileNameForFileStorage = Guid.NewGuid().ToString() + fileName;
|
trustedFileNameForFileStorage= Guid.NewGuid().ToString() + fileName;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
trustedFileNameForFileStorage = Guid.NewGuid().ToString() + Path.GetFileNameWithoutExtension(fileName) + ".pdf";
|
trustedFileNameForFileStorage=Guid.NewGuid().ToString() + Path.GetFileNameWithoutExtension(fileName) + ".pdf";
|
||||||
}
|
}
|
||||||
|
|
||||||
return (trustedFileNameForFileStorage, fileName);
|
return (trustedFileNameForFileStorage, fileName);
|
||||||
@@ -131,10 +136,10 @@ 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 != StaticData.CultureInfo.zh_CN;
|
var isEn_US = CultureInfo.CurrentCulture.Name!= "zh-CN";
|
||||||
if (doc == null)
|
if (doc == null)
|
||||||
{
|
{
|
||||||
//---数据库没有找到对应的数据模板文件,请联系系统运维人员。
|
//---数据库没有找到对应的数据模板文件,请联系系统运维人员。
|
||||||
throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileNotFound"));
|
throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileNotFound"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,11 +147,11 @@ public static class FileStoreHelper
|
|||||||
|
|
||||||
if (!System.IO.File.Exists(filePath))
|
if (!System.IO.File.Exists(filePath))
|
||||||
{
|
{
|
||||||
//---数据模板文件存储路径上未找对应文件,请联系系统运维人员。
|
//---数据模板文件存储路径上未找对应文件,请联系系统运维人员。
|
||||||
throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileStoragePathInvalid"));
|
throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileStoragePathInvalid"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (filePath, isEn_US ? doc.Name.Trim('/') : doc.NameCN.Trim('/'));
|
return (filePath, isEn_US? doc.Name.Trim('/'): doc.NameCN.Trim('/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -197,7 +202,7 @@ public static class FileStoreHelper
|
|||||||
|
|
||||||
// 获取 入组确认 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)
|
||||||
{
|
{
|
||||||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
||||||
|
|
||||||
@@ -216,19 +221,19 @@ public static class FileStoreHelper
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static string GetSubjectVisitDicomFolderPhysicalPath(IWebHostEnvironment _hostEnvironment, Guid trialId, Guid siteId, Guid subjectId, Guid subjectVisitId)
|
public static string GetSubjectVisitDicomFolderPhysicalPath(IWebHostEnvironment _hostEnvironment,Guid trialId, Guid siteId, Guid subjectId, Guid subjectVisitId)
|
||||||
{
|
{
|
||||||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
||||||
|
|
||||||
return Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), siteId.ToString(), subjectId.ToString(), subjectVisitId.ToString(), StaticData.Folder.DicomFolder);
|
return Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), siteId.ToString(), subjectId.ToString(), subjectVisitId.ToString(), StaticData.Folder.DicomFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static (string PhysicalPath, string RelativePath) GetDicomInstanceFilePath(IWebHostEnvironment _hostEnvironment, Guid trialId, Guid subjectId, Guid subjectVisitId, Guid studyId, Guid instanceId)
|
public static (string PhysicalPath, string RelativePath) GetDicomInstanceFilePath(IWebHostEnvironment _hostEnvironment, Guid trialId, Guid subjectId, Guid subjectVisitId, Guid studyId, Guid instanceId)
|
||||||
{
|
{
|
||||||
#region 切换存储前
|
#region 切换存储前
|
||||||
//var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
//var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
||||||
#endregion
|
#endregion
|
||||||
var rootPath = Path.Combine(FileStoreHelper.GetBestStoreDisk(_hostEnvironment), StaticData.Folder.IRaCISDataFolder);
|
var rootPath = Path.Combine(FileStoreHelper.GetBestStoreDisk(_hostEnvironment), StaticData.Folder.IRaCISDataFolder) ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -241,7 +246,7 @@ public static class FileStoreHelper
|
|||||||
Directory.CreateDirectory(path);
|
Directory.CreateDirectory(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
var physicalPath = Path.Combine(path, instanceId.ToString());
|
var physicalPath = Path.Combine(path, instanceId.ToString() );
|
||||||
|
|
||||||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{subjectId}/{subjectVisitId}/{StaticData.Folder.DicomFolder}/{studyId}/{instanceId}";
|
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{subjectId}/{subjectVisitId}/{StaticData.Folder.DicomFolder}/{studyId}/{instanceId}";
|
||||||
|
|
||||||
@@ -255,7 +260,7 @@ public static class FileStoreHelper
|
|||||||
public static string GetBestStoreDisk(IWebHostEnvironment _hostEnvironment)
|
public static string GetBestStoreDisk(IWebHostEnvironment _hostEnvironment)
|
||||||
{
|
{
|
||||||
|
|
||||||
var json = File.ReadAllText(Path.Combine(_hostEnvironment.ContentRootPath, "appsettings.json"));
|
var json = File.ReadAllText( Path.Combine(_hostEnvironment.ContentRootPath, "appsettings.json"));
|
||||||
|
|
||||||
JObject jsonObject = (JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load })).IfNullThrowException();
|
JObject jsonObject = (JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load })).IfNullThrowException();
|
||||||
|
|
||||||
@@ -269,7 +274,7 @@ public static class FileStoreHelper
|
|||||||
{
|
{
|
||||||
|
|
||||||
//---解析Json文件配置出现问题
|
//---解析Json文件配置出现问题
|
||||||
throw new BusinessValidationFailedException(StaticData.International("SysMon_JsonConfig") + e.Message);
|
throw new BusinessValidationFailedException(StaticData.International("SysMon_JsonConfig") + e.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
//默认存储的路径
|
//默认存储的路径
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
using Hangfire;
|
using Hangfire;
|
||||||
|
using IRaCIS.Core.Application.Service;
|
||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using NPOI.SS.Formula.Functions;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Helper
|
namespace IRaCIS.Core.Application.Helper
|
||||||
{
|
{
|
||||||
@@ -55,7 +65,7 @@ namespace IRaCIS.Core.Application.Helper
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void AddOrUpdateTrialCronJob(string jobId, Guid trialId, EmailBusinessScenario businessScenario, string emailCron)
|
public static void AddOrUpdateTrialCronJob (string jobId, Guid trialId, EmailBusinessScenario businessScenario, string emailCron)
|
||||||
{
|
{
|
||||||
|
|
||||||
switch (businessScenario)
|
switch (businessScenario)
|
||||||
|
|||||||
@@ -1,105 +0,0 @@
|
|||||||
using RestSharp;
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Helper;
|
|
||||||
|
|
||||||
|
|
||||||
#region 对接模型
|
|
||||||
public class HolidayCalendar
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Version { get; set; }
|
|
||||||
public string Generated { get; set; }
|
|
||||||
public string Timezone { get; set; }
|
|
||||||
public string Author { get; set; }
|
|
||||||
public string URL { get; set; }
|
|
||||||
public Dictionary<string, List<HolidayYear>> Years { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class HolidayYear
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
|
||||||
public DateTime StartDate { get; set; }
|
|
||||||
public DateTime EndDate { get; set; }
|
|
||||||
public int Duration { get; set; }
|
|
||||||
public List<DateTime> CompDays { get; set; }
|
|
||||||
public string URL { get; set; }
|
|
||||||
public string Memo { get; set; }
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class HolidayHelper
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// github 链接:https://github.com/lanceliao/china-holiday-calender?tab=readme-ov-file
|
|
||||||
/// 接口请求参考文档:https://www.koudingke.cn/docs/zh-Hans/net-lib-docs/latest/RestSharp/Usage/Usage
|
|
||||||
/// </summary>
|
|
||||||
private static RestClient _client => new RestClient("https://www.shuyz.com/githubfiles/china-holiday-calender/master/holidayAPI.json");
|
|
||||||
|
|
||||||
private static HolidayCalendar _holidayCalendar { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
private static List<DateTime> _holidays = new List<DateTime>();
|
|
||||||
private static List<DateTime> _compensatedWorkdays = new List<DateTime>();
|
|
||||||
|
|
||||||
static HolidayHelper()
|
|
||||||
{
|
|
||||||
_holidayCalendar = _client.Get<HolidayCalendar>(new RestRequest()) ?? new HolidayCalendar();
|
|
||||||
|
|
||||||
foreach (var year in _holidayCalendar.Years.Values.SelectMany(x => x))
|
|
||||||
{
|
|
||||||
// 添加节假日到假日集合
|
|
||||||
for (DateTime date = year.StartDate; date <= year.EndDate; date = date.AddDays(1))
|
|
||||||
{
|
|
||||||
_holidays.Add(date);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加补班日到补班日集合
|
|
||||||
foreach (var compDay in year.CompDays)
|
|
||||||
{
|
|
||||||
_compensatedWorkdays.Add(compDay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static TimeSpan GetChinaWorkTimeSpan(DateTime startDate, DateTime endDate)
|
|
||||||
{
|
|
||||||
if (startDate > endDate)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("结束日期必须大于或等于开始日期");
|
|
||||||
}
|
|
||||||
|
|
||||||
var diffTimeSpan = endDate - startDate;
|
|
||||||
|
|
||||||
// 初始化工作日数为0
|
|
||||||
int workdays = 0;
|
|
||||||
|
|
||||||
// 找出在给定日期范围内的假期和补班日
|
|
||||||
var filteredHolidays = _holidays.Where(d => d >= startDate && d <= endDate).ToList();
|
|
||||||
var filteredCompensatedWorkdays = _compensatedWorkdays.Where(d => d >= startDate && d <= endDate).ToList();
|
|
||||||
|
|
||||||
// 遍历日期范围,计算工作日 注意 这里是小于
|
|
||||||
for (DateTime date = startDate.Date; date < endDate.Date; date = date.AddDays(1))
|
|
||||||
{
|
|
||||||
// 判断是否为工作日
|
|
||||||
bool isWeekend = date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday;
|
|
||||||
bool isHoliday = filteredHolidays.Contains(date);
|
|
||||||
bool isCompensatedWorkday = filteredCompensatedWorkdays.Contains(date);
|
|
||||||
|
|
||||||
// 如果是补班日,或是平日(非假期,非周末),则算作工作日
|
|
||||||
if (isCompensatedWorkday || (!isWeekend && !isHoliday))
|
|
||||||
{
|
|
||||||
workdays++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new TimeSpan(workdays, diffTimeSpan.Hours, diffTimeSpan.Minutes, diffTimeSpan.Seconds);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
namespace IRaCIS.Core.Application.Helper;
|
|
||||||
|
|
||||||
public static class IRCEmailPasswordHelper
|
|
||||||
{
|
|
||||||
private static readonly Random Random = new Random();
|
|
||||||
|
|
||||||
//显示位数:3分之2的位数,向上取整
|
|
||||||
//取哪几个个值:最后一位和前面几位
|
|
||||||
//其他:3个***。
|
|
||||||
//比如:hlj23@126.com
|
|
||||||
//为:hlj***3@126.com
|
|
||||||
|
|
||||||
//he@126.com
|
|
||||||
//为:h*** e@126.com
|
|
||||||
|
|
||||||
public static string MaskEmail(string email)
|
|
||||||
{
|
|
||||||
|
|
||||||
// 找到 "@" 符号的位置
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 密码必须包含:1)8 – 32 个字符;2)至少1个数字;3) 至少1个大写字母;4)至少1个小写字母;5)至少1个特殊字符 (~!-@#$%^&*_+?)
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static string GenerateRandomPassword(int length)
|
|
||||||
{
|
|
||||||
// 必须包含的字符组
|
|
||||||
const string numbers = "0123456789";
|
|
||||||
const string upperCaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
||||||
const string lowerCaseLetters = "abcdefghijklmnopqrstuvwxyz";
|
|
||||||
const string specialCharacters = "~!-@#$%^&*_+?";
|
|
||||||
|
|
||||||
// 随机选择至少一个字符
|
|
||||||
char[] requiredCharacters =
|
|
||||||
{
|
|
||||||
numbers[Random.Next(numbers.Length)],
|
|
||||||
upperCaseLetters[Random.Next(upperCaseLetters.Length)],
|
|
||||||
lowerCaseLetters[Random.Next(lowerCaseLetters.Length)],
|
|
||||||
specialCharacters[Random.Next(specialCharacters.Length)]
|
|
||||||
};
|
|
||||||
|
|
||||||
// 构建剩余的字符集,用于填充密码的其余部分
|
|
||||||
string allCharacters = numbers + upperCaseLetters + lowerCaseLetters + specialCharacters;
|
|
||||||
|
|
||||||
// 确保密码长度满足用户要求
|
|
||||||
char[] password = new char[length];
|
|
||||||
|
|
||||||
// 将必须包含的字符放入密码中
|
|
||||||
requiredCharacters.CopyTo(password, 0);
|
|
||||||
|
|
||||||
// 填充剩余的字符
|
|
||||||
for (int i = requiredCharacters.Length; i < length; i++)
|
|
||||||
{
|
|
||||||
password[i] = allCharacters[Random.Next(allCharacters.Length)];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 随机打乱密码字符顺序
|
|
||||||
return new string(password.OrderBy(_ => Random.Next()).ToArray());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
|
|
||||||
using FellowOakDicom.Imaging;
|
using FellowOakDicom.Imaging;
|
||||||
using SixLabors.ImageSharp;
|
|
||||||
using SixLabors.ImageSharp.Formats.Jpeg;
|
using SixLabors.ImageSharp.Formats.Jpeg;
|
||||||
|
using SixLabors.ImageSharp;
|
||||||
using SixLabors.ImageSharp.Processing;
|
using SixLabors.ImageSharp.Processing;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Helper;
|
namespace IRaCIS.Core.Application.Helper;
|
||||||
|
|
||||||
|
|||||||
@@ -4,204 +4,211 @@ using IRaCIS.Core.Infrastructure;
|
|||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using static IRaCIS.Core.Application.Service.Common.SystemMonitor;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Helper;
|
namespace IRaCIS.Core.Application.Helper
|
||||||
|
|
||||||
public static class InternationalizationHelper
|
|
||||||
{
|
{
|
||||||
public static string JsonFileFolder = Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources);
|
public static class InternationalizationHelper
|
||||||
|
|
||||||
public static FileSystemWatcher FileSystemWatcher_US { get; set; }
|
|
||||||
public static FileSystemWatcher FileSystemWatcher_CN { get; set; }
|
|
||||||
|
|
||||||
private static void VerifyFolder()
|
|
||||||
{
|
{
|
||||||
if (!Directory.Exists(JsonFileFolder) ||
|
public static string JsonFileFolder = Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources);
|
||||||
!Directory.GetFiles(JsonFileFolder).Any(filePath => Path.GetExtension(filePath).Equals(".json", StringComparison.OrdinalIgnoreCase)))
|
|
||||||
|
public static FileSystemWatcher FileSystemWatcher_US { get; set; }
|
||||||
|
public static FileSystemWatcher FileSystemWatcher_CN { get; set; }
|
||||||
|
|
||||||
|
private static void VerifyFolder()
|
||||||
{
|
{
|
||||||
throw new BusinessValidationFailedException("国际化Json文件目录有误");
|
if (!Directory.Exists(JsonFileFolder) ||
|
||||||
}
|
!Directory.GetFiles(JsonFileFolder).Any(filePath => Path.GetExtension(filePath).Equals(".json", StringComparison.OrdinalIgnoreCase)))
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task BatchAddJsonKeyValueAsync(List<BatchAddInternationalizationDto> batchAddDtos)
|
|
||||||
{
|
|
||||||
VerifyFolder();
|
|
||||||
|
|
||||||
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
|
|
||||||
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
|
|
||||||
|
|
||||||
|
|
||||||
//更新json 文件 同时更新内存缓存的数据
|
|
||||||
foreach (var filePath in new string[] { usJsonPath, cnJsonPath })
|
|
||||||
{
|
|
||||||
var json = await File.ReadAllTextAsync(filePath);
|
|
||||||
|
|
||||||
JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
|
|
||||||
|
|
||||||
// 添加或更新指定的键值对
|
|
||||||
|
|
||||||
if (filePath.Contains(StaticData.En_US_Json))
|
|
||||||
{
|
{
|
||||||
foreach (var item in batchAddDtos)
|
throw new BusinessValidationFailedException("国际化Json文件目录有误");
|
||||||
{
|
}
|
||||||
jsonObject[item.Code] = item.Value;
|
}
|
||||||
|
|
||||||
StaticData.En_US_Dic[item.Code] = item.Value;
|
public static async Task BatchAddJsonKeyValueAsync(List<BatchAddInternationalizationDto> batchAddDtos)
|
||||||
|
{
|
||||||
|
VerifyFolder();
|
||||||
|
|
||||||
|
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
|
||||||
|
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
|
||||||
|
|
||||||
|
|
||||||
|
//更新json 文件 同时更新内存缓存的数据
|
||||||
|
foreach (var filePath in new string[] { usJsonPath, cnJsonPath })
|
||||||
|
{
|
||||||
|
var json = await File.ReadAllTextAsync(filePath);
|
||||||
|
|
||||||
|
JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
|
||||||
|
|
||||||
|
// 添加或更新指定的键值对
|
||||||
|
|
||||||
|
if (filePath.Contains(StaticData.En_US_Json))
|
||||||
|
{
|
||||||
|
foreach (var item in batchAddDtos)
|
||||||
|
{
|
||||||
|
jsonObject[item.Code] = item.Value;
|
||||||
|
|
||||||
|
StaticData.En_US_Dic[item.Code] = item.Value;
|
||||||
|
|
||||||
|
//日志记录该信息方便自己人看, 返回给客户的是配置的
|
||||||
|
StaticData.Log_Locoalize_Dic[item.Code] = item.Description;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var item in batchAddDtos)
|
||||||
|
{
|
||||||
|
jsonObject[item.Code] = item.Value;
|
||||||
|
|
||||||
|
StaticData.Zh_CN_Dic[item.Code] = item.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
await File.WriteAllTextAsync(filePath, jsonObject.ToString());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task AddOrUpdateJsonKeyValueAsync(string key, string value, string valueCN,string description)
|
||||||
|
{
|
||||||
|
|
||||||
|
VerifyFolder();
|
||||||
|
|
||||||
|
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
|
||||||
|
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
|
||||||
|
|
||||||
|
|
||||||
|
//更新json 文件 同时更新内存缓存的数据
|
||||||
|
foreach (var filePath in new string[] { usJsonPath, cnJsonPath })
|
||||||
|
{
|
||||||
|
var json = await File.ReadAllTextAsync(filePath);
|
||||||
|
|
||||||
|
JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
|
||||||
|
|
||||||
|
// 添加或更新指定的键值对
|
||||||
|
|
||||||
|
if (filePath.Contains(StaticData.En_US_Json))
|
||||||
|
{
|
||||||
|
jsonObject[key] = value;
|
||||||
|
|
||||||
|
StaticData.En_US_Dic[key] = value;
|
||||||
|
|
||||||
//日志记录该信息方便自己人看, 返回给客户的是配置的
|
//日志记录该信息方便自己人看, 返回给客户的是配置的
|
||||||
StaticData.Log_Locoalize_Dic[item.Code] = item.Description;
|
StaticData.Log_Locoalize_Dic[key] = description;
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (var item in batchAddDtos)
|
|
||||||
{
|
{
|
||||||
jsonObject[item.Code] = item.Value;
|
jsonObject[key] = valueCN;
|
||||||
|
|
||||||
StaticData.Zh_CN_Dic[item.Code] = item.Value;
|
StaticData.Zh_CN_Dic[key] = valueCN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
await File.WriteAllTextAsync(filePath, jsonObject.ToString());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
await File.WriteAllTextAsync(filePath, jsonObject.ToString());
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task AddOrUpdateJsonKeyValueAsync(string key, string value, string valueCN, string description)
|
|
||||||
{
|
|
||||||
|
|
||||||
VerifyFolder();
|
|
||||||
|
|
||||||
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
|
|
||||||
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
|
|
||||||
|
|
||||||
|
|
||||||
//更新json 文件 同时更新内存缓存的数据
|
public static async Task InitInternationlizationDataAndWatchJsonFileAsync(IRepository<Internationalization> _internationalizationRepository)
|
||||||
foreach (var filePath in new string[] { usJsonPath, cnJsonPath })
|
|
||||||
{
|
{
|
||||||
var json = await File.ReadAllTextAsync(filePath);
|
//查询数据库的数据
|
||||||
|
var toJsonList = await _internationalizationRepository.Where(t => t.InternationalizationType == 1).Select(t => new
|
||||||
JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
|
|
||||||
|
|
||||||
// 添加或更新指定的键值对
|
|
||||||
|
|
||||||
if (filePath.Contains(StaticData.En_US_Json))
|
|
||||||
{
|
{
|
||||||
jsonObject[key] = value;
|
t.Code,
|
||||||
|
t.Value,
|
||||||
|
t.ValueCN,
|
||||||
|
t.Description
|
||||||
|
}).ToListAsync();
|
||||||
|
|
||||||
StaticData.En_US_Dic[key] = value;
|
//组织成json 文件
|
||||||
|
|
||||||
|
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
|
||||||
|
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
|
||||||
|
|
||||||
|
|
||||||
|
//本地静态文件国际化需要
|
||||||
|
foreach (var tojsonItem in toJsonList)
|
||||||
|
{
|
||||||
|
StaticData.En_US_Dic[tojsonItem.Code] = tojsonItem.Value;
|
||||||
|
StaticData.Zh_CN_Dic[tojsonItem.Code] = tojsonItem.ValueCN;
|
||||||
|
|
||||||
//日志记录该信息方便自己人看, 返回给客户的是配置的
|
//日志记录该信息方便自己人看, 返回给客户的是配置的
|
||||||
StaticData.Log_Locoalize_Dic[key] = description;
|
StaticData.Log_Locoalize_Dic[tojsonItem.Code] = tojsonItem.Description;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
File.WriteAllText(usJsonPath, JsonConvert.SerializeObject(StaticData.En_US_Dic));
|
||||||
|
File.WriteAllText(cnJsonPath, JsonConvert.SerializeObject(StaticData.Zh_CN_Dic));
|
||||||
|
|
||||||
|
|
||||||
|
//监测Json文件变更 实时刷新数据
|
||||||
|
|
||||||
|
if (!File.Exists(usJsonPath) || !File.Exists(cnJsonPath))
|
||||||
{
|
{
|
||||||
jsonObject[key] = valueCN;
|
throw new BusinessValidationFailedException(StaticData.International("IRaCISCHangfireJob_FileNotFound"));
|
||||||
|
|
||||||
StaticData.Zh_CN_Dic[key] = valueCN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
await File.WriteAllTextAsync(filePath, jsonObject.ToString());
|
// //监测Json文件变更 实时刷新数据
|
||||||
|
|
||||||
|
|
||||||
|
FileSystemWatcher_US = new FileSystemWatcher
|
||||||
|
{
|
||||||
|
Path = Path.GetDirectoryName(usJsonPath)!,
|
||||||
|
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
|
||||||
|
Filter = Path.GetFileName(usJsonPath),
|
||||||
|
EnableRaisingEvents = true,
|
||||||
|
|
||||||
|
};
|
||||||
|
// 添加文件更改事件的处理程序
|
||||||
|
FileSystemWatcher_US.Changed += (sender, e) => LoadJsonFile(StaticData.Folder.Resources + "\\" + StaticData.En_US_Json);
|
||||||
|
|
||||||
|
|
||||||
|
FileSystemWatcher_CN = new FileSystemWatcher
|
||||||
|
{
|
||||||
|
Path = Path.GetDirectoryName(cnJsonPath)!,
|
||||||
|
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
|
||||||
|
Filter = Path.GetFileName(cnJsonPath),
|
||||||
|
EnableRaisingEvents = true,
|
||||||
|
|
||||||
|
};
|
||||||
|
FileSystemWatcher_CN.Changed += (sender, e) => LoadJsonFile(StaticData.Folder.Resources + "\\" + StaticData.Zh_CN_Json);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static void LoadJsonFile(string filePath)
|
||||||
|
{
|
||||||
|
Console.WriteLine("刷新json内存数据");
|
||||||
|
IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile(filePath, false, false);
|
||||||
|
|
||||||
|
IConfigurationRoot enConfiguration = builder.Build();
|
||||||
|
|
||||||
|
foreach (IConfigurationSection section in enConfiguration.GetChildren())
|
||||||
|
{
|
||||||
|
if (filePath.Contains(StaticData.En_US_Json))
|
||||||
|
{
|
||||||
|
StaticData.En_US_Dic[section.Key] = section.Value;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StaticData.Zh_CN_Dic[section.Key] = section.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static async Task InitInternationlizationDataAndWatchJsonFileAsync(IRepository<Internationalization> _internationalizationRepository)
|
|
||||||
{
|
|
||||||
//查询数据库的数据
|
|
||||||
var toJsonList = await _internationalizationRepository.Where(t => t.InternationalizationType == 1).Select(t => new
|
|
||||||
{
|
|
||||||
t.Code,
|
|
||||||
t.Value,
|
|
||||||
t.ValueCN,
|
|
||||||
t.Description
|
|
||||||
}).ToListAsync();
|
|
||||||
|
|
||||||
//组织成json 文件
|
|
||||||
|
|
||||||
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
|
|
||||||
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
|
|
||||||
|
|
||||||
|
|
||||||
//本地静态文件国际化需要
|
|
||||||
foreach (var tojsonItem in toJsonList)
|
|
||||||
{
|
|
||||||
StaticData.En_US_Dic[tojsonItem.Code] = tojsonItem.Value;
|
|
||||||
StaticData.Zh_CN_Dic[tojsonItem.Code] = tojsonItem.ValueCN;
|
|
||||||
|
|
||||||
//日志记录该信息方便自己人看, 返回给客户的是配置的
|
|
||||||
StaticData.Log_Locoalize_Dic[tojsonItem.Code] = tojsonItem.Description;
|
|
||||||
}
|
|
||||||
|
|
||||||
File.WriteAllText(usJsonPath, JsonConvert.SerializeObject(StaticData.En_US_Dic));
|
|
||||||
File.WriteAllText(cnJsonPath, JsonConvert.SerializeObject(StaticData.Zh_CN_Dic));
|
|
||||||
|
|
||||||
|
|
||||||
//监测Json文件变更 实时刷新数据
|
|
||||||
|
|
||||||
if (!File.Exists(usJsonPath) || !File.Exists(cnJsonPath))
|
|
||||||
{
|
|
||||||
throw new BusinessValidationFailedException(StaticData.International("IRaCISCHangfireJob_FileNotFound"));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// //监测Json文件变更 实时刷新数据
|
|
||||||
|
|
||||||
|
|
||||||
FileSystemWatcher_US = new FileSystemWatcher
|
|
||||||
{
|
|
||||||
Path = Path.GetDirectoryName(usJsonPath)!,
|
|
||||||
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
|
|
||||||
Filter = Path.GetFileName(usJsonPath),
|
|
||||||
EnableRaisingEvents = true,
|
|
||||||
|
|
||||||
};
|
|
||||||
// 添加文件更改事件的处理程序
|
|
||||||
FileSystemWatcher_US.Changed += (sender, e) => LoadJsonFile(StaticData.Folder.Resources + "\\" + StaticData.En_US_Json);
|
|
||||||
|
|
||||||
|
|
||||||
FileSystemWatcher_CN = new FileSystemWatcher
|
|
||||||
{
|
|
||||||
Path = Path.GetDirectoryName(cnJsonPath)!,
|
|
||||||
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
|
|
||||||
Filter = Path.GetFileName(cnJsonPath),
|
|
||||||
EnableRaisingEvents = true,
|
|
||||||
|
|
||||||
};
|
|
||||||
FileSystemWatcher_CN.Changed += (sender, e) => LoadJsonFile(StaticData.Folder.Resources + "\\" + StaticData.Zh_CN_Json);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static void LoadJsonFile(string filePath)
|
|
||||||
{
|
|
||||||
Console.WriteLine("刷新json内存数据");
|
|
||||||
IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile(filePath, false, false);
|
|
||||||
|
|
||||||
IConfigurationRoot enConfiguration = builder.Build();
|
|
||||||
|
|
||||||
foreach (IConfigurationSection section in enConfiguration.GetChildren())
|
|
||||||
{
|
|
||||||
if (filePath.Contains(StaticData.En_US_Json))
|
|
||||||
{
|
|
||||||
StaticData.En_US_Dic[section.Key] = section.Value;
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
StaticData.Zh_CN_Dic[section.Key] = section.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user