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.Infrastructure.Extention;
|
||||
|
||||
namespace IRaCIS.Application.Services.BusinessFilter
|
||||
namespace IRaCIS.Core.Application.Service.BusinessFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// 统一返回前端数据包装,之前在控制器包装,现在修改为动态Api 在ResultFilter这里包装,减少重复冗余代码
|
||||
|
||||
@@ -7,7 +7,7 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using IRaCIS.Core.Domain.Models;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Application.Services;
|
||||
using IRaCIS.Core.Application.Service;
|
||||
using AutoMapper;
|
||||
using IRaCIS.Core.SCP.Service;
|
||||
|
||||
|
||||
@@ -7,8 +7,11 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<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="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.SqlServer" Version="1.0.5" />
|
||||
<PackageReference Include="fo-dicom" Version="5.1.3" />
|
||||
|
||||
@@ -113,6 +113,11 @@ builder.Services.AddAutoMapper(automapper =>
|
||||
//EF ORM QueryWithNoLock
|
||||
builder.Services.AddEFSetup(_configuration);
|
||||
|
||||
builder.Services.AddMediator(cfg =>
|
||||
{
|
||||
|
||||
});
|
||||
|
||||
|
||||
//转发头设置 获取真实IP
|
||||
builder.Services.Configure<ForwardedHeadersOptions>(options =>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using AutoMapper;
|
||||
using IRaCIS.Application.Services.BusinessFilter;
|
||||
using IRaCIS.Core.Application.Service.BusinessFilter;
|
||||
using IRaCIS.Core.Infra.EFCore;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
|
||||
@@ -176,6 +176,13 @@ namespace IRaCIS.Core.SCP.Service
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -236,11 +243,11 @@ namespace IRaCIS.Core.SCP.Service
|
||||
//奇怪的bug 上传的时候,用王捷修改的影像,会关闭,重新连接,导致检查id 丢失,然后状态不一致
|
||||
if (exception == null)
|
||||
{
|
||||
var _studyRepository = _serviceProvider.GetService<IRepository<SCPStudy>>();
|
||||
//将检查设置为传输结束
|
||||
await _studyRepository.BatchUpdateNoTrackingAsync(t => _SCPStudyIdList.Contains(t.Id), u => new SCPStudy() { IsUploadFinished = true });
|
||||
//var _studyRepository = _serviceProvider.GetService<IRepository<SCPStudy>>();
|
||||
////将检查设置为传输结束
|
||||
//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}");
|
||||
|
||||
+664
-336
File diff suppressed because it is too large
Load Diff
@@ -9,23 +9,16 @@
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "AliyunOSS",
|
||||
"AliyunOSS": {
|
||||
"regionId": "cn-shanghai",
|
||||
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||
"bucketName": "zy-irc-store",
|
||||
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
||||
"viewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com",
|
||||
"region": "oss-cn-shanghai"
|
||||
},
|
||||
"MinIO": {
|
||||
"endpoint": "http://192.168.3.68",
|
||||
"port": "8001",
|
||||
"useSSL": false,
|
||||
"accessKey": "IDFkwEpWej0b4DtiuThL",
|
||||
"secretKey": "Lhuu83yMhVwu7c1SnjvGY6lq74jzpYqifK6Qtj4h",
|
||||
"bucketName": "test"
|
||||
"RegionId": "cn-shanghai",
|
||||
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"AccessKeyId": "LTAI5tNRTsqL6aWmHkDmTwoH",
|
||||
"AccessKeySecret": "7mtGz3qrYWI6JMMBZiLeC119VWicZH",
|
||||
"RoleArn": "acs:ram::1899121822495495:role/irc-oss-access",
|
||||
"BucketName": "zy-irc-store",
|
||||
"ViewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com",
|
||||
"Region": "oss-cn-shanghai",
|
||||
"DurationSeconds": 7200
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -9,15 +9,16 @@
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "AliyunOSS",
|
||||
"AliyunOSS": {
|
||||
"regionId": "cn-shanghai",
|
||||
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||
"endPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||
"bucketName": "zy-irc-test-store",
|
||||
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
||||
"viewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
|
||||
"region": "oss-cn-shanghai"
|
||||
"RegionId": "cn-shanghai",
|
||||
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
|
||||
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
|
||||
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
|
||||
"BucketName": "zy-irc-test-store",
|
||||
"ViewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
|
||||
"Region": "oss-cn-shanghai",
|
||||
"DurationSeconds": 7200
|
||||
},
|
||||
|
||||
"MinIO": {
|
||||
@@ -28,53 +29,20 @@
|
||||
"secretKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
|
||||
"bucketName": "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": {
|
||||
"RemoteNew": "Server=106.14.89.110,1435;Database=Test_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=106.14.89.110,1435;Database=Test_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
},
|
||||
"BasicSystemConfig": {
|
||||
|
||||
"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": {
|
||||
"CalledAEList": [
|
||||
"STORESCP",
|
||||
"Value1",
|
||||
"Value2",
|
||||
"Value3"
|
||||
"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/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": {
|
||||
"ObjectStoreUse": "AliyunOSS",
|
||||
"AliyunOSS": {
|
||||
"regionId": "cn-shanghai",
|
||||
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||
"bucketName": "zy-irc-uat-store",
|
||||
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
||||
"viewEndpoint": "https://zy-irc-uat-store.oss-cn-shanghai.aliyuncs.com",
|
||||
"region": "oss-cn-shanghai"
|
||||
},
|
||||
|
||||
"AWS": {
|
||||
"endPoint": "s3.us-east-1.amazonaws.com",
|
||||
"useSSL": false,
|
||||
"accessKey": "AKIAZQ3DRSOHFPJJ6FEU",
|
||||
"secretKey": "l+yjtvV7Z4jiwm/7xCYv30UeUj/SvuqqYzAwjJHf",
|
||||
"bucketName": "ei-irc-test-store",
|
||||
"viewEndpoint": "https://ei-irc-test-store.s3.amazonaws.com/"
|
||||
"RegionId": "cn-shanghai",
|
||||
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
|
||||
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
|
||||
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
|
||||
"BucketName": "zy-irc-uat-store",
|
||||
"ViewEndpoint": "https://zy-irc-uat-store.oss-cn-shanghai.aliyuncs.com",
|
||||
"Region": "oss-cn-shanghai",
|
||||
"DurationSeconds": 7200
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=47.117.164.182,1434;Database=Uat_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=47.117.164.182,1434;Database=Uat_IRC.Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
},
|
||||
"BasicSystemConfig": {
|
||||
|
||||
"OpenUserComplexPassword": false,
|
||||
|
||||
"OpenSignDocumentBeforeWork": false,
|
||||
|
||||
"OpenTrialRelationDelete": true,
|
||||
|
||||
"OpenLoginLimit": false,
|
||||
"LoginMaxFailCount": 5,
|
||||
|
||||
"LoginFailLockMinutes": 30
|
||||
},
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"FromEmail": "uat-study@extimaging.com",
|
||||
"FromName": "Uat_Study",
|
||||
"AuthorizationCode": "zhanying123",
|
||||
"SiteUrl": "http://study.uat.extimaging.com/login"
|
||||
},
|
||||
"DicomSCPServiceConfig": {
|
||||
"CalledAEList": [
|
||||
"STORESCP",
|
||||
"Value1",
|
||||
"Value2",
|
||||
"Value3"
|
||||
"STORESCP"
|
||||
],
|
||||
"ServerPort": 11112
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRaCIS.Core.Infra.EFCore",
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRaCIS.Core.Infrastructure", "IRaCIS.Core.Infrastructure\IRaCIS.Core.Infrastructure.csproj", "{07EED0F8-08E6-46F3-ACBE-17BC1391BD4C}"
|
||||
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
|
||||
Global
|
||||
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 IRaCIS.Core.Application.Interfaces;
|
||||
using System.Threading.Tasks;
|
||||
using IRaCIS.Application.Services;
|
||||
using IRaCIS.Core.Application.Service;
|
||||
using IRaCIS.Core.Infra.EFCore;
|
||||
using IRaCIS.Core.Domain.Models;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
@@ -37,6 +37,7 @@ using Amazon.SecurityToken.Model;
|
||||
using Amazon.SecurityToken;
|
||||
using Amazon;
|
||||
using AssumeRoleRequest = Amazon.SecurityToken.Model.AssumeRoleRequest;
|
||||
using AutoMapper;
|
||||
|
||||
namespace IRaCIS.Api.Controllers
|
||||
{
|
||||
@@ -109,8 +110,12 @@ namespace IRaCIS.Api.Controllers
|
||||
[FromServices] ITokenService _tokenService,
|
||||
[FromServices] IReadingImageTaskService readingImageTaskService,
|
||||
[FromServices] IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig,
|
||||
[FromServices] IOptionsMonitor<SystemEmailSendConfig> _emailConfig,
|
||||
|
||||
[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
|
||||
if (loginUser.UserId != null && _verifyConfig.CurrentValue.OpenLoginMFA)
|
||||
@@ -143,10 +148,11 @@ namespace IRaCIS.Api.Controllers
|
||||
// 验证阅片休息时间
|
||||
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);
|
||||
|
||||
}
|
||||
@@ -221,9 +227,9 @@ namespace IRaCIS.Api.Controllers
|
||||
|
||||
if (_verifyConfig.CurrentValue.OpenLoginMFA)
|
||||
{
|
||||
//发版屏蔽
|
||||
|
||||
//returnModel.Data.JWTStr = _tokenService.GetToken(IRaCISClaims.Create(returnModel.Data.BasicInfo));
|
||||
|
||||
|
||||
|
||||
//MFA 发送邮件
|
||||
|
||||
@@ -231,11 +237,21 @@ namespace IRaCIS.Api.Controllers
|
||||
|
||||
var email = returnModel.Data.BasicInfo.EMail;
|
||||
|
||||
var hiddenEmail = EmailMaskHelper.MaskEmail(email);
|
||||
var hiddenEmail = IRCEmailPasswordHelper.MaskEmail(email);
|
||||
|
||||
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
|
||||
@@ -264,6 +280,8 @@ namespace IRaCIS.Api.Controllers
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
returnModel.Data.CompanyInfo = companyInfo;
|
||||
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")]
|
||||
@@ -297,100 +321,14 @@ namespace IRaCIS.Api.Controllers
|
||||
}
|
||||
|
||||
[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()
|
||||
{
|
||||
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 });
|
||||
}
|
||||
return ResponseOutput.Ok(result);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ using IRaCIS.Core.Application.Filter;
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using System.Threading.Tasks;
|
||||
using IRaCIS.Application.Services;
|
||||
using IRaCIS.Core.Application.Service;
|
||||
using IRaCIS.Core.Application.Service.Inspection.DTO;
|
||||
using IRaCIS.Core.Infra.EFCore;
|
||||
using IRaCIS.Core.Domain.Models;
|
||||
|
||||
@@ -38,6 +38,7 @@ using Newtonsoft.Json;
|
||||
using SharpCompress.Archives;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Data;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
@@ -234,36 +235,10 @@ namespace IRaCIS.Core.API.Controllers
|
||||
IRepository<SubjectVisit> _subjectVisitRepository,
|
||||
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>
|
||||
@@ -271,7 +246,7 @@ namespace IRaCIS.Core.API.Controllers
|
||||
[DisableFormValueModelBinding]
|
||||
[DisableRequestSizeLimit]
|
||||
[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] IStudyService _studyService,
|
||||
[FromServices] IHubContext<UploadHub, IUploadClient> _uploadHub,
|
||||
@@ -419,12 +394,26 @@ namespace IRaCIS.Core.API.Controllers
|
||||
|
||||
public class UploadNoneDicomFileCommand
|
||||
{
|
||||
public Guid TrialId { get; set; }
|
||||
[NotDefault]
|
||||
public Guid SubjectVisitId { get; set; }
|
||||
public Guid NoneDicomStudyId { get; set; }
|
||||
|
||||
|
||||
[NotDefault]
|
||||
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>();
|
||||
|
||||
|
||||
@@ -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>
|
||||
/// 上传非Dicom 文件 支持压缩包 多文件上传
|
||||
/// </summary>
|
||||
@@ -470,24 +494,37 @@ namespace IRaCIS.Core.API.Controllers
|
||||
|
||||
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 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.IsDicom = false;
|
||||
studyMonitor.IsDicomReUpload = false;
|
||||
studyMonitor.StudyId = noneDicomStudyId;
|
||||
studyMonitor.StudyId = noneDicomStudyId.Value;
|
||||
studyMonitor.StudyCode = noneDicomStudy.StudyCode;
|
||||
studyMonitor.ArchiveFinishedTime = DateTime.Now;
|
||||
studyMonitor.IP = _userInfo.IP;
|
||||
studyMonitor.IsSuccess = true;
|
||||
|
||||
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 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)
|
||||
{
|
||||
@@ -979,9 +1016,9 @@ namespace IRaCIS.Core.API.Controllers
|
||||
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, excelList.ToList());
|
||||
await _trialSiteSurveyService.ImportGenerateAccountAndJoinTrialAsync(trialId, baseUrl, routeUrl, list);
|
||||
|
||||
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">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<SignAssembly>false</SignAssembly>
|
||||
<UserSecretsId>354572d4-9e15-4099-807c-63a2d29ff9f2</UserSecretsId>
|
||||
<LangVersion>default</LangVersion>
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
<Version>1.0.1.001</Version>
|
||||
<Company>上海展影医疗科技有限公司</Company>
|
||||
<Product>IRC影像系统 (EICS)</Product>
|
||||
<Copyright>上海展影医疗科技有限公司版权所有</Copyright>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<SignAssembly>false</SignAssembly>
|
||||
<UserSecretsId>354572d4-9e15-4099-807c-63a2d29ff9f2</UserSecretsId>
|
||||
<LangVersion>default</LangVersion>
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
<Version>1.0.1.001</Version>
|
||||
<Company>上海展影医疗科技有限公司</Company>
|
||||
<Product>IRC影像系统 (EICS)</Product>
|
||||
<Copyright>上海展影医疗科技有限公司版权所有</Copyright>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DocumentationFile>.\IRaCIS.Core.API.xml</DocumentationFile>
|
||||
<NoWarn>1701;1702;1591;1570;</NoWarn>
|
||||
<OutputPath>..\bin\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DocumentationFile>.\IRaCIS.Core.API.xml</DocumentationFile>
|
||||
<NoWarn>1701;1702;1591;1570;</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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="wwwroot\swagger\ui\abp.swagger.js">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="wwwroot\swagger\ui\Index.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Protobuf Include="Protos\GrpcToken.proto">
|
||||
<GrpcServices>Client</GrpcServices>
|
||||
</Protobuf>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="GrpcToken.proto" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="wwwroot\swagger\ui\abp.js">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="wwwroot\swagger\ui\abp.swagger.js">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="wwwroot\swagger\ui\Index.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Protobuf Include="Protos\GrpcToken.proto">
|
||||
<GrpcServices>Client</GrpcServices>
|
||||
</Protobuf>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.1.4" />
|
||||
<PackageReference Include="AspNetCoreRateLimit" Version="5.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="AspNetCoreRateLimit" Version="5.0.0" />
|
||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" />
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\IRaCIS.Core.Application\IRaCIS.Core.Application.csproj" />
|
||||
<ProjectReference Include="..\IRaCIS.Core.Infra.EFCore\IRaCIS.Core.Infra.EFCore.csproj" />
|
||||
</ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.8">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</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>
|
||||
<None Include="..\.editorconfig" Link=".editorconfig" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\IRaCIS.Core.Application\IRaCIS.Core.Application.csproj" />
|
||||
<ProjectReference Include="..\IRaCIS.Core.Infra.EFCore\IRaCIS.Core.Infra.EFCore.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="wwwroot\EmailTemplate\AdminAddUser_US.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\AdminResetUser_US.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\AdminResetUser.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\SubjectEnrollConfirmOrPDProgress_US.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\TrialDoctorExistJoin_US.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\TrialDoctorFirstJoin.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\TrialSiteSurveyReject.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\TrialSiteSurveyReject_US.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\TrialDoctorExistJoin.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\TrialUserExistJoin_US.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\TrialUserExistJoin.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\AdminAddUser.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\TrialDoctorFirstJoin_US.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\SubjectEnrollConfirmOrPDProgress.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\TrialUserFirstJoin_US.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\UserOptCommon_US.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\UserOptCommon.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\TrialUserFirstJoin.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\.editorconfig" Link=".editorconfig" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\PublishProfiles\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\PublishProfiles\" />
|
||||
</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>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<param name="doctorId"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Api.Controllers.ExtraController.Login(IRaCIS.Application.Contracts.UserLoginDTO,ZiggyCreatures.Caching.Fusion.IFusionCache,IRaCIS.Application.Services.IUserService,IRaCIS.Core.Application.Auth.ITokenService,IRaCIS.Core.Application.Contracts.IReadingImageTaskService,Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.ServiceVerifyConfigOption},IRaCIS.Application.Services.IMailVerificationService)">
|
||||
<member name="M:IRaCIS.Api.Controllers.ExtraController.Login(IRaCIS.Application.Contracts.UserLoginDTO,ZiggyCreatures.Caching.Fusion.IFusionCache,IRaCIS.Core.Application.Service.IUserService,IRaCIS.Core.Application.Auth.ITokenService,IRaCIS.Core.Application.Contracts.IReadingImageTaskService,Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.ServiceVerifyConfigOption},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig},IRaCIS.Core.Application.Service.IMailVerificationService)">
|
||||
<summary> 系统用户登录接口[New] </summary>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.AddOrUpdateTrialInspection(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Application.Contracts.TrialCommand})">
|
||||
@@ -41,7 +41,7 @@
|
||||
<param name="param"></param>
|
||||
<returns>新记录Id</returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.WorkLoadAddOrUpdate(IRaCIS.Application.Services.IDoctorWorkloadService,IRaCIS.Application.Contracts.WorkloadCommand)">
|
||||
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.WorkLoadAddOrUpdate(IRaCIS.Core.Application.Service.IDoctorWorkloadService,IRaCIS.Application.Contracts.WorkloadCommand)">
|
||||
<summary>
|
||||
添加或更新工作量[AUTH]
|
||||
</summary>
|
||||
@@ -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})">
|
||||
<summary>Dicom 归档</summary>
|
||||
</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})">
|
||||
<summary>
|
||||
上传非Dicom 文件 支持压缩包 多文件上传
|
||||
@@ -366,11 +375,6 @@
|
||||
<param name="memberSerialization">序列化成员</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:TimeZoneAdjustmentMiddleware">
|
||||
<summary>
|
||||
废弃,没用
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:ZhaoXi._001.NET5Demo.Practice.WebApi.Utility.Jwt.CustomHSJWTService">
|
||||
<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 IRaCIS.Core.Application.Filter;
|
||||
using Microsoft.AspNetCore.HttpOverrides;
|
||||
using IRaCIS.Application.Services.BackGroundJob;
|
||||
using IRaCIS.Core.Application.Service.BackGroundJob;
|
||||
using LogDashboard;
|
||||
using FellowOakDicom.Network;
|
||||
using IRaCIS.Core.Application.Service.ImageAndDoc;
|
||||
@@ -33,6 +33,8 @@ using Newtonsoft.Json;
|
||||
using Microsoft.AspNetCore.Diagnostics;
|
||||
using IRaCIS.Core.Application.MassTransit.Command;
|
||||
using IRaCIS.Core.Application.MassTransit.Consumer;
|
||||
using DocumentFormat.OpenXml.InkML;
|
||||
using IRaCIS.Core.Domain;
|
||||
|
||||
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
|
||||
AppContext.SetSwitch("Npgsql.DisableDateTimeInfinityConversions", true);
|
||||
@@ -110,7 +112,7 @@ builder.Services.AddControllers(options =>
|
||||
options.Filters.Add<ModelActionFilter>();
|
||||
options.Filters.Add<ProjectExceptionFilter>();
|
||||
options.Filters.Add<UnitOfWorkFilter>();
|
||||
options.Filters.Add<EncreptApiResultFilter>(10);
|
||||
//options.Filters.Add<EncreptApiResultFilter>(10);
|
||||
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<AliyunOSSOptions>(_configuration.GetSection("AliyunOSS"));
|
||||
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.Configure<IRaCISBasicConfigOption>(_configuration.GetSection("IRaCISBasicConfig"));
|
||||
|
||||
|
||||
//动态WebApi + UnifiedApiResultFilter 省掉控制器代码
|
||||
builder.Services.AddDynamicWebApiSetup();
|
||||
//AutoMapper
|
||||
builder.Services.AddAutoMapperSetup();
|
||||
//EF ORM QueryWithNoLock
|
||||
builder.Services.AddEFSetup(_configuration,enviromentName);
|
||||
builder.Services.AddEFSetup(_configuration, enviromentName);
|
||||
//Http 响应压缩
|
||||
builder.Services.AddResponseCompressionSetup();
|
||||
//Swagger Api 文档
|
||||
@@ -143,15 +147,30 @@ builder.Services.AddJWTAuthSetup(_configuration);
|
||||
|
||||
#region MassTransit
|
||||
//masstransit组件 也支持MediatR 中介者模式,但是支持分布式,考虑后续,所以在次替代MediatR
|
||||
//参考链接:https://masstransit.io/documentation/concepts/mediator#scoped-mediator
|
||||
builder.Services.AddMediator(cfg =>
|
||||
{
|
||||
cfg.AddConsumer<ConsistencyCheckConsumer>();
|
||||
cfg.AddConsumer<AddSubjectTriggerConsumer>();
|
||||
cfg.AddConsumer<AddSubjectTriggerConsumer2>();
|
||||
//cfg.ConfigureMediator((context, cfg) => cfg.UseHttpContextScopeFilter(context));
|
||||
});
|
||||
|
||||
//添加 MassTransit 和 InMemory 传输
|
||||
builder.Services.AddMassTransit(cfg =>
|
||||
{
|
||||
cfg.UsingInMemory();
|
||||
// 注册消费者
|
||||
cfg.AddConsumer<AddSubjectTriggerConsumer>(); // 替换为你的消费者类
|
||||
cfg.AddConsumer<AddSubjectTriggerConsumer2>();
|
||||
|
||||
// 使用 InMemory 作为消息传递机制
|
||||
cfg.UsingInMemory((context, cfg) =>
|
||||
{
|
||||
// 这里可以进行额外的配置
|
||||
cfg.ConfigureEndpoints(context); // 自动配置所有消费者的端点
|
||||
});
|
||||
});
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -193,6 +212,7 @@ builder.Services.AddSingleton<ISearcher>(new Searcher(CachePolicy.Content, Path.
|
||||
//builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
|
||||
//builder.Services.AddProblemDetails();
|
||||
|
||||
|
||||
#region 历史废弃配置
|
||||
//builder.Services.AddMemoryCache();
|
||||
////上传限制 配置
|
||||
@@ -215,6 +235,7 @@ var env = app.Environment;
|
||||
|
||||
#region 配置中间件
|
||||
|
||||
app.UseMiddleware<EncryptionRequestMiddleware>();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Hangfire;
|
||||
using Hangfire.Dashboard;
|
||||
using Hangfire.Dashboard.BasicAuthorization;
|
||||
using IRaCIS.Application.Services.BackGroundJob;
|
||||
using IRaCIS.Core.Application.Service.BackGroundJob;
|
||||
using IRaCIS.Core.API.Filter;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace IRaCIS.Core.API
|
||||
|
||||
// 全局忽略 DomainEvents 属性
|
||||
automapper.AddGlobalIgnore(nameof(Entity.DomainEvents));
|
||||
automapper.AddGlobalIgnore(nameof(Entity.DomainCommands));
|
||||
|
||||
#region 会使 IncludeMembers 失效 不能全局使用
|
||||
//mapping an EntityFramework Core DbContext-object.
|
||||
|
||||
@@ -9,7 +9,7 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using IRaCIS.Core.Domain.Models;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Application.Services;
|
||||
using IRaCIS.Core.Application.Service;
|
||||
using IRaCIS.Application.Interfaces;
|
||||
using AutoMapper;
|
||||
|
||||
|
||||
@@ -8,9 +8,11 @@ using Medallion.Threading;
|
||||
using Medallion.Threading.SqlServer;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using StackExchange.Redis;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
@@ -46,10 +48,11 @@ namespace IRaCIS.Core.API
|
||||
else
|
||||
{
|
||||
options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value, contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure());
|
||||
|
||||
}
|
||||
|
||||
|
||||
//迁移的时候,不生成外键
|
||||
options.ReplaceService<IMigrationsSqlGenerator, NoForeignKeyMigrationsSqlGenerator>();
|
||||
|
||||
|
||||
options.UseLoggerFactory(logFactory);
|
||||
@@ -72,18 +75,15 @@ namespace IRaCIS.Core.API
|
||||
|
||||
options.UseTriggers(triggerOptions =>
|
||||
{
|
||||
triggerOptions.AddTrigger<AddSubjectTrigger>();
|
||||
triggerOptions.AddTrigger<ChallengeStateTrigger>();
|
||||
triggerOptions.AddTrigger<SubjectStateTrigger>();
|
||||
triggerOptions.AddTrigger<AddCRCCliniaclDataTrigger>();
|
||||
triggerOptions.AddTrigger<SubjectVisitCheckPassedTrigger>();
|
||||
triggerOptions.AddTrigger<SubjectVisitFinalVisitTrigger>();
|
||||
triggerOptions.AddTrigger<SubjectTrigger>();
|
||||
triggerOptions.AddTrigger<ChallengeStateTrigger>();
|
||||
triggerOptions.AddTrigger<SubjectVisitTrigger>();
|
||||
triggerOptions.AddTrigger<SubjectVisitScanDateTrigger>();
|
||||
triggerOptions.AddTrigger<TrialCriterionSignTrigger>();
|
||||
triggerOptions.AddTrigger<TableQuestionRowTrigger>();
|
||||
//triggerOptions.AddTrigger<AddlTrialUserTrigger>();
|
||||
triggerOptions.AddTrigger<VisitTaskIsFrontTaskNeedSignButNotSignTrigger>();
|
||||
triggerOptions.AddTrigger<VisitTaskIbeforeTrigger>();
|
||||
triggerOptions.AddTrigger<JudgeVisitTaskTrigger>();
|
||||
|
||||
triggerOptions.AddTrigger<UserLogTrigger>();
|
||||
|
||||
|
||||
@@ -35,7 +35,9 @@ namespace IRaCIS.Core.API
|
||||
else
|
||||
{
|
||||
// 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
|
||||
|
||||
@@ -13,15 +13,16 @@
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "AliyunOSS",
|
||||
"AliyunOSS": {
|
||||
"regionId": "cn-shanghai",
|
||||
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||
"bucketName": "zy-irc-store",
|
||||
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
||||
"viewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com",
|
||||
"region": "oss-cn-shanghai"
|
||||
"RegionId": "cn-shanghai",
|
||||
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"AccessKeyId": "LTAI5tNRTsqL6aWmHkDmTwoH",
|
||||
"AccessKeySecret": "7mtGz3qrYWI6JMMBZiLeC119VWicZH",
|
||||
"RoleArn": "acs:ram::1899121822495495:role/irc-oss-access",
|
||||
"BucketName": "zy-irc-store",
|
||||
"ViewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com",
|
||||
"Region": "oss-cn-shanghai",
|
||||
"DurationSeconds": 7200
|
||||
},
|
||||
"MinIO": {
|
||||
"endpoint": "http://192.168.3.68",
|
||||
@@ -63,7 +64,8 @@
|
||||
"CompanyName": "Extensive Imaging",
|
||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||
"CompanyShortName": "Extensive Imaging",
|
||||
"CompanyShortNameCN": "展影医疗"
|
||||
"CompanyShortNameCN": "展影医疗",
|
||||
"IsEnv_US": false
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -15,15 +15,16 @@
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "AliyunOSS",
|
||||
"AliyunOSS": {
|
||||
"regionId": "cn-shanghai",
|
||||
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||
"bucketName": "zy-irc-store",
|
||||
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
||||
"viewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com",
|
||||
"region": "oss-cn-shanghai"
|
||||
"RegionId": "cn-shanghai",
|
||||
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"AccessKeyId": "LTAI5tNRTsqL6aWmHkDmTwoH",
|
||||
"AccessKeySecret": "7mtGz3qrYWI6JMMBZiLeC119VWicZH",
|
||||
"RoleArn": "acs:ram::1899121822495495:role/irc-oss-access",
|
||||
"BucketName": "zy-irc-store",
|
||||
"ViewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com",
|
||||
"Region": "oss-cn-shanghai",
|
||||
"DurationSeconds": 7200
|
||||
},
|
||||
"MinIO": {
|
||||
"endpoint": "http://192.168.3.68",
|
||||
@@ -67,7 +68,8 @@
|
||||
"CompanyName": "Extensive Imaging",
|
||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||
"CompanyShortName": "Extensive Imaging",
|
||||
"CompanyShortNameCN": "展影医疗"
|
||||
"CompanyShortNameCN": "展影医疗",
|
||||
"IsEnv_US": false
|
||||
},
|
||||
"SystemPacsConfig": {
|
||||
"Port": "11113",
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
"RegionId": "cn-shanghai",
|
||||
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"AccessKeyId": "LTAI5tJV76pYX5yPg1N9QVE8",
|
||||
"AccessKeySecret": "roRNLa9YG1of4pYruJGCNKBXEWTAWa",
|
||||
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
|
||||
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
|
||||
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
|
||||
"BucketName": "zy-irc-test-store",
|
||||
"RoleArn": "acs:ram::1899121822495495:role/webdirect",
|
||||
"ViewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
|
||||
"Region": "oss-cn-shanghai",
|
||||
"DurationSeconds": 7200
|
||||
@@ -40,11 +40,11 @@
|
||||
"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",
|
||||
"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/",
|
||||
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com",
|
||||
"DurationSeconds": 7200
|
||||
}
|
||||
},
|
||||
@@ -88,7 +88,8 @@
|
||||
"CompanyName": "Extensive Imaging",
|
||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||
"CompanyShortName": "Extensive Imaging",
|
||||
"CompanyShortNameCN": "展影医疗"
|
||||
"CompanyShortNameCN": "展影医疗",
|
||||
"IsEnv_US": false
|
||||
},
|
||||
|
||||
"SystemPacsConfig": {
|
||||
|
||||
@@ -15,18 +15,6 @@
|
||||
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "AWS",
|
||||
"AliyunOSS": {
|
||||
"regionId": "cn-shanghai",
|
||||
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||
"endPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"accessKeyId": "",
|
||||
"accessKeySecret": "",
|
||||
"bucketName": "zy-irc-test-store",
|
||||
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
||||
"viewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
|
||||
"region": "oss-cn-shanghai"
|
||||
},
|
||||
|
||||
"MinIO": {
|
||||
"endPoint": "44.210.231.169",
|
||||
"port": "9001",
|
||||
@@ -38,12 +26,15 @@
|
||||
},
|
||||
|
||||
"AWS": {
|
||||
"endPoint": "s3.us-east-1.amazonaws.com",
|
||||
"useSSL": true,
|
||||
"accessKey": "AKIAW3MEAFJX5P32P6NA",
|
||||
"secretKey": "soKfYlzZE11Zi4RyTjXp0myXN0U3U+ka8rT49+B/",
|
||||
"bucketName": "ei-med-s3-lili-store",
|
||||
"viewEndpoint": "https://ei-med-s3-lili-store.s3.amazonaws.com/"
|
||||
"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
|
||||
}
|
||||
},
|
||||
"BasicSystemConfig": {
|
||||
@@ -82,7 +73,13 @@
|
||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||
"CompanyShortName": "Elevate Imaging",
|
||||
"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": {
|
||||
|
||||
"ObjectStoreUse": "MinIO",
|
||||
"AliyunOSS": {
|
||||
"regionId": "cn-shanghai",
|
||||
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||
"endPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||
"bucketName": "zy-irc-test-store",
|
||||
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
||||
"viewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
|
||||
"region": "oss-cn-shanghai"
|
||||
},
|
||||
|
||||
"ObjectStoreUse": "AWS",
|
||||
"MinIO": {
|
||||
//"endPoint": "hir-oss.uat.extimaging.com",
|
||||
//"port": "443",
|
||||
@@ -44,23 +32,26 @@
|
||||
},
|
||||
|
||||
"AWS": {
|
||||
"endPoint": "s3.us-east-1.amazonaws.com",
|
||||
"useSSL": true,
|
||||
"accessKey": "AKIAZQ3DRSOHFPJJ6FEU",
|
||||
"secretKey": "l+yjtvV7Z4jiwm/7xCYv30UeUj/SvuqqYzAwjJHf",
|
||||
"bucketName": "ei-irc-test-store",
|
||||
"viewEndpoint": "https://ei-irc-test-store.s3.amazonaws.com/"
|
||||
"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
|
||||
}
|
||||
},
|
||||
"BasicSystemConfig": {
|
||||
|
||||
"OpenUserComplexPassword": false,
|
||||
"OpenUserComplexPassword": true,
|
||||
|
||||
"OpenSignDocumentBeforeWork": false,
|
||||
"OpenSignDocumentBeforeWork": true,
|
||||
|
||||
"OpenTrialRelationDelete": true,
|
||||
|
||||
"OpenLoginLimit": false,
|
||||
"OpenLoginLimit": true,
|
||||
|
||||
"LoginMaxFailCount": 5,
|
||||
|
||||
@@ -72,7 +63,9 @@
|
||||
"ReadingRestTimeMin": 10,
|
||||
"IsNeedChangePassWord": true,
|
||||
|
||||
"ChangePassWordDays": 90
|
||||
"ChangePassWordDays": 90,
|
||||
|
||||
"OpenLoginMFA": true
|
||||
},
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
@@ -88,7 +81,13 @@
|
||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||
"CompanyShortName": "Elevate Imaging",
|
||||
"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": {
|
||||
"RemoteNew": "Server=us-mssql-service,1433;Database=US_Uat_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=us-mssql-service,1433;Database=US_Uat_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
//"RemoteNew": "Server=us-mssql-service,1433;Database=US_Uat_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
//"Hangfire": "Server=us-mssql-service,1433;Database=US_Uat_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
|
||||
//"RemoteNew": "Server=3.226.182.187,1435;Database=US_Uat_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
//"Hangfire": "Server=3.226.182.187,1435;Database=US_Uat_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
"RemoteNew": "Server=3.226.182.187,1435;Database=US_Uat_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=3.226.182.187,1435;Database=US_Uat_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
},
|
||||
|
||||
"ObjectStoreService": {
|
||||
@@ -36,19 +36,22 @@
|
||||
},
|
||||
|
||||
"AWS": {
|
||||
"endPoint": "s3.us-east-1.amazonaws.com",
|
||||
"useSSL": true,
|
||||
"accessKey": "AKIAW3MEAFJXUO6XYFYN",
|
||||
"secretKey": "AeX5r4xHQH7tNJlTTFVv5/zBXie1Kj+mAayKrukp",
|
||||
"bucketName": "ei-med-s3-lili-uat-store",
|
||||
"viewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com/"
|
||||
"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
|
||||
}
|
||||
},
|
||||
"BasicSystemConfig": {
|
||||
|
||||
"OpenUserComplexPassword": false,
|
||||
"OpenUserComplexPassword": true,
|
||||
|
||||
"OpenSignDocumentBeforeWork": false,
|
||||
"OpenSignDocumentBeforeWork": true,
|
||||
|
||||
"OpenTrialRelationDelete": true,
|
||||
|
||||
@@ -66,7 +69,7 @@
|
||||
|
||||
"ChangePassWordDays": 90,
|
||||
|
||||
"OpenLoginMFA": true
|
||||
"OpenLoginMFA": false
|
||||
},
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
@@ -82,7 +85,13 @@
|
||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||
"CompanyShortName": "Elevate Imaging",
|
||||
"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",
|
||||
|
||||
"AliyunOSS": {
|
||||
"regionId": "cn-shanghai",
|
||||
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||
"bucketName": "zy-irc-uat-store",
|
||||
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
||||
"viewEndpoint": "https://zy-irc-uat-store.oss-cn-shanghai.aliyuncs.com",
|
||||
"region": "oss-cn-shanghai"
|
||||
"RegionId": "cn-shanghai",
|
||||
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
|
||||
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
|
||||
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
|
||||
"BucketName": "zy-irc-uat-store",
|
||||
"ViewEndpoint": "https://zy-irc-uat-store.oss-cn-shanghai.aliyuncs.com",
|
||||
"Region": "oss-cn-shanghai",
|
||||
"DurationSeconds": 7200
|
||||
},
|
||||
|
||||
"MinIO": {
|
||||
@@ -38,6 +39,17 @@
|
||||
"secretKey": "DzMaU2L4OXl90uytwOmDXF2encN0Jf4Nxu2XkYqQ",
|
||||
"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",
|
||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||
"CompanyShortName": "Extensive Imaging",
|
||||
"CompanyShortNameCN": "展影医疗"
|
||||
"CompanyShortNameCN": "展影医疗",
|
||||
"IsEnv_US": false
|
||||
},
|
||||
|
||||
"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": {
|
||||
"SwitchingMode": "RemainingDiskCapacity",
|
||||
"SwitchingRatio": 80,
|
||||
@@ -88,13 +54,15 @@
|
||||
"QCChallengeCodePrefix": "Q",
|
||||
"NoneDicomStudyCodePrefix": "NST",
|
||||
"DicomStudyCodePrefix": "ST",
|
||||
"TaskStudyCodePrefix": "P-ST",
|
||||
"SystemSiteCodePrefix": "S",
|
||||
"DefaultPassword": "123456",
|
||||
"ImageShareExpireDays": 10
|
||||
},
|
||||
|
||||
"EncrypteResponseConfig": {
|
||||
"IsEnable": true,
|
||||
"Base64RSAPublicKey": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0NCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBaHp3T1hYTWYyaEFkS1ZoWHczYUYNCmNaT3QycE1lcmdEaFVrOUdQK2s4VDBrUjFTRVlGVGtzNlkzaEVvL0dRTExqMHZFYVV3bTNhSFNuTTl5NmdLRWoNCmY5cTN6dkoyZzRSQjE4Z0UrTnNWWi9DMkVRZ3k5OWFiWGc5TitGREVlT0NmSjlSRTJPV3JBQ2s0V0RPbFFUdXYNCnhvR2JmcnkwVElSaFBrOGtuYkFmVkZ1and1VXJGblpJZ0ExYXhKZVZ6aDhwcmV1SEgreW1jdHp6NVo4V1pSV3kNCi9ISURHUy90dkg2NUMra2l6cUxRYUpKNHYwODMrRGpaVTBmNzNCdkk5eWt1dW1saXFzY1pvU2preDFOUFJwSkUNCkFtMVFNQ0hMRCtFdzlHT2Vsc2Mwa1ZxdjdaeEF1TkFrMkZuUURNRk1BUmZuUFd0aGVhOGZYVTJsMW9ROWs3WDcNCmN3SURBUUFCDQotLS0tLUVORCBQVUJMSUMgS0VZLS0tLS0NCg==",
|
||||
"Base64RSAPrivateKey": "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRW9nSUJBQUtDQVFFQWh6d09YWE1mMmhBZEtWaFh3M2FGY1pPdDJwTWVyZ0RoVWs5R1ArazhUMGtSMVNFWQ0KRlRrczZZM2hFby9HUUxMajB2RWFVd20zYUhTbk05eTZnS0VqZjlxM3p2SjJnNFJCMThnRStOc1ZaL0MyRVFneQ0KOTlhYlhnOU4rRkRFZU9DZko5UkUyT1dyQUNrNFdET2xRVHV2eG9HYmZyeTBUSVJoUGs4a25iQWZWRnVqd3VVcg0KRm5aSWdBMWF4SmVWemg4cHJldUhIK3ltY3R6ejVaOFdaUld5L0hJREdTL3R2SDY1QytraXpxTFFhSko0djA4Mw0KK0RqWlUwZjczQnZJOXlrdXVtbGlxc2Nab1Nqa3gxTlBScEpFQW0xUU1DSExEK0V3OUdPZWxzYzBrVnF2N1p4QQ0KdU5BazJGblFETUZNQVJmblBXdGhlYThmWFUybDFvUTlrN1g3Y3dJREFRQUJBb0lCQUNDRFoxNi9XWWFYZmpOZA0KQ29pemU2VFJZU2llVzI5eFJic0ExVDV6YUcwVmY4U1NsdFF2Y1dWYmw2UGJUa3BxMkF4MHJDUVB2M2xOSm8vNA0KL3h3QzRlS1E1c1ZLRlFWTXJIbmhISlRxTTJ6UWVpMkJINlBuaEdZcVh0QVhOdzFxejhrSEoyQlFZM3IvN2d5Qw0KcWpZVFVCRDFRem5HeThCanlXOXVIcnNNeDVPRHRRZWxBM3B1TFd1bXZNb3Z1L2JhaDZvTGtOSHY4b0VTdzhGSQ0KTllyTUtscHhFTjZaWUdwSTl2VTZnYUhuTmhEa2ExTHlvUnZ5NnA2dTRLR0FsRTc1VXk4T0dsdncydU5uay9sdg0KSEMyYnY5TnlCRGJpSFNDY0MyK1JXUXMrN0tNWFlwYnBvTVFCR0hqV01GRHVBODFaUCs1TWYxUm9yQUpRNGxrRw0KQnRDQThva0NnWUVBeWY4alBjcFIvQ3dJNU5MYnlwb3ZUWEFHVkFKMmtWRlJVUC9HT2ZOMkFyYWMvL20wdDJ5NA0KemNYVkJZc0pJeHkvVWYxRTFJNFg3VFg3V3NBNGxVNGlPTkwzTnN4dDBEbk1PV2tKUlBPZlF1bW1JaWw5QVRiYQ0KTnRVWFNlTmRoUFFGMGlCb21acFFJYWpSN1RmUnVBbzR6dmpTLzkzeXZZY0lIWU1zM0tjR00ya0NnWUVBcTJPbg0KZlp0RmhLTElGanVlRzRrNklGTWdjbytEUUh5TTFWSUp5Tk05K1o2TEgybzI5eDJCaSs2Qm82M2NKUjQ2STZncQ0KNWUrSTBvdzZRYmNQeTZUNHFSQ0o3Ujd6MllkdEw4eXdJTkNYS3U0cC9qaFNqNWJ1TzFJWlI3ZStSV29CakNtUQ0KWFd0ZVBCbldqWVlLdVRCazROc2FXV09GTXg1QndKdUp2MjBnQ0hzQ2dZQlV4QnFYM1lWV0cyeUlDZXh1TXhIUw0KbjBZb2p2Z090MTgyYkg5VTVsUUpnM1NTL3NqVmlHeHMvYTROSzNGa0tMWW93KzNVZk9TUmlPdTRBNTQ3R1pURw0KMzlFYVQrTnRWRFBkaTdSMkdQNG1hRUp0WjVlcm9NY2w1M3BrYVdOZlhiL3JrK29STzI2UkVYVTI1UXUrL1pzbA0KVDhuTDBlb0JtdDdPODdNcHpYV09zUUtCZ0ZxVGFQSGx2RUNUY3FEbFV2S0VmRmFXOTkvelhrOFhRNnA5RjdTdA0KaHVSRDJJeDZxcC9BVlRWcGo5Tzd6MHRDaFVGUTM1THpHMkVDUU10My9uNEdLbS9XMEwyakRRWWFIeWNTeXNZYw0KMXJjV2ROVG9XU0dQaDBtTVl0WFhFbFJHNkpoMVl0a3NJL29wUVkwN21MRTBGU3dNUHdtY29jbFpKVEN3UW9VTA0KRzlHL0FvR0FWM25kcWcydnUyR0x4TlRUbm1UTWRJNFB3UzBmN0V4VnVNUnRicGZyOWhKNzlDakVNTGFXQ1FsNg0KeE43TElMTnArNVQwQW1DZVBqcitkbnJkRUNidFZPTDFybDc3Z0krRkwzaVVqYmZmMVZqa0N3M0x6K3cyb1FFdA0KbGE4aTZrL1NRK01iYkRPaWRJOVczdlN6MmlJRlZobWJiK1Q2SlZwakxqNjlkblM3eUxZPQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg==",
|
||||
"IsResponseEncreptEnable": true,
|
||||
"ApiPathList": [
|
||||
"/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,
|
||||
FullName = user.UserName,
|
||||
RealName = user.RealName,
|
||||
UserTypeEnum=user.UserTypeEnum,
|
||||
UserTypeId=user.UserTypeId,
|
||||
IsTestUser=user.IsTestUser,
|
||||
UserTypeEnum = user.UserTypeEnum,
|
||||
UserTypeId = user.UserTypeId,
|
||||
IsTestUser = user.IsTestUser,
|
||||
Code = user.Code,
|
||||
PermissionStr = user.PermissionStr,
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace IRaCIS.Core.Application.Auth
|
||||
{
|
||||
Id = doctor.Id,
|
||||
FullName = doctor.FirstName + doctor.LastName,
|
||||
Phone = doctor.Phone,
|
||||
Phone = doctor.Phone,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IRaCIS.Core.Application.Auth
|
||||
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";
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using System.Text;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
namespace IRaCIS.Core.Application.Auth
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace IRaCIS.Core.Application.Auth
|
||||
{
|
||||
@@ -56,5 +56,5 @@ namespace IRaCIS.Core.Application.Auth
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,16 +1,10 @@
|
||||
using Hangfire;
|
||||
using Hangfire.Storage;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Core.Application.Service;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
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
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
using IRaCIS.Core.Infra.EFCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace IRaCIS.Core.Application.BackGroundJob
|
||||
{
|
||||
public interface IObtainTaskAutoCancelJob
|
||||
{
|
||||
Task CancelQCObtaion(Guid subjectVisitId,DateTime startTime);
|
||||
Task CancelQCObtaion(Guid subjectVisitId, DateTime startTime);
|
||||
}
|
||||
|
||||
public class ObtainTaskAutoCancelJob : IObtainTaskAutoCancelJob
|
||||
@@ -13,7 +12,7 @@ namespace IRaCIS.Core.Application.BackGroundJob
|
||||
private readonly IRepository<SubjectVisit> _subjectVisitRepository;
|
||||
private readonly ILogger<ObtainTaskAutoCancelJob> _logger;
|
||||
|
||||
public ObtainTaskAutoCancelJob(IRepository<SubjectVisit> subjectVisitRepository, ILogger<ObtainTaskAutoCancelJob> logger)
|
||||
public ObtainTaskAutoCancelJob(IRepository<SubjectVisit> subjectVisitRepository, ILogger<ObtainTaskAutoCancelJob> logger)
|
||||
{
|
||||
_subjectVisitRepository = subjectVisitRepository;
|
||||
_logger = logger;
|
||||
@@ -30,7 +29,7 @@ namespace IRaCIS.Core.Application.BackGroundJob
|
||||
|
||||
var success = await _subjectVisitRepository.SaveChangesAsync();
|
||||
|
||||
_logger.LogWarning($"任务建立时间:{startTime} 取消时间:{DateTime.Now} 取消 受试者访视:{ subjectVisitId }success:{success}");
|
||||
_logger.LogWarning($"任务建立时间:{startTime} 取消时间:{DateTime.Now} 取消 受试者访视:{subjectVisitId}success:{success}");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
using AutoMapper;
|
||||
using IRaCIS.Application.Services.BusinessFilter;
|
||||
using IRaCIS.Core.Infra.EFCore;
|
||||
using IRaCIS.Core.Application.Service.BusinessFilter;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Panda.DynamicWebApi;
|
||||
using Panda.DynamicWebApi.Attributes;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ZiggyCreatures.Caching.Fusion;
|
||||
|
||||
namespace IRaCIS.Core.Application
|
||||
namespace IRaCIS.Core.Application.Service
|
||||
{
|
||||
|
||||
#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.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
namespace IRaCIS.Core.Application.BusinessFilter
|
||||
namespace IRaCIS.Core.Application.BusinessFilter;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 不生效,不知道为啥
|
||||
/// </summary>
|
||||
public class GlobalExceptionHandler : IExceptionHandler
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 不生效,不知道为啥
|
||||
/// </summary>
|
||||
public class GlobalExceptionHandler : IExceptionHandler
|
||||
private readonly ILogger<GlobalExceptionHandler> _logger;
|
||||
public GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger)
|
||||
{
|
||||
this._logger = logger;
|
||||
}
|
||||
public ValueTask<bool> TryHandleAsync(
|
||||
HttpContext httpContext,
|
||||
Exception exception,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
private readonly ILogger<GlobalExceptionHandler> _logger;
|
||||
public GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger)
|
||||
{
|
||||
this._logger = logger;
|
||||
}
|
||||
public ValueTask<bool> TryHandleAsync(
|
||||
HttpContext httpContext,
|
||||
Exception exception,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
|
||||
httpContext.Response.ContentType = "application/json";
|
||||
httpContext.Response.ContentType = "application/json";
|
||||
|
||||
|
||||
var ex = exception;
|
||||
var errorInfo = $"Exception: {ex.Message}[{ex.StackTrace}]" + (ex.InnerException != null ? $" InnerException: {ex.InnerException.Message}[{ex.InnerException.StackTrace}]" : "");
|
||||
var ex = exception;
|
||||
var errorInfo = $"Exception: {ex.Message}[{ex.StackTrace}]" + (ex.InnerException != null ? $" InnerException: {ex.InnerException.Message}[{ex.InnerException.StackTrace}]" : "");
|
||||
|
||||
httpContext.Response.WriteAsJsonAsync(ResponseOutput.NotOk($"{ex?.Message}"));
|
||||
httpContext.Response.WriteAsJsonAsync(ResponseOutput.NotOk($"{ex?.Message}"));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
_logger.LogError(errorInfo);
|
||||
_logger.LogError(errorInfo);
|
||||
|
||||
// return true to signal that this exception is handled
|
||||
return ValueTask.FromResult(false);
|
||||
}
|
||||
// return true to signal that this exception is handled
|
||||
return ValueTask.FromResult(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Newtonsoft.Json;
|
||||
using ZiggyCreatures.Caching.Fusion;
|
||||
|
||||
namespace IRaCIS.Core.Application.Filter;
|
||||
@@ -25,7 +23,7 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter
|
||||
|
||||
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;
|
||||
_userInfo = userInfo;
|
||||
@@ -55,7 +53,7 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter
|
||||
{
|
||||
context.HttpContext.Response.ContentType = "application/json";
|
||||
context.HttpContext.Response.StatusCode = StatusCodes.Status200OK;
|
||||
//---当前请求未从Header/Url取到用户Token,请联系开发者
|
||||
//---当前请求未从Header/Url取到用户Token,请联系开发者
|
||||
//await context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(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.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
|
||||
{
|
||||
@@ -106,7 +104,7 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter
|
||||
//---您的账户在其他地方已登陆,您被迫下线。
|
||||
|
||||
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.Extensions.Localization;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
|
||||
namespace IRaCIS.Core.Application.Filter
|
||||
namespace IRaCIS.Core.Application.Filter;
|
||||
|
||||
|
||||
|
||||
public class ModelActionFilter : ActionFilterAttribute, IActionFilter
|
||||
{
|
||||
|
||||
|
||||
public class ModelActionFilter : ActionFilterAttribute, IActionFilter
|
||||
public IStringLocalizer _localizer;
|
||||
public ModelActionFilter(IStringLocalizer localizer)
|
||||
{
|
||||
public IStringLocalizer _localizer;
|
||||
public ModelActionFilter(IStringLocalizer localizer)
|
||||
{
|
||||
_localizer = localizer;
|
||||
}
|
||||
|
||||
public override void OnActionExecuting(ActionExecutingContext context)
|
||||
{
|
||||
if (!context.ModelState.IsValid)
|
||||
{
|
||||
|
||||
var validationErrors = context.ModelState
|
||||
.Keys
|
||||
.SelectMany(k => context.ModelState[k]!.Errors)
|
||||
.Select(e => e.ErrorMessage)
|
||||
.ToArray();
|
||||
|
||||
//---提供给接口的参数无效。
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ModelAction_InvalidAPIParameter"] + JsonConvert.SerializeObject( validationErrors)));
|
||||
}
|
||||
}
|
||||
_localizer = localizer;
|
||||
}
|
||||
|
||||
public override void OnActionExecuting(ActionExecutingContext context)
|
||||
{
|
||||
if (!context.ModelState.IsValid)
|
||||
{
|
||||
|
||||
var validationErrors = context.ModelState
|
||||
.Keys
|
||||
.SelectMany(k => context.ModelState[k]!.Errors)
|
||||
.Select(e => e.ErrorMessage)
|
||||
.ToArray();
|
||||
|
||||
//---提供给接口的参数无效。
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ModelAction_InvalidAPIParameter"] + JsonConvert.SerializeObject(validationErrors)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,26 @@
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
|
||||
namespace IRaCIS.Core.Application.Filter
|
||||
namespace IRaCIS.Core.Application.Filter;
|
||||
|
||||
#region snippet_DisableFormValueModelBindingAttribute
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
||||
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
|
||||
{
|
||||
#region snippet_DisableFormValueModelBindingAttribute
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
||||
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
|
||||
public void OnResourceExecuting(ResourceExecutingContext context)
|
||||
{
|
||||
public void OnResourceExecuting(ResourceExecutingContext context)
|
||||
{
|
||||
|
||||
|
||||
var factories = context.ValueProviderFactories;
|
||||
//factories.RemoveType<FormValueProviderFactory>();
|
||||
factories.RemoveType<FormFileValueProviderFactory>();
|
||||
factories.RemoveType<JQueryFormValueProviderFactory>();
|
||||
context.HttpContext.Request.EnableBuffering();
|
||||
}
|
||||
|
||||
public void OnResourceExecuted(ResourceExecutedContext context)
|
||||
{
|
||||
}
|
||||
var factories = context.ValueProviderFactories;
|
||||
//factories.RemoveType<FormValueProviderFactory>();
|
||||
factories.RemoveType<FormFileValueProviderFactory>();
|
||||
factories.RemoveType<JQueryFormValueProviderFactory>();
|
||||
context.HttpContext.Request.EnableBuffering();
|
||||
}
|
||||
|
||||
public void OnResourceExecuted(ResourceExecutedContext context)
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -1,77 +1,75 @@
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace IRaCIS.Core.Application.Filter
|
||||
namespace IRaCIS.Core.Application.Filter;
|
||||
|
||||
public class ProjectExceptionFilter : Attribute, IExceptionFilter
|
||||
{
|
||||
public class ProjectExceptionFilter : Attribute, IExceptionFilter
|
||||
private readonly ILogger<ProjectExceptionFilter> _logger;
|
||||
|
||||
public IStringLocalizer _localizer;
|
||||
|
||||
public ProjectExceptionFilter(IStringLocalizer localizer, ILogger<ProjectExceptionFilter> logger)
|
||||
{
|
||||
private readonly ILogger<ProjectExceptionFilter> _logger;
|
||||
_logger = logger;
|
||||
_localizer = localizer;
|
||||
}
|
||||
public void OnException(ExceptionContext context)
|
||||
{
|
||||
//context.ExceptionHandled;//记录当前这个异常是否已经被处理过了
|
||||
|
||||
public IStringLocalizer _localizer;
|
||||
|
||||
public ProjectExceptionFilter(IStringLocalizer localizer, ILogger<ProjectExceptionFilter> logger)
|
||||
if (!context.ExceptionHandled)
|
||||
{
|
||||
_logger = logger;
|
||||
_localizer = localizer;
|
||||
}
|
||||
public void OnException(ExceptionContext context)
|
||||
{
|
||||
//context.ExceptionHandled;//记录当前这个异常是否已经被处理过了
|
||||
|
||||
if (!context.ExceptionHandled)
|
||||
if (context.Exception.GetType().Name == "DbUpdateConcurrencyException")
|
||||
{
|
||||
if (context.Exception.GetType().Name == "DbUpdateConcurrencyException")
|
||||
//---并发更新,当前不允许该操作
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ProjectException_ConcurrentUpdateNotAllowed"] + context.Exception.Message));
|
||||
}
|
||||
|
||||
if (context.Exception.GetType() == typeof(BusinessValidationFailedException))
|
||||
{
|
||||
var error = context.Exception as BusinessValidationFailedException;
|
||||
|
||||
var info = string.Empty;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(error!.LocalizedKey) && StaticData.Log_Locoalize_Dic.ContainsKey(error!.LocalizedKey))
|
||||
{
|
||||
//---并发更新,当前不允许该操作
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ProjectException_ConcurrentUpdateNotAllowed"] + context.Exception.Message));
|
||||
info = $"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}";
|
||||
}
|
||||
|
||||
if (context.Exception.GetType() == typeof(BusinessValidationFailedException))
|
||||
{
|
||||
var error = context.Exception as BusinessValidationFailedException;
|
||||
|
||||
var info = string.Empty;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(error!.LocalizedKey) && StaticData.Log_Locoalize_Dic.ContainsKey(error!.LocalizedKey))
|
||||
{
|
||||
info = $"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}";
|
||||
}
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, "", error!.Code, localizedInfo: info));
|
||||
|
||||
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, "", error!.Code, localizedInfo: info));
|
||||
|
||||
|
||||
//warning 级别记录
|
||||
//_logger.LogWarning($"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}");
|
||||
}
|
||||
else if (context.Exception.GetType() == typeof(QueryBusinessObjectNotExistException))
|
||||
{
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, ApiResponseCodeEnum.DataNotExist));
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (context.Exception.InnerException is null ? (context.Exception.Message /*+ context.Exception.StackTrace*/)
|
||||
: (context.Exception.InnerException?.Message /*+ context.Exception.InnerException?.StackTrace*/)), ApiResponseCodeEnum.ProgramException));
|
||||
|
||||
_logger.LogError(context.Exception.InnerException is null ? (context.Exception.Message + context.Exception.StackTrace) : (context.Exception.InnerException?.Message + context.Exception.InnerException?.StackTrace));
|
||||
|
||||
}
|
||||
|
||||
context.ExceptionHandled = true;//标记当前异常已经被处理过了
|
||||
|
||||
|
||||
//throw new Exception("test-result-exceptioin");
|
||||
|
||||
//warning 级别记录
|
||||
//_logger.LogWarning($"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}");
|
||||
}
|
||||
else if (context.Exception.GetType() == typeof(QueryBusinessObjectNotExistException))
|
||||
{
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, ApiResponseCodeEnum.DataNotExist));
|
||||
}
|
||||
else
|
||||
{
|
||||
//继续
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (context.Exception.InnerException is null ? (context.Exception.Message /*+ context.Exception.StackTrace*/)
|
||||
: (context.Exception.InnerException?.Message /*+ context.Exception.InnerException?.StackTrace*/)), ApiResponseCodeEnum.ProgramException));
|
||||
|
||||
_logger.LogError(context.Exception.InnerException is null ? (context.Exception.Message + context.Exception.StackTrace) : (context.Exception.InnerException?.Message + context.Exception.InnerException?.StackTrace));
|
||||
|
||||
}
|
||||
|
||||
context.ExceptionHandled = true;//标记当前异常已经被处理过了
|
||||
|
||||
|
||||
//throw new Exception("test-result-exceptioin");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//继续
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,174 +8,189 @@ using System.Text.RegularExpressions;
|
||||
using ZiggyCreatures.Caching.Fusion;
|
||||
using static IRaCIS.Core.Domain.Share.StaticData;
|
||||
|
||||
namespace IRaCIS.Core.Application.Filter
|
||||
namespace IRaCIS.Core.Application.Filter;
|
||||
|
||||
/// <summary>
|
||||
/// 主要为了 处理项目结束 锁库,不允许操作
|
||||
/// </summary>
|
||||
public class TrialResourceFilter : Attribute, IAsyncResourceFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// 主要为了 处理项目结束 锁库,不允许操作
|
||||
/// </summary>
|
||||
public class TrialResourceFilter : Attribute, IAsyncResourceFilter
|
||||
private readonly IUserInfo _userInfo;
|
||||
private readonly IFusionCache _fusionCache;
|
||||
public IStringLocalizer _localizer;
|
||||
private readonly IRepository<Trial> _trialRepository;
|
||||
private readonly List<string> _trialOptList = new List<string>();
|
||||
|
||||
|
||||
public TrialResourceFilter(IFusionCache fusionCache, IRepository<Trial> trialRepository, IStringLocalizer localizer, IUserInfo userInfo, string trialOpt = null, string trialOpt2 = null, string trialOpt3 = null)
|
||||
{
|
||||
private readonly IUserInfo _userInfo;
|
||||
private readonly IFusionCache _fusionCache;
|
||||
public IStringLocalizer _localizer;
|
||||
private readonly IRepository<Trial> _trialRepository;
|
||||
private readonly List<string> _trialOptList = new List<string>();
|
||||
_fusionCache = fusionCache;
|
||||
_userInfo = userInfo;
|
||||
_localizer = localizer;
|
||||
_trialRepository = trialRepository;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(trialOpt)) _trialOptList.Add(trialOpt.Trim());
|
||||
if (!string.IsNullOrWhiteSpace(trialOpt2)) _trialOptList.Add(trialOpt2.Trim());
|
||||
if (!string.IsNullOrWhiteSpace(trialOpt3)) _trialOptList.Add(trialOpt3.Trim());
|
||||
|
||||
public TrialResourceFilter(IFusionCache fusionCache, IRepository<Trial> trialRepository, IStringLocalizer localizer, IUserInfo userInfo, string trialOpt = null, string trialOpt2 = null, string trialOpt3 = null)
|
||||
}
|
||||
|
||||
//优先选择异步的方法
|
||||
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
|
||||
{
|
||||
// var typeFilter = context.ActionDescriptor.EndpointMetadata.Where(t => t.GetType() == typeof(TypeFilterAttribute)).Select(t => (TypeFilterAttribute)t).ToList().FirstOrDefault();
|
||||
//var _trialOptList= typeFilter.Arguments.Select(t => t.ToString()).ToList();
|
||||
|
||||
// 获取当前请求的 Host 信息
|
||||
var requestHost = context.HttpContext.Request.Host;
|
||||
|
||||
// 检查请求是否来自 localhost:6100
|
||||
if (requestHost.Host == "localhost" && (requestHost.Port == 6100|| requestHost.Port==3305))
|
||||
{
|
||||
_fusionCache = fusionCache;
|
||||
_userInfo = userInfo;
|
||||
_localizer = localizer;
|
||||
_trialRepository = trialRepository;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(trialOpt)) _trialOptList.Add(trialOpt.Trim());
|
||||
if (!string.IsNullOrWhiteSpace(trialOpt2)) _trialOptList.Add(trialOpt2.Trim());
|
||||
if (!string.IsNullOrWhiteSpace(trialOpt3)) _trialOptList.Add(trialOpt3.Trim());
|
||||
await next.Invoke();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//优先选择异步的方法
|
||||
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
|
||||
#region 处理新的用户类型,不能操作项目相关接口
|
||||
|
||||
// 后期列举出具体的类型,其他任何用户类型,都不允许操作
|
||||
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;
|
||||
}
|
||||
|
||||
// 后期列举出具体的类型,其他任何用户类型,都不允许操作
|
||||
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower() != "TrialDocument/userConfirm".ToLower())
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
//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)
|
||||
{
|
||||
//---对不起,您的账户没有操作权限。
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"]));
|
||||
|
||||
return;
|
||||
trialIdStr = matchResult.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
else
|
||||
{
|
||||
#region body 中取数据
|
||||
|
||||
//设置可以多次读
|
||||
context.HttpContext.Request.EnableBuffering();
|
||||
var reader = new StreamReader(context.HttpContext.Request.Body);
|
||||
var contentFromBody = await reader.ReadToEndAsync();
|
||||
//读取后,流的位置还原
|
||||
context.HttpContext.Request.Body.Seek(0, SeekOrigin.Begin);
|
||||
//context.HttpContext.Request.Body.Position = 0;
|
||||
|
||||
//找到参数位置在字符串中的索引
|
||||
var trialIdIndex = contentFromBody.IndexOf("\"TrialId\"", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
//TrialId 传递的途径多种,可能在path 可能在body 可能在数组中,也可能在对象中,可能就在url
|
||||
var trialIdStr = string.Empty;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(context.HttpContext.Request.Query["trialId"]))
|
||||
if (trialIdIndex > -1)
|
||||
{
|
||||
trialIdStr = context.HttpContext.Request.Query["trialId"];
|
||||
}
|
||||
// (?<="trialId" *: *").*?(?=",)
|
||||
|
||||
//先尝试从path中取TrialId
|
||||
else if (context.RouteData.Values.Keys.Any(t => t.Contains("trialId")))
|
||||
{
|
||||
var index = context.RouteData.Values.Keys.ToList().IndexOf("trialId");
|
||||
trialIdStr = context.RouteData.Values.Values.ToList()[index] as string;
|
||||
}
|
||||
else if (context.HttpContext.Request.Headers["Referer"].ToString().Contains("trialId"))
|
||||
{
|
||||
var headerStr = context.HttpContext.Request.Headers["Referer"].ToString();
|
||||
//使用正则 [0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}
|
||||
|
||||
var trialIdIndex = headerStr.IndexOf("trialId");
|
||||
|
||||
|
||||
var matchResult = Regex.Match(headerStr.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
|
||||
var matchResult = Regex.Match(contentFromBody.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
|
||||
|
||||
if (matchResult.Success)
|
||||
{
|
||||
//有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下
|
||||
|
||||
trialIdStr = matchResult.Value;
|
||||
|
||||
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(trialStatusStr))
|
||||
{
|
||||
|
||||
//数据库 检查该项目Id不对
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
#region body 中取数据
|
||||
|
||||
//设置可以多次读
|
||||
context.HttpContext.Request.EnableBuffering();
|
||||
var reader = new StreamReader(context.HttpContext.Request.Body);
|
||||
var contentFromBody = await reader.ReadToEndAsync();
|
||||
//读取后,流的位置还原
|
||||
context.HttpContext.Request.Body.Seek(0, SeekOrigin.Begin);
|
||||
//context.HttpContext.Request.Body.Position = 0;
|
||||
|
||||
//找到参数位置在字符串中的索引
|
||||
var trialIdIndex = contentFromBody.IndexOf("\"TrialId\"", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
if (trialIdIndex > -1)
|
||||
{
|
||||
// (?<="trialId" *: *").*?(?=",)
|
||||
|
||||
//使用正则 [0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}
|
||||
|
||||
var matchResult = Regex.Match(contentFromBody.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
|
||||
|
||||
if (matchResult.Success)
|
||||
{
|
||||
//有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下
|
||||
|
||||
trialIdStr = matchResult.Value;
|
||||
|
||||
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(trialStatusStr))
|
||||
{
|
||||
//数据库 检查该项目Id不对
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||
}
|
||||
|
||||
//使用字符串取 如果是swagger 可能有时取的不对 因为空格的原因
|
||||
//trialIdStr = contentFromBody.Substring(trialIdIndex + "TrialId".Length + 4, 3
|
||||
}
|
||||
|
||||
#endregion
|
||||
//使用字符串取 如果是swagger 可能有时取的不对 因为空格的原因
|
||||
//trialIdStr = contentFromBody.Substring(trialIdIndex + "TrialId".Length + 4, 3
|
||||
}
|
||||
|
||||
//通过path 或者body 找到trialId 了
|
||||
if (!string.IsNullOrWhiteSpace(trialIdStr))
|
||||
#endregion
|
||||
}
|
||||
|
||||
//通过path 或者body 找到trialId 了
|
||||
if (!string.IsNullOrWhiteSpace(trialIdStr))
|
||||
{
|
||||
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
|
||||
|
||||
// 这里是统一拦截 项目有关的操作允许情况(特殊的地方,比如项目配置(有的在多种状态(初始化,ongoing)都可以操作,有的仅仅在Initializing)还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口)
|
||||
if (trialStatusStr == StaticData.TrialState.TrialOngoing || _trialOptList.Any(t => t == TrialOpt.BeforeOngoingCantOpt))
|
||||
{
|
||||
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
|
||||
|
||||
// 这里是统一拦截 项目有关的操作允许情况(特殊的地方,比如项目配置(有的在多种状态(初始化,ongoing)都可以操作,有的仅仅在Initializing)还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口)
|
||||
if (trialStatusStr == StaticData.TrialState.TrialOngoing || _trialOptList.Any(t => t == TrialOpt.BeforeOngoingCantOpt))
|
||||
{
|
||||
|
||||
await next.Invoke();
|
||||
|
||||
}
|
||||
// 项目停止、或者完成 不允许操作
|
||||
else
|
||||
{
|
||||
//---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_InterceptedProjectStatusRule"]));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
//添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截
|
||||
else if (_trialOptList.Any(t => t == TrialOpt.AddOrUpdateTrial || t == TrialOpt.SignSystemDocNoTrialId))
|
||||
{
|
||||
await next.Invoke();
|
||||
}
|
||||
|
||||
}
|
||||
// 项目停止、或者完成 不允许操作
|
||||
else
|
||||
{
|
||||
//如果项目相关接口没有传递trialId 会来到这里,提醒,以便修改
|
||||
//---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_InterceptedProjectStatusRule"]));
|
||||
|
||||
//---该接口参数中,没有传递项目编号,请核对。
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_MissingProjectNumber"]));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
//添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截
|
||||
else if (_trialOptList.Any(t => t == TrialOpt.AddOrUpdateTrial || t == TrialOpt.SignSystemDocNoTrialId))
|
||||
{
|
||||
await next.Invoke();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
//如果项目相关接口没有传递trialId 会来到这里,提醒,以便修改
|
||||
|
||||
//---该接口参数中,没有传递项目编号,请核对。
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_MissingProjectNumber"]));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,123 +1,122 @@
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
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>
|
||||
/// 统一返回前端数据包装,之前在控制器包装,现在修改为动态Api 在ResultFilter这里包装,减少重复冗余代码
|
||||
/// by zhouhang 2021.09.12 周末
|
||||
/// </summary>
|
||||
public class UnifiedApiResultFilter : Attribute, IAsyncResultFilter
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public UnifiedApiResultFilter(ILogger<UnifiedApiResultFilter> logger)
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public UnifiedApiResultFilter(ILogger<UnifiedApiResultFilter> logger)
|
||||
/// <summary>
|
||||
/// 异步版本
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="next"></param>
|
||||
/// <returns></returns>
|
||||
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
|
||||
{
|
||||
|
||||
if (context.Result is ObjectResult objectResult)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
var statusCode = objectResult.StatusCode ?? context.HttpContext.Response.StatusCode;
|
||||
|
||||
/// <summary>
|
||||
/// 异步版本
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="next"></param>
|
||||
/// <returns></returns>
|
||||
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
|
||||
{
|
||||
|
||||
if (context.Result is ObjectResult objectResult)
|
||||
//是200 并且没有包装 那么包装结果
|
||||
if (statusCode == 200 && !(objectResult.Value is IResponseOutput))
|
||||
{
|
||||
var statusCode = objectResult.StatusCode ?? context.HttpContext.Response.StatusCode;
|
||||
|
||||
//是200 并且没有包装 那么包装结果
|
||||
if (statusCode == 200 && !(objectResult.Value is IResponseOutput))
|
||||
var type = objectResult.Value?.GetType();
|
||||
|
||||
|
||||
if (type != null && type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(ValueTuple<,>) || type.GetGenericTypeDefinition() == typeof(Tuple<,>)))
|
||||
{
|
||||
|
||||
var type = objectResult.Value?.GetType();
|
||||
|
||||
|
||||
if (type != null && type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(ValueTuple<,>) || type.GetGenericTypeDefinition() == typeof(Tuple<,>)))
|
||||
{
|
||||
|
||||
//报错
|
||||
//var tuple = (object, object))objectResult.Value;
|
||||
//var (val1, val2) = ((dynamic, dynamic))objectResult.Value;
|
||||
//var apiResponse = ResponseOutput.Ok(val1, val2);
|
||||
|
||||
//OK
|
||||
var tuple = (dynamic)objectResult.Value;
|
||||
var apiResponse = ResponseOutput.Ok(tuple!.Item1, tuple!.Item2);
|
||||
|
||||
|
||||
objectResult.Value = apiResponse;
|
||||
objectResult.DeclaredType = apiResponse.GetType();
|
||||
}
|
||||
else
|
||||
{
|
||||
var apiResponse = ResponseOutput.Ok(objectResult.Value);
|
||||
|
||||
objectResult.Value = apiResponse;
|
||||
objectResult.DeclaredType = apiResponse.GetType();
|
||||
}
|
||||
//报错
|
||||
//var tuple = (object, object))objectResult.Value;
|
||||
//var (val1, val2) = ((dynamic, dynamic))objectResult.Value;
|
||||
//var apiResponse = ResponseOutput.Ok(val1, val2);
|
||||
|
||||
//OK
|
||||
var tuple = (dynamic)objectResult.Value;
|
||||
var apiResponse = ResponseOutput.Ok(tuple!.Item1, tuple!.Item2);
|
||||
|
||||
|
||||
objectResult.Value = apiResponse;
|
||||
objectResult.DeclaredType = apiResponse.GetType();
|
||||
}
|
||||
//如果是200 是IResponseOutput 记录下日志
|
||||
else if (statusCode == 200 && (objectResult.Value is IResponseOutput))
|
||||
else
|
||||
{
|
||||
var result = objectResult.Value as IResponseOutput;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(result.LocalizedInfo))
|
||||
{
|
||||
//统一在这里记录国际化的日志信息
|
||||
_logger.LogWarning($"{result.LocalizedInfo}");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else if (statusCode != 200 && !(objectResult.Value is IResponseOutput))
|
||||
{
|
||||
//---程序错误,请联系开发人员。
|
||||
var apiResponse = ResponseOutput.NotOk(StaticData.International("UnifiedAPI_ProgramError"));
|
||||
var apiResponse = ResponseOutput.Ok(objectResult.Value);
|
||||
|
||||
objectResult.Value = apiResponse;
|
||||
objectResult.DeclaredType = apiResponse.GetType();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
await next.Invoke();
|
||||
|
||||
}
|
||||
|
||||
public static bool IsTupleType(Type type, bool checkBaseTypes = false)
|
||||
{
|
||||
if (type == null)
|
||||
throw new ArgumentNullException(nameof(type));
|
||||
|
||||
if (type == typeof(Tuple))
|
||||
return true;
|
||||
|
||||
while (type != null)
|
||||
//如果是200 是IResponseOutput 记录下日志
|
||||
else if (statusCode == 200 && (objectResult.Value is IResponseOutput))
|
||||
{
|
||||
if (type.IsGenericType)
|
||||
var result = objectResult.Value as IResponseOutput;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(result.LocalizedInfo))
|
||||
{
|
||||
var genType = type.GetGenericTypeDefinition();
|
||||
if (genType == typeof(Tuple<>)
|
||||
|| genType == typeof(Tuple<,>)
|
||||
|| genType == typeof(Tuple<,>))
|
||||
return true;
|
||||
//统一在这里记录国际化的日志信息
|
||||
_logger.LogWarning($"{result.LocalizedInfo}");
|
||||
}
|
||||
|
||||
if (!checkBaseTypes)
|
||||
break;
|
||||
|
||||
type = type.BaseType;
|
||||
}
|
||||
|
||||
return false;
|
||||
else if (statusCode != 200 && !(objectResult.Value is IResponseOutput))
|
||||
{
|
||||
//---程序错误,请联系开发人员。
|
||||
var apiResponse = ResponseOutput.NotOk(StaticData.International("UnifiedAPI_ProgramError"));
|
||||
|
||||
objectResult.Value = apiResponse;
|
||||
objectResult.DeclaredType = apiResponse.GetType();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
await next.Invoke();
|
||||
|
||||
}
|
||||
|
||||
public static bool IsTupleType(Type type, bool checkBaseTypes = false)
|
||||
{
|
||||
if (type == null)
|
||||
throw new ArgumentNullException(nameof(type));
|
||||
|
||||
if (type == typeof(Tuple))
|
||||
return true;
|
||||
|
||||
while (type != null)
|
||||
{
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
var genType = type.GetGenericTypeDefinition();
|
||||
if (genType == typeof(Tuple<>)
|
||||
|| genType == typeof(Tuple<,>)
|
||||
|| genType == typeof(Tuple<,>))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!checkBaseTypes)
|
||||
break;
|
||||
|
||||
type = type.BaseType;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
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;
|
||||
|
||||
@@ -33,7 +28,7 @@ namespace IRaCIS.Core.Application.Helper
|
||||
}
|
||||
|
||||
//针对不同的标准 翻译的字典不一样
|
||||
public DictionaryTranslateAttribute(string dicParentCode, CriterionType criterionType )
|
||||
public DictionaryTranslateAttribute(string dicParentCode, CriterionType criterionType)
|
||||
{
|
||||
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;
|
||||
|
||||
|
||||
@@ -1,75 +1,69 @@
|
||||
using IRaCIS.Core.Domain.Models;
|
||||
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
|
||||
|
||||
public static class CacheKeys
|
||||
{
|
||||
//项目缓存
|
||||
public static string Trial(string trialIdStr) => $"TrialId:{trialIdStr}";
|
||||
|
||||
public static class CacheKeys
|
||||
//检查编号递增锁
|
||||
public static string TrialStudyMaxCode(Guid trialId) => $"TrialStudyMaxCode:{trialId}";
|
||||
|
||||
public static string TrialStudyUidUploading(Guid trialId, string studyUid) => $"TrialStudyUid:{trialId}_{studyUid}";
|
||||
//CRC上传影像提交锁key
|
||||
public static string TrialStudyUidDBLock(Guid trialId, string studyUid) => $"TrialStudyUidDBLock:{trialId}_{studyUid}";
|
||||
|
||||
public static string TrialTaskStudyUidUploading(Guid trialId, Guid visiTaskId, string studyUid) => $"TrialStudyUid:{trialId}_{visiTaskId}_{studyUid}";
|
||||
//影像后处理上传提交锁key
|
||||
public static string TrialTaskStudyUidDBLock(Guid trialId, Guid visiTaskId, string studyUid) => $"TrialTaskStudyUidDBLock:{trialId}_{visiTaskId}_{studyUid}";
|
||||
//系统匿名化
|
||||
public static string SystemAnonymization => $"SystemAnonymization";
|
||||
//前端国际化
|
||||
public static string FrontInternational => $"FrontInternationalList";
|
||||
|
||||
//登录挤账号
|
||||
public static string UserToken(Guid userId) => $"UserToken:{userId}";
|
||||
|
||||
//超时没请求接口自动退出
|
||||
public static string UserAutoLoginOut(Guid userId) => $"UserAutoLoginOut:{userId}";
|
||||
|
||||
/// <summary>
|
||||
/// 跳过阅片
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
public static string SkipReadingCacheKey(Guid userId) => $"{userId}SkipReadingCache";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 开始阅片时间
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
public static string StartReadingTimeKey(Guid userId) => $"{userId}StartReadingTime";
|
||||
|
||||
/// <summary>
|
||||
/// 开始休息时间
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
public static string StartRestTime(Guid userId) => $"{userId}StartRestTime";
|
||||
|
||||
}
|
||||
|
||||
public static class CacheHelper
|
||||
{
|
||||
public static async Task<string?> GetTrialStatusAsync(Guid trialId, IRepository<Trial> _trialRepository)
|
||||
{
|
||||
public static string Trial(string trialIdStr) => $"TrialId:{trialIdStr}";
|
||||
|
||||
public static string TrialStudyMaxCode(Guid trialId) => $"TrialStudyMaxCode:{trialId}";
|
||||
|
||||
public static string TrialStudyUidUploading(Guid trialId, string studyUid) => $"TrialStudyUid:{trialId}_{studyUid}";
|
||||
|
||||
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";
|
||||
var statusStr = await _trialRepository.Where(t => t.Id == trialId, ignoreQueryFilters: true).Select(t => t.TrialStatusStr).FirstOrDefaultAsync();
|
||||
|
||||
return statusStr;
|
||||
}
|
||||
|
||||
public static class CacheHelper
|
||||
public static async Task<List<SystemAnonymization>> GetSystemAnonymizationListAsync(IRepository<SystemAnonymization> _systemAnonymizationRepository)
|
||||
{
|
||||
public static async Task<string?> GetTrialStatusAsync(Guid trialId, IRepository<Trial> _trialRepository)
|
||||
{
|
||||
var statusStr = await _trialRepository.Where(t => t.Id == trialId, ignoreQueryFilters: true).Select(t => t.TrialStatusStr).FirstOrDefaultAsync();
|
||||
var list = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
|
||||
|
||||
return statusStr;
|
||||
}
|
||||
|
||||
public static async Task<List<SystemAnonymization>> GetSystemAnonymizationListAsync(IRepository<SystemAnonymization> _systemAnonymizationRepository)
|
||||
{
|
||||
var list = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
|
||||
|
||||
return list;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,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 DocumentFormat.OpenXml.Spreadsheet;
|
||||
using DocumentFormat.OpenXml.Wordprocessing;
|
||||
using IRaCIS.Application.Contracts;
|
||||
using IRaCIS.Application.Contracts;
|
||||
using IRaCIS.Application.Interfaces;
|
||||
using IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using MiniExcelLibs;
|
||||
using MiniExcelLibs.OpenXml;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NPOI.HSSF.UserModel;
|
||||
using NPOI.SS.Formula.Functions;
|
||||
using NPOI.SS.UserModel;
|
||||
using NPOI.XSSF.UserModel;
|
||||
using System.Collections;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
|
||||
namespace IRaCIS.Core.Application.Service;
|
||||
|
||||
public static class ExcelExportHelper
|
||||
{
|
||||
//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)
|
||||
{
|
||||
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))
|
||||
{
|
||||
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.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace IRaCIS.Core.Application.Helper
|
||||
namespace IRaCIS.Core.Application.Helper;
|
||||
|
||||
public class FileConvertHelper
|
||||
{
|
||||
public class FileConvertHelper
|
||||
|
||||
|
||||
static public void ConvertWordToPdf(string inputWordFilePath, string outputPdfDir)
|
||||
{
|
||||
// 设置 libreoffice 命令行参数
|
||||
string arguments = $"--headless --invisible --convert-to pdf \"{inputWordFilePath}\" --outdir \"{outputPdfDir}\"";
|
||||
|
||||
|
||||
static public void ConvertWordToPdf(string inputWordFilePath, string outputPdfDir)
|
||||
// 启动 libreoffice 进程
|
||||
using (Process process = new Process())
|
||||
{
|
||||
// 设置 libreoffice 命令行参数
|
||||
string arguments = $"--headless --invisible --convert-to pdf \"{inputWordFilePath}\" --outdir \"{outputPdfDir}\"";
|
||||
process.StartInfo.FileName = "libreoffice";
|
||||
process.StartInfo.Arguments = arguments;
|
||||
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
||||
process.StartInfo.RedirectStandardOutput = true;
|
||||
process.StartInfo.RedirectStandardError = true;
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
process.StartInfo.CreateNoWindow = true;
|
||||
|
||||
// 启动 libreoffice 进程
|
||||
using (Process process = new Process())
|
||||
{
|
||||
process.StartInfo.FileName = "libreoffice";
|
||||
process.StartInfo.Arguments = arguments;
|
||||
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
||||
process.StartInfo.RedirectStandardOutput = true;
|
||||
process.StartInfo.RedirectStandardError = true;
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
process.StartInfo.CreateNoWindow = true;
|
||||
process.Start();
|
||||
|
||||
process.Start();
|
||||
|
||||
// 等待进程结束
|
||||
process.WaitForExit();
|
||||
}
|
||||
// 等待进程结束
|
||||
process.WaitForExit();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
|
||||
|
||||
using Aliyun.OSS;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Configuration;
|
||||
using System.Globalization;
|
||||
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;
|
||||
|
||||
if (isChangeToPdfFormat==false)
|
||||
if (isChangeToPdfFormat == false)
|
||||
{
|
||||
trustedFileNameForFileStorage= Guid.NewGuid().ToString() + fileName;
|
||||
trustedFileNameForFileStorage = Guid.NewGuid().ToString() + fileName;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
trustedFileNameForFileStorage=Guid.NewGuid().ToString() + Path.GetFileNameWithoutExtension(fileName) + ".pdf";
|
||||
trustedFileNameForFileStorage = Guid.NewGuid().ToString() + Path.GetFileNameWithoutExtension(fileName) + ".pdf";
|
||||
}
|
||||
|
||||
return (trustedFileNameForFileStorage, fileName);
|
||||
@@ -57,7 +52,7 @@ public static class FileStoreHelper
|
||||
//API vue 部署目录
|
||||
public static string GetIRaCISRootPath(IWebHostEnvironment _hostEnvironment)
|
||||
{
|
||||
string parentDirectory = Path.GetFullPath(Path.Combine(_hostEnvironment.ContentRootPath, ".."));
|
||||
string parentDirectory = Path.GetFullPath(Path.Combine(_hostEnvironment.ContentRootPath, ".."));
|
||||
|
||||
return parentDirectory;
|
||||
|
||||
@@ -136,10 +131,10 @@ public static class FileStoreHelper
|
||||
{
|
||||
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)
|
||||
{
|
||||
//---数据库没有找到对应的数据模板文件,请联系系统运维人员。
|
||||
//---数据库没有找到对应的数据模板文件,请联系系统运维人员。
|
||||
throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileNotFound"));
|
||||
}
|
||||
|
||||
@@ -147,11 +142,11 @@ public static class FileStoreHelper
|
||||
|
||||
if (!System.IO.File.Exists(filePath))
|
||||
{
|
||||
//---数据模板文件存储路径上未找对应文件,请联系系统运维人员。
|
||||
//---数据模板文件存储路径上未找对应文件,请联系系统运维人员。
|
||||
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 存放路径
|
||||
|
||||
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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
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 切换存储前
|
||||
//var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
||||
#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);
|
||||
}
|
||||
|
||||
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}";
|
||||
|
||||
@@ -260,7 +255,7 @@ public static class FileStoreHelper
|
||||
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();
|
||||
|
||||
@@ -274,7 +269,7 @@ public static class FileStoreHelper
|
||||
{
|
||||
|
||||
//---解析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 IRaCIS.Core.Application.Service;
|
||||
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
|
||||
{
|
||||
@@ -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)
|
||||
@@ -88,5 +78,5 @@ namespace IRaCIS.Core.Application.Helper
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,111 +1,105 @@
|
||||
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
|
||||
{
|
||||
|
||||
#region 对接模型
|
||||
public class HolidayCalendar
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Version { get; set; }
|
||||
public string Generated { get; set; }
|
||||
public string Timezone { get; set; }
|
||||
public string Author { get; set; }
|
||||
public string URL { get; set; }
|
||||
public Dictionary<string, List<HolidayYear>> Years { get; set; }
|
||||
}
|
||||
|
||||
public class HolidayYear
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public DateTime StartDate { get; set; }
|
||||
public DateTime EndDate { get; set; }
|
||||
public int Duration { get; set; }
|
||||
public List<DateTime> CompDays { get; set; }
|
||||
public string URL { get; set; }
|
||||
public string Memo { get; set; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
public class HolidayHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// github 链接:https://github.com/lanceliao/china-holiday-calender?tab=readme-ov-file
|
||||
/// 接口请求参考文档:https://www.koudingke.cn/docs/zh-Hans/net-lib-docs/latest/RestSharp/Usage/Usage
|
||||
/// </summary>
|
||||
private static RestClient _client => new RestClient("https://www.shuyz.com/githubfiles/china-holiday-calender/master/holidayAPI.json");
|
||||
|
||||
private static HolidayCalendar _holidayCalendar { get; set; }
|
||||
|
||||
|
||||
private static List<DateTime> _holidays = new List<DateTime>();
|
||||
private static List<DateTime> _compensatedWorkdays = new List<DateTime>();
|
||||
|
||||
static HolidayHelper()
|
||||
{
|
||||
_holidayCalendar = _client.Get<HolidayCalendar>(new RestRequest()) ?? new HolidayCalendar();
|
||||
|
||||
foreach (var year in _holidayCalendar.Years.Values.SelectMany(x => x))
|
||||
{
|
||||
// 添加节假日到假日集合
|
||||
for (DateTime date = year.StartDate; date <= year.EndDate; date = date.AddDays(1))
|
||||
{
|
||||
_holidays.Add(date);
|
||||
}
|
||||
|
||||
// 添加补班日到补班日集合
|
||||
foreach (var compDay in year.CompDays)
|
||||
{
|
||||
_compensatedWorkdays.Add(compDay);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static TimeSpan GetChinaWorkTimeSpan(DateTime startDate, DateTime endDate)
|
||||
{
|
||||
if (startDate > endDate)
|
||||
{
|
||||
throw new ArgumentException("结束日期必须大于或等于开始日期");
|
||||
}
|
||||
|
||||
var diffTimeSpan = endDate - startDate;
|
||||
|
||||
// 初始化工作日数为0
|
||||
int workdays = 0;
|
||||
|
||||
// 找出在给定日期范围内的假期和补班日
|
||||
var filteredHolidays = _holidays.Where(d => d >= startDate && d <= endDate).ToList();
|
||||
var filteredCompensatedWorkdays = _compensatedWorkdays.Where(d => d >= startDate && d <= endDate).ToList();
|
||||
|
||||
// 遍历日期范围,计算工作日 注意 这里是小于
|
||||
for (DateTime date = startDate.Date; date < endDate.Date; date = date.AddDays(1))
|
||||
{
|
||||
// 判断是否为工作日
|
||||
bool isWeekend = date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday;
|
||||
bool isHoliday = filteredHolidays.Contains(date);
|
||||
bool isCompensatedWorkday = filteredCompensatedWorkdays.Contains(date);
|
||||
|
||||
// 如果是补班日,或是平日(非假期,非周末),则算作工作日
|
||||
if (isCompensatedWorkday || (!isWeekend && !isHoliday))
|
||||
{
|
||||
workdays++;
|
||||
}
|
||||
}
|
||||
|
||||
return new TimeSpan(workdays, diffTimeSpan.Hours, diffTimeSpan.Minutes, diffTimeSpan.Seconds);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
public string Name { get; set; }
|
||||
public string Version { get; set; }
|
||||
public string Generated { get; set; }
|
||||
public string Timezone { get; set; }
|
||||
public string Author { get; set; }
|
||||
public string URL { get; set; }
|
||||
public Dictionary<string, List<HolidayYear>> Years { get; set; }
|
||||
}
|
||||
|
||||
public class HolidayYear
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public DateTime StartDate { get; set; }
|
||||
public DateTime EndDate { get; set; }
|
||||
public int Duration { get; set; }
|
||||
public List<DateTime> CompDays { get; set; }
|
||||
public string URL { get; set; }
|
||||
public string Memo { get; set; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
public class HolidayHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// github 链接:https://github.com/lanceliao/china-holiday-calender?tab=readme-ov-file
|
||||
/// 接口请求参考文档:https://www.koudingke.cn/docs/zh-Hans/net-lib-docs/latest/RestSharp/Usage/Usage
|
||||
/// </summary>
|
||||
private static RestClient _client => new RestClient("https://www.shuyz.com/githubfiles/china-holiday-calender/master/holidayAPI.json");
|
||||
|
||||
private static HolidayCalendar _holidayCalendar { get; set; }
|
||||
|
||||
|
||||
private static List<DateTime> _holidays = new List<DateTime>();
|
||||
private static List<DateTime> _compensatedWorkdays = new List<DateTime>();
|
||||
|
||||
static HolidayHelper()
|
||||
{
|
||||
_holidayCalendar = _client.Get<HolidayCalendar>(new RestRequest()) ?? new HolidayCalendar();
|
||||
|
||||
foreach (var year in _holidayCalendar.Years.Values.SelectMany(x => x))
|
||||
{
|
||||
// 添加节假日到假日集合
|
||||
for (DateTime date = year.StartDate; date <= year.EndDate; date = date.AddDays(1))
|
||||
{
|
||||
_holidays.Add(date);
|
||||
}
|
||||
|
||||
// 添加补班日到补班日集合
|
||||
foreach (var compDay in year.CompDays)
|
||||
{
|
||||
_compensatedWorkdays.Add(compDay);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static TimeSpan GetChinaWorkTimeSpan(DateTime startDate, DateTime endDate)
|
||||
{
|
||||
if (startDate > endDate)
|
||||
{
|
||||
throw new ArgumentException("结束日期必须大于或等于开始日期");
|
||||
}
|
||||
|
||||
var diffTimeSpan = endDate - startDate;
|
||||
|
||||
// 初始化工作日数为0
|
||||
int workdays = 0;
|
||||
|
||||
// 找出在给定日期范围内的假期和补班日
|
||||
var filteredHolidays = _holidays.Where(d => d >= startDate && d <= endDate).ToList();
|
||||
var filteredCompensatedWorkdays = _compensatedWorkdays.Where(d => d >= startDate && d <= endDate).ToList();
|
||||
|
||||
// 遍历日期范围,计算工作日 注意 这里是小于
|
||||
for (DateTime date = startDate.Date; date < endDate.Date; date = date.AddDays(1))
|
||||
{
|
||||
// 判断是否为工作日
|
||||
bool isWeekend = date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday;
|
||||
bool isHoliday = filteredHolidays.Contains(date);
|
||||
bool isCompensatedWorkday = filteredCompensatedWorkdays.Contains(date);
|
||||
|
||||
// 如果是补班日,或是平日(非假期,非周末),则算作工作日
|
||||
if (isCompensatedWorkday || (!isWeekend && !isHoliday))
|
||||
{
|
||||
workdays++;
|
||||
}
|
||||
}
|
||||
|
||||
return new TimeSpan(workdays, diffTimeSpan.Hours, diffTimeSpan.Minutes, diffTimeSpan.Seconds);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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 SixLabors.ImageSharp.Formats.Jpeg;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Formats.Jpeg;
|
||||
using SixLabors.ImageSharp.Processing;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace IRaCIS.Core.Application.Helper;
|
||||
|
||||
|
||||
@@ -4,211 +4,204 @@ using IRaCIS.Core.Infrastructure;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Newtonsoft.Json;
|
||||
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);
|
||||
|
||||
public static FileSystemWatcher FileSystemWatcher_US { get; set; }
|
||||
public static FileSystemWatcher FileSystemWatcher_CN { get; set; }
|
||||
|
||||
private static void VerifyFolder()
|
||||
if (!Directory.Exists(JsonFileFolder) ||
|
||||
!Directory.GetFiles(JsonFileFolder).Any(filePath => Path.GetExtension(filePath).Equals(".json", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
if (!Directory.Exists(JsonFileFolder) ||
|
||||
!Directory.GetFiles(JsonFileFolder).Any(filePath => Path.GetExtension(filePath).Equals(".json", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
throw new BusinessValidationFailedException("国际化Json文件目录有误");
|
||||
}
|
||||
throw new BusinessValidationFailedException("国际化Json文件目录有误");
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task BatchAddJsonKeyValueAsync(List<BatchAddInternationalizationDto> batchAddDtos)
|
||||
public static async Task BatchAddJsonKeyValueAsync(List<BatchAddInternationalizationDto> batchAddDtos)
|
||||
{
|
||||
VerifyFolder();
|
||||
|
||||
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
|
||||
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
|
||||
|
||||
|
||||
//更新json 文件 同时更新内存缓存的数据
|
||||
foreach (var filePath in new string[] { usJsonPath, cnJsonPath })
|
||||
{
|
||||
VerifyFolder();
|
||||
var json = await File.ReadAllTextAsync(filePath);
|
||||
|
||||
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
|
||||
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
|
||||
JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
|
||||
|
||||
// 添加或更新指定的键值对
|
||||
|
||||
//更新json 文件 同时更新内存缓存的数据
|
||||
foreach (var filePath in new string[] { usJsonPath, cnJsonPath })
|
||||
if (filePath.Contains(StaticData.En_US_Json))
|
||||
{
|
||||
var json = await File.ReadAllTextAsync(filePath);
|
||||
|
||||
JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
|
||||
|
||||
// 添加或更新指定的键值对
|
||||
|
||||
if (filePath.Contains(StaticData.En_US_Json))
|
||||
foreach (var item in batchAddDtos)
|
||||
{
|
||||
foreach (var item in batchAddDtos)
|
||||
{
|
||||
jsonObject[item.Code] = item.Value;
|
||||
jsonObject[item.Code] = item.Value;
|
||||
|
||||
StaticData.En_US_Dic[item.Code] = item.Value;
|
||||
|
||||
//日志记录该信息方便自己人看, 返回给客户的是配置的
|
||||
StaticData.Log_Locoalize_Dic[item.Code] = item.Description;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var item in batchAddDtos)
|
||||
{
|
||||
jsonObject[item.Code] = item.Value;
|
||||
|
||||
StaticData.Zh_CN_Dic[item.Code] = item.Value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
await File.WriteAllTextAsync(filePath, jsonObject.ToString());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task AddOrUpdateJsonKeyValueAsync(string key, string value, string valueCN,string description)
|
||||
{
|
||||
|
||||
VerifyFolder();
|
||||
|
||||
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
|
||||
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
|
||||
|
||||
|
||||
//更新json 文件 同时更新内存缓存的数据
|
||||
foreach (var filePath in new string[] { usJsonPath, cnJsonPath })
|
||||
{
|
||||
var json = await File.ReadAllTextAsync(filePath);
|
||||
|
||||
JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
|
||||
|
||||
// 添加或更新指定的键值对
|
||||
|
||||
if (filePath.Contains(StaticData.En_US_Json))
|
||||
{
|
||||
jsonObject[key] = value;
|
||||
|
||||
StaticData.En_US_Dic[key] = value;
|
||||
StaticData.En_US_Dic[item.Code] = item.Value;
|
||||
|
||||
//日志记录该信息方便自己人看, 返回给客户的是配置的
|
||||
StaticData.Log_Locoalize_Dic[key] = description;
|
||||
StaticData.Log_Locoalize_Dic[item.Code] = item.Description;
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var item in batchAddDtos)
|
||||
{
|
||||
jsonObject[key] = valueCN;
|
||||
jsonObject[item.Code] = item.Value;
|
||||
|
||||
StaticData.Zh_CN_Dic[key] = valueCN;
|
||||
StaticData.Zh_CN_Dic[item.Code] = item.Value;
|
||||
}
|
||||
|
||||
|
||||
await File.WriteAllTextAsync(filePath, jsonObject.ToString());
|
||||
|
||||
}
|
||||
|
||||
|
||||
await File.WriteAllTextAsync(filePath, jsonObject.ToString());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task AddOrUpdateJsonKeyValueAsync(string key, string value, string valueCN, string description)
|
||||
{
|
||||
|
||||
VerifyFolder();
|
||||
|
||||
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
|
||||
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
|
||||
|
||||
|
||||
public static async Task InitInternationlizationDataAndWatchJsonFileAsync(IRepository<Internationalization> _internationalizationRepository)
|
||||
//更新json 文件 同时更新内存缓存的数据
|
||||
foreach (var filePath in new string[] { usJsonPath, cnJsonPath })
|
||||
{
|
||||
//查询数据库的数据
|
||||
var toJsonList = await _internationalizationRepository.Where(t => t.InternationalizationType == 1).Select(t => new
|
||||
var json = await File.ReadAllTextAsync(filePath);
|
||||
|
||||
JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
|
||||
|
||||
// 添加或更新指定的键值对
|
||||
|
||||
if (filePath.Contains(StaticData.En_US_Json))
|
||||
{
|
||||
t.Code,
|
||||
t.Value,
|
||||
t.ValueCN,
|
||||
t.Description
|
||||
}).ToListAsync();
|
||||
jsonObject[key] = value;
|
||||
|
||||
//组织成json 文件
|
||||
|
||||
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
|
||||
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
|
||||
|
||||
|
||||
//本地静态文件国际化需要
|
||||
foreach (var tojsonItem in toJsonList)
|
||||
{
|
||||
StaticData.En_US_Dic[tojsonItem.Code] = tojsonItem.Value;
|
||||
StaticData.Zh_CN_Dic[tojsonItem.Code] = tojsonItem.ValueCN;
|
||||
StaticData.En_US_Dic[key] = value;
|
||||
|
||||
//日志记录该信息方便自己人看, 返回给客户的是配置的
|
||||
StaticData.Log_Locoalize_Dic[tojsonItem.Code] = tojsonItem.Description;
|
||||
StaticData.Log_Locoalize_Dic[key] = description;
|
||||
}
|
||||
|
||||
File.WriteAllText(usJsonPath, JsonConvert.SerializeObject(StaticData.En_US_Dic));
|
||||
File.WriteAllText(cnJsonPath, JsonConvert.SerializeObject(StaticData.Zh_CN_Dic));
|
||||
|
||||
|
||||
//监测Json文件变更 实时刷新数据
|
||||
|
||||
if (!File.Exists(usJsonPath) || !File.Exists(cnJsonPath))
|
||||
else
|
||||
{
|
||||
throw new BusinessValidationFailedException(StaticData.International("IRaCISCHangfireJob_FileNotFound"));
|
||||
jsonObject[key] = valueCN;
|
||||
|
||||
StaticData.Zh_CN_Dic[key] = valueCN;
|
||||
}
|
||||
|
||||
|
||||
// //监测Json文件变更 实时刷新数据
|
||||
|
||||
|
||||
FileSystemWatcher_US = new FileSystemWatcher
|
||||
{
|
||||
Path = Path.GetDirectoryName(usJsonPath)!,
|
||||
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
|
||||
Filter = Path.GetFileName(usJsonPath),
|
||||
EnableRaisingEvents = true,
|
||||
|
||||
};
|
||||
// 添加文件更改事件的处理程序
|
||||
FileSystemWatcher_US.Changed += (sender, e) => LoadJsonFile(StaticData.Folder.Resources + "\\" + StaticData.En_US_Json);
|
||||
|
||||
|
||||
FileSystemWatcher_CN = new FileSystemWatcher
|
||||
{
|
||||
Path = Path.GetDirectoryName(cnJsonPath)!,
|
||||
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
|
||||
Filter = Path.GetFileName(cnJsonPath),
|
||||
EnableRaisingEvents = true,
|
||||
|
||||
};
|
||||
FileSystemWatcher_CN.Changed += (sender, e) => LoadJsonFile(StaticData.Folder.Resources + "\\" + StaticData.Zh_CN_Json);
|
||||
await File.WriteAllTextAsync(filePath, jsonObject.ToString());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static void LoadJsonFile(string filePath)
|
||||
{
|
||||
Console.WriteLine("刷新json内存数据");
|
||||
IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile(filePath, false, false);
|
||||
|
||||
IConfigurationRoot enConfiguration = builder.Build();
|
||||
|
||||
foreach (IConfigurationSection section in enConfiguration.GetChildren())
|
||||
{
|
||||
if (filePath.Contains(StaticData.En_US_Json))
|
||||
{
|
||||
StaticData.En_US_Dic[section.Key] = section.Value;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
StaticData.Zh_CN_Dic[section.Key] = section.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static async Task InitInternationlizationDataAndWatchJsonFileAsync(IRepository<Internationalization> _internationalizationRepository)
|
||||
{
|
||||
//查询数据库的数据
|
||||
var toJsonList = await _internationalizationRepository.Where(t => t.InternationalizationType == 1).Select(t => new
|
||||
{
|
||||
t.Code,
|
||||
t.Value,
|
||||
t.ValueCN,
|
||||
t.Description
|
||||
}).ToListAsync();
|
||||
|
||||
//组织成json 文件
|
||||
|
||||
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
|
||||
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
|
||||
|
||||
|
||||
//本地静态文件国际化需要
|
||||
foreach (var tojsonItem in toJsonList)
|
||||
{
|
||||
StaticData.En_US_Dic[tojsonItem.Code] = tojsonItem.Value;
|
||||
StaticData.Zh_CN_Dic[tojsonItem.Code] = tojsonItem.ValueCN;
|
||||
|
||||
//日志记录该信息方便自己人看, 返回给客户的是配置的
|
||||
StaticData.Log_Locoalize_Dic[tojsonItem.Code] = tojsonItem.Description;
|
||||
}
|
||||
|
||||
File.WriteAllText(usJsonPath, JsonConvert.SerializeObject(StaticData.En_US_Dic));
|
||||
File.WriteAllText(cnJsonPath, JsonConvert.SerializeObject(StaticData.Zh_CN_Dic));
|
||||
|
||||
|
||||
//监测Json文件变更 实时刷新数据
|
||||
|
||||
if (!File.Exists(usJsonPath) || !File.Exists(cnJsonPath))
|
||||
{
|
||||
throw new BusinessValidationFailedException(StaticData.International("IRaCISCHangfireJob_FileNotFound"));
|
||||
}
|
||||
|
||||
|
||||
// //监测Json文件变更 实时刷新数据
|
||||
|
||||
|
||||
FileSystemWatcher_US = new FileSystemWatcher
|
||||
{
|
||||
Path = Path.GetDirectoryName(usJsonPath)!,
|
||||
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
|
||||
Filter = Path.GetFileName(usJsonPath),
|
||||
EnableRaisingEvents = true,
|
||||
|
||||
};
|
||||
// 添加文件更改事件的处理程序
|
||||
FileSystemWatcher_US.Changed += (sender, e) => LoadJsonFile(StaticData.Folder.Resources + "\\" + StaticData.En_US_Json);
|
||||
|
||||
|
||||
FileSystemWatcher_CN = new FileSystemWatcher
|
||||
{
|
||||
Path = Path.GetDirectoryName(cnJsonPath)!,
|
||||
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
|
||||
Filter = Path.GetFileName(cnJsonPath),
|
||||
EnableRaisingEvents = true,
|
||||
|
||||
};
|
||||
FileSystemWatcher_CN.Changed += (sender, e) => LoadJsonFile(StaticData.Folder.Resources + "\\" + StaticData.Zh_CN_Json);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static void LoadJsonFile(string filePath)
|
||||
{
|
||||
Console.WriteLine("刷新json内存数据");
|
||||
IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile(filePath, false, false);
|
||||
|
||||
IConfigurationRoot enConfiguration = builder.Build();
|
||||
|
||||
foreach (IConfigurationSection section in enConfiguration.GetChildren())
|
||||
{
|
||||
if (filePath.Contains(StaticData.En_US_Json))
|
||||
{
|
||||
StaticData.En_US_Dic[section.Key] = section.Value;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
StaticData.Zh_CN_Dic[section.Key] = section.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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.Security;
|
||||
using MimeKit;
|
||||
using NPOI.HPSF;
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,101 +1,95 @@
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using NPOI.XWPF.UserModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Xceed.Document.NET;
|
||||
using Xceed.Words.NET;
|
||||
|
||||
namespace IRaCIS.Core.Application.Helper
|
||||
namespace IRaCIS.Core.Application.Helper;
|
||||
|
||||
/// <summary>
|
||||
/// 利用DocX 库 处理word国际化模板
|
||||
/// </summary>
|
||||
public static class WordTempleteHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 利用DocX 库 处理word国际化模板
|
||||
/// </summary>
|
||||
public static class WordTempleteHelper
|
||||
public static void DocX_GetInternationalTempleteStream(string filePath, Stream memoryStream)
|
||||
{
|
||||
public static void DocX_GetInternationalTempleteStream(string filePath, Stream memoryStream)
|
||||
|
||||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
||||
|
||||
using (DocX document = DocX.Load(filePath))
|
||||
{
|
||||
// 查找书签
|
||||
var bookmarkEn_Start = document.Bookmarks.FirstOrDefault(b => b.Name == StaticData.CultureInfo.en_US_bookMark);
|
||||
|
||||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
||||
|
||||
using (DocX document = DocX.Load(filePath))
|
||||
if (bookmarkEn_Start != null)
|
||||
{
|
||||
// 查找书签
|
||||
var bookmarkEn_Start = document.Bookmarks.FirstOrDefault(b => b.Name == StaticData.CultureInfo.en_US_bookMark);
|
||||
// 获取书签的起始位置
|
||||
//int bookmarkCNStartPos = bookmarkCn_Start.Paragraph.StartIndex;
|
||||
|
||||
if (bookmarkEn_Start != null)
|
||||
var bookmarkENStartPos = bookmarkEn_Start.Paragraph.StartIndex;
|
||||
|
||||
// 创建一个要删除段落的列表
|
||||
List<Paragraph> paragraphsToRemove = new List<Paragraph>();
|
||||
|
||||
foreach (var item in document.Paragraphs)
|
||||
{
|
||||
// 获取书签的起始位置
|
||||
//int bookmarkCNStartPos = bookmarkCn_Start.Paragraph.StartIndex;
|
||||
//中文模板在前,英文在后,英文模板,就删除英文之前的,中文模板就删除英文之后的
|
||||
|
||||
var bookmarkENStartPos = bookmarkEn_Start.Paragraph.StartIndex;
|
||||
|
||||
// 创建一个要删除段落的列表
|
||||
List<Paragraph> paragraphsToRemove = new List<Paragraph>();
|
||||
|
||||
foreach (var item in document.Paragraphs)
|
||||
if (isEn_US ? item.EndIndex < bookmarkENStartPos : item.StartIndex >= bookmarkENStartPos)
|
||||
{
|
||||
//中文模板在前,英文在后,英文模板,就删除英文之前的,中文模板就删除英文之后的
|
||||
|
||||
if (isEn_US ? item.EndIndex < bookmarkENStartPos : item.StartIndex >= bookmarkENStartPos)
|
||||
{
|
||||
paragraphsToRemove.Add(item);
|
||||
}
|
||||
paragraphsToRemove.Add(item);
|
||||
}
|
||||
|
||||
foreach (var paragraph in paragraphsToRemove)
|
||||
{
|
||||
document.RemoveParagraph(paragraph);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 保存修改
|
||||
document.SaveAs(memoryStream);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void Npoi_GetInternationalTempleteStream(string filePath, Stream memoryStream)
|
||||
{
|
||||
|
||||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
||||
|
||||
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
XWPFDocument doc = new XWPFDocument(fs);
|
||||
|
||||
// 查找包含指定书签的段落及其索引
|
||||
var bookmarkParagraph = doc.Paragraphs
|
||||
.FirstOrDefault(p => p.GetCTP().GetBookmarkStartList().Any(b => b.name == StaticData.CultureInfo.en_US_bookMark));
|
||||
|
||||
if (bookmarkParagraph != null)
|
||||
foreach (var paragraph in paragraphsToRemove)
|
||||
{
|
||||
int bookmarkIndex = doc.Paragraphs.IndexOf(bookmarkParagraph);
|
||||
|
||||
if (isEn_US)
|
||||
{
|
||||
// 从书签所在段落开始,删除之前的所有段落
|
||||
for (int i = bookmarkIndex - 1; i >= 0; i--)
|
||||
{
|
||||
doc.RemoveBodyElement(i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 删除书签之后的所有段落
|
||||
for (int i = doc.Paragraphs.Count - 1; i >= bookmarkIndex; i--)
|
||||
{
|
||||
doc.RemoveBodyElement(i);
|
||||
}
|
||||
}
|
||||
document.RemoveParagraph(paragraph);
|
||||
}
|
||||
doc.Write(memoryStream);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 保存修改
|
||||
document.SaveAs(memoryStream);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void Npoi_GetInternationalTempleteStream(string filePath, Stream memoryStream)
|
||||
{
|
||||
|
||||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
||||
|
||||
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
XWPFDocument doc = new XWPFDocument(fs);
|
||||
|
||||
// 查找包含指定书签的段落及其索引
|
||||
var bookmarkParagraph = doc.Paragraphs
|
||||
.FirstOrDefault(p => p.GetCTP().GetBookmarkStartList().Any(b => b.name == StaticData.CultureInfo.en_US_bookMark));
|
||||
|
||||
if (bookmarkParagraph != null)
|
||||
{
|
||||
int bookmarkIndex = doc.Paragraphs.IndexOf(bookmarkParagraph);
|
||||
|
||||
if (isEn_US)
|
||||
{
|
||||
// 从书签所在段落开始,删除之前的所有段落
|
||||
for (int i = bookmarkIndex - 1; i >= 0; i--)
|
||||
{
|
||||
doc.RemoveBodyElement(i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 删除书签之后的所有段落
|
||||
for (int i = doc.Paragraphs.Count - 1; i >= bookmarkIndex; i--)
|
||||
{
|
||||
doc.RemoveBodyElement(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
doc.Write(memoryStream);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,21 +19,6 @@
|
||||
</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>
|
||||
<Compile Remove="WebAppConfig.cs" />
|
||||
</ItemGroup>
|
||||
@@ -58,8 +43,10 @@
|
||||
</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="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="FreeSpire.Doc" Version="12.2.0" />
|
||||
<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.Codecs" Version="5.14.5" />
|
||||
<PackageReference Include="IP2Region.Net" Version="2.0.2" />
|
||||
<PackageReference Include="MailKit" Version="4.2.0" />
|
||||
<PackageReference Include="MimeKit" Version="4.2.0" />
|
||||
<PackageReference Include="MailKit" Version="4.7.1.1" />
|
||||
<PackageReference Include="MimeKit" Version="4.7.1" />
|
||||
<PackageReference Include="MiniExcel" Version="1.34.1" />
|
||||
<PackageReference Include="Minio" Version="6.0.3" />
|
||||
<PackageReference Include="MiniWord" Version="0.8.0" />
|
||||
@@ -84,7 +71,6 @@
|
||||
<PackageReference Include="RestSharp" Version="112.0.0" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.5" />
|
||||
<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" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -98,4 +84,8 @@
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Triggers\TempAbandon\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,5 @@
|
||||
using MiniExcelLibs.Attributes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IRaCIS.Core.Application.MassTransit.Command
|
||||
{
|
||||
|
||||
@@ -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 Microsoft.Extensions.Localization;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IRaCIS.Core.Application.MassTransit.Consumer
|
||||
{
|
||||
@@ -286,7 +281,7 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer
|
||||
|
||||
//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
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||
//--------------------------------------------------------------------
|
||||
using System;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using IRaCIS.Application.Contracts;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Newtonsoft.Json;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace IRaCIS.Core.Application.ViewModel
|
||||
{
|
||||
@@ -112,18 +110,19 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
public List<CriterionReadingCategory> CriterionCategoryList =>
|
||||
|
||||
TrialReadingCriterionList.Select(t =>
|
||||
new CriterionReadingCategory() {
|
||||
EnrollId = EnrollId,
|
||||
TrialReadingCriterionId = t.TrialReadingCriterionId,
|
||||
new CriterionReadingCategory()
|
||||
{
|
||||
EnrollId = EnrollId,
|
||||
TrialReadingCriterionId = t.TrialReadingCriterionId,
|
||||
ReadingCategorys = CriterionReadingCategoryList.Where(c => c.TrialReadingCriterionId == t.TrialReadingCriterionId).Select(t => t.ReadingCategory).OrderBy(c => c).ToList()
|
||||
}).ToList();
|
||||
|
||||
|
||||
|
||||
//CriterionReadingCategoryList.Count == 0 ? TrialReadingCriterionList.Select(t => new CriterionReadingCategory() { EnrollId = EnrollId, TrialReadingCriterionId = t.TrialReadingCriterionId }).ToList() :
|
||||
// CriterionReadingCategoryList
|
||||
//.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();
|
||||
//CriterionReadingCategoryList.Count == 0 ? TrialReadingCriterionList.Select(t => new CriterionReadingCategory() { EnrollId = EnrollId, TrialReadingCriterionId = t.TrialReadingCriterionId }).ToList() :
|
||||
// CriterionReadingCategoryList
|
||||
//.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();
|
||||
|
||||
}
|
||||
|
||||
@@ -212,7 +211,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
public class GenerateTaskCommand
|
||||
{
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
|
||||
//针对访视产生任务的 有用
|
||||
public bool IsAssignSubjectToDoctor { get; set; }
|
||||
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
// 生成时间 2022-07-01 15:33:01
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||
//--------------------------------------------------------------------
|
||||
using System;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
@@ -81,7 +79,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
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 class DoctorSelfConsistentSubjectView: ConsistentCommonView
|
||||
public class DoctorSelfConsistentSubjectView : ConsistentCommonView
|
||||
{
|
||||
public string FirstGlobalVisitName { get; set; } = string.Empty;
|
||||
public string? BlindSubjectCode { get; set; }
|
||||
public string? BlindSubjectCode { get; set; }
|
||||
|
||||
public List<VisitTaskSimpleDTO> VisitTaskList { get; set; }
|
||||
|
||||
@@ -130,14 +128,14 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
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<UserSimpleInfo> DoctorUserList { get; set; }=new List<UserSimpleInfo>();
|
||||
public List<UserSimpleInfo> DoctorUserList { get; set; } = new List<UserSimpleInfo>();
|
||||
}
|
||||
|
||||
public class VisitTaskGroupSimpleDTO
|
||||
@@ -175,10 +173,10 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
public bool IsClinicalDataSign { get; set; }
|
||||
}
|
||||
|
||||
public class VisitTaskSimpleDTO :VisitTaskGroupSimpleDTO
|
||||
public class VisitTaskSimpleDTO : VisitTaskGroupSimpleDTO
|
||||
{
|
||||
public Guid? Id { get; set; }
|
||||
|
||||
|
||||
|
||||
public string TaskCode { get; set; }
|
||||
|
||||
@@ -289,7 +287,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
|
||||
public class GetConsistentRuleOut
|
||||
{
|
||||
public TaskConsistentRuleBasic? ConsistentRuleBasic { get; set; }
|
||||
public TaskConsistentRuleBasic? ConsistentRuleBasic { get; set; }
|
||||
/// <summary>
|
||||
/// 任务展示访视 读片任务显示是否顺序
|
||||
/// </summary>
|
||||
@@ -316,7 +314,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
public string VirtualSiteCode { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateTrialSiteCodeCommandView: UpdateTrialSiteCodeCommand
|
||||
public class UpdateTrialSiteCodeCommandView : UpdateTrialSiteCodeCommand
|
||||
{
|
||||
public DateTime Creatime { get; set; }
|
||||
}
|
||||
|
||||
@@ -3,11 +3,8 @@
|
||||
// 生成时间 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 System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace IRaCIS.Core.Application.ViewModel
|
||||
{
|
||||
@@ -33,7 +30,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
public List<TaskBasicIdView> ActualTumorTaskList { get; set; }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
[JsonIgnore]
|
||||
public List<TaskBasicIdView> GeneratedVisitTaskList { get; set; }
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
// 生成时间 2022-06-29 10:59:50
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||
//--------------------------------------------------------------------
|
||||
using System;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace IRaCIS.Core.Application.ViewModel
|
||||
@@ -69,7 +67,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
{
|
||||
if (!ReadingDurationTimeSpan.HasValue)
|
||||
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)*/;
|
||||
}
|
||||
}
|
||||
@@ -102,18 +100,18 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
|
||||
public Guid? SubjectId { get; set; }
|
||||
|
||||
public Guid? MedicalManagerUserId { get; set; }
|
||||
public Guid? MedicalManagerUserId { get; set; }
|
||||
|
||||
public DateTime? BeginSignTime { get; set; }
|
||||
public AuditAdvice? AuditAdviceEnum { get; set; }
|
||||
public DateTime? BeginSignTime { 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 TaskName { get; set; } = String.Empty;
|
||||
@@ -133,7 +131,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
|
||||
public Guid? TrialReadingCriterionId { get; set; }
|
||||
|
||||
public MedicalReviewDoctorUserIdea? DoctorUserIdeaEnum { get; set; }
|
||||
public MedicalReviewDoctorUserIdea? DoctorUserIdeaEnum { get; set; }
|
||||
|
||||
public Arm? ArmEnum { get; set; }
|
||||
|
||||
|
||||
@@ -3,11 +3,9 @@
|
||||
// 生成时间 2022-06-07 14:10:54
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||
//--------------------------------------------------------------------
|
||||
using System;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Newtonsoft.Json;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace IRaCIS.Core.Application.ViewModel
|
||||
{
|
||||
@@ -86,9 +84,9 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
public bool IsClinicalDataSign { get; set; }
|
||||
|
||||
|
||||
public CompleteClinicalDataEnum CompleteClinicalDataEnum =>
|
||||
public CompleteClinicalDataEnum CompleteClinicalDataEnum =>
|
||||
(IsNeedClinicalDataSign && IsClinicalDataSign) ? CompleteClinicalDataEnum.Complete : (IsNeedClinicalDataSign && IsClinicalDataSign == false) ? CompleteClinicalDataEnum.NotComplete : CompleteClinicalDataEnum.NA;
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
@@ -99,7 +97,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
/// <summary>
|
||||
/// 任务展示访视 读片任务显示是否顺序
|
||||
/// </summary>
|
||||
public ReadingOrder IsReadingTaskViewInOrder { get; set; }
|
||||
public ReadingOrder IsReadingTaskViewInOrder { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
@@ -163,7 +161,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
|
||||
public bool IsCanEditUrgentState { get; set; }
|
||||
|
||||
public DateTime? FirstReadingTime { get;set; }
|
||||
public DateTime? FirstReadingTime { get; set; }
|
||||
|
||||
public string ReadingDuration
|
||||
{
|
||||
@@ -221,11 +219,10 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
|
||||
public class AnalysisTaskView : ReadingTaskView
|
||||
{
|
||||
public bool? IsSelfAnalysis { get; set; }
|
||||
|
||||
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 IsSubjectJudge => UnReadCanReadTaskList.All(t => t.ReadingCategory == ReadingCategory.Judge);
|
||||
|
||||
public int UnReadTaskCount { get; set; }
|
||||
|
||||
public int UnReadCanReadTaskCount { get; set; }
|
||||
@@ -317,7 +316,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
if (this.SuggesteFinishedTime != null)
|
||||
{
|
||||
var date = DateTime.Now;
|
||||
var timeSpan = SuggesteFinishedTime.Value- date;
|
||||
var timeSpan = SuggesteFinishedTime.Value - date;
|
||||
if (timeSpan.TotalDays <= 2)
|
||||
{
|
||||
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 => UnReadTaskList.Where(y => y.IsFrontTaskNeedSignButNotSign == false && (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true)).ToList();
|
||||
public List<IRUnreadTaskView> UnReadCanReadTaskList { get; set; } = new List<IRUnreadTaskView>();
|
||||
|
||||
public List<IRUnreadTaskView> UnReadTaskList { get; set; } = new List<IRUnreadTaskView>();
|
||||
public List<IRUnreadTaskView> UnReadTaskList { get; set; } = new List<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;
|
||||
|
||||
@@ -410,7 +407,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
|
||||
public Guid? TrialSiteId { get; set; }
|
||||
public Guid? TrialSiteId { get; set; }
|
||||
|
||||
public Guid? SubjectId { get; set; }
|
||||
|
||||
@@ -436,7 +433,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
|
||||
public DateTime? BeginSignTime { get; set; }
|
||||
|
||||
public DateTime? EndSignTime { get; set; }
|
||||
public DateTime? EndSignTime { get; set; }
|
||||
|
||||
public DateTime? BeginRequestReReadingTime { get; set; }
|
||||
public DateTime? EndRequestReReadingTime { get; set; }
|
||||
@@ -554,7 +551,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
|
||||
public int? SubjectAllocateState { get; set; }
|
||||
|
||||
public List<Arm> ArmList { get; set; }=new List<Arm>() { };
|
||||
public List<Arm> ArmList { get; set; } = new List<Arm>() { };
|
||||
|
||||
[NotDefault]
|
||||
public Guid TrialReadingCriterionId { get; set; }
|
||||
@@ -602,9 +599,9 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
[JsonIgnore]
|
||||
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 Guid? OrignalSubjectUserId { get; set; }
|
||||
public Guid? ReplacedSubjectUserId { get; set; }
|
||||
|
||||
public UserSimpleInfo DoctorUser { get; set; }
|
||||
}
|
||||
|
||||
+12
-12
@@ -6,20 +6,20 @@
|
||||
|
||||
using IRaCIS.Core.Application.ViewModel;
|
||||
namespace IRaCIS.Core.Application.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// ITaskAllocationRuleService
|
||||
/// </summary>
|
||||
public interface ITaskAllocationRuleService
|
||||
{
|
||||
/// <summary>
|
||||
/// ITaskAllocationRuleService
|
||||
/// </summary>
|
||||
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