Compare commits
66 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 30e71b11e8 | |||
| 2de504005e | |||
| 6a41c33d34 | |||
| 3b48dfae31 | |||
| c7fd9a6bcb | |||
| 169ef180ff | |||
| f33d3d474b | |||
| 63e1331bd1 | |||
| 418cc9b4b9 | |||
| 71fb1eac6b | |||
| 0804a05925 | |||
| de6098013d | |||
| f8cd361415 | |||
| 0b1a640c3e | |||
| aa9df5838c | |||
| 2edacc9ff5 | |||
| a9a0a9d307 | |||
| 1937804e47 | |||
| 8e8b55fa46 | |||
| 3096671595 | |||
| a6102490c8 | |||
| 9e1cc1521f | |||
| a579c26ada | |||
| 754da2c7fc | |||
| 995bdee1f6 | |||
| a70f661e86 | |||
| 8312bfb78b | |||
| 7194796841 | |||
| c6918cca46 | |||
| be7b38c6ce | |||
| a7ebd50536 | |||
| 05f9b81e04 | |||
| 1f9eb9e36b | |||
| af46eb2d65 | |||
| d1e54629e7 | |||
| 78dbe23d0e | |||
| 4bf93d10b0 | |||
| 00827e9975 | |||
| 021b32587a | |||
| 5ffe1675db | |||
| d34eca2cb8 | |||
| 12ac7af11e | |||
| a19eb2abca | |||
| 4c9a8aadab | |||
| 034058999d | |||
| 34ea39e764 | |||
| 7caf00bd75 | |||
| aabe604e18 | |||
| f2bc281e2b | |||
| 4187a568f8 | |||
| 1611554c00 | |||
| 60fc8f9bce | |||
| 48eb20fa66 | |||
| 9e7bc09f84 | |||
| ec9e35180b | |||
| c757212c07 | |||
| 8415dd2be1 | |||
| 17d734ba11 | |||
| 476387b468 | |||
| 3a2cb138ab | |||
| fa763e6341 | |||
| c988ca0bca | |||
| c257dd4171 | |||
| ff026f45fc | |||
| cd2166f11b | |||
| 33cfacec84 |
@@ -4,6 +4,7 @@ using IRaCIS.Core.Infra.EFCore;
|
||||
using Medallion.Threading;
|
||||
using Medallion.Threading.SqlServer;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
@@ -15,11 +16,12 @@ namespace IRaCIS.Core.SCP
|
||||
{
|
||||
services.AddHttpContextAccessor();
|
||||
services.AddScoped<IUserInfo, UserInfo>();
|
||||
services.AddScoped<ISaveChangesInterceptor, AuditEntityInterceptor>();
|
||||
|
||||
|
||||
//这个注入没有成功--注入是没问题的,构造函数也只是支持参数就好,错在注入的地方不能写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(); });
|
||||
@@ -35,6 +37,7 @@ namespace IRaCIS.Core.SCP
|
||||
options.EnableSensitiveDataLogging();
|
||||
|
||||
options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor());
|
||||
options.AddInterceptors(sp.GetServices<ISaveChangesInterceptor>());
|
||||
|
||||
options.UseProjectables();
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<PackageReference Include="My.Extensions.Localization.Json" Version="3.3.0">
|
||||
<TreatAsUsed>true</TreatAsUsed>
|
||||
</PackageReference>
|
||||
<PackageReference Include="NewId" Version="4.0.1" />
|
||||
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" />
|
||||
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.0.3" />
|
||||
<PackageReference Include="Serilog.Extensions.Hosting" Version="8.0.0" />
|
||||
|
||||
@@ -73,7 +73,6 @@ builder.Services.AddJsonLocalization(options => options.ResourcesPath = "Resourc
|
||||
// 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim()
|
||||
builder.Services.AddControllers(options =>
|
||||
{
|
||||
//options.Filters.Add<LogActionFilter>();
|
||||
options.Filters.Add<ModelActionFilter>();
|
||||
options.Filters.Add<ProjectExceptionFilter>();
|
||||
options.Filters.Add<UnitOfWorkFilter>();
|
||||
|
||||
@@ -10,5 +10,16 @@
|
||||
"environmentVariables": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,10 +31,8 @@
|
||||
},
|
||||
|
||||
"ConnectionStrings": {
|
||||
//"RemoteNew": "Server=47.117.165.18,1434;Database=Prod_Study;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true",
|
||||
//"Hangfire": "Server=47.117.165.18,1434;Database=Prod_Study_Hangfire;User ID=sa;Password=zhanying@2021;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"
|
||||
"RemoteNew": "Server=us-prod-mssql-service,1433;Database=US_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=us-prod-mssql-service,1433;Database=US_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
},
|
||||
|
||||
"BasicSystemConfig": {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
}
|
||||
},
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "MinIO",
|
||||
"ObjectStoreUse": "AliyunOSS",
|
||||
"AliyunOSS": {
|
||||
"regionId": "cn-shanghai",
|
||||
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||
@@ -20,16 +20,6 @@
|
||||
"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": {
|
||||
"endPoint": "s3.us-east-1.amazonaws.com",
|
||||
"useSSL": false,
|
||||
@@ -40,8 +30,8 @@
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=47.117.164.182,1434;Database=Uat_HIR;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"
|
||||
"RemoteNew": "Server=47.117.164.182,1434;Database=Uat_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=47.117.164.182,1434;Database=Uat_IRC.Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
},
|
||||
"BasicSystemConfig": {
|
||||
|
||||
|
||||
@@ -10,8 +10,7 @@ using IRaCIS.Core.Application.Contracts.Dicom;
|
||||
using IRaCIS.Core.Application.Contracts.Dicom.DTO;
|
||||
using IRaCIS.Core.Application.Filter;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Core.Application.MediatR.CommandAndQueries;
|
||||
using IRaCIS.Core.Application.MediatR.Handlers;
|
||||
using IRaCIS.Core.Application.MassTransit.Command;
|
||||
using IRaCIS.Core.Application.Service;
|
||||
using IRaCIS.Core.Application.Service.ImageAndDoc;
|
||||
using IRaCIS.Core.Application.Service.Reading.Dto;
|
||||
@@ -21,7 +20,7 @@ using IRaCIS.Core.Infra.EFCore;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using MassTransit;
|
||||
using MediatR;
|
||||
using MassTransit.Mediator;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Cors.Infrastructure;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
@@ -232,9 +231,12 @@ namespace IRaCIS.Core.API.Controllers
|
||||
{
|
||||
public IMapper _mapper { get; set; }
|
||||
public IUserInfo _userInfo { get; set; }
|
||||
|
||||
|
||||
private readonly IMediator _mediator;
|
||||
|
||||
|
||||
|
||||
public IStringLocalizer _localizer { get; set; }
|
||||
|
||||
|
||||
@@ -266,11 +268,6 @@ namespace IRaCIS.Core.API.Controllers
|
||||
[FromServices] IRepository<StudyMonitor> _studyMonitorRepository)
|
||||
{
|
||||
|
||||
if (_provider.Get<List<SystemAnonymization>>(StaticData.Anonymize.Anonymize_AddFixedFiled).Value == null)
|
||||
{
|
||||
await _mediator.Send(new AnonymizeCacheRequest());
|
||||
}
|
||||
|
||||
var savedInfo = _studyService.GetSaveToDicomInfo(preArchiveStudyCommand.SubjectVisitId);
|
||||
|
||||
var studyMonitor = new StudyMonitor()
|
||||
@@ -743,11 +740,16 @@ namespace IRaCIS.Core.API.Controllers
|
||||
//---请保证上传数据符合模板文件中的样式,且存在有效数据。
|
||||
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();
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -326,38 +326,6 @@
|
||||
<param name="_attachmentrepository"></param>
|
||||
<returns></returns>
|
||||
</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})">
|
||||
<summary> 通用文件下载 </summary>
|
||||
</member>
|
||||
|
||||
+93
-15
@@ -4,8 +4,6 @@ using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Serilog;
|
||||
using MediatR;
|
||||
using IRaCIS.Core.Application.MediatR.Handlers;
|
||||
using System.Threading.Tasks;
|
||||
using MassTransit;
|
||||
using MassTransit.NewIdProviders;
|
||||
@@ -29,6 +27,12 @@ using IRaCIS.Core.Application.Service.ImageAndDoc;
|
||||
using IP2Region.Net.Abstractions;
|
||||
using IP2Region.Net.XDB;
|
||||
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 获取环境变量
|
||||
@@ -134,7 +138,28 @@ builder.Services.AddSwaggerSetup();
|
||||
builder.Services.AddJWTAuthSetup(_configuration);
|
||||
|
||||
// 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 缓存
|
||||
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.AddExceptionHandler<GlobalExceptionHandler>();
|
||||
//builder.Services.AddProblemDetails();
|
||||
|
||||
#region 历史废弃配置
|
||||
//builder.Services.AddMemoryCache();
|
||||
@@ -190,6 +217,56 @@ var env = app.Environment;
|
||||
|
||||
// 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();
|
||||
|
||||
@@ -198,12 +275,11 @@ app.UseForwardedHeaders();
|
||||
//响应压缩
|
||||
app.UseResponseCompression();
|
||||
|
||||
//app.UseCors(t => t.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
|
||||
|
||||
//不需要 token 访问的静态文件 wwwroot css, JavaScript, and images don't require authentication.
|
||||
app.UseStaticFiles();
|
||||
|
||||
app.UseMiddleware<MultiDiskStaticFilesMiddleware>();
|
||||
|
||||
|
||||
//LogDashboard
|
||||
app.UseLogDashboard("/LogDashboard");
|
||||
@@ -211,22 +287,24 @@ app.UseLogDashboard("/LogDashboard");
|
||||
//hangfire
|
||||
app.UseHangfireConfig(env);
|
||||
|
||||
#region 暂时废弃
|
||||
|
||||
//app.UseMiddleware<MultiDiskStaticFilesMiddleware>();
|
||||
////限流 中间件
|
||||
//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);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using AutoMapper.EquivalencyExpression;
|
||||
using IRaCIS.Core.Application.Service;
|
||||
using IRaCIS.Core.Domain.Models;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
@@ -14,6 +15,10 @@ namespace IRaCIS.Core.API
|
||||
//AutoMapper.Collection.EntityFrameworkCore
|
||||
automapper.AddCollectionMappers();
|
||||
|
||||
|
||||
// 全局忽略 DomainEvents 属性
|
||||
automapper.AddGlobalIgnore(nameof(Entity.DomainEvents));
|
||||
|
||||
#region 会使 IncludeMembers 失效 不能全局使用
|
||||
//mapping an EntityFramework Core DbContext-object.
|
||||
//automapper.UseEntityFrameworkCoreModel<IRaCISDBContext>(services);
|
||||
|
||||
@@ -10,7 +10,6 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using IRaCIS.Core.Domain.Models;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using MediatR;
|
||||
using IRaCIS.Application.Services;
|
||||
using IRaCIS.Application.Interfaces;
|
||||
using AutoMapper;
|
||||
|
||||
@@ -4,9 +4,11 @@ using Hangfire.SqlServer;
|
||||
using IRaCIS.Core.Application.Triggers;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Infra.EFCore;
|
||||
using IRaCIS.Core.Infra.EFCore.Interceptor;
|
||||
using Medallion.Threading;
|
||||
using Medallion.Threading.SqlServer;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@@ -21,12 +23,15 @@ namespace IRaCIS.Core.API
|
||||
|
||||
services.AddHttpContextAccessor();
|
||||
services.AddScoped<IUserInfo, UserInfo>();
|
||||
services.AddScoped<ISaveChangesInterceptor, AuditEntityInterceptor>();
|
||||
services.AddScoped<ISaveChangesInterceptor, DispatchDomainEventsInterceptor>();
|
||||
|
||||
|
||||
// First, register a pooling context factory as a Singleton service, as usual:
|
||||
|
||||
//这个注入没有成功--注入是没问题的,构造函数也只是支持参数就好,错在注入的地方不能写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.AddInterceptors(new QueryWithNoLockDbCommandInterceptor());
|
||||
options.AddInterceptors(sp.GetServices<ISaveChangesInterceptor>());
|
||||
|
||||
options.UseProjectables();
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
},
|
||||
"ObjectStoreService": {
|
||||
|
||||
"ObjectStoreUse": "MinIO",
|
||||
"ObjectStoreUse": "AliyunOSS",
|
||||
|
||||
"AliyunOSS": {
|
||||
"regionId": "cn-shanghai",
|
||||
|
||||
@@ -9,6 +9,7 @@ using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using SharpCompress.Common;
|
||||
using ZiggyCreatures.Caching.Fusion;
|
||||
|
||||
namespace IRaCIS.Application.Services.BackGroundJob
|
||||
{
|
||||
@@ -21,77 +22,45 @@ namespace IRaCIS.Application.Services.BackGroundJob
|
||||
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);
|
||||
|
||||
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()
|
||||
{
|
||||
_logger.LogInformation("项目启动 hangfire 任务初始化 执行开始~");
|
||||
|
||||
|
||||
//项目状态 立即加载到缓存中
|
||||
await MemoryCacheTrialStatusAsync();
|
||||
|
||||
await MemoryCacheAnonymizeData();
|
||||
|
||||
|
||||
//创建项目缓存 定时任务
|
||||
HangfireJobHelper.AddOrUpdateInitCronJob<IIRaCISHangfireJob>("RecurringJob_Cache_TrialState", t => t.MemoryCacheTrialStatusAsync(), Cron.Daily());
|
||||
|
||||
//初始化
|
||||
//初始化国际化
|
||||
|
||||
await InternationalizationHelper.InitInternationlizationDataAndWatchJsonFileAsync(_internationalizationRepository);
|
||||
|
||||
//创建邮件定时任务
|
||||
await InitSysAndTrialCronJobAsync();
|
||||
|
||||
#region 废弃
|
||||
////项目状态 立即加载到缓存中
|
||||
//await MemoryCacheTrialStatusAsync();
|
||||
|
||||
////await MemoryCacheAnonymizeData();
|
||||
|
||||
|
||||
////创建项目缓存 定时任务
|
||||
//HangfireJobHelper.AddOrUpdateInitCronJob<IIRaCISHangfireJob>("RecurringJob_Cache_TrialState", t => t.MemoryCacheTrialStatusAsync(), Cron.Daily());
|
||||
#endregion
|
||||
|
||||
|
||||
_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,6 +9,7 @@ using Panda.DynamicWebApi.Attributes;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ZiggyCreatures.Caching.Fusion;
|
||||
|
||||
namespace IRaCIS.Core.Application
|
||||
{
|
||||
@@ -32,7 +33,7 @@ namespace IRaCIS.Core.Application
|
||||
|
||||
public IWebHostEnvironment _hostEnvironment { get; set; }
|
||||
|
||||
|
||||
public IFusionCache _fusionCache { get; set; }
|
||||
|
||||
|
||||
public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class
|
||||
@@ -60,6 +61,9 @@ namespace IRaCIS.Core.Application
|
||||
[MemberNotNull(nameof(_hostEnvironment))]
|
||||
public IWebHostEnvironment _hostEnvironment { get; set; }
|
||||
|
||||
[MemberNotNull(nameof(_fusionCache))]
|
||||
public IFusionCache _fusionCache { get; set; }
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -81,7 +85,8 @@ namespace IRaCIS.Core.Application
|
||||
[MemberNotNull(nameof(_localizer))]
|
||||
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 IFusionCache _fusionCache { get; set; }
|
||||
|
||||
public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class
|
||||
{
|
||||
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));
|
||||
|
||||
|
||||
//warning 级别记录
|
||||
//_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));
|
||||
|
||||
}
|
||||
|
||||
context.ExceptionHandled = true;//标记当前异常已经被处理过了
|
||||
|
||||
|
||||
//throw new Exception("test-result-exceptioin");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//继续
|
||||
}
|
||||
context.ExceptionHandled = true;//标记当前异常已经被处理过了
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
using EasyCaching.Core;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using System.Text.RegularExpressions;
|
||||
using ZiggyCreatures.Caching.Fusion;
|
||||
using static IRaCIS.Core.Domain.Share.StaticData;
|
||||
|
||||
namespace IRaCIS.Core.Application.Filter
|
||||
@@ -16,47 +18,36 @@ namespace IRaCIS.Core.Application.Filter
|
||||
{
|
||||
private readonly IEasyCachingProvider _provider;
|
||||
private readonly IUserInfo _userInfo;
|
||||
|
||||
private readonly IFusionCache _fusionCache;
|
||||
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;
|
||||
_userInfo = userInfo;
|
||||
_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(trialOpt3)) _trialOptList.Add(trialOpt3.Trim());
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//public TrialResourceFilter(IEasyCachingProvider provider, IUserInfo userInfo)
|
||||
//{
|
||||
// _provider = provider;
|
||||
// _userInfo = userInfo;
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//优先选择异步的方法
|
||||
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
|
||||
{
|
||||
// var typeFilter = context.ActionDescriptor.EndpointMetadata.Where(t => t.GetType() == typeof(TypeFilterAttribute)).Select(t => (TypeFilterAttribute)t).ToList().FirstOrDefault();
|
||||
//var _trialOptList= typeFilter.Arguments.Select(t => t.ToString()).ToList();
|
||||
// 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();
|
||||
|
||||
#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"]));
|
||||
@@ -97,7 +88,7 @@ namespace IRaCIS.Core.Application.Filter
|
||||
}
|
||||
else
|
||||
{
|
||||
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
||||
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||
}
|
||||
|
||||
@@ -128,20 +119,20 @@ namespace IRaCIS.Core.Application.Filter
|
||||
if (matchResult.Success)
|
||||
{
|
||||
//有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下
|
||||
var cacheResultDic = _provider.GetAll<string>(new[] { matchResult.Value });
|
||||
|
||||
var trialStatusStr = cacheResultDic[matchResult.Value.ToLower()].Value;
|
||||
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
|
||||
{
|
||||
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
||||
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||
}
|
||||
|
||||
@@ -153,34 +144,12 @@ namespace IRaCIS.Core.Application.Filter
|
||||
}
|
||||
|
||||
//通过path 或者body 找到trialId 了
|
||||
if ( !string.IsNullOrWhiteSpace(trialIdStr))
|
||||
if (!string.IsNullOrWhiteSpace(trialIdStr))
|
||||
{
|
||||
|
||||
//如果没缓存数据,可能定时任务没执行或者缓存丢失 在此重新缓存
|
||||
if (_provider.GetCount() == 0)
|
||||
{
|
||||
|
||||
var _trialRepository = context.HttpContext.RequestServices.GetService(typeof(IRepository<Trial>)) as IRepository<Trial>;
|
||||
|
||||
var list = _trialRepository.IfNullThrowException().Select(t => new { TrialId = t.Id, TrialStatusStr = t.TrialStatusStr })
|
||||
.ToList();
|
||||
|
||||
list.ForEach(t => _provider.Set(t.TrialId.ToString(), t.TrialStatusStr, TimeSpan.FromDays(7)));
|
||||
}
|
||||
|
||||
var cacheResultDic = _provider.GetAll<string>(new[] { trialIdStr });
|
||||
|
||||
var trialStatusStr = cacheResultDic[trialIdStr].Value;
|
||||
|
||||
//意外 导致缓存过期,调整服务器时间,测试不想重启程序
|
||||
if (string.IsNullOrWhiteSpace(trialStatusStr))
|
||||
{
|
||||
var trialRepository = context.HttpContext.RequestServices.GetService(typeof(IRepository<Trial>)) as IRepository<Trial>;
|
||||
trialStatusStr = trialRepository?.Where(t => t.Id == Guid.Parse(trialIdStr)).Select(t => t.TrialStatusStr).FirstOrDefault();
|
||||
}
|
||||
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
|
||||
|
||||
// 这里是统一拦截 项目有关的操作允许情况(特殊的地方,比如项目配置(有的在多种状态(初始化,ongoing)都可以操作,有的仅仅在Initializing)还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口)
|
||||
if (trialStatusStr == StaticData.TrialState.TrialOngoing || _trialOptList.Any(t=>t== TrialOpt.BeforeOngoingCantOpt) )
|
||||
if (trialStatusStr == StaticData.TrialState.TrialOngoing || _trialOptList.Any(t => t == TrialOpt.BeforeOngoingCantOpt))
|
||||
{
|
||||
|
||||
await next.Invoke();
|
||||
@@ -189,14 +158,14 @@ namespace IRaCIS.Core.Application.Filter
|
||||
// 项目停止、或者完成 不允许操作
|
||||
else
|
||||
{
|
||||
//---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改
|
||||
//---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -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="IP2Region.Net" Version="2.0.2" />
|
||||
<PackageReference Include="MailKit" Version="4.2.0" />
|
||||
<PackageReference Include="MediatR" Version="12.2.0" />
|
||||
<PackageReference Include="MimeKit" Version="4.2.0" />
|
||||
<PackageReference Include="MiniExcel" Version="1.32.0" />
|
||||
<PackageReference Include="Minio" Version="6.0.3" />
|
||||
@@ -86,7 +85,8 @@
|
||||
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.5" />
|
||||
<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>
|
||||
|
||||
@@ -29,31 +29,16 @@
|
||||
签名
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:IRaCIS.Core.Application.BusinessFilter.GlobalExceptionHandler">
|
||||
<summary>
|
||||
不生效,不知道为啥
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:IRaCIS.Core.Application.Filter.TrialResourceFilter">
|
||||
<summary>
|
||||
主要为了 处理项目结束 锁库,不允许操作
|
||||
</summary>
|
||||
</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)">
|
||||
<summary>
|
||||
写文件导到磁盘
|
||||
@@ -62,28 +47,6 @@
|
||||
<param name="path">文件保存路径</param>
|
||||
<returns></returns>
|
||||
</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)">
|
||||
<summary>
|
||||
oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder
|
||||
@@ -9948,6 +9911,11 @@
|
||||
TrialSiteDicomAEService
|
||||
</summary>
|
||||
</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">
|
||||
<summary> TaskAllocationRuleView 列表视图模型 </summary>
|
||||
</member>
|
||||
@@ -13345,24 +13313,9 @@
|
||||
维护 IsFrontTaskNeedSignButNotSign 字段 另外附加评估结果
|
||||
</summary>
|
||||
</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">
|
||||
<summary>
|
||||
缓存项目状态
|
||||
缓存项目状态--之前是启动的时候就获取所有的项目进行缓存,加上定时任务刷新,现在的话,改为是按照需要进行缓存请求数据库
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
@@ -15239,11 +15192,14 @@
|
||||
<param name="inQuery"></param>
|
||||
<returns></returns>
|
||||
</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>
|
||||
<param name="inCommand"></param>
|
||||
<param name="_dicomstudyRepository"></param>
|
||||
<param name="_dicomSeriesRepository"></param>
|
||||
<param name="_dicomInstanceRepository"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
+25
-14
@@ -1,16 +1,22 @@
|
||||
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 MassTransit;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Newtonsoft.Json;
|
||||
using MediatR;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
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 IUserInfo _userInfo;
|
||||
private readonly IRepository<Subject> _subjectRepository;
|
||||
@@ -24,7 +30,7 @@ namespace IRaCIS.Core.Application.MediatR.Handlers
|
||||
/// 构造函数注入
|
||||
/// </summary>
|
||||
|
||||
public ConsistencyVerificationHandler(IRepository<DicomStudy> studyRepository, IUserInfo userInfo,
|
||||
public ConsistencyCheckConsumer(IRepository<DicomStudy> studyRepository, IUserInfo userInfo,
|
||||
IRepository<Subject> subjectRepository, IRepository<SubjectVisit> subjectVisitRepository,
|
||||
IRepository<TrialSite> trialSiteRepository, IRepository<NoneDicomStudy> noneDicomStudyRepository,
|
||||
IMapper mapper, IStringLocalizer localizer)
|
||||
@@ -39,19 +45,22 @@ namespace IRaCIS.Core.Application.MediatR.Handlers
|
||||
_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大小写
|
||||
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(); });
|
||||
var etcList = request.ETCList;
|
||||
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 = context.Message.ETCList;
|
||||
|
||||
//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));
|
||||
|
||||
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));
|
||||
|
||||
var dicomQuery = from sv in _subjectVisitRepository.Where(subjectVisitLambda)
|
||||
@@ -274,11 +283,13 @@ namespace IRaCIS.Core.Application.MediatR.Handlers
|
||||
|
||||
}
|
||||
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 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 Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using NPOI.SS.Formula.Functions;
|
||||
using IRaCIS.Core.Application.Service.Reading.Dto;
|
||||
|
||||
namespace IRaCIS.Core.Application.Service
|
||||
{
|
||||
@@ -32,6 +33,8 @@ namespace IRaCIS.Core.Application.Service
|
||||
|
||||
private readonly IRepository<TaskConsistentRule> _taskConsistentRuleRepository;
|
||||
private readonly IRepository<VisitTask> _visitTaskRepository;
|
||||
private readonly IRepository<ReadingConsistentClinicalData> _readingConsistentClinicalDataRepository;
|
||||
private readonly IReadingClinicalDataService _readingClinicalDataService;
|
||||
private readonly IRepository<SubjectUser> _subjectUserRepository;
|
||||
private readonly IRepository<Subject> _subjectRepository;
|
||||
private readonly IRepository<Enroll> _enrollRepository;
|
||||
@@ -44,11 +47,16 @@ namespace IRaCIS.Core.Application.Service
|
||||
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)
|
||||
{
|
||||
_taskConsistentRuleRepository = taskConsistentRuleRepository;
|
||||
_visitTaskRepository = visitTaskRepository;
|
||||
this._readingConsistentClinicalDataRepository = readingConsistentClinicalDataRepository;
|
||||
this._readingClinicalDataService = readingClinicalDataService;
|
||||
_subjectUserRepository = subjectUserRepository;
|
||||
_subjectRepository = subjectRepository;
|
||||
_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 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();
|
||||
|
||||
@@ -253,6 +275,7 @@ namespace IRaCIS.Core.Application.Service
|
||||
TaskName = lastTask.TaskName + "_Global",
|
||||
TaskBlindName = lastTask.TaskBlindName + "_Global",
|
||||
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();
|
||||
@@ -496,7 +519,9 @@ namespace IRaCIS.Core.Application.Service
|
||||
TrialReadingCriterionId = trialReadingCriterionId,
|
||||
|
||||
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 IRaCIS.Core.Domain.Share.Reading;
|
||||
using IRaCIS.Core.Application.Service.Reading.Dto;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace IRaCIS.Core.Application.Service
|
||||
{
|
||||
@@ -26,7 +27,7 @@ namespace IRaCIS.Core.Application.Service
|
||||
/// 访视读片任务
|
||||
/// </summary>
|
||||
[ApiExplorerSettings(GroupName = "Trial")]
|
||||
public class VisitTaskHelpeService : IVisitTaskHelpeService
|
||||
public class VisitTaskHelpeService : BaseService, IVisitTaskHelpeService
|
||||
{
|
||||
|
||||
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)
|
||||
@@ -468,7 +482,9 @@ namespace IRaCIS.Core.Application.Service
|
||||
|
||||
//CRC 的自动签名 不用管 只用处理PM的就好
|
||||
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();
|
||||
@@ -1415,6 +1431,7 @@ namespace IRaCIS.Core.Application.Service
|
||||
case GenerateTaskCategory.SelfConsistent:
|
||||
|
||||
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 trialReadingCriterion=_trialReadingCriterionRepository.Where(t=>t.Id== trialReadingCriterionId).FirstOrDefault();
|
||||
|
||||
@@ -1457,7 +1474,11 @@ namespace IRaCIS.Core.Application.Service
|
||||
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.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.BusinessScenarioEnum != null, t => t.BusinessScenarioEnum == queryCommonDocument.BusinessScenarioEnum)
|
||||
.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.Code), t => t.Code.Contains(queryCommonDocument.Code))
|
||||
.WhereIf(!string.IsNullOrEmpty(queryCommonDocument.Name), t => t.Name.Contains(queryCommonDocument.Name))
|
||||
.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 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(!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);
|
||||
|
||||
|
||||
PageOutput<DocumentUnionWithUserStatView> GetTrialSystemDocumentList(DocumentTrialUnionQuery querySystemDocument);
|
||||
Task<PageOutput<DocumentUnionWithUserStatView>> GetTrialSystemDocumentList(DocumentTrialUnionQuery querySystemDocument);
|
||||
List<TrialUserUnionDocumentView> GetTrialUserDocumentList(Guid trialId);
|
||||
}
|
||||
}
|
||||
@@ -26,8 +26,8 @@ namespace IRaCIS.Core.Application.Services
|
||||
private readonly IRepository<TrialDocument> _trialDocumentRepository;
|
||||
private readonly IRepository<TrialDocConfirmedUser> _trialDocUserTypeConfirmedUserRepository;
|
||||
private readonly IRepository<Trial> _trialRepository;
|
||||
private readonly ISystemDocumentService _systemDocumentService;
|
||||
private readonly IRepository<SystemDocConfirmedUser> _systemDocConfirmedUserRepository;
|
||||
private readonly ISystemDocumentService _systemDocumentService;
|
||||
private readonly IRepository<SystemDocConfirmedUser> _systemDocConfirmedUserRepository;
|
||||
private readonly IRepository<SystemDocument> _systemDocumentRepository;
|
||||
private readonly IRepository<TrialCriterionAdditionalAssessmentType> _trialCriterionAdditionalAssessmentTypeRepository;
|
||||
private readonly IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository;
|
||||
@@ -36,8 +36,8 @@ namespace IRaCIS.Core.Application.Services
|
||||
public TrialDocumentService(IRepository<TrialDocument> trialDocumentRepository,
|
||||
IRepository<TrialDocConfirmedUser> trialDocUserTypeConfirmedUserRepository,
|
||||
IRepository<Trial> trialRepository,
|
||||
ISystemDocumentService systemDocumentService,
|
||||
IRepository<SystemDocConfirmedUser> systemDocConfirmedUserRepository,
|
||||
ISystemDocumentService systemDocumentService,
|
||||
IRepository<SystemDocConfirmedUser> systemDocConfirmedUserRepository,
|
||||
IRepository<TrialCriterionAdditionalAssessmentType> trialCriterionAdditionalAssessmentTypeRepository,
|
||||
IRepository<ReadingQuestionCriterionTrial> readingQuestionCriterionTrialRepository
|
||||
, IRepository<SystemDocument> systemDocumentRepository)
|
||||
@@ -45,8 +45,8 @@ namespace IRaCIS.Core.Application.Services
|
||||
_trialDocumentRepository = trialDocumentRepository;
|
||||
this._trialDocUserTypeConfirmedUserRepository = trialDocUserTypeConfirmedUserRepository;
|
||||
this._trialRepository = trialRepository;
|
||||
this._systemDocumentService = systemDocumentService;
|
||||
this._systemDocConfirmedUserRepository = systemDocConfirmedUserRepository;
|
||||
this._systemDocumentService = systemDocumentService;
|
||||
this._systemDocConfirmedUserRepository = systemDocConfirmedUserRepository;
|
||||
_systemDocumentRepository = systemDocumentRepository;
|
||||
_readingQuestionCriterionTrialRepository = readingQuestionCriterionTrialRepository;
|
||||
_trialCriterionAdditionalAssessmentTypeRepository = trialCriterionAdditionalAssessmentTypeRepository;
|
||||
@@ -64,7 +64,7 @@ namespace IRaCIS.Core.Application.Services
|
||||
var trialDocumentQueryable = _trialDocumentRepository.AsQueryable(true).Where(t => t.TrialId == queryTrialDocument.TrialId)
|
||||
.WhereIf(!string.IsNullOrEmpty(queryTrialDocument.Name), t => t.Name.Contains(queryTrialDocument.Name))
|
||||
.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)
|
||||
.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)
|
||||
{
|
||||
var trialDocQueryable = from trialDoc in _trialDocumentRepository.AsQueryable(true)
|
||||
.WhereIf(querySystemDocument.TrialId!=null,t=>t.TrialId==querySystemDocument.TrialId)
|
||||
.Where(t => t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == _userInfo.UserTypeId) )
|
||||
.WhereIf(querySystemDocument.TrialId != null, t => t.TrialId == querySystemDocument.TrialId)
|
||||
.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
|
||||
new { trialUser.UserId, TrialDocumentId = trialDoc.Id } equals new { UserId = confirm.ConfirmUserId, confirm.TrialDocumentId } into cc
|
||||
|
||||
from confirm in cc.DefaultIfEmpty()
|
||||
select new TrialSignDocView()
|
||||
{
|
||||
TrialCode=trialDoc.Trial.TrialCode,
|
||||
TrialCode = trialDoc.Trial.TrialCode,
|
||||
ResearchProgramNo = trialDoc.Trial.ResearchProgramNo,
|
||||
ExperimentName = trialDoc.Trial.ExperimentName,
|
||||
Id = trialDoc.Id,
|
||||
@@ -116,7 +116,7 @@ namespace IRaCIS.Core.Application.Services
|
||||
.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()
|
||||
{
|
||||
PageIndex=1,
|
||||
PageIndex = 1,
|
||||
IsSigned = false,
|
||||
PageSize=1,
|
||||
Asc=false,
|
||||
SortField="UpdateTime",
|
||||
});
|
||||
PageSize = 1,
|
||||
Asc = false,
|
||||
SortField = "UpdateTime",
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (result.CurrentPageData.Count > 0)
|
||||
@@ -823,7 +823,7 @@ namespace IRaCIS.Core.Application.Services
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[Obsolete]
|
||||
public PageOutput<DocumentUnionWithUserStatView> GetTrialSystemDocumentList(DocumentTrialUnionQuery querySystemDocument)
|
||||
public async Task<PageOutput<DocumentUnionWithUserStatView>> GetTrialSystemDocumentList(DocumentTrialUnionQuery querySystemDocument)
|
||||
{
|
||||
var systemDocumentQueryable = _repository
|
||||
.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(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
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace IRaCIS.Core.Application.Service
|
||||
{
|
||||
GroupId=gropId,
|
||||
LimitEdit=LimitEdit.OnlyBaseLine,
|
||||
DictionaryCode="YesOrNoOrNa",
|
||||
DictionaryCode="YesOrNoOrNE",
|
||||
IsJudgeQuestion=false,
|
||||
IsShowInDicom=false,
|
||||
GlobalReadingShowType=GlobalReadingShowType.NotShow,
|
||||
|
||||
@@ -10,7 +10,6 @@ using IRaCIS.Core.Infrastructure;
|
||||
using DocumentFormat.OpenXml.Presentation;
|
||||
using IRaCIS.Core.Domain.Models;
|
||||
using IRaCIS.Core.Application.Filter;
|
||||
using IRaCIS.Core.Application.MediatR.Handlers;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Newtonsoft.Json;
|
||||
using System.Threading;
|
||||
@@ -206,6 +205,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
||||
study.TrialId = incommand.TrialId;
|
||||
study.SubjectId = incommand.SubjectId;
|
||||
study.SubjectVisitId = incommand.SubjectVisitId;
|
||||
study.IsFromPACS = false;
|
||||
|
||||
//如果因为意外情况,连续点击两次,导致第一次插入了,第二次进来也会插入,在此判断一下
|
||||
var findStudy = await _dicomstudyRepository.FirstOrDefaultAsync(t => t.Id == study.Id);
|
||||
@@ -280,6 +280,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
||||
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());
|
||||
SpecialArchiveStudyDeal(study);
|
||||
modalitys = study.Modalities;
|
||||
|
||||
@@ -5,10 +5,8 @@
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
using IRaCIS.Core.Application.Interfaces;
|
||||
using IRaCIS.Core.Application.MediatR.Handlers;
|
||||
using IRaCIS.Core.Application.ViewModel;
|
||||
using IRaCIS.Core.Infra.EFCore;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
namespace IRaCIS.Core.Application.Service
|
||||
{
|
||||
@@ -18,12 +16,10 @@ namespace IRaCIS.Core.Application.Service
|
||||
[ApiExplorerSettings(GroupName = "Image")]
|
||||
public class SystemAnonymizationService : BaseService, ISystemAnonymizationService
|
||||
{
|
||||
private readonly IMediator _mediator;
|
||||
private readonly IRepository<SystemAnonymization> systemAnonymizationRepository;
|
||||
|
||||
public SystemAnonymizationService(IMediator mediator, IRepository<SystemAnonymization> systemAnonymizationRepository)
|
||||
public SystemAnonymizationService( IRepository<SystemAnonymization> systemAnonymizationRepository)
|
||||
{
|
||||
_mediator = mediator;
|
||||
this.systemAnonymizationRepository = systemAnonymizationRepository;
|
||||
}
|
||||
|
||||
@@ -47,7 +43,6 @@ namespace IRaCIS.Core.Application.Service
|
||||
|
||||
var entity = await _repository.InsertOrUpdateAsync<SystemAnonymization, SystemAnonymizationAddOrEdit>(addOrEditSystemAnonymization, true);
|
||||
|
||||
await _mediator.Send(new AnonymizeCacheRequest());
|
||||
|
||||
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.DTO;
|
||||
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.Interface;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Infra.EFCore.Common;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
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
|
||||
from leftusertype in usertypetemp.DefaultIfEmpty()
|
||||
|
||||
//join trialCriterion in _repository.GetQueryable<ReadingQuestionCriterionTrial>().IgnoreQueryFilters() on data.TrialReadingCriterionId equals trialCriterion.Id into criterion
|
||||
//from leftCriterion in criterion.DefaultIfEmpty()
|
||||
join visttask in _repository.GetQueryable<VisitTask>().IgnoreQueryFilters() on data.VisitTaskId equals visttask.Id into visttasktemp
|
||||
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 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,
|
||||
|
||||
|
||||
SubjectCode = leftsubject.Code,
|
||||
SubjectCode = leftvisttask.BlindSubjectCode.IsNullOrEmpty()? leftsubject.Code: leftvisttask.BlindSubjectCode,
|
||||
SiteCode = lefttrialSite.TrialSiteCode,
|
||||
|
||||
ResearchProgramNo = leftrial.ResearchProgramNo,
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace IRaCIS.Application.Contracts
|
||||
public string RealName { get; set; } = string.Empty;
|
||||
public int? Sex { get; set; } // 1-男 2-女
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// LastLoginIP
|
||||
/// </summary>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using IRaCIS.Application.Contracts;
|
||||
using IRaCIS.Core.Application.MediatR.CommandAndQueries;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
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
|
||||
|
||||
@@ -157,6 +157,8 @@ namespace IRaCIS.Core.Application.Contracts
|
||||
|
||||
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; }
|
||||
|
||||
[DictionaryTranslateAttribute("YesOrNo")]
|
||||
public bool IsConfirmed { get; set; }
|
||||
public bool IsConfirmed => ConfirmTime != null;
|
||||
|
||||
public string RealName { get; set; }
|
||||
|
||||
@@ -308,7 +310,7 @@ namespace IRaCIS.Core.Application.Contracts
|
||||
{
|
||||
if (!ClosedTime.HasValue)
|
||||
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.Service.Inspection.DTO;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
@@ -40,6 +39,6 @@ namespace IRaCIS.Core.Application.Image.QA
|
||||
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.IsPacsConnectConfiged= await _subjectVisitRepository.Where(t=>t.Id==subjectVisitId).AnyAsync(t=>t.Trial.IsPACSConnect && t.Subject.TrialSite.TrialSiteDicomAEList.Any());
|
||||
|
||||
return (list, config);
|
||||
}
|
||||
|
||||
@@ -2,11 +2,9 @@
|
||||
using IRaCIS.Core.Application.Contracts.DTO;
|
||||
using IRaCIS.Core.Application.Filter;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Data;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using WinSCP;
|
||||
using Newtonsoft.Json;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
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}")]
|
||||
//[Authorize(Policy = IRaCISPolicy.PM_APM)]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
public async Task<IResponseOutput> ForwardSVDicomImage(Guid[] subjectVisitIdList)
|
||||
{
|
||||
|
||||
bool isSuccess = false;
|
||||
// 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
|
||||
{
|
||||
// 主机及端口信息后面可以改到 配置文件
|
||||
SessionOptions sessionOptions = new SessionOptions
|
||||
{
|
||||
Protocol = Protocol.Sftp,
|
||||
PortNumber = 8022,
|
||||
HostName = "CS-690-sftp.mint-imaging.com",
|
||||
UserName = "zdong",
|
||||
Password = "Everest@2021",
|
||||
SshHostKeyFingerprint = @"ecdsa-sha2-nistp384 384 59gkjJ5lMwv3jsB8Wz2B35tBAIor5pSd8PcJYtoamPo="
|
||||
};
|
||||
// try
|
||||
// {
|
||||
// // 主机及端口信息后面可以改到 配置文件
|
||||
// SessionOptions sessionOptions = new SessionOptions
|
||||
// {
|
||||
// Protocol = Protocol.Sftp,
|
||||
// PortNumber = 8022,
|
||||
// HostName = "CS-690-sftp.mint-imaging.com",
|
||||
// UserName = "zdong",
|
||||
// Password = "Everest@2021",
|
||||
// SshHostKeyFingerprint = @"ecdsa-sha2-nistp384 384 59gkjJ5lMwv3jsB8Wz2B35tBAIor5pSd8PcJYtoamPo="
|
||||
// };
|
||||
|
||||
using (Session session = new Session())
|
||||
{
|
||||
var studyFolders = (new DirectoryInfo(path)).GetDirectories();
|
||||
// using (Session session = new Session())
|
||||
// {
|
||||
// var studyFolders = (new DirectoryInfo(path)).GetDirectories();
|
||||
|
||||
session.Open(sessionOptions);
|
||||
// session.Open(sessionOptions);
|
||||
|
||||
if (!session.FileExists(targetPath))
|
||||
{
|
||||
session.CreateDirectory(targetPath);
|
||||
}
|
||||
// if (!session.FileExists(targetPath))
|
||||
// {
|
||||
// session.CreateDirectory(targetPath);
|
||||
// }
|
||||
|
||||
|
||||
foreach (var studyFolder in studyFolders)
|
||||
{
|
||||
var targetFolder = Path.Combine(targetPath, studyFolder.Name);
|
||||
// foreach (var studyFolder in studyFolders)
|
||||
// {
|
||||
// var targetFolder = Path.Combine(targetPath, studyFolder.Name);
|
||||
|
||||
if (!session.FileExists(targetFolder))
|
||||
{
|
||||
session.CreateDirectory(targetFolder);
|
||||
}
|
||||
// if (!session.FileExists(targetFolder))
|
||||
// {
|
||||
// session.CreateDirectory(targetFolder);
|
||||
// }
|
||||
|
||||
foreach (var file in studyFolder.GetFiles())
|
||||
{
|
||||
if (file.Extension.Contains("dcm", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
string remoteFilePath =
|
||||
RemotePath.TranslateLocalPathToRemote(file.FullName, studyFolder.FullName, targetFolder);
|
||||
// foreach (var file in studyFolder.GetFiles())
|
||||
// {
|
||||
// if (file.Extension.Contains("dcm", StringComparison.OrdinalIgnoreCase))
|
||||
// {
|
||||
// string remoteFilePath =
|
||||
// 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)
|
||||
{
|
||||
await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.Id == subjectVisitId,
|
||||
u => new SubjectVisit() { ForwardState = ForwardStateEnum.ForwardFailed });
|
||||
// if (!result.IsSuccess)
|
||||
// {
|
||||
// await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.Id == subjectVisitId,
|
||||
// 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,
|
||||
u => new SubjectVisit() { ForwardState = ForwardStateEnum.Forwarded, ForwardUserId = _userInfo.Id, ForwardTime = DateTime.Now });
|
||||
// }
|
||||
// await _subjectVisitRepository.UpdatePartialFromQueryAsync(t => t.Id == subjectVisitId,
|
||||
// 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,
|
||||
u => new SubjectVisit() { ForwardState = ForwardStateEnum.ForwardFailed });
|
||||
// await _subjectVisitRepository.UpdatePartialFromQueryAsync(t => t.Id == subjectVisitId,
|
||||
// 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.Infra.EFCore.Common;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace IRaCIS.Core.Application.Contracts
|
||||
@@ -104,7 +105,9 @@ namespace IRaCIS.Core.Application.Contracts
|
||||
.ThenBy(t=>t.ShowOrder)
|
||||
.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)
|
||||
|
||||
@@ -3,7 +3,7 @@ using AutoMapper.EquivalencyExpression;
|
||||
using IRaCIS.Application.Contracts;
|
||||
using IRaCIS.Core.Application.Contracts;
|
||||
using IRaCIS.Core.Application.Contracts.DTO;
|
||||
using IRaCIS.Core.Application.MediatR.CommandAndQueries;
|
||||
using IRaCIS.Core.Application.MassTransit.Command;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using static IRaCIS.Core.Application.Contracts.SubjectProgressDto;
|
||||
|
||||
|
||||
@@ -637,8 +637,9 @@ namespace IRaCIS.Core.Application.Service
|
||||
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)
|
||||
.Where(x => x.ClinicalDataTrialSet.UploadRole == UploadRole.CRC)
|
||||
|
||||
@@ -255,7 +255,7 @@ namespace IRaCIS.Application.Services
|
||||
var query = _readingClinicalDataRepository.AsQueryable();
|
||||
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
|
||||
{
|
||||
@@ -1227,6 +1227,7 @@ namespace IRaCIS.Application.Services
|
||||
entity.ReadingClinicalDataState = ReadingClinicalDataStatus.HaveUploaded;
|
||||
entity.IsSign = false;
|
||||
entity.FileCount = fileCount;
|
||||
entity.CreateTime=DateTime.Now;
|
||||
var success = await _readingConsistentClinicalDataRepository.SaveChangesAsync();
|
||||
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<IResponseOutput> SignConsistencyAnalysisReadingClinicalData(SignConsistencyAnalysisReadingClinicalDataInDto inDto);
|
||||
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -65,7 +65,9 @@ namespace IRaCIS.Core.Application.Service
|
||||
.WhereIf(inDto.LanguageType != null, x => x.LanguageType == inDto.LanguageType!.Value)
|
||||
.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>
|
||||
|
||||
@@ -398,7 +398,7 @@ namespace IRaCIS.Core.Application.Contracts
|
||||
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();
|
||||
|
||||
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();
|
||||
return result;
|
||||
|
||||
@@ -279,6 +279,8 @@ namespace IRaCIS.Core.Application.Contracts
|
||||
public CriterionType? CriterionType { get; set; }
|
||||
|
||||
public string? PM_EMail { get; set; }
|
||||
|
||||
public List<Guid> TrialIdList { get; set; }=new List<Guid>();
|
||||
}
|
||||
|
||||
public class TrialToBeDoneDto : TrialBaseInfoDto
|
||||
|
||||
@@ -23,6 +23,8 @@ using IRaCIS.Application.Contracts;
|
||||
using SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors;
|
||||
using Newtonsoft.Json;
|
||||
using Microsoft.Extensions.Options;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using ZiggyCreatures.Caching.Fusion;
|
||||
|
||||
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();
|
||||
|
||||
@@ -1390,7 +1392,7 @@ namespace IRaCIS.Core.Application
|
||||
{
|
||||
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);
|
||||
|
||||
@@ -12,6 +12,8 @@ using Microsoft.AspNetCore.Authorization;
|
||||
using System.Linq.Expressions;
|
||||
using System.Linq;
|
||||
using IRaCIS.Core.Domain.Models;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using ZiggyCreatures.Caching.Fusion;
|
||||
|
||||
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(searchParam.SponsorId != null, o => o.SponsorId == searchParam.SponsorId)
|
||||
.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(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)
|
||||
.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);
|
||||
|
||||
@@ -103,7 +105,7 @@ namespace IRaCIS.Application.Services
|
||||
//过滤废除的项目
|
||||
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)
|
||||
|
||||
.ProjectTo<TrialSelectDTO>(_mapper.ConfigurationProvider).ToListAsync();
|
||||
@@ -119,7 +121,7 @@ namespace IRaCIS.Application.Services
|
||||
[HttpGet("{projectId:guid}")]
|
||||
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 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 });
|
||||
|
||||
|
||||
@@ -236,10 +238,9 @@ namespace IRaCIS.Application.Services
|
||||
}
|
||||
|
||||
|
||||
await _repository.AddRangeAsync(needAddBodyPartList,true);
|
||||
await _repository.AddRangeAsync(needAddBodyPartList, true);
|
||||
|
||||
|
||||
_provider.Set(trial.Id.ToString(), StaticData.TrialState.TrialInitializing, TimeSpan.FromDays(7));
|
||||
await _fusionCache.SetAsync(CacheKeys.Trial(trial.Id.ToString()), StaticData.TrialState.TrialInitializing, TimeSpan.FromDays(7));
|
||||
|
||||
return ResponseOutput.Ok(trial);
|
||||
}
|
||||
@@ -589,7 +590,7 @@ namespace IRaCIS.Application.Services
|
||||
|
||||
await _repository.BatchDeleteAsync<VisitTaskReReading>(t => t.OriginalReReadingTask.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();
|
||||
|
||||
@@ -650,7 +651,7 @@ namespace IRaCIS.Application.Services
|
||||
.WhereIf(!string.IsNullOrEmpty(searchModel.Code), o => o.TrialCode.Contains(searchModel.Code))
|
||||
.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))
|
||||
.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);
|
||||
|
||||
@@ -382,7 +382,7 @@ namespace IRaCIS.Application.Contracts
|
||||
|
||||
}
|
||||
|
||||
public class SubmitVisitStudyBindingCommand
|
||||
public class VerifyPacsImageCommand
|
||||
{
|
||||
[NotDefault]
|
||||
public Guid TrialId { get; set; }
|
||||
@@ -396,6 +396,13 @@ namespace IRaCIS.Application.Contracts
|
||||
public List<Guid> SCPStudyIdList { get; set; }
|
||||
}
|
||||
|
||||
public class SubmitVisitStudyBindingCommand: VerifyPacsImageCommand
|
||||
{
|
||||
|
||||
|
||||
public List<Guid> ReUploadSCPStudyIdList { get; set; }
|
||||
}
|
||||
|
||||
public class SubjectVisitSelectQuery
|
||||
{
|
||||
[NotDefault]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using MiniExcelLibs.Attributes;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace IRaCIS.Application.Contracts
|
||||
@@ -103,5 +104,53 @@ namespace IRaCIS.Application.Contracts
|
||||
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 int SeriesCount =>SeriesList.Count;
|
||||
public int SeriesCount => SeriesList.Count;
|
||||
public int InstanceCount { get; set; }
|
||||
|
||||
public bool IsDicom { get; set; } = true;
|
||||
@@ -369,6 +369,16 @@ namespace IRaCIS.Core.Application.Contracts
|
||||
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
|
||||
{
|
||||
|
||||
@@ -54,10 +54,12 @@ namespace IRaCIS.Application.Services
|
||||
private readonly IRepository<SCPStudy> _scpStudyRepository;
|
||||
private readonly IRepository<Subject> _subjectRepository;
|
||||
private readonly IRepository<SubjectVisit> _subjectVisitRepository;
|
||||
private readonly IRepository<Dictionary> _dictionaryRepository;
|
||||
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;
|
||||
_trialRepository = trialRepository;
|
||||
_patientRepository = patientRepository;
|
||||
@@ -75,7 +77,7 @@ namespace IRaCIS.Application.Services
|
||||
[HttpPost]
|
||||
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.CallingAEIP), t => t.CallingAEIP.Contains(inQuery.CallingAEIP))
|
||||
.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>
|
||||
/// <param name="inCommand"></param>
|
||||
/// <param name="_dicomstudyRepository"></param>
|
||||
/// <param name="_dicomSeriesRepository"></param>
|
||||
/// <param name="_dicomInstanceRepository"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[UnitOfWork]
|
||||
[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 subjectVisitId = inCommand.SubjectVisitId;
|
||||
var trialId = inCommand.TrialId;
|
||||
|
||||
|
||||
|
||||
var @lock = _distributedLockProvider.CreateLock($"StudyCode");
|
||||
|
||||
using (await @lock.AcquireAsync())
|
||||
@@ -308,6 +413,7 @@ namespace IRaCIS.Application.Services
|
||||
|
||||
int currentNextCodeInt = dbStudyCodeIntMax + 1;
|
||||
|
||||
//新增的,上传的
|
||||
foreach (var scpStudyId in inCommand.SCPStudyIdList)
|
||||
{
|
||||
|
||||
@@ -315,7 +421,6 @@ namespace IRaCIS.Application.Services
|
||||
|
||||
if (find != null)
|
||||
{
|
||||
|
||||
var newStuty = _mapper.Map<DicomStudy>(find.SCPStudy);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ using IRaCIS.Application.Contracts;
|
||||
using IRaCIS.Core.Application.Filter;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Application.MediatR.CommandAndQueries;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using IRaCIS.Core.Application.Auth;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using IRaCIS.Application.Contracts;
|
||||
using IRaCIS.Core.Application.Contracts;
|
||||
using IRaCIS.Core.Application.Contracts.Dicom.DTO;
|
||||
using IRaCIS.Core.Application.MediatR.CommandAndQueries;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -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.Schema;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace IRaCIS.Core.Domain.Models
|
||||
{
|
||||
|
||||
|
||||
public interface IAggregateRoot;
|
||||
public interface IEntity<TKey>
|
||||
{
|
||||
abstract TKey Id { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public abstract class Entity : IEntity<Guid>
|
||||
{
|
||||
[Key]
|
||||
[Required]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.None)]
|
||||
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 减少实体属性,增加基类
|
||||
|
||||
|
||||
@@ -158,7 +158,8 @@ namespace IRaCIS.Core.Infra.EFCore.Common
|
||||
t.IsTrialBasicLogicConfirmed,
|
||||
t.IsTrialProcessConfirmed,
|
||||
t.IsTrialUrgentConfirmed,
|
||||
t.IsConfigureEmail
|
||||
t.IsConfigureEmail,
|
||||
t.IsTrialPACSConfirmed,
|
||||
}).FirstOrDefaultAsync();
|
||||
switch (_userInfo.RequestUrl)
|
||||
{
|
||||
@@ -172,6 +173,9 @@ namespace IRaCIS.Core.Infra.EFCore.Common
|
||||
case "configTrialBasicInfo/ConfigTrialUrgentInfoConfirm":
|
||||
extraIdentification = $"/{oldentity.IsTrialUrgentConfirmed.ToString()}";
|
||||
break;
|
||||
case "configTrialBasicInfo/ConfigTrialPACSInfoConfirm":
|
||||
extraIdentification = $"/{oldentity.IsTrialPACSConfirmed.ToString()}";
|
||||
break;
|
||||
|
||||
case "TrialEmailNoticeConfig/setTrialEmail":
|
||||
|
||||
|
||||
@@ -511,7 +511,6 @@ namespace IRaCIS.Core.Infra.EFCore
|
||||
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
// 采用触发器的方式 设置 CreateUserId CreateTime UpdateTime UpdateUserId 稽查实体里面没有这四个字段的值 因为先后顺序的原因
|
||||
SetCommonEntityAuditInfo();
|
||||
await AddAudit();
|
||||
|
||||
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; }
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
<PackageReference Include="EntityFrameworkCore.Exceptions.SqlServer" 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="NewId" Version="4.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</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>
|
||||
<PackageReference Include="AutoMapper" Version="13.0.1" />
|
||||
<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.Localization.Abstractions" Version="8.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
|
||||
@@ -5,44 +5,86 @@ using Microsoft.EntityFrameworkCore;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Internal;
|
||||
|
||||
namespace IRaCIS.Core.Infrastructure.Extention
|
||||
{
|
||||
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)
|
||||
{
|
||||
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
|
||||
.Take(pageSize)
|
||||
.ToArray();
|
||||
if (propertyNameList.Count == 0)
|
||||
{
|
||||
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>()
|
||||
{
|
||||
PageIndex = pageIndex,
|
||||
PageSize = pageSize,
|
||||
PageIndex = pageInput.PageIndex,
|
||||
PageSize = pageInput.PageSize,
|
||||
TotalCount = count,
|
||||
CurrentPageData = items
|
||||
};
|
||||
@@ -50,8 +92,10 @@ namespace IRaCIS.Core.Infrastructure.Extention
|
||||
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)
|
||||
@@ -68,7 +112,7 @@ namespace IRaCIS.Core.Infrastructure.Extention
|
||||
pageSize = 10;
|
||||
}
|
||||
|
||||
var count = await source.CountAsync(cancellationToken).ConfigureAwait(false);
|
||||
var count = await source.CountAsync().ConfigureAwait(false);
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
@@ -90,7 +134,7 @@ namespace IRaCIS.Core.Infrastructure.Extention
|
||||
source = source.Skip((pageNumber - 1) * pageSize);
|
||||
var items = await source
|
||||
.Take(pageSize)
|
||||
.ToArrayAsync(cancellationToken)
|
||||
.ToArrayAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
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)
|
||||
{
|
||||
if (pageIndex <= 0)
|
||||
{
|
||||
pageIndex = 1;
|
||||
}
|
||||
if (pageSize <= 0)
|
||||
{
|
||||
pageSize = 10;
|
||||
}
|
||||
var count = source.Count();
|
||||
#region 同步方法废弃
|
||||
////单字段排序
|
||||
//public static PageOutput<T> ToPagedList<T>(this IQueryable<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;
|
||||
}
|
||||
|
||||
//多字段排序异步 ["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);
|
||||
}
|
||||
// if (count == 0)
|
||||
// {
|
||||
// return new PageOutput<T>() { CurrentPageData = new T[0] };
|
||||
// }
|
||||
|
||||
|
||||
source = source.Skip((pageNumber - 1) * pageSize);
|
||||
var items = await source
|
||||
.Take(pageSize)
|
||||
.ToArrayAsync(cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
// var propName = string.IsNullOrWhiteSpace(defaultSortFiled) ? "Id" : defaultSortFiled;
|
||||
|
||||
var pagedList = new PageOutput<T>()
|
||||
{
|
||||
PageIndex = pageNumber,
|
||||
PageSize = pageSize,
|
||||
TotalCount = count,
|
||||
CurrentPageData = items
|
||||
};
|
||||
// source = isAsc ? source.OrderBy(propName) : source.OrderBy(propName + " desc");
|
||||
|
||||
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; }
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -15,6 +15,7 @@ public static class StaticData
|
||||
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 Zh_CN_Json = "zh-CN.json";
|
||||
|
||||
@@ -70,9 +71,11 @@ public static class StaticData
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 字典表项固定值
|
||||
public static readonly string Title = "Title";
|
||||
#region 字典表项固定值
|
||||
|
||||
public static readonly string Title = "Title";
|
||||
public static readonly string ReadingType = "ReadingType";
|
||||
public static readonly string Subspeciality = "Subspeciality";
|
||||
|
||||
@@ -80,6 +83,7 @@ public static class StaticData
|
||||
public static readonly string Criterion = "Criterion";
|
||||
public static readonly string ReviewType = "ReviewType";
|
||||
public static readonly string ReadingStandard = "ReadingStandard";
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
@@ -72,11 +72,9 @@ namespace IRaCIS.Core.Application.Service
|
||||
var <#=char.ToLower(tableName[0]) + tableName.Substring(1)#>Queryable =
|
||||
|
||||
_<#=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
|
||||
.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrWhiteSpace(inQuery.SortField) ? nameof(<#=tableName#>View.Id) : inQuery.SortField,
|
||||
inQuery.Asc);
|
||||
var pageList= await <#=char.ToLower(tableName[0]) + tableName.Substring(1)#>Queryable.ToPagedListAsync(inQuery);
|
||||
|
||||
return pageList;
|
||||
}
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ steps:
|
||||
- name: build-uat-irc
|
||||
commands:
|
||||
- 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:
|
||||
branch:
|
||||
|
||||
Reference in New Issue
Block a user