Compare commits
181 Commits
Test_IRC_N
...
Test_HIR_N
Author | SHA1 | Date |
---|---|---|
|
7c7ce6632a | |
|
787bc250c1 | |
|
3b5ac96a98 | |
|
3d4dc0c1f4 | |
|
2990420361 | |
|
2521147579 | |
|
4f860cca07 | |
|
bea324aa56 | |
|
c78cbbb737 | |
|
e197f6c2bb | |
|
c7d8e38cd3 | |
|
8a241754ca | |
|
b3e77ec422 | |
|
daf593f76a | |
|
5c4388a2e7 | |
|
0da73ce1db | |
|
1d2ef4561f | |
|
dbf75535c5 | |
|
aa34c96a39 | |
|
e6b6a24b3b | |
|
0b958f21a5 | |
|
e6310a4533 | |
|
49c3a0d494 | |
|
213cb69332 | |
|
e43dce220c | |
|
52dc6e05d4 | |
|
31e76a2e97 | |
|
19d9ca44fb | |
|
c8b0681dfa | |
|
eed17feae0 | |
|
c0478ef96e | |
|
4713d2a09b | |
|
ea72e6cf65 | |
|
9f5aee9258 | |
|
e56d1b9573 | |
|
6d5a7bd3a2 | |
|
a73ef7108b | |
|
507500f051 | |
|
913084cc8d | |
|
5874223866 | |
|
d5609560e2 | |
|
a5b4ab6531 | |
|
a91705b35d | |
|
65369c73bf | |
|
eb9bb75825 | |
|
69216ae75d | |
|
309ea7b1d1 | |
|
5beacacc0f | |
|
008a909f5b | |
|
bdfc65c07b | |
|
5ee7a70c65 | |
|
c9590829b2 | |
|
80805bde06 | |
|
20718bca5d | |
|
3d58e91644 | |
|
ade2a25fc4 | |
|
dcddf88a66 | |
|
89574e05bc | |
|
95fe14fece | |
|
cfaf14ed65 | |
|
a50f82c42a | |
|
1c0e1e01ce | |
|
5ec3fc3d13 | |
|
9bd080b566 | |
|
f7cdb5b858 | |
|
00c3ad8f9e | |
|
d4b3038f6d | |
|
dde513a976 | |
|
8378e8f2d6 | |
|
374f024f85 | |
|
32aadceaac | |
|
285e742136 | |
|
704a876cf0 | |
|
7184ea9565 | |
|
6da50126e1 | |
|
965c8a56c9 | |
|
0611c1d9fe | |
|
642acc9cba | |
|
b87fb98c6c | |
|
d0d249655b | |
|
a847bb1785 | |
|
445ee00840 | |
|
ecd33d969b | |
|
470420410e | |
|
2952b9e59f | |
|
7e8995a7b2 | |
|
e7046173f8 | |
|
f1a39e3b9d | |
|
2838f232f3 | |
|
9ac4b262f3 | |
|
582b8b3c07 | |
|
91b20e07f2 | |
|
5a99f476f9 | |
|
e06b47c8b3 | |
|
613cf6441b | |
|
57dd964db2 | |
|
42dd5d384f | |
|
f2138623f4 | |
|
c69b2569ce | |
|
6f8b88422b | |
|
4c4d19b0d6 | |
|
91e0f0b787 | |
|
c7f64ea0fe | |
|
fdb0b74296 | |
|
0d7a04f1e8 | |
|
0a72c15dfd | |
|
282c0b40c2 | |
|
5783f5836a | |
|
aff1f5b599 | |
|
b12079f8d9 | |
|
99de20ef76 | |
|
c187b5fb94 | |
|
d852de4a5b | |
|
d10020d944 | |
|
f7c17546da | |
|
c267bb34b4 | |
|
98b0b36e3b | |
|
468224cae9 | |
|
6b385b619a | |
|
88669ccbff | |
|
5f338de0cd | |
|
c266c68be8 | |
|
364b84fd1c | |
|
982bd80898 | |
|
0050ae8d0a | |
|
8d11115fab | |
|
355ca22134 | |
|
d568964c64 | |
|
81443e5e36 | |
|
1c4d513f5b | |
|
d0a3ce9a09 | |
|
0a368c0607 | |
|
1104c1481e | |
|
7318dd4812 | |
|
1ee30d047d | |
|
39e7218b52 | |
|
959fa1c40c | |
|
fb074048df | |
|
0b20c42513 | |
|
7c0e53db73 | |
|
d77a6ebda0 | |
|
42f7bf9c97 | |
|
b9d9552ae8 | |
|
ba81a842b7 | |
|
28b3f16ef0 | |
|
37bf4905bb | |
|
0ab9cebe45 | |
|
a8c9587572 | |
|
48380aa7ea | |
|
b1831bfba0 | |
|
b9f866807e | |
|
8896450fcc | |
|
2dc0cc3525 | |
|
a3f635894b | |
|
542ead68a7 | |
|
7c25809ad5 | |
|
1f14adec2a | |
|
8173e6a8f2 | |
|
0baf4700f1 | |
|
e3f1fe5569 | |
|
9aa5c27f60 | |
|
a1479420c8 | |
|
0f368f0a5e | |
|
5d0c6417a4 | |
|
12d8944ca7 | |
|
521a4ad3f0 | |
|
040777ec87 | |
|
b68d3a5d99 | |
|
0af3c5ab8b | |
|
6ca1e81b6a | |
|
068b3fa8d7 | |
|
976b89e970 | |
|
47e85ebbdf | |
|
44f33fb7f0 | |
|
2c5ba280e9 | |
|
5250cd524a | |
|
787dd9aa5f | |
|
e059dcb2b2 | |
|
75bf9b394b | |
|
c158d53a39 | |
|
8e6125796b |
|
@ -27,8 +27,7 @@ namespace IRaCIS.Core.SCP
|
|||
//public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); });
|
||||
var logFactory = LoggerFactory.Create(builder => { builder.AddDebug(); });
|
||||
|
||||
options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value,
|
||||
contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure());
|
||||
options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value);
|
||||
|
||||
options.UseLoggerFactory(logFactory);
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.1.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.10" />
|
||||
<PackageReference Include="AutoMapper" Version="13.0.1" />
|
||||
<PackageReference Include="Minio" Version="6.0.3" />
|
||||
<PackageReference Include="Minio" Version="6.0.4" />
|
||||
<PackageReference Include="My.Extensions.Localization.Json" Version="3.3.0">
|
||||
<TreatAsUsed>true</TreatAsUsed>
|
||||
</PackageReference>
|
||||
|
@ -36,4 +36,12 @@
|
|||
<ProjectReference Include="..\IRaCIS.Core.Infra.EFCore\IRaCIS.Core.Infra.EFCore.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="appsettings.Prod_HIR_SCP.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -82,7 +82,6 @@ builder.Services.AddControllers(options =>
|
|||
.AddNewtonsoftJsonSetup(builder.Services); // NewtonsoftJson 序列化 处理
|
||||
|
||||
|
||||
builder.Services.AddOptions().Configure<AliyunOSSOptions>(_configuration.GetSection("AliyunOSS"));
|
||||
builder.Services.AddOptions().Configure<ObjectStoreServiceOptions>(_configuration.GetSection("ObjectStoreService"));
|
||||
builder.Services.AddOptions().Configure<DicomSCPServiceOption>(_configuration.GetSection("DicomSCPServiceConfig"));
|
||||
|
||||
|
@ -126,19 +125,25 @@ builder.Services.Configure<ForwardedHeadersOptions>(options =>
|
|||
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
|
||||
});
|
||||
|
||||
//Dicom影像渲染图片 跨平台
|
||||
//builder.Services.AddDicomSetup();
|
||||
new DicomSetupBuilder()
|
||||
.RegisterServices(s =>
|
||||
s.AddFellowOakDicom()
|
||||
.AddTranscoderManager<NativeTranscoderManager>()
|
||||
builder.Services.AddFellowOakDicom().AddTranscoderManager<NativeTranscoderManager>()
|
||||
//.AddTranscoderManager<FellowOakDicom.Imaging.NativeCodec.NativeTranscoderManager>()
|
||||
.AddImageManager<ImageSharpImageManager>())
|
||||
.SkipValidation()
|
||||
.Build();
|
||||
.AddImageManager<ImageSharpImageManager>();
|
||||
|
||||
|
||||
|
||||
////Dicom影像渲染图片 跨平台
|
||||
////builder.Services.AddDicomSetup();
|
||||
//new DicomSetupBuilder()
|
||||
// .RegisterServices(s =>
|
||||
// s.AddFellowOakDicom()
|
||||
// .AddTranscoderManager<NativeTranscoderManager>()
|
||||
// //.AddTranscoderManager<FellowOakDicom.Imaging.NativeCodec.NativeTranscoderManager>()
|
||||
// .AddImageManager<ImageSharpImageManager>())
|
||||
// .SkipValidation()
|
||||
|
||||
// .Build();
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
// Add services to the container.
|
||||
|
@ -211,9 +216,14 @@ else
|
|||
|
||||
#endregion
|
||||
|
||||
DicomSetupBuilder.UseServiceProvider(app.Services);
|
||||
|
||||
|
||||
var logger = app.Services.GetService<Microsoft.Extensions.Logging.ILogger<Program>>();
|
||||
|
||||
var server = DicomServerFactory.Create<CStoreSCPService>(_configuration.GetSection("DicomSCPServiceConfig").GetValue<int>("ServerPort"), userState: app.Services,logger: logger);
|
||||
|
||||
|
||||
|
||||
|
||||
app.Run();
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"profiles": {
|
||||
"Test_IRC_SCP": {
|
||||
"Test_HIR_SCP": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"applicationUrl": "http://localhost:6200",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Test_IRC_SCP"
|
||||
"ASPNETCORE_ENVIRONMENT": "Test_HIR_SCP"
|
||||
}
|
||||
},
|
||||
"Uat_IRC_SCP": {
|
||||
"Uat_HIR_SCP": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"applicationUrl": "http://localhost:6200",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Uat_IRC_SCP"
|
||||
"ASPNETCORE_ENVIRONMENT": "Uat_HIR_SCP"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,17 +37,13 @@ namespace IRaCIS.Core.SCP.Service
|
|||
|
||||
public class CStoreSCPService : DicomService, IDicomServiceProvider, IDicomCStoreProvider, IDicomCEchoProvider
|
||||
{
|
||||
//private IServiceProvider _injectServiceProvider { get; set; }
|
||||
private IServiceProvider _serviceProvider { get; set; }
|
||||
|
||||
private List<Guid> _SCPStudyIdList { get; set; } = new List<Guid>();
|
||||
|
||||
private SCPImageUpload _upload { get; set; }
|
||||
|
||||
private Guid _trialId { get; set; }
|
||||
|
||||
private Guid _trialSiteId { get; set; }
|
||||
|
||||
|
||||
|
||||
private static readonly DicomTransferSyntax[] _acceptedTransferSyntaxes = new DicomTransferSyntax[]
|
||||
{
|
||||
|
@ -58,27 +54,28 @@ namespace IRaCIS.Core.SCP.Service
|
|||
|
||||
private static readonly DicomTransferSyntax[] _acceptedImageTransferSyntaxes = new DicomTransferSyntax[]
|
||||
{
|
||||
// Lossless
|
||||
DicomTransferSyntax.JPEGLSLossless, //1.2.840.10008.1.2.4.80
|
||||
DicomTransferSyntax.JPEG2000Lossless, //1.2.840.10008.1.2.4.90
|
||||
DicomTransferSyntax.JPEGProcess14SV1, //1.2.840.10008.1.2.4.70
|
||||
DicomTransferSyntax.JPEGProcess14, //1.2.840.10008.1.2.4.57 JPEG Lossless, Non-Hierarchical (Process 14)
|
||||
DicomTransferSyntax.RLELossless, //1.2.840.10008.1.2.5
|
||||
// Lossless
|
||||
DicomTransferSyntax.JPEGLSLossless,
|
||||
DicomTransferSyntax.JPEG2000Lossless,
|
||||
DicomTransferSyntax.JPEGProcess14SV1,
|
||||
DicomTransferSyntax.JPEGProcess14,
|
||||
DicomTransferSyntax.RLELossless,
|
||||
// Lossy
|
||||
DicomTransferSyntax.JPEGLSNearLossless,//1.2.840.10008.1.2.4.81"
|
||||
DicomTransferSyntax.JPEG2000Lossy, //1.2.840.10008.1.2.4.91
|
||||
DicomTransferSyntax.JPEGProcess1, //1.2.840.10008.1.2.4.50
|
||||
DicomTransferSyntax.JPEGProcess2_4, //1.2.840.10008.1.2.4.51
|
||||
DicomTransferSyntax.JPEGLSNearLossless,
|
||||
DicomTransferSyntax.JPEG2000Lossy,
|
||||
DicomTransferSyntax.JPEGProcess1,
|
||||
DicomTransferSyntax.JPEGProcess2_4,
|
||||
// Uncompressed
|
||||
DicomTransferSyntax.ExplicitVRLittleEndian, //1.2.840.10008.1.2.1
|
||||
DicomTransferSyntax.ExplicitVRBigEndian, //1.2.840.10008.1.2.2
|
||||
DicomTransferSyntax.ImplicitVRLittleEndian //1.2.840.10008.1.2
|
||||
DicomTransferSyntax.ExplicitVRLittleEndian,
|
||||
DicomTransferSyntax.ExplicitVRBigEndian,
|
||||
DicomTransferSyntax.ImplicitVRLittleEndian
|
||||
};
|
||||
|
||||
|
||||
public CStoreSCPService(INetworkStream stream, Encoding fallbackEncoding, Microsoft.Extensions.Logging.ILogger log, DicomServiceDependencies dependencies)
|
||||
public CStoreSCPService(INetworkStream stream, Encoding fallbackEncoding, Microsoft.Extensions.Logging.ILogger log, DicomServiceDependencies dependencies, IServiceProvider injectServiceProvider)
|
||||
: base(stream, fallbackEncoding, log, dependencies)
|
||||
{
|
||||
_serviceProvider = injectServiceProvider.CreateScope().ServiceProvider;
|
||||
}
|
||||
|
||||
|
||||
|
@ -92,50 +89,22 @@ namespace IRaCIS.Core.SCP.Service
|
|||
|
||||
Log.Logger.Warning($"接收到来自{association.CallingAE}的连接");
|
||||
|
||||
_serviceProvider = (IServiceProvider)this.UserState;
|
||||
//_serviceProvider = (IServiceProvider)this.UserState;
|
||||
|
||||
//var tt = _injectServiceProvider;
|
||||
|
||||
var option = _serviceProvider.GetService<IOptionsMonitor<DicomSCPServiceOption>>().CurrentValue;
|
||||
|
||||
|
||||
|
||||
var _trialDicomAERepository = _serviceProvider.GetService<IRepository<TrialDicomAE>>();
|
||||
var calledAEList = option.CalledAEList;
|
||||
|
||||
if (!calledAEList.Contains(association.CalledAE))
|
||||
|
||||
var trialDicomAEList = _trialDicomAERepository.Select(t => new { t.CalledAE, t.TrialId }).ToList();
|
||||
var trialCalledAEList = trialDicomAEList.Select(t => t.CalledAE).ToList();
|
||||
|
||||
Log.Logger.Information("当前系统配置:", string.Join('|', trialDicomAEList));
|
||||
|
||||
var findCalledAE = trialDicomAEList.Where(t => t.CalledAE == association.CalledAE).FirstOrDefault();
|
||||
|
||||
var isCanReceiveIamge = false;
|
||||
|
||||
if (findCalledAE != null)
|
||||
{
|
||||
_trialId = findCalledAE.TrialId;
|
||||
|
||||
var _trialSiteDicomAERepository = _serviceProvider.GetService<IRepository<TrialSiteDicomAE>>();
|
||||
|
||||
|
||||
var findTrialSiteAE = _trialSiteDicomAERepository.Where(t => t.CallingAE == association.CallingAE && t.TrialId==_trialId).FirstOrDefault();
|
||||
|
||||
if (findTrialSiteAE != null)
|
||||
{
|
||||
_trialSiteId = findTrialSiteAE.TrialSiteId;
|
||||
|
||||
isCanReceiveIamge = true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (association.CallingAE == "test-callingAE")
|
||||
{
|
||||
isCanReceiveIamge = true;
|
||||
}
|
||||
|
||||
if (!trialCalledAEList.Contains(association.CalledAE) || isCanReceiveIamge == false)
|
||||
//if (association.CalledAE != "STORESCP")
|
||||
{
|
||||
|
||||
Log.Logger.Warning($"拒绝CallingAE:{association.CallingAE} CalledAE:{association.CalledAE}的连接");
|
||||
Log.Logger.Warning($"拒绝CalledAE:{association.CalledAE}的连接");
|
||||
|
||||
return SendAssociationRejectAsync(
|
||||
DicomRejectResult.Permanent,
|
||||
|
@ -155,33 +124,32 @@ namespace IRaCIS.Core.SCP.Service
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return SendAssociationAcceptAsync(association);
|
||||
}
|
||||
|
||||
|
||||
public async Task OnReceiveAssociationReleaseRequestAsync()
|
||||
{
|
||||
await DataMaintenanceAsaync();
|
||||
var _distributedLockProvider = _serviceProvider.GetService<IDistributedLockProvider>();
|
||||
|
||||
//记录监控
|
||||
var @lock = _distributedLockProvider.CreateLock($"{_upload.CallingAE}");
|
||||
|
||||
var _SCPImageUploadRepository = _serviceProvider.GetService<IRepository<SCPImageUpload>>();
|
||||
using (await @lock.AcquireAsync())
|
||||
{
|
||||
|
||||
_upload.EndTime = DateTime.Now;
|
||||
_upload.StudyCount = _SCPStudyIdList.Count;
|
||||
_upload.TrialId = _trialId;
|
||||
_upload.TrialSiteId = _trialSiteId;
|
||||
await DataMaintenanceAsaync();
|
||||
|
||||
await _SCPImageUploadRepository.AddAsync(_upload, true);
|
||||
//记录监控
|
||||
|
||||
var _SCPImageUploadRepository = _serviceProvider.GetService<IRepository<SCPImageUpload>>();
|
||||
|
||||
var _studyRepository = _serviceProvider.GetService<IRepository<SCPStudy>>();
|
||||
//将检查设置为传输结束
|
||||
await _studyRepository.BatchUpdateNoTrackingAsync(t => _SCPStudyIdList.Contains(t.Id), u => new SCPStudy() { IsUploadFinished = true });
|
||||
_upload.EndTime = DateTime.Now;
|
||||
_upload.StudyCount = _SCPStudyIdList.Count;
|
||||
|
||||
await _studyRepository.SaveChangesAndClearAllTrackingAsync();
|
||||
//可能是测试echo 导致记录了
|
||||
await _SCPImageUploadRepository.AddAsync(_upload, _upload.FileCount > 0 ? true : false);
|
||||
|
||||
}
|
||||
|
||||
await SendAssociationReleaseResponseAsync();
|
||||
}
|
||||
|
@ -189,9 +157,11 @@ namespace IRaCIS.Core.SCP.Service
|
|||
|
||||
private async Task DataMaintenanceAsaync()
|
||||
{
|
||||
Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE}传输结束:开始维护数据,处理检查Modality");
|
||||
Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE}传输结束:开始维护数据,处理检查Modality 以及自动创建访视,绑定检查");
|
||||
|
||||
var patientStudyService = _serviceProvider.GetService<IPatientStudyService>();
|
||||
|
||||
await patientStudyService.AutoBindingPatientStudyVisitAsync(_SCPStudyIdList);
|
||||
|
||||
//处理检查Modality
|
||||
var _dictionaryRepository = _serviceProvider.GetService<IRepository<Dictionary>>();
|
||||
|
@ -243,11 +213,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}");
|
||||
|
@ -263,9 +233,8 @@ namespace IRaCIS.Core.SCP.Service
|
|||
string seriesInstanceUid = request.Dataset.GetString(DicomTag.SeriesInstanceUID);
|
||||
string sopInstanceUid = request.Dataset.GetString(DicomTag.SOPInstanceUID);
|
||||
|
||||
//Guid studyId = IdentifierHelper.CreateGuid(studyInstanceUid, trialId.ToString());
|
||||
Guid seriesId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, _trialId.ToString());
|
||||
Guid instanceId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, sopInstanceUid, _trialId.ToString());
|
||||
Guid seriesId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid);
|
||||
Guid instanceId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, sopInstanceUid);
|
||||
|
||||
|
||||
var ossService = _serviceProvider.GetService<IOSSService>();
|
||||
|
@ -275,7 +244,7 @@ namespace IRaCIS.Core.SCP.Service
|
|||
var _distributedLockProvider = _serviceProvider.GetService<IDistributedLockProvider>();
|
||||
|
||||
var storeRelativePath = string.Empty;
|
||||
var ossFolderPath = $"{_trialId}/Image/PACS/{_trialSiteId}{studyInstanceUid}";
|
||||
var ossFolderPath = $"Dicom/{studyInstanceUid}";
|
||||
|
||||
|
||||
long fileSize = 0;
|
||||
|
@ -308,7 +277,7 @@ namespace IRaCIS.Core.SCP.Service
|
|||
{
|
||||
try
|
||||
{
|
||||
var scpStudyId = await dicomArchiveService.ArchiveDicomFileAsync(request.Dataset, _trialId, _trialSiteId, storeRelativePath, Association.CallingAE, Association.CalledAE,fileSize);
|
||||
var scpStudyId = await dicomArchiveService.ArchiveDicomFileAsync(request.Dataset, storeRelativePath, Association.CallingAE, Association.CalledAE, fileSize);
|
||||
|
||||
if (!_SCPStudyIdList.Contains(scpStudyId))
|
||||
{
|
||||
|
@ -337,10 +306,14 @@ namespace IRaCIS.Core.SCP.Service
|
|||
|
||||
series.ImageResizePath = seriesPath;
|
||||
|
||||
|
||||
|
||||
//await _seriesRepository.BatchUpdateNoTrackingAsync(t => t.Id == seriesId, u => new SCPSeries() { ImageResizePath = seriesPath });
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
await _seriesRepository.SaveChangesAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
|
@ -11,7 +11,6 @@ using FellowOakDicom.Network;
|
|||
using IRaCIS.Core.SCP.Service;
|
||||
using IRaCIS.Core.Infra.EFCore;
|
||||
using MassTransit;
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
using Serilog.Sinks.File;
|
||||
|
||||
namespace IRaCIS.Core.SCP.Service
|
||||
|
@ -52,18 +51,18 @@ namespace IRaCIS.Core.SCP.Service
|
|||
/// <param name="dataset"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public async Task<Guid> ArchiveDicomFileAsync(DicomDataset dataset, Guid trialId, Guid trialSiteId, string fileRelativePath, string callingAE, string calledAE,long fileSize)
|
||||
public async Task<Guid> ArchiveDicomFileAsync(DicomDataset dataset, string fileRelativePath, string callingAE, string calledAE, long fileSize)
|
||||
{
|
||||
string studyInstanceUid = dataset.GetString(DicomTag.StudyInstanceUID);
|
||||
string seriesInstanceUid = dataset.GetString(DicomTag.SeriesInstanceUID);
|
||||
string sopInstanceUid = dataset.GetString(DicomTag.SOPInstanceUID);
|
||||
|
||||
string patientIdStr = dataset.GetSingleValueOrDefault(DicomTag.PatientID,string.Empty);
|
||||
string patientIdStr = dataset.GetSingleValueOrDefault(DicomTag.PatientID, string.Empty);
|
||||
|
||||
//Guid patientId= IdentifierHelper.CreateGuid(patientIdStr);
|
||||
Guid studyId = IdentifierHelper.CreateGuid(studyInstanceUid,trialId.ToString());
|
||||
Guid seriesId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, trialId.ToString());
|
||||
Guid instanceId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, sopInstanceUid, trialId.ToString());
|
||||
Guid studyId = IdentifierHelper.CreateGuid(studyInstanceUid);
|
||||
Guid seriesId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid);
|
||||
Guid instanceId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, sopInstanceUid);
|
||||
|
||||
var isStudyNeedAdd = false;
|
||||
var isSeriesNeedAdd = false;
|
||||
|
@ -74,15 +73,16 @@ namespace IRaCIS.Core.SCP.Service
|
|||
|
||||
//using (@lock.Acquire())
|
||||
{
|
||||
var findPatient = await _patientRepository.FirstOrDefaultAsync(t => t.PatientIdStr == patientIdStr && t.TrialSiteId==trialSiteId );
|
||||
var findStudy = await _studyRepository.FirstOrDefaultAsync(t=>t.Id== studyId);
|
||||
var findSerice = await _seriesRepository.FirstOrDefaultAsync(t => t.Id == seriesId);
|
||||
var findPatient = await _patientRepository.FirstOrDefaultAsync(t => t.PatientIdStr == patientIdStr);
|
||||
var findStudy = await _studyRepository.FirstOrDefaultAsync(t => t.Id == studyId);
|
||||
var findSerice = await _seriesRepository.FirstOrDefaultAsync(t => t.Id == seriesId);
|
||||
var findInstance = await _instanceRepository.FirstOrDefaultAsync(t => t.Id == instanceId);
|
||||
|
||||
|
||||
DateTime? studyTime = dataset.GetSingleValueOrDefault(DicomTag.StudyDate, string.Empty) == string.Empty ? null : dataset.GetSingleValue<DateTime>(DicomTag.StudyDate).Add(dataset.GetSingleValueOrDefault(DicomTag.StudyTime, string.Empty) == string.Empty ? TimeSpan.Zero : dataset.GetSingleValue<DateTime>(DicomTag.StudyTime).TimeOfDay);
|
||||
|
||||
//先传输了修改了患者编号的,又传输了没有修改患者编号的,导致后传输的没有修改患者编号的下面的检查为0
|
||||
if (findPatient == null && findStudy==null)
|
||||
if (findPatient == null && findStudy == null)
|
||||
{
|
||||
isPatientNeedAdd = true;
|
||||
|
||||
|
@ -90,8 +90,6 @@ namespace IRaCIS.Core.SCP.Service
|
|||
findPatient = new SCPPatient()
|
||||
{
|
||||
Id = NewId.NextSequentialGuid(),
|
||||
TrialId=trialId,
|
||||
TrialSiteId=trialSiteId,
|
||||
PatientIdStr = dataset.GetSingleValueOrDefault(DicomTag.PatientID, string.Empty),
|
||||
PatientName = dataset.GetSingleValueOrDefault(DicomTag.PatientName, string.Empty),
|
||||
PatientAge = dataset.GetSingleValueOrDefault(DicomTag.PatientAge, string.Empty),
|
||||
|
@ -117,20 +115,6 @@ namespace IRaCIS.Core.SCP.Service
|
|||
{
|
||||
findPatient.PatientBirthDate = birthDateStr;
|
||||
|
||||
DateTime birthDate;
|
||||
|
||||
if (findPatient.PatientAge == string.Empty && studyTime.HasValue && DateTime.TryParse(findPatient.PatientBirthDate,out birthDate))
|
||||
{
|
||||
var patientAge = studyTime.Value.Year - birthDate.Year;
|
||||
// 如果生日还未到,年龄减去一岁
|
||||
if (studyTime.Value < birthDate.AddYears(patientAge))
|
||||
{
|
||||
patientAge--;
|
||||
}
|
||||
|
||||
findPatient.PatientAge = patientAge.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -163,8 +147,6 @@ namespace IRaCIS.Core.SCP.Service
|
|||
|
||||
PatientId = findPatient.Id,
|
||||
Id = studyId,
|
||||
TrialId = trialId,
|
||||
TrialSiteId = trialSiteId,
|
||||
StudyInstanceUid = studyInstanceUid,
|
||||
StudyTime = studyTime,
|
||||
Modalities = dataset.GetSingleValueOrDefault(DicomTag.Modality, string.Empty),
|
||||
|
@ -273,8 +255,7 @@ namespace IRaCIS.Core.SCP.Service
|
|||
|
||||
Path = fileRelativePath,
|
||||
|
||||
FileSize= fileSize,
|
||||
|
||||
FileSize = fileSize,
|
||||
};
|
||||
|
||||
++findStudy.InstanceCount;
|
||||
|
@ -298,13 +279,14 @@ namespace IRaCIS.Core.SCP.Service
|
|||
{
|
||||
await _seriesRepository.AddAsync(findSerice);
|
||||
}
|
||||
|
||||
if (isInstanceNeedAdd)
|
||||
{
|
||||
await _instanceRepository.AddAsync(findInstance);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _instanceRepository.BatchUpdateNoTrackingAsync(t => t.Id == instanceId, u => new SCPInstance() { Path = fileRelativePath,FileSize=fileSize });
|
||||
await _instanceRepository.BatchUpdateNoTrackingAsync(t => t.Id == instanceId, u => new SCPInstance() { Path = fileRelativePath, FileSize = fileSize });
|
||||
}
|
||||
|
||||
await _studyRepository.SaveChangesAsync();
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace IRaCIS.Core.SCP.Service
|
|||
{
|
||||
public interface IDicomArchiveService
|
||||
{
|
||||
Task<Guid> ArchiveDicomFileAsync(DicomDataset dicomDataset,Guid trialId,Guid trialSiteId, string fileRelativePath,string callingAE,string calledAE,long fileSize);
|
||||
Task<Guid> ArchiveDicomFileAsync(DicomDataset dicomDataset,string fileRelativePath,string callingAE,string calledAE,long fileSize);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ using MassTransit;
|
|||
using Microsoft.Extensions.Options;
|
||||
using Minio;
|
||||
using Minio.DataModel.Args;
|
||||
using System.Net;
|
||||
using System.Reactive.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
@ -216,9 +217,19 @@ public class OSSService : IOSSService
|
|||
.WithBucket(minIOConfig.BucketName)
|
||||
.WithObject(ossRelativePath)
|
||||
.WithStreamData(memoryStream)
|
||||
|
||||
.WithObjectSize(memoryStream.Length);
|
||||
|
||||
await minioClient.PutObjectAsync(putObjectArgs);
|
||||
var putResponse = await minioClient.PutObjectAsync(putObjectArgs);
|
||||
|
||||
if (putResponse.ResponseStatusCode == HttpStatusCode.OK)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new BusinessValidationFailedException($"上传发生异常:{putResponse.ResponseContent}");
|
||||
}
|
||||
}
|
||||
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
|
||||
{
|
||||
|
|
|
@ -0,0 +1,249 @@
|
|||
using IRaCIS.Core.Domain.Share;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
using Medallion.Threading;
|
||||
using FellowOakDicom;
|
||||
using FellowOakDicom.Imaging.Codec;
|
||||
using System.Data;
|
||||
using IRaCIS.Core.Domain.Models;
|
||||
using FellowOakDicom.Network;
|
||||
using IRaCIS.Core.SCP.Service;
|
||||
using IRaCIS.Core.Infra.EFCore;
|
||||
using MassTransit;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace IRaCIS.Core.SCP.Service
|
||||
{
|
||||
public interface IPatientStudyService
|
||||
{
|
||||
Task<IResponseOutput> AutoBindingPatientStudyVisitAsync(List<Guid> scpStudyIdList);
|
||||
}
|
||||
|
||||
[ApiExplorerSettings(GroupName = "Trial")]
|
||||
public class PatientStudyService : BaseService, IPatientStudyService
|
||||
{
|
||||
private readonly IRepository<SCPStudySubjectVisit> _studySubjectVisitRepository;
|
||||
private readonly IRepository<SubjectPatient> _subjectPatientRepository;
|
||||
private readonly IRepository<Trial> _trialRepository;
|
||||
private readonly IRepository<SCPPatient> _patientRepository;
|
||||
private readonly IRepository<SCPStudy> _studyRepository;
|
||||
private readonly IRepository<Subject> _subjectRepository;
|
||||
private readonly IRepository<SubjectVisit> _subjectVisitRepository;
|
||||
private readonly IDistributedLockProvider _distributedLockProvider;
|
||||
|
||||
public PatientStudyService(IRepository<SCPStudySubjectVisit> studySubjectVisitRepository, IRepository<SCPStudy> studyRepository, IRepository<SubjectPatient> subjectPatientRepository, IRepository<Trial> trialRepository, IRepository<SCPPatient> patientRepository, IRepository<Subject> subjectRepository, IRepository<SubjectVisit> subjectVisitRepository, IDistributedLockProvider distributedLockProvider)
|
||||
{
|
||||
_studySubjectVisitRepository = studySubjectVisitRepository;
|
||||
_studyRepository = studyRepository;
|
||||
_subjectPatientRepository = subjectPatientRepository;
|
||||
_trialRepository = trialRepository;
|
||||
_patientRepository = patientRepository;
|
||||
_subjectRepository = subjectRepository;
|
||||
_subjectVisitRepository = subjectVisitRepository;
|
||||
_distributedLockProvider = distributedLockProvider;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class AuToBindingStudyInfo
|
||||
{
|
||||
public Guid SCPStudyId { get; set; }
|
||||
public DateTime? StudyTime { get; set; }
|
||||
}
|
||||
|
||||
private async Task DealAutoBindingStudyAsync(Guid trialId, Guid subjectId, List<AuToBindingStudyInfo> studyList, decimal? startBindVisitNum = null)
|
||||
{
|
||||
|
||||
//自动创建访视 和检查绑定
|
||||
|
||||
//1. 查询已存在的访视
|
||||
var subjectAllVisitList = await _subjectVisitRepository.Where(t => t.SubjectId == subjectId)
|
||||
.Select(t => new
|
||||
{
|
||||
t.SubjectId,
|
||||
SubjectVisitId = t.Id,
|
||||
t.SubmitState,
|
||||
VisitNum = t.VisitNum,
|
||||
MaxStudyTime = t.SCPStudySubjectVisitList.Max(t => t.SCPStudy.StudyTime),
|
||||
MinStudyTime = t.SCPStudySubjectVisitList.Min(t => t.SCPStudy.StudyTime)
|
||||
})
|
||||
.ToListAsync();
|
||||
|
||||
|
||||
//2、获取项目配置
|
||||
var trialconfig = _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.BlindBaseLineName, t.BlindFollowUpPrefix }).FirstOrDefault();
|
||||
|
||||
//3、 未提交的最小的访视号 从这个访视开始绑定
|
||||
|
||||
var subjectMaxVisitNum = startBindVisitNum == null ? subjectAllVisitList.Where(t => t.SubmitState != SubmitStateEnum.Submitted).MinOrDefault(t => t.VisitNum) : startBindVisitNum.Value;
|
||||
|
||||
|
||||
List<(int VisitCount, Guid SCPStudyId)> visits = new List<(int, Guid)>();
|
||||
|
||||
int visitCount = 0;
|
||||
|
||||
DateTime? lastVisitTime = null;
|
||||
|
||||
foreach (var study in studyList)
|
||||
{
|
||||
if (lastVisitTime == null || (study.StudyTime - lastVisitTime.Value).Value.TotalDays >= 15)
|
||||
{
|
||||
// 当前时间点与上一个访视时间点间隔大于等于 15 天,需要建立一个新的访视
|
||||
visitCount++;
|
||||
|
||||
visits.Add((visitCount, study.SCPStudyId));
|
||||
}
|
||||
else
|
||||
{
|
||||
visits.Add((visitCount, study.SCPStudyId));
|
||||
}
|
||||
|
||||
lastVisitTime = study.StudyTime;
|
||||
}
|
||||
|
||||
//4、生成访视 并且绑定
|
||||
|
||||
for (int i = 0; i < visitCount; i++)
|
||||
{
|
||||
|
||||
var bindSubjectVisitId = Guid.Empty;
|
||||
|
||||
var bindVisitNum = i + subjectMaxVisitNum;
|
||||
|
||||
var existSubjectVisit = subjectAllVisitList.FirstOrDefault(t => t.SubjectId == subjectId && t.VisitNum == bindVisitNum);
|
||||
|
||||
if (existSubjectVisit == null)
|
||||
{
|
||||
bindSubjectVisitId = NewId.NextGuid();
|
||||
|
||||
//基线
|
||||
if (bindVisitNum == 0)
|
||||
{
|
||||
|
||||
await _subjectVisitRepository.AddAsync(new SubjectVisit() { TrialId = trialId, SubjectId = subjectId, VisitName = trialconfig.BlindBaseLineName, VisitNum = bindVisitNum, Id = bindSubjectVisitId, SubmitState = SubmitStateEnum.ToSubmit, IsBaseLine = true });
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
await _subjectVisitRepository.AddAsync(new SubjectVisit() { TrialId = trialId, SubjectId = subjectId, VisitName = trialconfig.BlindFollowUpPrefix + $" {(int)bindVisitNum}", VisitNum = bindVisitNum, Id = bindSubjectVisitId, SubmitState = SubmitStateEnum.ToSubmit });
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
bindSubjectVisitId = existSubjectVisit.SubjectVisitId;
|
||||
}
|
||||
|
||||
|
||||
|
||||
var currentVisitStudyList = visits.Where(t => t.VisitCount == (i + 1)).ToList();
|
||||
|
||||
foreach (var item in currentVisitStudyList)
|
||||
{
|
||||
//访视状态为未提交才绑定
|
||||
if (!subjectAllVisitList.Any(t => t.SubjectId == subjectId && t.SubjectVisitId == bindSubjectVisitId && t.SubmitState == SubmitStateEnum.Submitted))
|
||||
{
|
||||
var find = await _subjectVisitRepository.FindAsync(bindSubjectVisitId);
|
||||
find.SubmitState = SubmitStateEnum.ToSubmit;
|
||||
await _studySubjectVisitRepository.AddAsync(new SCPStudySubjectVisit() { TrialId = trialId, SubjectVisitId = bindSubjectVisitId, SCPStudyId = item.SCPStudyId, SubjectId = subjectId });
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
await _subjectPatientRepository.SaveChangesAsync();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 传输完成后,自动给检查绑定访视
|
||||
/// </summary>
|
||||
/// <param name="inCommand"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<IResponseOutput> AutoBindingPatientStudyVisitAsync(List<Guid> scpStudyIdList)
|
||||
{
|
||||
//一个检查 可能绑定到不同的项目的不同subject 有的该检查已绑定访视,有的该检查绑定了访视
|
||||
|
||||
var query = from scpStudy in _studyRepository.Where(t => scpStudyIdList.Contains(t.Id))
|
||||
join subjectPatient in _subjectPatientRepository.AsQueryable()
|
||||
on scpStudy.PatientId equals subjectPatient.PatientId
|
||||
select new
|
||||
{
|
||||
subjectPatient.Subject.Status,
|
||||
subjectPatient.Subject.TrialId,
|
||||
subjectPatient.SubjectId,
|
||||
subjectPatient.PatientId,
|
||||
SCPStudyId = scpStudy.Id,
|
||||
scpStudy.StudyTime
|
||||
};
|
||||
|
||||
var list = query.ToList();
|
||||
|
||||
if (list.Count > 0)
|
||||
{
|
||||
|
||||
|
||||
var subjectIdList = list.Select(t => t.SubjectId).ToList();
|
||||
|
||||
var allSubjectVisitList = await _subjectVisitRepository.Where(t => subjectIdList.Contains(t.SubjectId))
|
||||
.Select(t => new { t.SubjectId, SubjectVisitId = t.Id, t.SubmitState, VisitNum = t.VisitNum, MaxStudyTime = t.SCPStudySubjectVisitList.Max(t => t.SCPStudy.StudyTime), MinStudyTime = t.SCPStudySubjectVisitList.Min(t => t.SCPStudy.StudyTime) })
|
||||
.ToListAsync();
|
||||
|
||||
foreach (var g in list.GroupBy(t => new { t.SubjectId, t.TrialId, t.Status }))
|
||||
{
|
||||
var subjectId = g.Key.SubjectId;
|
||||
var trialId = g.Key.TrialId;
|
||||
|
||||
//访视结束,那么就不处理
|
||||
if (g.Key.Status == SubjectStatus.EndOfVisit)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// 预先处理1: 数据库可能有已存在的subject 患者绑定,在这里要一起考虑绑定
|
||||
|
||||
var dbPatientIdList = _subjectPatientRepository.Where(t => t.SubjectId == subjectId).Select(t => t.PatientId).ToList();
|
||||
|
||||
// 预先处理2: 删除未提交的所有绑定的检查记录,所有检查一起考虑绑定
|
||||
|
||||
await _studySubjectVisitRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId && t.SubjectVisit.SubmitState != SubmitStateEnum.Submitted);
|
||||
|
||||
//预处理3 找到该subjecct 已提交的访视的最大检查时间,绑定的检查时间要比这个时间要大
|
||||
|
||||
var maxStudyTime = allSubjectVisitList.Where(t => t.SubjectId == subjectId && t.SubmitState == SubmitStateEnum.Submitted).MaxOrDefault(t => t.MaxStudyTime);
|
||||
|
||||
|
||||
// 预处理4: 处理需要绑定的检查
|
||||
//获取 该受试者绑定患者已存在的检查,考虑要生成多少个访视,去除已提交的检查
|
||||
|
||||
var studyList = await _studyRepository.Where(t => dbPatientIdList.Contains(t.PatientId)
|
||||
&& !t.SCPStudySubjectVisitList.Any(t => t.SubjectId == subjectId && t.SubjectVisit.SubmitState == SubmitStateEnum.Submitted))
|
||||
.WhereIf(maxStudyTime != null, t => t.StudyTime > maxStudyTime)
|
||||
.Select(t => new AuToBindingStudyInfo { SCPStudyId = t.Id, StudyTime = t.StudyTime }).OrderBy(t => t.StudyTime).ToListAsync();
|
||||
|
||||
await DealAutoBindingStudyAsync(trialId, subjectId, studyList);
|
||||
|
||||
|
||||
}
|
||||
|
||||
await _subjectVisitRepository.SaveChangesAsync();
|
||||
}
|
||||
|
||||
//将检查设置为传输结束
|
||||
await _studyRepository.BatchUpdateNoTrackingAsync(t => scpStudyIdList.Contains(t.Id), u => new SCPStudy() { IsUploadFinished = true });
|
||||
|
||||
return ResponseOutput.Ok();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "MinIO",
|
||||
"MinIO": {
|
||||
"EndPoint": "192.168.3.112",
|
||||
"Port": "9000",
|
||||
"UseSSL": false,
|
||||
"AccessKeyId": "Jnywl9aIw83yewZIJKod",
|
||||
"SecretAccessKey": "N83bTzoJGkg4OLW8x54IZRwwSvdxcdYi9UZ2BYII",
|
||||
"BucketName": "hir-images",
|
||||
"ViewEndpoint": "http://192.168.3.112:9000/hir-images"
|
||||
}
|
||||
},
|
||||
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=192.168.3.114,1433;Database=Prod_HIR_Images;User ID=sa;Password=xc_123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=192.168.3.114,1433;Database=Prod_HIR_Hangfire;User ID=sa;Password=xc_123456;TrustServerCertificate=true"
|
||||
},
|
||||
"DicomSCPServiceConfig": {
|
||||
"CalledAEList": [
|
||||
"STORESCP",
|
||||
"HIRAE",
|
||||
"Value2",
|
||||
"Value3"
|
||||
],
|
||||
"ServerPort": 11112
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "AliyunOSS",
|
||||
"AliyunOSS": {
|
||||
"RegionId": "cn-shanghai",
|
||||
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"AccessKeyId": "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
|
||||
}
|
||||
},
|
||||
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=prod_mssql_standard,1433;Database=Prod_IRC;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=prod_mssql_standard,1433;Database=Prod_IRC_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true"
|
||||
},
|
||||
|
||||
"DicomSCPServiceConfig": {
|
||||
"CalledAEList": [
|
||||
"STORESCP"
|
||||
],
|
||||
"ServerPort": 11112
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "MinIO",
|
||||
"MinIO": {
|
||||
"EndPoint": "192.168.40.99",
|
||||
"Port": "9000",
|
||||
"UseSSL": false,
|
||||
"AccessKeyId": "Jnywl9aIw83yewZIJKod",
|
||||
"SecretAccessKey": "N83bTzoJGkg4OLW8x54IZRwwSvdxcdYi9UZ2BYII",
|
||||
"BucketName": "tj-hir",
|
||||
"ViewEndpoint": "http://192.168.40.99:9000/tj-hir"
|
||||
}
|
||||
},
|
||||
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=192.168.40.98,1433;Database=TJ_Prod_HIR;User ID=sa;Password=xc_123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=192.168.40.98,1433;Database=TJ_Prod_HIR_Hangfire;User ID=sa;Password=xc_123456;TrustServerCertificate=true"
|
||||
},
|
||||
"DicomSCPServiceConfig": {
|
||||
"CalledAEList": [
|
||||
"STORESCP",
|
||||
"HIRAE",
|
||||
"Value2",
|
||||
"Value3"
|
||||
],
|
||||
"ServerPort": 11112
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "MinIO",
|
||||
"MinIO": {
|
||||
"EndPoint": "106.14.89.110",
|
||||
"Port": "9001",
|
||||
"UseSSL": false,
|
||||
"AccessKeyId": "fbStsVYCIPKHQneeqMwD",
|
||||
"SecretAccessKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
|
||||
"BucketName": "hir-test",
|
||||
"ViewEndpoint": "http://106.14.89.110:9001/hir-test/"
|
||||
}
|
||||
},
|
||||
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=106.14.89.110,1435;Database=Test_HIR_New;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=106.14.89.110,1435;Database=Test_HIR_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
},
|
||||
"DicomSCPServiceConfig": {
|
||||
"CalledAEList": [
|
||||
"STORESCP",
|
||||
"HIRAE",
|
||||
"Value2",
|
||||
"Value3"
|
||||
],
|
||||
"ServerPort": 11112
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "AliyunOSS",
|
||||
"AliyunOSS": {
|
||||
"RegionId": "cn-shanghai",
|
||||
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"AccessKeyId": "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": {
|
||||
"endPoint": "106.14.89.110",
|
||||
"port": "9001",
|
||||
"useSSL": false,
|
||||
"accessKey": "fbStsVYCIPKHQneeqMwD",
|
||||
"secretKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
|
||||
"bucketName": "hir-test",
|
||||
"viewEndpoint": "http://106.14.89.110:9001/hir-test/"
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
"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"
|
||||
},
|
||||
|
||||
"DicomSCPServiceConfig": {
|
||||
"CalledAEList": [
|
||||
"STORESCP"
|
||||
],
|
||||
"ServerPort": 11112
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "MinIO",
|
||||
"MinIO": {
|
||||
"EndPoint": "3.226.182.187",
|
||||
"Port": "9001",
|
||||
"UseSSL": false,
|
||||
"AccessKeyId": "7rvVIHs7D6pbyscRcJhz",
|
||||
"SecretAccessKey": "DQsCQldHFL3QRjlnaLWV7oM4E9PtsO21QPC2h9BD",
|
||||
"BucketName": "hir-us",
|
||||
"ViewEndpoint": "http://hir-minio.uat.elevateimaging.ai/hir-us"
|
||||
}
|
||||
},
|
||||
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=3.226.182.187,1435;Database=US_HIR;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=3.226.182.187,1435;Database=US_HIR_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
},
|
||||
"DicomSCPServiceConfig": {
|
||||
"CalledAEList": [
|
||||
"STORESCP",
|
||||
"HIRAE",
|
||||
"Value2",
|
||||
"Value3"
|
||||
],
|
||||
"ServerPort": 11112
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "AWS",
|
||||
"AWS": {
|
||||
"Region": "us-east-1",
|
||||
"EndPoint": "s3.us-east-1.amazonaws.com",
|
||||
"UseSSL": true,
|
||||
"RoleArn": "arn:aws:iam::471112624751:role/lili_s3_access",
|
||||
"AccessKeyId": "AKIAW3MEAFJXZ2TZK7GM",
|
||||
"SecretAccessKey": "9MLQCQ1HifEVW1gf068zBRAOb4wNnfrOkvBVByth",
|
||||
"BucketName": "ei-med-s3-lili-store",
|
||||
"ViewEndpoint": "https://ei-med-s3-lili-store.s3.amazonaws.com",
|
||||
"DurationSeconds": 7200
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=us-prod-mssql-service,1433;Database=US_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=us-prod-mssql-service,1433;Database=US_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
},
|
||||
"DicomSCPServiceConfig": {
|
||||
"CalledAEList": [
|
||||
"STORESCP"
|
||||
],
|
||||
"ServerPort": 11112
|
||||
}
|
||||
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "AWS",
|
||||
"AWS": {
|
||||
"Region": "us-east-1",
|
||||
"EndPoint": "s3.us-east-1.amazonaws.com",
|
||||
"UseSSL": true,
|
||||
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
|
||||
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
|
||||
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
|
||||
"BucketName": "ei-med-s3-lili-uat-store",
|
||||
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com/",
|
||||
"DurationSeconds": 7200
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=us-mssql-service,1433;Database=US_Uat_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=us-mssql-service,1433;Database=US_Uat_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
},
|
||||
"DicomSCPServiceConfig": {
|
||||
"CalledAEList": [
|
||||
"STORESCP"
|
||||
],
|
||||
"ServerPort": 11112
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "MinIO",
|
||||
"MinIO": {
|
||||
"EndPoint": "101.132.253.119",
|
||||
"Port": "9001",
|
||||
"UseSSL": false,
|
||||
"AccessKeyId": "ylWQa99fDdVdTfnj47ll",
|
||||
"SecretAccessKey": "kVpy2RIYN0GmyFsU2qAWhbKDf4Nskt23tEqd6sob",
|
||||
"BucketName": "hir-uat",
|
||||
"ViewEndpoint": "http://101.132.253.119:9001/hir-uat/"
|
||||
}
|
||||
},
|
||||
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=101.132.253.119,1435;Database=Uat_HIR_New;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=101.132.253.119,1435;Database=Uat_HIR_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
},
|
||||
|
||||
|
||||
"DicomSCPServiceConfig": {
|
||||
"CalledAEList": [
|
||||
"STORESCP",
|
||||
"HIRAE",
|
||||
"Value2",
|
||||
"Value3"
|
||||
],
|
||||
"ServerPort": 11112
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "AliyunOSS",
|
||||
"AliyunOSS": {
|
||||
"RegionId": "cn-shanghai",
|
||||
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"AccessKeyId": "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"
|
||||
},
|
||||
"DicomSCPServiceConfig": {
|
||||
"CalledAEList": [
|
||||
"STORESCP"
|
||||
],
|
||||
"ServerPort": 11112
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using Amazon.Auth.AccessControlPolicy;
|
||||
using AlibabaCloud.SDK.Sts20150401;
|
||||
using Amazon.Auth.AccessControlPolicy;
|
||||
using Amazon.SecurityToken;
|
||||
using Azure.Core;
|
||||
using IdentityModel.Client;
|
||||
|
@ -24,6 +25,7 @@ using RestSharp;
|
|||
using RestSharp.Authenticators;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
|
@ -101,6 +103,80 @@ namespace IRaCIS.Api.Controllers
|
|||
|
||||
|
||||
|
||||
[HttpGet, Route("user/loginSelectUserType")]
|
||||
public async Task<IResponseOutput<LoginReturnDTO>> LoginSelectUserType(Guid userId, Guid userTypeId,
|
||||
[FromServices] IUserService _userService,
|
||||
[FromServices] IFusionCache _fusionCache,
|
||||
[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 };
|
||||
|
||||
var returnModel = await _userService.LoginSelectUserType(userId, userTypeId);
|
||||
|
||||
if (returnModel.IsSuccess)
|
||||
{
|
||||
if (_verifyConfig.CurrentValue.OpenLoginMFA)
|
||||
{
|
||||
//MFA 发送邮件
|
||||
|
||||
returnModel.Data.IsMFA = true;
|
||||
|
||||
var email = returnModel.Data.BasicInfo.EMail;
|
||||
|
||||
var hiddenEmail = IRCEmailPasswordHelper.MaskEmail(email);
|
||||
|
||||
returnModel.Data.BasicInfo.EMail = hiddenEmail;
|
||||
|
||||
//修改密码
|
||||
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
|
||||
{
|
||||
returnModel.Data.JWTStr = _tokenService.GetToken(IRaCISClaims.Create(returnModel.Data.BasicInfo));
|
||||
|
||||
// 创建一个 CookieOptions 对象,用于设置 Cookie 的属性
|
||||
var option = new CookieOptions
|
||||
{
|
||||
Expires = DateTime.Now.AddMonths(1), // 设置过期时间为 30 分钟之后
|
||||
HttpOnly = false, // 确保 cookie 只能通过 HTTP 访问
|
||||
SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None, // 设置 SameSite 属性
|
||||
Secure = false // 确保 cookie 只能通过 HTTPS 访问
|
||||
};
|
||||
|
||||
HttpContext.Response.Cookies.Append("access_token", returnModel.Data.JWTStr, option);
|
||||
|
||||
|
||||
|
||||
// 验证阅片休息时间
|
||||
await readingImageTaskService.ResetReadingRestTime(returnModel.Data.BasicInfo.Id);
|
||||
|
||||
await _fusionCache.SetAsync(CacheKeys.UserToken(userId), returnModel.Data.JWTStr, TimeSpan.FromDays(7));
|
||||
|
||||
await _fusionCache.SetAsync(CacheKeys.UserAutoLoginOut(userId), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(_verifyConfig.CurrentValue.AutoLoginOutMinutes));
|
||||
}
|
||||
}
|
||||
|
||||
returnModel.Data.CompanyInfo = companyInfo;
|
||||
|
||||
return returnModel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -325,6 +401,7 @@ namespace IRaCIS.Api.Controllers
|
|||
}
|
||||
|
||||
[HttpGet("user/GetObjectStoreToken")]
|
||||
[AllowAnonymous]
|
||||
public async Task<IResponseOutput> GetObjectStoreTokenAsync([FromServices] IOptionsMonitor<ObjectStoreServiceOptions> options, [FromServices] IOSSService _oSSService)
|
||||
{
|
||||
|
||||
|
@ -374,7 +451,53 @@ namespace IRaCIS.Api.Controllers
|
|||
return tempToken;
|
||||
}
|
||||
|
||||
#region 老项目依赖
|
||||
|
||||
[HttpGet("user/GenerateSTS")]
|
||||
public IResponseOutput GenerateSTS([FromServices] IOptionsMonitor<ObjectStoreServiceOptions> options)
|
||||
{
|
||||
|
||||
var ossOptions = options.CurrentValue.AliyunOSS;
|
||||
|
||||
var client = new Client(new AlibabaCloud.OpenApiClient.Models.Config()
|
||||
{
|
||||
AccessKeyId = ossOptions.AccessKeyId,
|
||||
AccessKeySecret = ossOptions.AccessKeySecret,
|
||||
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;
|
||||
|
||||
|
||||
|
||||
// 返回STS令牌信息给前端
|
||||
var stsToken = new
|
||||
{
|
||||
AccessKeyId = credentials.AccessKeyId,
|
||||
AccessKeySecret = credentials.AccessKeySecret,
|
||||
SecurityToken = credentials.SecurityToken,
|
||||
Expiration = credentials.Expiration,
|
||||
|
||||
Region = ossOptions.Region,
|
||||
BucketName = ossOptions.BucketName,
|
||||
ViewEndpoint = ossOptions.ViewEndpoint,
|
||||
|
||||
};
|
||||
|
||||
return ResponseOutput.Ok(stsToken);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
[HttpGet("User/UserRedirect")]
|
||||
|
|
|
@ -112,6 +112,48 @@
|
|||
<Content Update="Resources\zh-CN.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\ReadReoprtTemplate\downLoad\file.txt">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\ReadReoprtTemplate\ReportTemplate_IRECIST_CN_V1.docx">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\ReadReoprtTemplate\ReportTemplate_PCWG3_CN_V1.docx">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\ReadReoprtTemplate\ReportTemplate_RECIST1.1_CN_V1.docx">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\ReadReoprtTemplate\TumorEvaluation_RECIST1.1_CN_V1.docx">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\ReadReoprtTemplate\医院模板\协和\ReportTemplate_IRECIST_CN_V1.docx">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\ReadReoprtTemplate\医院模板\协和\ReportTemplate_PCWG3_CN_V1.docx">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\ReadReoprtTemplate\医院模板\协和\ReportTemplate_RECIST1.1_CN_V1.docx">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\ReadReoprtTemplate\医院模板\同济\ReportTemplate_IRECIST_CN_V1.docx">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\ReadReoprtTemplate\医院模板\同济\ReportTemplate_PCWG3_CN_V1.docx">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\ReadReoprtTemplate\医院模板\同济\ReportTemplate_RECIST1.1_CN_V1.docx">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\ReadReoprtTemplate\医院模板\复旦大学肿瘤附属医院\ReportTemplate_IRECIST_CN_V1.docx">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\ReadReoprtTemplate\医院模板\复旦大学肿瘤附属医院\ReportTemplate_PCWG3_CN_V1.docx">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\ReadReoprtTemplate\医院模板\复旦大学肿瘤附属医院\ReportTemplate_RECIST1.1_CN_V1.docx">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ProjectExtensions>
|
||||
|
|
|
@ -16,60 +16,31 @@
|
|||
"ASPNETCORE_ENVIRONMENT": "Test_IRC"
|
||||
}
|
||||
},
|
||||
"IRaCIS.Test_IRC": {
|
||||
"Uat_HIR": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Test_IRC"
|
||||
"ASPNETCORE_ENVIRONMENT": "Uat_HIR"
|
||||
},
|
||||
"applicationUrl": "http://localhost:6100"
|
||||
},
|
||||
"IRaCIS.Test_IRC_PGSQL": {
|
||||
"Prod_HIR": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Test_IRC_PGSQL"
|
||||
"ASPNETCORE_ENVIRONMENT": "Prod_HIR"
|
||||
},
|
||||
"applicationUrl": "http://localhost:6100"
|
||||
},
|
||||
"IRaCIS.Event_IRC": {
|
||||
"Test_HIR": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Event_IRC"
|
||||
},
|
||||
"applicationUrl": "http://localhost:6100"
|
||||
},
|
||||
"Docker": {
|
||||
"commandName": "Docker",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
|
||||
"publishAllPorts": true
|
||||
},
|
||||
"IRaCIS.Uat_IRC": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Uat_IRC"
|
||||
},
|
||||
"applicationUrl": "http://localhost:6100"
|
||||
},
|
||||
"IRaCIS.Prod_IRC": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Prod_IRC"
|
||||
},
|
||||
"applicationUrl": "http://localhost:6100"
|
||||
},
|
||||
"IRaCIS.US_Uat_IRC": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "US_Uat_IRC"
|
||||
"ASPNETCORE_ENVIRONMENT": "Test_HIR"
|
||||
},
|
||||
"applicationUrl": "http://localhost:6100"
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
using FellowOakDicom;
|
||||
using FellowOakDicom.Imaging;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
|
@ -9,12 +10,14 @@ namespace IRaCIS.Core.API
|
|||
public static void AddDicomSetup(this IServiceCollection services)
|
||||
{
|
||||
new DicomSetupBuilder()
|
||||
.RegisterServices(s => s.AddFellowOakDicom()
|
||||
.AddTranscoderManager<FellowOakDicom.Imaging.NativeCodec.NativeTranscoderManager>()
|
||||
.AddImageManager<ImageSharpImageManager>()
|
||||
.RegisterServices(s => s.AddFellowOakDicom().AddLogging(config => config.AddConsole())
|
||||
.AddTranscoderManager<FellowOakDicom.Imaging.NativeCodec.NativeTranscoderManager>()
|
||||
//.AddImageManager<ImageSharpImageManager>()
|
||||
)
|
||||
.SkipValidation()
|
||||
.Build();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,8 +80,13 @@ namespace IRaCIS.Core.API
|
|||
triggerOptions.AddTrigger<UserLogTrigger>();
|
||||
|
||||
triggerOptions.AddTrigger<UserAddTrigger>();
|
||||
|
||||
triggerOptions.AddTrigger<UserModifyTrigger>();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using IP2Region.Net.Abstractions;
|
||||
using IP2Region.Net.XDB;
|
||||
using IRaCIS.Application.Contracts;
|
||||
using IRaCIS.Core.Application.BackGroundJob;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Core.Application.Service;
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=47.117.164.182,1434;Database=Event_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=47.117.164.182,1434;Database=Event_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
},
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "AliyunOSS",
|
||||
"AliyunOSS": {
|
||||
"RegionId": "cn-shanghai",
|
||||
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"AccessKeyId": "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",
|
||||
"port": "8001",
|
||||
"useSSL": false,
|
||||
"accessKey": "IDFkwEpWej0b4DtiuThL",
|
||||
"secretKey": "Lhuu83yMhVwu7c1SnjvGY6lq74jzpYqifK6Qtj4h",
|
||||
"bucketName": "test"
|
||||
}
|
||||
},
|
||||
|
||||
"BasicSystemConfig": {
|
||||
|
||||
"OpenUserComplexPassword": true,
|
||||
|
||||
"OpenSignDocumentBeforeWork": true,
|
||||
|
||||
"OpenLoginLimit": true,
|
||||
"LoginMaxFailCount": 5,
|
||||
|
||||
"LoginFailLockMinutes": 30,
|
||||
"AutoLoginOutMinutes": 60,
|
||||
|
||||
"ContinuousReadingTimeMin": 120,
|
||||
|
||||
"ReadingRestTimeMin": 10,
|
||||
|
||||
"IsNeedChangePassWord": true,
|
||||
|
||||
"ChangePassWordDays": 90
|
||||
},
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"FromEmail": "uat@extimaging.com",
|
||||
"FromName": "UAT_IRC",
|
||||
"AuthorizationCode": "SHzyyl2021",
|
||||
"SiteUrl": "http://irc.event.extimaging.com/login",
|
||||
"CompanyName": "Extensive Imaging",
|
||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||
"CompanyShortName": "Extensive Imaging",
|
||||
"CompanyShortNameCN": "展影医疗",
|
||||
"IsEnv_US": false
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "MinIO",
|
||||
"MinIO": {
|
||||
"EndPoint": "192.168.3.112",
|
||||
"Port": "9080",
|
||||
"UseSSL": true,
|
||||
"AccessKeyId": "Jnywl9aIw83yewZIJKod",
|
||||
"SecretAccessKey": "N83bTzoJGkg4OLW8x54IZRwwSvdxcdYi9UZ2BYII",
|
||||
"BucketName": "hir-images",
|
||||
"ViewEndpoint": "https://192.168.3.112:9080/hir-images"
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=192.168.3.114,1433;Database=Prod_HIR_Images;User ID=sa;Password=xc_123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=192.168.3.114,1433;Database=Prod_HIR_Hangfire;User ID=sa;Password=xc_123456;TrustServerCertificate=true"
|
||||
},
|
||||
"BasicSystemConfig": {
|
||||
"OpenUserComplexPassword": true,
|
||||
"OpenSignDocumentBeforeWork": false,
|
||||
"OpenTrialRelationDelete": false,
|
||||
"OpenLoginLimit": true,
|
||||
"LoginMaxFailCount": 5,
|
||||
"LoginFailLockMinutes": 30,
|
||||
"AutoLoginOutMinutes": 120,
|
||||
"AESKey": "HIR_System_AES_Key_Info",
|
||||
"CmoveIntervalMinutes": 1,
|
||||
"CmoveInstanceIntervalMinutes": 1
|
||||
},
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"FromEmail": "test-study@extimaging.com",
|
||||
"FromName": "Test_HIR",
|
||||
"AuthorizationCode": "zhanying123",
|
||||
"SiteUrl": "http://hir.test.extimaging.com/login"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
//"RemoteNew": "Server=101.132.193.237,1434;Database=Prod_IRC;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true",
|
||||
//"Hangfire": "Server=101.132.193.237,1434;Database=Prod_IRC_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true"
|
||||
"RemoteNew": "Server=prod_mssql_standard,1433;Database=Prod_IRC;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=prod_mssql_standard,1433;Database=Prod_IRC_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true"
|
||||
},
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "AliyunOSS",
|
||||
"AliyunOSS": {
|
||||
"RegionId": "cn-shanghai",
|
||||
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"AccessKeyId": "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",
|
||||
"port": "8001",
|
||||
"useSSL": false,
|
||||
"accessKey": "IDFkwEpWej0b4DtiuThL",
|
||||
"secretKey": "Lhuu83yMhVwu7c1SnjvGY6lq74jzpYqifK6Qtj4h",
|
||||
"bucketName": "test"
|
||||
}
|
||||
},
|
||||
"BasicSystemConfig": {
|
||||
|
||||
"OpenUserComplexPassword": true,
|
||||
"OpenSignDocumentBeforeWork": true,
|
||||
|
||||
"OpenLoginLimit": true,
|
||||
"LoginMaxFailCount": 5,
|
||||
"LoginFailLockMinutes": 30,
|
||||
|
||||
"AutoLoginOutMinutes": 360,
|
||||
|
||||
"OpenLoginMFA": false,
|
||||
|
||||
"ContinuousReadingTimeMin": 120,
|
||||
|
||||
"ReadingRestTimeMin": 10,
|
||||
|
||||
"IsNeedChangePassWord": true,
|
||||
|
||||
"ChangePassWordDays": 90
|
||||
},
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"FromEmail": "IRC@extimaging.com",
|
||||
"FromName": "IRC",
|
||||
"AuthorizationCode": "ExtImg@2022",
|
||||
"SiteUrl": "http://irc.extimaging.com/login",
|
||||
"OrganizationName": "Extlmaging",
|
||||
"OrganizationNameCN": "Extlmaging",
|
||||
"CompanyName": "Extensive Imaging",
|
||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||
"CompanyShortName": "Extensive Imaging",
|
||||
"CompanyShortNameCN": "展影医疗",
|
||||
"IsEnv_US": false,
|
||||
"IsOpenErrorNoticeEmail": true,
|
||||
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
|
||||
},
|
||||
"SystemPacsConfig": {
|
||||
"Port": "11113",
|
||||
"IP": "101.132.193.237"
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "MinIO",
|
||||
"MinIO": {
|
||||
"EndPoint": "192.168.40.99",
|
||||
"Port": "9000",
|
||||
"UseSSL": false,
|
||||
"AccessKeyId": "Jnywl9aIw83yewZIJKod",
|
||||
"SecretAccessKey": "N83bTzoJGkg4OLW8x54IZRwwSvdxcdYi9UZ2BYII",
|
||||
"BucketName": "tj-hir",
|
||||
"ViewEndpoint": "http://192.168.40.99:9000/tj-hir"
|
||||
}
|
||||
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=192.168.40.98,1433;Database=TJ_Prod_HIR;User ID=sa;Password=xc_123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=192.168.40.98,1433;Database=TJ_Prod_HIR_Hangfire;User ID=sa;Password=xc_123456;TrustServerCertificate=true"
|
||||
},
|
||||
"BasicSystemConfig": {
|
||||
"OpenUserComplexPassword": true,
|
||||
"OpenSignDocumentBeforeWork": false,
|
||||
"OpenTrialRelationDelete": false,
|
||||
"OpenLoginLimit": true,
|
||||
"LoginMaxFailCount": 5,
|
||||
"LoginFailLockMinutes": 30,
|
||||
"AutoLoginOutMinutes": 120,
|
||||
"AESKey": "HIR_System_AES_Key_Info",
|
||||
"CmoveIntervalMinutes": 1,
|
||||
"CmoveInstanceIntervalMinutes": 1
|
||||
},
|
||||
"SystemHospitalConfig": {
|
||||
"HospitalCode": "EI",
|
||||
"HospitalLogoPath": "/System/GeneralDocuments/1716453306898_图片2.png",
|
||||
"TrialKeepCount": 60,
|
||||
"HospitalName": "上海展影医疗科技有限公司",
|
||||
"HospitalAliasName": "展影医疗",
|
||||
"Country": "中国",
|
||||
"City": "上海",
|
||||
"Province": "上海",
|
||||
"Address": "上海市杨浦区国泰路复旦科技园",
|
||||
"Phone": "021-60702575",
|
||||
"IsCanConnectInternet": false
|
||||
},
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"FromEmail": "test-study@extimaging.com",
|
||||
"FromName": "Test_HIR",
|
||||
"AuthorizationCode": "zhanying123",
|
||||
"SiteUrl": "http://hir.test.extimaging.com/login"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "MinIO",
|
||||
"MinIO": {
|
||||
"EndPoint": "hir-oss.test.extimaging.com",
|
||||
"Port": "443",
|
||||
"UseSSL": true,
|
||||
//"endPoint": "106.14.89.110",
|
||||
//"port": "9001",
|
||||
//"useSSL": false,
|
||||
"AccessKeyId": "fbStsVYCIPKHQneeqMwD",
|
||||
"SecretAccessKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
|
||||
"BucketName": "hir-test",
|
||||
//"viewEndpoint": "https://hir.test.extimaging.com/oss/hir-test"
|
||||
"ViewEndpoint": "https://hir-oss.test.extimaging.com/hir-test"
|
||||
}
|
||||
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=106.14.89.110,1435;Database=Test_HIR_New;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=106.14.89.110,1435;Database=Test_HIR_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
},
|
||||
"BasicSystemConfig": {
|
||||
"OpenUserComplexPassword": true,
|
||||
"OpenSignDocumentBeforeWork": true,
|
||||
"OpenTrialRelationDelete": true,
|
||||
"OpenLoginLimit": true,
|
||||
"LoginMaxFailCount": 5,
|
||||
"LoginFailLockMinutes": 30,
|
||||
"AutoLoginOutMinutes": 120,
|
||||
"AESKey": "HIR_System_AES_Key_Info",
|
||||
"CmoveIntervalMinutes": 1,
|
||||
"CmoveInstanceIntervalMinutes": 1
|
||||
},
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"FromEmail": "test-study@extimaging.com",
|
||||
"FromName": "Test_HIR",
|
||||
"AuthorizationCode": "zhanying123",
|
||||
"SiteUrl": "http://hir.test.extimaging.com/login"
|
||||
}
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"Db_Type": "pgsql",
|
||||
"RemoteNew": "Host=106.14.89.110;Port=5432;Username=sa;Password=pgsql_pwd;Database=Test2_PG",
|
||||
"Hangfire": "Server=106.14.89.110,1435;Database=Test_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
},
|
||||
|
||||
"ObjectStoreService": {
|
||||
|
||||
"ObjectStoreUse": "AliyunOSS",
|
||||
|
||||
"AliyunOSS": {
|
||||
"regionId": "cn-shanghai",
|
||||
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||
"endPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||
"bucketName": "zy-irc-test-store",
|
||||
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
||||
"viewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
|
||||
"region": "oss-cn-shanghai"
|
||||
},
|
||||
"MinIO": {
|
||||
"endPoint": "hir-oss.test.extimaging.com",
|
||||
"port": "443",
|
||||
"useSSL": true,
|
||||
"accessKey": "fbStsVYCIPKHQneeqMwD",
|
||||
"secretKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
|
||||
"bucketName": "irc-test",
|
||||
"viewEndpoint": "https://hir-oss.test.extimaging.com/irc-test"
|
||||
},
|
||||
"AWS": {
|
||||
"endPoint": "s3.us-east-1.amazonaws.com",
|
||||
"useSSL": true,
|
||||
"accessKey": "AKIAZQ3DRSOHFPJJ6FEU",
|
||||
"secretKey": "l+yjtvV7Z4jiwm/7xCYv30UeUj/SvuqqYzAwjJHf",
|
||||
"bucketName": "ei-irc-test-store",
|
||||
"viewEndpoint": "https://ei-irc-test-store.s3.amazonaws.com/"
|
||||
}
|
||||
},
|
||||
|
||||
"BasicSystemConfig": {
|
||||
|
||||
"OpenUserComplexPassword": false,
|
||||
|
||||
"OpenSignDocumentBeforeWork": false,
|
||||
|
||||
"OpenTrialRelationDelete": true,
|
||||
|
||||
"OpenLoginLimit": false,
|
||||
|
||||
"LoginMaxFailCount": 5,
|
||||
|
||||
"LoginFailLockMinutes": 1,
|
||||
|
||||
"AutoLoginOutMinutes": 1,
|
||||
|
||||
"OpenLoginMFA": false,
|
||||
|
||||
"ContinuousReadingTimeMin": 120,
|
||||
|
||||
"ReadingRestTimeMin": 10,
|
||||
"IsNeedChangePassWord": true,
|
||||
|
||||
"ChangePassWordDays": 90
|
||||
},
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"FromEmail": "test@extimaging.com",
|
||||
"FromName": "Test_IRC",
|
||||
"AuthorizationCode": "SHzyyl2021",
|
||||
"SiteUrl": "http://irc.test.extimaging.com/login",
|
||||
|
||||
"OrganizationName": "Extlmaging",
|
||||
"OrganizationNameCN": "Extlmaging",
|
||||
"CompanyName": "Extensive Imaging",
|
||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||
"CompanyShortName": "Extensive Imaging",
|
||||
"CompanyShortNameCN": "展影医疗"
|
||||
},
|
||||
|
||||
"SystemPacsConfig": {
|
||||
"Port": "11113",
|
||||
"IP": "106.14.89.110"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "MinIO",
|
||||
"MinIO": {
|
||||
"EndPoint": "hir-minio.uat.elevateimaging.ai",
|
||||
"Port": "443",
|
||||
"UseSSL": true,
|
||||
"AccessKeyId": "7rvVIHs7D6pbyscRcJhz",
|
||||
"SecretAccessKey": "DQsCQldHFL3QRjlnaLWV7oM4E9PtsO21QPC2h9BD",
|
||||
"BucketName": "hir-us",
|
||||
//"viewEndpoint": "https://hir.test.extimaging.com/oss/hir-test"
|
||||
"ViewEndpoint": "https://hir-minio.uat.elevateimaging.ai/hir-us"
|
||||
}
|
||||
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=3.226.182.187,1435;Database=US_HIR;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=3.226.182.187,1435;Database=US_HIR_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
},
|
||||
"BasicSystemConfig": {
|
||||
"OpenUserComplexPassword": true,
|
||||
"OpenSignDocumentBeforeWork": true,
|
||||
"OpenTrialRelationDelete": true,
|
||||
"OpenLoginLimit": true,
|
||||
"LoginMaxFailCount": 5,
|
||||
"LoginFailLockMinutes": 30,
|
||||
"AutoLoginOutMinutes": 120,
|
||||
"AESKey": "HIR_System_AES_Key_Info",
|
||||
"CmoveIntervalMinutes": 1,
|
||||
"CmoveInstanceIntervalMinutes": 1
|
||||
},
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"FromEmail": "uat-study@extimaging.com",
|
||||
"FromName": "Uat_HIR",
|
||||
"AuthorizationCode": "zhanying123",
|
||||
"SiteUrl": "https://hir.uat.elevateimaging.ai/login"
|
||||
}
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=us-prod-mssql-service,1433;Database=US_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=us-prod-mssql-service,1433;Database=US_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
//"RemoteNew": "Server=44.210.231.169,1435;Database=US_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
//"Hangfire": "Server=44.210.231.169,1435;Database=US_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
},
|
||||
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "AWS",
|
||||
"MinIO": {
|
||||
"endPoint": "44.210.231.169",
|
||||
"port": "9001",
|
||||
"useSSL": false,
|
||||
"accessKey": "e9bT1isTOqSAUxb6wd4n",
|
||||
"secretKey": "b5TaDzNdQCBtCvfm8eZ3dR6yY7tfZu2JYze2Po1i",
|
||||
"bucketName": "prod-irc-us",
|
||||
"viewEndpoint": "http://44.210.231.169:9001/prod-irc-us/"
|
||||
},
|
||||
|
||||
"AWS": {
|
||||
"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": {
|
||||
|
||||
"OpenUserComplexPassword": false,
|
||||
|
||||
"OpenSignDocumentBeforeWork": false,
|
||||
|
||||
"OpenTrialRelationDelete": true,
|
||||
|
||||
"OpenLoginLimit": false,
|
||||
|
||||
"LoginMaxFailCount": 5,
|
||||
|
||||
"LoginFailLockMinutes": 30,
|
||||
"AutoLoginOutMinutes": 60,
|
||||
|
||||
"ContinuousReadingTimeMin": 120,
|
||||
|
||||
"ReadingRestTimeMin": 10,
|
||||
"IsNeedChangePassWord": true,
|
||||
|
||||
"ChangePassWordDays": 90
|
||||
},
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 587,
|
||||
"Host": "smtp-mail.outlook.com",
|
||||
"FromEmail": "donotreply@elevateimaging.ai",
|
||||
"FromName": "LiLi",
|
||||
"AuthorizationCode": "Q#669869497420ul",
|
||||
|
||||
"OrganizationName": "Elevate Imaging",
|
||||
"OrganizationNameCN": "Elevate Imaging",
|
||||
"CompanyName": "Elevate Imaging Inc.",
|
||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||
"CompanyShortName": "Elevate Imaging",
|
||||
"CompanyShortNameCN": "展影医疗",
|
||||
"SiteUrl": "https://lili.elevateimaging.ai/login",
|
||||
"IsEnv_US": true,
|
||||
"IsOpenErrorNoticeEmail": true,
|
||||
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
|
||||
},
|
||||
|
||||
"SystemPacsConfig": {
|
||||
"Port": "104",
|
||||
"IP": "44.210.231.169"
|
||||
}
|
||||
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=106.14.89.110,1435;Database=Test_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=106.14.89.110,1435;Database=Test_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
},
|
||||
|
||||
"ObjectStoreService": {
|
||||
|
||||
"ObjectStoreUse": "AWS",
|
||||
"MinIO": {
|
||||
//"endPoint": "hir-oss.uat.extimaging.com",
|
||||
//"port": "443",
|
||||
//"useSSL": true,
|
||||
//"viewEndpoint": "https://hir-oss.uat.extimaging.com/hir-uat",
|
||||
|
||||
"endPoint": "47.117.164.182",
|
||||
"port": "9001",
|
||||
"useSSL": false,
|
||||
"viewEndpoint": "http://47.117.164.182:9001/test-irc-us",
|
||||
|
||||
"accessKey": "b9Ul0e98xPzt6PwRXA1Q",
|
||||
"secretKey": "DzMaU2L4OXl90uytwOmDXF2encN0Jf4Nxu2XkYqQ",
|
||||
"bucketName": "test-irc-us"
|
||||
|
||||
},
|
||||
|
||||
"AWS": {
|
||||
"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": true,
|
||||
|
||||
"OpenSignDocumentBeforeWork": true,
|
||||
|
||||
"OpenTrialRelationDelete": true,
|
||||
|
||||
"OpenLoginLimit": true,
|
||||
|
||||
"LoginMaxFailCount": 5,
|
||||
|
||||
"LoginFailLockMinutes": 30,
|
||||
"AutoLoginOutMinutes": 60,
|
||||
|
||||
"ContinuousReadingTimeMin": 120,
|
||||
|
||||
"ReadingRestTimeMin": 10,
|
||||
"IsNeedChangePassWord": true,
|
||||
|
||||
"ChangePassWordDays": 90,
|
||||
|
||||
"OpenLoginMFA": true
|
||||
},
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 587,
|
||||
"Host": "smtp-mail.outlook.com",
|
||||
"FromEmail": "donotreply@elevateimaging.ai",
|
||||
"FromName": "LiLi",
|
||||
"AuthorizationCode": "Q#669869497420ul",
|
||||
|
||||
"OrganizationName": "Elevate Imaging",
|
||||
"OrganizationNameCN": "Elevate Imaging",
|
||||
"CompanyName": "Elevate Imaging Inc.",
|
||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||
"CompanyShortName": "Elevate Imaging",
|
||||
"CompanyShortNameCN": "展影医疗",
|
||||
"SiteUrl": "https://lili.test.elevateimaging.ai/login",
|
||||
"IsEnv_US": true,
|
||||
"IsOpenErrorNoticeEmail": false,
|
||||
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
|
||||
},
|
||||
|
||||
"SystemPacsConfig": {
|
||||
"Port": "104",
|
||||
"IP": "3.226.182.187"
|
||||
}
|
||||
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
//"RemoteNew": "Server=us-mssql-service,1433;Database=US_Uat_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
//"Hangfire": "Server=us-mssql-service,1433;Database=US_Uat_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
|
||||
"RemoteNew": "Server=3.226.182.187,1435;Database=US_Uat_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=3.226.182.187,1435;Database=US_Uat_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
},
|
||||
|
||||
"ObjectStoreService": {
|
||||
|
||||
"ObjectStoreUse": "AWS",
|
||||
|
||||
"MinIO": {
|
||||
//"endPoint": "hir-minio.uat.elevateimaging.ai",
|
||||
//"port": "443",
|
||||
//"useSSL": true,
|
||||
//"viewEndpoint": "https://hir-minio.uat.elevateimaging.ai/uat-irc-us",
|
||||
|
||||
"endPoint": "3.226.182.187",
|
||||
"port": "9001",
|
||||
"useSSL": false,
|
||||
"viewEndpoint": "http://44.218.11.19:9001/uat-irc-us",
|
||||
|
||||
"accessKey": "lH8DkKskLuDqPaiubuSQ",
|
||||
"secretKey": "pdPdicvvLeH7xAC5yFUrI7odMyBfOXxvVWMvKYV4",
|
||||
"bucketName": "uat-irc-us"
|
||||
|
||||
},
|
||||
|
||||
"AWS": {
|
||||
"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": true,
|
||||
|
||||
"OpenSignDocumentBeforeWork": true,
|
||||
|
||||
"OpenTrialRelationDelete": true,
|
||||
|
||||
"OpenLoginLimit": false,
|
||||
|
||||
"LoginMaxFailCount": 5,
|
||||
|
||||
"LoginFailLockMinutes": 30,
|
||||
"AutoLoginOutMinutes": 60,
|
||||
|
||||
"ContinuousReadingTimeMin": 120,
|
||||
|
||||
"ReadingRestTimeMin": 10,
|
||||
"IsNeedChangePassWord": true,
|
||||
|
||||
"ChangePassWordDays": 90,
|
||||
|
||||
"OpenLoginMFA": false
|
||||
},
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 587,
|
||||
"Host": "smtp-mail.outlook.com",
|
||||
"FromEmail": "donotreply@elevateimaging.ai",
|
||||
"FromName": "LiLi",
|
||||
"AuthorizationCode": "Q#669869497420ul",
|
||||
|
||||
"OrganizationName": "Elevate Imaging",
|
||||
"OrganizationNameCN": "Elevate Imaging",
|
||||
"CompanyName": "Elevate Imaging Inc.",
|
||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||
"CompanyShortName": "Elevate Imaging",
|
||||
"CompanyShortNameCN": "展影医疗",
|
||||
"SiteUrl": "https://lili.test.elevateimaging.ai/login",
|
||||
"IsEnv_US": true,
|
||||
"IsOpenErrorNoticeEmail": false,
|
||||
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
|
||||
},
|
||||
|
||||
"SystemPacsConfig": {
|
||||
"Port": "104",
|
||||
"IP": "3.226.182.187"
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "MinIO",
|
||||
"MinIO": {
|
||||
"EndPoint": "hir-oss.uat.extimaging.com",
|
||||
"Port": "443",
|
||||
"UseSSL": true,
|
||||
//"endPoint": "106.14.89.110",
|
||||
//"port": "9001",
|
||||
//"useSSL": false,
|
||||
"AccessKeyId": "L6owzRVeDJJw3PcRmK2c",
|
||||
"SecretAccessKey": "2XvFDYSH7EyHQNtpDCgk4efgdsdarQmRKgx1LlOI",
|
||||
"BucketName": "hir-uat",
|
||||
"ViewEndpoint": "https://hir-oss.uat.extimaging.com/hir-uat"
|
||||
}
|
||||
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=101.132.253.119,1435;Database=Uat_HIR_New;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=101.132.253.119,1435;Database=Uat_HIR_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
},
|
||||
"BasicSystemConfig": {
|
||||
"OpenUserComplexPassword": true,
|
||||
"OpenSignDocumentBeforeWork": false,
|
||||
"OpenTrialRelationDelete": false,
|
||||
"OpenLoginLimit": true,
|
||||
"LoginMaxFailCount": 5,
|
||||
"LoginFailLockMinutes": 30,
|
||||
"AutoLoginOutMinutes": 120,
|
||||
"AESKey": "HIR_System_AES_Key_Info",
|
||||
"CmoveIntervalMinutes": 1,
|
||||
"CmoveInstanceIntervalMinutes": 1
|
||||
},
|
||||
"SystemHospitalConfig": {
|
||||
"HospitalCode": "EI",
|
||||
"HospitalLogoPath": "/System/GeneralDocuments/1716453306898_图片2.png",
|
||||
"TrialKeepCount": 60,
|
||||
"HospitalName": "上海展影医疗科技有限公司",
|
||||
"HospitalAliasName": "展影医疗",
|
||||
"Country": "中国",
|
||||
"City": "上海",
|
||||
"Province": "上海",
|
||||
"Address": "上海市杨浦区国泰路复旦科技园",
|
||||
"Phone": "021-60702575",
|
||||
"IsCanConnectInternet": false
|
||||
},
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"FromEmail": "test-study@extimaging.com",
|
||||
"FromName": "Test_HIR",
|
||||
"AuthorizationCode": "zhanying123",
|
||||
"SiteUrl": "http://hir.test.extimaging.com/login"
|
||||
}
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"ObjectStoreService": {
|
||||
|
||||
"ObjectStoreUse": "AliyunOSS",
|
||||
|
||||
"AliyunOSS": {
|
||||
"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": {
|
||||
"endPoint": "hir-oss.uat.extimaging.com",
|
||||
"port": "80",
|
||||
"useSSL": false,
|
||||
"viewEndpoint": "http://hir-oss.uat.extimaging.com/irc-uat",
|
||||
//"port": "443",
|
||||
//"useSSL": true,
|
||||
//"viewEndpoint": "https://hir-oss.uat.extimaging.com/irc-uat",
|
||||
"accessKey": "b9Ul0e98xPzt6PwRXA1Q",
|
||||
"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
|
||||
}
|
||||
},
|
||||
|
||||
"BasicSystemConfig": {
|
||||
|
||||
"OpenUserComplexPassword": true,
|
||||
|
||||
"OpenSignDocumentBeforeWork": true,
|
||||
|
||||
"OpenLoginLimit": true,
|
||||
"LoginMaxFailCount": 5,
|
||||
|
||||
"LoginFailLockMinutes": 30,
|
||||
"AutoLoginOutMinutes": 60,
|
||||
"OpenLoginMFA": false,
|
||||
|
||||
"ContinuousReadingTimeMin": 120,
|
||||
|
||||
"ReadingRestTimeMin": 10,
|
||||
"IsNeedChangePassWord": true,
|
||||
|
||||
"ChangePassWordDays": 90
|
||||
|
||||
},
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"FromEmail": "uat@extimaging.com",
|
||||
"FromName": "UAT_IRC",
|
||||
"AuthorizationCode": "SHzyyl2021",
|
||||
"SiteUrl": "http://irc.uat.extimaging.com/login",
|
||||
"OrganizationName": "Extlmaging",
|
||||
"OrganizationNameCN": "Extlmaging",
|
||||
"CompanyName": "Extensive Imaging",
|
||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||
"CompanyShortName": "Extensive Imaging",
|
||||
"CompanyShortNameCN": "展影医疗",
|
||||
"IsEnv_US": false,
|
||||
"IsOpenErrorNoticeEmail": false,
|
||||
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
|
||||
},
|
||||
|
||||
"SystemPacsConfig": {
|
||||
"Port": "11113",
|
||||
"IP": "47.117.164.182"
|
||||
}
|
||||
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -50,7 +50,7 @@ public class EncryptionRequestMiddleware
|
|||
{
|
||||
try
|
||||
{
|
||||
var decryptedSegment = AesEncryption.Decrypt(pathSegments[i], decryptedSymmetricKey);
|
||||
var decryptedSegment = Infrastructure.Encryption.AesEncryption.Decrypt(pathSegments[i], decryptedSymmetricKey);
|
||||
pathSegments[i] = decryptedSegment;
|
||||
}
|
||||
catch
|
||||
|
@ -74,7 +74,7 @@ public class EncryptionRequestMiddleware
|
|||
foreach (var param in queryParams)
|
||||
{
|
||||
var encryptedValue = param.Value;
|
||||
var decryptedValue = AesEncryption.Decrypt(encryptedValue, decryptedSymmetricKey);
|
||||
var decryptedValue = Infrastructure.Encryption.AesEncryption.Decrypt(encryptedValue, decryptedSymmetricKey);
|
||||
decryptedQueryParams[param.Key] = decryptedValue;
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,7 @@ public class EncryptionRequestMiddleware
|
|||
foreach (var property in encryptedJson.Properties())
|
||||
{
|
||||
var encryptedValue = property.Value.ToString();
|
||||
var decryptedValue = AesEncryption.Decrypt(encryptedValue, decryptedSymmetricKey);
|
||||
var decryptedValue = Infrastructure.Encryption.AesEncryption.Decrypt(encryptedValue, decryptedSymmetricKey);
|
||||
decryptedJson[property.Name] = decryptedValue;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
using IRaCIS.Core.Application.BusinessFilter;
|
||||
using IRaCIS.Application.Contracts;
|
||||
using IRaCIS.Core.Application.BusinessFilter;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Core.Infrastructure.Encryption;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
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;
|
||||
|
@ -13,7 +17,10 @@ using static IRaCIS.Core.Domain.Share.StaticData;
|
|||
|
||||
namespace IRaCIS.Core.Application.Filter;
|
||||
|
||||
public class TrialGlobalLimitActionFilter(IFusionCache _fusionCache, IUserInfo _userInfo, IRepository<Trial> _trialRepository) : IAsyncActionFilter
|
||||
public class TrialGlobalLimitActionFilter(IFusionCache _fusionCache, IUserInfo _userInfo, IRepository<Trial> _trialRepository,
|
||||
IOptionsMonitor<ServiceVerifyConfigOption> _basicSystemConfigConfig,
|
||||
IRepository<HIRHospital> _hirHospitalRepository,
|
||||
IStringLocalizer _localizer) : IAsyncActionFilter
|
||||
{
|
||||
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
|
||||
{
|
||||
|
@ -113,9 +120,9 @@ public class TrialGlobalLimitActionFilter(IFusionCache _fusionCache, IUserInfo _
|
|||
|
||||
trialIdStr = matchResult.Value;
|
||||
|
||||
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
|
||||
var trialInfo = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), async _ =>await CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(trialStatusStr))
|
||||
if (string.IsNullOrWhiteSpace(trialInfo?.TrialStatusStr))
|
||||
{
|
||||
|
||||
//数据库 检查该项目Id不对
|
||||
|
@ -145,22 +152,83 @@ public class TrialGlobalLimitActionFilter(IFusionCache _fusionCache, IUserInfo _
|
|||
//通过path 或者body 找到trialId 了
|
||||
if (!string.IsNullOrWhiteSpace(trialIdStr))
|
||||
{
|
||||
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
|
||||
var trialInfo = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), async _ => await CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
|
||||
|
||||
// 这里是统一拦截 项目有关的操作允许情况(特殊的地方,比如项目配置(有的在多种状态(初始化,ongoing)都可以操作,有的仅仅在Initializing)还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口)
|
||||
if (trialStatusStr == StaticData.TrialState.TrialOngoing || optActions.Any(t => t == TrialOpt.BeforeOngoingCantOpt))
|
||||
var hospitalInfo = await _fusionCache.GetOrSetAsync(CacheKeys.Hospital, async _ => await CacheHelper.GetHospitalCode(_hirHospitalRepository), TimeSpan.FromDays(7));
|
||||
|
||||
var trialStatusStr = string.Empty;
|
||||
|
||||
if (trialInfo != null)
|
||||
{
|
||||
trialStatusStr = trialInfo.TrialStatusStr;
|
||||
|
||||
await next();
|
||||
var activationCode = trialInfo.AuthorizationEncrypt;
|
||||
|
||||
if (string.IsNullOrEmpty(activationCode))
|
||||
{
|
||||
//context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["项目未进行授权之前,不能进行操作"]));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
var decodedText = string.Empty;
|
||||
try
|
||||
{
|
||||
//解析加密信息
|
||||
decodedText = AesEncryption.Decrypt(activationCode, _basicSystemConfigConfig.CurrentValue.AESKey, "Trial_AuthorizationEncrypt");
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//该授权码与该项目不匹配(无法解密)
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialGlobalLimit_AuthorizationCodeError"]));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var hospitalCode = hospitalInfo.HospitalCode;
|
||||
var authInfo = JsonConvert.DeserializeObject<TrialAuthorizationInfo>(decodedText);
|
||||
|
||||
if (authInfo != null)
|
||||
{
|
||||
if (authInfo.TrialCode != trialInfo.TrialCode || authInfo.CreateUserId != trialInfo.CreateUserId || authInfo.TrialId != trialInfo.TrialId
|
||||
|| authInfo.HospitalCode != hospitalCode || trialInfo.CriterionTypeList.Except(authInfo.CriterionTypeList).Count() != 0)
|
||||
{
|
||||
// 您的操作被禁止,系统检测到该项目授权码与该项目授权配置信息不一致,请还原项目授权配置信息!
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialGlobalLimit_AuthorizationCodeInfoError"]));
|
||||
return;
|
||||
}
|
||||
|
||||
if (DateTime.Now > authInfo.AuthorizationDeadLineDate.Value.AddDays(15))
|
||||
{
|
||||
//当前时间已经超过项目授权截止时间半个月,请重新获取项目授权后再进行操作!
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialGlobalLimit_AuthorizationCodeAfterDeadLine15Days"]));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["该授权码与该项目不匹配"]));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 这里是统一拦截 项目有关的操作允许情况(特殊的地方,比如项目配置(有的在多种状态(初始化,ongoing)都可以操作,有的仅仅在Initializing)还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口)
|
||||
if (trialStatusStr == StaticData.TrialState.TrialOngoing || optActions.Any(t => t == TrialOpt.BeforeOngoingCantOpt))
|
||||
{
|
||||
|
||||
await next();
|
||||
|
||||
}
|
||||
// 项目停止、或者完成 不允许操作
|
||||
else
|
||||
{
|
||||
//---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(I18n.T("TrialResource_InterceptedProjectStatusRule")));
|
||||
|
||||
}
|
||||
}
|
||||
// 项目停止、或者完成 不允许操作
|
||||
else
|
||||
{
|
||||
//---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(I18n.T("TrialResource_InterceptedProjectStatusRule")));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
//添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截
|
||||
|
|
|
@ -1,196 +0,0 @@
|
|||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using System.Text.RegularExpressions;
|
||||
using ZiggyCreatures.Caching.Fusion;
|
||||
using static IRaCIS.Core.Domain.Share.StaticData;
|
||||
|
||||
namespace IRaCIS.Core.Application.Filter;
|
||||
|
||||
/// <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)
|
||||
{
|
||||
_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 async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
|
||||
{
|
||||
// var typeFilter = context.ActionDescriptor.EndpointMetadata.Where(t => t.GetType() == typeof(TypeFilterAttribute)).Select(t => (TypeFilterAttribute)t).ToList().FirstOrDefault();
|
||||
//var _trialOptList= typeFilter.Arguments.Select(t => t.ToString()).ToList();
|
||||
|
||||
// 获取当前请求的 Host 信息
|
||||
var requestHost = context.HttpContext.Request.Host;
|
||||
|
||||
// 检查请求是否来自 localhost:6100
|
||||
if (requestHost.Host == "localhost" && (requestHost.Port == 6100|| requestHost.Port==3305))
|
||||
{
|
||||
await next.Invoke();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#region 处理新的用户类型,不能操作项目相关接口
|
||||
|
||||
// 后期列举出具体的类型,其他任何用户类型,都不允许操作
|
||||
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower() != "TrialDocument/userConfirm".ToLower())
|
||||
{
|
||||
//---对不起,您的账户没有操作权限。
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"]));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
trialIdStr = matchResult.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
#region body 中取数据
|
||||
|
||||
//设置可以多次读
|
||||
context.HttpContext.Request.EnableBuffering();
|
||||
var reader = new StreamReader(context.HttpContext.Request.Body);
|
||||
var contentFromBody = await reader.ReadToEndAsync();
|
||||
//读取后,流的位置还原
|
||||
context.HttpContext.Request.Body.Seek(0, SeekOrigin.Begin);
|
||||
//context.HttpContext.Request.Body.Position = 0;
|
||||
|
||||
//找到参数位置在字符串中的索引
|
||||
var trialIdIndex = contentFromBody.IndexOf("\"TrialId\"", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
if (trialIdIndex > -1)
|
||||
{
|
||||
// (?<="trialId" *: *").*?(?=",)
|
||||
|
||||
//使用正则 [0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}
|
||||
|
||||
var matchResult = Regex.Match(contentFromBody.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
|
||||
|
||||
if (matchResult.Success)
|
||||
{
|
||||
//有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下
|
||||
|
||||
trialIdStr = matchResult.Value;
|
||||
|
||||
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(trialStatusStr))
|
||||
{
|
||||
|
||||
//数据库 检查该项目Id不对
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//使用字符串取 如果是swagger 可能有时取的不对 因为空格的原因
|
||||
//trialIdStr = contentFromBody.Substring(trialIdIndex + "TrialId".Length + 4, 3
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
//通过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))
|
||||
{
|
||||
|
||||
await next.Invoke();
|
||||
|
||||
}
|
||||
// 项目停止、或者完成 不允许操作
|
||||
else
|
||||
{
|
||||
//---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_InterceptedProjectStatusRule"]));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
//添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截
|
||||
else if (_trialOptList.Any(t => t == TrialOpt.AddOrUpdateTrial || t == TrialOpt.SignSystemDocNoTrialId))
|
||||
{
|
||||
await next.Invoke();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
//如果项目相关接口没有传递trialId 会来到这里,提醒,以便修改
|
||||
|
||||
//---该接口参数中,没有传递项目编号,请核对。
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_MissingProjectNumber"]));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -1,6 +1,10 @@
|
|||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Application.Contracts;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Core.Infrastructure.Encryption;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
@ -24,7 +28,10 @@ public class TrialGlobalLimitAttribute : Attribute
|
|||
|
||||
|
||||
|
||||
public class TrialGlobalLimitEndpointFilter(IFusionCache _fusionCache, IUserInfo _userInfo, IRepository<Trial> _trialRepository) : IEndpointFilter
|
||||
public class TrialGlobalLimitEndpointFilter(IFusionCache _fusionCache, IUserInfo _userInfo, IRepository<Trial> _trialRepository,
|
||||
IOptionsMonitor<ServiceVerifyConfigOption> _basicSystemConfigConfig,
|
||||
IRepository<HIRHospital> _hirHospitalRepository,
|
||||
IStringLocalizer _localizer) : IEndpointFilter
|
||||
|
||||
{
|
||||
public async ValueTask<object?> InvokeAsync(EndpointFilterInvocationContext context, EndpointFilterDelegate next)
|
||||
|
@ -121,9 +128,9 @@ public class TrialGlobalLimitEndpointFilter(IFusionCache _fusionCache, IUserInfo
|
|||
|
||||
trialIdStr = matchResult.Value;
|
||||
|
||||
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
|
||||
var trialInfo = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), async _ => await CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(trialStatusStr))
|
||||
if (string.IsNullOrWhiteSpace(trialInfo?.TrialStatusStr))
|
||||
{
|
||||
|
||||
//数据库 检查该项目Id不对
|
||||
|
@ -151,22 +158,81 @@ public class TrialGlobalLimitEndpointFilter(IFusionCache _fusionCache, IUserInfo
|
|||
//通过path 或者body 找到trialId 了
|
||||
if (!string.IsNullOrWhiteSpace(trialIdStr))
|
||||
{
|
||||
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
|
||||
var trialInfo = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), async _ => await CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
|
||||
|
||||
// 这里是统一拦截 项目有关的操作允许情况(特殊的地方,比如项目配置(有的在多种状态(初始化,ongoing)都可以操作,有的仅仅在Initializing)还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口)
|
||||
if (trialStatusStr == StaticData.TrialState.TrialOngoing || optActions.Any(t => t == TrialOpt.BeforeOngoingCantOpt))
|
||||
var hospitalInfo = await _fusionCache.GetOrSetAsync(CacheKeys.Hospital, async _ => await CacheHelper.GetHospitalCode(_hirHospitalRepository), TimeSpan.FromDays(7));
|
||||
|
||||
var trialStatusStr = string.Empty;
|
||||
|
||||
|
||||
if (trialInfo != null)
|
||||
{
|
||||
trialStatusStr = trialInfo.TrialStatusStr;
|
||||
|
||||
return await next(context);
|
||||
var activationCode = trialInfo.AuthorizationEncrypt;
|
||||
|
||||
if (string.IsNullOrEmpty(activationCode))
|
||||
{
|
||||
//context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["项目未进行授权之前,不能进行操作"]));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
var decodedText = string.Empty;
|
||||
try
|
||||
{
|
||||
//解析加密信息
|
||||
decodedText = AesEncryption.Decrypt(activationCode, _basicSystemConfigConfig.CurrentValue.AESKey, "Trial_AuthorizationEncrypt");
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
return Results.Json(ResponseOutput.NotOk(_localizer["该授权码与该项目不匹配"]));
|
||||
}
|
||||
|
||||
|
||||
var hospitalCode = hospitalInfo.HospitalCode;
|
||||
var authInfo = JsonConvert.DeserializeObject<TrialAuthorizationInfo>(decodedText);
|
||||
|
||||
if (authInfo != null)
|
||||
{
|
||||
if (authInfo.TrialCode != trialInfo.TrialCode || authInfo.CreateUserId != trialInfo.CreateUserId || authInfo.TrialId != trialInfo.TrialId
|
||||
|| authInfo.HospitalCode != hospitalCode || trialInfo.CriterionTypeList.Except(authInfo.CriterionTypeList).Count() != 0)
|
||||
{
|
||||
return Results.Json(ResponseOutput.NotOk(_localizer["您的操作被禁止,系统检测到该项目授权码与该项目授权配置信息不一致,请还原项目授权配置信息!"]));
|
||||
}
|
||||
|
||||
if (DateTime.Now > authInfo.AuthorizationDeadLineDate.Value.AddDays(15))
|
||||
{
|
||||
return Results.Json(ResponseOutput.NotOk(_localizer["当前时间已经超过项目授权截止时间半个月,请重新获取项目授权后再进行操作!"]));
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["该授权码与该项目不匹配"]));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 这里是统一拦截 项目有关的操作允许情况(特殊的地方,比如项目配置(有的在多种状态(初始化,ongoing)都可以操作,有的仅仅在Initializing)还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口)
|
||||
if (trialStatusStr == StaticData.TrialState.TrialOngoing || optActions.Any(t => t == TrialOpt.BeforeOngoingCantOpt))
|
||||
{
|
||||
|
||||
return await next(context);
|
||||
|
||||
}
|
||||
// 项目停止、或者完成 不允许操作
|
||||
else
|
||||
{
|
||||
//---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改
|
||||
return Results.Json(ResponseOutput.NotOk(I18n.T("TrialResource_InterceptedProjectStatusRule")));
|
||||
|
||||
}
|
||||
}
|
||||
// 项目停止、或者完成 不允许操作
|
||||
else
|
||||
{
|
||||
//---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改
|
||||
return Results.Json(ResponseOutput.NotOk(I18n.T("TrialResource_InterceptedProjectStatusRule")));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
//添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截
|
||||
|
|
|
@ -36,6 +36,13 @@ public class ServiceVerifyConfigOption
|
|||
|
||||
public string ThirdPdfUrl { get; set; }
|
||||
|
||||
public string AESKey { get; set; }
|
||||
|
||||
|
||||
public int CmoveIntervalMinutes { get; set; }
|
||||
|
||||
public int CmoveInstanceIntervalMinutes { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class SystemEmailSendConfig
|
||||
|
@ -66,7 +73,7 @@ public class SystemEmailSendConfig
|
|||
|
||||
public bool IsOpenErrorNoticeEmail { get; set; }
|
||||
|
||||
public List<string> ErrorNoticeEmailList { get; set; } =new List<string>();
|
||||
public List<string> ErrorNoticeEmailList { get; set; } = new List<string>();
|
||||
}
|
||||
|
||||
public class SystemEmailSendConfigView
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
namespace IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Application.Contracts;
|
||||
using IRaCIS.Core.Application.ViewModel;
|
||||
|
||||
namespace IRaCIS.Core.Application.Helper;
|
||||
|
||||
|
||||
public static class CacheKeys
|
||||
|
@ -56,13 +59,19 @@ public static class CacheKeys
|
|||
/// <returns></returns>
|
||||
public static string StartRestTime(Guid userId) => $"{userId}StartRestTime";
|
||||
|
||||
|
||||
public static string CmoveStudyId(string studyIdStr) => $"CmoveStudyId:{studyIdStr}";
|
||||
|
||||
public static string Hospital => $"Hospital";
|
||||
|
||||
}
|
||||
|
||||
public static class CacheHelper
|
||||
{
|
||||
public static async Task<string?> GetTrialStatusAsync(Guid trialId, IRepository<Trial> _trialRepository)
|
||||
public static async Task<TrialCacheInfo> GetTrialStatusAsync(Guid trialId, IRepository<Trial> _trialRepository)
|
||||
{
|
||||
var statusStr = await _trialRepository.Where(t => t.Id == trialId, ignoreQueryFilters: true).Select(t => t.TrialStatusStr).FirstOrDefaultAsync();
|
||||
var statusStr = await _trialRepository.Where(t => t.Id == trialId, ignoreQueryFilters: true).Select(t => new TrialCacheInfo { TrialId = t.Id, TrialStatusStr = t.TrialStatusStr, CriterionTypes = t.CriterionTypes, AuthorizationEncrypt = t.AuthorizationEncrypt, AuthorizationDate = t.AuthorizationDate, CreateUserId = t.CreateUserId, TrialCode = t.TrialCode })
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
return statusStr;
|
||||
}
|
||||
|
@ -73,4 +82,10 @@ public static class CacheHelper
|
|||
|
||||
return list;
|
||||
}
|
||||
|
||||
public static async Task<HIRHospital?> GetHospitalCode(IRepository<HIRHospital> _hirHospitalRepository)
|
||||
{
|
||||
return await _hirHospitalRepository.Where(t => t.IsDefault == true).FirstOrDefaultAsync();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ public static class ExcelExportHelper
|
|||
foreach (var key in dic.Keys)
|
||||
{
|
||||
//是数组 那么找到对应的属性 进行翻译
|
||||
if (dic[key].GetType().GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList<>)))
|
||||
if (dic[key] != null && dic[key].GetType().GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList<>)))
|
||||
{
|
||||
|
||||
var newObjList = new List<object>();
|
||||
|
@ -165,7 +165,7 @@ public static class ExcelExportHelper
|
|||
}
|
||||
|
||||
//中文替换项目术语
|
||||
if (isEn_US == false && data.TrialObjectNameList.Count > 0)
|
||||
if (data.TrialObjectNameList?.Count > 0)
|
||||
{
|
||||
var replaceObjectList = data.TrialObjectNameList;
|
||||
|
||||
|
@ -176,24 +176,30 @@ public static class ExcelExportHelper
|
|||
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++)
|
||||
{
|
||||
var row = sheet.GetRow(rowIndex);
|
||||
var colums = row.LastCellNum;
|
||||
|
||||
for (int colIndex = 0; colIndex < colums; colIndex++)
|
||||
if (row != null)
|
||||
{
|
||||
var cell = row.GetCell(colIndex);
|
||||
|
||||
// 只处理字符串类型的单元格
|
||||
if (cell != null)
|
||||
var colums = row.LastCellNum;
|
||||
|
||||
for (int colIndex = 0; colIndex < colums; colIndex++)
|
||||
{
|
||||
var cellValue = cell.StringCellValue;
|
||||
var cell = row.GetCell(colIndex);
|
||||
|
||||
var find = replaceObjectList.FirstOrDefault(t => t.Name == cellValue);
|
||||
if (find != null)
|
||||
// 只处理字符串类型的单元格
|
||||
if (cell != null)
|
||||
{
|
||||
cell.SetCellValue(find.TrialName);
|
||||
var cellValue = cell.StringCellValue;
|
||||
|
||||
var find = replaceObjectList.FirstOrDefault(t => t.Name == cellValue);
|
||||
if (find != null)
|
||||
{
|
||||
cell.SetCellValue(find.TrialName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -316,7 +322,7 @@ public static class ExcelExportHelper
|
|||
foreach (var key in dic.Keys)
|
||||
{
|
||||
//是数组 那么找到对应的属性 进行翻译
|
||||
if (dic[key].GetType().GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList<>)))
|
||||
if (dic[key] != null && dic[key].GetType().GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList<>)))
|
||||
//if (dic[key].GetType().IsAssignableFrom(typeof(JArray)))
|
||||
{
|
||||
|
||||
|
@ -415,7 +421,7 @@ public static class ExcelExportHelper
|
|||
}
|
||||
|
||||
//中文替换项目术语
|
||||
if (isEn_US == false && data.TrialObjectNameList.Count > 0)
|
||||
if (data.TrialObjectNameList?.Count > 0)
|
||||
{
|
||||
var replaceObjectList = data.TrialObjectNameList;
|
||||
|
||||
|
@ -426,21 +432,25 @@ public static class ExcelExportHelper
|
|||
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++)
|
||||
{
|
||||
var row = sheet.GetRow(rowIndex);
|
||||
var colums = row.LastCellNum;
|
||||
|
||||
for (int colIndex = 0; colIndex < colums; colIndex++)
|
||||
if (row != null)
|
||||
{
|
||||
var cell = row.GetCell(colIndex);
|
||||
|
||||
// 只处理字符串类型的单元格
|
||||
if (cell != null)
|
||||
var colums = row.LastCellNum;
|
||||
|
||||
for (int colIndex = 0; colIndex < colums; colIndex++)
|
||||
{
|
||||
var cellValue = cell.StringCellValue;
|
||||
var cell = row.GetCell(colIndex);
|
||||
|
||||
var find = replaceObjectList.FirstOrDefault(t => t.Name == cellValue);
|
||||
if (find != null)
|
||||
// 只处理字符串类型的单元格
|
||||
if (cell != null)
|
||||
{
|
||||
cell.SetCellValue(find.TrialName);
|
||||
var cellValue = cell.StringCellValue;
|
||||
|
||||
var find = replaceObjectList.FirstOrDefault(t => t.Name == cellValue);
|
||||
if (find != null)
|
||||
{
|
||||
cell.SetCellValue(find.TrialName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@ using MassTransit;
|
|||
using Microsoft.Extensions.Options;
|
||||
using Minio;
|
||||
using Minio.DataModel.Args;
|
||||
using Newtonsoft.Json;
|
||||
using System.Net;
|
||||
using System.Reactive.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
@ -20,9 +22,19 @@ namespace IRaCIS.Core.Application.Helper;
|
|||
#region 绑定和返回模型
|
||||
|
||||
[LowerCamelCaseJson]
|
||||
public class MinIOOptions : AWSOptions
|
||||
public class MinIOOptions
|
||||
{
|
||||
public int Port { get; set; }
|
||||
public string EndPoint { get; set; }
|
||||
public bool UseSSL { get; set; }
|
||||
|
||||
[JsonProperty("accessKey")]
|
||||
public string AccessKeyId { get; set; }
|
||||
|
||||
[JsonProperty("secretKey")]
|
||||
public string SecretAccessKey { get; set; }
|
||||
public string BucketName { get; set; }
|
||||
public string ViewEndpoint { get; set; }
|
||||
|
||||
}
|
||||
|
||||
|
@ -31,13 +43,19 @@ public class AWSOptions
|
|||
{
|
||||
public string EndPoint { get; set; }
|
||||
public bool UseSSL { get; set; }
|
||||
|
||||
[JsonProperty("AccessKey")]
|
||||
public string AccessKeyId { get; set; }
|
||||
public string RoleArn { get; set; }
|
||||
|
||||
[JsonProperty("SecretKey")]
|
||||
public string SecretAccessKey { get; set; }
|
||||
public string BucketName { get; set; }
|
||||
public string ViewEndpoint { get; set; }
|
||||
public int DurationSeconds { get; set; }
|
||||
public string Region { get; set; }
|
||||
|
||||
public string viewEndpoint { get; set; }
|
||||
}
|
||||
|
||||
public class AliyunOSSOptions
|
||||
|
@ -205,11 +223,17 @@ public class OSSService : IOSSService
|
|||
}
|
||||
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
|
||||
{
|
||||
var httpClientHandler = new HttpClientHandler
|
||||
{
|
||||
ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
|
||||
};
|
||||
|
||||
var minIOConfig = ObjectStoreServiceOptions.MinIO;
|
||||
|
||||
|
||||
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
|
||||
.WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL)
|
||||
.WithHttpClient(new HttpClient(httpClientHandler))
|
||||
.Build();
|
||||
|
||||
var putObjectArgs = new PutObjectArgs()
|
||||
|
@ -296,11 +320,18 @@ public class OSSService : IOSSService
|
|||
}
|
||||
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
|
||||
{
|
||||
|
||||
var httpClientHandler = new HttpClientHandler
|
||||
{
|
||||
ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
|
||||
};
|
||||
|
||||
var minIOConfig = ObjectStoreServiceOptions.MinIO;
|
||||
|
||||
|
||||
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
|
||||
.WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL)
|
||||
.WithHttpClient(new HttpClient(httpClientHandler))
|
||||
.Build();
|
||||
|
||||
var putObjectArgs = new PutObjectArgs()
|
||||
|
@ -373,12 +404,20 @@ public class OSSService : IOSSService
|
|||
}
|
||||
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
|
||||
{
|
||||
|
||||
var httpClientHandler = new HttpClientHandler
|
||||
{
|
||||
ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
|
||||
};
|
||||
|
||||
var minIOConfig = ObjectStoreServiceOptions.MinIO;
|
||||
|
||||
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
|
||||
.WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL)
|
||||
.WithHttpClient(new HttpClient(httpClientHandler))
|
||||
.Build();
|
||||
|
||||
|
||||
var getObjectArgs = new GetObjectArgs()
|
||||
.WithBucket(minIOConfig.BucketName)
|
||||
.WithObject(ossRelativePath)
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
<PackageReference Include="MimeKit" Version="4.7.1" />
|
||||
<PackageReference Include="MiniExcel" Version="1.34.2" />
|
||||
<PackageReference Include="Minio" Version="6.0.3" />
|
||||
<PackageReference Include="MiniWord" Version="0.8.0" />
|
||||
<PackageReference Include="MiniWord" Version="0.9.2" />
|
||||
<PackageReference Include="My.Extensions.Localization.Json" Version="3.3.0">
|
||||
<TreatAsUsed>true</TreatAsUsed>
|
||||
</PackageReference>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -3,6 +3,7 @@
|
|||
// 生成时间 2022-06-07 14:10:54
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||
//--------------------------------------------------------------------
|
||||
using IRaCIS.Application.Contracts;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Newtonsoft.Json;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
@ -10,8 +11,108 @@ using System.ComponentModel.DataAnnotations;
|
|||
namespace IRaCIS.Core.Application.ViewModel
|
||||
{
|
||||
|
||||
public class PIReaingTaskView : ReadingTaskView
|
||||
{
|
||||
public Guid? FirstAuditUserId { get; set; }
|
||||
|
||||
public string FirstAuditUserName { get; set; }
|
||||
public DateTime? FirstAuditTime { get; set; }
|
||||
|
||||
|
||||
public Guid? LatestReplyUserId { get; set; }
|
||||
|
||||
public string LatestReplyUserName { get; set; }
|
||||
public DateTime? LatestReplyTime { get; set; }
|
||||
|
||||
|
||||
}
|
||||
public class PIAuditTaskEnrollOrPdCommand
|
||||
{
|
||||
[NotDefault]
|
||||
public Guid VisitTaskId { get; set; }
|
||||
public bool? IsEnrollment { get; set; }
|
||||
|
||||
public bool? IsPDConfirm { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class PIAuditTaskCommand
|
||||
{
|
||||
[NotDefault]
|
||||
public Guid VisitTaskId { get; set; }
|
||||
public string NotAgreeReason { get; set; }
|
||||
public string PIAuditNote { get; set; } = string.Empty;
|
||||
|
||||
public List<string> PIAuditImagePathList { get; set; }
|
||||
|
||||
public PIAuditState PIAuditState { get; set; }
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class PIAuditTaskReplyCommand
|
||||
{
|
||||
[NotDefault]
|
||||
public Guid VisitTaskId { get; set; }
|
||||
|
||||
public string ReplyContent { get; set; } = string.Empty;
|
||||
}
|
||||
public class ClinicalDataDialog
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public DateTime CreateTime { get; set; }
|
||||
public string Content { get; set; }
|
||||
}
|
||||
public class PIAuditDialogQuery
|
||||
{
|
||||
[NotDefault]
|
||||
public Guid VisitTaskId { get; set; }
|
||||
}
|
||||
public class PIAuditDialogListView
|
||||
{
|
||||
|
||||
public Guid VisitTaskId { get; set; }
|
||||
public string NotAgreeReason { get; set; }
|
||||
public string PIAuditNote { get; set; } = string.Empty;
|
||||
|
||||
public List<string> PIAuditImagePathList { get; set; }
|
||||
|
||||
public PIAuditState? PIAuditState { get; set; }
|
||||
|
||||
public string ReplyContent { get; set; } = string.Empty;
|
||||
|
||||
public bool? IsEnrollment { get; set; }
|
||||
|
||||
public bool? IsPDConfirm { get; set; }
|
||||
|
||||
public bool IsCurrentUser { get; set; }
|
||||
|
||||
public Guid CreateUserId { get; set; }
|
||||
|
||||
public string CreateUserName { get; set; }
|
||||
|
||||
|
||||
public DateTime CreateTime { get; set; }
|
||||
|
||||
|
||||
public UserTypeEnum UserTypeEnum { get; set; }
|
||||
|
||||
|
||||
}
|
||||
public class PIReadingResult
|
||||
{
|
||||
public Guid QuestionId { get; set; }
|
||||
|
||||
public string Answer { get; set; }
|
||||
}
|
||||
|
||||
public class VisitTaskViewBasic
|
||||
{
|
||||
|
||||
public Guid? SourceSubjectVisitId { get; set; }
|
||||
|
||||
public string SubjectShortName { get; set; }
|
||||
|
||||
public Guid Id { get; set; }
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
|
@ -214,6 +315,12 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||
/// </summary>
|
||||
public bool IsManualGeneration { get; set; }
|
||||
//public bool IsAfterConvertedTask { get; set; }
|
||||
|
||||
|
||||
public List<PIReadingResult> PIReadingResultList { get; set; }
|
||||
|
||||
|
||||
public List<PatientBasicInfo> PatientList { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
@ -284,10 +391,26 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||
public ReReadingApplyState ReReadingApplyState { get; set; }
|
||||
public DateTime? SuggesteFinishedTime { get; set; }
|
||||
|
||||
|
||||
#region HIR
|
||||
|
||||
public List<PatientBasicInfo> PatientList { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
public class IRUnReadSubjectView
|
||||
{
|
||||
#region HIR
|
||||
public Guid? ClaimUserId { get; set; }
|
||||
|
||||
public string? ClaimUserName { get; set; }
|
||||
|
||||
public string SubjectName { get; set; }
|
||||
|
||||
public List<PatientBasicInfo> PatientList { get; set; }
|
||||
#endregion
|
||||
public int Index { get; set; } = 0;
|
||||
|
||||
public Guid SubjectId { get; set; }
|
||||
|
@ -399,10 +522,23 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||
|
||||
public string? SubjectCode { get; set; } = null;
|
||||
|
||||
public string? SubjectName { get; set; }
|
||||
public string? PatientName { get; set; }
|
||||
public string? PatientIdStr { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class VisitTaskQuery : PageInput
|
||||
{
|
||||
#region HIR
|
||||
|
||||
public DateTime? BeginSignDate { get; set; }
|
||||
|
||||
public DateTime? EndSignDate { get; set; }
|
||||
|
||||
public string? SubjectName { get; set; }
|
||||
#endregion
|
||||
|
||||
[NotDefault]
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
|
@ -465,6 +601,33 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||
public string? RequestReReadingReason { get; set; }
|
||||
|
||||
public ExportResult? ReadingExportType { get; set; }
|
||||
|
||||
|
||||
|
||||
|
||||
#region HIR
|
||||
public PIAuditState? PIAuditState { get; set; }
|
||||
|
||||
|
||||
|
||||
public string? FirstAuditUserName { get; set; }
|
||||
|
||||
|
||||
public bool? IsWaitPIAudit { get; set; }
|
||||
|
||||
|
||||
public string? LatestReplyUserName { get; set; }
|
||||
|
||||
public DateTime? FirstAuditTimeBegin { get; set; }
|
||||
public DateTime? FirstAuditTimeEnd { get; set; }
|
||||
public DateTime? LatestReplyTimeBegin { get; set; }
|
||||
public DateTime? LatestReplyTimeEnd { get; set; }
|
||||
|
||||
public string? PatientName { get; set; }
|
||||
public string? PatientIdStr { get; set; }
|
||||
|
||||
public string? PatientSex { get; set; }
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
|
@ -486,6 +649,10 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||
|
||||
public class IRUnReadSubjectQuery : PageInput
|
||||
{
|
||||
public string? PatientName { get; set; }
|
||||
public string? PatientIdStr { get; set; }
|
||||
public string? SubjectName { get; set; }
|
||||
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
public string SubjectCode { get; set; }
|
||||
|
@ -837,6 +1004,8 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||
|
||||
[NotDefault]
|
||||
public Guid TrialReadingCriterionId { get; set; }
|
||||
|
||||
public Guid? VisitTaskId { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -336,7 +336,10 @@ namespace IRaCIS.Core.Application.Service
|
|||
ReadingCategory = ReadingCategory.Visit,
|
||||
TrialReadingCriterionId = trialReadingCriterionConfig.TrialReadingCriterionId,
|
||||
IsNeedClinicalDataSign = isNeedClinicalDataSign,
|
||||
IsClinicalDataSign = isClinicalDataSign
|
||||
IsClinicalDataSign = isClinicalDataSign,
|
||||
|
||||
//HIR
|
||||
SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget)
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1065,7 +1068,10 @@ namespace IRaCIS.Core.Application.Service
|
|||
TrialReadingCriterionId = trialReadingCriterionConfig.TrialReadingCriterionId,
|
||||
IsNeedClinicalDataSign = isNeedClinicalDataSign,
|
||||
IsClinicalDataSign = isClinicalDataSign,
|
||||
IsFrontTaskNeedSignButNotSign = isFrontTaskNeedSignButNotSign
|
||||
IsFrontTaskNeedSignButNotSign = isFrontTaskNeedSignButNotSign,
|
||||
|
||||
//HIR
|
||||
SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget)
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -8,14 +8,17 @@ using IRaCIS.Application.Contracts;
|
|||
using IRaCIS.Core.Application.Contracts;
|
||||
using IRaCIS.Core.Application.Filter;
|
||||
using IRaCIS.Core.Application.ViewModel;
|
||||
using IRaCIS.Core.Domain.Models;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Domain.Share.Reading;
|
||||
using IRaCIS.Core.Infra.EFCore.Common;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using MassTransit;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using System.Reactive.Subjects;
|
||||
using Subject = IRaCIS.Core.Domain.Models.Subject;
|
||||
|
||||
namespace IRaCIS.Core.Application.Service.Allocation;
|
||||
|
@ -48,10 +51,196 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||
IRepository<TaskInfluence> _taskInfluenceRepository,
|
||||
IRepository<TrialQCQuestionAnswer> _trialQCQuestionAnswerRepository,
|
||||
ILogger<VisitTaskService> _logger,
|
||||
IRepository<PIAudit> _PIAuditRepository,
|
||||
IRepository<ReadingQuestionTrial> _readingQuestionTrialRepository,
|
||||
IRepository<SubjectCriteriaEvaluationVisitStudyFilter> _subjectCriteriaEvaluationVisitStudyFilterRepository, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, IVisitTaskService
|
||||
{
|
||||
|
||||
#region HIR PI 相关接口
|
||||
|
||||
private IQueryable<VisitTask> GetReadingTaskQueryable(VisitTaskQuery inQuery)
|
||||
{
|
||||
var trialConfig = _trialRepository.Where(t => t.Id == inQuery.TrialId).Select(t => new { t.EnrollConfirmDefaultUserType, t.PDProgressDefaultUserType }).FirstOrDefault();
|
||||
|
||||
var visitTaskQueryable = _visitTaskRepository.Where(t => t.TrialId == inQuery.TrialId && t.IsAnalysisCreate == false)
|
||||
|
||||
.WhereIf(inQuery.TaskState != null, t => t.TaskState == inQuery.TaskState)
|
||||
.WhereIf(inQuery.TrialSiteId != null, t => t.Subject.TrialSiteId == inQuery.TrialSiteId)
|
||||
.WhereIf(inQuery.SubjectId != null, t => t.SubjectId == inQuery.SubjectId)
|
||||
.WhereIf(inQuery.IsUrgent != null, t => t.IsUrgent == inQuery.IsUrgent)
|
||||
.WhereIf(inQuery.DoctorUserId != null, t => t.DoctorUserId == inQuery.DoctorUserId)
|
||||
.WhereIf(inQuery.ReadingCategory != null, t => t.ReadingCategory == inQuery.ReadingCategory)
|
||||
.WhereIf(inQuery.ReadingTaskState != null, t => t.ReadingTaskState == inQuery.ReadingTaskState)
|
||||
.WhereIf(inQuery.TaskAllocationState != null, t => t.TaskAllocationState == inQuery.TaskAllocationState)
|
||||
.WhereIf(inQuery.TrialReadingCriterionId != null, t => t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId)
|
||||
.WhereIf(inQuery.ReReadingApplyState != null, t => t.ReReadingApplyState == inQuery.ReReadingApplyState)
|
||||
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), t => t.Subject.SubjectPatientList.Any(t => t.Patient.PatientIdStr.Contains(inQuery.PatientIdStr)))
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientName), t => t.Subject.SubjectPatientList.Any(t => t.Patient.PatientName.Contains(inQuery.PatientName)))
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientSex), t => t.Subject.SubjectPatientList.Any(t => t.Patient.PatientSex.Contains(inQuery.PatientSex)))
|
||||
|
||||
.WhereIf(inQuery.CompleteClinicalDataEnum == CompleteClinicalDataEnum.Complete, t => t.IsClinicalDataSign && t.IsNeedClinicalDataSign == true)
|
||||
.WhereIf(inQuery.CompleteClinicalDataEnum == CompleteClinicalDataEnum.NotComplete, t => t.IsClinicalDataSign == false && t.IsNeedClinicalDataSign == true)
|
||||
.WhereIf(inQuery.CompleteClinicalDataEnum == CompleteClinicalDataEnum.NA, t => t.IsNeedClinicalDataSign == false)
|
||||
.WhereIf(!string.IsNullOrEmpty(inQuery.TrialSiteCode), t => (t.BlindTrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.IsAnalysisCreate) || (t.Subject.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.IsAnalysisCreate == false))
|
||||
.WhereIf(!string.IsNullOrEmpty(inQuery.TaskName), t => t.TaskName.Contains(inQuery.TaskName) || t.TaskBlindName.Contains(inQuery.TaskName))
|
||||
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => (t.Subject.Code.Contains(inQuery.SubjectCode) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(inQuery.SubjectCode) && t.IsAnalysisCreate))
|
||||
.WhereIf(inQuery.BeginAllocateDate != null, t => t.AllocateTime > inQuery.BeginAllocateDate)
|
||||
.WhereIf(inQuery.EndAllocateDate != null, t => t.AllocateTime < inQuery.EndAllocateDate!.Value.AddDays(1))
|
||||
|
||||
.WhereIf(trialConfig?.EnrollConfirmDefaultUserType == UserTypeEnum.MIM && trialConfig?.PDProgressDefaultUserType != UserTypeEnum.MIM && _userInfo.UserTypeEnumInt == (int)UserTypeEnum.MIM, t => t.SourceSubjectVisit.IsBaseLine == true)
|
||||
.WhereIf(trialConfig?.EnrollConfirmDefaultUserType != UserTypeEnum.MIM && trialConfig?.PDProgressDefaultUserType == UserTypeEnum.MIM && _userInfo.UserTypeEnumInt == (int)UserTypeEnum.MIM, t => t.SourceSubjectVisit.IsBaseLine == false)
|
||||
.WhereIf(inQuery.IsWaitPIAudit == true, t => t.FirstAuditUserId == null)
|
||||
.WhereIf(inQuery.IsWaitPIAudit == false, t => t.FirstAuditUserId != null)
|
||||
.WhereIf(inQuery.PIAuditState != null, t => t.PIAuditState == inQuery.PIAuditState)
|
||||
.WhereIf(inQuery.FirstAuditTimeBegin != null, t => t.AllocateTime > inQuery.FirstAuditTimeBegin)
|
||||
.WhereIf(inQuery.FirstAuditTimeEnd != null, t => t.AllocateTime < inQuery.FirstAuditTimeEnd)
|
||||
.WhereIf(inQuery.LatestReplyTimeBegin != null, t => t.AllocateTime > inQuery.LatestReplyTimeBegin)
|
||||
.WhereIf(inQuery.LatestReplyTimeEnd != null, t => t.AllocateTime < inQuery.LatestReplyTimeEnd);
|
||||
|
||||
return visitTaskQueryable;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IResponseOutput<PageOutput<PIReaingTaskView>>> GetPIReadingAuditList(VisitTaskQuery queryVisitTask)
|
||||
{
|
||||
|
||||
var visitTaskQueryable = GetReadingTaskQueryable(queryVisitTask)
|
||||
.ProjectTo<PIReaingTaskView>(_mapper.ConfigurationProvider);
|
||||
|
||||
var defalutSortArray = new string[] { nameof(VisitTask.IsUrgent) + " desc", nameof(VisitTask.SubjectId), nameof(VisitTask.VisitTaskNum) };
|
||||
|
||||
var pageList = await visitTaskQueryable.ToPagedListAsync(queryVisitTask, defalutSortArray);
|
||||
|
||||
var trialTaskConfig = _trialRepository.Where(t => t.Id == queryVisitTask.TrialId).ProjectTo<TrialUrgentConfig>(_mapper.ConfigurationProvider).FirstOrDefault();
|
||||
|
||||
var questionList = _readingQuestionTrialRepository.Where(t => t.TrialId == queryVisitTask.TrialId && t.ReadingQuestionCriterionTrialId == queryVisitTask.TrialReadingCriterionId)
|
||||
.Where(t => t.IsJudgeQuestion == true)
|
||||
.Select(t => new { QuestionId = t.Id, QuestionName = _userInfo.IsEn_Us ? t.QuestionEnName : t.QuestionName, t.DictionaryCode }).ToList();
|
||||
|
||||
trialTaskConfig!.OtherObj = questionList;
|
||||
return ResponseOutput.Ok(pageList, trialTaskConfig);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///new- 首次审核 后续编辑审核
|
||||
/// </summary>
|
||||
/// <param name="incommand"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
|
||||
public async Task<IResponseOutput> PIAuditTask(PIAuditTaskCommand incommand)
|
||||
{
|
||||
//需要设置首次审核时间 审核人
|
||||
var visitTask = await _visitTaskRepository.FirstOrDefaultAsync(t => t.Id == incommand.VisitTaskId);
|
||||
var isFirstAudit = visitTask.FirstAuditUserId == null;
|
||||
|
||||
visitTask.NotAgreeReason = incommand.NotAgreeReason;
|
||||
visitTask.PIAuditNote = incommand.PIAuditNote;
|
||||
visitTask.PIAuditImagePath = string.Join('|', incommand.PIAuditImagePathList);
|
||||
visitTask.PIAuditState = incommand.PIAuditState;
|
||||
|
||||
visitTask.LatestReplyUserId = _userInfo.Id;
|
||||
visitTask.LatestReplyTime = DateTime.Now;
|
||||
visitTask.IsEnrollment = incommand.PIAuditState == PIAuditState.PINotAgree ? null : visitTask.IsEnrollment;
|
||||
visitTask.IsPDConfirm = incommand.PIAuditState == PIAuditState.PINotAgree ? null : visitTask.IsPDConfirm;
|
||||
|
||||
if (isFirstAudit)
|
||||
{
|
||||
visitTask.FirstAuditUserId = _userInfo.Id;
|
||||
visitTask.FirstAuditTime = DateTime.Now;
|
||||
}
|
||||
|
||||
//发送对话
|
||||
var addDialig = _mapper.Map<PIAudit>(incommand);
|
||||
|
||||
addDialig.PIAuditState = incommand.PIAuditState;
|
||||
|
||||
addDialig.PIAuditImagePath = visitTask.PIAuditImagePath;
|
||||
|
||||
await _PIAuditRepository.AddAsync(addDialig);
|
||||
|
||||
await _visitTaskRepository.SaveChangesAsync();
|
||||
|
||||
return ResponseOutput.Ok();
|
||||
|
||||
}
|
||||
|
||||
|
||||
[HttpPost]
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> PIAuditTaskEnrollOrPD(PIAuditTaskEnrollOrPdCommand incommand, [FromServices] IEmailSendService emailSendService)
|
||||
{
|
||||
var visitTask = await _visitTaskRepository.FirstOrDefaultAsync(t => t.Id == incommand.VisitTaskId);
|
||||
visitTask.IsEnrollment = incommand.IsEnrollment != null ? incommand.IsEnrollment : visitTask.IsEnrollment;
|
||||
visitTask.IsPDConfirm = incommand.IsPDConfirm != null ? incommand.IsPDConfirm : visitTask.IsPDConfirm;
|
||||
visitTask.LatestReplyUserId = _userInfo.Id;
|
||||
visitTask.LatestReplyTime = DateTime.Now;
|
||||
|
||||
await _visitTaskRepository.SaveChangesAsync();
|
||||
|
||||
//await emailSendService.SendEnrollOrPdEmail(visitTask.Id, incommand.IsEnrollment, incommand.IsPDConfirm);
|
||||
|
||||
return ResponseOutput.Ok();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///new- 回复审核内容
|
||||
/// </summary>
|
||||
/// <param name="incommand"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<IResponseOutput> PIAuditTaskReply(PIAuditTaskReplyCommand incommand)
|
||||
{
|
||||
await _PIAuditRepository.AddAsync(new PIAudit() { ReplyContent = incommand.ReplyContent, VisitTaskId = incommand.VisitTaskId });
|
||||
|
||||
await _PIAuditRepository.SaveChangesAsync();
|
||||
|
||||
return ResponseOutput.Ok();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// new- 获取审核对话列表
|
||||
/// </summary>
|
||||
/// <param name="inQuery"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<List<PIAuditDialogListView>> GetPIAuditDialogList(PIAuditDialogQuery inQuery)
|
||||
{
|
||||
|
||||
|
||||
var list = await _PIAuditRepository.Where(t => t.VisitTaskId == inQuery.VisitTaskId).OrderBy(t => t.CreateTime).ProjectTo<PIAuditDialogListView>(_mapper.ConfigurationProvider).ToListAsync();
|
||||
|
||||
foreach (var item in list)
|
||||
{
|
||||
item.IsCurrentUser = item.CreateUserId == _userInfo.Id;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public async Task<IResponseOutput> AddClinicalDataDialog(Guid visiTaskId, string content,
|
||||
[FromServices] IRepository<SubjectVisitClinicalDialog> subjectVisitClinicalDialogRepository,
|
||||
[FromServices] IEmailSendService emailSendService)
|
||||
{
|
||||
var taskInfo = await _visitTaskRepository.Where(t => t.Id == visiTaskId).Select(t => new { t.SourceSubjectVisitId, t.Subject.Code, t.SourceSubjectVisit.VisitName, t.Trial.ResearchProgramNo, t.Trial.TrialCode }).FirstOrDefaultAsync();
|
||||
|
||||
await subjectVisitClinicalDialogRepository.AddAsync(new SubjectVisitClinicalDialog() { SubjectVisitId = (Guid)taskInfo.SourceSubjectVisitId, Content = content }, true);
|
||||
|
||||
await emailSendService.SendClinicalDataQuestionAsync(visiTaskId, content);
|
||||
|
||||
return ResponseOutput.Ok();
|
||||
}
|
||||
|
||||
public async Task<List<ClinicalDataDialog>> GetClinicalDataDialog(Guid visiTaskId,
|
||||
[FromServices] IRepository<SubjectVisitClinicalDialog> _subjectVisitClinicalDialogRepository)
|
||||
{
|
||||
var subjectVisitId = await _visitTaskRepository.Where(t => t.Id == visiTaskId).Select(t => t.SourceSubjectVisitId).FirstOrDefaultAsync();
|
||||
var list = _subjectVisitClinicalDialogRepository.Where(t => t.SubjectVisitId == subjectVisitId).ProjectTo<ClinicalDataDialog>(_mapper.ConfigurationProvider).OrderByDescending(t => t.CreateTime).ToList();
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 设置任务加急
|
||||
|
@ -861,8 +1050,16 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||
.WhereIf(!string.IsNullOrEmpty(inQuery.TrialSiteCode), t => (t.OriginalReReadingTask.BlindTrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.OriginalReReadingTask.IsAnalysisCreate) || (t.OriginalReReadingTask.Subject.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.OriginalReReadingTask.IsAnalysisCreate == false))
|
||||
.WhereIf(!string.IsNullOrEmpty(inQuery.TaskName), t => t.OriginalReReadingTask.TaskName.Contains(inQuery.TaskName) || t.NewReReadingTask.TaskBlindName.Contains(inQuery.TaskName))
|
||||
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => (t.OriginalReReadingTask.Subject.Code.Contains(inQuery.SubjectCode) && t.OriginalReReadingTask.IsAnalysisCreate == false) || (t.OriginalReReadingTask.BlindSubjectCode.Contains(inQuery.SubjectCode) && t.OriginalReReadingTask.IsAnalysisCreate))
|
||||
|
||||
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectName), t => t.OriginalReReadingTask.Subject.ShortName.Contains(inQuery.SubjectName))
|
||||
|
||||
|
||||
.WhereIf(inQuery.BeginAllocateDate != null, t => t.OriginalReReadingTask.AllocateTime > inQuery.BeginAllocateDate)
|
||||
.WhereIf(inQuery.EndAllocateDate != null, t => t.OriginalReReadingTask.AllocateTime < inQuery.EndAllocateDate!.Value.AddDays(1))
|
||||
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), t => t.OriginalReReadingTask.Subject.SubjectPatientList.Any(t => t.Patient.PatientIdStr.Contains(inQuery.PatientIdStr)))
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientName), t => t.OriginalReReadingTask.Subject.SubjectPatientList.Any(t => t.Patient.PatientName.Contains(inQuery.PatientName)))
|
||||
|
||||
.ProjectTo<ReReadingTaskView>(_mapper.ConfigurationProvider);
|
||||
|
||||
|
||||
|
@ -949,12 +1146,39 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||
TrialReadingCriterionId = trialReadingCriterionId,
|
||||
SubjectCode = inQuery.SubjectCode,
|
||||
|
||||
SubjectName = inQuery.SubjectName,
|
||||
PatientIdStr = inQuery.PatientIdStr,
|
||||
PatientName = inQuery.PatientName,
|
||||
|
||||
PageIndex = inQuery.PageIndex,
|
||||
PageSize = inQuery.PageSize,
|
||||
Asc = inQuery.Asc,
|
||||
SortField = inQuery.SortField,
|
||||
});
|
||||
|
||||
//给出患者编号
|
||||
var currentPageData = result.CurrentPageData;
|
||||
var subjectIdList = currentPageData.Select(t => t.SubjectId).ToList();
|
||||
var list = await _subjectRepository.Where(t => subjectIdList.Contains(t.Id)).Select(t => new
|
||||
{
|
||||
SubjectId = t.Id,
|
||||
PatientList = t.SubjectPatientList.Select(c => new PatientBasicInfo()
|
||||
{
|
||||
PatientId = c.PatientId,
|
||||
PatientAge = c.Patient.PatientAge,
|
||||
PatientBirthDate = c.Patient.PatientBirthDate,
|
||||
PatientIdStr = c.Patient.PatientIdStr,
|
||||
PatientSex = c.Patient.PatientSex,
|
||||
PatientName = c.Patient.PatientName,
|
||||
}).ToList(),
|
||||
}).ToListAsync();
|
||||
|
||||
foreach (var item in currentPageData)
|
||||
{
|
||||
item.PatientList = list.Where(t => t.SubjectId == item.SubjectId).FirstOrDefault()?.PatientList;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
//随机阅片
|
||||
else
|
||||
|
@ -1001,9 +1225,53 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||
|
||||
var critrion = await _trialReadingCriterionRepository.FindAsync(trialReadingCriterionId);
|
||||
|
||||
|
||||
var readingDivisionEnum = critrion.ReadingDivisionEnum;
|
||||
|
||||
var piReadingScopenEnum = critrion.PIReadingScopenEnum;
|
||||
|
||||
if (critrion.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
|
||||
{
|
||||
var visitQuery = _visitTaskRepository.Where(x => x.TrialId == inQuery.TrialId && x.DoctorUserId == _userInfo.Id && x.TaskState == TaskState.Effect)
|
||||
var visitQuery = _visitTaskRepository.Where(x => x.TrialId == inQuery.TrialId/* && x.DoctorUserId == _userInfo.Id*/ && x.TaskState == TaskState.Effect)
|
||||
.WhereIf(inQuery.SubjectId != null, t => t.SubjectId == inQuery.SubjectId)
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), t => t.Subject.SubjectPatientList.Any(t => t.Patient.PatientIdStr.Contains(inQuery.PatientIdStr)))
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientName), t => t.Subject.SubjectPatientList.Any(t => t.Patient.PatientName.Contains(inQuery.PatientName)))
|
||||
|
||||
//PI 读基线的时候,subject 如果PI基线没阅片完,SR就不能看
|
||||
.WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.SR && piReadingScopenEnum == PIReadingScopenEnum.AllBaseline && readingDivisionEnum == ReadingDivisionEnum.PIandSR,
|
||||
t => t.Subject.SubjectVisitTaskList.Any(c => c.SourceSubjectVisit.IsBaseLine == true && c.ReadingTaskState == ReadingTaskState.HaveSigned && c.TaskState == TaskState.Effect && c.TrialReadingCriterionId == trialReadingCriterionId))
|
||||
|
||||
//PI 读随访的时候, subject 如果SR基线没阅片完,PI就不能看
|
||||
.WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.PI && piReadingScopenEnum == PIReadingScopenEnum.AllVisit && readingDivisionEnum == ReadingDivisionEnum.PIandSR,
|
||||
t => t.Subject.SubjectVisitTaskList.Any(c => c.SourceSubjectVisit.IsBaseLine == true && c.ReadingTaskState == ReadingTaskState.HaveSigned && c.TaskState == TaskState.Effect && c.TrialReadingCriterionId == trialReadingCriterionId))
|
||||
|
||||
//没有site概念
|
||||
//.WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.SR, t => t.Subject.TrialSite.CRCUserList.Any(u => u.UserId == _userInfo.Id))
|
||||
// 仅仅SR阅片 PI 没有任务列表
|
||||
.WhereIf(readingDivisionEnum == ReadingDivisionEnum.OnlySR && _userInfo.UserTypeEnumInt == (int)UserTypeEnum.PI, t => t.TrialId == Guid.Empty)
|
||||
|
||||
//PI查看 PI阅片所有基线
|
||||
.WhereIf(readingDivisionEnum == ReadingDivisionEnum.PIandSR && _userInfo.UserTypeEnumInt == (int)UserTypeEnum.PI && piReadingScopenEnum == PIReadingScopenEnum.AllBaseline,
|
||||
t => t.SourceSubjectVisit.IsBaseLine == true)
|
||||
|
||||
// PI查看 PI 阅片所有
|
||||
.WhereIf(readingDivisionEnum == ReadingDivisionEnum.PIandSR && _userInfo.UserTypeEnumInt == (int)UserTypeEnum.PI && piReadingScopenEnum == PIReadingScopenEnum.AllBaselineandVisit,
|
||||
t => true)
|
||||
|
||||
// PI查看 PI 阅片访视
|
||||
.WhereIf(readingDivisionEnum == ReadingDivisionEnum.PIandSR && _userInfo.UserTypeEnumInt == (int)UserTypeEnum.PI && piReadingScopenEnum == PIReadingScopenEnum.AllVisit,
|
||||
t => t.SourceSubjectVisit.IsBaseLine == false)
|
||||
|
||||
//SR查看 PI阅片所有基线
|
||||
.WhereIf(readingDivisionEnum == ReadingDivisionEnum.PIandSR && _userInfo.UserTypeEnumInt == (int)UserTypeEnum.SR && piReadingScopenEnum == PIReadingScopenEnum.AllBaseline,
|
||||
t => t.SourceSubjectVisit.IsBaseLine == false)
|
||||
|
||||
//SR查看 PI 阅片所有
|
||||
.WhereIf(readingDivisionEnum == ReadingDivisionEnum.PIandSR && _userInfo.UserTypeEnumInt == (int)UserTypeEnum.SR && piReadingScopenEnum == PIReadingScopenEnum.AllBaselineandVisit,
|
||||
t => t.TrialId == Guid.Empty)
|
||||
//SR查看 PI 阅片访视
|
||||
.WhereIf(readingDivisionEnum == ReadingDivisionEnum.PIandSR && _userInfo.UserTypeEnumInt == (int)UserTypeEnum.SR && piReadingScopenEnum == PIReadingScopenEnum.AllVisit,
|
||||
t => t.SourceSubjectVisit.IsBaseLine == true)
|
||||
|
||||
.WhereIf(inQuery.SubjectId != null, x => x.SubjectId == inQuery.SubjectId)
|
||||
//前序 不存在 未生成任务的访视
|
||||
|
@ -1011,21 +1279,20 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||
|
||||
// 前序 不存在 未一致性核查未通过的
|
||||
.Where(t => !t.Subject.SubjectVisitList.Any(sv => sv.CheckState != CheckStateEnum.CVPassed && t.VisitTaskNum >= sv.VisitNum))
|
||||
//.WhereIf(critrion.IsAutoCreate == false, t => t.Subject.SubjectCriteriaEvaluationVisitFilterList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId).Any(t => t.IsGeneratedTask == false) ?
|
||||
//t.VisitTaskNum <= t.Subject.SubjectCriteriaEvaluationVisitFilterList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId && t.IsGeneratedTask == false).Min(t => t.SubjectVisit.VisitNum) : true)
|
||||
//.Where(t => t.Subject.SubjectVisitList.Any(t => t.CheckState != CheckStateEnum.CVPassed) ? t.VisitTaskNum <= t.Subject.SubjectVisitList.Where(t => t.CheckState != CheckStateEnum.CVPassed).Min(t => t.VisitNum) : true)
|
||||
//满足前序访视不存在 需要签署但是未签署 sql 相当复杂 同时想查询所有未读的统计数字 就无法统计 byzhouhang
|
||||
//但是加字段 IsFrontTaskNeedSignButNotSign 那么签名临床数据的时候,要对该subject 该标准的有效的任务 这个字段需要在签名的时候维护 采取这种方式 统计数字灵活
|
||||
//.Where(t => t.Subject.SubjectVisitTaskList.AsQueryable().Where(visitTaskLambda).Any(c => c.IsNeedClinicalDataSign == true && c.IsClinicalDataSign == false && c.VisitTaskNum < t.VisitTaskNum))
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectName), t => t.Subject.ShortName.Contains(inQuery.SubjectName))
|
||||
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => (t.Subject.Code.Contains(inQuery.SubjectCode!) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(inQuery.SubjectCode!) && t.IsAnalysisCreate));
|
||||
|
||||
|
||||
var visitGroupQuery = visitQuery.GroupBy(x => new { x.SubjectId, x.Subject.Code, x.BlindSubjectCode });
|
||||
var visitGroupQuery = visitQuery.GroupBy(x => new { x.SubjectId, x.Subject.Code, x.BlindSubjectCode, x.Subject.ShortName, x.SubjectCriterionClaimUserId, x.SubjectCriterionClaimUser.UserName });
|
||||
|
||||
var visitTaskQuery = visitGroupQuery.Select(x => new IRUnReadSubjectView()
|
||||
{
|
||||
SubjectId = x.Key.SubjectId,
|
||||
SubjectCode = x.Key.BlindSubjectCode == string.Empty ? x.Key.Code : x.Key.BlindSubjectCode,
|
||||
SubjectName = x.Key.ShortName,
|
||||
|
||||
ClaimUserId = x.Key.SubjectCriterionClaimUserId,
|
||||
ClaimUserName = x.Key.UserName,
|
||||
|
||||
SuggesteFinishedTime = x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned).Min(x => x.SuggesteFinishedTime),
|
||||
|
||||
|
@ -1219,17 +1486,23 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||
|
||||
|
||||
var visitTaskQueryable = _visitTaskRepository.Where(t => t.TrialId == inQuery.TrialId)
|
||||
.Where(t => t.DoctorUserId == _userInfo.Id && t.ReadingTaskState == ReadingTaskState.HaveSigned)//该医生 已经签名的数据
|
||||
|
||||
|
||||
.WhereIf(inQuery.TrialSiteId != null, t => t.Subject.TrialSiteId == inQuery.TrialSiteId)
|
||||
.Where(t => /*t.DoctorUserId == _userInfo.Id &&*/ t.ReadingTaskState == ReadingTaskState.HaveSigned)//该医生 已经签名的数据
|
||||
.WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.PI, t => t.DoctorUser.UserTypeEnum == UserTypeEnum.PI)
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), t => t.Subject.SubjectPatientList.Any(t => t.Patient.PatientIdStr.Contains(inQuery.PatientIdStr)))
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientName), t => t.Subject.SubjectPatientList.Any(t => t.Patient.PatientName.Contains(inQuery.PatientName)))
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientSex), t => t.Subject.SubjectPatientList.Any(t => t.Patient.PatientSex.Contains(inQuery.PatientSex)))
|
||||
.WhereIf(inQuery.PIAuditState != null, t => t.PIAuditState == inQuery.PIAuditState)
|
||||
.WhereIf(inQuery.BeginSignDate != null, t => t.SignTime >= inQuery.BeginSignDate)
|
||||
.WhereIf(inQuery.EndSignDate != null, t => t.SignTime <= inQuery.EndSignDate)
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectName), t => t.Subject.ShortName.Contains(inQuery.SubjectName))
|
||||
//.WhereIf(inQuery.TrialSiteId != null, t => t.Subject.TrialSiteId == inQuery.TrialSiteId)
|
||||
.WhereIf(inQuery.SubjectId != null, t => t.SubjectId == inQuery.SubjectId)
|
||||
.WhereIf(inQuery.IsUrgent != null, t => t.IsUrgent == inQuery.IsUrgent)
|
||||
.WhereIf(inQuery.ReadingCategory != null, t => t.ReadingCategory == inQuery.ReadingCategory)
|
||||
.WhereIf(inQuery.TaskAllocationState != null, t => t.TaskAllocationState == inQuery.TaskAllocationState)
|
||||
.WhereIf(inQuery.TrialReadingCriterionId != null, t => t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId)
|
||||
|
||||
|
||||
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectName), t => t.Subject.ShortName.Contains(inQuery.SubjectName))
|
||||
.WhereIf(inQuery.TaskState != null, t => t.TaskState == inQuery.TaskState)
|
||||
.WhereIf(!string.IsNullOrEmpty(inQuery.TrialSiteCode), t => (t.BlindTrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.IsAnalysisCreate) || (t.Subject.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.IsAnalysisCreate == false))
|
||||
.WhereIf(!string.IsNullOrEmpty(inQuery.TaskName), t => t.TaskName.Contains(inQuery.TaskName) || t.TaskBlindName.Contains(inQuery.TaskName))
|
||||
|
@ -1249,55 +1522,105 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||
|
||||
[HttpPost]
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> AIRReReading(AIRReReadingCommand command, [FromServices] IVisitTaskHelpeService _visitTaskCommonService)
|
||||
public async Task<IResponseOutput> AIRReReading(AIRReReadingCommand command,
|
||||
[FromServices] IVisitTaskHelpeService _visitTaskCommonService,
|
||||
[FromServices] IRepository<ReadingTableQuestionAnswer> _readingTableQuestionAnswerRepository)
|
||||
{
|
||||
var baseLineTaskList = await _visitTaskRepository.Where(t => t.TrialId == command.TrialId && t.TrialReadingCriterionId == command.TrialReadingCriterionId && t.DoctorUserId == _userInfo.Id
|
||||
&& t.TaskState == TaskState.Effect && t.ReadingCategory == ReadingCategory.Visit && t.ReadingTaskState == ReadingTaskState.HaveSigned && t.SourceSubjectVisit.IsBaseLine == true).ToListAsync();
|
||||
|
||||
var judegeList = await _visitTaskRepository.Where(t => t.TrialId == command.TrialId && t.TrialReadingCriterionId == command.TrialReadingCriterionId && t.DoctorUserId == _userInfo.Id
|
||||
&& t.TaskState == TaskState.Effect && t.ReadingCategory == ReadingCategory.Judge && t.ReadingTaskState == ReadingTaskState.HaveSigned).ToListAsync();
|
||||
|
||||
foreach (var item in judegeList)
|
||||
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.AIR)
|
||||
{
|
||||
if (!baseLineTaskList.Any(t => t.SubjectId == item.SubjectId))
|
||||
var baseLineTaskList = await _visitTaskRepository.Where(t => t.TrialId == command.TrialId && t.TrialReadingCriterionId == command.TrialReadingCriterionId && t.DoctorUserId == _userInfo.Id
|
||||
&& t.TaskState == TaskState.Effect && t.ReadingCategory == ReadingCategory.Visit && t.ReadingTaskState == ReadingTaskState.HaveSigned && t.SourceSubjectVisit.IsBaseLine == true).ToListAsync();
|
||||
|
||||
var judegeList = await _visitTaskRepository.Where(t => t.TrialId == command.TrialId && t.TrialReadingCriterionId == command.TrialReadingCriterionId && t.DoctorUserId == _userInfo.Id
|
||||
&& t.TaskState == TaskState.Effect && t.ReadingCategory == ReadingCategory.Judge && t.ReadingTaskState == ReadingTaskState.HaveSigned).ToListAsync();
|
||||
|
||||
foreach (var item in judegeList)
|
||||
{
|
||||
baseLineTaskList.Add(item);
|
||||
if (!baseLineTaskList.Any(t => t.SubjectId == item.SubjectId))
|
||||
{
|
||||
baseLineTaskList.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var baseLineTaskIdList = baseLineTaskList.Select(t => t.Id).ToList();
|
||||
|
||||
if (baseLineTaskIdList.Count == 0)
|
||||
{
|
||||
return ResponseOutput.Ok();
|
||||
}
|
||||
|
||||
//if (baseLineTaskList == null)
|
||||
//{
|
||||
// return ResponseOutput.NotOk("基线任务未阅完,不允许重阅基线任务");
|
||||
//}
|
||||
|
||||
await ApplyReReading(new ApplyReReadingCommand() { IsCopyFollowForms = false, IsCopyOrigenalForms = false, TaskIdList = baseLineTaskIdList, TrialId = command.TrialId, RequestReReadingReason = "AIR自动重阅基线", RequestReReadingType = RequestReReadingType.DocotorApply });
|
||||
|
||||
|
||||
|
||||
var requestRecordList = await _visitTaskReReadingRepository.Where(t => baseLineTaskIdList.Contains(t.OriginalReReadingTaskId) && t.RequestReReadingUserId == _userInfo.Id && t.RequestReReadingReason == "AIR自动重阅基线").ToListAsync();
|
||||
|
||||
if (requestRecordList.Count != baseLineTaskIdList.Count)
|
||||
{
|
||||
//---后台数据有错误
|
||||
return ResponseOutput.NotOk(_localizer["VisitTask_DoctorConfiguration"]);
|
||||
}
|
||||
|
||||
await ConfirmReReading(new ConfirmReReadingCommand()
|
||||
{
|
||||
TrialId = command.TrialId,
|
||||
RequestReReadingResultEnum = RequestReReadingResult.Agree,
|
||||
//ConfirmReReadingList = new List<ConfirmReReadingDTO>() { new ConfirmReReadingDTO() { Id = requestRecord.Id, OriginalReReadingTaskId = task.Id } }
|
||||
ConfirmReReadingList = requestRecordList.Select(t => new ConfirmReReadingDTO() { Id = t.Id, OriginalReReadingTaskId = t.OriginalReReadingTaskId }).ToList()
|
||||
}, _visitTaskCommonService);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (command.VisitTaskId != null)
|
||||
{
|
||||
var visitTaskId = command.VisitTaskId.Value;
|
||||
var taskIdList = new List<Guid>();
|
||||
|
||||
taskIdList.Add(visitTaskId);
|
||||
|
||||
await ApplyReReading(new ApplyReReadingCommand() { IsCopyFollowForms = false, IsCopyOrigenalForms = true, TaskIdList = taskIdList, TrialId = command.TrialId, RequestReReadingReason = "阅片人自动重阅阅片任务", RequestReReadingType = RequestReReadingType.DocotorApply });
|
||||
|
||||
var requestRecord = await _visitTaskReReadingRepository.Where(t => visitTaskId == t.OriginalReReadingTaskId && t.RequestReReadingUserId == _userInfo.Id && t.RequestReReadingReason == "阅片人自动重阅阅片任务").FirstAsync();
|
||||
|
||||
await ConfirmReReading(new ConfirmReReadingCommand()
|
||||
{
|
||||
TrialId = command.TrialId,
|
||||
RequestReReadingResultEnum = RequestReReadingResult.Agree,
|
||||
ConfirmReReadingList = new List<ConfirmReReadingDTO>() { new ConfirmReReadingDTO() { Id = requestRecord.Id, OriginalReReadingTaskId = visitTaskId } }
|
||||
}, _visitTaskCommonService);
|
||||
|
||||
//有序SR 申请重阅的时候,把后续任务的拷贝表单要清理掉
|
||||
|
||||
var taskInfo = _visitTaskRepository.Where(t => t.Id == visitTaskId).Select(t => new { t.TrialReadingCriterion.IsReadingTaskViewInOrder, t.TrialReadingCriterionId, t.SubjectId, t.VisitTaskNum }).FirstOrDefault();
|
||||
|
||||
if (taskInfo.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
|
||||
{
|
||||
|
||||
var afterTaskIdList = _visitTaskRepository.Where(t => t.SubjectId == taskInfo.SubjectId && t.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId
|
||||
&& t.ReadingCategory == ReadingCategory.Visit && t.VisitTaskNum > taskInfo.VisitTaskNum && t.TaskState == TaskState.Effect).Select(t => t.Id).ToList();
|
||||
|
||||
await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => afterTaskIdList.Contains(t.Id), u => new VisitTask() { FirstReadingTime = null, ReadingTaskState = ReadingTaskState.WaitReading });
|
||||
|
||||
await _readingCustomTagRepository.BatchDeleteNoTrackingAsync(t => afterTaskIdList.Contains(t.VisitTaskId));
|
||||
|
||||
await _readingTaskQuestionMarkRepository.BatchDeleteNoTrackingAsync(t => afterTaskIdList.Contains(t.VisitTaskId));
|
||||
|
||||
await _readingTaskQuestionAnswerRepository.BatchDeleteNoTrackingAsync(t => afterTaskIdList.Contains(t.VisitTaskId));
|
||||
|
||||
await _readingTableAnswerRowInfoRepository.BatchDeleteNoTrackingAsync(t => afterTaskIdList.Contains(t.VisitTaskId));
|
||||
|
||||
await _readingTableQuestionAnswerRepository.BatchDeleteNoTrackingAsync(t => afterTaskIdList.Contains(t.VisitTaskId));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var baseLineTaskIdList = baseLineTaskList.Select(t => t.Id).ToList();
|
||||
|
||||
if (baseLineTaskIdList.Count == 0)
|
||||
{
|
||||
return ResponseOutput.Ok();
|
||||
}
|
||||
|
||||
//if (baseLineTaskList == null)
|
||||
//{
|
||||
// return ResponseOutput.NotOk("基线任务未阅完,不允许重阅基线任务");
|
||||
//}
|
||||
|
||||
await ApplyReReading(new ApplyReReadingCommand() { IsCopyFollowForms = false, IsCopyOrigenalForms = false, TaskIdList = baseLineTaskIdList, TrialId = command.TrialId, RequestReReadingReason = "AIR自动重阅基线", RequestReReadingType = RequestReReadingType.DocotorApply });
|
||||
|
||||
|
||||
|
||||
var requestRecordList = await _visitTaskReReadingRepository.Where(t => baseLineTaskIdList.Contains(t.OriginalReReadingTaskId) && t.RequestReReadingUserId == _userInfo.Id && t.RequestReReadingReason == "AIR自动重阅基线").ToListAsync();
|
||||
|
||||
if (requestRecordList.Count != baseLineTaskIdList.Count)
|
||||
{
|
||||
//---后台数据有错误
|
||||
return ResponseOutput.NotOk(_localizer["VisitTask_DoctorConfiguration"]);
|
||||
}
|
||||
|
||||
await ConfirmReReading(new ConfirmReReadingCommand()
|
||||
{
|
||||
TrialId = command.TrialId,
|
||||
RequestReReadingResultEnum = RequestReReadingResult.Agree,
|
||||
//ConfirmReReadingList = new List<ConfirmReReadingDTO>() { new ConfirmReReadingDTO() { Id = requestRecord.Id, OriginalReReadingTaskId = task.Id } }
|
||||
ConfirmReReadingList = requestRecordList.Select(t => new ConfirmReReadingDTO() { Id = t.Id, OriginalReReadingTaskId = t.OriginalReReadingTaskId }).ToList()
|
||||
}, _visitTaskCommonService);
|
||||
|
||||
return ResponseOutput.Ok();
|
||||
|
||||
}
|
||||
|
@ -1334,7 +1657,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||
throw new BusinessValidationFailedException(_localizer["VisitTask_BackendData"]);
|
||||
}
|
||||
|
||||
_logger.LogError("重阅申请状态"+ (int)task.ReReadingApplyState);
|
||||
_logger.LogError("重阅申请状态" + (int)task.ReReadingApplyState);
|
||||
|
||||
if (task.ReReadingApplyState == ReReadingApplyState.DocotorHaveApplyed || task.ReReadingApplyState == ReReadingApplyState.TrialGroupHaveApplyed || task.ReReadingApplyState == ReReadingApplyState.Agree)
|
||||
{
|
||||
|
@ -1478,7 +1801,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||
}
|
||||
|
||||
//AIR 不加验证
|
||||
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.AIR)
|
||||
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.AIR || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.PI || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.SR)
|
||||
{
|
||||
task.ReReadingApplyState = ReReadingApplyState.DocotorHaveApplyed;
|
||||
}
|
||||
|
@ -1614,7 +1937,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||
visitTaskReReadingAppply.RequestReReadingRejectReason = agreeReReadingCommand.RequestReReadingRejectReason;
|
||||
|
||||
|
||||
Expression<Func<VisitTask, bool>> filterExpression = t => t.TrialId == trialId && t.SubjectId == origenalTask.SubjectId && (t.TaskState == TaskState.Effect || t.TaskState == TaskState.Freeze) && t.TaskAllocationState == TaskAllocationState.Allocated;
|
||||
Expression<Func<VisitTask, bool>> filterExpression = t => t.TrialId == trialId && t.SubjectId == origenalTask.SubjectId && (t.TaskState == TaskState.Effect || t.TaskState == TaskState.Freeze) /*&& t.TaskAllocationState == TaskAllocationState.Allocated*/;
|
||||
|
||||
//是否是一致性分析任务 正常申请 会影响一致性分析任务
|
||||
filterExpression = filterExpression.And(t => t.IsAnalysisCreate == origenalTask.IsAnalysisCreate);
|
||||
|
@ -1780,7 +2103,10 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||
|
||||
}
|
||||
//IR申请 PM 审批 注意这里有一致性分析的申请同意 不会回退访视,在此要生成影响的访视任务
|
||||
else if (visitTaskReReadingAppply.RequestReReadingType == RequestReReadingType.DocotorApply && (IsPMOrAPm() || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.AIR))
|
||||
else if (visitTaskReReadingAppply.RequestReReadingType == RequestReReadingType.DocotorApply && (IsPMOrAPm() ||
|
||||
_userInfo.UserTypeEnumInt == (int)UserTypeEnum.AIR
|
||||
|| _userInfo.UserTypeEnumInt == (int)UserTypeEnum.SR
|
||||
|| _userInfo.UserTypeEnumInt == (int)UserTypeEnum.PI))
|
||||
{
|
||||
|
||||
|
||||
|
@ -2161,6 +2487,8 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||
{
|
||||
item.Id = Guid.Empty;
|
||||
item.VisitTaskId = newTask.Id;
|
||||
|
||||
item.MeasureData = item.MeasureData.Replace(origenalTask.Id.ToString(), newTask.Id.ToString());
|
||||
}
|
||||
|
||||
_ = _readingCustomTagRepository.AddRangeAsync(readingCustomTagList).Result;
|
||||
|
@ -2172,6 +2500,8 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||
{
|
||||
item.Id = Guid.Empty;
|
||||
item.VisitTaskId = newTask.Id;
|
||||
|
||||
item.MeasureData = item.MeasureData.Replace(origenalTask.Id.ToString(), newTask.Id.ToString());
|
||||
}
|
||||
|
||||
_ = _readingTaskQuestionMarkRepository.AddRangeAsync(readingTaskQuestionMarkList).Result;
|
||||
|
@ -2196,6 +2526,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||
var originalVisitTaskId = item.VisitTaskId;
|
||||
var originalFristAddTaskId = item.FristAddTaskId;
|
||||
|
||||
item.MeasureData = item.MeasureData.Replace(origenalTask.Id.ToString(), newTask.Id.ToString());
|
||||
item.Id = NewId.NextSequentialGuid();
|
||||
item.VisitTaskId = newTask.Id;
|
||||
|
||||
|
@ -2576,7 +2907,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||
|
||||
var criterionConfig = (await _trialReadingCriterionRepository.Where(x => x.Id == filterObj.TrialReadingCriterionId).Select(x => new { x.ReadingTool, x.CriterionType, x.IsAdditionalAssessment, x.IsReadingTaskViewInOrder }).FirstOrDefaultAsync()).IfNullThrowException();
|
||||
|
||||
Expression<Func<VisitTask, bool>> filterExpression = t => t.TrialId == trialId && t.SubjectId == filterObj.SubjectId && (t.TaskState == TaskState.Effect || t.TaskState == TaskState.Freeze) && t.TaskAllocationState == TaskAllocationState.Allocated;
|
||||
Expression<Func<VisitTask, bool>> filterExpression = t => t.TrialId == trialId && t.SubjectId == filterObj.SubjectId && (t.TaskState == TaskState.Effect || t.TaskState == TaskState.Freeze);
|
||||
|
||||
//是否是一致性分析任务 (一致性分析的任务 不会产生裁判 肿瘤学 仅仅有生成的访视和全局)
|
||||
|
||||
|
|
|
@ -10,6 +10,21 @@ namespace IRaCIS.Core.Application.Service
|
|||
public AllocationConfig()
|
||||
{
|
||||
|
||||
#region HIR
|
||||
CreateMap<VisitTask, PIReaingTaskView>().IncludeBase<VisitTask, ReadingTaskView>()
|
||||
.ForMember(o => o.FirstAuditUserName, t => t.MapFrom(u => u.FirstAuditUser.UserName))
|
||||
.ForMember(o => o.LatestReplyUserName, t => t.MapFrom(u => u.LatestReplyUser.UserName))
|
||||
.ForMember(d => d.PatientList, u => u.MapFrom(s => s.Subject.SubjectPatientList));
|
||||
|
||||
CreateMap<PIAuditTaskCommand, PIAudit>();
|
||||
|
||||
CreateMap<PIAudit, PIAuditDialogListView>()
|
||||
.ForMember(o => o.CreateUserName, t => t.MapFrom(u => u.CreateUser.UserName))
|
||||
.ForMember(o => o.UserTypeEnum, t => t.MapFrom(u => u.CreateUser.UserTypeEnum))
|
||||
//.ForMember(o => o.PIAuditState, t => t.MapFrom(u => u.VisitTask.PIAuditState))
|
||||
;
|
||||
#endregion
|
||||
|
||||
CreateMap<ReadingTableAnswerRowInfo, ConvertedRowInfo>()
|
||||
.ForMember(d => d.OriginalId, u => u.MapFrom(s => s.Id));
|
||||
|
||||
|
@ -117,13 +132,14 @@ namespace IRaCIS.Core.Application.Service
|
|||
.ForMember(o => o.IsReadingShowPreviousResults, t => t.MapFrom(u => u.TrialReadingCriterion.IsReadingShowPreviousResults))
|
||||
.ForMember(o => o.DigitPlaces, t => t.MapFrom(u => u.TrialReadingCriterion.DigitPlaces))
|
||||
.ForMember(o => o.IseCRFShowInDicomReading, t => t.MapFrom(u => u.TrialReadingCriterion.IseCRFShowInDicomReading))
|
||||
.ForMember(o => o.CriterionType, t => t.MapFrom(u => u.TrialReadingCriterion.CriterionType));
|
||||
.ForMember(o => o.CriterionType, t => t.MapFrom(u => u.TrialReadingCriterion.CriterionType))
|
||||
.ForMember(o => o.SubjectShortName, t => t.MapFrom(u => u.Subject.ShortName));
|
||||
|
||||
CreateMap<VisitTask, VisitTaskView>().IncludeBase<VisitTask, VisitTaskViewBasic>()
|
||||
|
||||
|
||||
.ForMember(o => o.TrialSiteId, t => t.MapFrom(u => u.Subject.TrialSiteId))
|
||||
.ForMember(o => o.TrialSiteCode, t => t.MapFrom(u => /*u.IsAnalysisCreate == true ? u.BlindTrialSiteCode :*/ u.Subject.TrialSite.TrialSiteCode))
|
||||
//.ForMember(o => o.TrialSiteCode, t => t.MapFrom(u => /*u.IsAnalysisCreate == true ? u.BlindTrialSiteCode :*/ u.Subject.TrialSite.TrialSiteCode))
|
||||
.ForMember(o => o.SubjectCode, t => t.MapFrom(u => /*u.IsAnalysisCreate == true ? u.BlindSubjectCode :*/ u.Subject.Code))
|
||||
.ForMember(o => o.MedicalNo, t => t.MapFrom(u => u.Subject.MedicalNo))
|
||||
|
||||
|
@ -169,8 +185,9 @@ namespace IRaCIS.Core.Application.Service
|
|||
|
||||
CreateMap<VisitTask, IRHaveReadView>().IncludeBase<VisitTask, VisitTaskViewBasic>()
|
||||
.ForMember(o => o.TrialSiteId, t => t.MapFrom(u => u.Subject.TrialSiteId))
|
||||
.ForMember(o => o.TrialSiteCode, t => t.MapFrom(u => u.IsAnalysisCreate == true ? u.BlindTrialSiteCode : u.Subject.TrialSite.TrialSiteCode))
|
||||
.ForMember(o => o.SubjectCode, t => t.MapFrom(u => u.IsAnalysisCreate == true ? u.BlindSubjectCode : u.Subject.Code));
|
||||
//.ForMember(o => o.TrialSiteCode, t => t.MapFrom(u => u.IsAnalysisCreate == true ? u.BlindTrialSiteCode : u.Subject.TrialSite.TrialSiteCode))
|
||||
.ForMember(o => o.SubjectCode, t => t.MapFrom(u => u.IsAnalysisCreate == true ? u.BlindSubjectCode : u.Subject.Code))
|
||||
.ForMember(d => d.PatientList, u => u.MapFrom(s => s.Subject.SubjectPatientList));
|
||||
|
||||
|
||||
|
||||
|
@ -321,6 +338,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
CreateMap<ReadingClinicalDataPDF, ReadingConsistentClinicalDataPDF>().ReverseMap();
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -230,7 +230,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
ExperimentName = t.ExperimentName,
|
||||
TrialCode = t.TrialCode,
|
||||
CreateTime = t.CreateTime,
|
||||
Sponsor = _userInfo.IsEn_Us ? t.Sponsor.SponsorName : t.Sponsor.SponsorNameCN,
|
||||
Sponsor = _userInfo.IsEn_Us ? t.Sponsor : t.Sponsor,
|
||||
TrialStatusStr = t.TrialStatusStr,
|
||||
|
||||
ExpetiedTaskCount = isPM ? t.VisitTaskList.Where(t => t.IsUrgent).Count() : 0,
|
||||
|
@ -1252,40 +1252,8 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 影像接收记录表
|
||||
/// </summary>
|
||||
/// <param name="inQuery"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> GetSCPImageUploadList_Export(SCPImageUploadQuery inQuery,
|
||||
[FromServices] IRepository<SCPImageUpload> _scpImageUploadRepository,
|
||||
[FromServices] IDictionaryService _dictionaryService,
|
||||
[FromServices] IRepository<Trial> _trialRepository)
|
||||
{
|
||||
var query = _scpImageUploadRepository.Where(t => t.TrialId == inQuery.TrialId)
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.CalledAE), t => t.CalledAE.Contains(inQuery.CalledAE))
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.CallingAEIP), t => t.CallingAEIP.Contains(inQuery.CallingAEIP))
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.CallingAE), t => t.CallingAE.Contains(inQuery.CallingAE))
|
||||
.WhereIf(inQuery.StartTime != null, t => t.StartTime >= inQuery.StartTime)
|
||||
.WhereIf(inQuery.EndTime != null, t => t.EndTime <= inQuery.EndTime)
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.TrialSiteKeyInfo), t => t.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteKeyInfo)
|
||||
|| t.TrialSite.TrialSiteAliasName.Contains(inQuery.TrialSiteKeyInfo) || t.TrialSite.TrialSiteName.Contains(inQuery.TrialSiteKeyInfo))
|
||||
.ProjectTo<SCPImageUploadExportDTO>(_mapper.ConfigurationProvider);
|
||||
|
||||
|
||||
var list = await query.SortToListAsync(inQuery);
|
||||
|
||||
var exportInfo = (await _trialRepository.Where(t => t.Id == inQuery.TrialId).IgnoreQueryFilters().ProjectTo<ExcelExportInfo>(_mapper.ConfigurationProvider).FirstOrDefaultAsync()).IfNullThrowException();
|
||||
|
||||
exportInfo.List = ExportExcelConverterDate.ConvertToClientTimeInObject(list, _userInfo.TimeZoneId);
|
||||
exportInfo.CurrentTime = ExportExcelConverterDate.DateTimeInternationalToString(DateTime.Now, _userInfo.TimeZoneId);
|
||||
|
||||
|
||||
return await ExcelExportHelper.DataExportAsync(StaticData.Export.TrialSCPImageUploadList_Export, exportInfo, $"{exportInfo.ResearchProgramNo}", _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(SCPImageUploadExportDTO));
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 国际化导出
|
||||
/// </summary>
|
||||
|
@ -1322,76 +1290,8 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///影像检查列表-患者为维度组织
|
||||
/// </summary>
|
||||
/// <param name="inQuery"></param>
|
||||
/// <param name="_patientRepository"></param>
|
||||
/// <param name="_dictionaryService"></param>
|
||||
/// <param name="_trialRepository"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> GetPatientList_Export(PatientTrialQuery inQuery,
|
||||
[FromServices] IRepository<SCPPatient> _patientRepository,
|
||||
[FromServices] IDictionaryService _dictionaryService,
|
||||
[FromServices] IRepository<Trial> _trialRepository)
|
||||
{
|
||||
|
||||
|
||||
var query = _patientRepository.Where(t => t.TrialId == inQuery.TrialId)
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), t => t.PatientIdStr.Contains(inQuery.PatientIdStr))
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientName), t => t.PatientName.Contains(inQuery.PatientName))
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubejctCode), t => t.Subject.Code.Contains(inQuery.SubejctCode))
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.TrialSiteKeyInfo), t => t.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteKeyInfo)
|
||||
|| t.TrialSite.TrialSiteAliasName.Contains(inQuery.TrialSiteKeyInfo) || t.TrialSite.TrialSiteName.Contains(inQuery.TrialSiteKeyInfo))
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.CallingAE), t => t.SCPStudyList.Any(t => t.CallingAE == inQuery.CallingAE))
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.CalledAE), t => t.SCPStudyList.Any(t => t.CalledAE == inQuery.CalledAE))
|
||||
.WhereIf(inQuery.BeginPushTime != null, t => t.LatestPushTime >= inQuery.BeginPushTime)
|
||||
.WhereIf(inQuery.EndPushTime != null, t => t.LatestPushTime <= inQuery.EndPushTime);
|
||||
|
||||
|
||||
var resultQuery = from patient in query
|
||||
|
||||
select new SCPPatientSubjectExportDTO()
|
||||
{
|
||||
//CreateUserId = patient.CreateUserId,
|
||||
//UpdateTime = patient.UpdateTime,
|
||||
//UpdateUserId = patient.UpdateUserId,
|
||||
//TrialId = patient.TrialId,
|
||||
//SubejctId = patient.SubjectId,
|
||||
//CreateTime = patient.CreateTime,
|
||||
//PatientId = patient.Id,
|
||||
|
||||
PatientBirthDate = patient.PatientBirthDate,
|
||||
CalledAEList = patient.SCPStudyList.Select(t => t.CalledAE).Distinct().ToList(),
|
||||
CallingAEList = patient.SCPStudyList.Select(t => t.CallingAE).Distinct().ToList(),
|
||||
EarliestStudyTime = patient.EarliestStudyTime,
|
||||
LatestStudyTime = patient.LatestStudyTime,
|
||||
LatestPushTime = patient.LatestPushTime,
|
||||
PatientAge = patient.PatientAge,
|
||||
PatientName = patient.PatientName,
|
||||
PatientIdStr = patient.PatientIdStr,
|
||||
PatientSex = patient.PatientSex,
|
||||
StudyCount = patient.SCPStudyList.Count(),
|
||||
SubjectCode = patient.Subject.Code,
|
||||
TrialSiteAliasName = patient.TrialSite.TrialSiteAliasName,
|
||||
TrialSiteCode = patient.TrialSite.TrialSiteCode,
|
||||
TrialSiteName = patient.TrialSite.TrialSiteName
|
||||
|
||||
};
|
||||
|
||||
var list = await resultQuery.SortToListAsync(inQuery);
|
||||
|
||||
var exportInfo = (await _trialRepository.Where(t => t.Id == inQuery.TrialId).IgnoreQueryFilters().ProjectTo<ExcelExportInfo>(_mapper.ConfigurationProvider).FirstOrDefaultAsync()).IfNullThrowException();
|
||||
|
||||
exportInfo.List = ExportExcelConverterDate.ConvertToClientTimeInObject(list, _userInfo.TimeZoneId);
|
||||
exportInfo.CurrentTime = ExportExcelConverterDate.DateTimeInternationalToString(DateTime.Now, _userInfo.TimeZoneId);
|
||||
|
||||
|
||||
return await ExcelExportHelper.DataExportAsync(StaticData.Export.TrialSCPImageUploadPatientList_Export, exportInfo, $"{exportInfo.ResearchProgramNo}", _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(SCPPatientSubjectExportDTO));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 邮件导出
|
||||
|
@ -1502,11 +1402,25 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
}
|
||||
else
|
||||
{
|
||||
//如果没有产生裁判,默认选择R1
|
||||
if (item.ArmEnum == Arm.DoubleReadingArm1)
|
||||
//两个人都做了
|
||||
if (resultExceptJudgeList.Count(t => t.VisitTaskNum == item.VisitTaskNum && t.SubjectCode == item.SubjectCode) == 2)
|
||||
{
|
||||
item.IsJudgeSelect = true;
|
||||
//如果没有产生裁判,默认选择R1
|
||||
if (item.ArmEnum == Arm.DoubleReadingArm1)
|
||||
{
|
||||
item.IsJudgeSelect = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
item.IsJudgeSelect = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
item.IsJudgeSelect = null;
|
||||
item.IsTrigerJudge = null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1524,17 +1438,26 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
|
||||
var maxFinishedJudge = judegeList.Where(t => t.ReadingTaskState == ReadingTaskState.HaveSigned).OrderByDescending(t => t.VisitTaskNum).FirstOrDefault();
|
||||
|
||||
var maxNotFinishedJudge = judegeList.Where(t => t.ReadingTaskState != ReadingTaskState.HaveSigned).FirstOrDefault();
|
||||
var maxNotFinishedJudge = judegeList.Where(t => t.ReadingTaskState != ReadingTaskState.HaveSigned).OrderByDescending(t => t.VisitTaskNum).FirstOrDefault();
|
||||
|
||||
//仅有一个未完成的全局裁判,那么都是null
|
||||
|
||||
//n个裁判任务都未完成
|
||||
if (maxFinishedJudge == null && maxNotFinishedJudge != null)
|
||||
{
|
||||
if (visitItem.VisitTaskNum < maxNotFinishedJudge.VisitTaskNum)
|
||||
{
|
||||
visitItem.IsJudgeSelect = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
//大于当前未完成的全局裁判 后续 肯定是未知的
|
||||
visitItem.IsTrigerJudge = null;
|
||||
visitItem.IsJudgeSelect = null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
//全局裁判都完成了,那么以最后一次裁判选择的为准
|
||||
//n个全局裁判都完成了,那么以最后一次裁判选择的为准
|
||||
else if (maxFinishedJudge != null && maxNotFinishedJudge == null)
|
||||
{
|
||||
if (visitItem.ArmEnum == maxFinishedJudge.JudgeArmEnum && visitItem.VisitTaskNum < maxFinishedJudge.VisitTaskNum)
|
||||
|
@ -1547,14 +1470,27 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
{
|
||||
visitItem.IsJudgeSelect = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//裁判都完成的后续 没有其他裁判任务 肯定也是未知的
|
||||
visitItem.IsTrigerJudge = null;
|
||||
visitItem.IsJudgeSelect = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//两个都不为null 肯定是不同的裁判
|
||||
|
||||
//在完成裁判之后的,和未完成裁判之前的
|
||||
if (/*visitItem.VisitTaskNum < maxNotFinishedJudge.VisitTaskNum &&*/ visitItem.VisitTaskNum > maxFinishedJudge.VisitTaskNum)
|
||||
//在未完成裁判之后的
|
||||
if (visitItem.VisitTaskNum > maxNotFinishedJudge.VisitTaskNum)
|
||||
{
|
||||
visitItem.IsTrigerJudge = null;
|
||||
visitItem.IsJudgeSelect = null;
|
||||
}
|
||||
//完成裁判之后的 ,和未完成裁判之前的
|
||||
else if (visitItem.VisitTaskNum < maxNotFinishedJudge.VisitTaskNum && visitItem.VisitTaskNum > maxFinishedJudge.VisitTaskNum)
|
||||
{
|
||||
visitItem.IsTrigerJudge = true;
|
||||
visitItem.IsJudgeSelect = null;
|
||||
}
|
||||
else if (visitItem.ArmEnum == maxFinishedJudge.JudgeArmEnum && visitItem.VisitTaskNum < maxFinishedJudge.VisitTaskNum)
|
||||
|
@ -1571,11 +1507,27 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
}
|
||||
else
|
||||
{
|
||||
//不存在裁判 将R1设置
|
||||
if (visitItem.ArmEnum == Arm.DoubleReadingArm1)
|
||||
//没有产生裁判 有可能一个人没做完,也有可能做完了没产生裁判
|
||||
//两个人都做了
|
||||
if (resultExceptJudgeList.Count(t => t.VisitTaskNum == visitItem.VisitTaskNum && t.SubjectCode == visitItem.SubjectCode) == 2)
|
||||
{
|
||||
visitItem.IsJudgeSelect = true;
|
||||
//不存在裁判 将R1设置
|
||||
if (visitItem.ArmEnum == Arm.DoubleReadingArm1)
|
||||
{
|
||||
visitItem.IsJudgeSelect = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
visitItem.IsJudgeSelect = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
visitItem.IsJudgeSelect = null;
|
||||
visitItem.IsTrigerJudge = null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1842,7 +1794,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
|
||||
|
||||
|
||||
list.Add(new ExportDocumentDes() { Code = StaticData.Export.CommonJudgeReadingDetail_Export, ExportCatogory = ExportResult.DetailedTableOfAdjudicationResults });
|
||||
//list.Add(new ExportDocumentDes() { Code = StaticData.Export.CommonJudgeReadingDetail_Export, ExportCatogory = ExportResult.DetailedTableOfAdjudicationResults });
|
||||
|
||||
|
||||
if (criterion.CriterionType == CriterionType.RECIST1Point1 || criterion.CriterionType == CriterionType.RECIST1Pointt1_MB
|
||||
|
@ -1852,29 +1804,29 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
list.Add(new ExportDocumentDes() { Code = StaticData.Export.ReadingLession_Export, ExportCatogory = ExportResult.DetailedTableOfLesions });
|
||||
}
|
||||
|
||||
if (criterion.CriterionType == CriterionType.OCT)
|
||||
{
|
||||
list.Add(new ExportDocumentDes() { Code = StaticData.Export.OCT_ReadingLession_Export, ExportCatogory = ExportResult.OCT_ReadingLession_Export });
|
||||
}
|
||||
//if (criterion.CriterionType == CriterionType.OCT)
|
||||
//{
|
||||
// list.Add(new ExportDocumentDes() { Code = StaticData.Export.OCT_ReadingLession_Export, ExportCatogory = ExportResult.OCT_ReadingLession_Export });
|
||||
//}
|
||||
|
||||
switch (criterion.ArbitrationRule)
|
||||
{
|
||||
case ArbitrationRule.None:
|
||||
break;
|
||||
//switch (criterion.ArbitrationRule)
|
||||
//{
|
||||
// case ArbitrationRule.None:
|
||||
// break;
|
||||
|
||||
case ArbitrationRule.Visit:
|
||||
list.Add(new ExportDocumentDes() { Code = StaticData.Export.VisitJudgeRatio_Export, ExportCatogory = ExportResult.VisitJudgeRatio_Export });
|
||||
// case ArbitrationRule.Visit:
|
||||
// list.Add(new ExportDocumentDes() { Code = StaticData.Export.VisitJudgeRatio_Export, ExportCatogory = ExportResult.VisitJudgeRatio_Export });
|
||||
|
||||
break;
|
||||
case ArbitrationRule.Reading:
|
||||
list.Add(new ExportDocumentDes() { Code = StaticData.Export.ReadingPeriodJudgeRatio_Export, ExportCatogory = ExportResult.ReadingPeriodJudgeRatio_Export });
|
||||
// break;
|
||||
// case ArbitrationRule.Reading:
|
||||
// list.Add(new ExportDocumentDes() { Code = StaticData.Export.ReadingPeriodJudgeRatio_Export, ExportCatogory = ExportResult.ReadingPeriodJudgeRatio_Export });
|
||||
|
||||
break;
|
||||
case ArbitrationRule.NA:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// break;
|
||||
// case ArbitrationRule.NA:
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
//}
|
||||
|
||||
|
||||
//if (criterion.CriterionType == CriterionType.RECIST1Point1 || criterion.CriterionType == CriterionType.RECIST1Pointt1_MB)
|
||||
|
@ -2184,8 +2136,8 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
var dynamicColumnConfig = new DynamicColumnConfig()
|
||||
{
|
||||
AutoColumnTitleRowIndex = 2,
|
||||
AutoColumnStartIndex = 6,
|
||||
TempalteLastColumnIndex = 8,
|
||||
AutoColumnStartIndex = 5,
|
||||
TempalteLastColumnIndex = 4,
|
||||
DynamicItemDicName = "TranslateDicName",
|
||||
DynamicItemValueName = "QuestionValue",
|
||||
DynamicItemTitleName = "QuestionName",
|
||||
|
|
|
@ -100,7 +100,8 @@ namespace IRaCIS.Core.Application.Service
|
|||
.ForMember(d => d.UserName, u => u.MapFrom(s => s.CreateUser.UserName))
|
||||
.ForMember(d => d.TrialSiteCode, u => u.MapFrom(s => s.Subject.TrialSite.TrialSiteCode));
|
||||
|
||||
|
||||
CreateMap<InternationalizationAddOrEdit, IRCGlobalInfoDTO>();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Application.Contracts;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
@ -9,7 +10,11 @@ namespace IRaCIS.Core.Application.Service
|
|||
public interface IEmailSendService
|
||||
{
|
||||
Task SendEnrollOrPdEmail(Guid visitTaskId, bool? isEnrollment, bool? isPDConfirm);
|
||||
|
||||
|
||||
Task SendClinicalDataQuestionAsync(Guid visitTaskId, string content);
|
||||
|
||||
Task SendPIAuditResultAsync(Guid visitTaskId);
|
||||
|
||||
Task<(TrialEmailNoticeConfig?, SMTPEmailConfig?)> BuildEmailConfig(Guid trialId, EmailBusinessScenario businessScenario, Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc, Guid? siteId = null, Guid? trialReadingCriterionId = null);
|
||||
}
|
||||
|
||||
|
@ -18,6 +23,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
IRepository<TrialUser> _trialUserRepository,
|
||||
IRepository<VisitTask> _visitTaskRepository,
|
||||
IRepository<TrialSiteUser> _trialSiteUserRepository,
|
||||
IRepository<Dictionary> _dictionaryRepository,
|
||||
IOptionsMonitor<SystemEmailSendConfig> _SystemEmailSendConfig, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, IEmailSendService
|
||||
{
|
||||
|
||||
|
@ -53,7 +59,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
t.Trial.ResearchProgramNo,
|
||||
t.Subject.TrialSite.TrialSiteCode,
|
||||
SubjectCode = t.Subject.Code,
|
||||
t.Trial.Sponsor.SponsorName,
|
||||
t.Trial.Sponsor,
|
||||
t.SourceSubjectVisit.VisitName,
|
||||
t.TrialId,
|
||||
|
||||
|
@ -98,6 +104,71 @@ namespace IRaCIS.Core.Application.Service
|
|||
}
|
||||
|
||||
|
||||
//临床数据质询
|
||||
public async Task SendClinicalDataQuestionAsync(Guid visitTaskId, string content)
|
||||
{
|
||||
|
||||
var isEn_us = _userInfo.IsEn_Us;
|
||||
|
||||
var info = await _visitTaskRepository.Where(t => t.Id == visitTaskId, ignoreQueryFilters: true).Select(t => new { t.TrialId, t.Trial.ResearchProgramNo, t.Trial.TrialCode, t.SourceSubjectVisit.VisitName, t.Subject.TrialSiteId, t.Subject.Code }).FirstOrDefaultAsync();
|
||||
|
||||
|
||||
Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc = trialEmailConfig =>
|
||||
{
|
||||
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, info.ResearchProgramNo, info.Code, info.VisitName);
|
||||
var htmlBodyStr = string.Format(isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN,
|
||||
EmailNamePlaceholder, info.ResearchProgramNo, info.Code, info.VisitName, _userInfo.UserName, content, _SystemEmailSendConfig.CurrentValue.SiteUrl);
|
||||
return (topicStr, htmlBodyStr, isEn_us, null);
|
||||
};
|
||||
|
||||
await SendTrialEmailAsync(info.TrialId, EmailBusinessScenario.ClinicalDataQuestion, topicAndHtmlFunc, info.TrialSiteId);
|
||||
}
|
||||
|
||||
public async Task SendPIAuditResultAsync(Guid visitTaskId)
|
||||
{
|
||||
var isEn_us = _userInfo.IsEn_Us;
|
||||
|
||||
var info = await _visitTaskRepository.Where(t => t.Id == visitTaskId, ignoreQueryFilters: true).Select(t => new { t.TrialId, t.Trial.ResearchProgramNo, t.Trial.TrialCode, t.SourceSubjectVisit.VisitName, t.Subject.TrialSiteId, t.Subject.Code }).FirstOrDefaultAsync();
|
||||
var answerList = await _visitTaskRepository.Where(t => t.Id == visitTaskId, ignoreQueryFilters: true).SelectMany(t => t.ReadingTaskQuestionAnswerList).Where(t => t.ReadingQuestionTrial.IsJudgeQuestion == true).Select(t => new { QuestionName = isEn_us ? t.ReadingQuestionTrial.QuestionEnName : t.ReadingQuestionTrial.QuestionName, t.ReadingQuestionTrial.DictionaryCode, t.Answer }).ToListAsync();
|
||||
|
||||
var template = " <div style=\"margin-left: 2ch;\"> {0}: {1} </div>";
|
||||
|
||||
var needTranslateDicNameList = answerList.Where(t => !string.IsNullOrEmpty(t.DictionaryCode)).Select(t => t.DictionaryCode).ToList();
|
||||
|
||||
|
||||
var searchList = await _dictionaryRepository.Where(t => needTranslateDicNameList.ToArray().Contains(t.Parent.Code) && t.ParentId != null && t.IsEnable).ProjectTo<BasicDicSelectCopy>(_mapper.ConfigurationProvider, new { isEn_Us = _userInfo.IsEn_Us }).ToListAsync();
|
||||
|
||||
var translateDataList = searchList.GroupBy(t => t.ParentCode).ToDictionary(g => g.Key, g => g.OrderBy(t => t.ShowOrder).ToList());
|
||||
|
||||
|
||||
|
||||
Func<bool, string, string, string> transFunc = (bool isNeedTranslate, string dicCode, string answer) =>
|
||||
{
|
||||
if (isNeedTranslate && translateDataList.ContainsKey(dicCode))
|
||||
{
|
||||
var result = translateDataList[dicCode].Where(t => t.Code.ToLower() == answer.ToLower()).Select(t => isEn_us ? t.Value : t.ValueCN).FirstOrDefault() ?? answer;
|
||||
return result;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return answer;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
var piResult = string.Join(' ', answerList.Select(t => string.Format(template, t.QuestionName, transFunc(!string.IsNullOrEmpty(t.DictionaryCode), t.DictionaryCode, t.Answer))));
|
||||
|
||||
Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc = trialEmailConfig =>
|
||||
{
|
||||
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, info.ResearchProgramNo, info.Code, info.VisitName);
|
||||
var htmlBodyStr = string.Format(isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN,
|
||||
EmailNamePlaceholder, info.ResearchProgramNo, info.Code, info.VisitName, _userInfo.UserName, piResult, _SystemEmailSendConfig.CurrentValue.SiteUrl);
|
||||
return (topicStr, htmlBodyStr, isEn_us, null);
|
||||
};
|
||||
|
||||
await SendTrialEmailAsync(info.TrialId, EmailBusinessScenario.PIAuditResutl, topicAndHtmlFunc, info.TrialSiteId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -187,7 +187,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
t.Trial.ResearchProgramNo,
|
||||
t.Subject.TrialSite.TrialSiteCode,
|
||||
SubjectCode = t.Subject.Code,
|
||||
t.Trial.Sponsor.SponsorName,
|
||||
t.Trial.Sponsor,
|
||||
t.Trial.IsEnrollementQualificationConfirm,
|
||||
t.Trial.IsPDProgressView,
|
||||
|
||||
|
@ -617,7 +617,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
|
||||
var value = new Dictionary<string, object>()
|
||||
{
|
||||
["SponsorName"] = taskInfo.SponsorName,
|
||||
["SponsorName"] = taskInfo.Sponsor,
|
||||
["ResearchProgramNo"] = taskInfo.ResearchProgramNo,
|
||||
["TrialSiteCode"] = taskInfo.TrialSiteCode,
|
||||
["SubjectCode"] = taskInfo.SubjectCode,
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
CreateMap<TrialPaymentPrice, TrialPaymentPriceDTO>()
|
||||
.ForMember(t => t.TrialCode, u => u.MapFrom(t => t.Trial.Code))
|
||||
.ForMember(t => t.ReviewMode, u => u.MapFrom(t => t.Trial.ReviewMode.Value))
|
||||
.ForMember(t => t.Cro, u => u.MapFrom(t => t.Trial.CRO.CROName))
|
||||
.ForMember(t => t.Cro, u => u.MapFrom(t => t.Trial.CRO))
|
||||
.ForMember(t => t.Indication, u => u.MapFrom(t => t.Trial.Indication))
|
||||
.ForMember(t => t.Expedited, u => u.MapFrom(t => t.Trial.Expedited))
|
||||
.ForMember(t => t.DoctorsNames, u => u.MapFrom(t => string.Join(',', t.Trial.EnrollList.Select(t => t.Doctor.ChineseName))))
|
||||
|
|
|
@ -42,6 +42,7 @@ namespace IRaCIS.Core.Application.Contracts.Dicom.DTO
|
|||
|
||||
public List<InstanceBasicInfo> InstanceInfoList { get; set; } = new List<InstanceBasicInfo>();
|
||||
|
||||
|
||||
public bool IsExistMutiFrames => InstanceInfoList.Any(t => t.NumberOfFrames > 1);
|
||||
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ namespace IRaCIS.Core.Application.Services
|
|||
}
|
||||
|
||||
|
||||
var anonymizeList = await _fusionCache.GetOrSetAsync(CacheKeys.SystemAnonymization, _ => CacheHelper.GetSystemAnonymizationListAsync(_systemAnonymizationRepository), TimeSpan.FromDays(7));
|
||||
var anonymizeList = await _fusionCache.GetOrSetAsync(CacheKeys.SystemAnonymization, async _ => await CacheHelper.GetSystemAnonymizationListAsync(_systemAnonymizationRepository), TimeSpan.FromDays(7));
|
||||
|
||||
var fixedFiledList = anonymizeList.Where(t => t.IsFixed).ToList();
|
||||
var ircFiledList = anonymizeList.Where(t => t.IsFixed == false).ToList();
|
||||
|
|
|
@ -782,7 +782,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
|||
// 写入dicom 固定的信息,以及组织路径的信息 以及匿名化的信息
|
||||
var otherData = GetSaveToDicomInfo(verifyInfo.SubjectVisitId);
|
||||
|
||||
var anonymizeList = _fusionCache.GetOrSetAsync(CacheKeys.SystemAnonymization, _ => CacheHelper.GetSystemAnonymizationListAsync(_systemAnonymizationRepository), TimeSpan.FromDays(7)).Result;
|
||||
var anonymizeList = _fusionCache.GetOrSetAsync(CacheKeys.SystemAnonymization, async _ => await CacheHelper.GetSystemAnonymizationListAsync(_systemAnonymizationRepository), TimeSpan.FromDays(7)).Result;
|
||||
|
||||
return ResponseOutput.Ok<List<VerifyStudyUploadResult>>(result, new
|
||||
{
|
||||
|
|
|
@ -445,6 +445,9 @@ namespace IRaCIS.Core.Application.Service.Inspection.DTO
|
|||
/// </summary>
|
||||
public decimal? VisitPlanInfo { get; set; }
|
||||
|
||||
|
||||
public string? VisitName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 开始时间
|
||||
/// </summary>
|
||||
|
|
|
@ -190,6 +190,8 @@ namespace IRaCIS.Core.Application.Service.Inspection
|
|||
.WhereIf(!inQuery.TaskName.IsNullOrEmpty(), x => x.TaskName.Contains(inQuery.TaskName) || x.BlindName.Contains(inQuery.TaskName))
|
||||
.WhereIf(!inQuery.SubjectInfo.IsNullOrEmpty(), x => x.SubjectCode.Contains(inQuery.SubjectInfo))
|
||||
.WhereIf(!inQuery.RoleName.IsNullOrEmpty(), x => x.RoleName.Contains(inQuery.RoleName))
|
||||
.WhereIf(!inQuery.VisitName.IsNullOrEmpty(), x => x.VisitName.Contains(inQuery.VisitName))
|
||||
|
||||
//.WhereIf(dto.VisitPlanInfo != null&& dto.VisitPlanInfo!=(decimal) 1.11, x => x.VisitNum == dto.VisitPlanInfo)
|
||||
//.WhereIf(dto.VisitPlanInfo != (decimal)1.11,x=>x.InPlan!=null&& x.InPlan==false)
|
||||
.WhereIf(inQuery.StartTime != null, x => x.CreateTime >= inQuery.StartTime)
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
|
||||
//--------------------------------------------------------------------
|
||||
// 此代码由liquid模板自动生成 byzhouhang 20240909
|
||||
// 生成时间 2025-03-21 01:28:34Z
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||
//--------------------------------------------------------------------
|
||||
using System;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using System.Collections.Generic;
|
||||
namespace IRaCIS.Core.Application.ViewModel;
|
||||
|
||||
public class HIRHospitalView : HIRHospitalAddOrEdit
|
||||
{
|
||||
public DateTime CreateTime { get; set; }
|
||||
|
||||
public DateTime UpdateTime { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class HIRHospitalAddOrEdit
|
||||
{
|
||||
public Guid? Id { get; set; }
|
||||
|
||||
public string HospitalName { get; set; }
|
||||
public string HospitalAliasName { get; set; }
|
||||
public string Country { get; set; }
|
||||
public string City { get; set; }
|
||||
public string Province { get; set; }
|
||||
public string Address { get; set; }
|
||||
public string Phone { get; set; }
|
||||
|
||||
public bool IsCanConnectInternet { get; set; }
|
||||
|
||||
public string HospitalCode { get; set; }
|
||||
public string HospitalLogoPath { get; set; }
|
||||
public int TrialKeepCount { get; set; }
|
||||
|
||||
public bool IsDefault { get; set; }
|
||||
}
|
||||
|
||||
public class HIRHospitalQuery : PageInput
|
||||
{
|
||||
public string HospitalName { get; set; }
|
||||
public string Country { get; set; }
|
||||
public string City { get; set; }
|
||||
public string Province { get; set; }
|
||||
public string Address { get; set; }
|
||||
public string Phone { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -22,6 +22,32 @@ namespace IRaCIS.Application.Contracts
|
|||
public Guid? UserId { get; set; }
|
||||
}
|
||||
|
||||
public class TJUserInfoDto
|
||||
{
|
||||
public string Code { get; set; }
|
||||
|
||||
public string Msg { get; set; }
|
||||
|
||||
public bool Success { get; set; }
|
||||
|
||||
public TJUserInfoData Data { get; set; }
|
||||
}
|
||||
|
||||
public class TJUserInfoData
|
||||
{
|
||||
public string UserCode { get; set; }
|
||||
public string UserName { get; set; }
|
||||
public string DeptCode { get; set; }
|
||||
public string Sex { get; set; }
|
||||
public string Birthday { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string UserType { get; set; }
|
||||
|
||||
public List<string> Roles { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class LoginReturnDTO
|
||||
{
|
||||
public UserBasicInfo BasicInfo { get; set; } = new UserBasicInfo();
|
||||
|
@ -31,6 +57,26 @@ namespace IRaCIS.Application.Contracts
|
|||
|
||||
public SystemEmailSendConfigView CompanyInfo { get; set; }
|
||||
|
||||
public bool IsMutiAccount => AccountList?.Count > 1;
|
||||
public List<UserAccountInfo> AccountList { get; set; }
|
||||
|
||||
}
|
||||
public class UserAccountInfo
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string UserName { get; set; } = string.Empty;
|
||||
public string FullName { get; set; } = string.Empty;
|
||||
|
||||
public string Phone { get; set; } = string.Empty;
|
||||
public string EMail { get; set; } = string.Empty;
|
||||
|
||||
public Guid UserTypeId { get; set; }
|
||||
|
||||
public UserTypeEnum UserTypeEnum { get; set; }
|
||||
|
||||
public string UserTypeShortName { get; set; }
|
||||
|
||||
public int Status { get; set; }
|
||||
}
|
||||
|
||||
public class UserBasicInfo
|
||||
|
@ -120,10 +166,14 @@ namespace IRaCIS.Application.Contracts
|
|||
public class UserDetailDTO : UserInfo
|
||||
{
|
||||
public bool CanEditUserType { get; set; }
|
||||
|
||||
public bool IsMutiAccount => AccountList?.Count > 1;
|
||||
public List<UserAccountInfo> AccountList { get; set; }
|
||||
}
|
||||
|
||||
public class UserInfo
|
||||
{
|
||||
public string CheckCode { get; set; } = string.Empty;
|
||||
public Guid Id { get; set; }
|
||||
public string UserName { get; set; } = string.Empty;
|
||||
public string Password { get; set; } = string.Empty;
|
||||
|
@ -194,6 +244,8 @@ namespace IRaCIS.Application.Contracts
|
|||
|
||||
public string NewPassWord { get; set; } = string.Empty;
|
||||
public string OldPassWord { get; set; } = string.Empty;
|
||||
|
||||
public string CheckCode { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ namespace IRaCIS.Core.Application.Service
|
|||
Task<IResponseOutput> DeleteUser(Guid userId);
|
||||
Task<UserDetailDTO> GetUser(Guid id);
|
||||
Task<PageOutput<UserListDTO>> GetUserList(UserListQueryDTO param);
|
||||
|
||||
Task<IResponseOutput<LoginReturnDTO>> LoginSelectUserType(Guid userId, Guid userTypeId);
|
||||
Task<IResponseOutput<LoginReturnDTO>> Login(string userName, string password);
|
||||
Task<IResponseOutput> VerifyMFACodeAsync(Guid userId, string Code);
|
||||
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
using IP2Region.Net.Abstractions;
|
||||
using DocumentFormat.OpenXml.Spreadsheet;
|
||||
using IP2Region.Net.Abstractions;
|
||||
using IRaCIS.Application.Contracts;
|
||||
using IRaCIS.Core.Application.Auth;
|
||||
using IRaCIS.Core.Application.Contracts;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Core.Application.Helper.OtherTool;
|
||||
using IRaCIS.Core.Application.ViewModel;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
|
@ -9,6 +12,7 @@ using Medallion.Threading;
|
|||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Options;
|
||||
using NPOI.SS.Formula.Functions;
|
||||
using Panda.DynamicWebApi.Attributes;
|
||||
using System.Text.RegularExpressions;
|
||||
using ZiggyCreatures.Caching.Fusion;
|
||||
|
@ -27,12 +31,14 @@ namespace IRaCIS.Core.Application.Service
|
|||
IRepository<Trial> _trialRepository,
|
||||
IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig,
|
||||
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig,
|
||||
|
||||
IRepository<HIRHospital> _hirHospitalRepository,
|
||||
ITokenService _tokenService,
|
||||
ISearcher _searcher, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IFusionCache _fusionCache) : BaseService, IUserService
|
||||
{
|
||||
|
||||
private SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
|
||||
|
||||
|
||||
private async Task VerifyUserNameAsync(Guid? userId, string userName)
|
||||
{
|
||||
if (await _userRepository.WhereIf(userId != null, t => t.Id != userId).AnyAsync(t => t.UserName == userName))
|
||||
|
@ -237,8 +243,6 @@ namespace IRaCIS.Core.Application.Service
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IResponseOutput> InitSetUserNameAndPwd(Guid userId, string newUserName, string newPWd)
|
||||
{
|
||||
|
@ -275,11 +279,17 @@ namespace IRaCIS.Core.Application.Service
|
|||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> ResetPassword(Guid userId)
|
||||
{
|
||||
|
||||
var pwd = IRCEmailPasswordHelper.GenerateRandomPassword(10);
|
||||
var hospitalInfo = await _fusionCache.GetOrSetAsync(CacheKeys.Hospital,async _ => await CacheHelper.GetHospitalCode(_hirHospitalRepository), TimeSpan.FromDays(7));
|
||||
|
||||
|
||||
await _mailVerificationService.AdminResetPwdSendEmailAsync(userId, pwd);
|
||||
//var pwd = IRCEmailPasswordHelper.GenerateRandomPassword(10);
|
||||
|
||||
var pwd = "123456";
|
||||
|
||||
if (hospitalInfo.IsCanConnectInternet)
|
||||
{
|
||||
await _mailVerificationService.AdminResetPwdSendEmailAsync(userId, pwd);
|
||||
}
|
||||
|
||||
await _userRepository.UpdatePartialFromQueryAsync(userId, u => new User()
|
||||
{
|
||||
|
@ -337,50 +347,6 @@ namespace IRaCIS.Core.Application.Service
|
|||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证验证码,没问题就返回用户所有的账户
|
||||
/// </summary>
|
||||
/// <param name="email"></param>
|
||||
/// <param name="verifyCode"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="BusinessValidationFailedException"></exception>
|
||||
[AllowAnonymous]
|
||||
[HttpGet("{email}/{verifyCode}")]
|
||||
public async Task<List<UserAccountDto>> VerifyAnonymousVerifyCode(string email, string verifyCode)
|
||||
{
|
||||
var verificationRecord = await _verificationCodeRepository
|
||||
.Where(t => t.UserId == Guid.Empty && t.Code == verifyCode && t.CodeType == VerifyType.Email && t.EmailOrPhone == email).OrderByDescending(t => t.CreateTime).FirstOrDefaultAsync();
|
||||
|
||||
//检查数据库是否存在该验证码
|
||||
if (verificationRecord == null)
|
||||
{
|
||||
|
||||
//---验证码错误。
|
||||
throw new BusinessValidationFailedException(_localizer["User_VerificationCodeError"]);
|
||||
}
|
||||
else
|
||||
{
|
||||
//检查验证码是否失效
|
||||
if (verificationRecord.ExpirationTime < DateTime.Now)
|
||||
{
|
||||
|
||||
//---验证码已经过期。
|
||||
throw new BusinessValidationFailedException(_localizer["User_VerificationCodeExpired"]);
|
||||
}
|
||||
else //验证码正确 并且 没有超时
|
||||
{
|
||||
|
||||
//删除验证码历史记录
|
||||
await _verificationCodeRepository.BatchDeleteNoTrackingAsync(t => t.Id == verificationRecord.Id);
|
||||
}
|
||||
}
|
||||
|
||||
var list = await _userRepository.Where(t => t.EMail == email && t.Status == UserStateEnum.Enable).Select(t => new UserAccountDto() { UserId = t.Id, UserName = t.UserName, UserRealName = t.FullName, UserType = t.UserTypeRole.UserTypeShortName }).ToListAsync();
|
||||
|
||||
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
|
@ -397,7 +363,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
|
||||
await VerifyUserPwdAsync(userId, newPwd);
|
||||
|
||||
var success = await _userRepository.BatchUpdateNoTrackingAsync(t => t.Id == userId, u => new User()
|
||||
await _userRepository.UpdatePartialFromQueryAsync(t => t.Id == userId, u => new User()
|
||||
{
|
||||
Password = newPwd,
|
||||
IsFirstAdd = false
|
||||
|
@ -405,47 +371,11 @@ namespace IRaCIS.Core.Application.Service
|
|||
|
||||
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = userId, OptUserId = userId, LoginPassword = newPwd, OptType = UserOptType.UnloginModifyPasswoed }, true);
|
||||
|
||||
return ResponseOutput.Result(success);
|
||||
return ResponseOutput.Ok();
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 修改密码,当前支持旧密码修改密码
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> ModifyPassword(EditPasswordCommand editPwModel)
|
||||
{
|
||||
|
||||
await VerifyUserPwdAsync(_userInfo.Id, editPwModel.NewPassWord, editPwModel.OldPassWord);
|
||||
|
||||
|
||||
if (!string.IsNullOrEmpty(editPwModel.NewUserName))
|
||||
{
|
||||
|
||||
await VerifyUserNameAsync(_userInfo.Id, editPwModel.NewUserName);
|
||||
|
||||
await _userRepository.BatchUpdateNoTrackingAsync(t => t.Id == _userInfo.Id, u => new User()
|
||||
{
|
||||
UserName = editPwModel.NewUserName,
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
var success = await _userRepository.BatchUpdateNoTrackingAsync(t => t.Id == _userInfo.Id, u => new User()
|
||||
{
|
||||
Password = editPwModel.NewPassWord,
|
||||
IsFirstAdd = false
|
||||
});
|
||||
|
||||
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = _userInfo.Id, OptUserId = _userInfo.Id, OptType = UserOptType.LoginModifyPassword }, true);
|
||||
|
||||
return ResponseOutput.Result(success);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -471,6 +401,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
.WhereIf(inQuery.UserState != null, t => t.Status == inQuery.UserState)
|
||||
.WhereIf(inQuery.IsTestUser != null, t => t.IsTestUser == inQuery.IsTestUser)
|
||||
.WhereIf(inQuery.IsZhiZhun != null, t => t.IsZhiZhun == inQuery.IsZhiZhun)
|
||||
.WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.OA, t => t.UserTypeEnum != UserTypeEnum.Admin)
|
||||
.ProjectTo<UserListDTO>(_mapper.ConfigurationProvider);
|
||||
|
||||
return await userQueryable.ToPagedListAsync(inQuery);
|
||||
|
@ -486,7 +417,12 @@ namespace IRaCIS.Core.Application.Service
|
|||
public async Task<UserDetailDTO> GetUser(Guid id)
|
||||
{
|
||||
var userQuery = _userRepository.Where(t => t.Id == id).ProjectTo<UserDetailDTO>(_mapper.ConfigurationProvider);
|
||||
return await (userQuery.FirstOrDefaultAsync()).IfNullThrowException();
|
||||
var result = await (userQuery.FirstOrDefaultAsync()).IfNullThrowException();
|
||||
|
||||
result.AccountList = _userRepository.Where(t => t.EMail == result.EMail && t.UserTypeEnum != UserTypeEnum.SuperAdmin)
|
||||
.ProjectTo<UserAccountInfo>(_mapper.ConfigurationProvider).OrderBy(t => t.UserTypeShortName).ToList();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -497,6 +433,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
[UnitOfWork]
|
||||
public async Task<IResponseOutput<UserAddedReturnDTO>> AddUser(UserCommand userAddModel)
|
||||
{
|
||||
var hospitalInfo = await _fusionCache.GetOrSetAsync(CacheKeys.Hospital, async _ => await CacheHelper.GetHospitalCode(_hirHospitalRepository), TimeSpan.FromDays(7));
|
||||
|
||||
|
||||
await VerifyUserNameAsync(null, userAddModel.UserName);
|
||||
|
@ -516,23 +453,27 @@ namespace IRaCIS.Core.Application.Service
|
|||
|
||||
saveItem.UserCode = AppSettings.GetCodeStr(saveItem.Code, nameof(User));
|
||||
|
||||
if (saveItem.IsZhiZhun)
|
||||
{
|
||||
var organizationName = _userInfo.IsEn_Us ? _systemEmailConfig.OrganizationName : _systemEmailConfig.OrganizationNameCN;
|
||||
//if (saveItem.IsZhiZhun)
|
||||
//{
|
||||
// var organizationName = _userInfo.IsEn_Us ? _systemEmailConfig.OrganizationName : _systemEmailConfig.OrganizationNameCN;
|
||||
|
||||
saveItem.OrganizationName = organizationName;
|
||||
}
|
||||
// saveItem.OrganizationName = organizationName;
|
||||
//}
|
||||
|
||||
// IRCEmailPasswordHelper.GenerateRandomPassword(10)
|
||||
|
||||
saveItem.Password = MD5Helper.Md5(IRCEmailPasswordHelper.GenerateRandomPassword(10));
|
||||
saveItem.Password = MD5Helper.Md5("123456");
|
||||
|
||||
await _userRepository.AddAsync(saveItem);
|
||||
|
||||
var success = await _userRepository.SaveChangesAsync();
|
||||
}
|
||||
|
||||
if (hospitalInfo.IsCanConnectInternet)
|
||||
{
|
||||
await _mailVerificationService.AddUserSendEmailAsync(saveItem.Id, userAddModel.BaseUrl, userAddModel.RouteUrl);
|
||||
|
||||
await _mailVerificationService.AddUserSendEmailAsync(saveItem.Id, userAddModel.BaseUrl, userAddModel.RouteUrl);
|
||||
}
|
||||
|
||||
|
||||
return ResponseOutput.Ok(new UserAddedReturnDTO { Id = saveItem.Id, UserCode = saveItem.UserCode });
|
||||
|
@ -558,7 +499,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
|
||||
if (user == null) return Null404NotFound(user);
|
||||
|
||||
if (user.Status!=model.Status)
|
||||
if (user.Status != model.Status)
|
||||
{
|
||||
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = _userInfo.Id, OptUserId = model.Id, OptType = model.Status == UserStateEnum.Enable ? UserOptType.AccountEnable : UserOptType.AccountLocked }, true);
|
||||
|
||||
|
@ -567,14 +508,14 @@ namespace IRaCIS.Core.Application.Service
|
|||
|
||||
_mapper.Map(model, user);
|
||||
|
||||
if (user.IsZhiZhun)
|
||||
{
|
||||
user.OrganizationName = _userInfo.IsEn_Us ? _systemEmailConfig.OrganizationName : _systemEmailConfig.OrganizationNameCN;
|
||||
}
|
||||
//if (user.IsZhiZhun)
|
||||
//{
|
||||
// user.OrganizationName = _userInfo.IsEn_Us ? _systemEmailConfig.OrganizationName : _systemEmailConfig.OrganizationNameCN;
|
||||
//}
|
||||
|
||||
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = _userInfo.Id, OptUserId = model.Id, OptType = UserOptType.UpdateUser });
|
||||
|
||||
|
||||
|
||||
|
||||
var success = await _userRepository.SaveChangesAsync();
|
||||
|
||||
|
@ -695,6 +636,158 @@ namespace IRaCIS.Core.Application.Service
|
|||
return ResponseOutput.Ok();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同济生成账号
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
/// <param name="_userTypeRepository"></param>
|
||||
/// <param name="_hirHospitalRepository"></param>
|
||||
/// <returns></returns>
|
||||
[AllowAnonymous]
|
||||
[HttpGet]
|
||||
public async Task<IResponseOutput> TJUserLoginInfo(string token,
|
||||
[FromServices] IRepository<UserType> _userTypeRepository,
|
||||
[FromServices] IRepository<HIRHospital> _hirHospitalRepository)
|
||||
{
|
||||
#region MyRegion
|
||||
//同济医院token 地址:http://192.168.40.88:8080 appid:third-hirs
|
||||
|
||||
//本地测试地址接口
|
||||
|
||||
var apiUrl = "http://192.168.40.88:8080/dock/userinfo";
|
||||
var headers = new Dictionary<string, string>
|
||||
{
|
||||
{ "Content-Type", "application/json" } // 根据需要添加其他头部信息
|
||||
};
|
||||
|
||||
var requestData = new
|
||||
{
|
||||
token = token,
|
||||
appId = "third-hirs",
|
||||
};
|
||||
|
||||
var tjUserInfo = await RestClientAPI.PostAsync<TJUserInfoDto>(apiUrl, requestData, headers);
|
||||
#endregion
|
||||
|
||||
#region 测试数据
|
||||
|
||||
//var tjUserInfo = new TJUserInfoDto
|
||||
//{
|
||||
// Code = "200",
|
||||
// Msg = "操作成功",
|
||||
// Success = true,
|
||||
// Data = new TJUserInfoData
|
||||
// {
|
||||
// UserCode = "YS10138",
|
||||
// UserName = "胡学梅",
|
||||
// DeptCode = "2121",
|
||||
// Sex = "未知",
|
||||
// Birthday = "",
|
||||
// Title = "",
|
||||
// UserType = "doctor",
|
||||
// Roles = new List<string> { "pm", "crc" }
|
||||
// }
|
||||
//};
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
var generateRoles = new List<string>() { "PM", "CRC", "SR", "PI", "QA" };
|
||||
|
||||
if (tjUserInfo != null && tjUserInfo.Data?.Roles != null &&
|
||||
tjUserInfo.Data.Roles.Any(role => generateRoles.Any(gRole => string.Equals(gRole, role, StringComparison.OrdinalIgnoreCase))))
|
||||
{
|
||||
|
||||
var sysUserTypeList = _userTypeRepository.Where().Select(t => new { t.UserTypeShortName, t.UserTypeEnum, t.Id }).ToList();
|
||||
|
||||
var matchedRoles = generateRoles.Where(role => tjUserInfo.Data.Roles.Any(r => string.Equals(r, role, StringComparison.OrdinalIgnoreCase))).ToList();
|
||||
|
||||
|
||||
var hospital = await _hirHospitalRepository.Where(t => t.IsDefault == true).ProjectTo<HIRHospitalView>(_mapper.ConfigurationProvider).FirstNotNullAsync();
|
||||
|
||||
var thirdUId = tjUserInfo.Data.UserCode;
|
||||
|
||||
var email = $"{tjUserInfo.Data.UserCode}@tjhir.com";
|
||||
|
||||
var @lock = _distributedLockProvider.CreateLock($"UserAccount");
|
||||
|
||||
using (await @lock.AcquireAsync())
|
||||
{
|
||||
//匹配的角色 都匹配一遍账号,没有便生成
|
||||
foreach (var roleName in matchedRoles)
|
||||
{
|
||||
var userType = sysUserTypeList.Where(t => t.UserTypeShortName == roleName).First();
|
||||
|
||||
var userTypeId = userType.Id;
|
||||
|
||||
if (!_userRepository.Any(t => t.ThirdUserCode == thirdUId && t.UserTypeId == userTypeId))
|
||||
{
|
||||
var newCode = await _userRepository.Select(t => t.Code).DefaultIfEmpty().MaxAsync() + 1;
|
||||
|
||||
var newUser = new User()
|
||||
{
|
||||
FirstName = $"{tjUserInfo.Data.UserName}",
|
||||
LastName = "tj",
|
||||
|
||||
IsFirstAdd = false,
|
||||
IsZhiZhun = true,
|
||||
OrganizationName = hospital.HospitalName,
|
||||
Code = newCode,
|
||||
Password = MD5Helper.Md5("123456"),
|
||||
CheckCode = "123456",
|
||||
UserCode = AppSettings.GetCodeStr(newCode, nameof(User)),
|
||||
|
||||
UserTypeId = userTypeId,
|
||||
UserTypeEnum = userType.UserTypeEnum,
|
||||
|
||||
EMail = email,
|
||||
UserName = $"{tjUserInfo.Data.UserName}-{roleName}",
|
||||
ThirdUserCode = thirdUId,
|
||||
};
|
||||
|
||||
await _userRepository.AddAsync(newUser);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
await _userRepository.SaveChangesAsync();
|
||||
}
|
||||
|
||||
//返回该账号的在系统的中的所有角色,如果单个角色,就直接登录,如果是多个角色,那么前端进行选择后进行登录
|
||||
|
||||
var accountList = _userRepository.Where(t => t.EMail == email && t.UserTypeEnum != UserTypeEnum.SuperAdmin)
|
||||
.ProjectTo<UserAccountInfo>(_mapper.ConfigurationProvider).OrderBy(t => t.UserTypeShortName).ToList();
|
||||
|
||||
var hirToken = _tokenService.GetToken(IRaCISClaims.Create(new UserBasicInfo() { Id = Guid.NewGuid(), UserName = tjUserInfo.Data.UserName }));
|
||||
|
||||
return ResponseOutput.Ok(accountList, hirToken);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return ResponseOutput.NotOk("跳转系统对接的用户未配置当前系统的角色,无法自动生成账号,请联系管理员配置该跳转账户信息");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
[NonDynamicMethod]
|
||||
public async Task<IResponseOutput<LoginReturnDTO>> LoginSelectUserType(Guid userId, Guid userTypeId)
|
||||
{
|
||||
var userNamePwd = await _userRepository.Where(t => t.Id == userId && t.UserTypeId == userTypeId).Select(t => new { t.UserName, t.Password }).FirstNotNullAsync();
|
||||
|
||||
return await Login(userNamePwd.UserName, userNamePwd.Password);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 用户登陆
|
||||
/// </summary>
|
||||
|
@ -801,6 +894,9 @@ namespace IRaCIS.Core.Application.Service
|
|||
|
||||
});
|
||||
|
||||
userLoginReturnModel.AccountList = _userRepository.Where(t => t.EMail == userLoginReturnModel.BasicInfo.EMail && t.UserTypeEnum != UserTypeEnum.SuperAdmin)
|
||||
.ProjectTo<UserAccountInfo>(_mapper.ConfigurationProvider).ToList();
|
||||
|
||||
return ResponseOutput.Ok(userLoginReturnModel);
|
||||
|
||||
}
|
||||
|
@ -841,5 +937,124 @@ namespace IRaCIS.Core.Application.Service
|
|||
return ResponseOutput.Ok();
|
||||
}
|
||||
|
||||
|
||||
#region HIR 修改
|
||||
|
||||
/// <summary>
|
||||
/// 验证验证码,没问题就返回用户所有的账户
|
||||
/// </summary>
|
||||
/// <param name="email"></param>
|
||||
/// <param name="verifyCode"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="BusinessValidationFailedException"></exception>
|
||||
[AllowAnonymous]
|
||||
[HttpGet("{email}/{verifyCode}")]
|
||||
public async Task<List<UserAccountDto>> VerifyAnonymousVerifyCode(string email, string verifyCode)
|
||||
{
|
||||
var hospitalInfo = await _fusionCache.GetOrSetAsync(CacheKeys.Hospital, async _ => await CacheHelper.GetHospitalCode(_hirHospitalRepository), TimeSpan.FromDays(7));
|
||||
|
||||
if (hospitalInfo.IsCanConnectInternet)
|
||||
{
|
||||
var verificationRecord = await _verificationCodeRepository
|
||||
.Where(t => t.UserId == Guid.Empty && t.Code == verifyCode && t.CodeType == VerifyType.Email && t.EmailOrPhone == email).OrderByDescending(t => t.CreateTime).FirstOrDefaultAsync();
|
||||
|
||||
//检查数据库是否存在该验证码
|
||||
if (verificationRecord == null)
|
||||
{
|
||||
|
||||
//---验证码错误。
|
||||
throw new BusinessValidationFailedException(_localizer["User_VerificationCodeError"]);
|
||||
}
|
||||
else
|
||||
{
|
||||
//检查验证码是否失效
|
||||
if (verificationRecord.ExpirationTime < DateTime.Now)
|
||||
{
|
||||
|
||||
//---验证码已经过期。
|
||||
throw new BusinessValidationFailedException(_localizer["User_VerificationCodeExpired"]);
|
||||
}
|
||||
else //验证码正确 并且 没有超时
|
||||
{
|
||||
|
||||
//删除验证码历史记录
|
||||
await _verificationCodeRepository.BatchDeleteNoTrackingAsync(t => t.Id == verificationRecord.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var isPass = _userRepository.Where(t => t.EMail == email).Any(t => t.CheckCode == verifyCode);
|
||||
|
||||
if (!isPass)
|
||||
{
|
||||
throw new BusinessValidationFailedException(_localizer["User_VerificationCodeError"]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
var list = await _userRepository.Where(t => t.EMail == email).Select(t => new UserAccountDto() { UserId = t.Id, UserName = t.UserName, UserRealName = t.FullName, UserType = t.UserTypeRole.UserTypeShortName }).ToListAsync();
|
||||
|
||||
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
[HttpPut("{newCheckCode}")]
|
||||
public async Task<IResponseOutput> SetNewCheckCode(string newCheckCode)
|
||||
{
|
||||
var user = await _userRepository.FirstOrDefaultNoTrackingAsync(t => t.Id == _userInfo.Id);
|
||||
|
||||
await _userRepository.UpdatePartialFromQueryAsync(t => t.EMail == user.EMail, u => new User()
|
||||
{
|
||||
CheckCode = newCheckCode
|
||||
});
|
||||
|
||||
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = _userInfo.Id, OptUserId = _userInfo.Id, OptType = UserOptType.ModifyCheckCode }, true);
|
||||
return ResponseOutput.Ok();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 修改密码,当前支持旧密码修改密码
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> ModifyPassword(EditPasswordCommand editPwModel)
|
||||
{
|
||||
|
||||
await VerifyUserPwdAsync(_userInfo.Id, editPwModel.NewPassWord, editPwModel.OldPassWord);
|
||||
|
||||
|
||||
if (!string.IsNullOrEmpty(editPwModel.NewUserName))
|
||||
{
|
||||
|
||||
await VerifyUserNameAsync(_userInfo.Id, editPwModel.NewUserName);
|
||||
|
||||
await _userRepository.BatchUpdateNoTrackingAsync(t => t.Id == _userInfo.Id, u => new User()
|
||||
{
|
||||
UserName = editPwModel.NewUserName,
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
await _userRepository.UpdatePartialFromQueryAsync(t => t.Id == _userInfo.Id, u => new User()
|
||||
{
|
||||
Password = editPwModel.NewPassWord,
|
||||
CheckCode = editPwModel.CheckCode,
|
||||
IsFirstAdd = false
|
||||
});
|
||||
|
||||
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = _userInfo.Id, OptUserId = _userInfo.Id, OptType = UserOptType.LoginModifyPassword }, true);
|
||||
|
||||
return ResponseOutput.Ok();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
}
|
||||
|
||||
|
||||
|
||||
#region HIR 修改
|
||||
|
||||
/// <summary>
|
||||
/// 通过传递场景枚举 返回对应的下拉框数据 1:是外部 2:是内部 3:是Site调研 4: 邮件接收人,5:邮件抄送人
|
||||
|
@ -105,49 +105,53 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
|
||||
if (userTypeSelectEnum == UserTypeSelectEnum.ExternalUser)
|
||||
{
|
||||
userTypeEnums = new List<UserTypeEnum>() { UserTypeEnum.CPM, UserTypeEnum.SPM, UserTypeEnum.CPM, UserTypeEnum.SMM, UserTypeEnum.CMM, UserTypeEnum.EA, UserTypeEnum.MC };
|
||||
}
|
||||
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.TA)
|
||||
{
|
||||
userTypeEnums = new List<UserTypeEnum>() { UserTypeEnum.ProjectManager };
|
||||
}
|
||||
else
|
||||
{
|
||||
userTypeEnums = new List<UserTypeEnum>() { UserTypeEnum.PI, UserTypeEnum.MIM, UserTypeEnum.IQC };
|
||||
}
|
||||
|
||||
|
||||
if (userTypeSelectEnum == UserTypeSelectEnum.InnerUser)
|
||||
{
|
||||
userTypeEnums = new List<UserTypeEnum>() { UserTypeEnum.ClinicalResearchCoordinator, UserTypeEnum.ProjectManager, UserTypeEnum.CRA, UserTypeEnum.IQC, UserTypeEnum.APM, UserTypeEnum.MIM, UserTypeEnum.QA, UserTypeEnum.MW, UserTypeEnum.MC };
|
||||
|
||||
//if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.SuperAdmin)
|
||||
//{
|
||||
// userTypeEnums.Add(UserTypeEnum.ProjectManager);
|
||||
//}
|
||||
}
|
||||
|
||||
if (userTypeSelectEnum == UserTypeSelectEnum.SiteSurvey)
|
||||
{
|
||||
userTypeEnums = new List<UserTypeEnum>() { UserTypeEnum.CRA, UserTypeEnum.ClinicalResearchCoordinator };
|
||||
|
||||
userTypeEnums = new List<UserTypeEnum>() { UserTypeEnum.SR, UserTypeEnum.ClinicalResearchCoordinator, UserTypeEnum.CRA };
|
||||
}
|
||||
|
||||
|
||||
if (userTypeSelectEnum == UserTypeSelectEnum.EnrollOrPD_EMailCopy)
|
||||
{
|
||||
userTypeEnums = new List<UserTypeEnum>() { UserTypeEnum.ProjectManager, UserTypeEnum.APM, UserTypeEnum.CPM, UserTypeEnum.SPM, UserTypeEnum.SMM, UserTypeEnum.CMM };
|
||||
userTypeEnums = new List<UserTypeEnum>() { UserTypeEnum.ProjectManager, UserTypeEnum.APM, UserTypeEnum.CPM, UserTypeEnum.SPM };
|
||||
|
||||
}
|
||||
|
||||
if (userTypeSelectEnum == UserTypeSelectEnum.EnrollOrPD_EmailReceive)
|
||||
{
|
||||
userTypeEnums = new List<UserTypeEnum>() { UserTypeEnum.CRA, UserTypeEnum.ClinicalResearchCoordinator };
|
||||
}
|
||||
|
||||
if (userTypeSelectEnum == UserTypeSelectEnum.TrialDoc)
|
||||
{
|
||||
userTypeEnums = new List<UserTypeEnum>() { UserTypeEnum.PI, UserTypeEnum.SR, UserTypeEnum.ProjectManager, UserTypeEnum.TA, UserTypeEnum.IQC, UserTypeEnum.IM, UserTypeEnum.MIM };
|
||||
}
|
||||
|
||||
|
||||
|
||||
var query = _userTypeRepository.Where(x => x.UserTypeEnum != UserTypeEnum.SuperAdmin)
|
||||
.WhereIf(userTypeSelectEnum != UserTypeSelectEnum.None, t => userTypeEnums.Contains(t.UserTypeEnum))
|
||||
.OrderBy(t => t.UserTypeShortName).ProjectTo<TrialUserType>(_mapper.ConfigurationProvider);
|
||||
var query = _userTypeRepository/*.Where(x => x.UserTypeEnum != UserTypeEnum.SuperAdmin)*/
|
||||
.WhereIf(userTypeSelectEnum != UserTypeSelectEnum.None && userTypeEnums.Count > 0, t => userTypeEnums.Contains(t.UserTypeEnum))
|
||||
.OrderBy(t => t.Order).ProjectTo<TrialUserType>(_mapper.ConfigurationProvider);
|
||||
|
||||
return await query.ToListAsync();
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -136,6 +136,11 @@ namespace IRaCIS.Core.Application.Service
|
|||
;
|
||||
|
||||
CreateMap<UserFeedBackAddOrEdit, UserFeedBack>().ReverseMap();
|
||||
|
||||
CreateMap<User, UserAccountInfo>()
|
||||
.ForMember(d => d.UserTypeShortName, c => c.MapFrom(t => t.UserTypeRole.UserTypeShortName));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -356,6 +356,8 @@ namespace IRaCIS.Core.Application.Contracts.DTO
|
|||
}
|
||||
public class QAStudyInfoDTO
|
||||
{
|
||||
public string PatientIdStr { get; set; }
|
||||
public string PatientName { get; set; }
|
||||
|
||||
public bool IsDeleted { get; set; }
|
||||
public string StudyInstanceUid { get; set; } = string.Empty;
|
||||
|
|
|
@ -1184,8 +1184,8 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
|
||||
|
||||
//在当前访视触发裁判,或者在截止日期小于等于当前访视的阅片期触发裁判
|
||||
[DictionaryTranslateAttribute("YesOrNo")]
|
||||
public bool IsTrigerJudge { get; set; }
|
||||
[DictionaryTranslateAttribute("YesOrNoAudit")]
|
||||
public bool? IsTrigerJudge { get; set; }
|
||||
|
||||
//(如果是访视点裁判,则仅在所选阅片人对应访视 显示;如果是阅片期裁判,则在所选阅片人 阅片期内的所有访视 显示此原因)
|
||||
public string JudgeNote { get; set; } = string.Empty;
|
||||
|
|
|
@ -771,7 +771,7 @@ namespace IRaCIS.Core.Application.Image.QA
|
|||
var succeess2 = await _dicomInstanceRepository.BatchDeleteNoTrackingAsync(t => t.StudyId == id);
|
||||
var success3 = await _dicomSeriesrepository.BatchDeleteNoTrackingAsync(t => t.StudyId == id);
|
||||
|
||||
await _scpStudyRepository.BatchUpdateNoTrackingAsync(t => t.Id == id, u => new SCPStudy() { SubjectVisitId = null });
|
||||
//await _scpStudyRepository.BatchUpdateNoTrackingAsync(t => t.Id == id, u => new SCPStudy() { SubjectVisitId = null });
|
||||
|
||||
|
||||
|
||||
|
@ -797,17 +797,17 @@ namespace IRaCIS.Core.Application.Image.QA
|
|||
|
||||
}
|
||||
|
||||
var subjectId = waitDeleteStudyList.Select(t => t.SubjectId).FirstOrDefault();
|
||||
//var subjectId = waitDeleteStudyList.Select(t => t.SubjectId).FirstOrDefault();
|
||||
|
||||
var patientList = _scpPatientRepository.Where(t => t.SubjectId == subjectId).Select(t => t.Id).ToList();
|
||||
//var patientList = _scpPatientRepository.Where(t => t.SubjectId == subjectId).Select(t => t.Id).ToList();
|
||||
|
||||
foreach (var patientId in patientList)
|
||||
{
|
||||
if (_scpPatientRepository.Where(t => t.Id == patientId).Any(t => t.SCPStudyList.Count() == t.SCPStudyList.Where(t => t.SubjectVisitId == null).Count()))
|
||||
{
|
||||
await _scpPatientRepository.BatchUpdateNoTrackingAsync(t => t.Id == patientId, u => new SCPPatient() { SubjectId = null });
|
||||
}
|
||||
}
|
||||
//foreach (var patientId in patientList)
|
||||
//{
|
||||
// if (_scpPatientRepository.Where(t => t.Id == patientId).Any(t => t.SCPStudyList.Count() == t.SCPStudyList.Where(t => t.SubjectVisitId == null).Count()))
|
||||
// {
|
||||
// await _scpPatientRepository.BatchUpdateNoTrackingAsync(t => t.Id == patientId, u => new SCPPatient() { SubjectId = null });
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -255,7 +255,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
false)))
|
||||
.ForMember(o => o.JudgeNote, t => t.MapFrom(u => u.JudgeVisitTask.JudgeResultRemark))
|
||||
.ForMember(o => o.VisitNote, t => t.MapFrom(u => u.ReadingTaskQuestionAnswerList.Where(c => c.ReadingQuestionTrial.QuestionType == QuestionType.AdjustReason).FirstOrDefault()!.Answer))
|
||||
.ForMember(o => o.TrialSiteCode, t => t.MapFrom(u => u.Subject.TrialSite.TrialSiteCode))
|
||||
//.ForMember(o => o.TrialSiteCode, t => t.MapFrom(u => u.Subject.TrialSite.TrialSiteCode))
|
||||
.ForMember(o => o.SubjectCode, t => t.MapFrom(u => u.Subject.Code))
|
||||
.ForMember(o => o.UserName, t => t.MapFrom(u => u.DoctorUser.UserName))
|
||||
.ForMember(o => o.QuestionAnswerList, t => t.MapFrom(u => u.ReadingTaskQuestionAnswerList
|
||||
|
|
|
@ -0,0 +1,404 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IRaCIS.Core.Application.Service.Reading.Dto
|
||||
{
|
||||
|
||||
public class TumorEvaluationInfo
|
||||
{
|
||||
|
||||
|
||||
public List<ExportTumorEvaluationInfo> VisitList { get; set; }
|
||||
}
|
||||
|
||||
public class ExportTumorEvaluationInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 所有访视的靶病灶列表
|
||||
/// </summary>
|
||||
public List<ExportVisitData> VisitList { get; set; }
|
||||
|
||||
public bool IsLastPage { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 受试者Code
|
||||
/// </summary>
|
||||
public string SubjectCode { get; set; } =string.Empty;
|
||||
|
||||
public string SubjectName { get; set; } = string.Empty;
|
||||
|
||||
public string ResearchProgramNo { get; set; } = string.Empty;
|
||||
|
||||
public ExportData Lesion { get; set; }=new ExportData();
|
||||
|
||||
/// <summary>
|
||||
/// 访视一
|
||||
/// </summary>
|
||||
public ExportVisitData VisitOne
|
||||
{
|
||||
get
|
||||
{
|
||||
return VisitList[0];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 访视二
|
||||
/// </summary>
|
||||
public ExportVisitData VisitTwo
|
||||
{
|
||||
get
|
||||
{
|
||||
if (VisitList.Count >= 2)
|
||||
{
|
||||
return VisitList[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
return new ExportVisitData();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 访视三
|
||||
/// </summary>
|
||||
public ExportVisitData VisitThree
|
||||
{
|
||||
get
|
||||
{
|
||||
if (VisitList.Count >= 3)
|
||||
{
|
||||
return VisitList[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
return new ExportVisitData();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 靶病灶信息
|
||||
/// </summary>
|
||||
public List<TargetInfo> TargetInfoList
|
||||
{
|
||||
get
|
||||
{
|
||||
List<TargetInfo> targets=new List<TargetInfo>();
|
||||
|
||||
var index = 0;
|
||||
foreach (var item in VisitOne.VisitTargetInfoList)
|
||||
{
|
||||
TargetInfo targetInfo = new TargetInfo()
|
||||
{
|
||||
Title = item.Title,
|
||||
VisitOneImgNum = item.VisitImgNum,
|
||||
VisitOneLength = item.VisitLength.ToString(),
|
||||
VisitTwoImgNum = VisitList.Count >= 2 ? VisitTwo.VisitTargetInfoList[index].VisitImgNum : string.Empty,
|
||||
VisitTwoLength = VisitList.Count >= 2 ? VisitTwo.VisitTargetInfoList[index].VisitLength.ToString() : string.Empty,
|
||||
VisitThreeImgNum = VisitList.Count >= 3 ? VisitThree.VisitTargetInfoList[index].VisitImgNum : string.Empty,
|
||||
VisitThreeLength = VisitList.Count >= 3 ? VisitThree.VisitTargetInfoList[index].VisitLength.ToString() : string.Empty
|
||||
};
|
||||
targets.Add(targetInfo);
|
||||
index++;
|
||||
}
|
||||
return targets;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 非靶病灶信息
|
||||
/// </summary>
|
||||
public List<TargetInfo> NoTargetInfoList
|
||||
{
|
||||
get
|
||||
{
|
||||
List<TargetInfo> targets = new List<TargetInfo>();
|
||||
|
||||
var index = 0;
|
||||
foreach (var item in VisitOne.VisitNoTargetInfoList)
|
||||
{
|
||||
TargetInfo targetInfo = new TargetInfo()
|
||||
{
|
||||
Title = item.Title,
|
||||
VisitOneImgNum = item.VisitImgNum,
|
||||
VisitOneLength = item.VisitLength!=null? item.VisitLength.Value.ToString():string.Empty,
|
||||
VisitTwoImgNum = VisitList.Count >= 2 ? VisitTwo.VisitNoTargetInfoList[index].VisitImgNum : string.Empty,
|
||||
VisitTwoLength = VisitList.Count >= 2&& VisitTwo.VisitNoTargetInfoList[index].VisitLength!=null ? VisitTwo.VisitNoTargetInfoList[index].VisitLength.Value.ToString() : string.Empty,
|
||||
VisitThreeImgNum = VisitList.Count >= 3 ? VisitThree.VisitNoTargetInfoList[index].VisitImgNum : string.Empty,
|
||||
VisitThreeLength = VisitList.Count >= 3&& VisitThree.VisitNoTargetInfoList[index].VisitLength!=null ? VisitThree.VisitNoTargetInfoList[index].VisitLength.Value.ToString() : string.Empty
|
||||
};
|
||||
targets.Add(targetInfo);
|
||||
index++;
|
||||
}
|
||||
return targets;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class TargetInfo
|
||||
{
|
||||
public string Title { get; set; } = string.Empty;
|
||||
|
||||
public string VisitOneImgNum { get; set; } = string.Empty;
|
||||
|
||||
public string VisitOneLength { get; set; } = string.Empty;
|
||||
|
||||
public string VisitTwoImgNum { get; set; } = string.Empty;
|
||||
|
||||
public string VisitTwoLength { get; set; } = string.Empty;
|
||||
|
||||
public string VisitThreeImgNum { get; set; } = string.Empty;
|
||||
|
||||
public string VisitThreeLength { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public class ExportData
|
||||
{
|
||||
public string OneVisitName { get; set; } = string.Empty;
|
||||
|
||||
public string OneCheckDate { get; set; } = string.Empty;
|
||||
|
||||
public string OneCheckInfoStr { get; set; } = string.Empty;
|
||||
|
||||
public string OneTargetSum { get; set; } = string.Empty;
|
||||
|
||||
public string OneHaveNewLesion { get; set; } = string.Empty;
|
||||
|
||||
public string OneTargetResult { get; set; } = string.Empty;
|
||||
|
||||
public string OneNoTargetResult { get; set; } = string.Empty;
|
||||
|
||||
public string OneOverallResult { get; set; } = string.Empty;
|
||||
|
||||
public string OneDoctorSignTime { get; set; } = string.Empty;
|
||||
|
||||
public string TwoVisitName { get; set; } = string.Empty;
|
||||
|
||||
public string TwoCheckDate { get; set; } = string.Empty;
|
||||
|
||||
|
||||
public string TwoCheckInfoStr { get; set; } = string.Empty;
|
||||
|
||||
public string TwoTargetSum { get; set; } = string.Empty;
|
||||
|
||||
public string TwoHaveNewLesion { get; set; } = string.Empty;
|
||||
|
||||
public string TwoTargetResult { get; set; } = string.Empty;
|
||||
|
||||
public string TwoNoTargetResult { get; set; } = string.Empty;
|
||||
|
||||
public string TwoOverallResult { get; set; } = string.Empty;
|
||||
|
||||
public string TwoDoctorSignTime { get; set; } = string.Empty;
|
||||
|
||||
public string ThreeVisitName { get; set; } = string.Empty;
|
||||
|
||||
public string ThreeCheckDate { get; set; } = string.Empty;
|
||||
|
||||
public string ThreeCheckInfoStr { get; set; } = string.Empty;
|
||||
|
||||
public string ThreeTargetSum { get; set; } = string.Empty;
|
||||
|
||||
public string ThreeHaveNewLesion { get; set; } = string.Empty;
|
||||
|
||||
public string ThreeTargetResult { get; set; } = string.Empty;
|
||||
|
||||
public string ThreeNoTargetResult { get; set; } = string.Empty;
|
||||
|
||||
public string ThreeOverallResult { get; set; } = string.Empty;
|
||||
|
||||
public string ThreeDoctorSignTime { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public class ExportVisitData
|
||||
{
|
||||
/// <summary>
|
||||
/// 访视名称
|
||||
/// </summary>
|
||||
public string VisitName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 访视序号
|
||||
/// </summary>
|
||||
public decimal VisitNum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 检查日期
|
||||
/// </summary>
|
||||
public string CheckDate { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 检查信息
|
||||
/// </summary>
|
||||
public List<DicomStudyInfo> CheckInfoList { get; set; } = new List<DicomStudyInfo>();
|
||||
|
||||
/// <summary>
|
||||
/// 检查信息字符串
|
||||
/// </summary>
|
||||
public string CheckInfoStr => string.Join(";", CheckInfoList.Select(x => $"{x.Modalities}/{x.BodyPartExamined}"));
|
||||
|
||||
/// <summary>
|
||||
/// 是否有新病灶
|
||||
/// </summary>
|
||||
public string HaveNewLesion { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 靶病灶结果
|
||||
/// </summary>
|
||||
public string TargetResult { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 非靶病灶结果
|
||||
/// </summary>
|
||||
public string NoTargetResult { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 总体结果
|
||||
/// </summary>
|
||||
public string OverallResult { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 医生名称
|
||||
/// </summary>
|
||||
public string DoctorName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 签名时间
|
||||
/// </summary>
|
||||
public string SignTime { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 医生签名时间
|
||||
/// </summary>
|
||||
public string DoctorSignTime
|
||||
{
|
||||
get
|
||||
{
|
||||
return DoctorName==string.Empty?string.Empty: $"{DoctorName}/{SignTime}";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 靶病灶信息
|
||||
/// </summary>
|
||||
public List<VisitLesionInfo> VisitTargetInfoList { get; set; } = new List<VisitLesionInfo>();
|
||||
|
||||
/// <summary>
|
||||
/// 靶病灶总长度
|
||||
/// </summary>
|
||||
public decimal? TargetSum
|
||||
{
|
||||
get
|
||||
{
|
||||
return VisitTargetInfoList.Sum(x => x.VisitLength);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 非靶病灶信息
|
||||
/// </summary>
|
||||
public List<VisitLesionInfo> VisitNoTargetInfoList { get; set; } = new List<VisitLesionInfo>();
|
||||
|
||||
}
|
||||
|
||||
public class VisitLesionInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 序号
|
||||
/// </summary>
|
||||
public string RowMark { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 器官
|
||||
/// </summary>
|
||||
public string Organ { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 部位
|
||||
/// </summary>
|
||||
public string Part { get; set; } = string.Empty;
|
||||
|
||||
public int Number { get; set; }
|
||||
|
||||
public string Title {
|
||||
get
|
||||
{
|
||||
if (RowMark != string.Empty)
|
||||
{
|
||||
return $"{Number}:{RowMark},{Organ}:{Part}";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"{Number}";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查号
|
||||
/// </summary>
|
||||
public int StudyCode { get; set; }
|
||||
|
||||
public Guid? RowId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 序列号
|
||||
/// </summary>
|
||||
public int SeriesNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 图像号
|
||||
/// </summary>
|
||||
public int InstanceNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 图像号
|
||||
/// </summary>
|
||||
public string VisitImgNum
|
||||
{
|
||||
get
|
||||
{
|
||||
if (RowId == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"{StudyCode}/{SeriesNumber}/{InstanceNumber}";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 长度
|
||||
/// </summary>
|
||||
public decimal? VisitLength { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class DicomStudyInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 检查类型
|
||||
/// </summary>
|
||||
public string Modalities { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 标记
|
||||
/// </summary>
|
||||
public string BodyPartExamined { get; set; }
|
||||
}
|
||||
}
|
|
@ -291,6 +291,32 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
public List<string> SheetNames { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class ExportReportQuestion
|
||||
{
|
||||
public string QuestionName { get; set; }
|
||||
|
||||
public QuestionType QuestionType { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public class DownLoadReadReportInDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务Id
|
||||
/// </summary>
|
||||
public Guid VisitTaskId { get; set; }
|
||||
|
||||
public Guid DownLoadGuid { get; set; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 阅片计算Dto
|
||||
/// </summary>
|
||||
|
|
|
@ -446,6 +446,24 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
|
||||
}
|
||||
|
||||
public class CaGetVisitReadReportUrl
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务Id
|
||||
/// </summary>
|
||||
public Guid VisitTaskId { get; set; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class GenerateReadingReportInDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务Id
|
||||
/// </summary>
|
||||
public Guid VisitTaskId { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class GetPreviousOtherPicturePathInDto
|
||||
{
|
||||
|
|
|
@ -41,5 +41,7 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
|
||||
Task<List<GetReadingPastResultListOutDto>> GetReadingPastResultList(GetReadingPastResultListInDto inDto);
|
||||
|
||||
Task<(List<GetRelatedVisitTaskOutDto>, object)> GetRelatedVisitTask(GetRelatedVisitTaskInDto inDto);
|
||||
|
||||
}
|
||||
}
|
|
@ -127,7 +127,8 @@ namespace IRaCIS.Core.Application.Service
|
|||
&& x.ReadingCategory == ReadingCategory.Visit
|
||||
&& x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId
|
||||
|
||||
&& x.DoctorUserId == taskInfo.DoctorUserId &&
|
||||
&&
|
||||
//x.DoctorUserId == taskInfo.DoctorUserId &&
|
||||
x.ReadingTaskState == ReadingTaskState.HaveSigned &&
|
||||
x.ReReadingApplyState != ReReadingApplyState.Agree
|
||||
).OrderBy(x => x.VisitTaskNum).Select(x => new TaskInfo()
|
||||
|
@ -155,7 +156,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
&& x.ReadingCategory == ReadingCategory.Visit
|
||||
&& x.IsAnalysisCreate == taskInfo.IsAnalysisCreate
|
||||
&& x.IsSelfAnalysis == taskInfo.IsSelfAnalysis
|
||||
&& x.DoctorUserId != taskInfo.DoctorUserId
|
||||
&& x.ArmEnum != taskInfo.ArmEnum
|
||||
&& x.ReadingTaskState == ReadingTaskState.HaveSigned
|
||||
&& x.ReReadingApplyState != ReReadingApplyState.Agree)
|
||||
.OrderBy(x => x.VisitTaskNum).Select(x => new TaskInfo()
|
||||
|
@ -204,7 +205,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
List<TaskInfo> otherTask = await _visitTaskRepository.Where(x =>
|
||||
x.SouceReadModuleId == taskInfo.SouceReadModuleId
|
||||
&& x.SourceSubjectVisitId == taskInfo.SourceSubjectVisitId
|
||||
&& x.DoctorUserId != taskInfo.DoctorUserId
|
||||
&& x.ArmEnum != taskInfo.ArmEnum
|
||||
&& x.IsAnalysisCreate == taskInfo.IsAnalysisCreate
|
||||
&& x.IsSelfAnalysis == taskInfo.IsSelfAnalysis
|
||||
&& x.ReadingTaskState == ReadingTaskState.HaveSigned
|
||||
|
@ -259,7 +260,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
&& (x.ReadingCategory == ReadingCategory.Global || x.ReadingCategory == ReadingCategory.Judge)
|
||||
&& x.IsAnalysisCreate == taskInfo.IsAnalysisCreate
|
||||
&& x.IsSelfAnalysis == taskInfo.IsSelfAnalysis
|
||||
&& x.DoctorUserId == taskInfo.DoctorUserId
|
||||
&& x.ArmEnum == taskInfo.ArmEnum
|
||||
&& x.ReadingTaskState == ReadingTaskState.HaveSigned
|
||||
&& x.ReReadingApplyState != ReReadingApplyState.Agree)
|
||||
.Select(x => new
|
||||
|
|
|
@ -244,7 +244,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
/// <param name="inDto"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[TypeFilter(typeof(TrialResourceFilter))]
|
||||
[TrialGlobalLimit("AfterStopCannNotOpt")]
|
||||
public async Task<IResponseOutput> AddOrUpdateReadingMedicineTrialQuestion(ReadingMedicineTrialQuestionAddOrEdit inDto)
|
||||
{
|
||||
var existsQuery = _readingMedicineTrialQuestionRepository
|
||||
|
|
|
@ -170,7 +170,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
|
||||
|
||||
var otherGlobalTask = await _visitTaskRepository.Where(x => x.SouceReadModuleId == taskInfo.SouceReadModuleId && x.IsAnalysisCreate == taskInfo.IsAnalysisCreate
|
||||
&& x.IsSelfAnalysis == taskInfo.IsSelfAnalysis && x.TaskState == TaskState.Effect && x.DoctorUserId != taskInfo.DoctorUserId
|
||||
&& x.IsSelfAnalysis == taskInfo.IsSelfAnalysis && x.TaskState == TaskState.Effect && x.ArmEnum != taskInfo.ArmEnum
|
||||
).FirstOrDefaultAsync();
|
||||
if (otherGlobalTask != null)
|
||||
{
|
||||
|
@ -196,7 +196,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
&& x.ReadingCategory == ReadingCategory.Judge
|
||||
&& x.IsAnalysisCreate == taskInfo.IsAnalysisCreate
|
||||
&& x.IsSelfAnalysis == taskInfo.IsSelfAnalysis
|
||||
&& x.DoctorUserId == taskInfo.DoctorUserId
|
||||
//&& x.DoctorUserId == taskInfo.DoctorUserId
|
||||
&& x.ReadingTaskState == ReadingTaskState.HaveSigned
|
||||
&& x.VisitTaskNum == taskInfo.VisitTaskNum + ReadingCommon.TaskNumDic[ReadingCategory.Judge]
|
||||
&& x.ReReadingApplyState != ReReadingApplyState.Agree).FirstOrDefaultAsync();
|
||||
|
@ -219,7 +219,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
x.IsAnalysisCreate == taskInfo.IsAnalysisCreate &&
|
||||
x.ArmEnum == taskInfo.ArmEnum &&
|
||||
x.IsSelfAnalysis == taskInfo.IsSelfAnalysis &&
|
||||
x.DoctorUserId == taskInfo.DoctorUserId &&
|
||||
x.ArmEnum == taskInfo.ArmEnum &&
|
||||
x.TaskState == TaskState.Effect &&
|
||||
x.VisitTaskNum < taskInfo.VisitTaskNum);
|
||||
|
||||
|
@ -334,7 +334,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
var lastGlobalTask = await _visitTaskRepository.Where(x => x.ReadingCategory == ReadingCategory.Global &&
|
||||
x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId &&
|
||||
x.SubjectId == taskInfo.SubjectId && x.IsAnalysisCreate == taskInfo.IsAnalysisCreate && x.TaskState == TaskState.Effect && x.VisitTaskNum < taskInfo.VisitTaskNum)
|
||||
.Where(x => x.DoctorUserId == taskInfo.DoctorUserId)
|
||||
.Where(x => x.ArmEnum == taskInfo.ArmEnum)
|
||||
.OrderByDescending(x => x.VisitTaskNum)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
|
|
|
@ -68,6 +68,58 @@ namespace IRaCIS.Core.Application.Service
|
|||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 下载阅片报告
|
||||
/// </summary>
|
||||
/// <param name="inDto"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<FileResult> DownLoadReadReport(DownLoadReadReportInDto inDto)
|
||||
{
|
||||
return await _readingCalculateService.DownLoadReadReport(inDto);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取阅片报告
|
||||
/// </summary>
|
||||
/// <param name="inDto"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<string> GetVisitReadReportUrl(GenerateReadingReportInDto inDto)
|
||||
{
|
||||
return await _readingCalculateService.GetVisitReadReportUrl(new CaGetVisitReadReportUrl()
|
||||
{
|
||||
VisitTaskId = inDto.VisitTaskId,
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载瘤评估
|
||||
/// </summary>
|
||||
/// <param name="inDto"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<FileResult> DownTumorEvaluation(DownLoadReadReportInDto inDto)
|
||||
{
|
||||
return await _readingCalculateService.DownLoadTumorEvaluation(inDto);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取肿瘤评估
|
||||
/// </summary>
|
||||
/// <param name="inDto"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<string> GetTumorEvaluationUrl(GenerateReadingReportInDto inDto)
|
||||
{
|
||||
return await _readingCalculateService.GetTumorEvaluationReportUrl(new CaGetVisitReadReportUrl()
|
||||
{
|
||||
VisitTaskId = inDto.VisitTaskId,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#region 计算
|
||||
|
||||
/// <summary>
|
||||
|
@ -490,7 +542,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
(x.TrialId == taskInfo.TrialId &&
|
||||
x.SubjectId == taskInfo.SubjectId &&
|
||||
x.ArmEnum == taskInfo.ArmEnum &&
|
||||
x.DoctorUserId == taskInfo.DoctorUserId &&
|
||||
//x.DoctorUserId == taskInfo.DoctorUserId &&
|
||||
|
||||
x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId &&
|
||||
x.TaskState == TaskState.Effect &&
|
||||
|
@ -605,7 +657,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
x.VisitTaskNum < taskInfo.VisitTaskNum &&
|
||||
x.ArmEnum == taskInfo.ArmEnum &&
|
||||
x.Id != inDto.VisitTaskId &&
|
||||
x.DoctorUserId == taskInfo.DoctorUserId &&
|
||||
//x.DoctorUserId == taskInfo.DoctorUserId &&
|
||||
x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId &&
|
||||
x.ReadingTaskState == ReadingTaskState.HaveSigned &&
|
||||
x.TaskState == TaskState.Effect &&
|
||||
|
@ -729,7 +781,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
if (await _visitTaskRepository.AnyAsync(x => x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId
|
||||
&& x.IsAnalysisCreate && taskInfo.IsAnalysisCreate
|
||||
&& x.SubjectId == taskInfo.SubjectId && x.TaskState == TaskState.Effect &&
|
||||
((x.ReReadingApplyState == ReReadingApplyState.DocotorHaveApplyed && x.DoctorUserId == taskInfo.DoctorUserId) || x.ReReadingApplyState == ReReadingApplyState.TrialGroupHaveApplyed)
|
||||
((x.ReReadingApplyState == ReReadingApplyState.DocotorHaveApplyed && x.ArmEnum == taskInfo.ArmEnum) || x.ReReadingApplyState == ReReadingApplyState.TrialGroupHaveApplyed)
|
||||
|
||||
))
|
||||
{
|
||||
|
@ -818,7 +870,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
var laskTaskId = await _visitTaskRepository.Where(x =>
|
||||
(x.SubjectId == taskInfo.SubjectId && x.TaskState == TaskState.Effect
|
||||
&& x.IsAnalysisCreate == taskInfo.IsAnalysisCreate
|
||||
&& x.DoctorUserId == taskInfo.DoctorUserId
|
||||
&& x.ArmEnum == taskInfo.ArmEnum
|
||||
&& x.IsSelfAnalysis == taskInfo.IsSelfAnalysis
|
||||
&& x.VisitTaskNum < taskInfo.VisitTaskNum
|
||||
&& x.ArmEnum == taskInfo.ArmEnum
|
||||
|
@ -1208,7 +1260,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
|
||||
var baselineTaskId = await _visitTaskRepository.Where(x => x.SourceSubjectVisitId == baseLineVisitId
|
||||
&& x.ArmEnum == taskInfo.ArmEnum
|
||||
&& x.DoctorUserId == taskInfo.DoctorUserId
|
||||
&& x.ArmEnum == taskInfo.ArmEnum
|
||||
&& x.IsAnalysisCreate == taskInfo.IsAnalysisCreate
|
||||
&& x.TaskState == TaskState.Effect
|
||||
&& x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId
|
||||
|
@ -1219,7 +1271,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
var laskTaskId = await _visitTaskRepository.Where(x =>
|
||||
(x.SubjectId == taskInfo.SubjectId && x.TaskState == TaskState.Effect
|
||||
&& x.IsAnalysisCreate == taskInfo.IsAnalysisCreate
|
||||
&& x.DoctorUserId == taskInfo.DoctorUserId
|
||||
&& x.ArmEnum == taskInfo.ArmEnum
|
||||
&& x.IsSelfAnalysis == taskInfo.IsSelfAnalysis
|
||||
&& x.VisitTaskNum < taskInfo.VisitTaskNum
|
||||
&& x.ArmEnum == taskInfo.ArmEnum
|
||||
|
@ -2105,7 +2157,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
.Where(x => x.IsAnalysisCreate == taskinfo.IsAnalysisCreate &&
|
||||
x.SubjectId == taskinfo.SubjectId &&
|
||||
x.ReadingCategory == taskinfo.ReadingCategory &&
|
||||
x.DoctorUserId == taskinfo.DoctorUserId &&
|
||||
x.ArmEnum == taskinfo.ArmEnum &&
|
||||
x.ArmEnum == taskinfo.ArmEnum &&
|
||||
x.TrialReadingCriterionId == taskinfo.TrialReadingCriterionId &&
|
||||
x.ReadingTaskState == ReadingTaskState.HaveSigned &&
|
||||
|
@ -3163,6 +3215,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
await VerifyTaskIsSign(visitTaskId);
|
||||
await _visitTaskRepository.UpdatePartialFromQueryAsync(visitTaskId, x => new VisitTask()
|
||||
{
|
||||
DoctorUserId = _userInfo.Id,
|
||||
ReadingTaskState = ReadingTaskState.HaveSigned,
|
||||
SignTime = DateTime.Now,
|
||||
});
|
||||
|
@ -3213,7 +3266,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
|
||||
await _visitTaskRepository.SaveChangesAsync();
|
||||
|
||||
await _trialEmailNoticeConfigService.BaseBusinessScenarioSendEmailAsync(visitTaskId);
|
||||
//await _trialEmailNoticeConfigService.BaseBusinessScenarioSendEmailAsync(visitTaskId);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3255,7 +3308,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
x.SubjectId == taskInfo.SubjectId &&
|
||||
x.VisitTaskNum < taskInfo.VisitTaskNum &&
|
||||
x.ArmEnum == taskInfo.ArmEnum &&
|
||||
x.DoctorUserId == taskInfo.DoctorUserId &&
|
||||
//x.DoctorUserId == taskInfo.DoctorUserId &&
|
||||
x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId &&
|
||||
x.ReadingTaskState == ReadingTaskState.HaveSigned &&
|
||||
x.TaskState == TaskState.Effect &&
|
||||
|
@ -3273,7 +3326,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
x.SubjectId == taskInfo.SubjectId &&
|
||||
x.VisitTaskNum <= taskInfo.VisitTaskNum &&
|
||||
x.ArmEnum == taskInfo.ArmEnum &&
|
||||
x.DoctorUserId == taskInfo.DoctorUserId &&
|
||||
//x.DoctorUserId == taskInfo.DoctorUserId &&
|
||||
x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId &&
|
||||
x.ReadingTaskState == ReadingTaskState.HaveSigned &&
|
||||
(x.TaskState == TaskState.Effect || x.TaskState == TaskState.Freeze) &&
|
||||
|
@ -3296,7 +3349,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
x.IsAnalysisCreate == taskInfo.IsAnalysisCreate &&
|
||||
x.ArmEnum == taskInfo.ArmEnum &&
|
||||
x.IsSelfAnalysis == taskInfo.IsSelfAnalysis &&
|
||||
x.DoctorUserId == taskInfo.DoctorUserId &&
|
||||
//x.DoctorUserId == taskInfo.DoctorUserId &&
|
||||
x.TaskState == TaskState.Effect && x.VisitTaskNum <= taskInfo.VisitTaskNum).Select(x => x.Id).ToListAsync();
|
||||
break;
|
||||
case ReadingCategory.Oncology:
|
||||
|
@ -3324,7 +3377,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
x.ArmEnum == taskInfo.ArmEnum &&
|
||||
x.IsSelfAnalysis == taskInfo.IsSelfAnalysis &&
|
||||
x.BlindSubjectCode == taskInfo.BlindSubjectCode &&
|
||||
x.DoctorUserId == taskInfo.DoctorUserId &&
|
||||
//x.DoctorUserId == taskInfo.DoctorUserId &&
|
||||
x.TaskState == TaskState.Effect && x.Id != taskInfo.Id).Select(x => x.Id).ToListAsync();
|
||||
|
||||
break;
|
||||
|
|
|
@ -160,7 +160,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
x.IsAnalysisCreate == globalOrVisitTaskInfo.IsAnalysisCreate &&
|
||||
x.ArmEnum == globalOrVisitTaskInfo.ArmEnum &&
|
||||
x.IsSelfAnalysis == globalOrVisitTaskInfo.IsSelfAnalysis &&
|
||||
x.DoctorUserId == globalOrVisitTaskInfo.DoctorUserId &&
|
||||
x.ArmEnum == globalOrVisitTaskInfo.ArmEnum &&
|
||||
x.TaskState == TaskState.Effect &&
|
||||
x.VisitTaskNum <= globalOrVisitTaskInfo.VisitTaskNum)
|
||||
.OrderBy(x => x.VisitTaskNum).Select(x => new GlobalVisitInfo()
|
||||
|
|
|
@ -3,12 +3,18 @@ using IRaCIS.Core.Application.Service.Reading.Dto;
|
|||
using IRaCIS.Core.Domain.Models;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Infra.EFCore.Common;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
using MassTransit;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MiniExcelLibs;
|
||||
using MiniSoftware;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using System.Data;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace IRaCIS.Core.Application.Service.ReadingCalculate
|
||||
|
@ -17,14 +23,16 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
|
|||
IRepository<VisitTask> _visitTaskRepository,
|
||||
IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository,
|
||||
ILogger<GeneralCalculateService> _logger,
|
||||
|
||||
IRepository<ReadingTableQuestionTrial> _readingTableQuestionTrialRepository,
|
||||
IRepository<ReadingTableAnswerRowInfo> _readingTableAnswerRowInfoRepository,
|
||||
IRepository<ReadingQuestionTrial> _readingQuestionTrialRepository,
|
||||
IRepository<SubjectVisit> _subjectVisitRepository,
|
||||
IOptionsMonitor<ObjectStoreServiceOptions> _options,
|
||||
IRepository<TumorAssessment_RECIST1Point1> _tumorAssessmentRepository,
|
||||
IRepository<ReadingTaskQuestionAnswer> _readingTaskQuestionAnswerRepository,
|
||||
IRepository<InspectionFile> _inspectionFileRepository,
|
||||
IOSSService oSSService, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, IGeneralCalculateService
|
||||
IOSSService _oSSService, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, IGeneralCalculateService
|
||||
{
|
||||
|
||||
|
||||
|
@ -71,7 +79,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
|
|||
|
||||
try
|
||||
{
|
||||
var ossRelativePath = await oSSService.UploadToOSSAsync(fileStream, "InspectionUpload/"+ pathCode, file.FileName);
|
||||
var ossRelativePath = await _oSSService.UploadToOSSAsync(fileStream, "InspectionUpload/"+ pathCode, file.FileName);
|
||||
await _inspectionFileRepository.AddAsync(new InspectionFile() { FileName = file.FileName, RelativePath = ossRelativePath, TrialId = trialId });
|
||||
}
|
||||
catch (Exception)
|
||||
|
@ -432,7 +440,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
|
|||
.Where(x => (x.SubjectId == visitTaskInfo.SubjectId
|
||||
&& (x.TaskState == TaskState.Effect || x.TaskState == TaskState.Freeze)
|
||||
&& x.IsAnalysisCreate == visitTaskInfo.IsAnalysisCreate
|
||||
&& x.DoctorUserId == visitTaskInfo.DoctorUserId
|
||||
&& x.ArmEnum == visitTaskInfo.ArmEnum
|
||||
&& x.IsSelfAnalysis == visitTaskInfo.IsSelfAnalysis
|
||||
&& x.VisitTaskNum <= visitTaskInfo.VisitTaskNum
|
||||
&& x.ArmEnum == visitTaskInfo.ArmEnum
|
||||
|
@ -482,5 +490,442 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
|
|||
});
|
||||
return taskInfoList;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 空转为横线
|
||||
/// </summary>
|
||||
/// <param name="myDictionary"></param>
|
||||
/// <returns></returns>
|
||||
public Dictionary<string, object> StringEmptyTurnedLine(Dictionary<string, object> myDictionary)
|
||||
{
|
||||
foreach (var item in myDictionary)
|
||||
{
|
||||
if (item.Value == null)
|
||||
{
|
||||
myDictionary[item.Key] = "-";
|
||||
}
|
||||
else if (item.Value.GetType() == typeof(string))
|
||||
{
|
||||
if (item.Value.ToString() == string.Empty || item.Value == null)
|
||||
{
|
||||
myDictionary[item.Key] = "-";
|
||||
};
|
||||
|
||||
}
|
||||
else if (item.Value.GetType() == typeof(List<Dictionary<string, object>>))
|
||||
{
|
||||
var value = item.Value;
|
||||
|
||||
foreach (var column in value as List<Dictionary<string, object>>)
|
||||
{
|
||||
foreach (var item2 in column)
|
||||
{
|
||||
if (item2.Value.ToString() == string.Empty || item.Value == null)
|
||||
{
|
||||
column[item2.Key] = "-";
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
myDictionary[item.Key] = value;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return myDictionary;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取word图片
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <param name="savePath"></param>
|
||||
/// <param name="width"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<MiniWordPicture> GetWordPicture(string url, string savePath, int width)
|
||||
{
|
||||
var resultUrl = await this.FileDownSave(url, savePath);
|
||||
|
||||
int picWidth = 0;
|
||||
int picHeight = 0;
|
||||
|
||||
|
||||
|
||||
using (var bitmap = Image<Rgba32>.Load(resultUrl))
|
||||
{
|
||||
// 获取图片的宽度和高度
|
||||
picWidth = bitmap.Width;
|
||||
picHeight = bitmap.Height;
|
||||
}
|
||||
|
||||
var height = width * picHeight / picWidth;
|
||||
|
||||
return new MiniWordPicture()
|
||||
{
|
||||
Path = resultUrl,
|
||||
Height = height,
|
||||
Width = width
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取word图片
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <param name="savePath"></param>
|
||||
/// <param name="width"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<MiniWordPicture> GetWordPicture(string url, string savePath, int width, int height)
|
||||
{
|
||||
var resultUrl = await this.FileDownSave(url, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"wwwroot/ReadReoprtTemplate/downLoad"));
|
||||
|
||||
return new MiniWordPicture()
|
||||
{
|
||||
Path = resultUrl,
|
||||
Height = height,
|
||||
Width = width
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 最大宽高
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <param name="savePath"></param>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<MiniWordPicture> GetWordPictureMaxWL(string url, string savePath, int width, int height)
|
||||
{
|
||||
var resultUrl = await this.FileDownSave(url, savePath);
|
||||
|
||||
|
||||
int picWidth = 0;
|
||||
int picHeight = 0;
|
||||
using (var bitmap = Image<Rgba32>.Load(resultUrl))
|
||||
{
|
||||
// 获取图片的宽度和高度
|
||||
picWidth = bitmap.Width;
|
||||
picHeight = bitmap.Height;
|
||||
}
|
||||
|
||||
if (picWidth / picHeight > width / height)
|
||||
{
|
||||
height = width * picHeight / picWidth;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
width = height * picWidth / picHeight;
|
||||
|
||||
}
|
||||
|
||||
|
||||
return new MiniWordPicture()
|
||||
{
|
||||
Path = resultUrl,
|
||||
Height = height,
|
||||
Width = width
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取任务问题答案
|
||||
/// </summary>
|
||||
/// <param name="answerList">问题答案</param>
|
||||
/// <param name="dictionList">字典数据</param>
|
||||
/// <param name="unitDictionary">单位字典</param>
|
||||
/// <param name="taskId">任务Id</param>
|
||||
/// <param name="questionType">任务类型</param>
|
||||
/// <returns></returns>
|
||||
public string GetTaskanswer(List<ReadingTaskQuestionAnswer>? answerList, List<Dictionary>? dictionList, List<Dictionary>? unitDictionary, Guid taskId, QuestionType questionType)
|
||||
{
|
||||
var answerData = answerList.FirstOrDefault(x => x.VisitTaskId == taskId && x.ReadingQuestionTrial.QuestionType == questionType);
|
||||
if (answerData == null || answerData.Answer == string.Empty)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
var answer = string.Empty;
|
||||
if (answerData.ReadingQuestionTrial.QuestionGenre == TableQuestionType.Dictionary)
|
||||
{
|
||||
answer = dictionList.Where(x => x.Code == answerData.ReadingQuestionTrial.DictionaryCode).SelectMany(x => x.ChildList).Where(x => x.Code == answerData.Answer).Select(x => x.ValueCN).FirstIsNullReturnEmpty();
|
||||
}
|
||||
else
|
||||
{
|
||||
answer = answerData.Answer;
|
||||
}
|
||||
if (answer != "NA" && answerData.ReadingQuestionTrial.Unit != null && answerData.ReadingQuestionTrial.Unit != ValueUnit.none)
|
||||
{
|
||||
answer += " " + unitDictionary.SelectMany(x => x.ChildList).Where(x => x.Code == ((int)answerData.ReadingQuestionTrial.Unit).ToString()).Select(x => x.ValueCN).FirstIsNullReturnEmpty();
|
||||
}
|
||||
if (answer != "NA" && answerData.ReadingQuestionTrial.ValueType == ValueOfType.Percentage)
|
||||
{
|
||||
answer += " %";
|
||||
|
||||
}
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
|
||||
public void SetPropertyDynamically(object targetObj, string targetPropName, object sourceObj, string prefix)
|
||||
{
|
||||
// 1. 解析目标属性名(如"CheckInfoStr")
|
||||
string basePropName = targetPropName.Replace(prefix, "");
|
||||
|
||||
// 2. 获取源对象路径(如"VisitOne.CheckInfoStr")
|
||||
string sourcePath = $"Visit{prefix}.{basePropName}";
|
||||
object sourceValue = GetNestedPropertyValue(sourceObj, sourcePath);
|
||||
|
||||
// 3. 赋值给目标属性
|
||||
PropertyInfo targetProp = targetObj.GetType().GetProperty(prefix+targetPropName);
|
||||
if (targetProp != null && sourceValue != null)
|
||||
{
|
||||
targetProp.SetValue(targetObj, sourceValue);
|
||||
}
|
||||
}
|
||||
|
||||
public object GetNestedPropertyValue(object obj, string path)
|
||||
{
|
||||
foreach (string part in path.Split('.'))
|
||||
{
|
||||
if (obj == null) return null;
|
||||
PropertyInfo prop = obj.GetType().GetProperty(part);
|
||||
if (prop == null) return null;
|
||||
obj = prop.GetValue(obj);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取报告No
|
||||
/// </summary>
|
||||
/// <param name="visitTaskInfo"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<string> GetReportExportNo(VisitTask visitTaskInfo)
|
||||
{
|
||||
if (visitTaskInfo.ReportExportDate != null && visitTaskInfo.ReportExportNum != null)
|
||||
{
|
||||
return visitTaskInfo.ReportExportDate.Value.ToString("yyyyMMdd") + visitTaskInfo.ReportExportNum.ToString().PadLeft(4, '0');
|
||||
}
|
||||
else
|
||||
{
|
||||
DateTime today = DateTime.Today;
|
||||
|
||||
|
||||
var reportExportNum = await _visitTaskRepository.Where(x => x.TrialId == visitTaskInfo.TrialId && x.ReportExportDate != null && x.ReportExportDate.Value.Date == today).MaxAsync(x => x.ReportExportNum);
|
||||
reportExportNum = reportExportNum == null ? 0 : reportExportNum;
|
||||
await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => x.Id == visitTaskInfo.Id, x => new VisitTask()
|
||||
{
|
||||
|
||||
ReportExportDate = today,
|
||||
ReportExportNum = reportExportNum + 1
|
||||
});
|
||||
|
||||
return today.ToString("yyyyMMdd") + (reportExportNum + 1).ToString().PadLeft(4, '0');
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取并复制文件流
|
||||
/// </summary>
|
||||
/// <param name="outputFilePath"></param>
|
||||
/// <returns></returns>
|
||||
public Stream ReadAndReturnStream(string outputFilePath)
|
||||
{
|
||||
byte[] data;
|
||||
|
||||
using (Stream stream = new FileStream(outputFilePath, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
// 从流中读取数据保存到内存中
|
||||
using (MemoryStream memoryStream = new MemoryStream())
|
||||
{
|
||||
stream.CopyTo(memoryStream);
|
||||
data = memoryStream.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
// 返回内存中的数据作为新的流
|
||||
return new MemoryStream(data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载并保存
|
||||
/// </summary>
|
||||
/// <param name="url">网络路径</param>
|
||||
/// <param name="savePath">保存本地的文件夹</param>
|
||||
/// <returns><placeholder>A <see cref="Task"/>
|
||||
public async Task<string> FileDownSave(string url, string savePath)
|
||||
{
|
||||
|
||||
#region 新
|
||||
try
|
||||
{
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(url))
|
||||
{
|
||||
string[] strArry = url.Split('/');
|
||||
savePath = savePath + "/" + strArry[strArry.Length - 1];
|
||||
}
|
||||
await _oSSService.DownLoadFromOSSAsync(url, savePath);
|
||||
|
||||
return savePath;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
throw new BusinessValidationFailedException(_localizer["ReadingCalculate_ImageNotExist"]);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region 之前
|
||||
// 之前需要有绝对路径
|
||||
//try
|
||||
//{
|
||||
// HttpClient httpClient = new HttpClient();
|
||||
// if (!string.IsNullOrWhiteSpace(url))
|
||||
// {
|
||||
// string[] strArry = url.Split('/');
|
||||
// savePath = savePath + "/" + strArry[strArry.Length - 1];
|
||||
// }
|
||||
|
||||
// var t = httpClient.GetByteArrayAsync(url);
|
||||
// t.Wait();
|
||||
// Stream responseStream = new MemoryStream(t.Result);
|
||||
// Stream stream = new FileStream(savePath, FileMode.Create);
|
||||
// byte[] bArr = new byte[1024];
|
||||
// int size = responseStream.Read(bArr, 0, bArr.Length);
|
||||
// while (size > 0)
|
||||
// {
|
||||
// stream.Write(bArr, 0, size);
|
||||
// size = responseStream.Read(bArr, 0, bArr.Length);
|
||||
// }
|
||||
|
||||
// stream.Close();
|
||||
// responseStream.Close();
|
||||
|
||||
// return savePath;
|
||||
//}
|
||||
//catch (Exception)
|
||||
//{
|
||||
|
||||
// throw new BusinessValidationFailedException(_localizer["ReadingCalculate_ImageNotExist"]);
|
||||
//}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取任务表格问题答案
|
||||
/// </summary>
|
||||
/// <param name="tableAnswerList">表格答案</param>
|
||||
/// <param name="dictionList">字典</param>
|
||||
/// <param name="unitDictionary">单位字典</param>
|
||||
/// <param name="taskId">任务Id</param>
|
||||
/// <param name="lesionType">病灶类型</param>
|
||||
/// <param name="questionMark">问题标识</param>
|
||||
/// <param name="rowIndex">索引</param>
|
||||
/// <returns></returns>
|
||||
public string GetTaskTableAnswer(List<ReadingTableQuestionAnswer>? tableAnswerList, List<Dictionary>? dictionList, List<Dictionary>? unitDictionary, Guid taskId, LesionType lesionType, QuestionMark questionMark, decimal rowIndex,bool AutoUnit=true)
|
||||
{
|
||||
var answerData = tableAnswerList.FirstOrDefault(x => x.VisitTaskId == taskId && x.ReadingQuestionTrial.LesionType == lesionType && x.ReadingTableQuestionTrial.QuestionMark == questionMark && x.RowIndex == rowIndex);
|
||||
|
||||
if (answerData == null || answerData.Answer == string.Empty)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
var answer = string.Empty;
|
||||
if (answerData.ReadingTableQuestionTrial.TableQuestionType == TableQuestionType.Dictionary)
|
||||
{
|
||||
answer = dictionList.Where(x => x.Code == answerData.ReadingTableQuestionTrial.DictionaryCode).SelectMany(x => x.ChildList).Where(x => x.Code == answerData.Answer).Select(x => x.ValueCN).FirstIsNullReturnEmpty();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
answer = answerData.Answer;
|
||||
|
||||
}
|
||||
if (AutoUnit)
|
||||
{
|
||||
if (answer != "NA" && answerData.ReadingTableQuestionTrial.Unit != null && answerData.ReadingTableQuestionTrial.Unit != ValueUnit.none)
|
||||
{
|
||||
answer += " " + unitDictionary.SelectMany(x => x.ChildList).Where(x => x.Code == ((int)answerData.ReadingTableQuestionTrial.Unit).ToString()).Select(x => x.ValueCN).FirstIsNullReturnEmpty();
|
||||
}
|
||||
|
||||
if (answer != "NA" && answerData.ReadingTableQuestionTrial.ValueType == ValueOfType.Percentage)
|
||||
{
|
||||
answer += " %";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取病灶的图片 rowinfoList要带question的信息
|
||||
/// </summary>
|
||||
/// <param name="rowinfoList"></param>
|
||||
/// <param name="lesionType"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<Dictionary<string, object>>> GetLesionPic(List<ReadingTableAnswerRowInfo> rowinfoList, LesionType lesionType, Guid DownLoadGuid)
|
||||
{
|
||||
var lesionRowinfo = rowinfoList.Where(x => x.PicturePath != string.Empty && x.ReadingQuestionTrial.LesionType == lesionType).OrderBy(x => x.VisitTask.VisitTaskNum).OrderBy(x => x.RowIndex).ToList();
|
||||
List<Dictionary<string, object>> lesionImage = new List<Dictionary<string, object>>();
|
||||
|
||||
|
||||
var lesionCount = lesionRowinfo.Select(x => x.VisitTask.VisitTaskNum).Distinct().OrderBy(x => x).ToList();
|
||||
|
||||
int picNum = 0;
|
||||
|
||||
foreach (var num in lesionCount)
|
||||
{
|
||||
var picRowinfo = lesionRowinfo.Where(x => x.VisitTask.VisitTaskNum == num).OrderBy(x => x.RowIndex).ToList();
|
||||
var picCount = picRowinfo.Count();
|
||||
for (int i = 0; i < Math.Ceiling((double)picCount / 2); i++)
|
||||
{
|
||||
lesionImage.Add(new Dictionary<string, object>()
|
||||
{
|
||||
{ "ImageOneMark",getPicNum(true)+ picRowinfo[2*i].VisitTask.TaskName+" "+picRowinfo[2*i].RowMark},
|
||||
{ "ImageOneUrl" ,await GetWordPictureMaxWL(picRowinfo[2*i].PicturePath ,System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $@"wwwroot/ReadReoprtTemplate/downLoad/{DownLoadGuid}"),290,390) },
|
||||
{ "ImageTwoMark",getPicNum(picCount>2*i+1) + (picCount<=2*i+1?string.Empty:picRowinfo[2*i+1].VisitTask.TaskName+" "+picRowinfo[2*i+1].RowMark) },
|
||||
{ "ImageTwoUrl", picCount<=2*i+1?string.Empty:await GetWordPictureMaxWL(picRowinfo[2*i+1].PicturePath ,System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $@"wwwroot/ReadReoprtTemplate/downLoad/{DownLoadGuid}"),290, 390) },
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
string getPicNum(bool isHavePic)
|
||||
{
|
||||
if (isHavePic)
|
||||
{
|
||||
picNum += 1;
|
||||
|
||||
return $"图{picNum} ";
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
return lesionImage;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue