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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,19 +6,8 @@
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
<<<<<<<< HEAD:IRaCIS.Core.API/appsettings.US_Test_IRC.json
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=106.14.89.110,1435;Database=Test_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=106.14.89.110,1435;Database=Test_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
},
|
||||
|
||||
"ObjectStoreService": {
|
||||
|
||||
"ObjectStoreUse": "MinIO",
|
||||
========
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "AliyunOSS",
|
||||
>>>>>>>> Test_IRC_Net8:IRC.Core.SCP/appsettings.Test_IRC_SCP.json
|
||||
"AliyunOSS": {
|
||||
"regionId": "cn-shanghai",
|
||||
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||
@@ -32,22 +21,6 @@
|
||||
},
|
||||
|
||||
"MinIO": {
|
||||
<<<<<<<< HEAD:IRaCIS.Core.API/appsettings.US_Test_IRC.json
|
||||
//"endPoint": "hir-oss.uat.extimaging.com",
|
||||
//"port": "443",
|
||||
//"useSSL": true,
|
||||
//"viewEndpoint": "https://hir-oss.uat.extimaging.com/hir-uat",
|
||||
|
||||
"endPoint": "47.117.164.182",
|
||||
"port": "9001",
|
||||
"useSSL": false,
|
||||
"viewEndpoint": "http://47.117.164.182:9001/test-irc-us",
|
||||
|
||||
"accessKey": "b9Ul0e98xPzt6PwRXA1Q",
|
||||
"secretKey": "DzMaU2L4OXl90uytwOmDXF2encN0Jf4Nxu2XkYqQ",
|
||||
"bucketName": "test-irc-us"
|
||||
|
||||
========
|
||||
"endPoint": "106.14.89.110",
|
||||
"port": "9001",
|
||||
"useSSL": false,
|
||||
@@ -55,7 +28,6 @@
|
||||
"secretKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
|
||||
"bucketName": "hir-test",
|
||||
"viewEndpoint": "http://106.14.89.110:9001/hir-test/"
|
||||
>>>>>>>> Test_IRC_Net8:IRC.Core.SCP/appsettings.Test_IRC_SCP.json
|
||||
},
|
||||
|
||||
"AWS": {
|
||||
@@ -83,31 +55,6 @@
|
||||
"OpenLoginLimit": false,
|
||||
"LoginMaxFailCount": 5,
|
||||
|
||||
<<<<<<<< HEAD:IRaCIS.Core.API/appsettings.US_Test_IRC.json
|
||||
"LoginFailLockMinutes": 30,
|
||||
"AutoLoginOutMinutes": 60,
|
||||
|
||||
"ContinuousReadingTimeMin": 120,
|
||||
|
||||
"ReadingRestTimeMin": 10
|
||||
},
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 587,
|
||||
"Host": "smtp-mail.outlook.com",
|
||||
"FromEmail": "donotreply@elevateimaging.ai",
|
||||
"FromName": "LiLi",
|
||||
"AuthorizationCode": "Q#669869497420ul",
|
||||
|
||||
"OrganizationName": "Elevate Imaging",
|
||||
"OrganizationNameCN": "Elevate Imaging",
|
||||
"CompanyName": "Elevate Imaging Inc.",
|
||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||
"CompanyShortName": "Elevate Imaging",
|
||||
"CompanyShortNameCN": "展影医疗",
|
||||
"SiteUrl": "https://lili.test.elevateimaging.ai/login"
|
||||
}
|
||||
========
|
||||
"LoginFailLockMinutes": 30
|
||||
|
||||
},
|
||||
@@ -118,7 +65,6 @@
|
||||
"FromEmail": "test-study@extimaging.com",
|
||||
"FromName": "Test_Study",
|
||||
"AuthorizationCode": "zhanying123",
|
||||
>>>>>>>> Test_IRC_Net8:IRC.Core.SCP/appsettings.Test_IRC_SCP.json
|
||||
|
||||
"SiteUrl": "http://study.test.extimaging.com/login"
|
||||
},
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
}
|
||||
},
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "MinIO",
|
||||
"ObjectStoreUse": "AliyunOSS",
|
||||
"AliyunOSS": {
|
||||
"regionId": "cn-shanghai",
|
||||
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||
|
||||
@@ -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,11 +15,15 @@ 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);
|
||||
|
||||
|
||||
|
||||
//automapper.ForAllMaps((a, b) => b.ForAllMembers(opt => opt.Condition((src, dest, srcMember, desMenber) =>
|
||||
//{
|
||||
// //// Can test When Guid? -> Guid if source is null will change to Guid.Empty
|
||||
@@ -27,7 +32,7 @@ namespace IRaCIS.Core.API
|
||||
// // not want to map a null Guid? value to db Guid value
|
||||
//})));
|
||||
#endregion
|
||||
|
||||
|
||||
}, typeof(QCConfig).Assembly);
|
||||
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -68,10 +68,5 @@
|
||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||
"CompanyShortName": "Extensive Imaging",
|
||||
"CompanyShortNameCN": "展影医疗"
|
||||
},
|
||||
"SystemPacsConfig": {
|
||||
"Port": "11113",
|
||||
"IP": "101.132.193.237"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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,8 +85,9 @@ namespace IRaCIS.Core.Application
|
||||
[MemberNotNull(nameof(_localizer))]
|
||||
public IStringLocalizer _localizer { get; set; }
|
||||
|
||||
[MemberNotNull(nameof(_fusionCache))]
|
||||
public IFusionCache _fusionCache { get; set; }
|
||||
|
||||
|
||||
}
|
||||
|
||||
[TypeFilter(typeof(UnifiedApiResultFilter))]
|
||||
@@ -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,35 +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 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"]));
|
||||
@@ -85,7 +88,7 @@ namespace IRaCIS.Core.Application.Filter
|
||||
}
|
||||
else
|
||||
{
|
||||
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
||||
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||
}
|
||||
|
||||
@@ -116,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"]));
|
||||
}
|
||||
|
||||
@@ -141,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();
|
||||
@@ -177,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();
|
||||
}
|
||||
|
||||
@@ -69,12 +69,8 @@ namespace IRaCIS.Application.Services.BusinessFilter
|
||||
{
|
||||
var result = objectResult.Value as IResponseOutput;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(result.LocalizedInfo))
|
||||
{
|
||||
//统一在这里记录国际化的日志信息
|
||||
_logger.LogWarning($"{result.LocalizedInfo}");
|
||||
}
|
||||
|
||||
//统一在这里记录国际化的日志信息
|
||||
_logger.LogWarning($"{result.LocalizedInfo}");
|
||||
}
|
||||
|
||||
else if (statusCode != 200 && !(objectResult.Value is IResponseOutput))
|
||||
|
||||
@@ -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,21 +13313,6 @@
|
||||
维护 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>
|
||||
缓存项目状态--之前是启动的时候就获取所有的项目进行缓存,加上定时任务刷新,现在的话,改为是按照需要进行缓存请求数据库
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
+26
-15
@@ -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)
|
||||
@@ -190,7 +199,7 @@ namespace IRaCIS.Core.Application.MediatR.Handlers
|
||||
dbSV.CheckUserId = _userInfo.Id;
|
||||
dbSV.CheckPassedTime = DateTime.Now;
|
||||
dbSV.CheckChallengeState = CheckChanllengeTypeEnum.Closed;
|
||||
|
||||
|
||||
//---核对EDC数据,完全一致
|
||||
dbSV.CheckResult = _localizer["ConsistencyVerification_EDCB"];
|
||||
//---自动核查通过
|
||||
@@ -274,11 +283,13 @@ namespace IRaCIS.Core.Application.MediatR.Handlers
|
||||
|
||||
}
|
||||
await _subjectVisitRepository.SaveChangesAsync();
|
||||
return "OK";
|
||||
|
||||
//await context.RespondAsync<ConsistenCheckResult>(new
|
||||
//{
|
||||
|
||||
//});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -33,6 +33,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
|
||||
public class TaskConsistentRuleBasic : TaskConsistentRuleAddOrEdit
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class SubjectGeneratedTask
|
||||
@@ -287,14 +288,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
}
|
||||
|
||||
|
||||
public class GetConsistentRuleOut
|
||||
{
|
||||
public TaskConsistentRuleBasic? ConsistentRuleBasic { get; set; }
|
||||
/// <summary>
|
||||
/// 任务展示访视 读片任务显示是否顺序
|
||||
/// </summary>
|
||||
public ReadingOrder IsReadingTaskViewInOrder { get; set; } = ReadingOrder.InOrder;
|
||||
}
|
||||
|
||||
|
||||
///<summary>TaskConsistentRuleQuery 列表查询参数模型</summary>
|
||||
public class TaskConsistentRuleQuery
|
||||
|
||||
@@ -34,7 +34,6 @@ namespace IRaCIS.Core.Application.Service
|
||||
private readonly IRepository<TaskConsistentRule> _taskConsistentRuleRepository;
|
||||
private readonly IRepository<VisitTask> _visitTaskRepository;
|
||||
private readonly IRepository<ReadingConsistentClinicalData> _readingConsistentClinicalDataRepository;
|
||||
private readonly IRepository<ReadingQuestionCriterionTrial> _trialReadingCriterionRepository;
|
||||
private readonly IReadingClinicalDataService _readingClinicalDataService;
|
||||
private readonly IRepository<SubjectUser> _subjectUserRepository;
|
||||
private readonly IRepository<Subject> _subjectRepository;
|
||||
@@ -50,7 +49,6 @@ namespace IRaCIS.Core.Application.Service
|
||||
|
||||
public TaskConsistentRuleService(IRepository<VisitTask> visitTaskRepository,
|
||||
IRepository<ReadingConsistentClinicalData> readingConsistentClinicalDataRepository,
|
||||
IRepository<ReadingQuestionCriterionTrial> trialReadingCriterionRepository,
|
||||
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)
|
||||
@@ -58,7 +56,6 @@ namespace IRaCIS.Core.Application.Service
|
||||
_taskConsistentRuleRepository = taskConsistentRuleRepository;
|
||||
_visitTaskRepository = visitTaskRepository;
|
||||
this._readingConsistentClinicalDataRepository = readingConsistentClinicalDataRepository;
|
||||
this._trialReadingCriterionRepository = trialReadingCriterionRepository;
|
||||
this._readingClinicalDataService = readingClinicalDataService;
|
||||
_subjectUserRepository = subjectUserRepository;
|
||||
_subjectRepository = subjectRepository;
|
||||
@@ -785,16 +782,9 @@ namespace IRaCIS.Core.Application.Service
|
||||
|
||||
|
||||
[HttpPost]
|
||||
public async Task<GetConsistentRuleOut> GetConsistentRule(TaskConsistentRuleQuery inQuery)
|
||||
public async Task<TaskConsistentRuleBasic?> GetConsistentRule(TaskConsistentRuleQuery inQuery)
|
||||
{
|
||||
|
||||
var IsReadingTaskViewInOrder = await _trialReadingCriterionRepository.Where(x => x.Id == inQuery.TrialReadingCriterionId).Select(x => x.IsReadingTaskViewInOrder).FirstNotNullAsync();
|
||||
var result = await _taskConsistentRuleRepository.Where(t => t.TrialId == inQuery.TrialId && t.IsSelfAnalysis == inQuery.IsSelfAnalysis && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId).ProjectTo<TaskConsistentRuleBasic>(_mapper.ConfigurationProvider).FirstOrDefaultAsync();
|
||||
return new GetConsistentRuleOut()
|
||||
{
|
||||
ConsistentRuleBasic = result,
|
||||
IsReadingTaskViewInOrder = IsReadingTaskViewInOrder
|
||||
};
|
||||
return await _taskConsistentRuleRepository.Where(t => t.TrialId == inQuery.TrialId && t.IsSelfAnalysis == inQuery.IsSelfAnalysis && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId).ProjectTo<TaskConsistentRuleBasic>(_mapper.ConfigurationProvider).FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ namespace IRaCIS.Application.Services
|
||||
|
||||
public async Task<EmailNoticeConfig> GetEmailConfigInfoAsync(EmailBusinessScenario scenario)
|
||||
{
|
||||
var configInfo = await _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario).Include(t => t.EmailNoticeUserTypeList).FirstOrDefaultAsync();
|
||||
var configInfo = await _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario).Include(t=>t.EmailNoticeUserTypeList).FirstOrDefaultAsync();
|
||||
|
||||
if (configInfo == null)
|
||||
{
|
||||
@@ -758,13 +758,11 @@ namespace IRaCIS.Application.Services
|
||||
|
||||
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||
|
||||
var emialScenario = feedBack.VisitTaskId != null ? EmailBusinessScenario.IRImageError : (feedBack.SubjectVisitId != null ? EmailBusinessScenario.TrialSubjectVisitFeedBack : (feedBack.TrialId != null ? EmailBusinessScenario.TrialFeedBack : EmailBusinessScenario.SysFeedBack));
|
||||
|
||||
var emailConfigInfo = await GetEmailConfigInfoAsync(emialScenario);
|
||||
var emailConfigInfo = await GetEmailConfigInfoAsync(feedBack.VisitTaskId != null? EmailBusinessScenario.IRImageError:(feedBack.TrialId != null? EmailBusinessScenario.TrialFeedBack: EmailBusinessScenario.SysFeedBack));
|
||||
|
||||
var userTypeEnumList = emailConfigInfo.EmailNoticeUserTypeList.Where(t => t.EmailUserType == EmailUserType.To).Select(t => t.UserType).ToList();
|
||||
|
||||
var emailList = await _repository.Where<User>(t => userTypeEnumList.Contains(t.UserTypeEnum) &&
|
||||
var emailList = await _repository.Where<User>(t => userTypeEnumList.Contains(t.UserTypeEnum) &&
|
||||
(isHaveTrialId ? t.UserTrials.Any(t => t.TrialId == feedBack.TrialId) : true)).Select(t => new { t.EMail, t.UserTypeEnum, t.FullName }).ToListAsync();
|
||||
|
||||
|
||||
@@ -773,11 +771,10 @@ namespace IRaCIS.Application.Services
|
||||
messageToSend.To.Add(new MailboxAddress(email.FullName, email.EMail));
|
||||
}
|
||||
|
||||
var userNames = string.Join(',', emailList.Select(t => t.FullName));
|
||||
|
||||
//影像阅片反馈 pm
|
||||
if (feedBack.VisitTaskId != null)
|
||||
{
|
||||
var userNames = string.Join(',', emailList.Where(email => email.UserTypeEnum == UserTypeEnum.ProjectManager).Select(t => t.FullName));
|
||||
|
||||
var emailType = await _repository.Where<Dictionary>(t => t.Parent.Code == "Email_BusinessScenario" && t.ParentId != null && t.Code == ((int)EmailBusinessScenario.IRImageError).ToString()).Select(t => _userInfo.IsEn_Us ? t.Value : t.ValueCN).FirstOrDefaultAsync();
|
||||
|
||||
@@ -786,7 +783,7 @@ namespace IRaCIS.Application.Services
|
||||
|
||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||
{
|
||||
var topicStr = string.Format(input.topicStr, info.ResearchProgramNo, info.SubejctCode, info.VisitName);
|
||||
var topicStr = string.Format(input.topicStr, info.SubejctCode, info.VisitName, info.ResearchProgramNo);
|
||||
|
||||
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
||||
userNames,
|
||||
@@ -807,38 +804,10 @@ namespace IRaCIS.Application.Services
|
||||
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.IRImageError, messageToSend, emailConfigFunc);
|
||||
|
||||
}
|
||||
else if (feedBack.SubjectVisitId != null)
|
||||
{
|
||||
var emailType = await _repository.Where<Dictionary>(t => t.Parent.Code == "Email_BusinessScenario" && t.ParentId != null && t.Code == ((int)EmailBusinessScenario.TrialSubjectVisitFeedBack).ToString()).Select(t => _userInfo.IsEn_Us ? t.Value : t.ValueCN).FirstOrDefaultAsync();
|
||||
|
||||
|
||||
var info = await _repository.Where<SubjectVisit>(t => t.Id == feedBack.SubjectVisitId).Select(t => new { t.Trial.ResearchProgramNo, t.Trial.TrialCode, SubejctCode = t.Subject.Code, t.VisitName }).FirstNotNullAsync();
|
||||
|
||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||
{
|
||||
var topicStr = string.Format(input.topicStr, info.ResearchProgramNo, info.SubejctCode, info.VisitName);
|
||||
|
||||
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
||||
userNames,
|
||||
info.TrialCode,
|
||||
info.SubejctCode,
|
||||
info.VisitName,
|
||||
feedBack.CreateUser.UserTypeRole.UserTypeShortName,
|
||||
feedBack.CreateUser.FullName,
|
||||
emailType,
|
||||
feedBack.QuestionDescription,
|
||||
_systemEmailConfig.SiteUrl
|
||||
);
|
||||
|
||||
return (topicStr, htmlBodyStr);
|
||||
};
|
||||
|
||||
|
||||
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.TrialSubjectVisitFeedBack, messageToSend, emailConfigFunc);
|
||||
}
|
||||
//项目相关的反馈 pm admin
|
||||
else if (feedBack.TrialId != null)
|
||||
{
|
||||
var userNames = string.Join(',', emailList.Where(email => email.UserTypeEnum == UserTypeEnum.ProjectManager || email.UserTypeEnum == UserTypeEnum.Admin).Select(t => t.FullName));
|
||||
|
||||
var emailType = await _repository.Where<Dictionary>(t => t.Parent.Code == "Email_BusinessScenario" && t.ParentId != null && t.Code == ((int)EmailBusinessScenario.TrialFeedBack).ToString()).Select(t => _userInfo.IsEn_Us ? t.Value : t.ValueCN).FirstOrDefaultAsync();
|
||||
|
||||
@@ -866,10 +835,11 @@ namespace IRaCIS.Application.Services
|
||||
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.TrialFeedBack, messageToSend, emailConfigFunc);
|
||||
|
||||
}
|
||||
//项目无关的反馈 admin
|
||||
//项目无关的反馈 admin zyss
|
||||
else
|
||||
{
|
||||
|
||||
var userNames = string.Join(',', emailList.Where(email => email.UserTypeEnum == UserTypeEnum.ZYSS || email.UserTypeEnum == UserTypeEnum.Admin).Select(t => t.FullName));
|
||||
|
||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -142,19 +142,19 @@ namespace IRaCIS.Core.Application.Services
|
||||
PageSize = 1,
|
||||
})).Data;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -90,7 +90,6 @@ namespace IRaCIS.Core.Application.Service
|
||||
.ForMember(o => o.IsReading, t => t.MapFrom(u => u.DicomSerie.IsReading));
|
||||
CreateMap<DicomStudy, DicomStudyDTO>();
|
||||
CreateMap<DicomSeries, DicomSeriesDTO>();
|
||||
CreateMap<SCPSeries, DicomSeriesDTO>();
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -113,7 +113,6 @@ namespace IRaCIS.Core.Application.Service
|
||||
|
||||
var entity = await _userFeedBackRepository.InsertOrUpdateAsync(addOrEditUserFeedBack, true);
|
||||
|
||||
//任务反馈的添加更新都需要发送邮件,其他的是添加的时候发送
|
||||
if (addOrEditUserFeedBack.VisitTaskId != null || addOrEditUserFeedBack.Id == null)
|
||||
{
|
||||
await mailService.UserFeedBackMail(entity.Id);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -294,7 +294,7 @@ namespace IRaCIS.Core.Application.Contracts
|
||||
|
||||
public string Content { get; set; } = string.Empty;
|
||||
|
||||
[DictionaryTranslateAttribute("ChallengeIsClosed")]
|
||||
[DictionaryTranslateAttribute("YesOrNo")]
|
||||
public bool IsClosed { get; set; }
|
||||
|
||||
public DateTime? ClosedTime { get; set; }
|
||||
@@ -310,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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -103,8 +104,10 @@ namespace IRaCIS.Core.Application.Contracts
|
||||
.OrderByDescending(x=>x.LanguageType)
|
||||
.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)
|
||||
|
||||
+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>
|
||||
|
||||
@@ -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,8 +1241,8 @@ 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();
|
||||
|
||||
return ResponseOutput.Ok();
|
||||
@@ -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 });
|
||||
|
||||
|
||||
@@ -234,12 +236,11 @@ namespace IRaCIS.Application.Services
|
||||
{
|
||||
item.TrialId = trial.Id;
|
||||
}
|
||||
|
||||
|
||||
await _repository.AddRangeAsync(needAddBodyPartList,true);
|
||||
|
||||
|
||||
_provider.Set(trial.Id.ToString(), StaticData.TrialState.TrialInitializing, TimeSpan.FromDays(7));
|
||||
await _repository.AddRangeAsync(needAddBodyPartList, true);
|
||||
|
||||
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);
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -69,43 +69,6 @@ namespace IRaCIS.Application.Services
|
||||
}
|
||||
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IResponseOutput<List<DicomSeriesDTO>>> GetPatientSeriesList(Guid scpStudyId,
|
||||
[FromServices] IRepository<SCPSeries> _seriesRepository,
|
||||
[FromServices] IRepository<SCPInstance> _instanceRepository
|
||||
)
|
||||
{
|
||||
|
||||
var seriesList = await _seriesRepository.Where(s => s.StudyId == scpStudyId).OrderBy(s => s.SeriesNumber).
|
||||
ThenBy(s => s.SeriesTime).ThenBy(s => s.CreateTime)
|
||||
.ProjectTo<DicomSeriesDTO>(_mapper.ConfigurationProvider).ToListAsync();
|
||||
|
||||
var instanceList = await _instanceRepository.Where(s => s.StudyId == scpStudyId).OrderBy(t => t.SeriesId).ThenBy(t => t.InstanceNumber)
|
||||
.ThenBy(s => s.InstanceTime).ThenBy(s => s.CreateTime)
|
||||
.Select(t => new { t.SeriesId, t.Id, t.Path, t.NumberOfFrames, t.InstanceNumber }).ToListAsync();//.GroupBy(u => u.SeriesId);
|
||||
|
||||
foreach (var series in seriesList)
|
||||
{
|
||||
|
||||
series.InstanceInfoList = instanceList.Where(t => t.SeriesId == series.Id).OrderBy(t => t.InstanceNumber).Select(k =>
|
||||
new InstanceBasicInfo()
|
||||
{
|
||||
Id = k.Id,
|
||||
NumberOfFrames = k.NumberOfFrames,
|
||||
//HtmlPath = string.Empty,
|
||||
Path = k.Path,
|
||||
InstanceNumber = k.InstanceNumber,
|
||||
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
var study = await _scpStudyRepository.FindAsync(scpStudyId);
|
||||
|
||||
return ResponseOutput.Ok(seriesList, study);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// scp 影像推送记录表
|
||||
/// </summary>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -91,11 +91,7 @@ namespace IRaCIS.Core.Domain.Share
|
||||
|
||||
SysFeedBack=26,
|
||||
|
||||
TrialFeedBack=27,
|
||||
|
||||
TrialSubjectVisitFeedBack = 28,
|
||||
|
||||
|
||||
TrialFeedBack=27
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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 减少实体属性,增加基类
|
||||
|
||||
|
||||
@@ -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>() };
|
||||
}
|
||||
// if (count == 0)
|
||||
// {
|
||||
// return new PageOutput<T>() { CurrentPageData = new T[0] };
|
||||
// }
|
||||
|
||||
var propName = string.IsNullOrWhiteSpace(defaultSortFiled) ? "Id" : defaultSortFiled;
|
||||
|
||||
IQueryable<T> sourceQuery = isAsc ? source.AsQueryable().OrderBy(propName) : source.AsQueryable().OrderBy(propName + " desc");
|
||||
// var propName = string.IsNullOrWhiteSpace(defaultSortFiled) ? "Id" : defaultSortFiled;
|
||||
|
||||
sourceQuery = sourceQuery.Skip((pageIndex - 1) * pageSize);
|
||||
// source = isAsc ? source.OrderBy(propName) : source.OrderBy(propName + " desc");
|
||||
|
||||
var items = sourceQuery
|
||||
.Take(pageSize)
|
||||
.ToArray();
|
||||
// source = source.Skip((pageIndex - 1) * pageSize);
|
||||
|
||||
var pagedList = new PageOutput<T>()
|
||||
{
|
||||
PageIndex = pageIndex,
|
||||
PageSize = pageSize,
|
||||
TotalCount = count,
|
||||
CurrentPageData = items
|
||||
};
|
||||
// var items = source
|
||||
// .Take(pageSize)
|
||||
// .ToArray();
|
||||
|
||||
return pagedList;
|
||||
}
|
||||
// var pagedList = new PageOutput<T>()
|
||||
// {
|
||||
// PageIndex = pageIndex,
|
||||
// PageSize = pageSize,
|
||||
// TotalCount = count,
|
||||
// CurrentPageData = items
|
||||
// };
|
||||
|
||||
//多字段排序 ["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();
|
||||
// return pagedList;
|
||||
//}
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
return new PageOutput<T>() { CurrentPageData = new T[0] };
|
||||
}
|
||||
//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();
|
||||
|
||||
var sortString = string.Join(',', sortArray);
|
||||
// if (count == 0)
|
||||
// {
|
||||
// return new PageOutput<T>() { CurrentPageData = new List<T>() };
|
||||
// }
|
||||
|
||||
source.OrderBy(sortString);
|
||||
// var propName = string.IsNullOrWhiteSpace(defaultSortFiled) ? "Id" : defaultSortFiled;
|
||||
|
||||
source = source.Skip((pageIndex - 1) * pageSize);
|
||||
// IQueryable<T> sourceQuery = isAsc ? source.AsQueryable().OrderBy(propName) : source.AsQueryable().OrderBy(propName + " desc");
|
||||
|
||||
var items = source
|
||||
.Take(pageSize)
|
||||
.ToArray();
|
||||
// sourceQuery = sourceQuery.Skip((pageIndex - 1) * pageSize);
|
||||
|
||||
var pagedList = new PageOutput<T>()
|
||||
{
|
||||
PageIndex = pageIndex,
|
||||
PageSize = pageSize,
|
||||
TotalCount = count,
|
||||
CurrentPageData = items
|
||||
};
|
||||
// var items = sourceQuery
|
||||
// .Take(pageSize)
|
||||
// .ToArray();
|
||||
|
||||
return pagedList;
|
||||
}
|
||||
// var pagedList = new PageOutput<T>()
|
||||
// {
|
||||
// PageIndex = pageIndex,
|
||||
// PageSize = pageSize,
|
||||
// TotalCount = count,
|
||||
// CurrentPageData = items
|
||||
// };
|
||||
|
||||
//多字段排序异步 ["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;
|
||||
}
|
||||
// return pagedList;
|
||||
//}
|
||||
|
||||
var count = await source.CountAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
return new PageOutput<T>() { CurrentPageData = new T[0] };
|
||||
}
|
||||
////多字段排序 ["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(sortArray.Count()>0)
|
||||
{
|
||||
var sortString = string.Join(',', sortArray);
|
||||
// if (count == 0)
|
||||
// {
|
||||
// return new PageOutput<T>() { CurrentPageData = new T[0] };
|
||||
// }
|
||||
|
||||
source = source.OrderBy(sortString);
|
||||
}
|
||||
|
||||
// var sortString = string.Join(',', sortArray);
|
||||
|
||||
source = source.Skip((pageNumber - 1) * pageSize);
|
||||
var items = await source
|
||||
.Take(pageSize)
|
||||
.ToArrayAsync(cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
// source.OrderBy(sortString);
|
||||
|
||||
var pagedList = new PageOutput<T>()
|
||||
{
|
||||
PageIndex = pageNumber,
|
||||
PageSize = pageSize,
|
||||
TotalCount = count,
|
||||
CurrentPageData = items
|
||||
};
|
||||
// source = source.Skip((pageIndex - 1) * pageSize);
|
||||
|
||||
return pagedList;
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user