Compare commits
416 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 431d2e7a97 | |||
| 7caac94d97 | |||
| ceedafb6b9 | |||
| 04e7cd5463 | |||
| ba37700812 | |||
| cdadad9ec5 | |||
| 795e128ef9 | |||
| 658f9c7c40 | |||
| 5bce1cafa3 | |||
| f539496f9f | |||
| fac077d2b7 | |||
| 874c8718b1 | |||
| fea009bf0c | |||
| 5ae837ac19 | |||
| eb55fafbc3 | |||
| 88893c9825 | |||
| c6a18aa18a | |||
| 8829723c19 | |||
| 8768fe0437 | |||
| cb7098830c | |||
| c69c139e00 | |||
| acb7e798e0 | |||
| 63d7bd5607 | |||
| 99e3610be6 | |||
| 50712aefc6 | |||
| d5d728fea6 | |||
| 9e71732061 | |||
| c24adcd09c | |||
| 0da842871c | |||
| 03702477d6 | |||
| e4a36f4689 | |||
| cb6271daef | |||
| 11fa028cd4 | |||
| 5a1a710d5a | |||
| e9e4b45823 | |||
| 7693c72802 | |||
| 1bacc222be | |||
| c5355e976f | |||
| 95a84bb330 | |||
| 6a60e4696b | |||
| 7ff77554ff | |||
| ba23950cd5 | |||
| 8ec2c676f1 | |||
| b183622e13 | |||
| cd9f7f8812 | |||
| 513d773be3 | |||
| cf24583974 | |||
| f5fbf96772 | |||
| 8dc2301184 | |||
| 7e135367b2 | |||
| 8626a6b453 | |||
| 870dda49dd | |||
| 171b8bac34 | |||
| 7c19ecc3f4 | |||
| 3e375ea6d1 | |||
| 416a94e302 | |||
| 7760b0736e | |||
| aba7dfdec9 | |||
| 1dabadfba4 | |||
| b8f5f32596 | |||
| b6459d2f9f | |||
| dded4f2d7c | |||
| fadb7a9d0e | |||
| 55f261b080 | |||
| ccf154e5e5 | |||
| 069ee25d18 | |||
| 64fd39ceb4 | |||
| 19cf8c7559 | |||
| 3c0199cebd | |||
| 62965e5aa5 | |||
| 654fb7116b | |||
| da6746beea | |||
| 2461646d5f | |||
| 02db483119 | |||
| b5e756ffa3 | |||
| f3c29d3530 | |||
| f2d9c6fe38 | |||
| 0d4d984135 | |||
| f9c155a378 | |||
| a9a67c1db2 | |||
| 3d6d64175b | |||
| 45c74694f2 | |||
| 033c47435f | |||
| ea48967492 | |||
| 8ec35d90fb | |||
| 53f3bb5d6d | |||
| e6628e952f | |||
| 1b26ed1b65 | |||
| d0018a3ec3 | |||
| a423c7c73a | |||
| 8eacc969ed | |||
| 33b02be6ed | |||
| 9834335767 | |||
| d4d5ed0d9a | |||
| 3fc7b72a45 | |||
| e525965d89 | |||
| af988e7276 | |||
| 627f3bf4a9 | |||
| aca261ace2 | |||
| 328a8549c6 | |||
| ff71e925ca | |||
| f46bbea98e | |||
| 1d5c274e38 | |||
| e32195c322 | |||
| 935b498ab5 | |||
| 21925f6d88 | |||
| 54b75dd3d5 | |||
| 7ed54e3be3 | |||
| 3a3184a5ac | |||
| 41153e42d6 | |||
| 3ca9be0a29 | |||
| 6c5f669ab6 | |||
| 282ba96c61 | |||
| fe80604331 | |||
| 19fdd02429 | |||
| c2f72d677f | |||
| 6713fff0e7 | |||
| ff8fa94341 | |||
| 82f2185825 | |||
| 5fdf9e0606 | |||
| cf9823c682 | |||
| 73e7ed11b1 | |||
| 9adab8cef1 | |||
| 3d382635cc | |||
| e389c1e581 | |||
| 1a3ebe1fc4 | |||
| fb6f12903e | |||
| 1da4fbe23b | |||
| 4d206ebf9d | |||
| 9c4ada3e66 | |||
| 0bc0421ee3 | |||
| a79aebe772 | |||
| d3ff114b6d | |||
| 50a45e2260 | |||
| 8090668650 | |||
| d27b4af793 | |||
| b097ca1db3 | |||
| 609742c914 | |||
| 79d76dcbaf | |||
| 721ab8dfd3 | |||
| b2d90005f8 | |||
| c58d880e28 | |||
| 183fc6143f | |||
| 9a71e1fa0f | |||
| 5977ab34e9 | |||
| c71b58e0e9 | |||
| 1fcb871de2 | |||
| d7a76bc110 | |||
| 78b76da7ed | |||
| a6c04d8fbb | |||
| 303cb54e7a | |||
| 92e1a3f90b | |||
| 8c51ae350c | |||
| 91fa8e75e1 | |||
| 893bdaf0f2 | |||
| 7051e68c09 | |||
| e9bb71f5c9 | |||
| 3ee0c2ccc7 | |||
| 40c8a51a31 | |||
| d3e3ed79ba | |||
| 83d3a547d1 | |||
| 3d428af85b | |||
| c5b8743064 | |||
| 69d390da81 | |||
| ae0f601727 | |||
| d509bc1649 | |||
| 23ffe2b143 | |||
| 718ddefe97 | |||
| 7524d39213 | |||
| 7e705ccf37 | |||
| 7fc2de5eb3 | |||
| b90f5f2d85 | |||
| 97b28fd920 | |||
| 3bdd5af113 | |||
| 6dcfbb8717 | |||
| 103d4b42a3 | |||
| fc30cb39ee | |||
| 115017197b | |||
| 32931e155c | |||
| 0a1ce59670 | |||
| 42e4fe59ec | |||
| 19f4385055 | |||
| d789c48004 | |||
| 32427f0f0c | |||
| 01ade2d62f | |||
| cec038fb92 | |||
| b5d117f6fa | |||
| b98df9dae8 | |||
| 4e7ce826c8 | |||
| 7df247d5e7 | |||
| fb067534e7 | |||
| de274e00d6 | |||
| 3501f2acdf | |||
| 2dd86652f3 | |||
| bf39613789 | |||
| a64cec987d | |||
| 5b2b5fead9 | |||
| 0216665d5b | |||
| f1fadebfba | |||
| 19b647fb4a | |||
| 65e47d9918 | |||
| ab68a63bdd | |||
| 5990477fdc | |||
| 961ca49f76 | |||
| 581e412106 | |||
| 3813158b00 | |||
| 010fdf6e2c | |||
| f7c669a7d7 | |||
| 68dc09d969 | |||
| a6a6765d9b | |||
| 5931a67825 | |||
| f26441719f | |||
| 67a930a208 | |||
| f189f9f361 | |||
| b6d0791f18 | |||
| 7285a9d672 | |||
| c3daa75e0e | |||
| 564ac4d931 | |||
| e065e44ab0 | |||
| bbc737811a | |||
| d507e625c6 | |||
| e997cb2a8f | |||
| bfa2d8afce | |||
| 3840627ce7 | |||
| 8fed969bec | |||
| d50091ed6b | |||
| 86864ae575 | |||
| 0fdcc7c56e | |||
| 849f48db25 | |||
| b31821848d | |||
| e5be375308 | |||
| 095db5786b | |||
| dcfe28d950 | |||
| f9f3a1422f | |||
| 8dcd1f2f56 | |||
| 7d39bf43fe | |||
| 8b8b52e0cc | |||
| 0cdc489278 | |||
| d4cef1148b | |||
| 40d4806f22 | |||
| 48427f2740 | |||
| a3296a1ab9 | |||
| 7404fabcda | |||
| 29842f484b | |||
| daac69c0d1 | |||
| 603f6e095c | |||
| c9b1e5f92a | |||
| 6fd9bd94df | |||
| fd6673c339 | |||
| 6fe4aa60d4 | |||
| df1665307a | |||
| 1ccb31fcf2 | |||
| 55f98d735e | |||
| 4642e4e00e | |||
| c6d74309f4 | |||
| 2abada285b | |||
| d600862fb0 | |||
| 4048be622f | |||
| eec0156fe7 | |||
| 85d1930730 | |||
| 7420fdeda5 | |||
| 4e2eb7b0a0 | |||
| 68e87a6c0e | |||
| 19f9af8af8 | |||
| 34faaaf231 | |||
| 136a9e54ca | |||
| 5b63e58c1d | |||
| 70c381831d | |||
| 2bf562d027 | |||
| c7e3403cae | |||
| 2f41c21f75 | |||
| 1688392216 | |||
| 6a1a56f0bc | |||
| 0f495a4568 | |||
| 81abcf39fc | |||
| 247b11cec4 | |||
| 21ded0d466 | |||
| 36c354c8f0 | |||
| cb6f93ec0a | |||
| da8812868c | |||
| 14ec78a2fd | |||
| eccb5dc562 | |||
| c11ff02a82 | |||
| b9b095a19c | |||
| 8678c3602f | |||
| 510a35e2b4 | |||
| 5e1ec1ffb2 | |||
| 3f38cf25c5 | |||
| b32225b8bb | |||
| ecbc27fbb8 | |||
| d3f13e844d | |||
| 405454f71f | |||
| f7dd5117a0 | |||
| 60330fbd93 | |||
| 6b7542b11f | |||
| e012384dfa | |||
| 2aa63a6132 | |||
| e12935d9aa | |||
| 21cb074469 | |||
| 204cb19d96 | |||
| 238fde7d01 | |||
| b59b46f938 | |||
| 0fbfe6c0e1 | |||
| 31e2aa24b8 | |||
| 5b52a3e67f | |||
| bb5844a8e8 | |||
| bc5956ed66 | |||
| 624d89563c | |||
| f6bcff7e13 | |||
| 36acbc1df8 | |||
| ca9ce6e4c5 | |||
| 08edc735e9 | |||
| 5b420a453b | |||
| 6a6411dfb8 | |||
| 360bcd6bfe | |||
| 16107dc8a9 | |||
| 578281b707 | |||
| 3730d955dd | |||
| 3dbf329a31 | |||
| afa2b50951 | |||
| b219e4a055 | |||
| 6e38f3f3df | |||
| 34370a36af | |||
| 1dfb27f08e | |||
| 3bf616667e | |||
| 15a3fd17df | |||
| 092a9c2dc6 | |||
| 6e1bf8265f | |||
| d4389e5c35 | |||
| d30b1853de | |||
| 532d7d155b | |||
| 9cff6b9c87 | |||
| e5f8b3dc71 | |||
| 8ac2de3434 | |||
| 74501c3584 | |||
| 757ccc3eb6 | |||
| 36fb3f2d53 | |||
| 8092b0680b | |||
| 42de7737cb | |||
| 273d2a4b88 | |||
| fe4b48f4bc | |||
| 444d3c3a59 | |||
| c8596c6815 | |||
| e2dd4b2466 | |||
| 429ca4dd6d | |||
| 55e0624dc6 | |||
| fff6ef5fe2 | |||
| 2127c47d00 | |||
| 564477b728 | |||
| c7e80401e1 | |||
| 7fee1abdb5 | |||
| 243fae4b19 | |||
| 6e2a58c3d7 | |||
| 2d864de128 | |||
| bee09217a2 | |||
| bd0e039e7a | |||
| f1423fba4f | |||
| c439e1bb42 | |||
| 6a17c2a9a8 | |||
| 0b987f937d | |||
| cd62a8741a | |||
| 67a8f10b03 | |||
| 27749ec3cd | |||
| 19220a1cbd | |||
| f4df76cccd | |||
| 6c443ca089 | |||
| 68be1d8583 | |||
| a965cf429f | |||
| c1c5add001 | |||
| a8049f2a60 | |||
| 9d01b557ce | |||
| 89b3bc94a2 | |||
| 7a7fde5fc0 | |||
| 632712cfee | |||
| 98be30449f | |||
| a7db67adb6 | |||
| c6fdae8879 | |||
| f925f8969a | |||
| f1601e7017 | |||
| caf5946b9e | |||
| 7dce99e045 | |||
| 0e59617691 | |||
| f0f688a1a3 | |||
| 753941204f | |||
| 6fd239cf70 | |||
| a8f6594142 | |||
| 0d5d5105ce | |||
| c078d496be | |||
| bceffcad6a | |||
| ccbf1f0544 | |||
| e5a8a06bbb | |||
| af1d85e65c | |||
| 7ace6c3593 | |||
| b3e0cf8ec1 | |||
| 4f77d1bfb3 | |||
| 72e54fe0d9 | |||
| 735083999e | |||
| 006a5729d6 | |||
| e4c3521b04 | |||
| dd13eddfe3 | |||
| 706cb888c8 | |||
| bfe5379206 | |||
| 2ffd1a2520 | |||
| 784e453eaa | |||
| 084b3d8822 | |||
| c03fd57c25 | |||
| 34d5f809ee | |||
| fd0d91faa4 | |||
| 2450602227 | |||
| 48ea90ce97 | |||
| 640ebdb835 | |||
| 5d59d729d7 | |||
| afadc5e2be | |||
| dc3c3f7557 | |||
| 61cbfe231d | |||
| 9ee2dd477e |
@@ -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.Application.Services.BusinessFilter
|
namespace IRaCIS.Core.Application.Service.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.Application.Services;
|
using IRaCIS.Core.Application.Service;
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using IRaCIS.Core.SCP.Service;
|
using IRaCIS.Core.SCP.Service;
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,11 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" />
|
<PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.1.4" />
|
||||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" />
|
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" />
|
||||||
|
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" />
|
||||||
|
<PackageReference Include="AWSSDK.S3" Version="3.7.402.7" />
|
||||||
|
<PackageReference Include="AWSSDK.SecurityToken" Version="3.7.400.16" />
|
||||||
<PackageReference Include="DistributedLock.Core" Version="1.0.7" />
|
<PackageReference Include="DistributedLock.Core" Version="1.0.7" />
|
||||||
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.5" />
|
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.5" />
|
||||||
<PackageReference Include="fo-dicom" Version="5.1.3" />
|
<PackageReference Include="fo-dicom" Version="5.1.3" />
|
||||||
|
|||||||
@@ -113,6 +113,11 @@ 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 =>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using IRaCIS.Application.Services.BusinessFilter;
|
using IRaCIS.Core.Application.Service.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;
|
||||||
|
|||||||
@@ -176,6 +176,13 @@ 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,11 +243,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}");
|
||||||
|
|||||||
+664
-336
File diff suppressed because it is too large
Load Diff
@@ -9,23 +9,16 @@
|
|||||||
"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": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
"AccessKeyId": "LTAI5tNRTsqL6aWmHkDmTwoH",
|
||||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
"AccessKeySecret": "7mtGz3qrYWI6JMMBZiLeC119VWicZH",
|
||||||
"bucketName": "zy-irc-store",
|
"RoleArn": "acs:ram::1899121822495495:role/irc-oss-access",
|
||||||
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
"BucketName": "zy-irc-store",
|
||||||
"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"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -9,15 +9,16 @@
|
|||||||
"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": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
|
||||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
|
||||||
"bucketName": "zy-irc-test-store",
|
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
|
||||||
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
"BucketName": "zy-irc-test-store",
|
||||||
"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": {
|
||||||
@@ -28,53 +29,20 @@
|
|||||||
"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/"
|
||||||
},
|
|
||||||
|
|
||||||
"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,
|
|
||||||
|
|
||||||
"LoginFailLockMinutes": 30
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
"SystemEmailSendConfig": {
|
|
||||||
"Port": 465,
|
|
||||||
"Host": "smtp.qiye.aliyun.com",
|
|
||||||
"FromEmail": "test-study@extimaging.com",
|
|
||||||
"FromName": "Test_Study",
|
|
||||||
"AuthorizationCode": "zhanying123",
|
|
||||||
|
|
||||||
"SiteUrl": "http://study.test.extimaging.com/login"
|
|
||||||
},
|
|
||||||
"DicomSCPServiceConfig": {
|
"DicomSCPServiceConfig": {
|
||||||
"CalledAEList": [
|
"CalledAEList": [
|
||||||
"STORESCP",
|
"STORESCP"
|
||||||
"Value1",
|
|
||||||
"Value2",
|
|
||||||
"Value3"
|
|
||||||
],
|
],
|
||||||
"ServerPort": 11112
|
"ServerPort": 11112
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -9,59 +9,27 @@
|
|||||||
"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": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
|
||||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
|
||||||
"bucketName": "zy-irc-uat-store",
|
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
|
||||||
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
"BucketName": "zy-irc-uat-store",
|
||||||
"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("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IRC.Core.SCP", "IRC.Core.SCP\IRC.Core.SCP.csproj", "{ECD08F47-DC1A-484E-BB91-6CDDC8823CC5}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "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
|
||||||
|
|||||||
@@ -1,99 +0,0 @@
|
|||||||
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; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -14,7 +14,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.Application.Services;
|
using IRaCIS.Core.Application.Service;
|
||||||
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;
|
||||||
@@ -37,6 +37,7 @@ using Amazon.SecurityToken.Model;
|
|||||||
using Amazon.SecurityToken;
|
using Amazon.SecurityToken;
|
||||||
using Amazon;
|
using Amazon;
|
||||||
using AssumeRoleRequest = Amazon.SecurityToken.Model.AssumeRoleRequest;
|
using AssumeRoleRequest = Amazon.SecurityToken.Model.AssumeRoleRequest;
|
||||||
|
using AutoMapper;
|
||||||
|
|
||||||
namespace IRaCIS.Api.Controllers
|
namespace IRaCIS.Api.Controllers
|
||||||
{
|
{
|
||||||
@@ -109,8 +110,12 @@ namespace IRaCIS.Api.Controllers
|
|||||||
[FromServices] ITokenService _tokenService,
|
[FromServices] ITokenService _tokenService,
|
||||||
[FromServices] IReadingImageTaskService readingImageTaskService,
|
[FromServices] IReadingImageTaskService readingImageTaskService,
|
||||||
[FromServices] IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig,
|
[FromServices] IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig,
|
||||||
|
[FromServices] IOptionsMonitor<SystemEmailSendConfig> _emailConfig,
|
||||||
|
|
||||||
[FromServices] 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)
|
||||||
@@ -143,10 +148,11 @@ namespace IRaCIS.Api.Controllers
|
|||||||
// 验证阅片休息时间
|
// 验证阅片休息时间
|
||||||
await readingImageTaskService.ResetReadingRestTime(userId);
|
await readingImageTaskService.ResetReadingRestTime(userId);
|
||||||
|
|
||||||
await _fusionCache.SetAsync(userId.ToString(), loginReturn.JWTStr, TimeSpan.FromDays(7));
|
await _fusionCache.SetAsync(CacheKeys.UserToken(userId), loginReturn.JWTStr, TimeSpan.FromDays(7));
|
||||||
|
|
||||||
await _fusionCache.SetAsync($"{userId.ToString()}_Online", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(_verifyConfig.CurrentValue.AutoLoginOutMinutes));
|
await _fusionCache.SetAsync(CacheKeys.UserAutoLoginOut(userId), 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);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -221,9 +227,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 发送邮件
|
||||||
|
|
||||||
@@ -231,11 +237,21 @@ namespace IRaCIS.Api.Controllers
|
|||||||
|
|
||||||
var email = returnModel.Data.BasicInfo.EMail;
|
var email = returnModel.Data.BasicInfo.EMail;
|
||||||
|
|
||||||
var hiddenEmail = EmailMaskHelper.MaskEmail(email);
|
var hiddenEmail = IRCEmailPasswordHelper.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
|
||||||
@@ -264,6 +280,8 @@ namespace IRaCIS.Api.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
returnModel.Data.CompanyInfo = companyInfo;
|
||||||
return returnModel;
|
return returnModel;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -273,8 +291,14 @@ 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")]
|
||||||
@@ -297,100 +321,14 @@ namespace IRaCIS.Api.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("user/GetObjectStoreToken")]
|
[HttpGet("user/GetObjectStoreToken")]
|
||||||
public async Task<IResponseOutput> GetObjectStoreTokenAsync([FromServices] IOptionsMonitor<ObjectStoreServiceOptions> options)
|
public async Task<IResponseOutput> GetObjectStoreTokenAsync([FromServices] IOptionsMonitor<ObjectStoreServiceOptions> options, [FromServices] IOSSService _oSSService)
|
||||||
{
|
{
|
||||||
var serviceOption = options.CurrentValue;
|
|
||||||
|
|
||||||
if (Enum.TryParse<ObjectStoreUse>(serviceOption.ObjectStoreUse, out var parsedEnum) && parsedEnum == ObjectStoreUse.AliyunOSS)
|
var result = _oSSService.GetObjectStoreTempToken();
|
||||||
{
|
|
||||||
|
|
||||||
var ossOptions = serviceOption.AliyunOSS;
|
//result.AWS = await GetAWSTemToken(options.CurrentValue);
|
||||||
|
|
||||||
var client = new Client(new AlibabaCloud.OpenApiClient.Models.Config()
|
return ResponseOutput.Ok(result);
|
||||||
{
|
|
||||||
AccessKeyId = ossOptions.AccessKeyId,
|
|
||||||
AccessKeySecret = ossOptions.AccessKeySecret,
|
|
||||||
//AccessKeyId = "LTAI5tJV76pYX5yPg1N9QVE8",
|
|
||||||
//AccessKeySecret = "roRNLa9YG1of4pYruJGCNKBXEWTAWa",
|
|
||||||
|
|
||||||
Endpoint = "sts.cn-hangzhou.aliyuncs.com"
|
|
||||||
});
|
|
||||||
|
|
||||||
var assumeRoleRequest = new AlibabaCloud.SDK.Sts20150401.Models.AssumeRoleRequest();
|
|
||||||
// 将<YOUR_ROLE_SESSION_NAME>设置为自定义的会话名称,例如oss-role-session。
|
|
||||||
assumeRoleRequest.RoleSessionName = $"session-name-{NewId.NextGuid()}";
|
|
||||||
// 将<YOUR_ROLE_ARN>替换为拥有上传文件到指定OSS Bucket权限的RAM角色的ARN。
|
|
||||||
assumeRoleRequest.RoleArn = ossOptions.RoleArn;
|
|
||||||
//assumeRoleRequest.RoleArn = "acs:ram::1899121822495495:role/webdirect";
|
|
||||||
assumeRoleRequest.DurationSeconds = ossOptions.DurationSeconds;
|
|
||||||
var runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions();
|
|
||||||
var response = client.AssumeRoleWithOptions(assumeRoleRequest, runtime);
|
|
||||||
var credentials = response.Body.Credentials;
|
|
||||||
|
|
||||||
var tempToken = new AliyunOSSTempToken()
|
|
||||||
{
|
|
||||||
AccessKeyId = credentials.AccessKeyId,
|
|
||||||
AccessKeySecret = credentials.AccessKeySecret,
|
|
||||||
Expiration = credentials.Expiration,
|
|
||||||
SecurityToken = credentials.SecurityToken,
|
|
||||||
|
|
||||||
|
|
||||||
Region = ossOptions.Region,
|
|
||||||
BucketName = ossOptions.BucketName,
|
|
||||||
EndPoint = ossOptions.EndPoint,
|
|
||||||
ViewEndpoint = ossOptions.ViewEndpoint,
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
var awstempToken = await GetAWSTemToken(serviceOption);
|
|
||||||
|
|
||||||
return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse = serviceOption.ObjectStoreUse, AliyunOSS = tempToken,AWS= awstempToken });
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (Enum.TryParse<ObjectStoreUse>(serviceOption.ObjectStoreUse, out var parsedValue) && parsedValue == ObjectStoreUse.MinIO)
|
|
||||||
{
|
|
||||||
return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse = serviceOption.ObjectStoreUse, MinIO = serviceOption.MinIO});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var awsOptions = serviceOption.AWS;
|
|
||||||
|
|
||||||
//aws 临时凭证
|
|
||||||
// 创建 STS 客户端
|
|
||||||
var stsClient = new AmazonSecurityTokenServiceClient(awsOptions.AccessKeyId, awsOptions.SecretAccessKey);
|
|
||||||
|
|
||||||
// 使用 AssumeRole 请求临时凭证
|
|
||||||
var assumeRoleRequest = new AssumeRoleRequest
|
|
||||||
{
|
|
||||||
|
|
||||||
RoleArn = awsOptions.RoleArn, // 角色 ARN
|
|
||||||
RoleSessionName = $"session-name-{NewId.NextGuid()}",
|
|
||||||
DurationSeconds = awsOptions.DurationSeconds // 临时凭证有效期
|
|
||||||
};
|
|
||||||
|
|
||||||
var assumeRoleResponse = await stsClient.AssumeRoleAsync(assumeRoleRequest);
|
|
||||||
|
|
||||||
var credentials = assumeRoleResponse.Credentials;
|
|
||||||
|
|
||||||
var tempToken = new AWSTempToken()
|
|
||||||
{
|
|
||||||
AccessKeyId = credentials.AccessKeyId,
|
|
||||||
SecretAccessKey = credentials.SecretAccessKey,
|
|
||||||
SessionToken= credentials.SessionToken,
|
|
||||||
Expiration=credentials.Expiration,
|
|
||||||
Region=awsOptions.Region,
|
|
||||||
|
|
||||||
BucketName = awsOptions.BucketName,
|
|
||||||
EndPoint = awsOptions.EndPoint,
|
|
||||||
ViewEndpoint = awsOptions.ViewEndpoint,
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse = serviceOption.ObjectStoreUse, MinIO = serviceOption.MinIO, AWS = tempToken });
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.Application.Services;
|
using IRaCIS.Core.Application.Service;
|
||||||
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;
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ 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;
|
||||||
@@ -234,36 +235,10 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
IRepository<SubjectVisit> _subjectVisitRepository,
|
IRepository<SubjectVisit> _subjectVisitRepository,
|
||||||
IStringLocalizer _localizer) : UploadBaseController
|
IStringLocalizer _localizer) : UploadBaseController
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[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,
|
|
||||||
IsDicom = preArchiveStudyCommand.IsDicom,
|
|
||||||
IP = _userInfo.IP
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var addEntity = await _studyMonitorRepository.AddAsync(studyMonitor, true);
|
|
||||||
|
|
||||||
return ResponseOutput.Ok(addEntity.Id);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>Dicom 归档</summary>
|
/// <summary>Dicom 归档</summary>
|
||||||
@@ -271,7 +246,7 @@ 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(Guid trialId, Guid subjectVisitId, string studyInstanceUid, Guid? abandonStudyId, Guid studyMonitorId,
|
||||||
[FromServices] ILogger<UploadDownLoadController> _logger,
|
[FromServices] ILogger<UploadDownLoadController> _logger,
|
||||||
[FromServices] IStudyService _studyService,
|
[FromServices] IStudyService _studyService,
|
||||||
[FromServices] IHubContext<UploadHub, IUploadClient> _uploadHub,
|
[FromServices] IHubContext<UploadHub, IUploadClient> _uploadHub,
|
||||||
@@ -419,12 +394,26 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
|
|
||||||
public class UploadNoneDicomFileCommand
|
public class UploadNoneDicomFileCommand
|
||||||
{
|
{
|
||||||
public Guid TrialId { get; set; }
|
[NotDefault]
|
||||||
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>();
|
||||||
|
|
||||||
|
|
||||||
@@ -438,6 +427,41 @@ 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>
|
||||||
@@ -470,24 +494,37 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
|
|
||||||
foreach (var item in incommand.UploadedFileList)
|
foreach (var item in incommand.UploadedFileList)
|
||||||
{
|
{
|
||||||
await _noneDicomStudyFileRepository.AddAsync(new NoneDicomStudyFile() { FileName = item.FileName, Path = item.FilePath, NoneDicomStudyId = noneDicomStudyId,FileType=item.FileType,FileSize=item.FileFize });
|
//如果是跟任务绑,那么NoneDicomStudyId 设置为空,不影响之前的检查,同时设置 OriginNoneDicomStudyId 保证关系
|
||||||
|
|
||||||
|
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.UploadedFileList.Count;
|
noneDicomStudy.FileCount = noneDicomStudy.FileCount + (incommand.VisitTaskId != null ? 0 : incommand.UploadedFileList.Count);
|
||||||
|
|
||||||
studyMonitor.FileCount = incommand.UploadedFileList.Count;
|
studyMonitor.RecordPath = incommand.RecordPath;
|
||||||
|
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;
|
studyMonitor.StudyId = noneDicomStudyId.Value;
|
||||||
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 _noneDicomStudyRepository.SaveChangesAsync();
|
||||||
|
|
||||||
@@ -955,7 +992,7 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
}
|
}
|
||||||
//处理好 用户类型 和用户类型枚举
|
//处理好 用户类型 和用户类型枚举
|
||||||
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)
|
||||||
{
|
{
|
||||||
@@ -979,9 +1016,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();
|
||||||
|
|
||||||
|
|||||||
@@ -1,107 +0,0 @@
|
|||||||
<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,156 +1,112 @@
|
|||||||
<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="AlibabaCloud.SDK.Sts20150401" Version="1.1.4" />
|
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
|
||||||
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
|
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" />
|
||||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" />
|
|
||||||
<PackageReference Include="AWSSDK.SecurityToken" Version="3.7.400.13" />
|
|
||||||
<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>
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.8">
|
||||||
<ProjectReference Include="..\IRaCIS.Core.Application\IRaCIS.Core.Application.csproj" />
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<ProjectReference Include="..\IRaCIS.Core.Infra.EFCore\IRaCIS.Core.Infra.EFCore.csproj" />
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</ItemGroup>
|
</PackageReference>
|
||||||
|
<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>
|
||||||
<None Include="..\.editorconfig" Link=".editorconfig" />
|
<ProjectReference Include="..\IRaCIS.Core.Application\IRaCIS.Core.Application.csproj" />
|
||||||
</ItemGroup>
|
<ProjectReference Include="..\IRaCIS.Core.Infra.EFCore\IRaCIS.Core.Infra.EFCore.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Update="wwwroot\EmailTemplate\AdminAddUser_US.html">
|
<None Include="..\.editorconfig" Link=".editorconfig" />
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
</ItemGroup>
|
||||||
</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>
|
||||||
|
|
||||||
<ProjectExtensions><VisualStudio><UserProperties properties_4launchsettings_1json__JsonSchema="" /></VisualStudio></ProjectExtensions>
|
<ItemGroup>
|
||||||
|
<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.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)">
|
<member name="M:IRaCIS.Api.Controllers.ExtraController.Login(IRaCIS.Application.Contracts.UserLoginDTO,ZiggyCreatures.Caching.Fusion.IFusionCache,IRaCIS.Core.Application.Service.IUserService,IRaCIS.Core.Application.Auth.ITokenService,IRaCIS.Core.Application.Contracts.IReadingImageTaskService,Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.ServiceVerifyConfigOption},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig},IRaCIS.Core.Application.Service.IMailVerificationService)">
|
||||||
<summary> 系统用户登录接口[New] </summary>
|
<summary> 系统用户登录接口[New] </summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.AddOrUpdateTrialInspection(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Application.Contracts.TrialCommand})">
|
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.AddOrUpdateTrialInspection(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Application.Contracts.TrialCommand})">
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
<param name="param"></param>
|
<param name="param"></param>
|
||||||
<returns>新记录Id</returns>
|
<returns>新记录Id</returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.WorkLoadAddOrUpdate(IRaCIS.Application.Services.IDoctorWorkloadService,IRaCIS.Application.Contracts.WorkloadCommand)">
|
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.WorkLoadAddOrUpdate(IRaCIS.Core.Application.Service.IDoctorWorkloadService,IRaCIS.Application.Contracts.WorkloadCommand)">
|
||||||
<summary>
|
<summary>
|
||||||
添加或更新工作量[AUTH]
|
添加或更新工作量[AUTH]
|
||||||
</summary>
|
</summary>
|
||||||
@@ -281,6 +281,15 @@
|
|||||||
<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},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})">
|
||||||
|
<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})">
|
<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 文件 支持压缩包 多文件上传
|
||||||
@@ -366,11 +375,6 @@
|
|||||||
<param name="memberSerialization">序列化成员</param>
|
<param name="memberSerialization">序列化成员</param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</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>
|
||||||
对称可逆加密
|
对称可逆加密
|
||||||
|
|||||||
@@ -1,118 +0,0 @@
|
|||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -20,7 +20,7 @@ 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.Application.Services.BackGroundJob;
|
using IRaCIS.Core.Application.Service.BackGroundJob;
|
||||||
using LogDashboard;
|
using LogDashboard;
|
||||||
using FellowOakDicom.Network;
|
using FellowOakDicom.Network;
|
||||||
using IRaCIS.Core.Application.Service.ImageAndDoc;
|
using IRaCIS.Core.Application.Service.ImageAndDoc;
|
||||||
@@ -33,6 +33,8 @@ using Newtonsoft.Json;
|
|||||||
using Microsoft.AspNetCore.Diagnostics;
|
using Microsoft.AspNetCore.Diagnostics;
|
||||||
using IRaCIS.Core.Application.MassTransit.Command;
|
using IRaCIS.Core.Application.MassTransit.Command;
|
||||||
using IRaCIS.Core.Application.MassTransit.Consumer;
|
using IRaCIS.Core.Application.MassTransit.Consumer;
|
||||||
|
using DocumentFormat.OpenXml.InkML;
|
||||||
|
using IRaCIS.Core.Domain;
|
||||||
|
|
||||||
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
|
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
|
||||||
AppContext.SetSwitch("Npgsql.DisableDateTimeInfinityConversions", true);
|
AppContext.SetSwitch("Npgsql.DisableDateTimeInfinityConversions", true);
|
||||||
@@ -110,7 +112,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>();
|
||||||
|
|
||||||
|
|
||||||
@@ -121,16 +123,18 @@ builder.Services.AddOptions().Configure<SystemEmailSendConfig>(_configuration.Ge
|
|||||||
builder.Services.AddOptions().Configure<ServiceVerifyConfigOption>(_configuration.GetSection("BasicSystemConfig"));
|
builder.Services.AddOptions().Configure<ServiceVerifyConfigOption>(_configuration.GetSection("BasicSystemConfig"));
|
||||||
builder.Services.AddOptions().Configure<AliyunOSSOptions>(_configuration.GetSection("AliyunOSS"));
|
builder.Services.AddOptions().Configure<AliyunOSSOptions>(_configuration.GetSection("AliyunOSS"));
|
||||||
builder.Services.AddOptions().Configure<ObjectStoreServiceOptions>(_configuration.GetSection("ObjectStoreService"));
|
builder.Services.AddOptions().Configure<ObjectStoreServiceOptions>(_configuration.GetSection("ObjectStoreService"));
|
||||||
builder.Services.AddOptions().Configure<EncreptResponseOption>(_configuration.GetSection("EncrypteResponseConfig"));
|
builder.Services.AddOptions().Configure<IRCEncreptOption>(_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, enviromentName);
|
||||||
//Http 响应压缩
|
//Http 响应压缩
|
||||||
builder.Services.AddResponseCompressionSetup();
|
builder.Services.AddResponseCompressionSetup();
|
||||||
//Swagger Api 文档
|
//Swagger Api 文档
|
||||||
@@ -143,15 +147,30 @@ builder.Services.AddJWTAuthSetup(_configuration);
|
|||||||
|
|
||||||
#region MassTransit
|
#region MassTransit
|
||||||
//masstransit组件 也支持MediatR 中介者模式,但是支持分布式,考虑后续,所以在次替代MediatR
|
//masstransit组件 也支持MediatR 中介者模式,但是支持分布式,考虑后续,所以在次替代MediatR
|
||||||
|
//参考链接:https://masstransit.io/documentation/concepts/mediator#scoped-mediator
|
||||||
builder.Services.AddMediator(cfg =>
|
builder.Services.AddMediator(cfg =>
|
||||||
{
|
{
|
||||||
cfg.AddConsumer<ConsistencyCheckConsumer>();
|
cfg.AddConsumer<ConsistencyCheckConsumer>();
|
||||||
|
cfg.AddConsumer<AddSubjectTriggerConsumer>();
|
||||||
|
cfg.AddConsumer<AddSubjectTriggerConsumer2>();
|
||||||
|
//cfg.ConfigureMediator((context, cfg) => cfg.UseHttpContextScopeFilter(context));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//添加 MassTransit 和 InMemory 传输
|
||||||
builder.Services.AddMassTransit(cfg =>
|
builder.Services.AddMassTransit(cfg =>
|
||||||
{
|
{
|
||||||
cfg.UsingInMemory();
|
// 注册消费者
|
||||||
|
cfg.AddConsumer<AddSubjectTriggerConsumer>(); // 替换为你的消费者类
|
||||||
|
cfg.AddConsumer<AddSubjectTriggerConsumer2>();
|
||||||
|
|
||||||
|
// 使用 InMemory 作为消息传递机制
|
||||||
|
cfg.UsingInMemory((context, cfg) =>
|
||||||
|
{
|
||||||
|
// 这里可以进行额外的配置
|
||||||
|
cfg.ConfigureEndpoints(context); // 自动配置所有消费者的端点
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
@@ -193,6 +212,7 @@ builder.Services.AddSingleton<ISearcher>(new Searcher(CachePolicy.Content, Path.
|
|||||||
//builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
|
//builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
|
||||||
//builder.Services.AddProblemDetails();
|
//builder.Services.AddProblemDetails();
|
||||||
|
|
||||||
|
|
||||||
#region 历史废弃配置
|
#region 历史废弃配置
|
||||||
//builder.Services.AddMemoryCache();
|
//builder.Services.AddMemoryCache();
|
||||||
////上传限制 配置
|
////上传限制 配置
|
||||||
@@ -215,6 +235,7 @@ var env = app.Environment;
|
|||||||
|
|
||||||
#region 配置中间件
|
#region 配置中间件
|
||||||
|
|
||||||
|
app.UseMiddleware<EncryptionRequestMiddleware>();
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
// Configure the HTTP request pipeline.
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using Hangfire;
|
using Hangfire;
|
||||||
using Hangfire.Dashboard;
|
using Hangfire.Dashboard;
|
||||||
using Hangfire.Dashboard.BasicAuthorization;
|
using Hangfire.Dashboard.BasicAuthorization;
|
||||||
using IRaCIS.Application.Services.BackGroundJob;
|
using IRaCIS.Core.Application.Service.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;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ namespace IRaCIS.Core.API
|
|||||||
|
|
||||||
// 全局忽略 DomainEvents 属性
|
// 全局忽略 DomainEvents 属性
|
||||||
automapper.AddGlobalIgnore(nameof(Entity.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.
|
||||||
|
|||||||
@@ -9,7 +9,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.Application.Services;
|
using IRaCIS.Core.Application.Service;
|
||||||
using IRaCIS.Application.Interfaces;
|
using IRaCIS.Application.Interfaces;
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,11 @@ using Medallion.Threading;
|
|||||||
using Medallion.Threading.SqlServer;
|
using Medallion.Threading.SqlServer;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
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
|
||||||
@@ -46,10 +48,11 @@ namespace IRaCIS.Core.API
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value, contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure());
|
options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value, contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//迁移的时候,不生成外键
|
||||||
|
options.ReplaceService<IMigrationsSqlGenerator, NoForeignKeyMigrationsSqlGenerator>();
|
||||||
|
|
||||||
|
|
||||||
options.UseLoggerFactory(logFactory);
|
options.UseLoggerFactory(logFactory);
|
||||||
@@ -72,18 +75,15 @@ namespace IRaCIS.Core.API
|
|||||||
|
|
||||||
options.UseTriggers(triggerOptions =>
|
options.UseTriggers(triggerOptions =>
|
||||||
{
|
{
|
||||||
triggerOptions.AddTrigger<AddSubjectTrigger>();
|
triggerOptions.AddTrigger<SubjectTrigger>();
|
||||||
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<VisitTaskIbeforeTrigger>();
|
triggerOptions.AddTrigger<JudgeVisitTaskTrigger>();
|
||||||
|
|
||||||
triggerOptions.AddTrigger<UserLogTrigger>();
|
triggerOptions.AddTrigger<UserLogTrigger>();
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,9 @@ namespace IRaCIS.Core.API
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Default or English date format
|
// Default or English date format
|
||||||
_dateFormat = "MM/dd/yyyy HH:mm:ss";
|
//_dateFormat = "MM/dd/yyyy HH:mm:ss";
|
||||||
|
|
||||||
|
_dateFormat = "yyyy-MM-dd HH:mm:ss";
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -13,15 +13,16 @@
|
|||||||
"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": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
"AccessKeyId": "LTAI5tNRTsqL6aWmHkDmTwoH",
|
||||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
"AccessKeySecret": "7mtGz3qrYWI6JMMBZiLeC119VWicZH",
|
||||||
"bucketName": "zy-irc-store",
|
"RoleArn": "acs:ram::1899121822495495:role/irc-oss-access",
|
||||||
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
"BucketName": "zy-irc-store",
|
||||||
"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",
|
||||||
@@ -63,7 +64,8 @@
|
|||||||
"CompanyName": "Extensive Imaging",
|
"CompanyName": "Extensive Imaging",
|
||||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||||
"CompanyShortName": "Extensive Imaging",
|
"CompanyShortName": "Extensive Imaging",
|
||||||
"CompanyShortNameCN": "展影医疗"
|
"CompanyShortNameCN": "展影医疗",
|
||||||
|
"IsEnv_US": false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -15,15 +15,16 @@
|
|||||||
"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": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
"AccessKeyId": "LTAI5tNRTsqL6aWmHkDmTwoH",
|
||||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
"AccessKeySecret": "7mtGz3qrYWI6JMMBZiLeC119VWicZH",
|
||||||
"bucketName": "zy-irc-store",
|
"RoleArn": "acs:ram::1899121822495495:role/irc-oss-access",
|
||||||
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
"BucketName": "zy-irc-store",
|
||||||
"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",
|
||||||
@@ -67,7 +68,8 @@
|
|||||||
"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",
|
||||||
|
|||||||
@@ -19,10 +19,10 @@
|
|||||||
"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": "LTAI5tJV76pYX5yPg1N9QVE8",
|
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
|
||||||
"AccessKeySecret": "roRNLa9YG1of4pYruJGCNKBXEWTAWa",
|
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
|
||||||
|
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
|
||||||
"BucketName": "zy-irc-test-store",
|
"BucketName": "zy-irc-test-store",
|
||||||
"RoleArn": "acs:ram::1899121822495495:role/webdirect",
|
|
||||||
"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
|
"DurationSeconds": 7200
|
||||||
@@ -40,11 +40,11 @@
|
|||||||
"Region": "us-east-1",
|
"Region": "us-east-1",
|
||||||
"EndPoint": "s3.us-east-1.amazonaws.com",
|
"EndPoint": "s3.us-east-1.amazonaws.com",
|
||||||
"UseSSL": true,
|
"UseSSL": true,
|
||||||
"RoleArn": "arn:aws:iam::471112624751:role/sts_s3_upload",
|
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
|
||||||
"AccessKeyId": "AKIAW3MEAFJXWRCGSX5Z",
|
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
|
||||||
"SecretAccessKey": "miais4jQGSd37A+TfBEP11AQM5u/CvotSmznJd8k",
|
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
|
||||||
"BucketName": "ei-med-s3-lili-uat-store",
|
"BucketName": "ei-med-s3-lili-uat-store",
|
||||||
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com/",
|
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com",
|
||||||
"DurationSeconds": 7200
|
"DurationSeconds": 7200
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -88,7 +88,8 @@
|
|||||||
"CompanyName": "Extensive Imaging",
|
"CompanyName": "Extensive Imaging",
|
||||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||||
"CompanyShortName": "Extensive Imaging",
|
"CompanyShortName": "Extensive Imaging",
|
||||||
"CompanyShortNameCN": "展影医疗"
|
"CompanyShortNameCN": "展影医疗",
|
||||||
|
"IsEnv_US": false
|
||||||
},
|
},
|
||||||
|
|
||||||
"SystemPacsConfig": {
|
"SystemPacsConfig": {
|
||||||
|
|||||||
@@ -15,18 +15,6 @@
|
|||||||
|
|
||||||
"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",
|
||||||
@@ -38,12 +26,15 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"AWS": {
|
"AWS": {
|
||||||
"endPoint": "s3.us-east-1.amazonaws.com",
|
"Region": "us-east-1",
|
||||||
"useSSL": true,
|
"EndPoint": "s3.us-east-1.amazonaws.com",
|
||||||
"accessKey": "AKIAW3MEAFJX5P32P6NA",
|
"UseSSL": true,
|
||||||
"secretKey": "soKfYlzZE11Zi4RyTjXp0myXN0U3U+ka8rT49+B/",
|
"RoleArn": "arn:aws:iam::471112624751:role/lili_s3_access",
|
||||||
"bucketName": "ei-med-s3-lili-store",
|
"AccessKeyId": "AKIAW3MEAFJXZ2TZK7GM",
|
||||||
"viewEndpoint": "https://ei-med-s3-lili-store.s3.amazonaws.com/"
|
"SecretAccessKey": "9MLQCQ1HifEVW1gf068zBRAOb4wNnfrOkvBVByth",
|
||||||
|
"BucketName": "ei-med-s3-lili-store",
|
||||||
|
"ViewEndpoint": "https://ei-med-s3-lili-store.s3.amazonaws.com",
|
||||||
|
"DurationSeconds": 7200
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"BasicSystemConfig": {
|
"BasicSystemConfig": {
|
||||||
@@ -82,7 +73,13 @@
|
|||||||
"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,19 +13,7 @@
|
|||||||
|
|
||||||
"ObjectStoreService": {
|
"ObjectStoreService": {
|
||||||
|
|
||||||
"ObjectStoreUse": "MinIO",
|
"ObjectStoreUse": "AWS",
|
||||||
"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",
|
||||||
@@ -44,23 +32,26 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"AWS": {
|
"AWS": {
|
||||||
"endPoint": "s3.us-east-1.amazonaws.com",
|
"Region": "us-east-1",
|
||||||
"useSSL": true,
|
"EndPoint": "s3.us-east-1.amazonaws.com",
|
||||||
"accessKey": "AKIAZQ3DRSOHFPJJ6FEU",
|
"UseSSL": true,
|
||||||
"secretKey": "l+yjtvV7Z4jiwm/7xCYv30UeUj/SvuqqYzAwjJHf",
|
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
|
||||||
"bucketName": "ei-irc-test-store",
|
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
|
||||||
"viewEndpoint": "https://ei-irc-test-store.s3.amazonaws.com/"
|
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
|
||||||
|
"BucketName": "ei-med-s3-lili-uat-store",
|
||||||
|
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com",
|
||||||
|
"DurationSeconds": 7200
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"BasicSystemConfig": {
|
"BasicSystemConfig": {
|
||||||
|
|
||||||
"OpenUserComplexPassword": false,
|
"OpenUserComplexPassword": true,
|
||||||
|
|
||||||
"OpenSignDocumentBeforeWork": false,
|
"OpenSignDocumentBeforeWork": true,
|
||||||
|
|
||||||
"OpenTrialRelationDelete": true,
|
"OpenTrialRelationDelete": true,
|
||||||
|
|
||||||
"OpenLoginLimit": false,
|
"OpenLoginLimit": true,
|
||||||
|
|
||||||
"LoginMaxFailCount": 5,
|
"LoginMaxFailCount": 5,
|
||||||
|
|
||||||
@@ -72,7 +63,9 @@
|
|||||||
"ReadingRestTimeMin": 10,
|
"ReadingRestTimeMin": 10,
|
||||||
"IsNeedChangePassWord": true,
|
"IsNeedChangePassWord": true,
|
||||||
|
|
||||||
"ChangePassWordDays": 90
|
"ChangePassWordDays": 90,
|
||||||
|
|
||||||
|
"OpenLoginMFA": true
|
||||||
},
|
},
|
||||||
|
|
||||||
"SystemEmailSendConfig": {
|
"SystemEmailSendConfig": {
|
||||||
@@ -88,7 +81,13 @@
|
|||||||
"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,19 +36,22 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"AWS": {
|
"AWS": {
|
||||||
"endPoint": "s3.us-east-1.amazonaws.com",
|
"Region": "us-east-1",
|
||||||
"useSSL": true,
|
"EndPoint": "s3.us-east-1.amazonaws.com",
|
||||||
"accessKey": "AKIAW3MEAFJXUO6XYFYN",
|
"UseSSL": true,
|
||||||
"secretKey": "AeX5r4xHQH7tNJlTTFVv5/zBXie1Kj+mAayKrukp",
|
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
|
||||||
"bucketName": "ei-med-s3-lili-uat-store",
|
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
|
||||||
"viewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com/"
|
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
|
||||||
|
"BucketName": "ei-med-s3-lili-uat-store",
|
||||||
|
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com/",
|
||||||
|
"DurationSeconds": 7200
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"BasicSystemConfig": {
|
"BasicSystemConfig": {
|
||||||
|
|
||||||
"OpenUserComplexPassword": false,
|
"OpenUserComplexPassword": true,
|
||||||
|
|
||||||
"OpenSignDocumentBeforeWork": false,
|
"OpenSignDocumentBeforeWork": true,
|
||||||
|
|
||||||
"OpenTrialRelationDelete": true,
|
"OpenTrialRelationDelete": true,
|
||||||
|
|
||||||
@@ -66,7 +69,7 @@
|
|||||||
|
|
||||||
"ChangePassWordDays": 90,
|
"ChangePassWordDays": 90,
|
||||||
|
|
||||||
"OpenLoginMFA": true
|
"OpenLoginMFA": false
|
||||||
},
|
},
|
||||||
|
|
||||||
"SystemEmailSendConfig": {
|
"SystemEmailSendConfig": {
|
||||||
@@ -82,7 +85,13 @@
|
|||||||
"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,15 +15,16 @@
|
|||||||
"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": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
|
||||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
|
||||||
"bucketName": "zy-irc-uat-store",
|
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
|
||||||
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
"BucketName": "zy-irc-uat-store",
|
||||||
"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": {
|
||||||
@@ -38,6 +39,17 @@
|
|||||||
"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
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -74,7 +86,8 @@
|
|||||||
"CompanyName": "Extensive Imaging",
|
"CompanyName": "Extensive Imaging",
|
||||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||||
"CompanyShortName": "Extensive Imaging",
|
"CompanyShortName": "Extensive Imaging",
|
||||||
"CompanyShortNameCN": "展影医疗"
|
"CompanyShortNameCN": "展影医疗",
|
||||||
|
"IsEnv_US": false
|
||||||
},
|
},
|
||||||
|
|
||||||
"SystemPacsConfig": {
|
"SystemPacsConfig": {
|
||||||
|
|||||||
@@ -43,40 +43,6 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"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,
|
||||||
@@ -88,13 +54,15 @@
|
|||||||
"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": {
|
||||||
"IsEnable": true,
|
"Base64RSAPublicKey": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0NCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBaHp3T1hYTWYyaEFkS1ZoWHczYUYNCmNaT3QycE1lcmdEaFVrOUdQK2s4VDBrUjFTRVlGVGtzNlkzaEVvL0dRTExqMHZFYVV3bTNhSFNuTTl5NmdLRWoNCmY5cTN6dkoyZzRSQjE4Z0UrTnNWWi9DMkVRZ3k5OWFiWGc5TitGREVlT0NmSjlSRTJPV3JBQ2s0V0RPbFFUdXYNCnhvR2JmcnkwVElSaFBrOGtuYkFmVkZ1and1VXJGblpJZ0ExYXhKZVZ6aDhwcmV1SEgreW1jdHp6NVo4V1pSV3kNCi9ISURHUy90dkg2NUMra2l6cUxRYUpKNHYwODMrRGpaVTBmNzNCdkk5eWt1dW1saXFzY1pvU2preDFOUFJwSkUNCkFtMVFNQ0hMRCtFdzlHT2Vsc2Mwa1ZxdjdaeEF1TkFrMkZuUURNRk1BUmZuUFd0aGVhOGZYVTJsMW9ROWs3WDcNCmN3SURBUUFCDQotLS0tLUVORCBQVUJMSUMgS0VZLS0tLS0NCg==",
|
||||||
|
"Base64RSAPrivateKey": "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRW9nSUJBQUtDQVFFQWh6d09YWE1mMmhBZEtWaFh3M2FGY1pPdDJwTWVyZ0RoVWs5R1ArazhUMGtSMVNFWQ0KRlRrczZZM2hFby9HUUxMajB2RWFVd20zYUhTbk05eTZnS0VqZjlxM3p2SjJnNFJCMThnRStOc1ZaL0MyRVFneQ0KOTlhYlhnOU4rRkRFZU9DZko5UkUyT1dyQUNrNFdET2xRVHV2eG9HYmZyeTBUSVJoUGs4a25iQWZWRnVqd3VVcg0KRm5aSWdBMWF4SmVWemg4cHJldUhIK3ltY3R6ejVaOFdaUld5L0hJREdTL3R2SDY1QytraXpxTFFhSko0djA4Mw0KK0RqWlUwZjczQnZJOXlrdXVtbGlxc2Nab1Nqa3gxTlBScEpFQW0xUU1DSExEK0V3OUdPZWxzYzBrVnF2N1p4QQ0KdU5BazJGblFETUZNQVJmblBXdGhlYThmWFUybDFvUTlrN1g3Y3dJREFRQUJBb0lCQUNDRFoxNi9XWWFYZmpOZA0KQ29pemU2VFJZU2llVzI5eFJic0ExVDV6YUcwVmY4U1NsdFF2Y1dWYmw2UGJUa3BxMkF4MHJDUVB2M2xOSm8vNA0KL3h3QzRlS1E1c1ZLRlFWTXJIbmhISlRxTTJ6UWVpMkJINlBuaEdZcVh0QVhOdzFxejhrSEoyQlFZM3IvN2d5Qw0KcWpZVFVCRDFRem5HeThCanlXOXVIcnNNeDVPRHRRZWxBM3B1TFd1bXZNb3Z1L2JhaDZvTGtOSHY4b0VTdzhGSQ0KTllyTUtscHhFTjZaWUdwSTl2VTZnYUhuTmhEa2ExTHlvUnZ5NnA2dTRLR0FsRTc1VXk4T0dsdncydU5uay9sdg0KSEMyYnY5TnlCRGJpSFNDY0MyK1JXUXMrN0tNWFlwYnBvTVFCR0hqV01GRHVBODFaUCs1TWYxUm9yQUpRNGxrRw0KQnRDQThva0NnWUVBeWY4alBjcFIvQ3dJNU5MYnlwb3ZUWEFHVkFKMmtWRlJVUC9HT2ZOMkFyYWMvL20wdDJ5NA0KemNYVkJZc0pJeHkvVWYxRTFJNFg3VFg3V3NBNGxVNGlPTkwzTnN4dDBEbk1PV2tKUlBPZlF1bW1JaWw5QVRiYQ0KTnRVWFNlTmRoUFFGMGlCb21acFFJYWpSN1RmUnVBbzR6dmpTLzkzeXZZY0lIWU1zM0tjR00ya0NnWUVBcTJPbg0KZlp0RmhLTElGanVlRzRrNklGTWdjbytEUUh5TTFWSUp5Tk05K1o2TEgybzI5eDJCaSs2Qm82M2NKUjQ2STZncQ0KNWUrSTBvdzZRYmNQeTZUNHFSQ0o3Ujd6MllkdEw4eXdJTkNYS3U0cC9qaFNqNWJ1TzFJWlI3ZStSV29CakNtUQ0KWFd0ZVBCbldqWVlLdVRCazROc2FXV09GTXg1QndKdUp2MjBnQ0hzQ2dZQlV4QnFYM1lWV0cyeUlDZXh1TXhIUw0KbjBZb2p2Z090MTgyYkg5VTVsUUpnM1NTL3NqVmlHeHMvYTROSzNGa0tMWW93KzNVZk9TUmlPdTRBNTQ3R1pURw0KMzlFYVQrTnRWRFBkaTdSMkdQNG1hRUp0WjVlcm9NY2w1M3BrYVdOZlhiL3JrK29STzI2UkVYVTI1UXUrL1pzbA0KVDhuTDBlb0JtdDdPODdNcHpYV09zUUtCZ0ZxVGFQSGx2RUNUY3FEbFV2S0VmRmFXOTkvelhrOFhRNnA5RjdTdA0KaHVSRDJJeDZxcC9BVlRWcGo5Tzd6MHRDaFVGUTM1THpHMkVDUU10My9uNEdLbS9XMEwyakRRWWFIeWNTeXNZYw0KMXJjV2ROVG9XU0dQaDBtTVl0WFhFbFJHNkpoMVl0a3NJL29wUVkwN21MRTBGU3dNUHdtY29jbFpKVEN3UW9VTA0KRzlHL0FvR0FWM25kcWcydnUyR0x4TlRUbm1UTWRJNFB3UzBmN0V4VnVNUnRicGZyOWhKNzlDakVNTGFXQ1FsNg0KeE43TElMTnArNVQwQW1DZVBqcitkbnJkRUNidFZPTDFybDc3Z0krRkwzaVVqYmZmMVZqa0N3M0x6K3cyb1FFdA0KbGE4aTZrL1NRK01iYkRPaWRJOVczdlN6MmlJRlZobWJiK1Q2SlZwakxqNjlkblM3eUxZPQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg==",
|
||||||
|
"IsResponseEncreptEnable": true,
|
||||||
"ApiPathList": [
|
"ApiPathList": [
|
||||||
"/test/get"
|
"/test/get"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
<!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>
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
<!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>
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
<!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>
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
<!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>
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
<!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>
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
<!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>
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
<!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>
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
<!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>
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
<!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>
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
<!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>
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
<!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>
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
<!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>
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
<!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>
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
<!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>
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
<!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>
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
<!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>
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
<!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>
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
<!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,
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ namespace IRaCIS.Core.Application.Auth
|
|||||||
{
|
{
|
||||||
Id = doctor.Id,
|
Id = doctor.Id,
|
||||||
FullName = doctor.FirstName + doctor.LastName,
|
FullName = doctor.FirstName + doctor.LastName,
|
||||||
Phone = doctor.Phone,
|
Phone = doctor.Phone,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,4 @@
|
|||||||
using System;
|
namespace IRaCIS.Core.Application.Auth
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Auth
|
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
@@ -13,7 +7,7 @@ namespace IRaCIS.Core.Application.Auth
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public const string CRC = "CRC";
|
public const string CRC = "CRC";
|
||||||
|
|
||||||
public const string PM = "PM";
|
public const string PM = "PM";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
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 System.IdentityModel.Tokens.Jwt;
|
using IRaCIS.Core.Domain.Share;
|
||||||
using System.Security.Claims;
|
|
||||||
using IRaCIS.Core.Domain.Share;
|
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using System.Security.Claims;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Auth
|
namespace IRaCIS.Core.Application.Auth
|
||||||
{
|
{
|
||||||
@@ -56,5 +56,5 @@ namespace IRaCIS.Core.Application.Auth
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,10 @@
|
|||||||
using Hangfire;
|
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;
|
|
||||||
using ZiggyCreatures.Caching.Fusion;
|
|
||||||
|
|
||||||
namespace IRaCIS.Application.Services.BackGroundJob
|
namespace IRaCIS.Core.Application.Service.BackGroundJob
|
||||||
{
|
{
|
||||||
|
|
||||||
public interface IIRaCISHangfireJob
|
public interface IIRaCISHangfireJob
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
using IRaCIS.Core.Infra.EFCore;
|
using Microsoft.Extensions.Logging;
|
||||||
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
|
||||||
@@ -13,7 +12,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;
|
||||||
@@ -30,7 +29,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,17 +1,16 @@
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using IRaCIS.Application.Services.BusinessFilter;
|
using IRaCIS.Core.Application.Service.BusinessFilter;
|
||||||
using IRaCIS.Core.Infra.EFCore;
|
using IRaCIS.Core.Domain.Share;
|
||||||
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 IRaCIS.Core.Domain.Share;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using ZiggyCreatures.Caching.Fusion;
|
using ZiggyCreatures.Caching.Fusion;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application
|
namespace IRaCIS.Core.Application.Service
|
||||||
{
|
{
|
||||||
|
|
||||||
#pragma warning disable CS8618
|
#pragma warning disable CS8618
|
||||||
|
|||||||
@@ -1,71 +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;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.BusinessFilter
|
|
||||||
{
|
|
||||||
public class EncreptApiResultFilter : IAsyncResultFilter
|
|
||||||
{
|
|
||||||
|
|
||||||
private readonly IOptionsMonitor<EncreptResponseOption> _encreptResponseMonitor;
|
|
||||||
|
|
||||||
public EncreptApiResultFilter(IOptionsMonitor<EncreptResponseOption> encreptResponseMonitor)
|
|
||||||
{
|
|
||||||
_encreptResponseMonitor = encreptResponseMonitor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
|
|
||||||
{
|
|
||||||
|
|
||||||
if(_encreptResponseMonitor.CurrentValue.IsEnable)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (context.Result is ObjectResult objectResult)
|
|
||||||
{
|
|
||||||
var statusCode = objectResult.StatusCode ?? context.HttpContext.Response.StatusCode;
|
|
||||||
|
|
||||||
var objectValue = objectResult.Value;
|
|
||||||
|
|
||||||
|
|
||||||
if (objectValue is IResponseOutput)
|
|
||||||
{
|
|
||||||
var responseOutput = objectValue as IResponseOutput<object>;
|
|
||||||
|
|
||||||
var path = context.HttpContext?.Request.Path.Value?.ToLower();
|
|
||||||
|
|
||||||
|
|
||||||
if(!string.IsNullOrEmpty(path) && path.Length>5 && _encreptResponseMonitor.CurrentValue.ApiPathList.Contains(path.ToLower()))
|
|
||||||
{
|
|
||||||
|
|
||||||
if(responseOutput.IsSuccess)
|
|
||||||
{
|
|
||||||
responseOutput.Code = ApiResponseCodeEnum.ResultEncrepted;
|
|
||||||
responseOutput.Data = JsonConvert.SerializeObject(Convert.ToBase64String(Encoding.UTF8.GetBytes(responseOutput.Data.ToString())));
|
|
||||||
|
|
||||||
objectResult.Value = responseOutput;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
await next.Invoke();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
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,50 +1,43 @@
|
|||||||
using Microsoft.AspNetCore.Diagnostics;
|
using Microsoft.AspNetCore.Diagnostics;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.BusinessFilter
|
namespace IRaCIS.Core.Application.BusinessFilter;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 不生效,不知道为啥
|
||||||
|
/// </summary>
|
||||||
|
public class GlobalExceptionHandler : IExceptionHandler
|
||||||
{
|
{
|
||||||
|
private readonly ILogger<GlobalExceptionHandler> _logger;
|
||||||
/// <summary>
|
public GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger)
|
||||||
/// 不生效,不知道为啥
|
{
|
||||||
/// </summary>
|
this._logger = logger;
|
||||||
public class GlobalExceptionHandler : IExceptionHandler
|
}
|
||||||
|
public ValueTask<bool> TryHandleAsync(
|
||||||
|
HttpContext httpContext,
|
||||||
|
Exception exception,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
private readonly ILogger<GlobalExceptionHandler> _logger;
|
|
||||||
public GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger)
|
|
||||||
{
|
|
||||||
this._logger = logger;
|
|
||||||
}
|
|
||||||
public ValueTask<bool> TryHandleAsync(
|
|
||||||
HttpContext httpContext,
|
|
||||||
Exception exception,
|
|
||||||
CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
httpContext.Response.ContentType = "application/json";
|
httpContext.Response.ContentType = "application/json";
|
||||||
|
|
||||||
|
|
||||||
var ex = exception;
|
var ex = exception;
|
||||||
var errorInfo = $"Exception: {ex.Message}[{ex.StackTrace}]" + (ex.InnerException != null ? $" InnerException: {ex.InnerException.Message}[{ex.InnerException.StackTrace}]" : "");
|
var errorInfo = $"Exception: {ex.Message}[{ex.StackTrace}]" + (ex.InnerException != null ? $" InnerException: {ex.InnerException.Message}[{ex.InnerException.StackTrace}]" : "");
|
||||||
|
|
||||||
httpContext.Response.WriteAsJsonAsync(ResponseOutput.NotOk($"{ex?.Message}"));
|
httpContext.Response.WriteAsJsonAsync(ResponseOutput.NotOk($"{ex?.Message}"));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
_logger.LogError(errorInfo);
|
_logger.LogError(errorInfo);
|
||||||
|
|
||||||
// return true to signal that this exception is handled
|
// return true to signal that this exception is handled
|
||||||
return ValueTask.FromResult(false);
|
return ValueTask.FromResult(false);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
using IRaCIS.Core.Application.Helper;
|
using IRaCIS.Core.Application.Helper;
|
||||||
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 Newtonsoft.Json;
|
|
||||||
using ZiggyCreatures.Caching.Fusion;
|
using ZiggyCreatures.Caching.Fusion;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Filter;
|
namespace IRaCIS.Core.Application.Filter;
|
||||||
@@ -25,7 +23,7 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter
|
|||||||
|
|
||||||
private readonly IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig;
|
private readonly IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig;
|
||||||
|
|
||||||
public LimitUserRequestAuthorization(IFusionCache fusionCache, IUserInfo userInfo, IStringLocalizer localizer ,IOptionsMonitor<ServiceVerifyConfigOption> verifyConfig)
|
public LimitUserRequestAuthorization(IFusionCache fusionCache, IUserInfo userInfo, IStringLocalizer localizer, IOptionsMonitor<ServiceVerifyConfigOption> verifyConfig)
|
||||||
{
|
{
|
||||||
_fusionCache = fusionCache;
|
_fusionCache = fusionCache;
|
||||||
_userInfo = userInfo;
|
_userInfo = userInfo;
|
||||||
@@ -55,7 +53,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"]));
|
||||||
@@ -92,7 +90,7 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter
|
|||||||
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_AccountAuto_LoginOut"], ApiResponseCodeEnum.AutoLoginOut));
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["LimitUser_AccountAuto_LoginOut"], ApiResponseCodeEnum.AutoLoginOut));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -106,7 +104,7 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter
|
|||||||
//---您的账户在其他地方已登陆,您被迫下线。
|
//---您的账户在其他地方已登陆,您被迫下线。
|
||||||
|
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["LimitUser_AccountLoggedInElsewhere"], ApiResponseCodeEnum.LoginInOtherPlace));
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["LimitUser_AccountLoggedInElsewhere"], ApiResponseCodeEnum.LoginInOtherPlace));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +1,34 @@
|
|||||||
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 Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Filter
|
namespace IRaCIS.Core.Application.Filter;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class ModelActionFilter : ActionFilterAttribute, IActionFilter
|
||||||
{
|
{
|
||||||
|
public IStringLocalizer _localizer;
|
||||||
|
public ModelActionFilter(IStringLocalizer localizer)
|
||||||
public class ModelActionFilter : ActionFilterAttribute, IActionFilter
|
|
||||||
{
|
{
|
||||||
public IStringLocalizer _localizer;
|
_localizer = localizer;
|
||||||
public ModelActionFilter(IStringLocalizer localizer)
|
|
||||||
{
|
|
||||||
_localizer = localizer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnActionExecuting(ActionExecutingContext context)
|
|
||||||
{
|
|
||||||
if (!context.ModelState.IsValid)
|
|
||||||
{
|
|
||||||
|
|
||||||
var validationErrors = context.ModelState
|
|
||||||
.Keys
|
|
||||||
.SelectMany(k => context.ModelState[k]!.Errors)
|
|
||||||
.Select(e => e.ErrorMessage)
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
//---提供给接口的参数无效。
|
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ModelAction_InvalidAPIParameter"] + JsonConvert.SerializeObject( validationErrors)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void OnActionExecuting(ActionExecutingContext context)
|
||||||
|
{
|
||||||
|
if (!context.ModelState.IsValid)
|
||||||
|
{
|
||||||
|
|
||||||
|
var validationErrors = context.ModelState
|
||||||
|
.Keys
|
||||||
|
.SelectMany(k => context.ModelState[k]!.Errors)
|
||||||
|
.Select(e => e.ErrorMessage)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
//---提供给接口的参数无效。
|
||||||
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ModelAction_InvalidAPIParameter"] + JsonConvert.SerializeObject(validationErrors)));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,26 @@
|
|||||||
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
|
||||||
{
|
{
|
||||||
#region snippet_DisableFormValueModelBindingAttribute
|
public void OnResourceExecuting(ResourceExecutingContext context)
|
||||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
|
||||||
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
|
|
||||||
{
|
{
|
||||||
public void OnResourceExecuting(ResourceExecutingContext context)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
var factories = context.ValueProviderFactories;
|
var factories = context.ValueProviderFactories;
|
||||||
//factories.RemoveType<FormValueProviderFactory>();
|
//factories.RemoveType<FormValueProviderFactory>();
|
||||||
factories.RemoveType<FormFileValueProviderFactory>();
|
factories.RemoveType<FormFileValueProviderFactory>();
|
||||||
factories.RemoveType<JQueryFormValueProviderFactory>();
|
factories.RemoveType<JQueryFormValueProviderFactory>();
|
||||||
context.HttpContext.Request.EnableBuffering();
|
context.HttpContext.Request.EnableBuffering();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnResourceExecuted(ResourceExecutedContext context)
|
public void OnResourceExecuted(ResourceExecutedContext context)
|
||||||
{
|
{
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|||||||
@@ -1,77 +1,75 @@
|
|||||||
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
|
||||||
{
|
{
|
||||||
public class ProjectExceptionFilter : Attribute, IExceptionFilter
|
private readonly ILogger<ProjectExceptionFilter> _logger;
|
||||||
|
|
||||||
|
public IStringLocalizer _localizer;
|
||||||
|
|
||||||
|
public ProjectExceptionFilter(IStringLocalizer localizer, ILogger<ProjectExceptionFilter> logger)
|
||||||
{
|
{
|
||||||
private readonly ILogger<ProjectExceptionFilter> _logger;
|
_logger = logger;
|
||||||
|
_localizer = localizer;
|
||||||
|
}
|
||||||
|
public void OnException(ExceptionContext context)
|
||||||
|
{
|
||||||
|
//context.ExceptionHandled;//记录当前这个异常是否已经被处理过了
|
||||||
|
|
||||||
public IStringLocalizer _localizer;
|
if (!context.ExceptionHandled)
|
||||||
|
|
||||||
public ProjectExceptionFilter(IStringLocalizer localizer, ILogger<ProjectExceptionFilter> logger)
|
|
||||||
{
|
{
|
||||||
_logger = logger;
|
if (context.Exception.GetType().Name == "DbUpdateConcurrencyException")
|
||||||
_localizer = localizer;
|
|
||||||
}
|
|
||||||
public void OnException(ExceptionContext context)
|
|
||||||
{
|
|
||||||
//context.ExceptionHandled;//记录当前这个异常是否已经被处理过了
|
|
||||||
|
|
||||||
if (!context.ExceptionHandled)
|
|
||||||
{
|
{
|
||||||
if (context.Exception.GetType().Name == "DbUpdateConcurrencyException")
|
//---并发更新,当前不允许该操作
|
||||||
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ProjectException_ConcurrentUpdateNotAllowed"] + context.Exception.Message));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.Exception.GetType() == typeof(BusinessValidationFailedException))
|
||||||
|
{
|
||||||
|
var error = context.Exception as BusinessValidationFailedException;
|
||||||
|
|
||||||
|
var info = string.Empty;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(error!.LocalizedKey) && StaticData.Log_Locoalize_Dic.ContainsKey(error!.LocalizedKey))
|
||||||
{
|
{
|
||||||
//---并发更新,当前不允许该操作
|
info = $"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}";
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ProjectException_ConcurrentUpdateNotAllowed"] + context.Exception.Message));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.Exception.GetType() == typeof(BusinessValidationFailedException))
|
|
||||||
{
|
|
||||||
var error = context.Exception as BusinessValidationFailedException;
|
|
||||||
|
|
||||||
var info = string.Empty;
|
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, "", error!.Code, localizedInfo: info));
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(error!.LocalizedKey) && StaticData.Log_Locoalize_Dic.ContainsKey(error!.LocalizedKey))
|
|
||||||
{
|
|
||||||
info = $"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, "", error!.Code, localizedInfo: info));
|
//warning 级别记录
|
||||||
|
//_logger.LogWarning($"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}");
|
||||||
|
}
|
||||||
//warning 级别记录
|
else if (context.Exception.GetType() == typeof(QueryBusinessObjectNotExistException))
|
||||||
//_logger.LogWarning($"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}");
|
{
|
||||||
}
|
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, ApiResponseCodeEnum.DataNotExist));
|
||||||
else if (context.Exception.GetType() == typeof(QueryBusinessObjectNotExistException))
|
|
||||||
{
|
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, ApiResponseCodeEnum.DataNotExist));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (context.Exception.InnerException is null ? (context.Exception.Message /*+ context.Exception.StackTrace*/)
|
|
||||||
: (context.Exception.InnerException?.Message /*+ context.Exception.InnerException?.StackTrace*/)), ApiResponseCodeEnum.ProgramException));
|
|
||||||
|
|
||||||
_logger.LogError(context.Exception.InnerException is null ? (context.Exception.Message + context.Exception.StackTrace) : (context.Exception.InnerException?.Message + context.Exception.InnerException?.StackTrace));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
context.ExceptionHandled = true;//标记当前异常已经被处理过了
|
|
||||||
|
|
||||||
|
|
||||||
//throw new Exception("test-result-exceptioin");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//继续
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (context.Exception.InnerException is null ? (context.Exception.Message /*+ context.Exception.StackTrace*/)
|
||||||
|
: (context.Exception.InnerException?.Message /*+ context.Exception.InnerException?.StackTrace*/)), ApiResponseCodeEnum.ProgramException));
|
||||||
|
|
||||||
|
_logger.LogError(context.Exception.InnerException is null ? (context.Exception.Message + context.Exception.StackTrace) : (context.Exception.InnerException?.Message + context.Exception.InnerException?.StackTrace));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context.ExceptionHandled = true;//标记当前异常已经被处理过了
|
||||||
|
|
||||||
|
|
||||||
|
//throw new Exception("test-result-exceptioin");
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//继续
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,174 +8,189 @@ using System.Text.RegularExpressions;
|
|||||||
using ZiggyCreatures.Caching.Fusion;
|
using ZiggyCreatures.Caching.Fusion;
|
||||||
using static IRaCIS.Core.Domain.Share.StaticData;
|
using static IRaCIS.Core.Domain.Share.StaticData;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Filter
|
namespace IRaCIS.Core.Application.Filter;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 主要为了 处理项目结束 锁库,不允许操作
|
||||||
|
/// </summary>
|
||||||
|
public class TrialResourceFilter : Attribute, IAsyncResourceFilter
|
||||||
{
|
{
|
||||||
/// <summary>
|
private readonly IUserInfo _userInfo;
|
||||||
/// 主要为了 处理项目结束 锁库,不允许操作
|
private readonly IFusionCache _fusionCache;
|
||||||
/// </summary>
|
public IStringLocalizer _localizer;
|
||||||
public class TrialResourceFilter : Attribute, IAsyncResourceFilter
|
private readonly IRepository<Trial> _trialRepository;
|
||||||
|
private readonly List<string> _trialOptList = new List<string>();
|
||||||
|
|
||||||
|
|
||||||
|
public TrialResourceFilter(IFusionCache fusionCache, IRepository<Trial> trialRepository, IStringLocalizer localizer, IUserInfo userInfo, string trialOpt = null, string trialOpt2 = null, string trialOpt3 = null)
|
||||||
{
|
{
|
||||||
private readonly IUserInfo _userInfo;
|
_fusionCache = fusionCache;
|
||||||
private readonly IFusionCache _fusionCache;
|
_userInfo = userInfo;
|
||||||
public IStringLocalizer _localizer;
|
_localizer = localizer;
|
||||||
private readonly IRepository<Trial> _trialRepository;
|
_trialRepository = trialRepository;
|
||||||
private readonly List<string> _trialOptList = new List<string>();
|
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(trialOpt)) _trialOptList.Add(trialOpt.Trim());
|
||||||
|
if (!string.IsNullOrWhiteSpace(trialOpt2)) _trialOptList.Add(trialOpt2.Trim());
|
||||||
|
if (!string.IsNullOrWhiteSpace(trialOpt3)) _trialOptList.Add(trialOpt3.Trim());
|
||||||
|
|
||||||
public TrialResourceFilter(IFusionCache fusionCache, IRepository<Trial> trialRepository, IStringLocalizer localizer, IUserInfo userInfo, string trialOpt = null, string trialOpt2 = null, string trialOpt3 = null)
|
}
|
||||||
|
|
||||||
|
//优先选择异步的方法
|
||||||
|
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
|
||||||
|
{
|
||||||
|
// var typeFilter = context.ActionDescriptor.EndpointMetadata.Where(t => t.GetType() == typeof(TypeFilterAttribute)).Select(t => (TypeFilterAttribute)t).ToList().FirstOrDefault();
|
||||||
|
//var _trialOptList= typeFilter.Arguments.Select(t => t.ToString()).ToList();
|
||||||
|
|
||||||
|
// 获取当前请求的 Host 信息
|
||||||
|
var requestHost = context.HttpContext.Request.Host;
|
||||||
|
|
||||||
|
// 检查请求是否来自 localhost:6100
|
||||||
|
if (requestHost.Host == "localhost" && (requestHost.Port == 6100|| requestHost.Port==3305))
|
||||||
{
|
{
|
||||||
_fusionCache = fusionCache;
|
await next.Invoke();
|
||||||
_userInfo = userInfo;
|
|
||||||
_localizer = localizer;
|
|
||||||
_trialRepository = trialRepository;
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(trialOpt)) _trialOptList.Add(trialOpt.Trim());
|
|
||||||
if (!string.IsNullOrWhiteSpace(trialOpt2)) _trialOptList.Add(trialOpt2.Trim());
|
|
||||||
if (!string.IsNullOrWhiteSpace(trialOpt3)) _trialOptList.Add(trialOpt3.Trim());
|
|
||||||
|
|
||||||
|
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();
|
//---对不起,您的账户没有操作权限。
|
||||||
//var _trialOptList= typeFilter.Arguments.Select(t => t.ToString()).ToList();
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"]));
|
||||||
|
|
||||||
#region 处理新的用户类型,不能操作项目相关接口
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 后期列举出具体的类型,其他任何用户类型,都不允许操作
|
#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
|
||||||
return;
|
{
|
||||||
|
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
||||||
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#region body 中取数据
|
||||||
|
|
||||||
|
//设置可以多次读
|
||||||
|
context.HttpContext.Request.EnableBuffering();
|
||||||
|
var reader = new StreamReader(context.HttpContext.Request.Body);
|
||||||
|
var contentFromBody = await reader.ReadToEndAsync();
|
||||||
|
//读取后,流的位置还原
|
||||||
|
context.HttpContext.Request.Body.Seek(0, SeekOrigin.Begin);
|
||||||
|
//context.HttpContext.Request.Body.Position = 0;
|
||||||
|
|
||||||
|
//找到参数位置在字符串中的索引
|
||||||
|
var trialIdIndex = contentFromBody.IndexOf("\"TrialId\"", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
//TrialId 传递的途径多种,可能在path 可能在body 可能在数组中,也可能在对象中,可能就在url
|
if (trialIdIndex > -1)
|
||||||
var trialIdStr = string.Empty;
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(context.HttpContext.Request.Query["trialId"]))
|
|
||||||
{
|
{
|
||||||
trialIdStr = context.HttpContext.Request.Query["trialId"];
|
// (?<="trialId" *: *").*?(?=",)
|
||||||
}
|
|
||||||
|
|
||||||
//先尝试从path中取TrialId
|
//使用正则 [0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}
|
||||||
else if (context.RouteData.Values.Keys.Any(t => t.Contains("trialId")))
|
|
||||||
{
|
|
||||||
var index = context.RouteData.Values.Keys.ToList().IndexOf("trialId");
|
|
||||||
trialIdStr = context.RouteData.Values.Values.ToList()[index] as string;
|
|
||||||
}
|
|
||||||
else if (context.HttpContext.Request.Headers["Referer"].ToString().Contains("trialId"))
|
|
||||||
{
|
|
||||||
var headerStr = context.HttpContext.Request.Headers["Referer"].ToString();
|
|
||||||
|
|
||||||
var trialIdIndex = headerStr.IndexOf("trialId");
|
var matchResult = Regex.Match(contentFromBody.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
|
||||||
|
|
||||||
|
|
||||||
var matchResult = Regex.Match(headerStr.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
|
|
||||||
|
|
||||||
if (matchResult.Success)
|
if (matchResult.Success)
|
||||||
{
|
{
|
||||||
|
//有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下
|
||||||
|
|
||||||
trialIdStr = matchResult.Value;
|
trialIdStr = matchResult.Value;
|
||||||
|
|
||||||
|
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(trialStatusStr))
|
||||||
|
{
|
||||||
|
|
||||||
|
//数据库 检查该项目Id不对
|
||||||
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
//使用字符串取 如果是swagger 可能有时取的不对 因为空格的原因
|
||||||
else
|
//trialIdStr = contentFromBody.Substring(trialIdIndex + "TrialId".Length + 4, 3
|
||||||
{
|
|
||||||
#region body 中取数据
|
|
||||||
|
|
||||||
//设置可以多次读
|
|
||||||
context.HttpContext.Request.EnableBuffering();
|
|
||||||
var reader = new StreamReader(context.HttpContext.Request.Body);
|
|
||||||
var contentFromBody = await reader.ReadToEndAsync();
|
|
||||||
//读取后,流的位置还原
|
|
||||||
context.HttpContext.Request.Body.Seek(0, SeekOrigin.Begin);
|
|
||||||
//context.HttpContext.Request.Body.Position = 0;
|
|
||||||
|
|
||||||
//找到参数位置在字符串中的索引
|
|
||||||
var trialIdIndex = contentFromBody.IndexOf("\"TrialId\"", StringComparison.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
if (trialIdIndex > -1)
|
|
||||||
{
|
|
||||||
// (?<="trialId" *: *").*?(?=",)
|
|
||||||
|
|
||||||
//使用正则 [0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}
|
|
||||||
|
|
||||||
var matchResult = Regex.Match(contentFromBody.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
|
|
||||||
|
|
||||||
if (matchResult.Success)
|
|
||||||
{
|
|
||||||
//有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下
|
|
||||||
|
|
||||||
trialIdStr = matchResult.Value;
|
|
||||||
|
|
||||||
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(trialStatusStr))
|
|
||||||
{
|
|
||||||
//数据库 检查该项目Id不对
|
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
|
||||||
}
|
|
||||||
|
|
||||||
//使用字符串取 如果是swagger 可能有时取的不对 因为空格的原因
|
|
||||||
//trialIdStr = contentFromBody.Substring(trialIdIndex + "TrialId".Length + 4, 3
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//通过path 或者body 找到trialId 了
|
#endregion
|
||||||
if (!string.IsNullOrWhiteSpace(trialIdStr))
|
}
|
||||||
|
|
||||||
|
//通过path 或者body 找到trialId 了
|
||||||
|
if (!string.IsNullOrWhiteSpace(trialIdStr))
|
||||||
|
{
|
||||||
|
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
|
||||||
|
|
||||||
|
// 这里是统一拦截 项目有关的操作允许情况(特殊的地方,比如项目配置(有的在多种状态(初始化,ongoing)都可以操作,有的仅仅在Initializing)还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口)
|
||||||
|
if (trialStatusStr == StaticData.TrialState.TrialOngoing || _trialOptList.Any(t => t == TrialOpt.BeforeOngoingCantOpt))
|
||||||
{
|
{
|
||||||
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
|
|
||||||
|
|
||||||
// 这里是统一拦截 项目有关的操作允许情况(特殊的地方,比如项目配置(有的在多种状态(初始化,ongoing)都可以操作,有的仅仅在Initializing)还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口)
|
|
||||||
if (trialStatusStr == StaticData.TrialState.TrialOngoing || _trialOptList.Any(t => t == TrialOpt.BeforeOngoingCantOpt))
|
|
||||||
{
|
|
||||||
|
|
||||||
await next.Invoke();
|
|
||||||
|
|
||||||
}
|
|
||||||
// 项目停止、或者完成 不允许操作
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改
|
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_InterceptedProjectStatusRule"]));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
//添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截
|
|
||||||
else if (_trialOptList.Any(t => t == TrialOpt.AddOrUpdateTrial || t == TrialOpt.SignSystemDocNoTrialId))
|
|
||||||
{
|
|
||||||
await next.Invoke();
|
await next.Invoke();
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
|
// 项目停止、或者完成 不允许操作
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//如果项目相关接口没有传递trialId 会来到这里,提醒,以便修改
|
//---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改
|
||||||
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_InterceptedProjectStatusRule"]));
|
||||||
|
|
||||||
//---该接口参数中,没有传递项目编号,请核对。
|
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_MissingProjectNumber"]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
//添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截
|
||||||
|
else if (_trialOptList.Any(t => t == TrialOpt.AddOrUpdateTrial || t == TrialOpt.SignSystemDocNoTrialId))
|
||||||
|
{
|
||||||
|
await next.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//如果项目相关接口没有传递trialId 会来到这里,提醒,以便修改
|
||||||
|
|
||||||
|
//---该接口参数中,没有传递项目编号,请核对。
|
||||||
|
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_MissingProjectNumber"]));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,123 +1,122 @@
|
|||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using IRaCIS.Core.Domain.Share;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using IRaCIS.Core.Domain.Share;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace IRaCIS.Application.Services.BusinessFilter
|
namespace IRaCIS.Core.Application.Service.BusinessFilter;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 统一返回前端数据包装,之前在控制器包装,现在修改为动态Api 在ResultFilter这里包装,减少重复冗余代码
|
||||||
|
/// by zhouhang 2021.09.12 周末
|
||||||
|
/// </summary>
|
||||||
|
public class UnifiedApiResultFilter : Attribute, IAsyncResultFilter
|
||||||
{
|
{
|
||||||
/// <summary>
|
private readonly ILogger _logger;
|
||||||
/// 统一返回前端数据包装,之前在控制器包装,现在修改为动态Api 在ResultFilter这里包装,减少重复冗余代码
|
|
||||||
/// by zhouhang 2021.09.12 周末
|
public UnifiedApiResultFilter(ILogger<UnifiedApiResultFilter> logger)
|
||||||
/// </summary>
|
|
||||||
public class UnifiedApiResultFilter : Attribute, IAsyncResultFilter
|
|
||||||
{
|
{
|
||||||
private readonly ILogger _logger;
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
public UnifiedApiResultFilter(ILogger<UnifiedApiResultFilter> logger)
|
/// <summary>
|
||||||
|
/// 异步版本
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="context"></param>
|
||||||
|
/// <param name="next"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (context.Result is ObjectResult objectResult)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
var statusCode = objectResult.StatusCode ?? context.HttpContext.Response.StatusCode;
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
//是200 并且没有包装 那么包装结果
|
||||||
/// 异步版本
|
if (statusCode == 200 && !(objectResult.Value is IResponseOutput))
|
||||||
/// </summary>
|
|
||||||
/// <param name="context"></param>
|
|
||||||
/// <param name="next"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (context.Result is ObjectResult objectResult)
|
|
||||||
{
|
{
|
||||||
var statusCode = objectResult.StatusCode ?? context.HttpContext.Response.StatusCode;
|
|
||||||
|
|
||||||
//是200 并且没有包装 那么包装结果
|
var type = objectResult.Value?.GetType();
|
||||||
if (statusCode == 200 && !(objectResult.Value is IResponseOutput))
|
|
||||||
|
|
||||||
|
if (type != null && type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(ValueTuple<,>) || type.GetGenericTypeDefinition() == typeof(Tuple<,>)))
|
||||||
{
|
{
|
||||||
|
|
||||||
var type = objectResult.Value?.GetType();
|
//报错
|
||||||
|
//var tuple = (object, object))objectResult.Value;
|
||||||
|
//var (val1, val2) = ((dynamic, dynamic))objectResult.Value;
|
||||||
if (type != null && type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(ValueTuple<,>) || type.GetGenericTypeDefinition() == typeof(Tuple<,>)))
|
//var apiResponse = ResponseOutput.Ok(val1, val2);
|
||||||
{
|
|
||||||
|
//OK
|
||||||
//报错
|
var tuple = (dynamic)objectResult.Value;
|
||||||
//var tuple = (object, object))objectResult.Value;
|
var apiResponse = ResponseOutput.Ok(tuple!.Item1, tuple!.Item2);
|
||||||
//var (val1, val2) = ((dynamic, dynamic))objectResult.Value;
|
|
||||||
//var apiResponse = ResponseOutput.Ok(val1, val2);
|
|
||||||
|
|
||||||
//OK
|
|
||||||
var tuple = (dynamic)objectResult.Value;
|
|
||||||
var apiResponse = ResponseOutput.Ok(tuple!.Item1, tuple!.Item2);
|
|
||||||
|
|
||||||
|
|
||||||
objectResult.Value = apiResponse;
|
|
||||||
objectResult.DeclaredType = apiResponse.GetType();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var apiResponse = ResponseOutput.Ok(objectResult.Value);
|
|
||||||
|
|
||||||
objectResult.Value = apiResponse;
|
|
||||||
objectResult.DeclaredType = apiResponse.GetType();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
objectResult.Value = apiResponse;
|
||||||
|
objectResult.DeclaredType = apiResponse.GetType();
|
||||||
}
|
}
|
||||||
//如果是200 是IResponseOutput 记录下日志
|
else
|
||||||
else if (statusCode == 200 && (objectResult.Value is IResponseOutput))
|
|
||||||
{
|
{
|
||||||
var result = objectResult.Value as IResponseOutput;
|
var apiResponse = ResponseOutput.Ok(objectResult.Value);
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(result.LocalizedInfo))
|
|
||||||
{
|
|
||||||
//统一在这里记录国际化的日志信息
|
|
||||||
_logger.LogWarning($"{result.LocalizedInfo}");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (statusCode != 200 && !(objectResult.Value is IResponseOutput))
|
|
||||||
{
|
|
||||||
//---程序错误,请联系开发人员。
|
|
||||||
var apiResponse = ResponseOutput.NotOk(StaticData.International("UnifiedAPI_ProgramError"));
|
|
||||||
|
|
||||||
objectResult.Value = apiResponse;
|
objectResult.Value = apiResponse;
|
||||||
objectResult.DeclaredType = apiResponse.GetType();
|
objectResult.DeclaredType = apiResponse.GetType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
//如果是200 是IResponseOutput 记录下日志
|
||||||
await next.Invoke();
|
else if (statusCode == 200 && (objectResult.Value is IResponseOutput))
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsTupleType(Type type, bool checkBaseTypes = false)
|
|
||||||
{
|
|
||||||
if (type == null)
|
|
||||||
throw new ArgumentNullException(nameof(type));
|
|
||||||
|
|
||||||
if (type == typeof(Tuple))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
while (type != null)
|
|
||||||
{
|
{
|
||||||
if (type.IsGenericType)
|
var result = objectResult.Value as IResponseOutput;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(result.LocalizedInfo))
|
||||||
{
|
{
|
||||||
var genType = type.GetGenericTypeDefinition();
|
//统一在这里记录国际化的日志信息
|
||||||
if (genType == typeof(Tuple<>)
|
_logger.LogWarning($"{result.LocalizedInfo}");
|
||||||
|| genType == typeof(Tuple<,>)
|
|
||||||
|| genType == typeof(Tuple<,>))
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!checkBaseTypes)
|
|
||||||
break;
|
|
||||||
|
|
||||||
type = type.BaseType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
else if (statusCode != 200 && !(objectResult.Value is IResponseOutput))
|
||||||
|
{
|
||||||
|
//---程序错误,请联系开发人员。
|
||||||
|
var apiResponse = ResponseOutput.NotOk(StaticData.International("UnifiedAPI_ProgramError"));
|
||||||
|
|
||||||
|
objectResult.Value = apiResponse;
|
||||||
|
objectResult.DeclaredType = apiResponse.GetType();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await next.Invoke();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsTupleType(Type type, bool checkBaseTypes = false)
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
throw new ArgumentNullException(nameof(type));
|
||||||
|
|
||||||
|
if (type == typeof(Tuple))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
while (type != null)
|
||||||
|
{
|
||||||
|
if (type.IsGenericType)
|
||||||
|
{
|
||||||
|
var genType = type.GetGenericTypeDefinition();
|
||||||
|
if (genType == typeof(Tuple<>)
|
||||||
|
|| genType == typeof(Tuple<,>)
|
||||||
|
|| genType == typeof(Tuple<,>))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!checkBaseTypes)
|
||||||
|
break;
|
||||||
|
|
||||||
|
type = type.BaseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,164 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
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,9 +1,4 @@
|
|||||||
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
|
||||||
{
|
{
|
||||||
@@ -19,9 +14,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;
|
||||||
|
|
||||||
@@ -33,7 +28,7 @@ namespace IRaCIS.Core.Application.Helper
|
|||||||
}
|
}
|
||||||
|
|
||||||
//针对不同的标准 翻译的字典不一样
|
//针对不同的标准 翻译的字典不一样
|
||||||
public DictionaryTranslateAttribute(string dicParentCode, CriterionType criterionType )
|
public DictionaryTranslateAttribute(string dicParentCode, CriterionType criterionType)
|
||||||
{
|
{
|
||||||
DicParentCode = dicParentCode;
|
DicParentCode = dicParentCode;
|
||||||
|
|
||||||
@@ -42,7 +37,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,75 +1,69 @@
|
|||||||
using IRaCIS.Core.Domain.Models;
|
namespace IRaCIS.Core.Application.Helper;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Helper
|
|
||||||
|
public static class CacheKeys
|
||||||
{
|
{
|
||||||
|
//项目缓存
|
||||||
|
public static string Trial(string trialIdStr) => $"TrialId:{trialIdStr}";
|
||||||
|
|
||||||
public static class CacheKeys
|
//检查编号递增锁
|
||||||
|
public static string TrialStudyMaxCode(Guid trialId) => $"TrialStudyMaxCode:{trialId}";
|
||||||
|
|
||||||
|
public static string TrialStudyUidUploading(Guid trialId, string studyUid) => $"TrialStudyUid:{trialId}_{studyUid}";
|
||||||
|
//CRC上传影像提交锁key
|
||||||
|
public static string TrialStudyUidDBLock(Guid trialId, string studyUid) => $"TrialStudyUidDBLock:{trialId}_{studyUid}";
|
||||||
|
|
||||||
|
public static string TrialTaskStudyUidUploading(Guid trialId, Guid visiTaskId, string studyUid) => $"TrialStudyUid:{trialId}_{visiTaskId}_{studyUid}";
|
||||||
|
//影像后处理上传提交锁key
|
||||||
|
public static string TrialTaskStudyUidDBLock(Guid trialId, Guid visiTaskId, string studyUid) => $"TrialTaskStudyUidDBLock:{trialId}_{visiTaskId}_{studyUid}";
|
||||||
|
//系统匿名化
|
||||||
|
public static string SystemAnonymization => $"SystemAnonymization";
|
||||||
|
//前端国际化
|
||||||
|
public static string FrontInternational => $"FrontInternationalList";
|
||||||
|
|
||||||
|
//登录挤账号
|
||||||
|
public static string UserToken(Guid userId) => $"UserToken:{userId}";
|
||||||
|
|
||||||
|
//超时没请求接口自动退出
|
||||||
|
public static string UserAutoLoginOut(Guid userId) => $"UserAutoLoginOut:{userId}";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 跳过阅片
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string SkipReadingCacheKey(Guid userId) => $"{userId}SkipReadingCache";
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 开始阅片时间
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string StartReadingTimeKey(Guid userId) => $"{userId}StartReadingTime";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 开始休息时间
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string StartRestTime(Guid userId) => $"{userId}StartRestTime";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CacheHelper
|
||||||
|
{
|
||||||
|
public static async Task<string?> GetTrialStatusAsync(Guid trialId, IRepository<Trial> _trialRepository)
|
||||||
{
|
{
|
||||||
public static string Trial(string trialIdStr) => $"TrialId:{trialIdStr}";
|
var statusStr = await _trialRepository.Where(t => t.Id == trialId, ignoreQueryFilters: true).Select(t => t.TrialStatusStr).FirstOrDefaultAsync();
|
||||||
|
|
||||||
public static string TrialStudyMaxCode(Guid trialId) => $"TrialStudyMaxCode:{trialId}";
|
|
||||||
|
|
||||||
public static string TrialStudyUidUploading(Guid trialId, string studyUid) => $"TrialStudyUid:{trialId}_{studyUid}";
|
|
||||||
|
|
||||||
public static string TrialStudyUidDBLock(Guid trialId, string studyUid) => $"TrialStudyUidDBLock:{trialId}_{studyUid}";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static string SystemAnonymization => $"SystemAnonymization";
|
|
||||||
|
|
||||||
public static string FrontInternational => $"FrontInternationalList";
|
|
||||||
|
|
||||||
//登录挤账号
|
|
||||||
public static string UserToken(Guid userId) => $"UserToken:{userId}";
|
|
||||||
|
|
||||||
//超时没请求接口自动退出
|
|
||||||
public static string UserAutoLoginOut(Guid userId) => $"UserAutoLoginOut:{userId}";
|
|
||||||
|
|
||||||
// 你可以为其他实体和模块定义更多的键
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 跳过阅片
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="userId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static string SkipReadingCacheKey(Guid userId) => $"{userId}SkipReadingCache";
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 开始阅片时间
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="userId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static string StartReadingTimeKey(Guid userId) => $"{userId}StartReadingTime";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 开始休息时间
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="userId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static string StartRestTime(Guid userId) => $"{userId}StartRestTime";
|
|
||||||
|
|
||||||
|
return statusStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class CacheHelper
|
public static async Task<List<SystemAnonymization>> GetSystemAnonymizationListAsync(IRepository<SystemAnonymization> _systemAnonymizationRepository)
|
||||||
{
|
{
|
||||||
public static async Task<string?> GetTrialStatusAsync(Guid trialId, IRepository<Trial> _trialRepository)
|
var list = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
|
||||||
{
|
|
||||||
var statusStr = await _trialRepository.Where(t => t.Id == trialId, ignoreQueryFilters: true).Select(t => t.TrialStatusStr).FirstOrDefaultAsync();
|
|
||||||
|
|
||||||
return statusStr;
|
return list;
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<List<SystemAnonymization>> GetSystemAnonymizationListAsync(IRepository<SystemAnonymization> _systemAnonymizationRepository)
|
|
||||||
{
|
|
||||||
var list = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
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,29 +1,37 @@
|
|||||||
using DocumentFormat.OpenXml.Drawing.Diagrams;
|
using IRaCIS.Application.Contracts;
|
||||||
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.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.ComponentModel;
|
|
||||||
using System.Globalization;
|
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;
|
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
||||||
@@ -68,7 +76,7 @@ public static class ExcelExportHelper
|
|||||||
{
|
{
|
||||||
if (DateTime.TryParse(itemValuePair.Value?.ToString(), out DateTime result))
|
if (DateTime.TryParse(itemValuePair.Value?.ToString(), out DateTime result))
|
||||||
{
|
{
|
||||||
itemDic[itemValuePair.Key] = ExportExcelConverterDate.DateTimeInternationalToString(result );
|
itemDic[itemValuePair.Key] = ExportExcelConverterDate.DateTimeInternationalToString(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,6 +356,85 @@ public static class ExcelExportHelper
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <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,39 +1,33 @@
|
|||||||
using System;
|
using System.Diagnostics;
|
||||||
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 进程
|
||||||
static public void ConvertWordToPdf(string inputWordFilePath, string outputPdfDir)
|
using (Process process = new Process())
|
||||||
{
|
{
|
||||||
// 设置 libreoffice 命令行参数
|
process.StartInfo.FileName = "libreoffice";
|
||||||
string arguments = $"--headless --invisible --convert-to pdf \"{inputWordFilePath}\" --outdir \"{outputPdfDir}\"";
|
process.StartInfo.Arguments = arguments;
|
||||||
|
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
||||||
|
process.StartInfo.RedirectStandardOutput = true;
|
||||||
|
process.StartInfo.RedirectStandardError = true;
|
||||||
|
process.StartInfo.UseShellExecute = false;
|
||||||
|
process.StartInfo.CreateNoWindow = true;
|
||||||
|
|
||||||
// 启动 libreoffice 进程
|
process.Start();
|
||||||
using (Process process = new Process())
|
|
||||||
{
|
|
||||||
process.StartInfo.FileName = "libreoffice";
|
|
||||||
process.StartInfo.Arguments = arguments;
|
|
||||||
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
|
||||||
process.StartInfo.RedirectStandardOutput = true;
|
|
||||||
process.StartInfo.RedirectStandardError = true;
|
|
||||||
process.StartInfo.UseShellExecute = false;
|
|
||||||
process.StartInfo.CreateNoWindow = true;
|
|
||||||
|
|
||||||
process.Start();
|
// 等待进程结束
|
||||||
|
process.WaitForExit();
|
||||||
// 等待进程结束
|
|
||||||
process.WaitForExit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,7 @@
|
|||||||
|
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;
|
||||||
|
|
||||||
@@ -16,7 +11,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)
|
||||||
{
|
{
|
||||||
|
|
||||||
//带目录层级,需要后端处理前端的路径
|
//带目录层级,需要后端处理前端的路径
|
||||||
@@ -41,14 +36,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);
|
||||||
@@ -57,7 +52,7 @@ public static class FileStoreHelper
|
|||||||
//API vue 部署目录
|
//API vue 部署目录
|
||||||
public static string GetIRaCISRootPath(IWebHostEnvironment _hostEnvironment)
|
public static string GetIRaCISRootPath(IWebHostEnvironment _hostEnvironment)
|
||||||
{
|
{
|
||||||
string parentDirectory = Path.GetFullPath(Path.Combine(_hostEnvironment.ContentRootPath, ".."));
|
string parentDirectory = Path.GetFullPath(Path.Combine(_hostEnvironment.ContentRootPath, ".."));
|
||||||
|
|
||||||
return parentDirectory;
|
return parentDirectory;
|
||||||
|
|
||||||
@@ -136,10 +131,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 != StaticData.CultureInfo.zh_CN;
|
||||||
if (doc == null)
|
if (doc == null)
|
||||||
{
|
{
|
||||||
//---数据库没有找到对应的数据模板文件,请联系系统运维人员。
|
//---数据库没有找到对应的数据模板文件,请联系系统运维人员。
|
||||||
throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileNotFound"));
|
throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileNotFound"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,11 +142,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('/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -202,7 +197,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);
|
||||||
|
|
||||||
@@ -221,19 +216,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);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -246,7 +241,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}";
|
||||||
|
|
||||||
@@ -260,7 +255,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();
|
||||||
|
|
||||||
@@ -274,7 +269,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
//默认存储的路径
|
//默认存储的路径
|
||||||
@@ -318,7 +313,7 @@ public static class FileStoreHelper
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,5 @@
|
|||||||
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
|
||||||
{
|
{
|
||||||
@@ -65,7 +55,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)
|
||||||
@@ -88,5 +78,5 @@ namespace IRaCIS.Core.Application.Helper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,111 +1,105 @@
|
|||||||
using RestSharp;
|
using RestSharp;
|
||||||
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;
|
||||||
|
|
||||||
|
|
||||||
|
#region 对接模型
|
||||||
|
public class HolidayCalendar
|
||||||
{
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
#region 对接模型
|
public string Version { get; set; }
|
||||||
public class HolidayCalendar
|
public string Generated { get; set; }
|
||||||
{
|
public string Timezone { get; set; }
|
||||||
public string Name { get; set; }
|
public string Author { get; set; }
|
||||||
public string Version { get; set; }
|
public string URL { get; set; }
|
||||||
public string Generated { get; set; }
|
public Dictionary<string, List<HolidayYear>> Years { get; set; }
|
||||||
public string Timezone { get; set; }
|
}
|
||||||
public string Author { get; set; }
|
|
||||||
public string URL { get; set; }
|
public class HolidayYear
|
||||||
public Dictionary<string, List<HolidayYear>> Years { get; set; }
|
{
|
||||||
}
|
public string Name { get; set; }
|
||||||
|
public DateTime StartDate { get; set; }
|
||||||
public class HolidayYear
|
public DateTime EndDate { get; set; }
|
||||||
{
|
public int Duration { get; set; }
|
||||||
public string Name { get; set; }
|
public List<DateTime> CompDays { get; set; }
|
||||||
public DateTime StartDate { get; set; }
|
public string URL { get; set; }
|
||||||
public DateTime EndDate { get; set; }
|
public string Memo { get; set; }
|
||||||
public int Duration { get; set; }
|
}
|
||||||
public List<DateTime> CompDays { get; set; }
|
#endregion
|
||||||
public string URL { get; set; }
|
|
||||||
public string Memo { get; set; }
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
public class HolidayHelper
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// github 链接:https://github.com/lanceliao/china-holiday-calender?tab=readme-ov-file
|
||||||
public class HolidayHelper
|
/// 接口请求参考文档:https://www.koudingke.cn/docs/zh-Hans/net-lib-docs/latest/RestSharp/Usage/Usage
|
||||||
{
|
/// </summary>
|
||||||
/// <summary>
|
private static RestClient _client => new RestClient("https://www.shuyz.com/githubfiles/china-holiday-calender/master/holidayAPI.json");
|
||||||
/// github 链接:https://github.com/lanceliao/china-holiday-calender?tab=readme-ov-file
|
|
||||||
/// 接口请求参考文档:https://www.koudingke.cn/docs/zh-Hans/net-lib-docs/latest/RestSharp/Usage/Usage
|
private static HolidayCalendar _holidayCalendar { get; set; }
|
||||||
/// </summary>
|
|
||||||
private static RestClient _client => new RestClient("https://www.shuyz.com/githubfiles/china-holiday-calender/master/holidayAPI.json");
|
|
||||||
|
private static List<DateTime> _holidays = new List<DateTime>();
|
||||||
private static HolidayCalendar _holidayCalendar { get; set; }
|
private static List<DateTime> _compensatedWorkdays = new List<DateTime>();
|
||||||
|
|
||||||
|
static HolidayHelper()
|
||||||
private static List<DateTime> _holidays = new List<DateTime>();
|
{
|
||||||
private static List<DateTime> _compensatedWorkdays = new List<DateTime>();
|
_holidayCalendar = _client.Get<HolidayCalendar>(new RestRequest()) ?? new HolidayCalendar();
|
||||||
|
|
||||||
static HolidayHelper()
|
foreach (var year in _holidayCalendar.Years.Values.SelectMany(x => x))
|
||||||
{
|
{
|
||||||
_holidayCalendar = _client.Get<HolidayCalendar>(new RestRequest()) ?? new HolidayCalendar();
|
// 添加节假日到假日集合
|
||||||
|
for (DateTime date = year.StartDate; date <= year.EndDate; date = date.AddDays(1))
|
||||||
foreach (var year in _holidayCalendar.Years.Values.SelectMany(x => x))
|
{
|
||||||
{
|
_holidays.Add(date);
|
||||||
// 添加节假日到假日集合
|
}
|
||||||
for (DateTime date = year.StartDate; date <= year.EndDate; date = date.AddDays(1))
|
|
||||||
{
|
// 添加补班日到补班日集合
|
||||||
_holidays.Add(date);
|
foreach (var compDay in year.CompDays)
|
||||||
}
|
{
|
||||||
|
_compensatedWorkdays.Add(compDay);
|
||||||
// 添加补班日到补班日集合
|
}
|
||||||
foreach (var compDay in year.CompDays)
|
}
|
||||||
{
|
|
||||||
_compensatedWorkdays.Add(compDay);
|
}
|
||||||
}
|
|
||||||
}
|
public static TimeSpan GetChinaWorkTimeSpan(DateTime startDate, DateTime endDate)
|
||||||
|
{
|
||||||
}
|
if (startDate > endDate)
|
||||||
|
{
|
||||||
public static TimeSpan GetChinaWorkTimeSpan(DateTime startDate, DateTime endDate)
|
throw new ArgumentException("结束日期必须大于或等于开始日期");
|
||||||
{
|
}
|
||||||
if (startDate > endDate)
|
|
||||||
{
|
var diffTimeSpan = endDate - startDate;
|
||||||
throw new ArgumentException("结束日期必须大于或等于开始日期");
|
|
||||||
}
|
// 初始化工作日数为0
|
||||||
|
int workdays = 0;
|
||||||
var diffTimeSpan = endDate - startDate;
|
|
||||||
|
// 找出在给定日期范围内的假期和补班日
|
||||||
// 初始化工作日数为0
|
var filteredHolidays = _holidays.Where(d => d >= startDate && d <= endDate).ToList();
|
||||||
int workdays = 0;
|
var filteredCompensatedWorkdays = _compensatedWorkdays.Where(d => d >= startDate && d <= endDate).ToList();
|
||||||
|
|
||||||
// 找出在给定日期范围内的假期和补班日
|
// 遍历日期范围,计算工作日 注意 这里是小于
|
||||||
var filteredHolidays = _holidays.Where(d => d >= startDate && d <= endDate).ToList();
|
for (DateTime date = startDate.Date; date < endDate.Date; date = date.AddDays(1))
|
||||||
var filteredCompensatedWorkdays = _compensatedWorkdays.Where(d => d >= startDate && d <= endDate).ToList();
|
{
|
||||||
|
// 判断是否为工作日
|
||||||
// 遍历日期范围,计算工作日 注意 这里是小于
|
bool isWeekend = date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday;
|
||||||
for (DateTime date = startDate.Date; date < endDate.Date; date = date.AddDays(1))
|
bool isHoliday = filteredHolidays.Contains(date);
|
||||||
{
|
bool isCompensatedWorkday = filteredCompensatedWorkdays.Contains(date);
|
||||||
// 判断是否为工作日
|
|
||||||
bool isWeekend = date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday;
|
// 如果是补班日,或是平日(非假期,非周末),则算作工作日
|
||||||
bool isHoliday = filteredHolidays.Contains(date);
|
if (isCompensatedWorkday || (!isWeekend && !isHoliday))
|
||||||
bool isCompensatedWorkday = filteredCompensatedWorkdays.Contains(date);
|
{
|
||||||
|
workdays++;
|
||||||
// 如果是补班日,或是平日(非假期,非周末),则算作工作日
|
}
|
||||||
if (isCompensatedWorkday || (!isWeekend && !isHoliday))
|
}
|
||||||
{
|
|
||||||
workdays++;
|
return new TimeSpan(workdays, diffTimeSpan.Hours, diffTimeSpan.Minutes, diffTimeSpan.Seconds);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
}
|
||||||
return new TimeSpan(workdays, diffTimeSpan.Hours, diffTimeSpan.Minutes, diffTimeSpan.Seconds);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
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,10 +1,8 @@
|
|||||||
|
|
||||||
using FellowOakDicom.Imaging;
|
using FellowOakDicom.Imaging;
|
||||||
using SixLabors.ImageSharp.Formats.Jpeg;
|
|
||||||
using SixLabors.ImageSharp;
|
using SixLabors.ImageSharp;
|
||||||
|
using SixLabors.ImageSharp.Formats.Jpeg;
|
||||||
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,211 +4,204 @@ 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 class InternationalizationHelper
|
public static string JsonFileFolder = Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources);
|
||||||
|
|
||||||
|
public static FileSystemWatcher FileSystemWatcher_US { get; set; }
|
||||||
|
public static FileSystemWatcher FileSystemWatcher_CN { get; set; }
|
||||||
|
|
||||||
|
private static void VerifyFolder()
|
||||||
{
|
{
|
||||||
public static string JsonFileFolder = Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources);
|
if (!Directory.Exists(JsonFileFolder) ||
|
||||||
|
!Directory.GetFiles(JsonFileFolder).Any(filePath => Path.GetExtension(filePath).Equals(".json", StringComparison.OrdinalIgnoreCase)))
|
||||||
public static FileSystemWatcher FileSystemWatcher_US { get; set; }
|
|
||||||
public static FileSystemWatcher FileSystemWatcher_CN { get; set; }
|
|
||||||
|
|
||||||
private static void VerifyFolder()
|
|
||||||
{
|
{
|
||||||
if (!Directory.Exists(JsonFileFolder) ||
|
throw new BusinessValidationFailedException("国际化Json文件目录有误");
|
||||||
!Directory.GetFiles(JsonFileFolder).Any(filePath => Path.GetExtension(filePath).Equals(".json", StringComparison.OrdinalIgnoreCase)))
|
|
||||||
{
|
|
||||||
throw new BusinessValidationFailedException("国际化Json文件目录有误");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static async Task BatchAddJsonKeyValueAsync(List<BatchAddInternationalizationDto> batchAddDtos)
|
public static async Task BatchAddJsonKeyValueAsync(List<BatchAddInternationalizationDto> batchAddDtos)
|
||||||
|
{
|
||||||
|
VerifyFolder();
|
||||||
|
|
||||||
|
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
|
||||||
|
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
|
||||||
|
|
||||||
|
|
||||||
|
//更新json 文件 同时更新内存缓存的数据
|
||||||
|
foreach (var filePath in new string[] { usJsonPath, cnJsonPath })
|
||||||
{
|
{
|
||||||
VerifyFolder();
|
var json = await File.ReadAllTextAsync(filePath);
|
||||||
|
|
||||||
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
|
JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
|
||||||
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
|
|
||||||
|
|
||||||
|
// 添加或更新指定的键值对
|
||||||
|
|
||||||
//更新json 文件 同时更新内存缓存的数据
|
if (filePath.Contains(StaticData.En_US_Json))
|
||||||
foreach (var filePath in new string[] { usJsonPath, cnJsonPath })
|
|
||||||
{
|
{
|
||||||
var json = await File.ReadAllTextAsync(filePath);
|
foreach (var item in batchAddDtos)
|
||||||
|
|
||||||
JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
|
|
||||||
|
|
||||||
// 添加或更新指定的键值对
|
|
||||||
|
|
||||||
if (filePath.Contains(StaticData.En_US_Json))
|
|
||||||
{
|
{
|
||||||
foreach (var item in batchAddDtos)
|
jsonObject[item.Code] = item.Value;
|
||||||
{
|
|
||||||
jsonObject[item.Code] = item.Value;
|
|
||||||
|
|
||||||
StaticData.En_US_Dic[item.Code] = item.Value;
|
StaticData.En_US_Dic[item.Code] = item.Value;
|
||||||
|
|
||||||
//日志记录该信息方便自己人看, 返回给客户的是配置的
|
|
||||||
StaticData.Log_Locoalize_Dic[item.Code] = item.Description;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (var item in batchAddDtos)
|
|
||||||
{
|
|
||||||
jsonObject[item.Code] = item.Value;
|
|
||||||
|
|
||||||
StaticData.Zh_CN_Dic[item.Code] = item.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
await File.WriteAllTextAsync(filePath, jsonObject.ToString());
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task AddOrUpdateJsonKeyValueAsync(string key, string value, string valueCN,string description)
|
|
||||||
{
|
|
||||||
|
|
||||||
VerifyFolder();
|
|
||||||
|
|
||||||
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
|
|
||||||
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
|
|
||||||
|
|
||||||
|
|
||||||
//更新json 文件 同时更新内存缓存的数据
|
|
||||||
foreach (var filePath in new string[] { usJsonPath, cnJsonPath })
|
|
||||||
{
|
|
||||||
var json = await File.ReadAllTextAsync(filePath);
|
|
||||||
|
|
||||||
JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
|
|
||||||
|
|
||||||
// 添加或更新指定的键值对
|
|
||||||
|
|
||||||
if (filePath.Contains(StaticData.En_US_Json))
|
|
||||||
{
|
|
||||||
jsonObject[key] = value;
|
|
||||||
|
|
||||||
StaticData.En_US_Dic[key] = value;
|
|
||||||
|
|
||||||
//日志记录该信息方便自己人看, 返回给客户的是配置的
|
//日志记录该信息方便自己人看, 返回给客户的是配置的
|
||||||
StaticData.Log_Locoalize_Dic[key] = description;
|
StaticData.Log_Locoalize_Dic[item.Code] = item.Description;
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var item in batchAddDtos)
|
||||||
{
|
{
|
||||||
jsonObject[key] = valueCN;
|
jsonObject[item.Code] = item.Value;
|
||||||
|
|
||||||
StaticData.Zh_CN_Dic[key] = valueCN;
|
StaticData.Zh_CN_Dic[item.Code] = item.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
await File.WriteAllTextAsync(filePath, jsonObject.ToString());
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
await File.WriteAllTextAsync(filePath, jsonObject.ToString());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task AddOrUpdateJsonKeyValueAsync(string key, string value, string valueCN, string description)
|
||||||
|
{
|
||||||
|
|
||||||
|
VerifyFolder();
|
||||||
|
|
||||||
|
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
|
||||||
|
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
|
||||||
|
|
||||||
|
|
||||||
public static async Task InitInternationlizationDataAndWatchJsonFileAsync(IRepository<Internationalization> _internationalizationRepository)
|
//更新json 文件 同时更新内存缓存的数据
|
||||||
|
foreach (var filePath in new string[] { usJsonPath, cnJsonPath })
|
||||||
{
|
{
|
||||||
//查询数据库的数据
|
var json = await File.ReadAllTextAsync(filePath);
|
||||||
var toJsonList = await _internationalizationRepository.Where(t => t.InternationalizationType == 1).Select(t => new
|
|
||||||
|
JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
|
||||||
|
|
||||||
|
// 添加或更新指定的键值对
|
||||||
|
|
||||||
|
if (filePath.Contains(StaticData.En_US_Json))
|
||||||
{
|
{
|
||||||
t.Code,
|
jsonObject[key] = value;
|
||||||
t.Value,
|
|
||||||
t.ValueCN,
|
|
||||||
t.Description
|
|
||||||
}).ToListAsync();
|
|
||||||
|
|
||||||
//组织成json 文件
|
StaticData.En_US_Dic[key] = value;
|
||||||
|
|
||||||
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
|
|
||||||
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
|
|
||||||
|
|
||||||
|
|
||||||
//本地静态文件国际化需要
|
|
||||||
foreach (var tojsonItem in toJsonList)
|
|
||||||
{
|
|
||||||
StaticData.En_US_Dic[tojsonItem.Code] = tojsonItem.Value;
|
|
||||||
StaticData.Zh_CN_Dic[tojsonItem.Code] = tojsonItem.ValueCN;
|
|
||||||
|
|
||||||
//日志记录该信息方便自己人看, 返回给客户的是配置的
|
//日志记录该信息方便自己人看, 返回给客户的是配置的
|
||||||
StaticData.Log_Locoalize_Dic[tojsonItem.Code] = tojsonItem.Description;
|
StaticData.Log_Locoalize_Dic[key] = description;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
File.WriteAllText(usJsonPath, JsonConvert.SerializeObject(StaticData.En_US_Dic));
|
|
||||||
File.WriteAllText(cnJsonPath, JsonConvert.SerializeObject(StaticData.Zh_CN_Dic));
|
|
||||||
|
|
||||||
|
|
||||||
//监测Json文件变更 实时刷新数据
|
|
||||||
|
|
||||||
if (!File.Exists(usJsonPath) || !File.Exists(cnJsonPath))
|
|
||||||
{
|
{
|
||||||
throw new BusinessValidationFailedException(StaticData.International("IRaCISCHangfireJob_FileNotFound"));
|
jsonObject[key] = valueCN;
|
||||||
|
|
||||||
|
StaticData.Zh_CN_Dic[key] = valueCN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// //监测Json文件变更 实时刷新数据
|
await File.WriteAllTextAsync(filePath, jsonObject.ToString());
|
||||||
|
|
||||||
|
|
||||||
FileSystemWatcher_US = new FileSystemWatcher
|
|
||||||
{
|
|
||||||
Path = Path.GetDirectoryName(usJsonPath)!,
|
|
||||||
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
|
|
||||||
Filter = Path.GetFileName(usJsonPath),
|
|
||||||
EnableRaisingEvents = true,
|
|
||||||
|
|
||||||
};
|
|
||||||
// 添加文件更改事件的处理程序
|
|
||||||
FileSystemWatcher_US.Changed += (sender, e) => LoadJsonFile(StaticData.Folder.Resources + "\\" + StaticData.En_US_Json);
|
|
||||||
|
|
||||||
|
|
||||||
FileSystemWatcher_CN = new FileSystemWatcher
|
|
||||||
{
|
|
||||||
Path = Path.GetDirectoryName(cnJsonPath)!,
|
|
||||||
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
|
|
||||||
Filter = Path.GetFileName(cnJsonPath),
|
|
||||||
EnableRaisingEvents = true,
|
|
||||||
|
|
||||||
};
|
|
||||||
FileSystemWatcher_CN.Changed += (sender, e) => LoadJsonFile(StaticData.Folder.Resources + "\\" + StaticData.Zh_CN_Json);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static void LoadJsonFile(string filePath)
|
|
||||||
{
|
|
||||||
Console.WriteLine("刷新json内存数据");
|
|
||||||
IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile(filePath, false, false);
|
|
||||||
|
|
||||||
IConfigurationRoot enConfiguration = builder.Build();
|
|
||||||
|
|
||||||
foreach (IConfigurationSection section in enConfiguration.GetChildren())
|
|
||||||
{
|
|
||||||
if (filePath.Contains(StaticData.En_US_Json))
|
|
||||||
{
|
|
||||||
StaticData.En_US_Dic[section.Key] = section.Value;
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
StaticData.Zh_CN_Dic[section.Key] = section.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static async Task InitInternationlizationDataAndWatchJsonFileAsync(IRepository<Internationalization> _internationalizationRepository)
|
||||||
|
{
|
||||||
|
//查询数据库的数据
|
||||||
|
var toJsonList = await _internationalizationRepository.Where(t => t.InternationalizationType == 1).Select(t => new
|
||||||
|
{
|
||||||
|
t.Code,
|
||||||
|
t.Value,
|
||||||
|
t.ValueCN,
|
||||||
|
t.Description
|
||||||
|
}).ToListAsync();
|
||||||
|
|
||||||
|
//组织成json 文件
|
||||||
|
|
||||||
|
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
|
||||||
|
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
|
||||||
|
|
||||||
|
|
||||||
|
//本地静态文件国际化需要
|
||||||
|
foreach (var tojsonItem in toJsonList)
|
||||||
|
{
|
||||||
|
StaticData.En_US_Dic[tojsonItem.Code] = tojsonItem.Value;
|
||||||
|
StaticData.Zh_CN_Dic[tojsonItem.Code] = tojsonItem.ValueCN;
|
||||||
|
|
||||||
|
//日志记录该信息方便自己人看, 返回给客户的是配置的
|
||||||
|
StaticData.Log_Locoalize_Dic[tojsonItem.Code] = tojsonItem.Description;
|
||||||
|
}
|
||||||
|
|
||||||
|
File.WriteAllText(usJsonPath, JsonConvert.SerializeObject(StaticData.En_US_Dic));
|
||||||
|
File.WriteAllText(cnJsonPath, JsonConvert.SerializeObject(StaticData.Zh_CN_Dic));
|
||||||
|
|
||||||
|
|
||||||
|
//监测Json文件变更 实时刷新数据
|
||||||
|
|
||||||
|
if (!File.Exists(usJsonPath) || !File.Exists(cnJsonPath))
|
||||||
|
{
|
||||||
|
throw new BusinessValidationFailedException(StaticData.International("IRaCISCHangfireJob_FileNotFound"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// //监测Json文件变更 实时刷新数据
|
||||||
|
|
||||||
|
|
||||||
|
FileSystemWatcher_US = new FileSystemWatcher
|
||||||
|
{
|
||||||
|
Path = Path.GetDirectoryName(usJsonPath)!,
|
||||||
|
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
|
||||||
|
Filter = Path.GetFileName(usJsonPath),
|
||||||
|
EnableRaisingEvents = true,
|
||||||
|
|
||||||
|
};
|
||||||
|
// 添加文件更改事件的处理程序
|
||||||
|
FileSystemWatcher_US.Changed += (sender, e) => LoadJsonFile(StaticData.Folder.Resources + "\\" + StaticData.En_US_Json);
|
||||||
|
|
||||||
|
|
||||||
|
FileSystemWatcher_CN = new FileSystemWatcher
|
||||||
|
{
|
||||||
|
Path = Path.GetDirectoryName(cnJsonPath)!,
|
||||||
|
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
|
||||||
|
Filter = Path.GetFileName(cnJsonPath),
|
||||||
|
EnableRaisingEvents = true,
|
||||||
|
|
||||||
|
};
|
||||||
|
FileSystemWatcher_CN.Changed += (sender, e) => LoadJsonFile(StaticData.Folder.Resources + "\\" + StaticData.Zh_CN_Json);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static void LoadJsonFile(string filePath)
|
||||||
|
{
|
||||||
|
Console.WriteLine("刷新json内存数据");
|
||||||
|
IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile(filePath, false, false);
|
||||||
|
|
||||||
|
IConfigurationRoot enConfiguration = builder.Build();
|
||||||
|
|
||||||
|
foreach (IConfigurationSection section in enConfiguration.GetChildren())
|
||||||
|
{
|
||||||
|
if (filePath.Contains(StaticData.En_US_Json))
|
||||||
|
{
|
||||||
|
StaticData.En_US_Dic[section.Key] = section.Value;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StaticData.Zh_CN_Dic[section.Key] = section.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,97 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Org.BouncyCastle.Crypto;
|
|
||||||
using Org.BouncyCastle.Crypto.Encodings;
|
|
||||||
using Org.BouncyCastle.Crypto.Engines;
|
|
||||||
using Org.BouncyCastle.Crypto.Generators;
|
|
||||||
using Org.BouncyCastle.OpenSsl;
|
|
||||||
using Org.BouncyCastle.Security;
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Helper
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// https://www.cnblogs.com/NBDWDYS2214143926/p/13329231.html
|
|
||||||
/// </summary>
|
|
||||||
public class RSAHelper
|
|
||||||
{
|
|
||||||
|
|
||||||
public static AsymmetricCipherKeyPair GenerateRSAKeyPair(int keySize)
|
|
||||||
{
|
|
||||||
var keyGenerationParameters = new KeyGenerationParameters(new SecureRandom(), keySize);
|
|
||||||
var keyPairGenerator = new RsaKeyPairGenerator();
|
|
||||||
keyPairGenerator.Init(keyGenerationParameters);
|
|
||||||
return keyPairGenerator.GenerateKeyPair();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string ExportPublicKey(AsymmetricKeyParameter publicKey)
|
|
||||||
{
|
|
||||||
using (StringWriter sw = new StringWriter())
|
|
||||||
{
|
|
||||||
PemWriter pw = new PemWriter(sw);
|
|
||||||
pw.WriteObject(publicKey);
|
|
||||||
pw.Writer.Flush();
|
|
||||||
return sw.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string ExportPrivateKey(AsymmetricKeyParameter privateKey)
|
|
||||||
{
|
|
||||||
using (StringWriter sw = new StringWriter())
|
|
||||||
{
|
|
||||||
PemWriter pw = new PemWriter(sw);
|
|
||||||
pw.WriteObject(privateKey);
|
|
||||||
pw.Writer.Flush();
|
|
||||||
return sw.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// RSA解密
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="privateKey">私钥</param>
|
|
||||||
/// <param name="decryptstring">待解密的字符串(Base64)</param>
|
|
||||||
/// <returns>解密后的字符串</returns>
|
|
||||||
public static string Decrypt(string privateKey, string decryptstring)
|
|
||||||
{
|
|
||||||
using (TextReader reader = new StringReader(privateKey))
|
|
||||||
{
|
|
||||||
dynamic key = new PemReader(reader).ReadObject();
|
|
||||||
var rsaDecrypt = new Pkcs1Encoding(new RsaEngine());
|
|
||||||
if (key is AsymmetricKeyParameter)
|
|
||||||
{
|
|
||||||
key = (AsymmetricKeyParameter)key;
|
|
||||||
}
|
|
||||||
else if (key is AsymmetricCipherKeyPair)
|
|
||||||
{
|
|
||||||
key = ((AsymmetricCipherKeyPair)key).Private;
|
|
||||||
}
|
|
||||||
rsaDecrypt.Init(false, key); //这里加密是true;解密是false
|
|
||||||
|
|
||||||
byte[] entData = Convert.FromBase64String(decryptstring);
|
|
||||||
entData = rsaDecrypt.ProcessBlock(entData, 0, entData.Length);
|
|
||||||
return Encoding.UTF8.GetString(entData);
|
|
||||||
}
|
|
||||||
}/// <summary>
|
|
||||||
|
|
||||||
/// 加密
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="publicKey">公钥</param>
|
|
||||||
/// <param name="encryptstring">待加密的字符串</param>
|
|
||||||
/// <returns>加密后的Base64</returns>
|
|
||||||
public static string Encrypt(string publicKey, string encryptstring)
|
|
||||||
{
|
|
||||||
using (TextReader reader = new StringReader(publicKey))
|
|
||||||
{
|
|
||||||
AsymmetricKeyParameter key = new PemReader(reader).ReadObject() as AsymmetricKeyParameter;
|
|
||||||
Pkcs1Encoding pkcs1 = new Pkcs1Encoding(new RsaEngine());
|
|
||||||
pkcs1.Init(true, key);//加密是true;解密是false;
|
|
||||||
byte[] entData = Encoding.UTF8.GetBytes(encryptstring);
|
|
||||||
entData = pkcs1.ProcessBlock(entData, 0, entData.Length);
|
|
||||||
return Convert.ToBase64String(entData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,7 @@
|
|||||||
using DocumentFormat.OpenXml.Spreadsheet;
|
using IRaCIS.Core.Domain.Share;
|
||||||
using IRaCIS.Core.Domain.Share;
|
|
||||||
using MailKit;
|
using MailKit;
|
||||||
using MailKit.Security;
|
using MailKit.Security;
|
||||||
using MimeKit;
|
using MimeKit;
|
||||||
using NPOI.HPSF;
|
|
||||||
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Helper;
|
namespace IRaCIS.Core.Application.Helper;
|
||||||
@@ -44,7 +42,7 @@ public static class SendEmailHelper
|
|||||||
{
|
{
|
||||||
|
|
||||||
//---邮件发送失败,您进行的操作未能成功,请检查邮箱或联系维护人员
|
//---邮件发送失败,您进行的操作未能成功,请检查邮箱或联系维护人员
|
||||||
throw new Exception(StaticData.International("SendEmail_SendFail"),new Exception(ex.Message));
|
throw new Exception(StaticData.International("SendEmail_SendFail"), new Exception(ex.Message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -64,7 +62,7 @@ public static class SendEmailHelper
|
|||||||
await client.DisconnectAsync(true);
|
await client.DisconnectAsync(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,101 +1,95 @@
|
|||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
using NPOI.XWPF.UserModel;
|
using NPOI.XWPF.UserModel;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Xceed.Document.NET;
|
using Xceed.Document.NET;
|
||||||
using Xceed.Words.NET;
|
using Xceed.Words.NET;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Helper
|
namespace IRaCIS.Core.Application.Helper;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 利用DocX 库 处理word国际化模板
|
||||||
|
/// </summary>
|
||||||
|
public static class WordTempleteHelper
|
||||||
{
|
{
|
||||||
/// <summary>
|
public static void DocX_GetInternationalTempleteStream(string filePath, Stream memoryStream)
|
||||||
/// 利用DocX 库 处理word国际化模板
|
|
||||||
/// </summary>
|
|
||||||
public static class WordTempleteHelper
|
|
||||||
{
|
{
|
||||||
public static void DocX_GetInternationalTempleteStream(string filePath, Stream memoryStream)
|
|
||||||
|
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
||||||
|
|
||||||
|
using (DocX document = DocX.Load(filePath))
|
||||||
{
|
{
|
||||||
|
// 查找书签
|
||||||
|
var bookmarkEn_Start = document.Bookmarks.FirstOrDefault(b => b.Name == StaticData.CultureInfo.en_US_bookMark);
|
||||||
|
|
||||||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
if (bookmarkEn_Start != null)
|
||||||
|
|
||||||
using (DocX document = DocX.Load(filePath))
|
|
||||||
{
|
{
|
||||||
// 查找书签
|
// 获取书签的起始位置
|
||||||
var bookmarkEn_Start = document.Bookmarks.FirstOrDefault(b => b.Name == StaticData.CultureInfo.en_US_bookMark);
|
//int bookmarkCNStartPos = bookmarkCn_Start.Paragraph.StartIndex;
|
||||||
|
|
||||||
if (bookmarkEn_Start != null)
|
var bookmarkENStartPos = bookmarkEn_Start.Paragraph.StartIndex;
|
||||||
|
|
||||||
|
// 创建一个要删除段落的列表
|
||||||
|
List<Paragraph> paragraphsToRemove = new List<Paragraph>();
|
||||||
|
|
||||||
|
foreach (var item in document.Paragraphs)
|
||||||
{
|
{
|
||||||
// 获取书签的起始位置
|
//中文模板在前,英文在后,英文模板,就删除英文之前的,中文模板就删除英文之后的
|
||||||
//int bookmarkCNStartPos = bookmarkCn_Start.Paragraph.StartIndex;
|
|
||||||
|
|
||||||
var bookmarkENStartPos = bookmarkEn_Start.Paragraph.StartIndex;
|
if (isEn_US ? item.EndIndex < bookmarkENStartPos : item.StartIndex >= bookmarkENStartPos)
|
||||||
|
|
||||||
// 创建一个要删除段落的列表
|
|
||||||
List<Paragraph> paragraphsToRemove = new List<Paragraph>();
|
|
||||||
|
|
||||||
foreach (var item in document.Paragraphs)
|
|
||||||
{
|
{
|
||||||
//中文模板在前,英文在后,英文模板,就删除英文之前的,中文模板就删除英文之后的
|
paragraphsToRemove.Add(item);
|
||||||
|
|
||||||
if (isEn_US ? item.EndIndex < bookmarkENStartPos : item.StartIndex >= bookmarkENStartPos)
|
|
||||||
{
|
|
||||||
paragraphsToRemove.Add(item);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var paragraph in paragraphsToRemove)
|
|
||||||
{
|
|
||||||
document.RemoveParagraph(paragraph);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存修改
|
foreach (var paragraph in paragraphsToRemove)
|
||||||
document.SaveAs(memoryStream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static void Npoi_GetInternationalTempleteStream(string filePath, Stream memoryStream)
|
|
||||||
{
|
|
||||||
|
|
||||||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
|
||||||
|
|
||||||
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
|
|
||||||
{
|
|
||||||
XWPFDocument doc = new XWPFDocument(fs);
|
|
||||||
|
|
||||||
// 查找包含指定书签的段落及其索引
|
|
||||||
var bookmarkParagraph = doc.Paragraphs
|
|
||||||
.FirstOrDefault(p => p.GetCTP().GetBookmarkStartList().Any(b => b.name == StaticData.CultureInfo.en_US_bookMark));
|
|
||||||
|
|
||||||
if (bookmarkParagraph != null)
|
|
||||||
{
|
{
|
||||||
int bookmarkIndex = doc.Paragraphs.IndexOf(bookmarkParagraph);
|
document.RemoveParagraph(paragraph);
|
||||||
|
|
||||||
if (isEn_US)
|
|
||||||
{
|
|
||||||
// 从书签所在段落开始,删除之前的所有段落
|
|
||||||
for (int i = bookmarkIndex - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
doc.RemoveBodyElement(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 删除书签之后的所有段落
|
|
||||||
for (int i = doc.Paragraphs.Count - 1; i >= bookmarkIndex; i--)
|
|
||||||
{
|
|
||||||
doc.RemoveBodyElement(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
doc.Write(memoryStream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存修改
|
||||||
|
document.SaveAs(memoryStream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void Npoi_GetInternationalTempleteStream(string filePath, Stream memoryStream)
|
||||||
|
{
|
||||||
|
|
||||||
|
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
||||||
|
|
||||||
|
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
|
||||||
|
{
|
||||||
|
XWPFDocument doc = new XWPFDocument(fs);
|
||||||
|
|
||||||
|
// 查找包含指定书签的段落及其索引
|
||||||
|
var bookmarkParagraph = doc.Paragraphs
|
||||||
|
.FirstOrDefault(p => p.GetCTP().GetBookmarkStartList().Any(b => b.name == StaticData.CultureInfo.en_US_bookMark));
|
||||||
|
|
||||||
|
if (bookmarkParagraph != null)
|
||||||
|
{
|
||||||
|
int bookmarkIndex = doc.Paragraphs.IndexOf(bookmarkParagraph);
|
||||||
|
|
||||||
|
if (isEn_US)
|
||||||
|
{
|
||||||
|
// 从书签所在段落开始,删除之前的所有段落
|
||||||
|
for (int i = bookmarkIndex - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
doc.RemoveBodyElement(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 删除书签之后的所有段落
|
||||||
|
for (int i = doc.Paragraphs.Count - 1; i >= bookmarkIndex; i--)
|
||||||
|
{
|
||||||
|
doc.RemoveBodyElement(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
doc.Write(memoryStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,21 +19,6 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
|
|
||||||
<Using Include="IRaCIS.Core.Application;" />
|
|
||||||
<Using Include="AutoMapper.QueryableExtensions;" />
|
|
||||||
<Using Include="Microsoft.EntityFrameworkCore;" />
|
|
||||||
<Using Include="IRaCIS.Core.Domain.Models;" />
|
|
||||||
<Using Include="IRaCIS.Core.Infrastructure.Extention;" />
|
|
||||||
<Using Include="IRaCIS.Core.Infra.EFCore;" />
|
|
||||||
|
|
||||||
<!-- Global using -->
|
|
||||||
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Remove="WebAppConfig.cs" />
|
<Compile Remove="WebAppConfig.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
@@ -58,8 +43,10 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.1.4" />
|
||||||
|
<PackageReference Include="AWSSDK.SecurityToken" Version="3.7.400.16" />
|
||||||
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" />
|
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" />
|
||||||
<PackageReference Include="AWSSDK.S3" Version="3.7.402.4" />
|
<PackageReference Include="AWSSDK.S3" Version="3.7.402.7" />
|
||||||
<PackageReference Include="DocX" Version="3.0.1" />
|
<PackageReference Include="DocX" Version="3.0.1" />
|
||||||
<PackageReference Include="FreeSpire.Doc" Version="12.2.0" />
|
<PackageReference Include="FreeSpire.Doc" Version="12.2.0" />
|
||||||
<PackageReference Include="Hangfire.Core" Version="1.8.14" />
|
<PackageReference Include="Hangfire.Core" Version="1.8.14" />
|
||||||
@@ -71,8 +58,8 @@
|
|||||||
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.1.3" />
|
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.1.3" />
|
||||||
<PackageReference Include="fo-dicom.Codecs" Version="5.14.5" />
|
<PackageReference Include="fo-dicom.Codecs" Version="5.14.5" />
|
||||||
<PackageReference Include="IP2Region.Net" Version="2.0.2" />
|
<PackageReference Include="IP2Region.Net" Version="2.0.2" />
|
||||||
<PackageReference Include="MailKit" Version="4.2.0" />
|
<PackageReference Include="MailKit" Version="4.7.1.1" />
|
||||||
<PackageReference Include="MimeKit" Version="4.2.0" />
|
<PackageReference Include="MimeKit" Version="4.7.1" />
|
||||||
<PackageReference Include="MiniExcel" Version="1.34.1" />
|
<PackageReference Include="MiniExcel" Version="1.34.1" />
|
||||||
<PackageReference Include="Minio" Version="6.0.3" />
|
<PackageReference Include="Minio" Version="6.0.3" />
|
||||||
<PackageReference Include="MiniWord" Version="0.8.0" />
|
<PackageReference Include="MiniWord" Version="0.8.0" />
|
||||||
@@ -84,7 +71,6 @@
|
|||||||
<PackageReference Include="RestSharp" Version="112.0.0" />
|
<PackageReference Include="RestSharp" Version="112.0.0" />
|
||||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.5" />
|
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.5" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.2" />
|
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.2" />
|
||||||
<PackageReference Include="MassTransit.AspNetCore" Version="7.3.1" />
|
|
||||||
<PackageReference Include="ZiggyCreatures.FusionCache" Version="1.3.0" />
|
<PackageReference Include="ZiggyCreatures.FusionCache" Version="1.3.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
@@ -98,4 +84,8 @@
|
|||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Triggers\TempAbandon\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,5 @@
|
|||||||
using MiniExcelLibs.Attributes;
|
using MiniExcelLibs.Attributes;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.MassTransit.Command
|
namespace IRaCIS.Core.Application.MassTransit.Command
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
|
||||||
|
using AutoMapper;
|
||||||
|
using IP2Region.Net.Abstractions;
|
||||||
|
using IRaCIS.Core.Domain;
|
||||||
|
using IRaCIS.Core.Domain.Models;
|
||||||
|
using MassTransit;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.Application.MassTransit.Consumer;
|
||||||
|
|
||||||
|
|
||||||
|
//国家|区域|省份|城市|ISP 缺省的地域信息默认是0
|
||||||
|
//0|0|0|内网IP|内网IP
|
||||||
|
// 中国|0|湖北省|武汉市|电信
|
||||||
|
public class AddUserLogTriggerConsumer(ISearcher _searcher) : IConsumer<AddUserLogTriggerCommand>
|
||||||
|
{
|
||||||
|
public async Task Consume(ConsumeContext<AddUserLogTriggerCommand> context)
|
||||||
|
{
|
||||||
|
var userLog = context.Message.UserLog;
|
||||||
|
|
||||||
|
var ipinfo = _searcher.Search(userLog.IP);
|
||||||
|
|
||||||
|
userLog.IPRegion = string.Join('|', ipinfo.Split('|').TakeLast(3));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,12 +5,7 @@ using IRaCIS.Core.Domain.Share;
|
|||||||
using MassTransit;
|
using MassTransit;
|
||||||
using Microsoft.Extensions.Localization;
|
using Microsoft.Extensions.Localization;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.MassTransit.Consumer
|
namespace IRaCIS.Core.Application.MassTransit.Consumer
|
||||||
{
|
{
|
||||||
@@ -286,7 +281,7 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer
|
|||||||
|
|
||||||
//await context.RespondAsync<ConsistenCheckResult>(new
|
//await context.RespondAsync<ConsistenCheckResult>(new
|
||||||
//{
|
//{
|
||||||
|
|
||||||
//});
|
//});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,101 @@
|
|||||||
|
|
||||||
|
|
||||||
|
using AutoMapper;
|
||||||
|
using IRaCIS.Core.Domain;
|
||||||
|
using MassTransit;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.Application.MassTransit.Consumer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 添加Subject 触发添加访视 不能代替 Trigger,稽查BatchId 不一致
|
||||||
|
/// 因为消费者这里的数据库上下文 和消息发送者上下文不是同一个,相当于两个独立的事务
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="_subjectVisitRepository"></param>
|
||||||
|
/// <param name="_visitStageRepository"></param>
|
||||||
|
/// <param name="_trialRepository"></param>
|
||||||
|
/// <param name="_mapper"></param>
|
||||||
|
public class AddSubjectTriggerConsumer(IRepository<SubjectVisit> _subjectVisitRepository,
|
||||||
|
|
||||||
|
IRepository<VisitStage> _visitStageRepository,
|
||||||
|
IRepository<Trial> _trialRepository,
|
||||||
|
IMapper _mapper) : IConsumer<AddSubjectTriggerCommand>
|
||||||
|
{
|
||||||
|
public async Task Consume(ConsumeContext<AddSubjectTriggerCommand> context)
|
||||||
|
{
|
||||||
|
var addSubjectEvent = context.Message;
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Console.WriteLine(_visitStageRepository._dbContext.GetHashCode());
|
||||||
|
|
||||||
|
Console.WriteLine("两个 DbContext 不是同一个实例");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//添加受试者的时候,获取访视计划列表,添加到受试者访视表。
|
||||||
|
var visitPlanList = await _visitStageRepository.Where(t => t.TrialId == addSubjectEvent.TrialId && t.IsConfirmed).ToListAsync();
|
||||||
|
|
||||||
|
var svList = _mapper.Map<List<SubjectVisit>>(visitPlanList);
|
||||||
|
|
||||||
|
var IsEnrollementQualificationConfirm = await _trialRepository.Where(t => t.Id == addSubjectEvent.TrialId).Select(u => u.IsEnrollementQualificationConfirm).FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
svList.ForEach(t =>
|
||||||
|
{
|
||||||
|
t.SubjectId = addSubjectEvent.SubjectId;
|
||||||
|
t.TrialId = addSubjectEvent.TrialId;
|
||||||
|
t.TrialSiteId = addSubjectEvent.TrialSiteId;
|
||||||
|
t.IsEnrollmentConfirm = t.IsBaseLine ? IsEnrollementQualificationConfirm : false;
|
||||||
|
t.Id = NewId.NextGuid();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
await _subjectVisitRepository.AddRangeAsync(svList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AddSubjectTriggerConsumer2(IRepository<SubjectVisit> _subjectVisitRepository,
|
||||||
|
|
||||||
|
IRepository<VisitStage> _visitStageRepository,
|
||||||
|
IRepository<Trial> _trialRepository,
|
||||||
|
IMapper _mapper) : IConsumer<AddSubjectTriggerCommand2>
|
||||||
|
{
|
||||||
|
public async Task Consume(ConsumeContext<AddSubjectTriggerCommand2> context)
|
||||||
|
{
|
||||||
|
var addSubjectEvent = context.Message;
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Console.WriteLine(_visitStageRepository._dbContext.GetHashCode());
|
||||||
|
|
||||||
|
Console.WriteLine("两个 DbContext 不是同一个实例");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//添加受试者的时候,获取访视计划列表,添加到受试者访视表。
|
||||||
|
var visitPlanList = await _visitStageRepository.Where(t => t.TrialId == addSubjectEvent.TrialId && t.IsConfirmed).ToListAsync();
|
||||||
|
|
||||||
|
var svList = _mapper.Map<List<SubjectVisit>>(visitPlanList);
|
||||||
|
|
||||||
|
var IsEnrollementQualificationConfirm = await _trialRepository.Where(t => t.Id == addSubjectEvent.TrialId).Select(u => u.IsEnrollementQualificationConfirm).FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
svList.ForEach(t =>
|
||||||
|
{
|
||||||
|
t.SubjectId = addSubjectEvent.SubjectId;
|
||||||
|
t.TrialId = addSubjectEvent.TrialId;
|
||||||
|
t.TrialSiteId = addSubjectEvent.TrialSiteId;
|
||||||
|
t.IsEnrollmentConfirm = t.IsBaseLine ? IsEnrollementQualificationConfirm : false;
|
||||||
|
t.Id = NewId.NextGuid();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
await _subjectVisitRepository.AddRangeAsync(svList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
+83
@@ -0,0 +1,83 @@
|
|||||||
|
|
||||||
|
|
||||||
|
using IRaCIS.Core.Application.MassTransit.Consumer;
|
||||||
|
using MassTransit;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.Application.MassTransit.Consumer;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 参考链接:https://github.com/MassTransit/MassTransit/discussions/2498
|
||||||
|
/// </summary>
|
||||||
|
public static class MediatorHttpContextScopeFilterExtensions
|
||||||
|
{
|
||||||
|
public static void UseHttpContextScopeFilter(this IMediatorConfigurator configurator, IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
var filter = new HttpContextScopeFilter(serviceProvider.GetRequiredService<IHttpContextAccessor>());
|
||||||
|
|
||||||
|
configurator.ConfigurePublish(x => x.UseFilter(filter));
|
||||||
|
configurator.ConfigureSend(x => x.UseFilter(filter));
|
||||||
|
configurator.UseFilter(filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class HttpContextScopeFilter :
|
||||||
|
IFilter<PublishContext>,
|
||||||
|
IFilter<SendContext>,
|
||||||
|
IFilter<ConsumeContext>
|
||||||
|
{
|
||||||
|
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||||
|
|
||||||
|
public HttpContextScopeFilter(IHttpContextAccessor httpContextAccessor)
|
||||||
|
{
|
||||||
|
_httpContextAccessor = httpContextAccessor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddPayload(PipeContext context)
|
||||||
|
{
|
||||||
|
if (_httpContextAccessor.HttpContext == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var serviceProvider = _httpContextAccessor.HttpContext.RequestServices;
|
||||||
|
context.GetOrAddPayload(() => serviceProvider);
|
||||||
|
context.GetOrAddPayload<IServiceScope>(() => new NoopScope(serviceProvider));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task Send(PublishContext context, IPipe<PublishContext> next)
|
||||||
|
{
|
||||||
|
AddPayload(context);
|
||||||
|
return next.Send(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task Send(SendContext context, IPipe<SendContext> next)
|
||||||
|
{
|
||||||
|
AddPayload(context);
|
||||||
|
return next.Send(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task Send(ConsumeContext context, IPipe<ConsumeContext> next)
|
||||||
|
{
|
||||||
|
AddPayload(context);
|
||||||
|
return next.Send(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Probe(ProbeContext context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private class NoopScope :
|
||||||
|
IServiceScope
|
||||||
|
{
|
||||||
|
public NoopScope(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
ServiceProvider = serviceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public IServiceProvider ServiceProvider { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,12 +3,10 @@
|
|||||||
// 生成时间 2022-06-07 13:16:33
|
// 生成时间 2022-06-07 13:16:33
|
||||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
using System;
|
|
||||||
using IRaCIS.Core.Domain.Share;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using IRaCIS.Application.Contracts;
|
using IRaCIS.Application.Contracts;
|
||||||
|
using IRaCIS.Core.Domain.Share;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.ViewModel
|
namespace IRaCIS.Core.Application.ViewModel
|
||||||
{
|
{
|
||||||
@@ -112,18 +110,19 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
public List<CriterionReadingCategory> CriterionCategoryList =>
|
public List<CriterionReadingCategory> CriterionCategoryList =>
|
||||||
|
|
||||||
TrialReadingCriterionList.Select(t =>
|
TrialReadingCriterionList.Select(t =>
|
||||||
new CriterionReadingCategory() {
|
new CriterionReadingCategory()
|
||||||
EnrollId = EnrollId,
|
{
|
||||||
TrialReadingCriterionId = t.TrialReadingCriterionId,
|
EnrollId = EnrollId,
|
||||||
|
TrialReadingCriterionId = t.TrialReadingCriterionId,
|
||||||
ReadingCategorys = CriterionReadingCategoryList.Where(c => c.TrialReadingCriterionId == t.TrialReadingCriterionId).Select(t => t.ReadingCategory).OrderBy(c => c).ToList()
|
ReadingCategorys = CriterionReadingCategoryList.Where(c => c.TrialReadingCriterionId == t.TrialReadingCriterionId).Select(t => t.ReadingCategory).OrderBy(c => c).ToList()
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//CriterionReadingCategoryList.Count == 0 ? TrialReadingCriterionList.Select(t => new CriterionReadingCategory() { EnrollId = EnrollId, TrialReadingCriterionId = t.TrialReadingCriterionId }).ToList() :
|
//CriterionReadingCategoryList.Count == 0 ? TrialReadingCriterionList.Select(t => new CriterionReadingCategory() { EnrollId = EnrollId, TrialReadingCriterionId = t.TrialReadingCriterionId }).ToList() :
|
||||||
// CriterionReadingCategoryList
|
// CriterionReadingCategoryList
|
||||||
//.GroupBy(t => new { t.TrialReadingCriterionId, t.EnrollId })
|
//.GroupBy(t => new { t.TrialReadingCriterionId, t.EnrollId })
|
||||||
//.Select(g => new CriterionReadingCategory() { EnrollId = g.Key.EnrollId, TrialReadingCriterionId = g.Key.TrialReadingCriterionId, ReadingCategorys = g.Select(t => t.ReadingCategory).OrderBy(t=>t).ToList() }).ToList();
|
//.Select(g => new CriterionReadingCategory() { EnrollId = g.Key.EnrollId, TrialReadingCriterionId = g.Key.TrialReadingCriterionId, ReadingCategorys = g.Select(t => t.ReadingCategory).OrderBy(t=>t).ToList() }).ToList();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,7 +211,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
public class GenerateTaskCommand
|
public class GenerateTaskCommand
|
||||||
{
|
{
|
||||||
public Guid TrialId { get; set; }
|
public Guid TrialId { get; set; }
|
||||||
|
|
||||||
//针对访视产生任务的 有用
|
//针对访视产生任务的 有用
|
||||||
public bool IsAssignSubjectToDoctor { get; set; }
|
public bool IsAssignSubjectToDoctor { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,7 @@
|
|||||||
// 生成时间 2022-07-01 15:33:01
|
// 生成时间 2022-07-01 15:33:01
|
||||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
using System;
|
|
||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
using System.Collections.Generic;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
@@ -81,7 +79,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
public Guid DoctorUserId { get; set; }
|
public Guid DoctorUserId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ConsistentConfirmGenerateCommand: SelfConsistentSimpleQuery
|
public class ConsistentConfirmGenerateCommand : SelfConsistentSimpleQuery
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
@@ -104,10 +102,10 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
public bool IsAutoAllocateGenerateTask { get; set; }
|
public bool IsAutoAllocateGenerateTask { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DoctorSelfConsistentSubjectView: ConsistentCommonView
|
public class DoctorSelfConsistentSubjectView : ConsistentCommonView
|
||||||
{
|
{
|
||||||
public string FirstGlobalVisitName { get; set; } = string.Empty;
|
public string FirstGlobalVisitName { get; set; } = string.Empty;
|
||||||
public string? BlindSubjectCode { get; set; }
|
public string? BlindSubjectCode { get; set; }
|
||||||
|
|
||||||
public List<VisitTaskSimpleDTO> VisitTaskList { get; set; }
|
public List<VisitTaskSimpleDTO> VisitTaskList { get; set; }
|
||||||
|
|
||||||
@@ -130,14 +128,14 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
public int? ValidVisitCount { get; set; }
|
public int? ValidVisitCount { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DoctorGroupConsistentSubjectView: ConsistentCommonView
|
public class DoctorGroupConsistentSubjectView : ConsistentCommonView
|
||||||
{
|
{
|
||||||
|
|
||||||
public List<VisitTaskGroupSimpleDTO> SubjectTaskVisitList => VisitTaskList.GroupBy(t => new { t.SubjectId, t.VisitTaskNum }).Where(g => g.Count() == 2).Select(g => g.First()).OrderBy(t=>t.VisitTaskNum).ToList();
|
public List<VisitTaskGroupSimpleDTO> SubjectTaskVisitList => VisitTaskList.GroupBy(t => new { t.SubjectId, t.VisitTaskNum }).Where(g => g.Count() == 2).Select(g => g.First()).OrderBy(t => t.VisitTaskNum).ToList();
|
||||||
|
|
||||||
public List<VisitTaskGroupSimpleDTO> VisitTaskList { get; set; } = new List<VisitTaskGroupSimpleDTO>();
|
public List<VisitTaskGroupSimpleDTO> VisitTaskList { get; set; } = new List<VisitTaskGroupSimpleDTO>();
|
||||||
|
|
||||||
public List<UserSimpleInfo> DoctorUserList { get; set; }=new List<UserSimpleInfo>();
|
public List<UserSimpleInfo> DoctorUserList { get; set; } = new List<UserSimpleInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class VisitTaskGroupSimpleDTO
|
public class VisitTaskGroupSimpleDTO
|
||||||
@@ -175,10 +173,10 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
public bool IsClinicalDataSign { get; set; }
|
public bool IsClinicalDataSign { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class VisitTaskSimpleDTO :VisitTaskGroupSimpleDTO
|
public class VisitTaskSimpleDTO : VisitTaskGroupSimpleDTO
|
||||||
{
|
{
|
||||||
public Guid? Id { get; set; }
|
public Guid? Id { get; set; }
|
||||||
|
|
||||||
|
|
||||||
public string TaskCode { get; set; }
|
public string TaskCode { get; set; }
|
||||||
|
|
||||||
@@ -289,7 +287,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
|
|
||||||
public class GetConsistentRuleOut
|
public class GetConsistentRuleOut
|
||||||
{
|
{
|
||||||
public TaskConsistentRuleBasic? ConsistentRuleBasic { get; set; }
|
public TaskConsistentRuleBasic? ConsistentRuleBasic { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 任务展示访视 读片任务显示是否顺序
|
/// 任务展示访视 读片任务显示是否顺序
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -316,7 +314,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
public string VirtualSiteCode { get; set; }
|
public string VirtualSiteCode { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UpdateTrialSiteCodeCommandView: UpdateTrialSiteCodeCommand
|
public class UpdateTrialSiteCodeCommandView : UpdateTrialSiteCodeCommand
|
||||||
{
|
{
|
||||||
public DateTime Creatime { get; set; }
|
public DateTime Creatime { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,8 @@
|
|||||||
// 生成时间 2022-06-29 13:36:46
|
// 生成时间 2022-06-29 13:36:46
|
||||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
using System;
|
|
||||||
using IRaCIS.Core.Domain.Share;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.ViewModel
|
namespace IRaCIS.Core.Application.ViewModel
|
||||||
{
|
{
|
||||||
@@ -33,7 +30,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
public List<TaskBasicIdView> ActualTumorTaskList { get; set; }
|
public List<TaskBasicIdView> ActualTumorTaskList { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public List<TaskBasicIdView> GeneratedVisitTaskList { get; set; }
|
public List<TaskBasicIdView> GeneratedVisitTaskList { get; set; }
|
||||||
|
|||||||
@@ -3,9 +3,7 @@
|
|||||||
// 生成时间 2022-06-29 10:59:50
|
// 生成时间 2022-06-29 10:59:50
|
||||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
using System;
|
|
||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.ViewModel
|
namespace IRaCIS.Core.Application.ViewModel
|
||||||
@@ -69,7 +67,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
{
|
{
|
||||||
if (!ReadingDurationTimeSpan.HasValue)
|
if (!ReadingDurationTimeSpan.HasValue)
|
||||||
return "";
|
return "";
|
||||||
else return string.Format("{0}h:{1}m:{2}s", (SignTime - FirstReadingTime)?.Hours, (SignTime - FirstReadingTime)?.Minutes, (SignTime - FirstReadingTime)?.Seconds)
|
else return string.Format("{0}h:{1}m:{2}s", (SignTime - FirstReadingTime)?.Hours, (SignTime - FirstReadingTime)?.Minutes, (SignTime - FirstReadingTime)?.Seconds)
|
||||||
/*string.Format("{0}分钟", (ReadingDurationTimeSpan)?.TotalMinutes)*/;
|
/*string.Format("{0}分钟", (ReadingDurationTimeSpan)?.TotalMinutes)*/;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,18 +100,18 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
|
|
||||||
public Guid? SubjectId { get; set; }
|
public Guid? SubjectId { get; set; }
|
||||||
|
|
||||||
public Guid? MedicalManagerUserId { get; set; }
|
public Guid? MedicalManagerUserId { get; set; }
|
||||||
|
|
||||||
public DateTime? BeginSignTime { get; set; }
|
public DateTime? BeginSignTime { get; set; }
|
||||||
public AuditAdvice? AuditAdviceEnum { get; set; }
|
public AuditAdvice? AuditAdviceEnum { get; set; }
|
||||||
|
|
||||||
public DateTime? EndSignTime { get; set; }
|
public DateTime? EndSignTime { get; set; }
|
||||||
|
|
||||||
public bool IsGetBeRead { get; set; } = false;
|
public bool IsGetBeRead { get; set; } = false;
|
||||||
|
|
||||||
public bool IsGetNextMedicalReviewTask { get; set; } = false;
|
public bool IsGetNextMedicalReviewTask { get; set; } = false;
|
||||||
|
|
||||||
public string SubjectCode { get; set; } = String.Empty;
|
public string SubjectCode { get; set; } = String.Empty;
|
||||||
|
|
||||||
public string TrialSiteCode { get; set; } = String.Empty;
|
public string TrialSiteCode { get; set; } = String.Empty;
|
||||||
public string TaskName { get; set; } = String.Empty;
|
public string TaskName { get; set; } = String.Empty;
|
||||||
@@ -133,7 +131,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
|
|
||||||
public Guid? TrialReadingCriterionId { get; set; }
|
public Guid? TrialReadingCriterionId { get; set; }
|
||||||
|
|
||||||
public MedicalReviewDoctorUserIdea? DoctorUserIdeaEnum { get; set; }
|
public MedicalReviewDoctorUserIdea? DoctorUserIdeaEnum { get; set; }
|
||||||
|
|
||||||
public Arm? ArmEnum { get; set; }
|
public Arm? ArmEnum { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -3,11 +3,9 @@
|
|||||||
// 生成时间 2022-06-07 14:10:54
|
// 生成时间 2022-06-07 14:10:54
|
||||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
using System;
|
|
||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.ViewModel
|
namespace IRaCIS.Core.Application.ViewModel
|
||||||
{
|
{
|
||||||
@@ -86,9 +84,9 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
public bool IsClinicalDataSign { get; set; }
|
public bool IsClinicalDataSign { get; set; }
|
||||||
|
|
||||||
|
|
||||||
public CompleteClinicalDataEnum CompleteClinicalDataEnum =>
|
public CompleteClinicalDataEnum CompleteClinicalDataEnum =>
|
||||||
(IsNeedClinicalDataSign && IsClinicalDataSign) ? CompleteClinicalDataEnum.Complete : (IsNeedClinicalDataSign && IsClinicalDataSign == false) ? CompleteClinicalDataEnum.NotComplete : CompleteClinicalDataEnum.NA;
|
(IsNeedClinicalDataSign && IsClinicalDataSign) ? CompleteClinicalDataEnum.Complete : (IsNeedClinicalDataSign && IsClinicalDataSign == false) ? CompleteClinicalDataEnum.NotComplete : CompleteClinicalDataEnum.NA;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -99,7 +97,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 任务展示访视 读片任务显示是否顺序
|
/// 任务展示访视 读片任务显示是否顺序
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ReadingOrder IsReadingTaskViewInOrder { get; set; }
|
public ReadingOrder IsReadingTaskViewInOrder { get; set; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -163,7 +161,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
|
|
||||||
public bool IsCanEditUrgentState { get; set; }
|
public bool IsCanEditUrgentState { get; set; }
|
||||||
|
|
||||||
public DateTime? FirstReadingTime { get;set; }
|
public DateTime? FirstReadingTime { get; set; }
|
||||||
|
|
||||||
public string ReadingDuration
|
public string ReadingDuration
|
||||||
{
|
{
|
||||||
@@ -221,11 +219,10 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
|
|
||||||
public class AnalysisTaskView : ReadingTaskView
|
public class AnalysisTaskView : ReadingTaskView
|
||||||
{
|
{
|
||||||
public bool? IsSelfAnalysis { get; set; }
|
|
||||||
|
|
||||||
public int ConsistentClinicalDataCount { get; set; } = 0;
|
public int ConsistentClinicalDataCount { get; set; } = 0;
|
||||||
|
|
||||||
public bool IsReReadingOrBackInfluenceAnalysis { get; set; }
|
public bool IsReReadingOrBackInfluenceAnalysis { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -298,6 +295,8 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
|
|
||||||
public bool IsUrgent => UnReadCanReadTaskList.Any(t => t.IsUrgent);
|
public bool IsUrgent => UnReadCanReadTaskList.Any(t => t.IsUrgent);
|
||||||
|
|
||||||
|
public bool IsSubjectJudge => UnReadCanReadTaskList.All(t => t.ReadingCategory == ReadingCategory.Judge);
|
||||||
|
|
||||||
public int UnReadTaskCount { get; set; }
|
public int UnReadTaskCount { get; set; }
|
||||||
|
|
||||||
public int UnReadCanReadTaskCount { get; set; }
|
public int UnReadCanReadTaskCount { get; set; }
|
||||||
@@ -317,7 +316,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
if (this.SuggesteFinishedTime != null)
|
if (this.SuggesteFinishedTime != null)
|
||||||
{
|
{
|
||||||
var date = DateTime.Now;
|
var date = DateTime.Now;
|
||||||
var timeSpan = SuggesteFinishedTime.Value- date;
|
var timeSpan = SuggesteFinishedTime.Value - date;
|
||||||
if (timeSpan.TotalDays <= 2)
|
if (timeSpan.TotalDays <= 2)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
@@ -338,14 +337,12 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int UrgentCount { get; set; }
|
public int UrgentCount { get; set; }
|
||||||
|
|
||||||
// public int UrgentCount => UnReadCanReadTaskList.Count(t => t.IsUrgent);
|
|
||||||
|
|
||||||
public List<IRUnreadTaskView> UnReadCanReadTaskList { get; set; } = new List<IRUnreadTaskView>();
|
public List<IRUnreadTaskView> UnReadCanReadTaskList { get; set; } = new List<IRUnreadTaskView>();
|
||||||
// public List<IRUnreadTaskView> UnReadCanReadTaskList => UnReadTaskList.Where(y => y.IsFrontTaskNeedSignButNotSign == false && (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true)).ToList();
|
|
||||||
|
|
||||||
public List<IRUnreadTaskView> UnReadTaskList { get; set; } = new List<IRUnreadTaskView>();
|
public List<IRUnreadTaskView> UnReadTaskList { get; set; } = new List<IRUnreadTaskView>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class IRUnreadTaskView
|
public class IRUnreadTaskView
|
||||||
@@ -392,13 +389,13 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public class GetReadingIQueryableInDto:PageInput
|
public class GetReadingIQueryableInDto : PageInput
|
||||||
{
|
{
|
||||||
public Guid TrialId { get; set; }
|
public Guid TrialId { get; set; }
|
||||||
|
|
||||||
public Guid? SubjectId { get; set; }
|
public Guid? SubjectId { get; set; }
|
||||||
|
|
||||||
public Guid TrialReadingCriterionId { get; set; }
|
public Guid TrialReadingCriterionId { get; set; }
|
||||||
|
|
||||||
public string? SubjectCode { get; set; } = null;
|
public string? SubjectCode { get; set; } = null;
|
||||||
|
|
||||||
@@ -410,7 +407,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
public Guid TrialId { get; set; }
|
public Guid TrialId { get; set; }
|
||||||
|
|
||||||
|
|
||||||
public Guid? TrialSiteId { get; set; }
|
public Guid? TrialSiteId { get; set; }
|
||||||
|
|
||||||
public Guid? SubjectId { get; set; }
|
public Guid? SubjectId { get; set; }
|
||||||
|
|
||||||
@@ -436,7 +433,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
|
|
||||||
public DateTime? BeginSignTime { get; set; }
|
public DateTime? BeginSignTime { get; set; }
|
||||||
|
|
||||||
public DateTime? EndSignTime { get; set; }
|
public DateTime? EndSignTime { get; set; }
|
||||||
|
|
||||||
public DateTime? BeginRequestReReadingTime { get; set; }
|
public DateTime? BeginRequestReReadingTime { get; set; }
|
||||||
public DateTime? EndRequestReReadingTime { get; set; }
|
public DateTime? EndRequestReReadingTime { get; set; }
|
||||||
@@ -554,7 +551,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
|
|
||||||
public int? SubjectAllocateState { get; set; }
|
public int? SubjectAllocateState { get; set; }
|
||||||
|
|
||||||
public List<Arm> ArmList { get; set; }=new List<Arm>() { };
|
public List<Arm> ArmList { get; set; } = new List<Arm>() { };
|
||||||
|
|
||||||
[NotDefault]
|
[NotDefault]
|
||||||
public Guid TrialReadingCriterionId { get; set; }
|
public Guid TrialReadingCriterionId { get; set; }
|
||||||
@@ -602,9 +599,9 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public List<SubjectUserView> DoctorUserList { get; set; }
|
public List<SubjectUserView> DoctorUserList { get; set; }
|
||||||
|
|
||||||
public List<SubjectUserView> PreviousDoctorUserList => DoctorUserList.Where(t => t.OrignalSubjectUserId != null).ToList();
|
public List<SubjectUserView> PreviousDoctorUserList => DoctorUserList.Where(t => t.ReplacedSubjectUserId != null).ToList();
|
||||||
|
|
||||||
public List<SubjectUserView> NowDoctorUserList => DoctorUserList.Where(t => t.OrignalSubjectUserId == null).ToList();
|
public List<SubjectUserView> NowDoctorUserList => DoctorUserList.Where(t => t.ReplacedSubjectUserId == null).ToList();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -622,7 +619,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
public bool IsConfirmed { get; set; }
|
public bool IsConfirmed { get; set; }
|
||||||
|
|
||||||
//该属性有值 说明该医生被替换了 分配的时候 要过滤掉
|
//该属性有值 说明该医生被替换了 分配的时候 要过滤掉
|
||||||
public Guid? OrignalSubjectUserId { get; set; }
|
public Guid? ReplacedSubjectUserId { get; set; }
|
||||||
|
|
||||||
public UserSimpleInfo DoctorUser { get; set; }
|
public UserSimpleInfo DoctorUser { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-12
@@ -6,20 +6,20 @@
|
|||||||
|
|
||||||
using IRaCIS.Core.Application.ViewModel;
|
using IRaCIS.Core.Application.ViewModel;
|
||||||
namespace IRaCIS.Core.Application.Interfaces
|
namespace IRaCIS.Core.Application.Interfaces
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ITaskAllocationRuleService
|
/// ITaskAllocationRuleService
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ITaskAllocationRuleService
|
public interface ITaskAllocationRuleService
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
//Task<List<TaskAllocationRuleView>> GetTaskAllocationRuleList(TaskAllocationRuleQuery queryTaskAllocationRule);
|
|
||||||
|
|
||||||
Task<IResponseOutput> AddOrUpdateTaskAllocationRule(TaskAllocationRuleAddOrEdit addOrEditTaskAllocationRule);
|
|
||||||
|
|
||||||
Task<IResponseOutput> DeleteTaskAllocationRule(Guid taskAllocationRuleId);
|
//Task<List<TaskAllocationRuleView>> GetTaskAllocationRuleList(TaskAllocationRuleQuery queryTaskAllocationRule);
|
||||||
|
|
||||||
|
Task<IResponseOutput> AddOrUpdateTaskAllocationRule(TaskAllocationRuleAddOrEdit addOrEditTaskAllocationRule);
|
||||||
|
|
||||||
|
Task<IResponseOutput> DeleteTaskAllocationRule(Guid taskAllocationRuleId);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user