Compare commits

...

66 Commits

Author SHA1 Message Date
he 30e71b11e8 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is failing
2024-08-21 17:15:01 +08:00
he 2de504005e 一致性分析完全随机自动生效 2024-08-21 17:15:01 +08:00
hang 6a41c33d34 pacs 验证写反了
continuous-integration/drone/push Build is passing
2024-08-21 14:51:57 +08:00
hang 3b48dfae31 项目缓存状态逻辑,全局修改
continuous-integration/drone/push Build is passing
2024-08-21 14:37:33 +08:00
hang c7fd9a6bcb Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-08-21 13:38:21 +08:00
hang 169ef180ff 修改pacs 反馈提示+中心调研bug 2024-08-21 13:38:20 +08:00
he f33d3d474b Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-08-21 13:26:46 +08:00
he 63e1331bd1 验证签名信息 2024-08-21 13:26:43 +08:00
hang 418cc9b4b9 修改pacs 验证
continuous-integration/drone/push Build is passing
2024-08-21 12:24:30 +08:00
hang 71fb1eac6b Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-08-21 12:18:36 +08:00
hang 0804a05925 准备新缓存临时工作 2024-08-21 12:18:36 +08:00
hang de6098013d 导表签名bug
continuous-integration/drone/push Build is passing
2024-08-21 10:46:33 +08:00
hang f8cd361415 添加FusionCache
continuous-integration/drone/push Build is passing
2024-08-21 00:06:36 +08:00
hang 0b1a640c3e Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-08-20 17:58:24 +08:00
hang aa9df5838c 修改添加pacs 影像 2024-08-20 17:58:24 +08:00
he 2edacc9ff5 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-08-20 16:03:18 +08:00
he a9a0a9d307 修改 2024-08-20 16:03:17 +08:00
hang 1937804e47 修改scp bug
continuous-integration/drone/push Build is passing
2024-08-20 15:08:03 +08:00
hang 8e8b55fa46 修改分页列表bug
continuous-integration/drone/push Build is passing
2024-08-20 14:58:35 +08:00
hang 3096671595 数组给默认参数
continuous-integration/drone/push Build is passing
2024-08-20 14:09:01 +08:00
hang a6102490c8 修改项目导表-指定项目导出
continuous-integration/drone/push Build is passing
2024-08-20 14:03:42 +08:00
hang 9e1cc1521f 修改分页参数
continuous-integration/drone/push Build is passing
2024-08-20 13:59:52 +08:00
he a579c26ada Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-08-20 13:50:04 +08:00
he 754da2c7fc 代码修改 2024-08-20 13:50:03 +08:00
hang 995bdee1f6 领域事件添加到测试环境-测试
continuous-integration/drone/push Build is passing
2024-08-20 13:14:06 +08:00
hang a70f661e86 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-08-20 11:17:50 +08:00
hang 8312bfb78b 修改scp 配置文件 2024-08-20 11:17:50 +08:00
he 7194796841 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-08-20 10:56:00 +08:00
he c6918cca46 代码修改 2024-08-20 10:56:00 +08:00
hang be7b38c6ce Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-08-20 10:42:16 +08:00
hang a7ebd50536 修改引用包 2024-08-20 10:42:16 +08:00
he 05f9b81e04 测试发布
continuous-integration/drone/push Build is failing
2024-08-20 10:37:58 +08:00
he 1f9eb9e36b Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is failing
2024-08-20 10:35:39 +08:00
he af46eb2d65 修改 2024-08-20 10:35:37 +08:00
hang d1e54629e7 x
continuous-integration/drone/push Build is failing
2024-08-20 10:25:45 +08:00
hang 78dbe23d0e 修改实体
continuous-integration/drone/push Build is running
2024-08-20 10:25:06 +08:00
hang 4bf93d10b0 暂时屏蔽事件分发
continuous-integration/drone/push Build is failing
2024-08-20 09:39:44 +08:00
hang 00827e9975 增加领域事件定义,增加MassTransit 发布事件
continuous-integration/drone/push Build is failing
2024-08-19 23:32:53 +08:00
hang 021b32587a 修改模板
continuous-integration/drone/push Build is passing
2024-08-19 21:18:28 +08:00
hang 5ffe1675db Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-08-19 17:49:11 +08:00
hang d34eca2cb8 增加 MassTransit 移除 MediatR 2024-08-19 17:49:08 +08:00
hang 12ac7af11e Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-08-19 17:36:45 +08:00
hang a19eb2abca 修改uat scp 数据库配置 2024-08-19 17:36:33 +08:00
hang 4c9a8aadab Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-08-19 16:00:10 +08:00
hang 034058999d 清理后端医生下载接口 2024-08-19 16:00:08 +08:00
he 34ea39e764 修改
continuous-integration/drone/push Build is passing
2024-08-19 15:33:52 +08:00
he 7caf00bd75 修改
continuous-integration/drone/push Build is passing
2024-08-19 15:27:51 +08:00
he aabe604e18 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-08-19 15:22:20 +08:00
he f2bc281e2b 修改 2024-08-19 15:22:19 +08:00
hang 4187a568f8 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-08-19 15:14:38 +08:00
hang 1611554c00 生成全局任务,没有设置VisitTaskNum 2024-08-19 15:14:36 +08:00
he 60fc8f9bce 修改
continuous-integration/drone/push Build is running
2024-08-19 15:14:23 +08:00
he 48eb20fa66 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-08-19 14:22:19 +08:00
he 9e7bc09f84 修改 2024-08-19 14:22:18 +08:00
hang ec9e35180b crc 上传控制pacs
continuous-integration/drone/push Build is passing
2024-08-19 14:03:16 +08:00
hang c757212c07 修改上传配置文件 2024-08-19 14:03:11 +08:00
hang 8415dd2be1 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8 2024-08-19 13:56:02 +08:00
he 17d734ba11 修改
continuous-integration/drone/push Build is passing
2024-08-19 13:24:41 +08:00
he 476387b468 修改
continuous-integration/drone/push Build is passing
2024-08-19 13:19:54 +08:00
he 3a2cb138ab 修改
continuous-integration/drone/push Build is passing
2024-08-19 13:12:04 +08:00
he fa763e6341 修改
continuous-integration/drone/push Build is passing
2024-08-19 11:32:41 +08:00
he c988ca0bca Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-08-19 11:28:05 +08:00
he c257dd4171 字典修改 2024-08-19 11:28:02 +08:00
hang ff026f45fc 优化分页排序和生成模板
continuous-integration/drone/push Build is passing
2024-08-17 20:33:21 +08:00
hang cd2166f11b 数据记录审计方法调整
continuous-integration/drone/push Build is passing
2024-08-17 16:06:35 +08:00
hang 33cfacec84 发布文件 2024-08-16 16:19:58 +08:00
75 changed files with 1383 additions and 986 deletions
+4 -1
View File
@@ -4,6 +4,7 @@ using IRaCIS.Core.Infra.EFCore;
using Medallion.Threading; using Medallion.Threading;
using Medallion.Threading.SqlServer; using Medallion.Threading.SqlServer;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
@@ -15,11 +16,12 @@ namespace IRaCIS.Core.SCP
{ {
services.AddHttpContextAccessor(); services.AddHttpContextAccessor();
services.AddScoped<IUserInfo, UserInfo>(); services.AddScoped<IUserInfo, UserInfo>();
services.AddScoped<ISaveChangesInterceptor, AuditEntityInterceptor>();
//这个注入没有成功--注入是没问题的,构造函数也只是支持参数就好,错在注入的地方不能写DbContext //这个注入没有成功--注入是没问题的,构造函数也只是支持参数就好,错在注入的地方不能写DbContext
//Web程序中通过重用池中DbContext实例可提高高并发场景下的吞吐量, 这在概念上类似于ADO.NET Provider原生的连接池操作方式,具有节省DbContext实例化成本的优点 //Web程序中通过重用池中DbContext实例可提高高并发场景下的吞吐量, 这在概念上类似于ADO.NET Provider原生的连接池操作方式,具有节省DbContext实例化成本的优点
services.AddDbContextPool<IRaCISDBContext>(options => services.AddDbContext<IRaCISDBContext>((sp, options) =>
{ {
// 在控制台 // 在控制台
//public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); }); //public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); });
@@ -35,6 +37,7 @@ namespace IRaCIS.Core.SCP
options.EnableSensitiveDataLogging(); options.EnableSensitiveDataLogging();
options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor()); options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor());
options.AddInterceptors(sp.GetServices<ISaveChangesInterceptor>());
options.UseProjectables(); options.UseProjectables();
-1
View File
@@ -21,7 +21,6 @@
<PackageReference Include="My.Extensions.Localization.Json" Version="3.3.0"> <PackageReference Include="My.Extensions.Localization.Json" Version="3.3.0">
<TreatAsUsed>true</TreatAsUsed> <TreatAsUsed>true</TreatAsUsed>
</PackageReference> </PackageReference>
<PackageReference Include="NewId" Version="4.0.1" />
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" /> <PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" />
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.0.3" /> <PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.0.3" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="8.0.0" /> <PackageReference Include="Serilog.Extensions.Hosting" Version="8.0.0" />
-1
View File
@@ -73,7 +73,6 @@ builder.Services.AddJsonLocalization(options => options.ResourcesPath = "Resourc
// 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim() // 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim()
builder.Services.AddControllers(options => builder.Services.AddControllers(options =>
{ {
//options.Filters.Add<LogActionFilter>();
options.Filters.Add<ModelActionFilter>(); options.Filters.Add<ModelActionFilter>();
options.Filters.Add<ProjectExceptionFilter>(); options.Filters.Add<ProjectExceptionFilter>();
options.Filters.Add<UnitOfWorkFilter>(); options.Filters.Add<UnitOfWorkFilter>();
@@ -10,5 +10,16 @@
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Test_IRC_SCP" "ASPNETCORE_ENVIRONMENT": "Test_IRC_SCP"
} }
},
"Uat_IRC_SCP": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:6200",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Uat_IRC_SCP"
}
} }
}
} }
+2 -4
View File
@@ -31,10 +31,8 @@
}, },
"ConnectionStrings": { "ConnectionStrings": {
//"RemoteNew": "Server=47.117.165.18,1434;Database=Prod_Study;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true", "RemoteNew": "Server=us-prod-mssql-service,1433;Database=US_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
//"Hangfire": "Server=47.117.165.18,1434;Database=Prod_Study_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true", "Hangfire": "Server=us-prod-mssql-service,1433;Database=US_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
"RemoteNew": "Server=prod_mssql_standard,1433;Database=Prod_Study;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true",
"Hangfire": "Server=prod_mssql_standard,1433;Database=Prod_Study_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true"
}, },
"BasicSystemConfig": { "BasicSystemConfig": {
+3 -13
View File
@@ -7,7 +7,7 @@
} }
}, },
"ObjectStoreService": { "ObjectStoreService": {
"ObjectStoreUse": "MinIO", "ObjectStoreUse": "AliyunOSS",
"AliyunOSS": { "AliyunOSS": {
"regionId": "cn-shanghai", "regionId": "cn-shanghai",
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com", "internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
@@ -20,16 +20,6 @@
"region": "oss-cn-shanghai" "region": "oss-cn-shanghai"
}, },
"MinIO": {
"endPoint": "47.117.164.182",
"port": "9001",
"useSSL": false,
"accessKey": "b9Ul0e98xPzt6PwRXA1Q",
"secretKey": "DzMaU2L4OXl90uytwOmDXF2encN0Jf4Nxu2XkYqQ",
"bucketName": "hir-uat",
"viewEndpoint": "http://hir.uat.extimaging.com/oss/hir-uat"
},
"AWS": { "AWS": {
"endPoint": "s3.us-east-1.amazonaws.com", "endPoint": "s3.us-east-1.amazonaws.com",
"useSSL": false, "useSSL": false,
@@ -40,8 +30,8 @@
} }
}, },
"ConnectionStrings": { "ConnectionStrings": {
"RemoteNew": "Server=47.117.164.182,1434;Database=Uat_HIR;User ID=sa;Password=xc@123456;TrustServerCertificate=true", "RemoteNew": "Server=47.117.164.182,1434;Database=Uat_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=47.117.164.182,1434;Database=Uat_HIR_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true" "Hangfire": "Server=47.117.164.182,1434;Database=Uat_IRC.Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
}, },
"BasicSystemConfig": { "BasicSystemConfig": {
@@ -10,8 +10,7 @@ using IRaCIS.Core.Application.Contracts.Dicom;
using IRaCIS.Core.Application.Contracts.Dicom.DTO; using IRaCIS.Core.Application.Contracts.Dicom.DTO;
using IRaCIS.Core.Application.Filter; using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.MediatR.CommandAndQueries; using IRaCIS.Core.Application.MassTransit.Command;
using IRaCIS.Core.Application.MediatR.Handlers;
using IRaCIS.Core.Application.Service; using IRaCIS.Core.Application.Service;
using IRaCIS.Core.Application.Service.ImageAndDoc; using IRaCIS.Core.Application.Service.ImageAndDoc;
using IRaCIS.Core.Application.Service.Reading.Dto; using IRaCIS.Core.Application.Service.Reading.Dto;
@@ -21,7 +20,7 @@ using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Infrastructure.Extention; using IRaCIS.Core.Infrastructure.Extention;
using MassTransit; using MassTransit;
using MediatR; using MassTransit.Mediator;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors.Infrastructure; using Microsoft.AspNetCore.Cors.Infrastructure;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
@@ -232,9 +231,12 @@ namespace IRaCIS.Core.API.Controllers
{ {
public IMapper _mapper { get; set; } public IMapper _mapper { get; set; }
public IUserInfo _userInfo { get; set; } public IUserInfo _userInfo { get; set; }
private readonly IMediator _mediator; private readonly IMediator _mediator;
public IStringLocalizer _localizer { get; set; } public IStringLocalizer _localizer { get; set; }
@@ -266,11 +268,6 @@ namespace IRaCIS.Core.API.Controllers
[FromServices] IRepository<StudyMonitor> _studyMonitorRepository) [FromServices] IRepository<StudyMonitor> _studyMonitorRepository)
{ {
if (_provider.Get<List<SystemAnonymization>>(StaticData.Anonymize.Anonymize_AddFixedFiled).Value == null)
{
await _mediator.Send(new AnonymizeCacheRequest());
}
var savedInfo = _studyService.GetSaveToDicomInfo(preArchiveStudyCommand.SubjectVisitId); var savedInfo = _studyService.GetSaveToDicomInfo(preArchiveStudyCommand.SubjectVisitId);
var studyMonitor = new StudyMonitor() var studyMonitor = new StudyMonitor()
@@ -743,11 +740,16 @@ namespace IRaCIS.Core.API.Controllers
//---请保证上传数据符合模板文件中的样式,且存在有效数据。 //---请保证上传数据符合模板文件中的样式,且存在有效数据。
return ResponseOutput.NotOk(_localizer["UploadDownLoad_InvalidData"]); return ResponseOutput.NotOk(_localizer["UploadDownLoad_InvalidData"]);
} }
} }
await _mediator.Send(new ConsistencyVerificationRequest() { ETCList = etcCheckList, TrialId = trialId });
// 适合获取结果的
//var client = _mediator.CreateRequestClient<ConsistenCheckCommand>();
//await client.GetResponse<ConsistenCheckResult>(new ConsistenCheckCommand() { ETCList = etcCheckList, TrialId = trialId });
//不获取结果,不用定义返回类型
await _mediator.Send(new ConsistenCheckCommand() { ETCList = etcCheckList, TrialId = trialId });
return ResponseOutput.Ok(); return ResponseOutput.Ok();
@@ -889,89 +891,6 @@ namespace IRaCIS.Core.API.Controllers
#region
/// <summary>
/// 下载多个医生的所有附件
/// </summary>
/// <param name="doctorIds"></param>
/// <returns></returns>
[Obsolete]
[HttpPost, Route("file/downloadDoctorAttachments")]
public async Task<IResponseOutput<UploadFileInfoDTO>> DownloadAttachment(Guid[] doctorIds)
{
var path = await _fileService.CreateDoctorsAllAttachmentZip(doctorIds);
return ResponseOutput.Ok(new UploadFileInfoDTO
{
FilePath = path,
FullFilePath = path + "?access_token=" + HttpContext.Request.Headers["Authorization"].ToString().Substring(7)
});
}
/// <summary>
/// 下载指定医生的指定附件
/// </summary>
/// <param name="doctorId">医生Id</param>
/// <param name="attachmentIds">要下载的附件Id</param>
/// <returns></returns>
[HttpPost, Route("file/downloadByAttachmentId/{doctorId}")]
[Obsolete]
public async Task<IResponseOutput<UploadFileInfoDTO>> DownloadAttachmentById(Guid doctorId, Guid[] attachmentIds)
{
var path = await _fileService.CreateZipPackageByAttachment(doctorId, attachmentIds);
return ResponseOutput.Ok(new UploadFileInfoDTO
{
FilePath = await _fileService.CreateZipPackageByAttachment(doctorId, attachmentIds),
FullFilePath = path + "?access_token=" + HttpContext.Request.Headers["Authorization"].ToString().Substring(7)
});
}
/// <summary>
/// 下载医生官方简历 首页 区分 中文和英文
/// </summary>
/// <param name="language"></param>
/// <param name="doctorIds"></param>
/// <returns></returns>
[HttpPost, Route("file/downloadOfficialCV/{language}")]
[Obsolete]
public async Task<IResponseOutput<UploadFileInfoDTO>> DownloadOfficialResume(int language, Guid[] doctorIds)
{
var path = await _fileService.CreateDoctorsAllAttachmentZip(doctorIds);
return ResponseOutput.Ok(new UploadFileInfoDTO
{
FilePath = await _fileService.CreateOfficialResumeZip(language, doctorIds),
FullFilePath = path + "?access_token=" + HttpContext.Request.Headers["Authorization"].ToString().Substring(7)
});
}
/// <summary>
/// 入组 项目下载简历
/// </summary>
/// <param name="language"></param>
/// <param name="trialId"></param>
/// <param name="doctorIdArray"></param>
/// <returns></returns>
[HttpPost, Route("enroll/downloadResume/{trialId:guid}/{language}")]
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
[AllowAnonymous]
[Obsolete]
public async Task<IResponseOutput<string>> DownloadResume(int language, Guid trialId, Guid[] doctorIdArray)
{
var zipPath = await _fileService.CreateOfficialResumeZip(language, doctorIdArray);
return ResponseOutput.Ok(zipPath);
}
#endregion
} }
#endregion #endregion
-32
View File
@@ -326,38 +326,6 @@
<param name="_attachmentrepository"></param> <param name="_attachmentrepository"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.API.Controllers.FileController.DownloadAttachment(System.Guid[])">
<summary>
下载多个医生的所有附件
</summary>
<param name="doctorIds"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.API.Controllers.FileController.DownloadAttachmentById(System.Guid,System.Guid[])">
<summary>
下载指定医生的指定附件
</summary>
<param name="doctorId">医生Id</param>
<param name="attachmentIds">要下载的附件Id</param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.API.Controllers.FileController.DownloadOfficialResume(System.Int32,System.Guid[])">
<summary>
下载医生官方简历 首页 区分 中文和英文
</summary>
<param name="language"></param>
<param name="doctorIds"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.API.Controllers.FileController.DownloadResume(System.Int32,System.Guid,System.Guid[])">
<summary>
入组 项目下载简历
</summary>
<param name="language"></param>
<param name="trialId"></param>
<param name="doctorIdArray"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.API.Controllers.UploadDownLoadController.DownloadCommonFile(System.String,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.CommonDocument})"> <member name="M:IRaCIS.Core.API.Controllers.UploadDownLoadController.DownloadCommonFile(System.String,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.CommonDocument})">
<summary> 通用文件下载 </summary> <summary> 通用文件下载 </summary>
</member> </member>
+93 -15
View File
@@ -4,8 +4,6 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Serilog; using Serilog;
using MediatR;
using IRaCIS.Core.Application.MediatR.Handlers;
using System.Threading.Tasks; using System.Threading.Tasks;
using MassTransit; using MassTransit;
using MassTransit.NewIdProviders; using MassTransit.NewIdProviders;
@@ -29,6 +27,12 @@ using IRaCIS.Core.Application.Service.ImageAndDoc;
using IP2Region.Net.Abstractions; using IP2Region.Net.Abstractions;
using IP2Region.Net.XDB; using IP2Region.Net.XDB;
using IRaCIS.Core.Application.BusinessFilter; using IRaCIS.Core.Application.BusinessFilter;
using Microsoft.AspNetCore.Http;
using IRaCIS.Core.Infrastructure.Extention;
using Newtonsoft.Json;
using Microsoft.AspNetCore.Diagnostics;
using IRaCIS.Core.Application.MassTransit.Command;
using IRaCIS.Core.Application.MassTransit.Consumer;
#region #region
@@ -134,7 +138,28 @@ builder.Services.AddSwaggerSetup();
builder.Services.AddJWTAuthSetup(_configuration); builder.Services.AddJWTAuthSetup(_configuration);
// MediatR 进程内消息 事件解耦 从程序集中 注册命令和handler对应关系 // MediatR 进程内消息 事件解耦 从程序集中 注册命令和handler对应关系
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<ConsistencyVerificationHandler>()); //builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<ConsistencyVerificationHandler>());
#region MassTransit
//masstransit组件 也支持MediatR 中介者模式,但是支持分布式,考虑后续,所以在次替代MediatR
builder.Services.AddMediator(cfg =>
{
cfg.AddConsumer<ConsistencyCheckConsumer>();
});
builder.Services.AddMassTransit(cfg =>
{
cfg.UsingInMemory();
});
#endregion
#region FusionCache
builder.Services.AddFusionCache();
#endregion
// EasyCaching 缓存 // EasyCaching 缓存
builder.Services.AddEasyCachingSetup(_configuration); builder.Services.AddEasyCachingSetup(_configuration);
@@ -164,6 +189,8 @@ builder.Services.AddSingleton<IUserIdProvider, IRaCISUserIdProvider>();
builder.Services.AddSingleton<ISearcher>(new Searcher(CachePolicy.Content, Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources, "ip2region.xdb"))); builder.Services.AddSingleton<ISearcher>(new Searcher(CachePolicy.Content, Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources, "ip2region.xdb")));
//builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
//builder.Services.AddProblemDetails();
#region #region
//builder.Services.AddMemoryCache(); //builder.Services.AddMemoryCache();
@@ -190,6 +217,56 @@ var env = app.Environment;
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
#region 400 -500
//app.UseStatusCodePagesWithReExecute("/Error/{0}");
app.UseStatusCodePages(async context =>
{
var code = context.HttpContext.Response.StatusCode;
context.HttpContext.Response.ContentType = "application/json";
if (code < 500)
{
await context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk($"Client error, actual request error status code({code})")));
}
else
{
//ResultFilter 里面的异常并不会到这里
await context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject((ResponseOutput.NotOk($"Server error , actual request error status code({code})"))));
}
});
//app.UseExceptionHandler(o => { });
//这里没生效,原因未知,官方文档也是这种写法,也用了GlobalExceptionHandler 尝试,还是不行,怀疑框架bug
//app.UseExceptionHandler(configure =>
//{
// configure.Run(async context =>
// {
// var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>();
//var ex = exceptionHandlerPathFeature?.Error;
//context.Response.ContentType = "application/json";
//if (ex != null)
//{
// var errorInfo = $"Exception: {ex.Message}[{ex.StackTrace}]" + (ex.InnerException != null ? $" InnerException: {ex.InnerException.Message}[{ex.InnerException.StackTrace}]" : "");
// await context.Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk($"{ex?.Message}")));
// Log.Logger.Error(errorInfo);
//}
// });
//});
#endregion
//本地化 //本地化
app.UseLocalization(); app.UseLocalization();
@@ -198,12 +275,11 @@ app.UseForwardedHeaders();
//响应压缩 //响应压缩
app.UseResponseCompression(); app.UseResponseCompression();
//app.UseCors(t => t.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
//不需要 token 访问的静态文件 wwwroot css, JavaScript, and images don't require authentication. //不需要 token 访问的静态文件 wwwroot css, JavaScript, and images don't require authentication.
app.UseStaticFiles(); app.UseStaticFiles();
app.UseMiddleware<MultiDiskStaticFilesMiddleware>();
//LogDashboard //LogDashboard
app.UseLogDashboard("/LogDashboard"); app.UseLogDashboard("/LogDashboard");
@@ -211,22 +287,24 @@ app.UseLogDashboard("/LogDashboard");
//hangfire //hangfire
app.UseHangfireConfig(env); app.UseHangfireConfig(env);
#region
//app.UseMiddleware<MultiDiskStaticFilesMiddleware>();
////限流 中间件 ////限流 中间件
//app.UseIpRateLimiting(); //app.UseIpRateLimiting();
//if (env.IsDevelopment())
//{
// app.UseDeveloperExceptionPage();
//}
//else
//{
// //app.UseHsts();
//}
#endregion
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
//app.UseHsts();
}
// 特殊异常处理 比如 404
app.UseStatusCodePagesWithReExecute("/Error/{0}");
SwaggerSetup.Configure(app, env); SwaggerSetup.Configure(app, env);
@@ -1,5 +1,6 @@
using AutoMapper.EquivalencyExpression; using AutoMapper.EquivalencyExpression;
using IRaCIS.Core.Application.Service; using IRaCIS.Core.Application.Service;
using IRaCIS.Core.Domain.Models;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
namespace IRaCIS.Core.API namespace IRaCIS.Core.API
@@ -14,6 +15,10 @@ namespace IRaCIS.Core.API
//AutoMapper.Collection.EntityFrameworkCore //AutoMapper.Collection.EntityFrameworkCore
automapper.AddCollectionMappers(); automapper.AddCollectionMappers();
// 全局忽略 DomainEvents 属性
automapper.AddGlobalIgnore(nameof(Entity.DomainEvents));
#region 使 IncludeMembers 使 #region 使 IncludeMembers 使
//mapping an EntityFramework Core DbContext-object. //mapping an EntityFramework Core DbContext-object.
//automapper.UseEntityFrameworkCoreModel<IRaCISDBContext>(services); //automapper.UseEntityFrameworkCoreModel<IRaCISDBContext>(services);
@@ -10,7 +10,6 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using MediatR;
using IRaCIS.Application.Services; using IRaCIS.Application.Services;
using IRaCIS.Application.Interfaces; using IRaCIS.Application.Interfaces;
using AutoMapper; using AutoMapper;
@@ -4,9 +4,11 @@ using Hangfire.SqlServer;
using IRaCIS.Core.Application.Triggers; using IRaCIS.Core.Application.Triggers;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore; using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Infra.EFCore.Interceptor;
using Medallion.Threading; using Medallion.Threading;
using Medallion.Threading.SqlServer; using Medallion.Threading.SqlServer;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@@ -21,12 +23,15 @@ namespace IRaCIS.Core.API
services.AddHttpContextAccessor(); services.AddHttpContextAccessor();
services.AddScoped<IUserInfo, UserInfo>(); services.AddScoped<IUserInfo, UserInfo>();
services.AddScoped<ISaveChangesInterceptor, AuditEntityInterceptor>();
services.AddScoped<ISaveChangesInterceptor, DispatchDomainEventsInterceptor>();
// First, register a pooling context factory as a Singleton service, as usual: // First, register a pooling context factory as a Singleton service, as usual:
//这个注入没有成功--注入是没问题的,构造函数也只是支持参数就好,错在注入的地方不能写DbContext //这个注入没有成功--注入是没问题的,构造函数也只是支持参数就好,错在注入的地方不能写DbContext
//Web程序中通过重用池中DbContext实例可提高高并发场景下的吞吐量, 这在概念上类似于ADO.NET Provider原生的连接池操作方式,具有节省DbContext实例化成本的优点 //Web程序中通过重用池中DbContext实例可提高高并发场景下的吞吐量, 这在概念上类似于ADO.NET Provider原生的连接池操作方式,具有节省DbContext实例化成本的优点
services.AddDbContext<IRaCISDBContext>(options => services.AddDbContext<IRaCISDBContext>((sp, options) =>
{ {
// 在控制台 // 在控制台
@@ -43,6 +48,7 @@ namespace IRaCIS.Core.API
options.EnableSensitiveDataLogging(); options.EnableSensitiveDataLogging();
options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor()); options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor());
options.AddInterceptors(sp.GetServices<ISaveChangesInterceptor>());
options.UseProjectables(); options.UseProjectables();
+1 -1
View File
@@ -12,7 +12,7 @@
}, },
"ObjectStoreService": { "ObjectStoreService": {
"ObjectStoreUse": "MinIO", "ObjectStoreUse": "AliyunOSS",
"AliyunOSS": { "AliyunOSS": {
"regionId": "cn-shanghai", "regionId": "cn-shanghai",
@@ -9,6 +9,7 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Newtonsoft.Json; using Newtonsoft.Json;
using SharpCompress.Common; using SharpCompress.Common;
using ZiggyCreatures.Caching.Fusion;
namespace IRaCIS.Application.Services.BackGroundJob namespace IRaCIS.Application.Services.BackGroundJob
{ {
@@ -21,77 +22,45 @@ namespace IRaCIS.Application.Services.BackGroundJob
Task InitHangfireJobTaskAsync(); Task InitHangfireJobTaskAsync();
} }
public class IRaCISCHangfireJob : IIRaCISHangfireJob public class IRaCISCHangfireJob(IRepository<Trial> _trialRepository,
IEasyCachingProvider _provider,
ILogger<IRaCISCHangfireJob> _logger,
IRepository<SystemAnonymization> _systemAnonymizationRepository,
IRepository<Internationalization> _internationalizationRepository,
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigRepository
) : IIRaCISHangfireJob
{ {
public static string JsonFileFolder = Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources); public static string JsonFileFolder = Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources);
private readonly IRepository<Trial> _trialRepository;
private readonly IEasyCachingProvider _provider;
private readonly ILogger<IRaCISCHangfireJob> _logger;
private readonly IRepository<SystemAnonymization> _systemAnonymizationRepository;
private readonly IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigRepository;
private readonly IRepository<Internationalization> _internationalizationRepository;
public IRaCISCHangfireJob(IRepository<Trial> trialRepository, ILogger<IRaCISCHangfireJob> logger, IEasyCachingProvider provider, IRepository<TrialEmailNoticeConfig> trialEmailNoticeConfigRepository, IRepository<Internationalization> internationalizationRepository, IRepository<SystemAnonymization> systemAnonymizationRepository)
{
_trialRepository = trialRepository;
_provider = provider;
_logger = logger;
_trialEmailNoticeConfigRepository = trialEmailNoticeConfigRepository;
_internationalizationRepository = internationalizationRepository;
_systemAnonymizationRepository = systemAnonymizationRepository;
}
public async Task InitHangfireJobTaskAsync() public async Task InitHangfireJobTaskAsync()
{ {
_logger.LogInformation("项目启动 hangfire 任务初始化 执行开始~"); _logger.LogInformation("项目启动 hangfire 任务初始化 执行开始~");
//初始化国际化
//项目状态 立即加载到缓存中
await MemoryCacheTrialStatusAsync();
await MemoryCacheAnonymizeData();
//创建项目缓存 定时任务
HangfireJobHelper.AddOrUpdateInitCronJob<IIRaCISHangfireJob>("RecurringJob_Cache_TrialState", t => t.MemoryCacheTrialStatusAsync(), Cron.Daily());
//初始化
await InternationalizationHelper.InitInternationlizationDataAndWatchJsonFileAsync(_internationalizationRepository); await InternationalizationHelper.InitInternationlizationDataAndWatchJsonFileAsync(_internationalizationRepository);
//创建邮件定时任务 //创建邮件定时任务
await InitSysAndTrialCronJobAsync(); await InitSysAndTrialCronJobAsync();
#region
////项目状态 立即加载到缓存中
//await MemoryCacheTrialStatusAsync();
////await MemoryCacheAnonymizeData();
////创建项目缓存 定时任务
//HangfireJobHelper.AddOrUpdateInitCronJob<IIRaCISHangfireJob>("RecurringJob_Cache_TrialState", t => t.MemoryCacheTrialStatusAsync(), Cron.Daily());
#endregion
_logger.LogInformation("项目启动 hangfire 任务初始化 执行结束"); _logger.LogInformation("项目启动 hangfire 任务初始化 执行结束");
} }
/// <summary>
/// 缓存项目状态
/// </summary>
/// <returns></returns>
public async Task MemoryCacheTrialStatusAsync()
{
var list = await _trialRepository.Select(t => new { TrialId = t.Id, TrialStatusStr = t.TrialStatusStr })
.ToListAsync();
list.ForEach(t => _provider.Set(t.TrialId.ToString(), t.TrialStatusStr, TimeSpan.FromDays(7)));
}
public async Task MemoryCacheAnonymizeData()
{
var systemAnonymizationList = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
_provider.Set(StaticData.Anonymize.Anonymize_AddFixedFiled, systemAnonymizationList.Where(t => t.IsAdd && t.IsFixed).ToList(), TimeSpan.FromDays(7));
_provider.Set(StaticData.Anonymize.Anonymize_AddIRCInfoFiled, systemAnonymizationList.Where(t => t.IsAdd && t.IsFixed == false).ToList(), TimeSpan.FromDays(7));
_provider.Set(StaticData.Anonymize.Anonymize_FixedField, systemAnonymizationList.Where(t => t.IsAdd == false && t.IsFixed).ToList(), TimeSpan.FromDays(7));
_provider.Set(StaticData.Anonymize.Anonymize_IRCInfoField, systemAnonymizationList.Where(t => t.IsAdd == false && t.IsFixed == false).ToList(), TimeSpan.FromDays(7));
}
@@ -136,6 +105,36 @@ namespace IRaCIS.Application.Services.BackGroundJob
} }
#region
/// <summary>
/// 缓存项目状态--之前是启动的时候就获取所有的项目进行缓存,加上定时任务刷新,现在的话,改为是按照需要进行缓存请求数据库
/// </summary>
/// <returns></returns>
public async Task MemoryCacheTrialStatusAsync()
{
var list = await _trialRepository.Select(t => new { TrialId = t.Id, TrialStatusStr = t.TrialStatusStr })
.ToListAsync();
list.ForEach(t => _provider.Set(t.TrialId.ToString(), t.TrialStatusStr, TimeSpan.FromDays(7)));
}
public async Task MemoryCacheAnonymizeData()
{
var systemAnonymizationList = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
_provider.Set(StaticData.Anonymize.Anonymize_AddFixedFiled, systemAnonymizationList.Where(t => t.IsAdd && t.IsFixed).ToList(), TimeSpan.FromDays(7));
_provider.Set(StaticData.Anonymize.Anonymize_AddIRCInfoFiled, systemAnonymizationList.Where(t => t.IsAdd && t.IsFixed == false).ToList(), TimeSpan.FromDays(7));
_provider.Set(StaticData.Anonymize.Anonymize_FixedField, systemAnonymizationList.Where(t => t.IsAdd == false && t.IsFixed).ToList(), TimeSpan.FromDays(7));
_provider.Set(StaticData.Anonymize.Anonymize_IRCInfoField, systemAnonymizationList.Where(t => t.IsAdd == false && t.IsFixed == false).ToList(), TimeSpan.FromDays(7));
}
#endregion
} }
+9 -2
View File
@@ -9,6 +9,7 @@ using Panda.DynamicWebApi.Attributes;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using ZiggyCreatures.Caching.Fusion;
namespace IRaCIS.Core.Application namespace IRaCIS.Core.Application
{ {
@@ -32,7 +33,7 @@ namespace IRaCIS.Core.Application
public IWebHostEnvironment _hostEnvironment { get; set; } public IWebHostEnvironment _hostEnvironment { get; set; }
public IFusionCache _fusionCache { get; set; }
public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class
@@ -60,6 +61,9 @@ namespace IRaCIS.Core.Application
[MemberNotNull(nameof(_hostEnvironment))] [MemberNotNull(nameof(_hostEnvironment))]
public IWebHostEnvironment _hostEnvironment { get; set; } public IWebHostEnvironment _hostEnvironment { get; set; }
[MemberNotNull(nameof(_fusionCache))]
public IFusionCache _fusionCache { get; set; }
} }
#endregion #endregion
@@ -81,7 +85,8 @@ namespace IRaCIS.Core.Application
[MemberNotNull(nameof(_localizer))] [MemberNotNull(nameof(_localizer))]
public IStringLocalizer _localizer { get; set; } public IStringLocalizer _localizer { get; set; }
[MemberNotNull(nameof(_fusionCache))]
public IFusionCache _fusionCache { get; set; }
} }
@@ -97,6 +102,8 @@ namespace IRaCIS.Core.Application
public IStringLocalizer _localizer { get; set; } public IStringLocalizer _localizer { get; set; }
public IFusionCache _fusionCache { get; set; }
public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class
{ {
return new ResponseOutput<string>() return new ResponseOutput<string>()
@@ -0,0 +1,50 @@
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.BusinessFilter
{
/// <summary>
/// 不生效,不知道为啥
/// </summary>
public class GlobalExceptionHandler : IExceptionHandler
{
private readonly ILogger<GlobalExceptionHandler> _logger;
public GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger)
{
this._logger = logger;
}
public ValueTask<bool> TryHandleAsync(
HttpContext httpContext,
Exception exception,
CancellationToken cancellationToken)
{
httpContext.Response.ContentType = "application/json";
var ex = exception;
var errorInfo = $"Exception: {ex.Message}[{ex.StackTrace}]" + (ex.InnerException != null ? $" InnerException: {ex.InnerException.Message}[{ex.InnerException.StackTrace}]" : "");
httpContext.Response.WriteAsJsonAsync(ResponseOutput.NotOk($"{ex?.Message}"));
_logger.LogError(errorInfo);
// return true to signal that this exception is handled
return ValueTask.FromResult(false);
}
}
}
@@ -45,6 +45,7 @@ namespace IRaCIS.Core.Application.Filter
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, "", error!.Code, localizedInfo: info)); context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, "", error!.Code, localizedInfo: info));
//warning 级别记录 //warning 级别记录
//_logger.LogWarning($"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}"); //_logger.LogWarning($"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}");
} }
@@ -60,12 +61,17 @@ namespace IRaCIS.Core.Application.Filter
_logger.LogError(context.Exception.InnerException is null ? (context.Exception.Message + context.Exception.StackTrace) : (context.Exception.InnerException?.Message + context.Exception.InnerException?.StackTrace)); _logger.LogError(context.Exception.InnerException is null ? (context.Exception.Message + context.Exception.StackTrace) : (context.Exception.InnerException?.Message + context.Exception.InnerException?.StackTrace));
} }
context.ExceptionHandled = true;//标记当前异常已经被处理过了
//throw new Exception("test-result-exceptioin");
} }
else else
{ {
//继续 //继续
} }
context.ExceptionHandled = true;//标记当前异常已经被处理过了
} }
} }
} }
@@ -1,10 +1,12 @@
using EasyCaching.Core; using EasyCaching.Core;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using ZiggyCreatures.Caching.Fusion;
using static IRaCIS.Core.Domain.Share.StaticData; using static IRaCIS.Core.Domain.Share.StaticData;
namespace IRaCIS.Core.Application.Filter namespace IRaCIS.Core.Application.Filter
@@ -16,47 +18,36 @@ namespace IRaCIS.Core.Application.Filter
{ {
private readonly IEasyCachingProvider _provider; private readonly IEasyCachingProvider _provider;
private readonly IUserInfo _userInfo; private readonly IUserInfo _userInfo;
private readonly IFusionCache _fusionCache;
public IStringLocalizer _localizer; public IStringLocalizer _localizer;
private readonly List<string> _trialOptList=new List<string>(); private readonly IRepository<Trial> _trialRepository;
private readonly List<string> _trialOptList = new List<string>();
public TrialResourceFilter(IEasyCachingProvider provider, IStringLocalizer localizer , IUserInfo userInfo, string trialOpt = null, string trialOpt2 = null, string trialOpt3 = null) public TrialResourceFilter(IFusionCache fusionCache, IRepository<Trial> trialRepository, IEasyCachingProvider provider, IStringLocalizer localizer, IUserInfo userInfo, string trialOpt = null, string trialOpt2 = null, string trialOpt3 = null)
{ {
_fusionCache = fusionCache;
_provider = provider; _provider = provider;
_userInfo = userInfo; _userInfo = userInfo;
_localizer = localizer; _localizer = localizer;
//_trialOpt = trialOpt; _trialRepository = trialRepository;
if (!string.IsNullOrWhiteSpace(trialOpt)) _trialOptList.Add(trialOpt.Trim()); if (!string.IsNullOrWhiteSpace(trialOpt)) _trialOptList.Add(trialOpt.Trim());
if (!string.IsNullOrWhiteSpace(trialOpt2)) _trialOptList.Add(trialOpt2.Trim()); if (!string.IsNullOrWhiteSpace(trialOpt2)) _trialOptList.Add(trialOpt2.Trim());
if (!string.IsNullOrWhiteSpace(trialOpt3)) _trialOptList.Add(trialOpt3.Trim()); if (!string.IsNullOrWhiteSpace(trialOpt3)) _trialOptList.Add(trialOpt3.Trim());
} }
//public TrialResourceFilter(IEasyCachingProvider provider, IUserInfo userInfo)
//{
// _provider = provider;
// _userInfo = userInfo;
//}
//优先选择异步的方法 //优先选择异步的方法
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next) public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
{ {
// var typeFilter = context.ActionDescriptor.EndpointMetadata.Where(t => t.GetType() == typeof(TypeFilterAttribute)).Select(t => (TypeFilterAttribute)t).ToList().FirstOrDefault(); // var typeFilter = context.ActionDescriptor.EndpointMetadata.Where(t => t.GetType() == typeof(TypeFilterAttribute)).Select(t => (TypeFilterAttribute)t).ToList().FirstOrDefault();
//var _trialOptList= typeFilter.Arguments.Select(t => t.ToString()).ToList(); //var _trialOptList= typeFilter.Arguments.Select(t => t.ToString()).ToList();
#region #region
// 后期列举出具体的类型,其他任何用户类型,都不允许操作 // 后期列举出具体的类型,其他任何用户类型,都不允许操作
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower()!= "TrialDocument/userConfirm".ToLower()) if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower() != "TrialDocument/userConfirm".ToLower())
{ {
//---对不起,您的账户没有操作权限。 //---对不起,您的账户没有操作权限。
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"])); context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"]));
@@ -97,7 +88,7 @@ namespace IRaCIS.Core.Application.Filter
} }
else else
{ {
//---正则取请求Refer 中trialId 失败,请联系开发人员核查 //---正则取请求Refer 中trialId 失败,请联系开发人员核查
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"])); context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
} }
@@ -128,20 +119,20 @@ namespace IRaCIS.Core.Application.Filter
if (matchResult.Success) if (matchResult.Success)
{ {
//有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下 //有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下
var cacheResultDic = _provider.GetAll<string>(new[] { matchResult.Value });
var trialStatusStr = cacheResultDic[matchResult.Value.ToLower()].Value; trialIdStr = matchResult.Value;
if (!string.IsNullOrWhiteSpace(trialStatusStr)) var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
if (string.IsNullOrWhiteSpace(trialStatusStr))
{ {
trialIdStr = matchResult.Value; //数据库 检查该项目Id不对
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
} }
} }
else else
{ {
//---正则取请求Refer 中trialId 失败,请联系开发人员核查 //---正则取请求Refer 中trialId 失败,请联系开发人员核查
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"])); context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
} }
@@ -153,34 +144,12 @@ namespace IRaCIS.Core.Application.Filter
} }
//通过path 或者body 找到trialId 了 //通过path 或者body 找到trialId 了
if ( !string.IsNullOrWhiteSpace(trialIdStr)) if (!string.IsNullOrWhiteSpace(trialIdStr))
{ {
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
//如果没缓存数据,可能定时任务没执行或者缓存丢失 在此重新缓存
if (_provider.GetCount() == 0)
{
var _trialRepository = context.HttpContext.RequestServices.GetService(typeof(IRepository<Trial>)) as IRepository<Trial>;
var list = _trialRepository.IfNullThrowException().Select(t => new { TrialId = t.Id, TrialStatusStr = t.TrialStatusStr })
.ToList();
list.ForEach(t => _provider.Set(t.TrialId.ToString(), t.TrialStatusStr, TimeSpan.FromDays(7)));
}
var cacheResultDic = _provider.GetAll<string>(new[] { trialIdStr });
var trialStatusStr = cacheResultDic[trialIdStr].Value;
//意外 导致缓存过期,调整服务器时间,测试不想重启程序
if (string.IsNullOrWhiteSpace(trialStatusStr))
{
var trialRepository = context.HttpContext.RequestServices.GetService(typeof(IRepository<Trial>)) as IRepository<Trial>;
trialStatusStr = trialRepository?.Where(t => t.Id == Guid.Parse(trialIdStr)).Select(t => t.TrialStatusStr).FirstOrDefault();
}
// 这里是统一拦截 项目有关的操作允许情况(特殊的地方,比如项目配置(有的在多种状态(初始化,ongoing)都可以操作,有的仅仅在Initializing)还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口) // 这里是统一拦截 项目有关的操作允许情况(特殊的地方,比如项目配置(有的在多种状态(初始化,ongoing)都可以操作,有的仅仅在Initializing)还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口)
if (trialStatusStr == StaticData.TrialState.TrialOngoing || _trialOptList.Any(t=>t== TrialOpt.BeforeOngoingCantOpt) ) if (trialStatusStr == StaticData.TrialState.TrialOngoing || _trialOptList.Any(t => t == TrialOpt.BeforeOngoingCantOpt))
{ {
await next.Invoke(); await next.Invoke();
@@ -189,14 +158,14 @@ namespace IRaCIS.Core.Application.Filter
// 项目停止、或者完成 不允许操作 // 项目停止、或者完成 不允许操作
else else
{ {
//---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改 //---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_InterceptedProjectStatusRule"])); context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_InterceptedProjectStatusRule"]));
} }
} }
//添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截 //添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截
else if (_trialOptList.Any(t => t == TrialOpt.AddOrUpdateTrial ||t ==TrialOpt.SignSystemDocNoTrialId)) else if (_trialOptList.Any(t => t == TrialOpt.AddOrUpdateTrial || t == TrialOpt.SignSystemDocNoTrialId))
{ {
await next.Invoke(); await next.Invoke();
} }
@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.Helper
{
public static class CacheKeys
{
public static string Trial(string trialIdStr) => $"TrialId:{trialIdStr}";
// 你可以为其他实体和模块定义更多的键
}
public static class CacheHelper
{
public static async Task<string?> GetTrialStatusAsync(Guid trialId, IRepository<Trial> _trialRepository)
{
var statusStr = await _trialRepository.Where(t => t.Id == trialId, ignoreQueryFilters: true).Select(t => t.TrialStatusStr).FirstOrDefaultAsync();
return statusStr;
}
}
}
@@ -74,7 +74,6 @@
<PackageReference Include="fo-dicom.Codecs" Version="5.14.4" /> <PackageReference Include="fo-dicom.Codecs" Version="5.14.4" />
<PackageReference Include="IP2Region.Net" Version="2.0.2" /> <PackageReference Include="IP2Region.Net" Version="2.0.2" />
<PackageReference Include="MailKit" Version="4.2.0" /> <PackageReference Include="MailKit" Version="4.2.0" />
<PackageReference Include="MediatR" Version="12.2.0" />
<PackageReference Include="MimeKit" Version="4.2.0" /> <PackageReference Include="MimeKit" Version="4.2.0" />
<PackageReference Include="MiniExcel" Version="1.32.0" /> <PackageReference Include="MiniExcel" Version="1.32.0" />
<PackageReference Include="Minio" Version="6.0.3" /> <PackageReference Include="Minio" Version="6.0.3" />
@@ -86,7 +85,8 @@
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" /> <PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.5" /> <PackageReference Include="SixLabors.ImageSharp" Version="3.1.5" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.2" /> <PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.2" />
<PackageReference Include="WinSCP" Version="6.3.3" /> <PackageReference Include="MassTransit.AspNetCore" Version="7.3.1" />
<PackageReference Include="ZiggyCreatures.FusionCache" Version="1.3.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -29,31 +29,16 @@
签名 签名
</summary> </summary>
</member> </member>
<member name="T:IRaCIS.Core.Application.BusinessFilter.GlobalExceptionHandler">
<summary>
不生效,不知道为啥
</summary>
</member>
<member name="T:IRaCIS.Core.Application.Filter.TrialResourceFilter"> <member name="T:IRaCIS.Core.Application.Filter.TrialResourceFilter">
<summary> <summary>
主要为了 处理项目结束 锁库,不允许操作 主要为了 处理项目结束 锁库,不允许操作
</summary> </summary>
</member> </member>
<member name="M:IRaCIS.Core.Application.Helper.FileStoreHelper.GetSystemClinicalPathAsync(Microsoft.AspNetCore.Hosting.IWebHostEnvironment,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ClinicalDataSystemSet},System.Guid)">
<summary>
</summary>
<param name="_hostEnvironment"></param>
<param name="_clinicalDataTrialSetRepository"></param>
<param name="id"></param>
<returns></returns>
<exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception>
</member>
<member name="M:IRaCIS.Core.Application.Helper.FileStoreHelper.GetTrialClinicalPathAsync(Microsoft.AspNetCore.Hosting.IWebHostEnvironment,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ClinicalDataTrialSet},System.Guid)">
<summary>
</summary>
<param name="_hostEnvironment"></param>
<param name="_clinicalDataTrialSetRepository"></param>
<param name="id"></param>
<returns></returns>
<exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception>
</member>
<member name="M:IRaCIS.Core.Application.Helper.FileStoreHelper.WriteFileAsync(System.IO.Stream,System.String)"> <member name="M:IRaCIS.Core.Application.Helper.FileStoreHelper.WriteFileAsync(System.IO.Stream,System.String)">
<summary> <summary>
写文件导到磁盘 写文件导到磁盘
@@ -62,28 +47,6 @@
<param name="path">文件保存路径</param> <param name="path">文件保存路径</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Helper.FileStoreHelper.GetUploadPrintscreenFilePath(Microsoft.AspNetCore.Hosting.IWebHostEnvironment,System.String,System.Guid,System.Guid,System.Guid)">
<summary>
上传截图
</summary>
<param name="_hostEnvironment"></param>
<param name="fileName"></param>
<param name="trialId"></param>
<param name="siteid"></param>
<param name="subjectId"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Helper.FileStoreHelper.GetFilePath(Microsoft.AspNetCore.Hosting.IWebHostEnvironment,System.String,System.Guid,System.Guid,System.String)">
<summary>
通用获取文件路径
</summary>
<param name="_hostEnvironment"></param>
<param name="fileName"></param>
<param name="trialId"></param>
<param name="id"></param>
<param name="type"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Helper.OSSService.UploadToOSSAsync(System.IO.Stream,System.String,System.String,System.Boolean)"> <member name="M:IRaCIS.Core.Application.Helper.OSSService.UploadToOSSAsync(System.IO.Stream,System.String,System.String,System.Boolean)">
<summary> <summary>
oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder
@@ -9948,6 +9911,11 @@
TrialSiteDicomAEService TrialSiteDicomAEService
</summary> </summary>
</member> </member>
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.ConsistencyCheckConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomStudy},IRaCIS.Core.Domain.Share.IUserInfo,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Subject},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialSite},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudy},AutoMapper.IMapper,Microsoft.Extensions.Localization.IStringLocalizer)">
<summary>
构造函数注入
</summary>
</member>
<member name="T:IRaCIS.Core.Application.ViewModel.TaskAllocationRuleView"> <member name="T:IRaCIS.Core.Application.ViewModel.TaskAllocationRuleView">
<summary> TaskAllocationRuleView 列表视图模型 </summary> <summary> TaskAllocationRuleView 列表视图模型 </summary>
</member> </member>
@@ -13345,24 +13313,9 @@
维护 IsFrontTaskNeedSignButNotSign 字段 另外附加评估结果 维护 IsFrontTaskNeedSignButNotSign 字段 另外附加评估结果
</summary> </summary>
</member> </member>
<member name="M:IRaCIS.Core.Application.MediatR.Handlers.AnonymizeCacheHandler.#ctor(IRaCIS.Core.Infra.EFCore.IRepository,EasyCaching.Core.IEasyCachingProvider)">
<summary>
构造函数注入
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MediatR.Handlers.ConsistencyVerificationHandler.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomStudy},IRaCIS.Core.Domain.Share.IUserInfo,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Subject},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialSite},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudy},AutoMapper.IMapper,Microsoft.Extensions.Localization.IStringLocalizer)">
<summary>
构造函数注入
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MediatR.Handlers.TrialStateCacheHandler.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},EasyCaching.Core.IEasyCachingProvider)">
<summary>
构造函数注入
</summary>
</member>
<member name="M:IRaCIS.Application.Services.BackGroundJob.IRaCISCHangfireJob.MemoryCacheTrialStatusAsync"> <member name="M:IRaCIS.Application.Services.BackGroundJob.IRaCISCHangfireJob.MemoryCacheTrialStatusAsync">
<summary> <summary>
缓存项目状态 缓存项目状态--之前是启动的时候就获取所有的项目进行缓存,加上定时任务刷新,现在的话,改为是按照需要进行缓存请求数据库
</summary> </summary>
<returns></returns> <returns></returns>
</member> </member>
@@ -15239,11 +15192,14 @@
<param name="inQuery"></param> <param name="inQuery"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Application.Services.PatientService.SubmitVisitStudyBinding(IRaCIS.Application.Contracts.SubmitVisitStudyBindingCommand)"> <member name="M:IRaCIS.Application.Services.PatientService.SubmitVisitStudyBinding(IRaCIS.Application.Contracts.SubmitVisitStudyBindingCommand,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomSeries},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomInstance})">
<summary> <summary>
提交 患者检查和访视的绑定 提交 患者检查和访视的绑定
</summary> </summary>
<param name="inCommand"></param> <param name="inCommand"></param>
<param name="_dicomstudyRepository"></param>
<param name="_dicomSeriesRepository"></param>
<param name="_dicomInstanceRepository"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Application.Services.SubjectService.AddOrUpdateSubject(IRaCIS.Application.Contracts.SubjectCommand)"> <member name="M:IRaCIS.Application.Services.SubjectService.AddOrUpdateSubject(IRaCIS.Application.Contracts.SubjectCommand)">
@@ -0,0 +1,96 @@
using MiniExcelLibs.Attributes;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.MassTransit.Command
{
public record ConsistenCheckCommand
{
public List<CheckViewModel> ETCList { get; set; } = new List<CheckViewModel>();
public Guid TrialId { get; set; }
}
public record ConsistenCheckResult
{
}
public class CheckDBModel : CheckViewModel
{
public Guid SubjectVisitId { get; set; }
public Guid StudyId { get; set; }
}
//[ExcelImporter(/*ImportResultFilter = typeof(ImportResultFilteTest),*/ IsLabelingError = true)]
public class CheckViewModel
{
//[Required(ErrorMessage = "中心编号不能为空")]
//[ImporterHeader(Name = "Site ID", AutoTrim = true)]
[ExcelColumnName("Site ID")]
public string SiteCode { get; set; } = string.Empty;
//[Required(ErrorMessage = "受试者筛选号不能为空")]
//[ImporterHeader(Name = "Subject ID", AutoTrim = true)]
[ExcelColumnName("Subject ID")]
public string SubjectCode { get; set; } = string.Empty;
//[Required(ErrorMessage = "访视名称不能为空")]
//[ImporterHeader(Name = "Visit Name", AutoTrim = true)]
[ExcelColumnName("Visit Name")]
public string VisitName { get; set; } = string.Empty;
//[Required(ErrorMessage = "检查日期不能为空")]
[CanConvertToTime(ErrorMessage = "Does not conform to Study Date format")]
//[ImporterHeader(Name = "Study Date", AutoTrim = true)]
[ExcelColumnName("Study Date")]
public string StudyDate { get; set; } = string.Empty;
//[Required(ErrorMessage = "Modality不能为空")]
//[ImporterHeader(Name = "Modality", AutoTrim = true)]
[ExcelColumnName("Modality")]
public string Modality { get; set; } = string.Empty;
public override bool Equals(object? obj)
{
if (obj == null) return false;
var checkModel = obj as CheckViewModel;
if (checkModel is not null)
{
return SiteCode == checkModel.SiteCode && SubjectCode == checkModel.SubjectCode && VisitName == checkModel.VisitName && StudyDate == checkModel.StudyDate && Modality == checkModel.Modality;
}
else
{
return false;
}
}
public override int GetHashCode()
{
return (SiteCode + SubjectCode + VisitName + StudyDate + Modality).GetHashCode();
}
}
}
@@ -1,16 +1,22 @@
using AutoMapper; using AutoMapper;
using IRaCIS.Core.Application.MediatR.CommandAndQueries; using IRaCIS.Core.Application.Contracts.DTO;
using IRaCIS.Core.Application.MassTransit.Command;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using MassTransit;
using Microsoft.Extensions.Localization;
using Newtonsoft.Json; using Newtonsoft.Json;
using MediatR; using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Text; using System.Text;
using Microsoft.Extensions.Localization; using System.Threading.Tasks;
namespace IRaCIS.Core.Application.MediatR.Handlers namespace IRaCIS.Core.Application.MassTransit.Consumer
{ {
public class ConsistencyVerificationHandler : IRequestHandler<ConsistencyVerificationRequest, string> public class ConsistencyCheckConsumer : IConsumer<ConsistenCheckCommand>
{ {
private readonly IRepository<DicomStudy> _studyRepository; private readonly IRepository<DicomStudy> _studyRepository;
private readonly IUserInfo _userInfo; private readonly IUserInfo _userInfo;
private readonly IRepository<Subject> _subjectRepository; private readonly IRepository<Subject> _subjectRepository;
@@ -24,7 +30,7 @@ namespace IRaCIS.Core.Application.MediatR.Handlers
/// 构造函数注入 /// 构造函数注入
/// </summary> /// </summary>
public ConsistencyVerificationHandler(IRepository<DicomStudy> studyRepository, IUserInfo userInfo, public ConsistencyCheckConsumer(IRepository<DicomStudy> studyRepository, IUserInfo userInfo,
IRepository<Subject> subjectRepository, IRepository<SubjectVisit> subjectVisitRepository, IRepository<Subject> subjectRepository, IRepository<SubjectVisit> subjectVisitRepository,
IRepository<TrialSite> trialSiteRepository, IRepository<NoneDicomStudy> noneDicomStudyRepository, IRepository<TrialSite> trialSiteRepository, IRepository<NoneDicomStudy> noneDicomStudyRepository,
IMapper mapper, IStringLocalizer localizer) IMapper mapper, IStringLocalizer localizer)
@@ -39,19 +45,22 @@ namespace IRaCIS.Core.Application.MediatR.Handlers
_localizer = localizer; _localizer = localizer;
} }
async Task<string> IRequestHandler<ConsistencyVerificationRequest, string>.Handle(ConsistencyVerificationRequest request, CancellationToken cancellationToken)
public async Task Consume(ConsumeContext<ConsistenCheckCommand> context)
{ {
var trialId = request.TrialId;
var trialId = context.Message.TrialId;
//处理Excel大小写 //处理Excel大小写
request.ETCList.ForEach(t => { t.Modality = t.Modality.ToUpper().Trim(); t.StudyDate = Convert.ToDateTime(t.StudyDate).ToString("yyyy-MM-dd"); t.SiteCode = t.SiteCode.ToUpper().Trim(); t.VisitName = t.VisitName.ToUpper().Trim(); t.SubjectCode = t.SubjectCode.ToUpper().Trim(); }); context.Message.ETCList.ForEach(t => { t.Modality = t.Modality.ToUpper().Trim(); t.StudyDate = Convert.ToDateTime(t.StudyDate).ToString("yyyy-MM-dd"); t.SiteCode = t.SiteCode.ToUpper().Trim(); t.VisitName = t.VisitName.ToUpper().Trim(); t.SubjectCode = t.SubjectCode.ToUpper().Trim(); });
var etcList = request.ETCList; var etcList = context.Message.ETCList;
//Expression<Func<SubjectVisit, bool>> subjectVisitLambda2 = x => x.TrialId == request.TrialId; //Expression<Func<SubjectVisit, bool>> subjectVisitLambda2 = x => x.TrialId == request.TrialId;
//subjectVisitLambda2= subjectVisitLambda2.And(x => x.CheckState == CheckStateEnum.ToCheck && x.AuditState == AuditStateEnum.QCPassed || (x.CheckState == CheckStateEnum.CVIng && x.AuditState == AuditStateEnum.QCPassed)); //subjectVisitLambda2= subjectVisitLambda2.And(x => x.CheckState == CheckStateEnum.ToCheck && x.AuditState == AuditStateEnum.QCPassed || (x.CheckState == CheckStateEnum.CVIng && x.AuditState == AuditStateEnum.QCPassed));
Expression<Func<SubjectVisit, bool>> subjectVisitLambda = x => x.TrialId == request.TrialId && Expression<Func<SubjectVisit, bool>> subjectVisitLambda = x => x.TrialId == trialId &&
(x.CheckState == CheckStateEnum.ToCheck && x.AuditState == AuditStateEnum.QCPassed || (x.CheckState == CheckStateEnum.CVIng && x.AuditState == AuditStateEnum.QCPassed)); (x.CheckState == CheckStateEnum.ToCheck && x.AuditState == AuditStateEnum.QCPassed || (x.CheckState == CheckStateEnum.CVIng && x.AuditState == AuditStateEnum.QCPassed));
var dicomQuery = from sv in _subjectVisitRepository.Where(subjectVisitLambda) var dicomQuery = from sv in _subjectVisitRepository.Where(subjectVisitLambda)
@@ -274,11 +283,13 @@ namespace IRaCIS.Core.Application.MediatR.Handlers
} }
await _subjectVisitRepository.SaveChangesAsync(); await _subjectVisitRepository.SaveChangesAsync();
return "OK";
//await context.RespondAsync<ConsistenCheckResult>(new
//{
//});
} }
} }
} }
@@ -211,7 +211,9 @@ namespace IRaCIS.Core.Application.ViewModel
{ {
public bool? IsSelfAnalysis { get; set; } public bool? IsSelfAnalysis { get; set; }
public bool IsReReadingOrBackInfluenceAnalysis { get; set; } public int ConsistentClinicalDataCount { get; set; } = 0;
public bool IsReReadingOrBackInfluenceAnalysis { get; set; }
} }
@@ -20,6 +20,7 @@ using IRaCIS.Core.Infrastructure.Extention;
using System; using System;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using NPOI.SS.Formula.Functions; using NPOI.SS.Formula.Functions;
using IRaCIS.Core.Application.Service.Reading.Dto;
namespace IRaCIS.Core.Application.Service namespace IRaCIS.Core.Application.Service
{ {
@@ -32,6 +33,8 @@ namespace IRaCIS.Core.Application.Service
private readonly IRepository<TaskConsistentRule> _taskConsistentRuleRepository; private readonly IRepository<TaskConsistentRule> _taskConsistentRuleRepository;
private readonly IRepository<VisitTask> _visitTaskRepository; private readonly IRepository<VisitTask> _visitTaskRepository;
private readonly IRepository<ReadingConsistentClinicalData> _readingConsistentClinicalDataRepository;
private readonly IReadingClinicalDataService _readingClinicalDataService;
private readonly IRepository<SubjectUser> _subjectUserRepository; private readonly IRepository<SubjectUser> _subjectUserRepository;
private readonly IRepository<Subject> _subjectRepository; private readonly IRepository<Subject> _subjectRepository;
private readonly IRepository<Enroll> _enrollRepository; private readonly IRepository<Enroll> _enrollRepository;
@@ -44,11 +47,16 @@ namespace IRaCIS.Core.Application.Service
private readonly IVisitTaskHelpeService _visitTaskCommonService; private readonly IVisitTaskHelpeService _visitTaskCommonService;
public TaskConsistentRuleService(IRepository<VisitTask> visitTaskRepository, IRepository<Enroll> enrollRepository, IRepository<TaskConsistentRule> taskConsistentRuleRepository, IRepository<SubjectUser> subjectUserRepository, IRepository<Subject> subjectRepository, IDistributedLockProvider distributedLockProvider, public TaskConsistentRuleService(IRepository<VisitTask> visitTaskRepository,
IRepository<ReadingConsistentClinicalData> readingConsistentClinicalDataRepository,
IReadingClinicalDataService readingClinicalDataService,
IRepository<Enroll> enrollRepository, IRepository<TaskConsistentRule> taskConsistentRuleRepository, IRepository<SubjectUser> subjectUserRepository, IRepository<Subject> subjectRepository, IDistributedLockProvider distributedLockProvider,
IRepository<Trial> trialRepository, IRepository<TrialSite> trialSiteRepository, IRepository<TrialVirtualSiteCodeUpdate> trialVirtualSiteCodeUpdateRepository, IVisitTaskHelpeService visitTaskCommonService) IRepository<Trial> trialRepository, IRepository<TrialSite> trialSiteRepository, IRepository<TrialVirtualSiteCodeUpdate> trialVirtualSiteCodeUpdateRepository, IVisitTaskHelpeService visitTaskCommonService)
{ {
_taskConsistentRuleRepository = taskConsistentRuleRepository; _taskConsistentRuleRepository = taskConsistentRuleRepository;
_visitTaskRepository = visitTaskRepository; _visitTaskRepository = visitTaskRepository;
this._readingConsistentClinicalDataRepository = readingConsistentClinicalDataRepository;
this._readingClinicalDataService = readingClinicalDataService;
_subjectUserRepository = subjectUserRepository; _subjectUserRepository = subjectUserRepository;
_subjectRepository = subjectRepository; _subjectRepository = subjectRepository;
_enrollRepository = enrollRepository; _enrollRepository = enrollRepository;
@@ -117,6 +125,20 @@ namespace IRaCIS.Core.Application.Service
var defalutSortArray = new string[] { nameof(VisitTask.IsUrgent) + " desc", nameof(VisitTask.SubjectId), nameof(VisitTask.VisitTaskNum) }; var defalutSortArray = new string[] { nameof(VisitTask.IsUrgent) + " desc", nameof(VisitTask.SubjectId), nameof(VisitTask.VisitTaskNum) };
var pageList = await visitTaskQueryable.ToPagedListAsync(queryVisitTask.PageIndex, queryVisitTask.PageSize, queryVisitTask.SortField, queryVisitTask.Asc, string.IsNullOrWhiteSpace(queryVisitTask.SortField), defalutSortArray); var pageList = await visitTaskQueryable.ToPagedListAsync(queryVisitTask.PageIndex, queryVisitTask.PageSize, queryVisitTask.SortField, queryVisitTask.Asc, string.IsNullOrWhiteSpace(queryVisitTask.SortField), defalutSortArray);
#region
foreach (var item in pageList.CurrentPageData)
{
item.ConsistentClinicalDataCount = (await _readingClinicalDataService.GetClinicalDataList(new GetReadingOrTaskClinicalDataListInDto()
{
SubjectId = item.SubjectId,
TrialId = item.TrialId,
SelectIsSign = false,
IsGetAllConsistencyAnalysis = false,
VisitTaskId = item.Id,
})).Count();
}
#endregion
var trialTaskConfig = _repository.Where<Trial>(t => t.Id == queryVisitTask.TrialId).Select(t => new { IsHaveDoubleReadCriterion = t.TrialReadingCriterionList.Any(t => t.IsSigned && t.IsConfirm && t.ReadingType == ReadingMethod.Double), t.VitrualSiteCode }).FirstOrDefault(); var trialTaskConfig = _repository.Where<Trial>(t => t.Id == queryVisitTask.TrialId).Select(t => new { IsHaveDoubleReadCriterion = t.TrialReadingCriterionList.Any(t => t.IsSigned && t.IsConfirm && t.ReadingType == ReadingMethod.Double), t.VitrualSiteCode }).FirstOrDefault();
@@ -253,6 +275,7 @@ namespace IRaCIS.Core.Application.Service
TaskName = lastTask.TaskName + "_Global", TaskName = lastTask.TaskName + "_Global",
TaskBlindName = lastTask.TaskBlindName + "_Global", TaskBlindName = lastTask.TaskBlindName + "_Global",
TrialReadingCriterionId = trialReadingCriterionId, TrialReadingCriterionId = trialReadingCriterionId,
VisitTaskNum= lastTask.VisitTaskNum + ReadingCommon.TaskNumDic[ReadingCategory.Global]
}; };
var afterGlobal = _visitTaskRepository.Where(t => t.SubjectId == lastTask.SubjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.TaskState == TaskState.Effect && t.ReadingCategory == ReadingCategory.Global && t.VisitTaskNum > lastTask.VisitTaskNum).ProjectTo<VisitTaskSimpleDTO>(_mapper.ConfigurationProvider).FirstOrDefault(); var afterGlobal = _visitTaskRepository.Where(t => t.SubjectId == lastTask.SubjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.TaskState == TaskState.Effect && t.ReadingCategory == ReadingCategory.Global && t.VisitTaskNum > lastTask.VisitTaskNum).ProjectTo<VisitTaskSimpleDTO>(_mapper.ConfigurationProvider).FirstOrDefault();
@@ -496,7 +519,9 @@ namespace IRaCIS.Core.Application.Service
TrialReadingCriterionId = trialReadingCriterionId, TrialReadingCriterionId = trialReadingCriterionId,
BlindSubjectCode = blindSubjectCode, BlindSubjectCode = blindSubjectCode,
BlindTrialSiteCode = filterObj.BlindTrialSiteCode BlindTrialSiteCode = filterObj.BlindTrialSiteCode,
VisitTaskNum = lastTask.VisitTaskNum + ReadingCommon.TaskNumDic[ReadingCategory.Global]
}; };
} }
@@ -17,6 +17,7 @@ using IRaCIS.Core.Infra.EFCore.Common;
using System.Linq.Expressions; using System.Linq.Expressions;
using IRaCIS.Core.Domain.Share.Reading; using IRaCIS.Core.Domain.Share.Reading;
using IRaCIS.Core.Application.Service.Reading.Dto; using IRaCIS.Core.Application.Service.Reading.Dto;
using System.Runtime.InteropServices;
namespace IRaCIS.Core.Application.Service namespace IRaCIS.Core.Application.Service
{ {
@@ -26,7 +27,7 @@ namespace IRaCIS.Core.Application.Service
/// 访视读片任务 /// 访视读片任务
/// </summary> /// </summary>
[ApiExplorerSettings(GroupName = "Trial")] [ApiExplorerSettings(GroupName = "Trial")]
public class VisitTaskHelpeService : IVisitTaskHelpeService public class VisitTaskHelpeService : BaseService, IVisitTaskHelpeService
{ {
private readonly IRepository<VisitTask> _visitTaskRepository; private readonly IRepository<VisitTask> _visitTaskRepository;
@@ -450,6 +451,19 @@ namespace IRaCIS.Core.Application.Service
} }
/// <summary>
/// 获取GetIsClinicalDataSignTest
/// </summary>
/// <param name="visitTask"></param>
/// <returns></returns>
public async Task<bool> GetIsClinicalDataSignTest(Guid visitTask)
{
var taskinfo = await _visitTaskRepository.Where(x => x.Id == visitTask).FirstNotNullAsync();
var clinicalDataConfirmList = _trialClinicalDataSetRepository.Where(t => t.TrialId == taskinfo.TrialId && t.IsConfirm).Include(t => t.TrialClinicalDataSetCriteriaList).ToList();
Guid readingid = taskinfo.SourceSubjectVisitId == null ? taskinfo.SouceReadModuleId!.Value : taskinfo.SourceSubjectVisitId.Value;
return IsClinicalDataSign(taskinfo.ReadingCategory, taskinfo.VisitTaskNum == 0m, taskinfo.TrialReadingCriterionId, clinicalDataConfirmList, readingid, taskinfo.TrialId); ;
}
// 有可能在任务生成之前 就签名完了临床数据 // 有可能在任务生成之前 就签名完了临床数据
private bool IsClinicalDataSign(ReadingCategory readingCategory, bool isbaseLine, Guid trialReadingCriterionId, List<ClinicalDataTrialSet> trialClinicalDataSetList, Guid readingId, Guid trialId) private bool IsClinicalDataSign(ReadingCategory readingCategory, bool isbaseLine, Guid trialReadingCriterionId, List<ClinicalDataTrialSet> trialClinicalDataSetList, Guid readingId, Guid trialId)
@@ -468,7 +482,9 @@ namespace IRaCIS.Core.Application.Service
//CRC 的自动签名 不用管 只用处理PM的就好 //CRC 的自动签名 不用管 只用处理PM的就好
var haveSignedCount = _readingClinicalDataRepository var haveSignedCount = _readingClinicalDataRepository
.Where(t => t.TrialId == trialId && t.IsSign && t.ReadingClinicalDataState == ReadingClinicalDataStatus.HaveSigned && t.ReadingId == readingId && t.ClinicalDataTrialSet.UploadRole == UploadRole.PM).Count(); .Where(t => t.TrialId == trialId && t.IsSign
&& t.ClinicalDataTrialSet.TrialClinicalDataSetCriteriaList.Any(x=>x.TrialReadingCriterionId== trialReadingCriterionId)
&& t.ReadingClinicalDataState == ReadingClinicalDataStatus.HaveSigned && t.ReadingId == readingId && t.ClinicalDataTrialSet.UploadRole == UploadRole.PM).Count();
var readModule = _readModuleRepository.Where(t => t.Id == readingId).FirstOrDefault(); var readModule = _readModuleRepository.Where(t => t.Id == readingId).FirstOrDefault();
@@ -1415,6 +1431,7 @@ namespace IRaCIS.Core.Application.Service
case GenerateTaskCategory.SelfConsistent: case GenerateTaskCategory.SelfConsistent:
var readingCriterionId = generateTaskCommand.GenerataConsistentTaskList.First().TrialReadingCriterionId; var readingCriterionId = generateTaskCommand.GenerataConsistentTaskList.First().TrialReadingCriterionId;
var isReadingTaskViewInOrder = await _trialReadingCriterionRepository.Where(t => t.Id == readingCriterionId).Select(x => x.IsReadingTaskViewInOrder).FirstNotNullAsync();
var subjectId = generateTaskCommand.GenerataConsistentTaskList.First().SubjectId; var subjectId = generateTaskCommand.GenerataConsistentTaskList.First().SubjectId;
//var trialReadingCriterion=_trialReadingCriterionRepository.Where(t=>t.Id== trialReadingCriterionId).FirstOrDefault(); //var trialReadingCriterion=_trialReadingCriterionRepository.Where(t=>t.Id== trialReadingCriterionId).FirstOrDefault();
@@ -1457,7 +1474,11 @@ namespace IRaCIS.Core.Application.Service
foreach (var task in generateTaskCommand.GenerataConsistentTaskList) foreach (var task in generateTaskCommand.GenerataConsistentTaskList)
{ {
var exsitPDF = await _readingClinicalDataRepository.AnyAsync(t => t.TrialId == trialId &&
var exsitPDF = await _readingClinicalDataRepository
.WhereIf(isReadingTaskViewInOrder== ReadingOrder.Random,t=>t.ReadingId== task.SouceReadModuleId|| t.ReadingId == task.SourceSubjectVisitId)
.AnyAsync(t => t.TrialId == trialId &&
t.SubjectId== task.SubjectId&& t.SubjectId== task.SubjectId&&
t.ClinicalDataTrialSet.TrialClinicalDataSetCriteriaList.Any(c => c.TrialReadingCriterionId == readingCriterionId) t.ClinicalDataTrialSet.TrialClinicalDataSetCriteriaList.Any(c => c.TrialReadingCriterionId == readingCriterionId)
@@ -37,11 +37,11 @@ namespace IRaCIS.Core.Application.Service
.WhereIf(queryCommonDocument.CriterionTypeEnum != null, t => t.CriterionTypeEnum == queryCommonDocument.CriterionTypeEnum) .WhereIf(queryCommonDocument.CriterionTypeEnum != null, t => t.CriterionTypeEnum == queryCommonDocument.CriterionTypeEnum)
.WhereIf(queryCommonDocument.BusinessScenarioEnum != null, t => t.BusinessScenarioEnum == queryCommonDocument.BusinessScenarioEnum) .WhereIf(queryCommonDocument.BusinessScenarioEnum != null, t => t.BusinessScenarioEnum == queryCommonDocument.BusinessScenarioEnum)
.WhereIf(string.IsNullOrEmpty(queryCommonDocument.Code), t => t.Code.Contains(queryCommonDocument.Code)) .WhereIf(!string.IsNullOrEmpty(queryCommonDocument.Code), t => t.Code.Contains(queryCommonDocument.Code))
.WhereIf(string.IsNullOrEmpty(queryCommonDocument.Name), t => t.Name.Contains(queryCommonDocument.Name)) .WhereIf(!string.IsNullOrEmpty(queryCommonDocument.Name), t => t.Name.Contains(queryCommonDocument.Name))
.ProjectTo<CommonDocumentView>(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken, userId = _userInfo.Id }); .ProjectTo<CommonDocumentView>(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken, userId = _userInfo.Id });
return await commonDocumentQueryable.ToPagedListAsync(queryCommonDocument.PageIndex, queryCommonDocument.PageSize, String.IsNullOrEmpty(queryCommonDocument.SortField) ? nameof(CommonDocument.Code) : queryCommonDocument.SortField, queryCommonDocument.Asc); ; return await commonDocumentQueryable.ToPagedListAsync(queryCommonDocument);
} }
@@ -206,7 +206,8 @@ namespace IRaCIS.Core.Application.Service.Common
var isIR = _userInfo.UserTypeEnumInt == (int)UserTypeEnum.IndependentReviewer; var isIR = _userInfo.UserTypeEnumInt == (int)UserTypeEnum.IndependentReviewer;
var query = _trialRepository.AsQueryable().IgnoreQueryFilters() var query = _trialRepository.AsQueryable()
.WhereIf(inQuery.TrialIdList.Count()>0, o => inQuery.TrialIdList.Contains(o.Id))
.WhereIf(inQuery.SponsorId != null, o => o.SponsorId == inQuery.SponsorId) .WhereIf(inQuery.SponsorId != null, o => o.SponsorId == inQuery.SponsorId)
.WhereIf(!string.IsNullOrEmpty(inQuery.Code), o => o.TrialCode.Contains(inQuery.Code)) .WhereIf(!string.IsNullOrEmpty(inQuery.Code), o => o.TrialCode.Contains(inQuery.Code))
@@ -25,7 +25,7 @@ namespace IRaCIS.Core.Application.Contracts
Task<List<TrialUserDto>> GetTrialUserSelect(Guid trialId); Task<List<TrialUserDto>> GetTrialUserSelect(Guid trialId);
PageOutput<DocumentUnionWithUserStatView> GetTrialSystemDocumentList(DocumentTrialUnionQuery querySystemDocument); Task<PageOutput<DocumentUnionWithUserStatView>> GetTrialSystemDocumentList(DocumentTrialUnionQuery querySystemDocument);
List<TrialUserUnionDocumentView> GetTrialUserDocumentList(Guid trialId); List<TrialUserUnionDocumentView> GetTrialUserDocumentList(Guid trialId);
} }
} }
@@ -26,8 +26,8 @@ namespace IRaCIS.Core.Application.Services
private readonly IRepository<TrialDocument> _trialDocumentRepository; private readonly IRepository<TrialDocument> _trialDocumentRepository;
private readonly IRepository<TrialDocConfirmedUser> _trialDocUserTypeConfirmedUserRepository; private readonly IRepository<TrialDocConfirmedUser> _trialDocUserTypeConfirmedUserRepository;
private readonly IRepository<Trial> _trialRepository; private readonly IRepository<Trial> _trialRepository;
private readonly ISystemDocumentService _systemDocumentService; private readonly ISystemDocumentService _systemDocumentService;
private readonly IRepository<SystemDocConfirmedUser> _systemDocConfirmedUserRepository; private readonly IRepository<SystemDocConfirmedUser> _systemDocConfirmedUserRepository;
private readonly IRepository<SystemDocument> _systemDocumentRepository; private readonly IRepository<SystemDocument> _systemDocumentRepository;
private readonly IRepository<TrialCriterionAdditionalAssessmentType> _trialCriterionAdditionalAssessmentTypeRepository; private readonly IRepository<TrialCriterionAdditionalAssessmentType> _trialCriterionAdditionalAssessmentTypeRepository;
private readonly IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository; private readonly IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository;
@@ -36,8 +36,8 @@ namespace IRaCIS.Core.Application.Services
public TrialDocumentService(IRepository<TrialDocument> trialDocumentRepository, public TrialDocumentService(IRepository<TrialDocument> trialDocumentRepository,
IRepository<TrialDocConfirmedUser> trialDocUserTypeConfirmedUserRepository, IRepository<TrialDocConfirmedUser> trialDocUserTypeConfirmedUserRepository,
IRepository<Trial> trialRepository, IRepository<Trial> trialRepository,
ISystemDocumentService systemDocumentService, ISystemDocumentService systemDocumentService,
IRepository<SystemDocConfirmedUser> systemDocConfirmedUserRepository, IRepository<SystemDocConfirmedUser> systemDocConfirmedUserRepository,
IRepository<TrialCriterionAdditionalAssessmentType> trialCriterionAdditionalAssessmentTypeRepository, IRepository<TrialCriterionAdditionalAssessmentType> trialCriterionAdditionalAssessmentTypeRepository,
IRepository<ReadingQuestionCriterionTrial> readingQuestionCriterionTrialRepository IRepository<ReadingQuestionCriterionTrial> readingQuestionCriterionTrialRepository
, IRepository<SystemDocument> systemDocumentRepository) , IRepository<SystemDocument> systemDocumentRepository)
@@ -45,8 +45,8 @@ namespace IRaCIS.Core.Application.Services
_trialDocumentRepository = trialDocumentRepository; _trialDocumentRepository = trialDocumentRepository;
this._trialDocUserTypeConfirmedUserRepository = trialDocUserTypeConfirmedUserRepository; this._trialDocUserTypeConfirmedUserRepository = trialDocUserTypeConfirmedUserRepository;
this._trialRepository = trialRepository; this._trialRepository = trialRepository;
this._systemDocumentService = systemDocumentService; this._systemDocumentService = systemDocumentService;
this._systemDocConfirmedUserRepository = systemDocConfirmedUserRepository; this._systemDocConfirmedUserRepository = systemDocConfirmedUserRepository;
_systemDocumentRepository = systemDocumentRepository; _systemDocumentRepository = systemDocumentRepository;
_readingQuestionCriterionTrialRepository = readingQuestionCriterionTrialRepository; _readingQuestionCriterionTrialRepository = readingQuestionCriterionTrialRepository;
_trialCriterionAdditionalAssessmentTypeRepository = trialCriterionAdditionalAssessmentTypeRepository; _trialCriterionAdditionalAssessmentTypeRepository = trialCriterionAdditionalAssessmentTypeRepository;
@@ -64,7 +64,7 @@ namespace IRaCIS.Core.Application.Services
var trialDocumentQueryable = _trialDocumentRepository.AsQueryable(true).Where(t => t.TrialId == queryTrialDocument.TrialId) var trialDocumentQueryable = _trialDocumentRepository.AsQueryable(true).Where(t => t.TrialId == queryTrialDocument.TrialId)
.WhereIf(!string.IsNullOrEmpty(queryTrialDocument.Name), t => t.Name.Contains(queryTrialDocument.Name)) .WhereIf(!string.IsNullOrEmpty(queryTrialDocument.Name), t => t.Name.Contains(queryTrialDocument.Name))
.WhereIf(queryTrialDocument.FileTypeId != null, t => t.FileTypeId == queryTrialDocument.FileTypeId) .WhereIf(queryTrialDocument.FileTypeId != null, t => t.FileTypeId == queryTrialDocument.FileTypeId)
.WhereIf(queryTrialDocument.UserTypeId != null, t => t.NeedConfirmedUserTypeList.Any(t=>t.NeedConfirmUserTypeId== queryTrialDocument.UserTypeId) ) .WhereIf(queryTrialDocument.UserTypeId != null, t => t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == queryTrialDocument.UserTypeId))
.WhereIf(queryTrialDocument.IsDeleted != null, t => t.IsDeleted == queryTrialDocument.IsDeleted) .WhereIf(queryTrialDocument.IsDeleted != null, t => t.IsDeleted == queryTrialDocument.IsDeleted)
.ProjectTo<TrialDocumentView>(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken, isEn_Us = _userInfo.IsEn_Us }); .ProjectTo<TrialDocumentView>(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken, isEn_Us = _userInfo.IsEn_Us });
@@ -75,17 +75,17 @@ namespace IRaCIS.Core.Application.Services
public async Task<PageOutput<TrialSignDocView>> GetTrialSignDocumentList(TrialDocQuery querySystemDocument) public async Task<PageOutput<TrialSignDocView>> GetTrialSignDocumentList(TrialDocQuery querySystemDocument)
{ {
var trialDocQueryable = from trialDoc in _trialDocumentRepository.AsQueryable(true) var trialDocQueryable = from trialDoc in _trialDocumentRepository.AsQueryable(true)
.WhereIf(querySystemDocument.TrialId!=null,t=>t.TrialId==querySystemDocument.TrialId) .WhereIf(querySystemDocument.TrialId != null, t => t.TrialId == querySystemDocument.TrialId)
.Where(t => t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == _userInfo.UserTypeId) ) .Where(t => t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == _userInfo.UserTypeId))
join trialUser in _repository.Where<TrialUser>(t=>t.UserId==_userInfo.Id) on trialDoc.TrialId equals trialUser.TrialId join trialUser in _repository.Where<TrialUser>(t => t.UserId == _userInfo.Id) on trialDoc.TrialId equals trialUser.TrialId
join confirm in _repository.Where<TrialDocConfirmedUser>() on join confirm in _repository.Where<TrialDocConfirmedUser>() on
new { trialUser.UserId, TrialDocumentId = trialDoc.Id } equals new { UserId = confirm.ConfirmUserId, confirm.TrialDocumentId } into cc new { trialUser.UserId, TrialDocumentId = trialDoc.Id } equals new { UserId = confirm.ConfirmUserId, confirm.TrialDocumentId } into cc
from confirm in cc.DefaultIfEmpty() from confirm in cc.DefaultIfEmpty()
select new TrialSignDocView() select new TrialSignDocView()
{ {
TrialCode=trialDoc.Trial.TrialCode, TrialCode = trialDoc.Trial.TrialCode,
ResearchProgramNo = trialDoc.Trial.ResearchProgramNo, ResearchProgramNo = trialDoc.Trial.ResearchProgramNo,
ExperimentName = trialDoc.Trial.ExperimentName, ExperimentName = trialDoc.Trial.ExperimentName,
Id = trialDoc.Id, Id = trialDoc.Id,
@@ -116,7 +116,7 @@ namespace IRaCIS.Core.Application.Services
.WhereIf(querySystemDocument.IsSigned == false, t => t.ConfirmTime == null); .WhereIf(querySystemDocument.IsSigned == false, t => t.ConfirmTime == null);
return await trialDocQueryable.ToPagedListAsync(querySystemDocument.PageIndex, querySystemDocument.PageSize, querySystemDocument.SortField, querySystemDocument.Asc); return await trialDocQueryable.ToPagedListAsync(querySystemDocument.PageIndex, querySystemDocument.PageSize, querySystemDocument.SortField, querySystemDocument.Asc);
} }
@@ -146,14 +146,14 @@ namespace IRaCIS.Core.Application.Services
{ {
result = await _systemDocumentService.getWaitSignSysDocList(new SystemDocumentQuery() result = await _systemDocumentService.getWaitSignSysDocList(new SystemDocumentQuery()
{ {
PageIndex=1, PageIndex = 1,
IsSigned = false, IsSigned = false,
PageSize=1, PageSize = 1,
Asc=false, Asc = false,
SortField="UpdateTime", SortField = "UpdateTime",
}); });
} }
if (result.CurrentPageData.Count > 0) if (result.CurrentPageData.Count > 0)
@@ -823,7 +823,7 @@ namespace IRaCIS.Core.Application.Services
/// <returns></returns> /// <returns></returns>
[HttpPost] [HttpPost]
[Obsolete] [Obsolete]
public PageOutput<DocumentUnionWithUserStatView> GetTrialSystemDocumentList(DocumentTrialUnionQuery querySystemDocument) public async Task<PageOutput<DocumentUnionWithUserStatView>> GetTrialSystemDocumentList(DocumentTrialUnionQuery querySystemDocument)
{ {
var systemDocumentQueryable = _repository var systemDocumentQueryable = _repository
.WhereIf<SystemDocument>(!_userInfo.IsAdmin, t => t.IsDeleted == false) .WhereIf<SystemDocument>(!_userInfo.IsAdmin, t => t.IsDeleted == false)
@@ -867,7 +867,7 @@ namespace IRaCIS.Core.Application.Services
.WhereIf(!string.IsNullOrEmpty(querySystemDocument.Name), t => t.Name.Contains(querySystemDocument.Name)) .WhereIf(!string.IsNullOrEmpty(querySystemDocument.Name), t => t.Name.Contains(querySystemDocument.Name))
.WhereIf(querySystemDocument.FileTypeId != null, t => t.FileTypeId == querySystemDocument.FileTypeId); .WhereIf(querySystemDocument.FileTypeId != null, t => t.FileTypeId == querySystemDocument.FileTypeId);
return unionQuery.ToPagedList(querySystemDocument.PageIndex, querySystemDocument.PageSize, querySystemDocument.SortField, querySystemDocument.Asc); return await unionQuery.ToPagedListAsync(querySystemDocument.PageIndex, querySystemDocument.PageSize, querySystemDocument.SortField, querySystemDocument.Asc);
} }
#endregion #endregion
@@ -66,7 +66,7 @@ namespace IRaCIS.Core.Application.Service
{ {
GroupId=gropId, GroupId=gropId,
LimitEdit=LimitEdit.OnlyBaseLine, LimitEdit=LimitEdit.OnlyBaseLine,
DictionaryCode="YesOrNoOrNa", DictionaryCode="YesOrNoOrNE",
IsJudgeQuestion=false, IsJudgeQuestion=false,
IsShowInDicom=false, IsShowInDicom=false,
GlobalReadingShowType=GlobalReadingShowType.NotShow, GlobalReadingShowType=GlobalReadingShowType.NotShow,
@@ -10,7 +10,6 @@ using IRaCIS.Core.Infrastructure;
using DocumentFormat.OpenXml.Presentation; using DocumentFormat.OpenXml.Presentation;
using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Application.Filter; using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.MediatR.Handlers;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.Threading; using System.Threading;
@@ -206,6 +205,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
study.TrialId = incommand.TrialId; study.TrialId = incommand.TrialId;
study.SubjectId = incommand.SubjectId; study.SubjectId = incommand.SubjectId;
study.SubjectVisitId = incommand.SubjectVisitId; study.SubjectVisitId = incommand.SubjectVisitId;
study.IsFromPACS = false;
//如果因为意外情况,连续点击两次,导致第一次插入了,第二次进来也会插入,在此判断一下 //如果因为意外情况,连续点击两次,导致第一次插入了,第二次进来也会插入,在此判断一下
var findStudy = await _dicomstudyRepository.FirstOrDefaultAsync(t => t.Id == study.Id); var findStudy = await _dicomstudyRepository.FirstOrDefaultAsync(t => t.Id == study.Id);
@@ -280,6 +280,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
studyMonitor.StudyCode = study.StudyCode; studyMonitor.StudyCode = study.StudyCode;
//特殊处理逻辑 //特殊处理逻辑
study.IsFromPACS = false;
study.Modalities = string.Join("、", incommand.Study.SeriesList.Select(t => t.Modality).Union(study.Modalities.Split("、", StringSplitOptions.RemoveEmptyEntries)).Distinct()); study.Modalities = string.Join("、", incommand.Study.SeriesList.Select(t => t.Modality).Union(study.Modalities.Split("、", StringSplitOptions.RemoveEmptyEntries)).Distinct());
SpecialArchiveStudyDeal(study); SpecialArchiveStudyDeal(study);
modalitys = study.Modalities; modalitys = study.Modalities;
@@ -5,10 +5,8 @@
//-------------------------------------------------------------------- //--------------------------------------------------------------------
using IRaCIS.Core.Application.Interfaces; using IRaCIS.Core.Application.Interfaces;
using IRaCIS.Core.Application.MediatR.Handlers;
using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Infra.EFCore; using IRaCIS.Core.Infra.EFCore;
using MediatR;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Core.Application.Service namespace IRaCIS.Core.Application.Service
{ {
@@ -18,12 +16,10 @@ namespace IRaCIS.Core.Application.Service
[ApiExplorerSettings(GroupName = "Image")] [ApiExplorerSettings(GroupName = "Image")]
public class SystemAnonymizationService : BaseService, ISystemAnonymizationService public class SystemAnonymizationService : BaseService, ISystemAnonymizationService
{ {
private readonly IMediator _mediator;
private readonly IRepository<SystemAnonymization> systemAnonymizationRepository; private readonly IRepository<SystemAnonymization> systemAnonymizationRepository;
public SystemAnonymizationService(IMediator mediator, IRepository<SystemAnonymization> systemAnonymizationRepository) public SystemAnonymizationService( IRepository<SystemAnonymization> systemAnonymizationRepository)
{ {
_mediator = mediator;
this.systemAnonymizationRepository = systemAnonymizationRepository; this.systemAnonymizationRepository = systemAnonymizationRepository;
} }
@@ -47,7 +43,6 @@ namespace IRaCIS.Core.Application.Service
var entity = await _repository.InsertOrUpdateAsync<SystemAnonymization, SystemAnonymizationAddOrEdit>(addOrEditSystemAnonymization, true); var entity = await _repository.InsertOrUpdateAsync<SystemAnonymization, SystemAnonymizationAddOrEdit>(addOrEditSystemAnonymization, true);
await _mediator.Send(new AnonymizeCacheRequest());
return ResponseOutput.Ok(entity.Id.ToString()); return ResponseOutput.Ok(entity.Id.ToString());
@@ -1,5 +1,4 @@
using Castle.Core.Internal; using IRaCIS.Application.Contracts;
using IRaCIS.Application.Contracts;
using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Contracts.DTO; using IRaCIS.Core.Application.Contracts.DTO;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
@@ -3,6 +3,7 @@ using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Service.Inspection.DTO; using IRaCIS.Core.Application.Service.Inspection.DTO;
using IRaCIS.Core.Application.Service.Inspection.Interface; using IRaCIS.Core.Application.Service.Inspection.Interface;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore.Common;
using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Infrastructure;
using Panda.DynamicWebApi.Attributes; using Panda.DynamicWebApi.Attributes;
@@ -58,8 +59,11 @@ namespace IRaCIS.Core.Application.Service.Inspection
join usertype in _repository.GetQueryable<UserType>().IgnoreQueryFilters() on leftuser.UserTypeId equals usertype.Id into usertypetemp join usertype in _repository.GetQueryable<UserType>().IgnoreQueryFilters() on leftuser.UserTypeId equals usertype.Id into usertypetemp
from leftusertype in usertypetemp.DefaultIfEmpty() from leftusertype in usertypetemp.DefaultIfEmpty()
//join trialCriterion in _repository.GetQueryable<ReadingQuestionCriterionTrial>().IgnoreQueryFilters() on data.TrialReadingCriterionId equals trialCriterion.Id into criterion join visttask in _repository.GetQueryable<VisitTask>().IgnoreQueryFilters() on data.VisitTaskId equals visttask.Id into visttasktemp
//from leftCriterion in criterion.DefaultIfEmpty() from leftvisttask in visttasktemp.DefaultIfEmpty()
//join trialCriterion in _repository.GetQueryable<ReadingQuestionCriterionTrial>().IgnoreQueryFilters() on data.TrialReadingCriterionId equals trialCriterion.Id into criterion
//from leftCriterion in criterion.DefaultIfEmpty()
//join moduleTyped in _repository.GetQueryable<Dictionary>().Where(x => x.Code == "ModuleType") on 1 equals 1 //join moduleTyped in _repository.GetQueryable<Dictionary>().Where(x => x.Code == "ModuleType") on 1 equals 1
//join moduleTypec in _repository.GetQueryable<Dictionary>() on new { ParentId = moduleTyped.Id, ModuleType = data.ModuleType } equals new { ParentId = moduleTypec.ParentId.Value, ModuleType = moduleTypec.Value } into moduleTypectemp //join moduleTypec in _repository.GetQueryable<Dictionary>() on new { ParentId = moduleTyped.Id, ModuleType = data.ModuleType } equals new { ParentId = moduleTypec.ParentId.Value, ModuleType = moduleTypec.Value } into moduleTypectemp
@@ -131,7 +135,7 @@ namespace IRaCIS.Core.Application.Service.Inspection
ExperimentName = leftrial.ExperimentName, ExperimentName = leftrial.ExperimentName,
SubjectCode = leftsubject.Code, SubjectCode = leftvisttask.BlindSubjectCode.IsNullOrEmpty()? leftsubject.Code: leftvisttask.BlindSubjectCode,
SiteCode = lefttrialSite.TrialSiteCode, SiteCode = lefttrialSite.TrialSiteCode,
ResearchProgramNo = leftrial.ResearchProgramNo, ResearchProgramNo = leftrial.ResearchProgramNo,
@@ -41,6 +41,7 @@ namespace IRaCIS.Application.Contracts
public string RealName { get; set; } = string.Empty; public string RealName { get; set; } = string.Empty;
public int? Sex { get; set; } // 1-男 2-女 public int? Sex { get; set; } // 1-男 2-女
/// <summary> /// <summary>
/// LastLoginIP /// LastLoginIP
/// </summary> /// </summary>
@@ -1,5 +1,4 @@
using IRaCIS.Application.Contracts; using IRaCIS.Application.Contracts;
using IRaCIS.Core.Application.MediatR.CommandAndQueries;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using Newtonsoft.Json; using Newtonsoft.Json;
@@ -489,7 +488,14 @@ namespace IRaCIS.Core.Application.Contracts.DTO
} }
} }
public class ParamInfoDto
{
public string Modality { get; set; }
public string StudyDate { get; set; }
}
public class QCChanllengeDialogDTO : CheckChanllengeDialogDTO public class QCChanllengeDialogDTO : CheckChanllengeDialogDTO
@@ -157,6 +157,8 @@ namespace IRaCIS.Core.Application.Contracts
public bool IsHaveVisitClinicalData { get; set; } = false; public bool IsHaveVisitClinicalData { get; set; } = false;
public bool IsPacsConnectConfiged { get; set; }
} }
@@ -185,7 +187,7 @@ namespace IRaCIS.Core.Application.Contracts
public DateTime CreateTime { get; set; } public DateTime CreateTime { get; set; }
[DictionaryTranslateAttribute("YesOrNo")] [DictionaryTranslateAttribute("YesOrNo")]
public bool IsConfirmed { get; set; } public bool IsConfirmed => ConfirmTime != null;
public string RealName { get; set; } public string RealName { get; set; }
@@ -308,7 +310,7 @@ namespace IRaCIS.Core.Application.Contracts
{ {
if (!ClosedTime.HasValue) if (!ClosedTime.HasValue)
return ""; return "";
else return string.Format("{0}d {1}h {2}min", (ClosedTime - CreateTime)?.Days, (ClosedTime - CreateTime)?.Hours, (ClosedTime - CreateTime)?.Minutes); else return string.Format("{0}d {1}h {2}m", (ClosedTime - CreateTime)?.Days, (ClosedTime - CreateTime)?.Hours, (ClosedTime - CreateTime)?.Minutes);
} }
} }
@@ -2,7 +2,6 @@
using IRaCIS.Core.Application.Contracts.DTO; using IRaCIS.Core.Application.Contracts.DTO;
using IRaCIS.Core.Application.Service.Inspection.DTO; using IRaCIS.Core.Application.Service.Inspection.DTO;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using MediatR;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
@@ -40,6 +39,6 @@ namespace IRaCIS.Core.Application.Image.QA
Task<IResponseOutput> VerifyCanQCPassedOrFailed(Guid subjectVisitId); Task<IResponseOutput> VerifyCanQCPassedOrFailed(Guid subjectVisitId);
Task<IResponseOutput> ForwardSVDicomImage(Guid[] subjectVisitIdList); //Task<IResponseOutput> ForwardSVDicomImage(Guid[] subjectVisitIdList);
} }
} }
@@ -547,6 +547,7 @@ namespace IRaCIS.Core.Application.Image.QA
config.IsHaveStudyClinicalData = await _clinicalDataTrialSetRepository.AnyAsync(x => x.IsConfirm && x.TrialId == visit.TrialId && x.ClinicalDataLevel == ClinicalLevel.Study); config.IsHaveStudyClinicalData = await _clinicalDataTrialSetRepository.AnyAsync(x => x.IsConfirm && x.TrialId == visit.TrialId && x.ClinicalDataLevel == ClinicalLevel.Study);
config.IsPacsConnectConfiged= await _subjectVisitRepository.Where(t=>t.Id==subjectVisitId).AnyAsync(t=>t.Trial.IsPACSConnect && t.Subject.TrialSite.TrialSiteDicomAEList.Any());
return (list, config); return (list, config);
} }
@@ -2,11 +2,9 @@
using IRaCIS.Core.Application.Contracts.DTO; using IRaCIS.Core.Application.Contracts.DTO;
using IRaCIS.Core.Application.Filter; using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using MediatR;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System.Data; using System.Data;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using WinSCP;
using Newtonsoft.Json; using Newtonsoft.Json;
using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Application.Service.Inspection.DTO; using IRaCIS.Core.Application.Service.Inspection.DTO;
@@ -2109,109 +2107,113 @@ namespace IRaCIS.Core.Application.Image.QA
} }
#region
//[HttpPost("{trialId:guid}")]
////[Authorize(Policy = IRaCISPolicy.PM_APM)]
//[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
//public async Task<IResponseOutput> ForwardSVDicomImage(Guid[] subjectVisitIdList)
//{
[HttpPost("{trialId:guid}")] // bool isSuccess = false;
//[Authorize(Policy = IRaCISPolicy.PM_APM)]
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
public async Task<IResponseOutput> ForwardSVDicomImage(Guid[] subjectVisitIdList)
{
bool isSuccess = false;
foreach (var subjectVisitId in subjectVisitIdList) // foreach (var subjectVisitId in subjectVisitIdList)
{ // {
var info = (await _subjectVisitRepository.Where(t => t.Id == subjectVisitId).ProjectTo<DicomTrialSiteSubjectInfo>(_mapper.ConfigurationProvider).FirstOrDefaultAsync()).IfNullThrowException(); // var info = (await _subjectVisitRepository.Where(t => t.Id == subjectVisitId).ProjectTo<DicomTrialSiteSubjectInfo>(_mapper.ConfigurationProvider).FirstOrDefaultAsync()).IfNullThrowException();
var targetPath = "/IMPORT-IMAGES/" + info.TrialCode + "_" + info.SubjectCode + "_" + info.VisitName; // var targetPath = "/IMPORT-IMAGES/" + info.TrialCode + "_" + info.SubjectCode + "_" + info.VisitName;
var path = FileStoreHelper.GetSubjectVisitDicomFolderPhysicalPath(_hostEnvironment, info.TrialId, info.TrialSiteId, info.SubjectId, info.SubjectVisitId); // var path = FileStoreHelper.GetSubjectVisitDicomFolderPhysicalPath(_hostEnvironment, info.TrialId, info.TrialSiteId, info.SubjectId, info.SubjectVisitId);
try // try
{ // {
// 主机及端口信息后面可以改到 配置文件 // // 主机及端口信息后面可以改到 配置文件
SessionOptions sessionOptions = new SessionOptions // SessionOptions sessionOptions = new SessionOptions
{ // {
Protocol = Protocol.Sftp, // Protocol = Protocol.Sftp,
PortNumber = 8022, // PortNumber = 8022,
HostName = "CS-690-sftp.mint-imaging.com", // HostName = "CS-690-sftp.mint-imaging.com",
UserName = "zdong", // UserName = "zdong",
Password = "Everest@2021", // Password = "Everest@2021",
SshHostKeyFingerprint = @"ecdsa-sha2-nistp384 384 59gkjJ5lMwv3jsB8Wz2B35tBAIor5pSd8PcJYtoamPo=" // SshHostKeyFingerprint = @"ecdsa-sha2-nistp384 384 59gkjJ5lMwv3jsB8Wz2B35tBAIor5pSd8PcJYtoamPo="
}; // };
using (Session session = new Session()) // using (Session session = new Session())
{ // {
var studyFolders = (new DirectoryInfo(path)).GetDirectories(); // var studyFolders = (new DirectoryInfo(path)).GetDirectories();
session.Open(sessionOptions); // session.Open(sessionOptions);
if (!session.FileExists(targetPath)) // if (!session.FileExists(targetPath))
{ // {
session.CreateDirectory(targetPath); // session.CreateDirectory(targetPath);
} // }
foreach (var studyFolder in studyFolders) // foreach (var studyFolder in studyFolders)
{ // {
var targetFolder = Path.Combine(targetPath, studyFolder.Name); // var targetFolder = Path.Combine(targetPath, studyFolder.Name);
if (!session.FileExists(targetFolder)) // if (!session.FileExists(targetFolder))
{ // {
session.CreateDirectory(targetFolder); // session.CreateDirectory(targetFolder);
} // }
foreach (var file in studyFolder.GetFiles()) // foreach (var file in studyFolder.GetFiles())
{ // {
if (file.Extension.Contains("dcm", StringComparison.OrdinalIgnoreCase)) // if (file.Extension.Contains("dcm", StringComparison.OrdinalIgnoreCase))
{ // {
string remoteFilePath = // string remoteFilePath =
RemotePath.TranslateLocalPathToRemote(file.FullName, studyFolder.FullName, targetFolder); // RemotePath.TranslateLocalPathToRemote(file.FullName, studyFolder.FullName, targetFolder);
var result = session.PutFiles(file.FullName, remoteFilePath, false); // var result = session.PutFiles(file.FullName, remoteFilePath, false);
if (!result.IsSuccess) // if (!result.IsSuccess)
{ // {
await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.Id == subjectVisitId, // await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.Id == subjectVisitId,
u => new SubjectVisit() { ForwardState = ForwardStateEnum.ForwardFailed }); // u => new SubjectVisit() { ForwardState = ForwardStateEnum.ForwardFailed });
//---转发影像失败。 // //---转发影像失败。
return ResponseOutput.NotOk(_localizer["QCOperation_ForwardingFailed"] + result.Failures.ToString() + result.ToJson()); // return ResponseOutput.NotOk(_localizer["QCOperation_ForwardingFailed"] + result.Failures.ToString() + result.ToJson());
} // }
} // }
} // }
} // }
} // }
await _subjectVisitRepository.UpdatePartialFromQueryAsync(t => t.Id == subjectVisitId, // await _subjectVisitRepository.UpdatePartialFromQueryAsync(t => t.Id == subjectVisitId,
u => new SubjectVisit() { ForwardState = ForwardStateEnum.Forwarded, ForwardUserId = _userInfo.Id, ForwardTime = DateTime.Now }); // u => new SubjectVisit() { ForwardState = ForwardStateEnum.Forwarded, ForwardUserId = _userInfo.Id, ForwardTime = DateTime.Now });
isSuccess = true; // isSuccess = true;
} // }
catch (Exception e) // catch (Exception e)
{ // {
await _subjectVisitRepository.UpdatePartialFromQueryAsync(t => t.Id == subjectVisitId, // await _subjectVisitRepository.UpdatePartialFromQueryAsync(t => t.Id == subjectVisitId,
u => new SubjectVisit() { ForwardState = ForwardStateEnum.ForwardFailed }); // u => new SubjectVisit() { ForwardState = ForwardStateEnum.ForwardFailed });
// --转发影像失败 // // --转发影像失败
return ResponseOutput.NotOk(_localizer["QCOperation_ForwardingFailed"] + e.Message); // return ResponseOutput.NotOk(_localizer["QCOperation_ForwardingFailed"] + e.Message);
} // }
} // }
await _subjectVisitRepository.SaveChangesAsync(); // await _subjectVisitRepository.SaveChangesAsync();
// //---转发影像失败。
// return isSuccess ? ResponseOutput.Ok() : ResponseOutput.NotOk(_localizer["QCOperation_ForwardingFailed"]);
//}
#endregion
//---转发影像失败。
return isSuccess ? ResponseOutput.Ok() : ResponseOutput.NotOk(_localizer["QCOperation_ForwardingFailed"]);
}
@@ -7,6 +7,7 @@
using IRaCIS.Core.Application.Service.Reading.Dto; using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Infra.EFCore.Common; using IRaCIS.Core.Infra.EFCore.Common;
using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Infrastructure.Extention;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Core.Application.Contracts namespace IRaCIS.Core.Application.Contracts
@@ -104,7 +105,9 @@ namespace IRaCIS.Core.Application.Contracts
.ThenBy(t=>t.ShowOrder) .ThenBy(t=>t.ShowOrder)
.ProjectTo<QCQuestionConfigureView>(_mapper.ConfigurationProvider); .ProjectTo<QCQuestionConfigureView>(_mapper.ConfigurationProvider);
return await QCQuestionQueryable.ToPagedListAsync(queryQCQuestionConfigure.PageIndex, queryQCQuestionConfigure.PageSize, new string[2] { "LanguageType desc", "ShowOrder asc" }); var defalutSortArray = new string[] { nameof(QCQuestionConfigureView.LanguageType) + " desc", nameof(QCQuestionConfigureView.ShowOrder) };
return await QCQuestionQueryable.ToPagedListAsync(queryQCQuestionConfigure, defalutSortArray);
} }
public async Task<IResponseOutput> AddOrUpdateQCQuestionConfigure(QCQuestionAddOrEdit addOrEditQCQuestionConfigure) public async Task<IResponseOutput> AddOrUpdateQCQuestionConfigure(QCQuestionAddOrEdit addOrEditQCQuestionConfigure)
@@ -3,7 +3,7 @@ using AutoMapper.EquivalencyExpression;
using IRaCIS.Application.Contracts; using IRaCIS.Application.Contracts;
using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Contracts.DTO; using IRaCIS.Core.Application.Contracts.DTO;
using IRaCIS.Core.Application.MediatR.CommandAndQueries; using IRaCIS.Core.Application.MassTransit.Command;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using static IRaCIS.Core.Application.Contracts.SubjectProgressDto; using static IRaCIS.Core.Application.Contracts.SubjectProgressDto;
@@ -637,8 +637,9 @@ namespace IRaCIS.Core.Application.Service
ModuleName=x.ModuleName, ModuleName=x.ModuleName,
}); });
var defalutSortArray = new string[] { nameof(GetCRCConfirmListOutDto.SubjectCode) + " desc", nameof(GetCRCConfirmListOutDto.LatestScanDate) };
var result = await query.ToPagedListAsync(inDto.PageIndex, inDto.PageSize, new string[2] { "SubjectCode asc", "LatestScanDate asc" }); var result = await query.ToPagedListAsync(inDto, defalutSortArray);
var formList = await _clinicalFormRepository.Where(x => x.TrialId == inDto.TrialId) var formList = await _clinicalFormRepository.Where(x => x.TrialId == inDto.TrialId)
.Where(x => x.ClinicalDataTrialSet.UploadRole == UploadRole.CRC) .Where(x => x.ClinicalDataTrialSet.UploadRole == UploadRole.CRC)
@@ -255,7 +255,7 @@ namespace IRaCIS.Application.Services
var query = _readingClinicalDataRepository.AsQueryable(); var query = _readingClinicalDataRepository.AsQueryable();
if (inDto.StudyId != null) if (inDto.StudyId != null)
{ {
query = query.Where(x => x.StudyId == inDto.StudyId.Value); query = query.Where(x => x.StudyId == inDto.StudyId.Value && x.TrialId==inDto.TrialId&&x.SubjectId==inDto.SubjectId);
} }
else else
{ {
@@ -1227,6 +1227,7 @@ namespace IRaCIS.Application.Services
entity.ReadingClinicalDataState = ReadingClinicalDataStatus.HaveUploaded; entity.ReadingClinicalDataState = ReadingClinicalDataStatus.HaveUploaded;
entity.IsSign = false; entity.IsSign = false;
entity.FileCount = fileCount; entity.FileCount = fileCount;
entity.CreateTime=DateTime.Now;
var success = await _readingConsistentClinicalDataRepository.SaveChangesAsync(); var success = await _readingConsistentClinicalDataRepository.SaveChangesAsync();
return ResponseOutput.Ok(entity.Id); return ResponseOutput.Ok(entity.Id);
@@ -31,5 +31,6 @@ namespace IRaCIS.Core.Application.Contracts
Task DealVisiTaskClinicalDataSignedAsync(Guid trialId, Guid subjectId, Guid readingId, bool isVisit, Guid trialReadingCritrialId); Task DealVisiTaskClinicalDataSignedAsync(Guid trialId, Guid subjectId, Guid readingId, bool isVisit, Guid trialReadingCritrialId);
Task<IResponseOutput> SignConsistencyAnalysisReadingClinicalData(SignConsistencyAnalysisReadingClinicalDataInDto inDto); Task<IResponseOutput> SignConsistencyAnalysisReadingClinicalData(SignConsistencyAnalysisReadingClinicalDataInDto inDto);
} }
} }
@@ -65,7 +65,9 @@ namespace IRaCIS.Core.Application.Service
.WhereIf(inDto.LanguageType != null, x => x.LanguageType == inDto.LanguageType!.Value) .WhereIf(inDto.LanguageType != null, x => x.LanguageType == inDto.LanguageType!.Value)
.ProjectTo<ReadingMedicineSystemQuestionView>(_mapper.ConfigurationProvider).OrderBy(x => x.ShowOrder); .ProjectTo<ReadingMedicineSystemQuestionView>(_mapper.ConfigurationProvider).OrderBy(x => x.ShowOrder);
return await query.ToPagedListAsync(inDto.PageIndex, inDto.PageSize, new string[2] { "LanguageType desc", "ShowOrder asc" }); var defalutSortArray = new string[] { nameof(ReadingMedicineSystemQuestionView.LanguageType) + " desc", nameof(ReadingMedicineSystemQuestionView.ShowOrder) };
return await query.ToPagedListAsync(inDto, defalutSortArray);
} }
/// <summary> /// <summary>
@@ -398,7 +398,7 @@ namespace IRaCIS.Core.Application.Contracts
var result = await _trialSiteSurveyRepository.Where(t => t.Id == trialSiteSurveyId && t.TrialId == trialId).IgnoreQueryFilters() var result = await _trialSiteSurveyRepository.Where(t => t.Id == trialSiteSurveyId && t.TrialId == trialId).IgnoreQueryFilters()
.ProjectTo<LoginReturnDTO>(_mapper.ConfigurationProvider, new { isEn_Us = _userInfo.IsEn_Us }).FirstOrDefaultAsync().IfNullThrowException(); .ProjectTo<LoginReturnDTO>(_mapper.ConfigurationProvider, new { isEn_Us = _userInfo.IsEn_Us }).FirstOrDefaultAsync().IfNullThrowException();
var siteSurveryConfig = _trialSiteSurveyRepository.Where(t => t.Id == trialSiteSurveyId).Select(t => t.Trial.TrialExtraConfigJsonStr).FirstOrDefault()??string.Empty; var siteSurveryConfig = _trialSiteSurveyRepository.Where(t => t.Id == trialSiteSurveyId).IgnoreQueryFilters().Select(t => t.Trial.TrialExtraConfigJsonStr).FirstOrDefault()??string.Empty;
result.SiteSurveyFiledConfig = JsonConvert.DeserializeObject<TrialExtraConfig>(siteSurveryConfig) ?? new TrialExtraConfig(); result.SiteSurveyFiledConfig = JsonConvert.DeserializeObject<TrialExtraConfig>(siteSurveryConfig) ?? new TrialExtraConfig();
return result; return result;
@@ -279,6 +279,8 @@ namespace IRaCIS.Core.Application.Contracts
public CriterionType? CriterionType { get; set; } public CriterionType? CriterionType { get; set; }
public string? PM_EMail { get; set; } public string? PM_EMail { get; set; }
public List<Guid> TrialIdList { get; set; }=new List<Guid>();
} }
public class TrialToBeDoneDto : TrialBaseInfoDto public class TrialToBeDoneDto : TrialBaseInfoDto
@@ -23,6 +23,8 @@ using IRaCIS.Application.Contracts;
using SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors; using SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors;
using Newtonsoft.Json; using Newtonsoft.Json;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using IRaCIS.Core.Application.Helper;
using ZiggyCreatures.Caching.Fusion;
namespace IRaCIS.Core.Application namespace IRaCIS.Core.Application
{ {
@@ -1239,7 +1241,7 @@ namespace IRaCIS.Core.Application
} }
await _provider.SetAsync(trialId.ToString(), trialStatusStr, TimeSpan.FromDays(7)); await _fusionCache.SetAsync(CacheKeys.Trial(trial.Id.ToString()), trialStatusStr, TimeSpan.FromDays(7));
await _repository.SaveChangesAsync(); await _repository.SaveChangesAsync();
@@ -1390,7 +1392,7 @@ namespace IRaCIS.Core.Application
{ {
var trialCode = await _trialRepository.Where(t => t.Id == trialId).Select(t => t.TrialCode).FirstOrDefaultAsync(); var trialCode = await _trialRepository.Where(t => t.Id == trialId).Select(t => t.TrialCode).FirstOrDefaultAsync();
return new TrialPacsInfo() { Ip=optionsMonitor.CurrentValue.IP,Port=optionsMonitor.CurrentValue.Port,TrialCalledAE=$"EI{trialCode}" }; return new TrialPacsInfo() { Ip = optionsMonitor.CurrentValue.IP, Port = optionsMonitor.CurrentValue.Port, TrialCalledAE = $"EI{trialCode}" };
} }
} }
} }
@@ -46,7 +46,7 @@ namespace IRaCIS.Core.Application.Service
var pageList = await dicomAEQueryable.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField == string.Empty ? nameof(DicomAEView.CalledAE) : inQuery.SortField, inQuery.Asc); var pageList = await dicomAEQueryable.ToPagedListAsync(inQuery);
return ResponseOutput.Ok(pageList); return ResponseOutput.Ok(pageList);
@@ -12,6 +12,8 @@ using Microsoft.AspNetCore.Authorization;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Linq; using System.Linq;
using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Application.Helper;
using ZiggyCreatures.Caching.Fusion;
namespace IRaCIS.Application.Services namespace IRaCIS.Application.Services
{ {
@@ -69,7 +71,7 @@ namespace IRaCIS.Application.Services
} }
var query = _trialRepository.AsQueryable().IgnoreQueryFilters() var query = _trialRepository.AsQueryable()
.WhereIf(!string.IsNullOrEmpty(searchParam.TrialStatusStr), o => o.TrialStatusStr.Contains(searchParam.TrialStatusStr)) .WhereIf(!string.IsNullOrEmpty(searchParam.TrialStatusStr), o => o.TrialStatusStr.Contains(searchParam.TrialStatusStr))
.WhereIf(searchParam.SponsorId != null, o => o.SponsorId == searchParam.SponsorId) .WhereIf(searchParam.SponsorId != null, o => o.SponsorId == searchParam.SponsorId)
.WhereIf(searchParam.Expedited != null, o => o.Expedited == searchParam.Expedited) .WhereIf(searchParam.Expedited != null, o => o.Expedited == searchParam.Expedited)
@@ -93,7 +95,7 @@ namespace IRaCIS.Application.Services
.WhereIf(multiCriteriaSelectCount > 0, t => t.TrialDicList.Count(t => t.KeyName == StaticData.Criterion) == multiCriteriaSelectCount) .WhereIf(multiCriteriaSelectCount > 0, t => t.TrialDicList.Count(t => t.KeyName == StaticData.Criterion) == multiCriteriaSelectCount)
.WhereIf(multiReviewTypeSelectCount > 0, t => t.TrialDicList.Count(t => t.KeyName == StaticData.ReviewType) == multiReviewTypeSelectCount) .WhereIf(multiReviewTypeSelectCount > 0, t => t.TrialDicList.Count(t => t.KeyName == StaticData.ReviewType) == multiReviewTypeSelectCount)
.WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin, t => t.TrialUserList.Any(t => t.UserId == _userInfo.Id && t.IsDeleted == false) && t.IsDeleted == false) .WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin, t => t.TrialUserList.Any(t => t.UserId == _userInfo.Id && t.IsDeleted == false) && t.IsDeleted == false)
.ProjectTo<TrialDetailDTO>(_mapper.ConfigurationProvider, new { userTypeEnumInt = _userInfo.UserTypeEnumInt, userId = _userInfo.Id , isEn_Us= _userInfo.IsEn_Us }); .ProjectTo<TrialDetailDTO>(_mapper.ConfigurationProvider, new { userTypeEnumInt = _userInfo.UserTypeEnumInt, userId = _userInfo.Id, isEn_Us = _userInfo.IsEn_Us });
return await query.ToPagedListAsync(searchParam.PageIndex, searchParam.PageSize, string.IsNullOrWhiteSpace(searchParam.SortField) ? "CreateTime" : searchParam.SortField, searchParam.Asc); return await query.ToPagedListAsync(searchParam.PageIndex, searchParam.PageSize, string.IsNullOrWhiteSpace(searchParam.SortField) ? "CreateTime" : searchParam.SortField, searchParam.Asc);
@@ -103,7 +105,7 @@ namespace IRaCIS.Application.Services
//过滤废除的项目 //过滤废除的项目
public async Task<List<TrialSelectDTO>> GetTrialSelect() public async Task<List<TrialSelectDTO>> GetTrialSelect()
{ {
return await _trialRepository.AsQueryable().IgnoreQueryFilters() return await _trialRepository.AsQueryable()
.WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin && _userInfo.UserTypeEnumInt != (int)UserTypeEnum.Admin && _userInfo.UserTypeEnumInt != (int)UserTypeEnum.OP, t => t.TrialUserList.Any(t => t.UserId == _userInfo.Id) && t.IsDeleted == false) .WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin && _userInfo.UserTypeEnumInt != (int)UserTypeEnum.Admin && _userInfo.UserTypeEnumInt != (int)UserTypeEnum.OP, t => t.TrialUserList.Any(t => t.UserId == _userInfo.Id) && t.IsDeleted == false)
.ProjectTo<TrialSelectDTO>(_mapper.ConfigurationProvider).ToListAsync(); .ProjectTo<TrialSelectDTO>(_mapper.ConfigurationProvider).ToListAsync();
@@ -119,7 +121,7 @@ namespace IRaCIS.Application.Services
[HttpGet("{projectId:guid}")] [HttpGet("{projectId:guid}")]
public async Task<TrialDetailDTO> GetTrialInfoAndLockState(Guid projectId) public async Task<TrialDetailDTO> GetTrialInfoAndLockState(Guid projectId)
{ {
return (await _trialRepository.Where(o => o.Id == projectId).IgnoreQueryFilters().ProjectTo<TrialDetailDTO>(_mapper.ConfigurationProvider, new {isEn_Us = _userInfo.IsEn_Us }).FirstOrDefaultAsync()).IfNullThrowException(); return (await _trialRepository.Where(o => o.Id == projectId).ProjectTo<TrialDetailDTO>(_mapper.ConfigurationProvider, new { isEn_Us = _userInfo.IsEn_Us }).FirstOrDefaultAsync()).IfNullThrowException();
} }
@@ -216,7 +218,7 @@ namespace IRaCIS.Application.Services
await _repository.AddAsync(new TrialPaymentPrice() { TrialId = trial.Id }); await _repository.AddAsync(new TrialPaymentPrice() { TrialId = trial.Id });
//添加访视 //添加访视
await _repository.AddAsync(new VisitStage { TrialId = trial.Id, VisitNum = 0, BlindName = "B" + 0.ToString("D3"), VisitDay = 0, VisitName = "Baseline", IsBaseLine = true,VisitWindowLeft=-28,VisitWindowRight=0 }); await _repository.AddAsync(new VisitStage { TrialId = trial.Id, VisitNum = 0, BlindName = "B" + 0.ToString("D3"), VisitDay = 0, VisitName = "Baseline", IsBaseLine = true, VisitWindowLeft = -28, VisitWindowRight = 0 });
await _repository.AddAsync(new VisitStage { TrialId = trial.Id, VisitNum = 1, BlindName = "B" + 10.ToString("D3"), VisitDay = 30, VisitName = "Visit 1", VisitWindowLeft = -5, VisitWindowRight = 5 }); await _repository.AddAsync(new VisitStage { TrialId = trial.Id, VisitNum = 1, BlindName = "B" + 10.ToString("D3"), VisitDay = 30, VisitName = "Visit 1", VisitWindowLeft = -5, VisitWindowRight = 5 });
@@ -236,10 +238,9 @@ namespace IRaCIS.Application.Services
} }
await _repository.AddRangeAsync(needAddBodyPartList,true); await _repository.AddRangeAsync(needAddBodyPartList, true);
await _fusionCache.SetAsync(CacheKeys.Trial(trial.Id.ToString()), StaticData.TrialState.TrialInitializing, TimeSpan.FromDays(7));
_provider.Set(trial.Id.ToString(), StaticData.TrialState.TrialInitializing, TimeSpan.FromDays(7));
return ResponseOutput.Ok(trial); return ResponseOutput.Ok(trial);
} }
@@ -589,7 +590,7 @@ namespace IRaCIS.Application.Services
await _repository.BatchDeleteAsync<VisitTaskReReading>(t => t.OriginalReReadingTask.TrialId == trialId); await _repository.BatchDeleteAsync<VisitTaskReReading>(t => t.OriginalReReadingTask.TrialId == trialId);
await _repository.BatchDeleteAsync<VisitTask>(t => t.TrialId == trialId); await _repository.BatchDeleteAsync<VisitTask>(t => t.TrialId == trialId);
await _repository.BatchDeleteAsync<TrialStateChange>(t => t.TrialId == trialId) ; await _repository.BatchDeleteAsync<TrialStateChange>(t => t.TrialId == trialId);
return ResponseOutput.Ok(); return ResponseOutput.Ok();
@@ -650,7 +651,7 @@ namespace IRaCIS.Application.Services
.WhereIf(!string.IsNullOrEmpty(searchModel.Code), o => o.TrialCode.Contains(searchModel.Code)) .WhereIf(!string.IsNullOrEmpty(searchModel.Code), o => o.TrialCode.Contains(searchModel.Code))
.WhereIf(!string.IsNullOrWhiteSpace(searchModel.Indication), o => o.Indication.Contains(searchModel.Indication)) .WhereIf(!string.IsNullOrWhiteSpace(searchModel.Indication), o => o.Indication.Contains(searchModel.Indication))
.WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin, t => t.TrialUserList.Any(t => t.UserId == _userInfo.Id)) .WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin, t => t.TrialUserList.Any(t => t.UserId == _userInfo.Id))
.ProjectTo<TrialDetailDTO>(_mapper.ConfigurationProvider, new { userTypeEnumInt = _userInfo.UserTypeEnumInt, userId = _userInfo.Id ,isEn_Us = _userInfo.IsEn_Us }); .ProjectTo<TrialDetailDTO>(_mapper.ConfigurationProvider, new { userTypeEnumInt = _userInfo.UserTypeEnumInt, userId = _userInfo.Id, isEn_Us = _userInfo.IsEn_Us });
return await query.ToPagedListAsync(searchModel.PageIndex, searchModel.PageSize, string.IsNullOrWhiteSpace(searchModel.SortField) ? "CreateTime" : searchModel.SortField, searchModel.Asc); return await query.ToPagedListAsync(searchModel.PageIndex, searchModel.PageSize, string.IsNullOrWhiteSpace(searchModel.SortField) ? "CreateTime" : searchModel.SortField, searchModel.Asc);
@@ -382,7 +382,7 @@ namespace IRaCIS.Application.Contracts
} }
public class SubmitVisitStudyBindingCommand public class VerifyPacsImageCommand
{ {
[NotDefault] [NotDefault]
public Guid TrialId { get; set; } public Guid TrialId { get; set; }
@@ -396,6 +396,13 @@ namespace IRaCIS.Application.Contracts
public List<Guid> SCPStudyIdList { get; set; } public List<Guid> SCPStudyIdList { get; set; }
} }
public class SubmitVisitStudyBindingCommand: VerifyPacsImageCommand
{
public List<Guid> ReUploadSCPStudyIdList { get; set; }
}
public class SubjectVisitSelectQuery public class SubjectVisitSelectQuery
{ {
[NotDefault] [NotDefault]
@@ -1,4 +1,5 @@
using IRaCIS.Core.Infrastructure.Extention; using IRaCIS.Core.Infrastructure.Extention;
using MiniExcelLibs.Attributes;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
namespace IRaCIS.Application.Contracts namespace IRaCIS.Application.Contracts
@@ -103,5 +104,53 @@ namespace IRaCIS.Application.Contracts
public int InconsistentCount { get; set; } public int InconsistentCount { get; set; }
} }
public class VisitPlanInfluenceSubjectVisitDTO
{
[ExcelColumn(Ignore = true)]
public Guid StudyId { get; set; }
[ExcelColumn(Ignore = true)]
public Guid TrialId { get; set; }
[ExcelColumn(Ignore = true)]
public Guid SubjectVisitId { get; set; }
[ExcelColumnName("中心编号")]
public string TrialSiteCode { get; set; } = string.Empty;
[ExcelColumnName("受试者")]
public string SubjectCode { get; set; } = string.Empty;
[ExcelColumnName("访视名称")]
public string VisitName { get; set; } = string.Empty;
[ExcelColumn(Name = "检查时间", Format = "yyyy-MM-dd HH:mm:ss")]
public DateTime StudyTime { get; set; }
[ExcelColumnName("检查技术")]
public string Modality { get; set; } = string.Empty;
[ExcelColumn(Ignore = true)]
public bool IsDicomStudy { get; set; }
[ExcelColumnName("影像类型")]
public string ImageType => IsDicomStudy ? "Dicom" : "非Dicom";
[ExcelColumnName("历史窗口")]
public string HistoryWindow { get; set; } = string.Empty;
[ExcelColumnName("之前超窗调整后没超窗")]
public bool IsOverWindowNowNotOverWindow { get; set; }
[ExcelColumnName("目前窗口")]
public string NowWindow { get; set; } = string.Empty;
[ExcelColumn(Ignore = true)]
public DateTime CreateTime { get; set; }
}
} }
@@ -264,7 +264,7 @@ namespace IRaCIS.Core.Application.Contracts
public bool IsCriticalSequence { get; set; } = false; public bool IsCriticalSequence { get; set; } = false;
public int SeriesCount =>SeriesList.Count; public int SeriesCount => SeriesList.Count;
public int InstanceCount { get; set; } public int InstanceCount { get; set; }
public bool IsDicom { get; set; } = true; public bool IsDicom { get; set; } = true;
@@ -369,6 +369,16 @@ namespace IRaCIS.Core.Application.Contracts
public List<string> SOPInstanceUIDList { get; set; } public List<string> SOPInstanceUIDList { get; set; }
} }
public class VerifySCPStudyUploadResult
{
public Guid SCPStudyId { get; set; }
public string ErrorMesseage { get; set; } = String.Empty;
public bool AllowUpload { get; set; } = false;
public bool AllowReUpload { get; set; } = false;
}
public class VerifyStudyUploadResult public class VerifyStudyUploadResult
{ {
@@ -54,10 +54,12 @@ namespace IRaCIS.Application.Services
private readonly IRepository<SCPStudy> _scpStudyRepository; private readonly IRepository<SCPStudy> _scpStudyRepository;
private readonly IRepository<Subject> _subjectRepository; private readonly IRepository<Subject> _subjectRepository;
private readonly IRepository<SubjectVisit> _subjectVisitRepository; private readonly IRepository<SubjectVisit> _subjectVisitRepository;
private readonly IRepository<Dictionary> _dictionaryRepository;
private readonly IDistributedLockProvider _distributedLockProvider; private readonly IDistributedLockProvider _distributedLockProvider;
public PatientService(IRepository<SCPStudy> studyRepository, IRepository<Trial> trialRepository, IRepository<SCPPatient> patientRepository, IRepository<Subject> subjectRepository, IRepository<SubjectVisit> subjectVisitRepository, IDistributedLockProvider distributedLockProvider) public PatientService(IRepository<SCPStudy> studyRepository, IRepository<Dictionary> dictionaryRepository, IRepository<Trial> trialRepository, IRepository<SCPPatient> patientRepository, IRepository<Subject> subjectRepository, IRepository<SubjectVisit> subjectVisitRepository, IDistributedLockProvider distributedLockProvider)
{ {
_dictionaryRepository = dictionaryRepository;
_scpStudyRepository = studyRepository; _scpStudyRepository = studyRepository;
_trialRepository = trialRepository; _trialRepository = trialRepository;
_patientRepository = patientRepository; _patientRepository = patientRepository;
@@ -75,7 +77,7 @@ namespace IRaCIS.Application.Services
[HttpPost] [HttpPost]
public async Task<IResponseOutput<PageOutput<SCPImageUploadView>>> GetSCPImageUploadList(SCPImageUploadQuery inQuery) public async Task<IResponseOutput<PageOutput<SCPImageUploadView>>> GetSCPImageUploadList(SCPImageUploadQuery inQuery)
{ {
var query = _repository.Where<SCPImageUpload>(t=>t.TrialId==inQuery.TrialId) var query = _repository.Where<SCPImageUpload>(t => t.TrialId == inQuery.TrialId)
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.CalledAE), t => t.CalledAE.Contains(inQuery.CalledAE)) .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.CallingAEIP), t => t.CallingAEIP.Contains(inQuery.CallingAEIP))
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.CallingAE), t => t.CallingAE.Contains(inQuery.CallingAE)) .WhereIf(!string.IsNullOrWhiteSpace(inQuery.CallingAE), t => t.CallingAE.Contains(inQuery.CallingAE))
@@ -283,23 +285,126 @@ namespace IRaCIS.Application.Services
public async Task<List<VerifySCPStudyUploadResult>> VerifyPacsImage(VerifyPacsImageCommand inCommand)
{
var trialId = inCommand.TrialId;
var subjectId = inCommand.SubjectId;
var isVerifyVisitImageDate = await _repository.Where<Trial>(t => t.Id == inCommand.TrialId).Select(t => t.IsVerifyVisitImageDate).FirstNotNullAsync();
var result = new List<VerifySCPStudyUploadResult>();
var visitList = _repository.Where<SubjectVisit>(t => t.SubjectId == inCommand.SubjectId).Select(t => new { t.VisitNum, t.EarliestScanDate, t.LatestScanDate, t.Id }).ToList();
var currentVisitNum = visitList.First(t => t.Id == inCommand.SubjectVisitId).VisitNum;
var scpStudyList = _scpStudyRepository.Where(t => inCommand.SCPStudyIdList.Contains(t.Id)).Select(t => new { StudyDate = t.StudyTime, t.Id }).ToList();
foreach (var waitUploadItem in scpStudyList)
{
if (isVerifyVisitImageDate)
{
//小于当前访视 最近的最晚拍片
var before = visitList.Where(u => u.VisitNum < currentVisitNum).Max(k => k.LatestScanDate);
if (before != null && waitUploadItem.StudyDate != null && before > waitUploadItem.StudyDate)
{
// $"当前访视检查时间{waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")}不能早于前序访视检查时间{before?.ToString("yyyy-MM-dd")},请核对检查数据是否有误",
result.Add(new VerifySCPStudyUploadResult() { SCPStudyId = waitUploadItem.Id, ErrorMesseage = _localizer["Study_VisitBeforePrevError", waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")!, before?.ToString("yyyy-MM-dd")!] });
continue; // 跳过当前迭代
}
//大于当前访视 最近的最早拍片日期
var after = visitList.Where(u => u.VisitNum > currentVisitNum).Min(k => k.EarliestScanDate);
if (after != null && waitUploadItem.StudyDate != null && after < waitUploadItem.StudyDate)
{
// $"当前访视检查时间{waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")}不能晚于该访视之后的检查时间{after?.ToString("yyyy-MM-dd")},请核对检查数据是否有误"
result.Add(new VerifySCPStudyUploadResult() { SCPStudyId = waitUploadItem.Id, ErrorMesseage = _localizer["Study_VisitAfterSubseqError", waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")!, after?.ToString("yyyy-MM-dd")!] });
continue; // 跳过当前迭代
}
}
var verifyStudyInfo = _repository.Where<DicomStudy>(t => t.TrialId == trialId && t.Id == waitUploadItem.Id).ProjectTo<VerifyStudyDto>(_mapper.ConfigurationProvider).FirstOrDefault();
var currentStudyResult = new VerifySCPStudyUploadResult() { SCPStudyId = waitUploadItem.Id };
//数据库不存在该检查 允许上传
if (verifyStudyInfo == null)
{
currentStudyResult.AllowUpload = true;
}
//数据库该项目有该检查 看是否支持重传
else
{
//是同一个受试者 支持重传
if (verifyStudyInfo.SubjectId == subjectId && verifyStudyInfo.SubjectVisitId == inCommand.SubjectVisitId)
{
currentStudyResult.AllowReUpload = true;
}
//不是同一个受试者
else
{
//有默认值,其实不用写,这里为了好理解
currentStudyResult.AllowUpload = false;
currentStudyResult.AllowReUpload = false;
//$"此处不可以上传。当前影像检查已经上传给受试者{verifyStudyInfo.SubjectCode}的{verifyStudyInfo.VisitName}"
currentStudyResult.ErrorMesseage = _localizer["Study_ImgAlreadyUploaded", verifyStudyInfo.SubjectCode, verifyStudyInfo.VisitName];
}
}
result.Add(currentStudyResult);
}
return result;
}
/// <summary> /// <summary>
/// 提交 患者检查和访视的绑定 /// 提交 患者检查和访视的绑定
/// </summary> /// </summary>
/// <param name="inCommand"></param> /// <param name="inCommand"></param>
/// <param name="_dicomstudyRepository"></param>
/// <param name="_dicomSeriesRepository"></param>
/// <param name="_dicomInstanceRepository"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost] [HttpPost]
[UnitOfWork] [UnitOfWork]
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
public async Task<IResponseOutput> SubmitVisitStudyBinding(SubmitVisitStudyBindingCommand inCommand) public async Task<IResponseOutput> SubmitVisitStudyBinding(SubmitVisitStudyBindingCommand inCommand,
[FromServices] IRepository<DicomStudy> _dicomstudyRepository,
[FromServices] IRepository<DicomSeries> _dicomSeriesRepository,
[FromServices] IRepository<DicomInstance> _dicomInstanceRepository)
{ {
//这里要做校验 + 同时验证本地系统里面的影像是否存在pacs推过来的
var copyCommand = inCommand.Clone();
copyCommand.SCPStudyIdList = inCommand.SCPStudyIdList.Union(inCommand.ReUploadSCPStudyIdList).ToList();
var verifyResult = await VerifyPacsImage(copyCommand);
var allowUploadList = verifyResult.Where(u => u.AllowUpload == true).Select(t => t.SCPStudyId).ToList();
var allowReUploadList = verifyResult.Where(u => u.AllowReUpload == true).Select(t => t.SCPStudyId).ToList();
if (!(inCommand.SCPStudyIdList.All(t => allowUploadList.Contains(t)) && inCommand.ReUploadSCPStudyIdList.All(t => allowReUploadList.Contains(t))))
{
throw new BusinessValidationFailedException("对接提示: 前端提交的检查有不能上传的,请刷新页面调用验证接口重试!");
}
var subjectId = inCommand.SubjectId; var subjectId = inCommand.SubjectId;
var subjectVisitId = inCommand.SubjectVisitId; var subjectVisitId = inCommand.SubjectVisitId;
var trialId = inCommand.TrialId; var trialId = inCommand.TrialId;
var @lock = _distributedLockProvider.CreateLock($"StudyCode"); var @lock = _distributedLockProvider.CreateLock($"StudyCode");
using (await @lock.AcquireAsync()) using (await @lock.AcquireAsync())
@@ -308,6 +413,7 @@ namespace IRaCIS.Application.Services
int currentNextCodeInt = dbStudyCodeIntMax + 1; int currentNextCodeInt = dbStudyCodeIntMax + 1;
//新增的,上传的
foreach (var scpStudyId in inCommand.SCPStudyIdList) foreach (var scpStudyId in inCommand.SCPStudyIdList)
{ {
@@ -315,7 +421,6 @@ namespace IRaCIS.Application.Services
if (find != null) if (find != null)
{ {
var newStuty = _mapper.Map<DicomStudy>(find.SCPStudy); var newStuty = _mapper.Map<DicomStudy>(find.SCPStudy);
await _repository.AddAsync(newStuty); await _repository.AddAsync(newStuty);
@@ -362,6 +467,93 @@ namespace IRaCIS.Application.Services
} }
foreach (var scpStudyId in inCommand.ReUploadSCPStudyIdList)
{
var study = await _dicomstudyRepository.FirstOrDefaultAsync(t => t.Id == scpStudyId);
var instanceIdList = _dicomInstanceRepository.Where(t => t.Id == scpStudyId).Select(t => t.Id).ToList();
var scpStudy = _scpStudyRepository.Where(t => t.Id == scpStudyId).Include(t => t.SeriesList).ThenInclude(t => t.SCPInstanceList).FirstOrDefault();
//以最后一次为准
study.IsFromPACS = true;
//特殊处理逻辑
study.Modalities = string.Join("、", scpStudy.SeriesList.Select(t => t.Modality).Union(study.Modalities.Split("、", StringSplitOptions.RemoveEmptyEntries)).Distinct());
SpecialArchiveStudyDeal(study);
// 少了整个序列
//某个序列下少了instance
foreach (var seriesItem in scpStudy.SeriesList)
{
var seriesId = IdentifierHelper.CreateGuid(seriesItem.StudyInstanceUid, seriesItem.SeriesInstanceUid, trialId.ToString());
DicomSeries dicomSeries = await _dicomSeriesRepository.FirstOrDefaultAsync(t => t.Id == seriesId);
//判断重复
if (dicomSeries == null)
{
var series = _mapper.Map<DicomSeries>(seriesItem);
series.SeqId = Guid.Empty;
series.TrialId = trialId;
series.SubjectId = subjectId;
series.SubjectVisitId = subjectVisitId;
dicomSeries = await _dicomSeriesRepository.AddAsync(series);
foreach (var instanceItem in seriesItem.SCPInstanceList)
{
var instance = _mapper.Map<DicomInstance>(instanceItem);
instance.SeqId = Guid.Empty;
instance.TrialId = trialId;
instance.SubjectId = subjectId;
instance.SubjectVisitId = subjectVisitId;
await _dicomInstanceRepository.AddAsync(instance);
}
//新的序列 那么 检查的序列数量+1
study.SeriesCount += 1;
study.InstanceCount += seriesItem.SCPInstanceList.Count;
}
else
{
//该序列掉了instance
dicomSeries.InstanceCount += seriesItem.SCPInstanceList.Count;
var newInstanceList = seriesItem.SCPInstanceList.Where(t => !instanceIdList.Contains(t.Id));
foreach (var instanceItem in newInstanceList)
{
var instance = _mapper.Map<DicomInstance>(instanceItem);
instance.SeqId = Guid.Empty;
instance.TrialId = trialId;
instance.SubjectId = subjectId;
instance.SubjectVisitId = subjectVisitId;
await _dicomInstanceRepository.AddAsync(instance);
}
study.InstanceCount += newInstanceList.Count();
}
}
await _repository.SaveChangesAsync();
await _repository.BatchUpdateAsync<SCPPatient>(t => t.Id == scpStudy.PatientId, u => new SCPPatient() { SubjectId = subjectId });
await _repository.BatchUpdateAsync<SCPStudy>(t => t.Id == scpStudyId, u => new SCPStudy() { SubjectVisitId = subjectVisitId });
}
} }
@@ -373,6 +565,43 @@ namespace IRaCIS.Application.Services
return ResponseOutput.Ok(); return ResponseOutput.Ok();
} }
private void SpecialArchiveStudyDeal(DicomStudy study)
{
#region
if (study.PatientBirthDate.Length == 8)
{
study.PatientBirthDate = $"{study.PatientBirthDate[0]}{study.PatientBirthDate[1]}{study.PatientBirthDate[2]}{study.PatientBirthDate[3]}-{study.PatientBirthDate[4]}{study.PatientBirthDate[5]}-{study.PatientBirthDate[6]}{study.PatientBirthDate[7]}";
}
var dicModalityList = _dictionaryRepository.Where(t => t.Code == "Modality").SelectMany(t => t.ChildList.Select(c => c.Value)).ToList();
var modality = study.Modalities;
var modalityForEdit = dicModalityList.Contains(modality) ? modality : String.Empty;
if (modality == "MR")
{
modalityForEdit = "MRI";
}
if (modality == "PT")
{
modalityForEdit = "PET";
}
if (modality == "PT、CT")
{
modalityForEdit = "PET-CT";
}
study.ModalityForEdit = modalityForEdit;
#endregion
}
#endregion #endregion
@@ -3,7 +3,6 @@ using IRaCIS.Application.Contracts;
using IRaCIS.Core.Application.Filter; using IRaCIS.Core.Application.Filter;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Application.MediatR.CommandAndQueries;
using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Infrastructure;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using IRaCIS.Core.Application.Auth; using IRaCIS.Core.Application.Auth;
@@ -2,7 +2,6 @@
using IRaCIS.Application.Contracts; using IRaCIS.Application.Contracts;
using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Contracts.Dicom.DTO; using IRaCIS.Core.Application.Contracts.Dicom.DTO;
using IRaCIS.Core.Application.MediatR.CommandAndQueries;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
namespace IRaCIS.Core.Application.Service namespace IRaCIS.Core.Application.Service
@@ -1,176 +0,0 @@
using IRaCIS.Core.Domain.Share;
using MediatR;
using MiniExcelLibs.Attributes;
using System.ComponentModel.DataAnnotations;
using System.Linq;
namespace IRaCIS.Core.Application.MediatR.CommandAndQueries
{
public class ConsistencyVerificationRequest : IRequest<string>
{
public List<CheckViewModel> ETCList { get; set; } = new List<CheckViewModel>();
public Guid TrialId { get; set; }
}
public class CheckDBModel : CheckViewModel
{
public Guid SubjectVisitId { get; set; }
public Guid StudyId { get; set; }
}
//public class ImportResultFilteTest : IImportResultFilter
//{
// public ImportResult<T> Filter<T>(ImportResult<T> importResult) where T : class, new()
// {
// if (typeof(T).IsAssignableFrom(typeof(CheckViewModel)))
// {
// var data = (List<CheckViewModel>)importResult.Data;
// var dt = DateTime.Now ;
// foreach (var item in data)
// {
// var index= data.IndexOf(item);
// if ( DateTime.TryParse(item.StudyDate, out dt) == false)
// {
// importResult.RowErrors.Add(new DataRowErrorInfo() { RowIndex = index, FieldErrors = new Dictionary<string, string> { { StaticData.International("ConsistencyVerification_Tech") , StaticData.International("ConsistencyVerification_Time") } } });
// }
// }
// }
// return importResult;
// }
//}
public class ParamInfoDto
{
public string Modality { get; set; }
public string StudyDate { get; set; }
//public int ErrorType { get; set; }
}
//[ExcelImporter(/*ImportResultFilter = typeof(ImportResultFilteTest),*/ IsLabelingError = true)]
public class CheckViewModel
{
//[Required(ErrorMessage = "中心编号不能为空")]
//[ImporterHeader(Name = "Site ID", AutoTrim = true)]
[ExcelColumnName("Site ID")]
public string SiteCode { get; set; } = string.Empty;
//[Required(ErrorMessage = "受试者筛选号不能为空")]
//[ImporterHeader(Name = "Subject ID", AutoTrim = true)]
[ExcelColumnName("Subject ID")]
public string SubjectCode { get; set; } = string.Empty;
//[Required(ErrorMessage = "访视名称不能为空")]
//[ImporterHeader(Name = "Visit Name", AutoTrim = true)]
[ExcelColumnName("Visit Name")]
public string VisitName { get; set; } = string.Empty;
//[Required(ErrorMessage = "检查日期不能为空")]
[CanConvertToTime(ErrorMessage = "Does not conform to Study Date format")]
//[ImporterHeader(Name = "Study Date", AutoTrim = true)]
[ExcelColumnName("Study Date")]
public string StudyDate { get; set; } = string.Empty;
//[Required(ErrorMessage = "Modality不能为空")]
//[ImporterHeader(Name = "Modality", AutoTrim = true)]
[ExcelColumnName("Modality")]
public string Modality { get; set; } = string.Empty;
public override bool Equals(object? obj)
{
if (obj == null) return false;
var checkModel = obj as CheckViewModel;
if (checkModel is not null)
{
return SiteCode == checkModel.SiteCode && SubjectCode == checkModel.SubjectCode && VisitName == checkModel.VisitName && StudyDate == checkModel.StudyDate && Modality == checkModel.Modality;
}
else
{
return false;
}
}
public override int GetHashCode()
{
return (SiteCode + SubjectCode + VisitName + StudyDate + Modality).GetHashCode();
}
}
public class VisitPlanInfluenceSubjectVisitDTO
{
[ExcelColumn(Ignore = true)]
public Guid StudyId { get; set; }
[ExcelColumn(Ignore = true)]
public Guid TrialId { get; set; }
[ExcelColumn(Ignore = true)]
public Guid SubjectVisitId { get; set; }
[ExcelColumnName("中心编号")]
public string TrialSiteCode { get; set; } = string.Empty;
[ExcelColumnName("受试者")]
public string SubjectCode { get; set; } = string.Empty;
[ExcelColumnName("访视名称")]
public string VisitName { get; set; } = string.Empty;
[ExcelColumn(Name = "检查时间", Format = "yyyy-MM-dd HH:mm:ss")]
public DateTime StudyTime { get; set; }
[ExcelColumnName("检查技术")]
public string Modality { get; set; } = string.Empty;
[ExcelColumn(Ignore = true)]
public bool IsDicomStudy { get; set; }
[ExcelColumnName("影像类型")]
public string ImageType => IsDicomStudy ? "Dicom" : "非Dicom";
[ExcelColumnName("历史窗口")]
public string HistoryWindow { get; set; } = string.Empty;
[ExcelColumnName("之前超窗调整后没超窗")]
public bool IsOverWindowNowNotOverWindow { get; set; }
[ExcelColumnName("目前窗口")]
public string NowWindow { get; set; } = string.Empty;
[ExcelColumn(Ignore =true)]
public DateTime CreateTime { get; set; }
}
}
@@ -1,44 +0,0 @@
using EasyCaching.Core;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore;
using MediatR;
namespace IRaCIS.Core.Application.MediatR.Handlers
{
public class AnonymizeCacheRequest : IRequest<bool>
{
}
public class AnonymizeCacheHandler : IRequestHandler<AnonymizeCacheRequest,bool>
{
private readonly IRepository _repository;
private readonly IEasyCachingProvider _provider;
/// <summary>
/// 构造函数注入
/// </summary>
public AnonymizeCacheHandler(IRepository repository, IEasyCachingProvider provider)
{
_repository = repository;
_provider = provider;
}
public Task<bool> Handle(AnonymizeCacheRequest request, CancellationToken cancellationToken)
{
var systemAnonymizationList = _repository.Where<SystemAnonymization>(t => t.IsEnable).ToList();
_provider.Set(StaticData.Anonymize.Anonymize_AddFixedFiled, systemAnonymizationList.Where(t => t.IsAdd && t.IsFixed).ToList(), TimeSpan.FromDays(7));
_provider.Set(StaticData.Anonymize.Anonymize_AddIRCInfoFiled, systemAnonymizationList.Where(t => t.IsAdd && t.IsFixed == false).ToList(), TimeSpan.FromDays(7));
_provider.Set(StaticData.Anonymize.Anonymize_FixedField, systemAnonymizationList.Where(t => t.IsAdd == false && t.IsFixed).ToList(), TimeSpan.FromDays(7));
_provider.Set(StaticData.Anonymize.Anonymize_IRCInfoField, systemAnonymizationList.Where(t => t.IsAdd == false && t.IsFixed == false).ToList(), TimeSpan.FromDays(7));
return Task.FromResult(true);
}
}
}
@@ -1,45 +0,0 @@
using EasyCaching.Core;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore;
using MediatR;
namespace IRaCIS.Core.Application.MediatR.Handlers
{
public class TrialStateCacheRequest : IRequest<bool>
{
}
public class TrialStateCacheHandler : IRequestHandler<TrialStateCacheRequest, bool>
{
private readonly IRepository<Trial> _trialRepository;
private readonly IEasyCachingProvider _provider;
/// <summary>
/// 构造函数注入
/// </summary>
public TrialStateCacheHandler(IRepository<Trial> trialRepository, IEasyCachingProvider provider)
{
_trialRepository = trialRepository;
_provider = provider;
}
public async Task<bool> Handle(TrialStateCacheRequest request, CancellationToken cancellationToken)
{
//项目启动,将项目状态缓存,因为hangfire 加入后台任务,还是向队列添加任务,执行都有延迟,效果不好
var list = await _trialRepository.Select(t => new { TrialId = t.Id, TrialStatusStr = t.TrialStatusStr }).ToListAsync();
// 每天都会有任务刷新状态,项目编辑 添加时 都会处理到缓存中
list.ForEach(t => _provider.Set(t.TrialId.ToString(), t.TrialStatusStr, TimeSpan.FromDays(7)));
return true;
}
}
}
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Domain.BaseModel
{
/// <summary>
/// 领域实体事件基类
/// </summary>
public abstract class DomainEvent
{
}
public class FailedDomainEvent
{
public Guid Id { get; set; }
public string EventType { get; set; }
public string EventData { get; set; }
public DateTime FailedAt { get; set; }
}
}
+42 -5
View File
@@ -1,21 +1,58 @@
using System; using IRaCIS.Core.Domain.BaseModel;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using System.Security.Cryptography;
namespace IRaCIS.Core.Domain.Models namespace IRaCIS.Core.Domain.Models
{ {
public interface IAggregateRoot;
public interface IEntity<TKey>
{
abstract TKey Id { get; set; }
}
public abstract class Entity : IEntity<Guid> public abstract class Entity : IEntity<Guid>
{ {
[Key] [Key]
[Required] [Required]
[DatabaseGenerated(DatabaseGeneratedOption.None)] [DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid Id { get; set; } public Guid Id { get; set; }
#region
private readonly List<DomainEvent> _domainEvents = [];
[NotMapped]
public IReadOnlyCollection<DomainEvent> DomainEvents => _domainEvents.AsReadOnly();
public void AddDomainEvent(DomainEvent domainEvent)
{
_domainEvents.Add(domainEvent);
}
public void RemoveDomainEvent(DomainEvent domainEvent)
{
_domainEvents.Remove(domainEvent);
}
public void ClearDomainEvents()
{
_domainEvents.Clear();
}
#endregion
} }
public interface IEntity<TKey>
{
abstract TKey Id { get; set; }
}
#region #region
@@ -158,7 +158,8 @@ namespace IRaCIS.Core.Infra.EFCore.Common
t.IsTrialBasicLogicConfirmed, t.IsTrialBasicLogicConfirmed,
t.IsTrialProcessConfirmed, t.IsTrialProcessConfirmed,
t.IsTrialUrgentConfirmed, t.IsTrialUrgentConfirmed,
t.IsConfigureEmail t.IsConfigureEmail,
t.IsTrialPACSConfirmed,
}).FirstOrDefaultAsync(); }).FirstOrDefaultAsync();
switch (_userInfo.RequestUrl) switch (_userInfo.RequestUrl)
{ {
@@ -172,6 +173,9 @@ namespace IRaCIS.Core.Infra.EFCore.Common
case "configTrialBasicInfo/ConfigTrialUrgentInfoConfirm": case "configTrialBasicInfo/ConfigTrialUrgentInfoConfirm":
extraIdentification = $"/{oldentity.IsTrialUrgentConfirmed.ToString()}"; extraIdentification = $"/{oldentity.IsTrialUrgentConfirmed.ToString()}";
break; break;
case "configTrialBasicInfo/ConfigTrialPACSInfoConfirm":
extraIdentification = $"/{oldentity.IsTrialPACSConfirmed.ToString()}";
break;
case "TrialEmailNoticeConfig/setTrialEmail": case "TrialEmailNoticeConfig/setTrialEmail":
@@ -511,7 +511,6 @@ namespace IRaCIS.Core.Infra.EFCore
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken()) public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
{ {
// 采用触发器的方式 设置 CreateUserId CreateTime UpdateTime UpdateUserId 稽查实体里面没有这四个字段的值 因为先后顺序的原因 // 采用触发器的方式 设置 CreateUserId CreateTime UpdateTime UpdateUserId 稽查实体里面没有这四个字段的值 因为先后顺序的原因
SetCommonEntityAuditInfo();
await AddAudit(); await AddAudit();
try try
@@ -595,85 +594,7 @@ namespace IRaCIS.Core.Infra.EFCore
} }
/// <summary>
/// 重写savechange方式 统一增加审计信息 CreateUserId CreateTime UpdateTime Update UserId
/// </summary>
private void SetCommonEntityAuditInfo()
{
ChangeTracker.DetectChanges(); // Important!
// 获取所有更改,删除,新增的实体,但排除审计实体(避免死循环)
var entities = ChangeTracker.Entries()
.Where(u => (u.State == EntityState.Modified || u.State == EntityState.Deleted || u.State == EntityState.Added)).Where(x => !typeof(DataInspection).IsAssignableFrom(x.Entity.GetType())).ToList();
foreach (var t in entities)
{
switch (t.State)
{
case EntityState.Deleted:
break;
case EntityState.Modified:
if (t.Entity is IAuditUpdate updateEntity1)
{
updateEntity1.UpdateTime = DateTime.Now;
updateEntity1.UpdateUserId = _userInfo.Id;
}
if (t.Entity is ISoftDelete softDelete)
{
if (softDelete.IsDeleted)
{
softDelete.DeleteUserId = _userInfo.Id;
softDelete.DeletedTime = DateTime.Now;
}
else
{
softDelete.DeletedTime = null;
}
}
break;
//添加的时候,更新审计字段也赋值
case EntityState.Added:
if (t.Entity is IAuditAdd addEntity)
{
if (addEntity.CreateTime == default(DateTime))
{
addEntity.CreateTime = DateTime.Now;
}
addEntity.CreateUserId = _userInfo.Id;
}
if (t.Entity is IAuditUpdate updateEntity)
{
updateEntity.UpdateTime = DateTime.Now;
updateEntity.UpdateUserId = _userInfo.Id;
}
if (t.Entity is IAuditAddWithUserName addEntity3)
{
if (addEntity3.CreateTime == default(DateTime))
{
addEntity3.CreateTime = DateTime.Now;
}
addEntity3.CreateUserId = _userInfo.Id;
addEntity3.CreateUser = _userInfo.RealName;
}
break;
}
}
}
public virtual DbSet<TaskAllocationRule> TaskAllocationRule { get; set; } public virtual DbSet<TaskAllocationRule> TaskAllocationRule { get; set; }
@@ -25,7 +25,6 @@
<PackageReference Include="EntityFrameworkCore.Exceptions.SqlServer" Version="8.0.0" /> <PackageReference Include="EntityFrameworkCore.Exceptions.SqlServer" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
<PackageReference Include="NewId" Version="4.0.1" />
</ItemGroup> </ItemGroup>
</Project> </Project>
@@ -0,0 +1,109 @@
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace IRaCIS.Core.Infra.EFCore;
public class AuditEntityInterceptor(IUserInfo _userInfo) : SaveChangesInterceptor
{
/// <summary>
/// 在事务提交之前执行
/// </summary>
/// <param name="eventData"></param>
/// <param name="result"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public override ValueTask<InterceptionResult<int>> SavingChangesAsync(DbContextEventData eventData,
InterceptionResult<int> result, CancellationToken cancellationToken = default)
{
AuditEntities(eventData.Context);
return base.SavingChangesAsync(eventData, result, cancellationToken);
}
public override InterceptionResult<int> SavingChanges(DbContextEventData eventData, InterceptionResult<int> result)
{
AuditEntities(eventData.Context);
return base.SavingChanges(eventData, result);
}
public void AuditEntities(DbContext? context)
{
if (context == null) return;
// 获取所有更改,删除,新增的实体,但排除审计实体(避免死循环)
foreach (var entry in context.ChangeTracker.Entries().Where(u => (u.State == EntityState.Modified || u.State == EntityState.Added))
.Where(x => !typeof(DataInspection).IsAssignableFrom(x.Entity.GetType())).ToList())
{
switch (entry.State)
{
case EntityState.Deleted:
break;
case EntityState.Modified:
if (entry.Entity is IAuditUpdate updateEntity1)
{
updateEntity1.UpdateTime = DateTime.Now;
updateEntity1.UpdateUserId = _userInfo.Id;
}
if (entry.Entity is ISoftDelete softDelete)
{
if (softDelete.IsDeleted)
{
softDelete.DeleteUserId = _userInfo.Id;
softDelete.DeletedTime = DateTime.Now;
}
else
{
softDelete.DeletedTime = null;
}
}
break;
//添加的时候,更新审计字段也赋值
case EntityState.Added:
if (entry.Entity is IAuditAdd addEntity)
{
if (addEntity.CreateTime == default(DateTime))
{
addEntity.CreateTime = DateTime.Now;
}
addEntity.CreateUserId = _userInfo.Id;
}
if (entry.Entity is IAuditUpdate updateEntity)
{
updateEntity.UpdateTime = DateTime.Now;
updateEntity.UpdateUserId = _userInfo.Id;
}
if (entry.Entity is IAuditAddWithUserName addEntity3)
{
if (addEntity3.CreateTime == default(DateTime))
{
addEntity3.CreateTime = DateTime.Now;
}
addEntity3.CreateUserId = _userInfo.Id;
addEntity3.CreateUser = _userInfo.RealName;
}
break;
}
}
}
}
@@ -0,0 +1,59 @@
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using IRaCIS.Core.Domain.Models;
using MassTransit;
namespace IRaCIS.Core.Infra.EFCore.Interceptor
{
public class DispatchDomainEventsInterceptor(IPublishEndpoint publishEndpoint) : SaveChangesInterceptor
{
//领域事件通常与数据变更密切相关。如果在 SaveChanges 之前发布事件,有可能事件发布时的数据状态还没有被持久化到数据库。这可能导致事件消费者看到的是一个不一致的状态
/// <summary>
/// 在事务提交之后分发事件
/// </summary>
/// <param name="eventData"></param>
/// <param name="result"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public override async ValueTask<int> SavedChangesAsync(SaveChangesCompletedEventData eventData, int result,
CancellationToken cancellationToken = default)
{
await DispatchDomainEvents(eventData.Context);
return await base.SavedChangesAsync(eventData, result, cancellationToken);
}
public override int SavedChanges(SaveChangesCompletedEventData eventData, int result)
{
DispatchDomainEvents(eventData.Context).GetAwaiter().GetResult();
return base.SavedChanges(eventData, result);
}
private async Task DispatchDomainEvents(DbContext? context)
{
if (context == null) return;
var entities = context.ChangeTracker
.Entries<Entity>()
.Where(e => e.Entity.DomainEvents.Any())
.Select(e => e.Entity)
.ToList();
var domainEvents = entities
.SelectMany(e => e.DomainEvents)
.ToList();
entities.ForEach(e => e.ClearDomainEvents());
foreach (var domainEvent in domainEvents)
{
await publishEndpoint.Publish(domainEvent);
}
}
}
}
@@ -11,6 +11,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AutoMapper" Version="13.0.1" /> <PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="AutoMapper.Collection.EntityFrameworkCore" Version="10.0.0" /> <PackageReference Include="AutoMapper.Collection.EntityFrameworkCore" Version="10.0.0" />
<PackageReference Include="MassTransit" Version="8.2.4" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="8.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
@@ -5,44 +5,86 @@ using Microsoft.EntityFrameworkCore;
using System.Linq.Dynamic.Core; using System.Linq.Dynamic.Core;
using System.Collections.Generic; using System.Collections.Generic;
using System; using System;
using System.Reflection;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
namespace IRaCIS.Core.Infrastructure.Extention namespace IRaCIS.Core.Infrastructure.Extention
{ {
public static class QueryablePageListExtensions public static class QueryablePageListExtensions
{ {
//单字段排序
public static PageOutput<T> ToPagedList<T>(this IQueryable<T> source, int pageIndex, int pageSize, string defaultSortFiled = "Id", bool isAsc = true) //单字段排序 异步 (或者默认排序字段是空,多字段排序,传递了,就以传递的单字段为准)
public static async Task<PageOutput<T>> ToPagedListAsync<T>(this IQueryable<T> source, PageInput pageInput, string[] sortArray = default, CancellationToken cancellationToken = default)
{ {
if (pageIndex <= 0) var isMultiSortFiled = false;
if (string.IsNullOrWhiteSpace(pageInput.SortField) && sortArray != default && sortArray != null)
{ {
pageIndex = 1; isMultiSortFiled = true;
} }
if (pageSize <= 0)
if (pageInput.PageIndex <= 0)
{ {
pageSize = 10; pageInput.PageIndex = 1;
} }
var count = source.Count(); if (pageInput.PageSize <= 0)
{
pageInput.PageSize = 10;
}
var count = await source.CountAsync(cancellationToken).ConfigureAwait(false);
if (count == 0) if (count == 0)
{ {
return new PageOutput<T>() { CurrentPageData = new T[0] }; return new PageOutput<T>() { CurrentPageData = new T[0] };
} }
if (isMultiSortFiled)
{
var sortString = string.Join(',', sortArray);
var propName = string.IsNullOrWhiteSpace(defaultSortFiled) ? "Id" : defaultSortFiled; source = source.OrderBy(sortString);
}
else
{
source = isAsc ? source.OrderBy(propName) : source.OrderBy(propName + " desc"); var propName = string.Empty;
source = source.Skip((pageIndex - 1) * pageSize); if (string.IsNullOrWhiteSpace(pageInput.SortField))
{
//没有指定,优先以Id排序,否则从属性里面随便取出来一个排序
var propertyNameList = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(t => t.CanWrite).Select(t => t.Name).OrderBy(t => t).ToList();
var items = source if (propertyNameList.Count == 0)
.Take(pageSize) {
.ToArray(); throw new InvalidOperationException("no default sort field.");
}
else
{
propName = propertyNameList.Contains("Id") ? "Id" : propertyNameList.FirstOrDefault();
}
}
else
{
//有值,以前段传输的为主
propName = pageInput.SortField;
}
source = pageInput.Asc ? source.OrderBy(propName) : source.OrderBy(propName + " desc");
}
source = source.Skip((pageInput.PageIndex - 1) * pageInput.PageSize);
var items = await source
.Take(pageInput.PageSize)
.ToArrayAsync(cancellationToken)
.ConfigureAwait(false);
var pagedList = new PageOutput<T>() var pagedList = new PageOutput<T>()
{ {
PageIndex = pageIndex, PageIndex = pageInput.PageIndex,
PageSize = pageSize, PageSize = pageInput.PageSize,
TotalCount = count, TotalCount = count,
CurrentPageData = items CurrentPageData = items
}; };
@@ -50,8 +92,10 @@ namespace IRaCIS.Core.Infrastructure.Extention
return pagedList; return pagedList;
} }
//单字段排序 异步 //单字段排序 异步
public static async Task<PageOutput<T>> ToPagedListAsync<T>(this IQueryable<T> source, int pageNumber, int pageSize, string defaultSortFiled = "Id", bool isAsc = true, bool isMultiSortFiled = false, string[] sortArray = default, CancellationToken cancellationToken = default) public static async Task<PageOutput<T>> ToPagedListAsync<T>(this IQueryable<T> source, int pageNumber, int pageSize, string defaultSortFiled = "Id", bool isAsc = true, bool isMultiSortFiled = false, string[] sortArray = default)
{ {
if (isMultiSortFiled && sortArray == default) if (isMultiSortFiled && sortArray == default)
@@ -68,7 +112,7 @@ namespace IRaCIS.Core.Infrastructure.Extention
pageSize = 10; pageSize = 10;
} }
var count = await source.CountAsync(cancellationToken).ConfigureAwait(false); var count = await source.CountAsync().ConfigureAwait(false);
if (count == 0) if (count == 0)
{ {
@@ -90,7 +134,7 @@ namespace IRaCIS.Core.Infrastructure.Extention
source = source.Skip((pageNumber - 1) * pageSize); source = source.Skip((pageNumber - 1) * pageSize);
var items = await source var items = await source
.Take(pageSize) .Take(pageSize)
.ToArrayAsync(cancellationToken) .ToArrayAsync()
.ConfigureAwait(false); .ConfigureAwait(false);
var pagedList = new PageOutput<T>() var pagedList = new PageOutput<T>()
@@ -105,126 +149,125 @@ namespace IRaCIS.Core.Infrastructure.Extention
} }
public static PageOutput<T> ToPagedList<T>(this IList<T> source, int pageIndex, int pageSize, string defaultSortFiled = "Id", bool isAsc = true) #region
{ ////单字段排序
if (pageIndex <= 0) //public static PageOutput<T> ToPagedList<T>(this IQueryable<T> source, int pageIndex, int pageSize, string defaultSortFiled = "Id", bool isAsc = true)
{ //{
pageIndex = 1; // if (pageIndex <= 0)
} // {
if (pageSize <= 0) // pageIndex = 1;
{ // }
pageSize = 10; // if (pageSize <= 0)
} // {
var count = source.Count(); // pageSize = 10;
// }
// var count = source.Count();
if (count == 0) // if (count == 0)
{ // {
return new PageOutput<T>() { CurrentPageData = new List<T>() }; // return new PageOutput<T>() { CurrentPageData = new T[0] };
} // }
var propName = string.IsNullOrWhiteSpace(defaultSortFiled) ? "Id" : defaultSortFiled;
IQueryable<T> sourceQuery = isAsc ? source.AsQueryable().OrderBy(propName) : source.AsQueryable().OrderBy(propName + " desc");
sourceQuery = sourceQuery.Skip((pageIndex - 1) * pageSize);
var items = sourceQuery
.Take(pageSize)
.ToArray();
var pagedList = new PageOutput<T>()
{
PageIndex = pageIndex,
PageSize = pageSize,
TotalCount = count,
CurrentPageData = items
};
return pagedList;
}
//多字段排序 ["a asc", "b desc", "c asc"]
public static PageOutput<T> ToPagedList<T>(this IQueryable<T> source, int pageIndex, int pageSize, string[] sortArray)
{
if (pageIndex <= 0)
{
pageIndex = 1;
}
if (pageSize <= 0)
{
pageSize = 10;
}
var count = source.Count();
if (count == 0)
{
return new PageOutput<T>() { CurrentPageData = new T[0] };
}
var sortString = string.Join(',', sortArray);
source.OrderBy(sortString);
source = source.Skip((pageIndex - 1) * pageSize);
var items = source
.Take(pageSize)
.ToArray();
var pagedList = new PageOutput<T>()
{
PageIndex = pageIndex,
PageSize = pageSize,
TotalCount = count,
CurrentPageData = items
};
return pagedList;
}
//多字段排序异步 ["a asc", "b desc", "c asc"]
public static async Task<PageOutput<T>> ToPagedListAsync<T>(this IQueryable<T> source, int pageNumber, int pageSize, string[] sortArray, CancellationToken cancellationToken = default)
{
if (pageNumber <= 0)
{
pageNumber = 1;
}
if (pageSize <= 0)
{
pageSize = 10;
}
var count = await source.CountAsync(cancellationToken).ConfigureAwait(false);
if (count == 0)
{
return new PageOutput<T>() { CurrentPageData = new T[0] };
}
if(sortArray.Count()>0)
{
var sortString = string.Join(',', sortArray);
source = source.OrderBy(sortString);
}
source = source.Skip((pageNumber - 1) * pageSize); // var propName = string.IsNullOrWhiteSpace(defaultSortFiled) ? "Id" : defaultSortFiled;
var items = await source
.Take(pageSize)
.ToArrayAsync(cancellationToken)
.ConfigureAwait(false);
var pagedList = new PageOutput<T>() // source = isAsc ? source.OrderBy(propName) : source.OrderBy(propName + " desc");
{
PageIndex = pageNumber,
PageSize = pageSize,
TotalCount = count,
CurrentPageData = items
};
return pagedList; // source = source.Skip((pageIndex - 1) * pageSize);
}
// var items = source
// .Take(pageSize)
// .ToArray();
// var pagedList = new PageOutput<T>()
// {
// PageIndex = pageIndex,
// PageSize = pageSize,
// TotalCount = count,
// CurrentPageData = items
// };
// return pagedList;
//}
//public static PageOutput<T> ToPagedList<T>(this IList<T> source, int pageIndex, int pageSize, string defaultSortFiled = "Id", bool isAsc = true)
//{
// if (pageIndex <= 0)
// {
// pageIndex = 1;
// }
// if (pageSize <= 0)
// {
// pageSize = 10;
// }
// var count = source.Count();
// if (count == 0)
// {
// return new PageOutput<T>() { CurrentPageData = new List<T>() };
// }
// var propName = string.IsNullOrWhiteSpace(defaultSortFiled) ? "Id" : defaultSortFiled;
// IQueryable<T> sourceQuery = isAsc ? source.AsQueryable().OrderBy(propName) : source.AsQueryable().OrderBy(propName + " desc");
// sourceQuery = sourceQuery.Skip((pageIndex - 1) * pageSize);
// var items = sourceQuery
// .Take(pageSize)
// .ToArray();
// var pagedList = new PageOutput<T>()
// {
// PageIndex = pageIndex,
// PageSize = pageSize,
// TotalCount = count,
// CurrentPageData = items
// };
// return pagedList;
//}
////多字段排序 ["a asc", "b desc", "c asc"]
//public static PageOutput<T> ToPagedList<T>(this IQueryable<T> source, int pageIndex, int pageSize, string[] sortArray)
//{
// if (pageIndex <= 0)
// {
// pageIndex = 1;
// }
// if (pageSize <= 0)
// {
// pageSize = 10;
// }
// var count = source.Count();
// if (count == 0)
// {
// return new PageOutput<T>() { CurrentPageData = new T[0] };
// }
// var sortString = string.Join(',', sortArray);
// source.OrderBy(sortString);
// source = source.Skip((pageIndex - 1) * pageSize);
// var items = source
// .Take(pageSize)
// .ToArray();
// var pagedList = new PageOutput<T>()
// {
// PageIndex = pageIndex,
// PageSize = pageSize,
// TotalCount = count,
// CurrentPageData = items
// };
// return pagedList;
//}
#endregion
@@ -19,6 +19,8 @@
public string LocalizedInfo { get; set; } public string LocalizedInfo { get; set; }
} }
/// <summary> /// <summary>
@@ -15,6 +15,7 @@ public static class StaticData
public static Dictionary<string, string> Log_Locoalize_Dic = new Dictionary<string, string>(); public static Dictionary<string, string> Log_Locoalize_Dic = new Dictionary<string, string>();
#region
public static readonly string En_US_Json = "en-US.json"; public static readonly string En_US_Json = "en-US.json";
public static readonly string Zh_CN_Json = "zh-CN.json"; public static readonly string Zh_CN_Json = "zh-CN.json";
@@ -70,9 +71,11 @@ public static class StaticData
} }
#endregion
#region #region
public static readonly string Title = "Title";
public static readonly string Title = "Title";
public static readonly string ReadingType = "ReadingType"; public static readonly string ReadingType = "ReadingType";
public static readonly string Subspeciality = "Subspeciality"; public static readonly string Subspeciality = "Subspeciality";
@@ -80,6 +83,7 @@ public static class StaticData
public static readonly string Criterion = "Criterion"; public static readonly string Criterion = "Criterion";
public static readonly string ReviewType = "ReviewType"; public static readonly string ReviewType = "ReviewType";
public static readonly string ReadingStandard = "ReadingStandard"; public static readonly string ReadingStandard = "ReadingStandard";
#endregion #endregion
@@ -72,11 +72,9 @@ namespace IRaCIS.Core.Application.Service
var <#=char.ToLower(tableName[0]) + tableName.Substring(1)#>Queryable = var <#=char.ToLower(tableName[0]) + tableName.Substring(1)#>Queryable =
_<#=char.ToLower(tableName[0]) + tableName.Substring(1)#>Repository _<#=char.ToLower(tableName[0]) + tableName.Substring(1)#>Repository
.ProjectTo<<#=tableName#>View>(_mapper.ConfigurationProvider); .ProjectTo<<#=tableName#>View>(_mapper.ConfigurationProvider);
var pageList= await <#=char.ToLower(tableName[0]) + tableName.Substring(1)#>Queryable var pageList= await <#=char.ToLower(tableName[0]) + tableName.Substring(1)#>Queryable.ToPagedListAsync(inQuery);
.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrWhiteSpace(inQuery.SortField) ? nameof(<#=tableName#>View.Id) : inQuery.SortField,
inQuery.Asc);
return pageList; return pageList;
} }
+1 -1
View File
@@ -19,7 +19,7 @@ steps:
- name: build-uat-irc - name: build-uat-irc
commands: commands:
- cd /opt/1panel/xc-deploy/Uat_IRC/devops-build-publish/Uat-To-Uat - cd /opt/1panel/xc-deploy/Uat_IRC/devops-build-publish/Uat-To-Uat
- sh pull-build-uat-irc-image.sh v${DRONE_BUILD_NUMBER} - sh uat-branch-latest-build-image-publish.sh v${DRONE_BUILD_NUMBER}
trigger: trigger:
branch: branch: