Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
commit
c988ca0bca
|
@ -4,6 +4,7 @@ using IRaCIS.Core.Infra.EFCore;
|
||||||
using Medallion.Threading;
|
using Medallion.Threading;
|
||||||
using Medallion.Threading.SqlServer;
|
using Medallion.Threading.SqlServer;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
@ -15,11 +16,12 @@ namespace IRaCIS.Core.SCP
|
||||||
{
|
{
|
||||||
services.AddHttpContextAccessor();
|
services.AddHttpContextAccessor();
|
||||||
services.AddScoped<IUserInfo, UserInfo>();
|
services.AddScoped<IUserInfo, UserInfo>();
|
||||||
|
services.AddScoped<ISaveChangesInterceptor, AuditEntityInterceptor>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//这个注入没有成功--注入是没问题的,构造函数也只是支持参数就好,错在注入的地方不能写DbContext
|
//这个注入没有成功--注入是没问题的,构造函数也只是支持参数就好,错在注入的地方不能写DbContext
|
||||||
//Web程序中通过重用池中DbContext实例可提高高并发场景下的吞吐量, 这在概念上类似于ADO.NET Provider原生的连接池操作方式,具有节省DbContext实例化成本的优点
|
//Web程序中通过重用池中DbContext实例可提高高并发场景下的吞吐量, 这在概念上类似于ADO.NET Provider原生的连接池操作方式,具有节省DbContext实例化成本的优点
|
||||||
services.AddDbContextPool<IRaCISDBContext>(options =>
|
services.AddDbContextPool<IRaCISDBContext>((sp, options) =>
|
||||||
{
|
{
|
||||||
// 在控制台
|
// 在控制台
|
||||||
//public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); });
|
//public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); });
|
||||||
|
@ -35,6 +37,7 @@ namespace IRaCIS.Core.SCP
|
||||||
options.EnableSensitiveDataLogging();
|
options.EnableSensitiveDataLogging();
|
||||||
|
|
||||||
options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor());
|
options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor());
|
||||||
|
options.AddInterceptors(sp.GetServices<ISaveChangesInterceptor>());
|
||||||
|
|
||||||
options.UseProjectables();
|
options.UseProjectables();
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,10 @@ using IRaCIS.Core.Application.Service.ImageAndDoc;
|
||||||
using IP2Region.Net.Abstractions;
|
using IP2Region.Net.Abstractions;
|
||||||
using IP2Region.Net.XDB;
|
using IP2Region.Net.XDB;
|
||||||
using IRaCIS.Core.Application.BusinessFilter;
|
using IRaCIS.Core.Application.BusinessFilter;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using IRaCIS.Core.Infrastructure.Extention;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Microsoft.AspNetCore.Diagnostics;
|
||||||
|
|
||||||
|
|
||||||
#region 获取环境变量
|
#region 获取环境变量
|
||||||
|
@ -164,6 +168,8 @@ builder.Services.AddSingleton<IUserIdProvider, IRaCISUserIdProvider>();
|
||||||
|
|
||||||
builder.Services.AddSingleton<ISearcher>(new Searcher(CachePolicy.Content, Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources, "ip2region.xdb")));
|
builder.Services.AddSingleton<ISearcher>(new Searcher(CachePolicy.Content, Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources, "ip2region.xdb")));
|
||||||
|
|
||||||
|
//builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
|
||||||
|
//builder.Services.AddProblemDetails();
|
||||||
|
|
||||||
#region 历史废弃配置
|
#region 历史废弃配置
|
||||||
//builder.Services.AddMemoryCache();
|
//builder.Services.AddMemoryCache();
|
||||||
|
@ -190,6 +196,56 @@ var env = app.Environment;
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
// Configure the HTTP request pipeline.
|
||||||
|
|
||||||
|
#region 异常处理 全局业务异常已统一处理了,非业务错误会来到这里 400 -500状态码
|
||||||
|
|
||||||
|
|
||||||
|
//app.UseStatusCodePagesWithReExecute("/Error/{0}");
|
||||||
|
|
||||||
|
app.UseStatusCodePages(async context =>
|
||||||
|
{
|
||||||
|
var code = context.HttpContext.Response.StatusCode;
|
||||||
|
context.HttpContext.Response.ContentType = "application/json";
|
||||||
|
if (code < 500)
|
||||||
|
{
|
||||||
|
await context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk($"Client error, actual request error status code({code})")));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//ResultFilter 里面的异常并不会到这里
|
||||||
|
await context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject((ResponseOutput.NotOk($"Server error , actual request error status code({code})"))));
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
//app.UseExceptionHandler(o => { });
|
||||||
|
|
||||||
|
//这里没生效,原因未知,官方文档也是这种写法,也用了GlobalExceptionHandler 尝试,还是不行,怀疑框架bug
|
||||||
|
//app.UseExceptionHandler(configure =>
|
||||||
|
//{
|
||||||
|
// configure.Run(async context =>
|
||||||
|
// {
|
||||||
|
// var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>();
|
||||||
|
//var ex = exceptionHandlerPathFeature?.Error;
|
||||||
|
//context.Response.ContentType = "application/json";
|
||||||
|
|
||||||
|
//if (ex != null)
|
||||||
|
//{
|
||||||
|
// var errorInfo = $"Exception: {ex.Message}[{ex.StackTrace}]" + (ex.InnerException != null ? $" InnerException: {ex.InnerException.Message}[{ex.InnerException.StackTrace}]" : "");
|
||||||
|
|
||||||
|
// await context.Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk($"{ex?.Message}")));
|
||||||
|
|
||||||
|
// Log.Logger.Error(errorInfo);
|
||||||
|
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
// });
|
||||||
|
//});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
//本地化
|
//本地化
|
||||||
app.UseLocalization();
|
app.UseLocalization();
|
||||||
|
|
||||||
|
@ -198,12 +254,11 @@ app.UseForwardedHeaders();
|
||||||
//响应压缩
|
//响应压缩
|
||||||
app.UseResponseCompression();
|
app.UseResponseCompression();
|
||||||
|
|
||||||
//app.UseCors(t => t.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
|
|
||||||
|
|
||||||
//不需要 token 访问的静态文件 wwwroot css, JavaScript, and images don't require authentication.
|
//不需要 token 访问的静态文件 wwwroot css, JavaScript, and images don't require authentication.
|
||||||
app.UseStaticFiles();
|
app.UseStaticFiles();
|
||||||
|
|
||||||
app.UseMiddleware<MultiDiskStaticFilesMiddleware>();
|
|
||||||
|
|
||||||
//LogDashboard
|
//LogDashboard
|
||||||
app.UseLogDashboard("/LogDashboard");
|
app.UseLogDashboard("/LogDashboard");
|
||||||
|
@ -211,22 +266,24 @@ app.UseLogDashboard("/LogDashboard");
|
||||||
//hangfire
|
//hangfire
|
||||||
app.UseHangfireConfig(env);
|
app.UseHangfireConfig(env);
|
||||||
|
|
||||||
|
#region 暂时废弃
|
||||||
|
|
||||||
|
//app.UseMiddleware<MultiDiskStaticFilesMiddleware>();
|
||||||
////限流 中间件
|
////限流 中间件
|
||||||
//app.UseIpRateLimiting();
|
//app.UseIpRateLimiting();
|
||||||
|
//if (env.IsDevelopment())
|
||||||
|
//{
|
||||||
|
// app.UseDeveloperExceptionPage();
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// //app.UseHsts();
|
||||||
|
//}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (env.IsDevelopment())
|
|
||||||
{
|
|
||||||
app.UseDeveloperExceptionPage();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//app.UseHsts();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 特殊异常处理 比如 404
|
|
||||||
app.UseStatusCodePagesWithReExecute("/Error/{0}");
|
|
||||||
|
|
||||||
SwaggerSetup.Configure(app, env);
|
SwaggerSetup.Configure(app, env);
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ using IRaCIS.Core.Infra.EFCore;
|
||||||
using Medallion.Threading;
|
using Medallion.Threading;
|
||||||
using Medallion.Threading.SqlServer;
|
using Medallion.Threading.SqlServer;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
@ -21,12 +22,14 @@ namespace IRaCIS.Core.API
|
||||||
|
|
||||||
services.AddHttpContextAccessor();
|
services.AddHttpContextAccessor();
|
||||||
services.AddScoped<IUserInfo, UserInfo>();
|
services.AddScoped<IUserInfo, UserInfo>();
|
||||||
|
services.AddScoped<ISaveChangesInterceptor, AuditEntityInterceptor>();
|
||||||
|
|
||||||
|
|
||||||
// First, register a pooling context factory as a Singleton service, as usual:
|
// First, register a pooling context factory as a Singleton service, as usual:
|
||||||
|
|
||||||
//这个注入没有成功--注入是没问题的,构造函数也只是支持参数就好,错在注入的地方不能写DbContext
|
//这个注入没有成功--注入是没问题的,构造函数也只是支持参数就好,错在注入的地方不能写DbContext
|
||||||
//Web程序中通过重用池中DbContext实例可提高高并发场景下的吞吐量, 这在概念上类似于ADO.NET Provider原生的连接池操作方式,具有节省DbContext实例化成本的优点
|
//Web程序中通过重用池中DbContext实例可提高高并发场景下的吞吐量, 这在概念上类似于ADO.NET Provider原生的连接池操作方式,具有节省DbContext实例化成本的优点
|
||||||
services.AddDbContext<IRaCISDBContext>(options =>
|
services.AddDbContext<IRaCISDBContext>((sp, options) =>
|
||||||
{
|
{
|
||||||
|
|
||||||
// 在控制台
|
// 在控制台
|
||||||
|
@ -43,6 +46,7 @@ namespace IRaCIS.Core.API
|
||||||
options.EnableSensitiveDataLogging();
|
options.EnableSensitiveDataLogging();
|
||||||
|
|
||||||
options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor());
|
options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor());
|
||||||
|
options.AddInterceptors(sp.GetServices<ISaveChangesInterceptor>());
|
||||||
|
|
||||||
options.UseProjectables();
|
options.UseProjectables();
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,11 @@
|
||||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||||
"CompanyShortName": "Extensive Imaging",
|
"CompanyShortName": "Extensive Imaging",
|
||||||
"CompanyShortNameCN": "展影医疗"
|
"CompanyShortNameCN": "展影医疗"
|
||||||
|
},
|
||||||
|
|
||||||
|
"SystemPacsConfig": {
|
||||||
|
"Port": "11113",
|
||||||
|
"IP": "47.117.164.182"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
using Microsoft.AspNetCore.Diagnostics;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.Application.BusinessFilter
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 不生效,不知道为啥
|
||||||
|
/// </summary>
|
||||||
|
public class GlobalExceptionHandler : IExceptionHandler
|
||||||
|
{
|
||||||
|
private readonly ILogger<GlobalExceptionHandler> _logger;
|
||||||
|
public GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger)
|
||||||
|
{
|
||||||
|
this._logger = logger;
|
||||||
|
}
|
||||||
|
public ValueTask<bool> TryHandleAsync(
|
||||||
|
HttpContext httpContext,
|
||||||
|
Exception exception,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
httpContext.Response.ContentType = "application/json";
|
||||||
|
|
||||||
|
|
||||||
|
var ex = exception;
|
||||||
|
var errorInfo = $"Exception: {ex.Message}[{ex.StackTrace}]" + (ex.InnerException != null ? $" InnerException: {ex.InnerException.Message}[{ex.InnerException.StackTrace}]" : "");
|
||||||
|
|
||||||
|
httpContext.Response.WriteAsJsonAsync(ResponseOutput.NotOk($"{ex?.Message}"));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
_logger.LogError(errorInfo);
|
||||||
|
|
||||||
|
// return true to signal that this exception is handled
|
||||||
|
return ValueTask.FromResult(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -45,6 +45,7 @@ namespace IRaCIS.Core.Application.Filter
|
||||||
|
|
||||||
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, "", error!.Code, localizedInfo: info));
|
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, "", error!.Code, localizedInfo: info));
|
||||||
|
|
||||||
|
|
||||||
//warning 级别记录
|
//warning 级别记录
|
||||||
//_logger.LogWarning($"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}");
|
//_logger.LogWarning($"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}");
|
||||||
}
|
}
|
||||||
|
@ -60,12 +61,17 @@ namespace IRaCIS.Core.Application.Filter
|
||||||
_logger.LogError(context.Exception.InnerException is null ? (context.Exception.Message + context.Exception.StackTrace) : (context.Exception.InnerException?.Message + context.Exception.InnerException?.StackTrace));
|
_logger.LogError(context.Exception.InnerException is null ? (context.Exception.Message + context.Exception.StackTrace) : (context.Exception.InnerException?.Message + context.Exception.InnerException?.StackTrace));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context.ExceptionHandled = true;//标记当前异常已经被处理过了
|
||||||
|
|
||||||
|
|
||||||
|
//throw new Exception("test-result-exceptioin");
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//继续
|
//继续
|
||||||
}
|
}
|
||||||
context.ExceptionHandled = true;//标记当前异常已经被处理过了
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,31 +29,16 @@
|
||||||
签名
|
签名
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="T:IRaCIS.Core.Application.BusinessFilter.GlobalExceptionHandler">
|
||||||
|
<summary>
|
||||||
|
不生效,不知道为啥
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
<member name="T:IRaCIS.Core.Application.Filter.TrialResourceFilter">
|
<member name="T:IRaCIS.Core.Application.Filter.TrialResourceFilter">
|
||||||
<summary>
|
<summary>
|
||||||
主要为了 处理项目结束 锁库,不允许操作
|
主要为了 处理项目结束 锁库,不允许操作
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:IRaCIS.Core.Application.Helper.FileStoreHelper.GetSystemClinicalPathAsync(Microsoft.AspNetCore.Hosting.IWebHostEnvironment,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ClinicalDataSystemSet},System.Guid)">
|
|
||||||
<summary>
|
|
||||||
|
|
||||||
</summary>
|
|
||||||
<param name="_hostEnvironment"></param>
|
|
||||||
<param name="_clinicalDataTrialSetRepository"></param>
|
|
||||||
<param name="id"></param>
|
|
||||||
<returns></returns>
|
|
||||||
<exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception>
|
|
||||||
</member>
|
|
||||||
<member name="M:IRaCIS.Core.Application.Helper.FileStoreHelper.GetTrialClinicalPathAsync(Microsoft.AspNetCore.Hosting.IWebHostEnvironment,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ClinicalDataTrialSet},System.Guid)">
|
|
||||||
<summary>
|
|
||||||
|
|
||||||
</summary>
|
|
||||||
<param name="_hostEnvironment"></param>
|
|
||||||
<param name="_clinicalDataTrialSetRepository"></param>
|
|
||||||
<param name="id"></param>
|
|
||||||
<returns></returns>
|
|
||||||
<exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception>
|
|
||||||
</member>
|
|
||||||
<member name="M:IRaCIS.Core.Application.Helper.FileStoreHelper.WriteFileAsync(System.IO.Stream,System.String)">
|
<member name="M:IRaCIS.Core.Application.Helper.FileStoreHelper.WriteFileAsync(System.IO.Stream,System.String)">
|
||||||
<summary>
|
<summary>
|
||||||
写文件导到磁盘
|
写文件导到磁盘
|
||||||
|
@ -62,28 +47,6 @@
|
||||||
<param name="path">文件保存路径</param>
|
<param name="path">文件保存路径</param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:IRaCIS.Core.Application.Helper.FileStoreHelper.GetUploadPrintscreenFilePath(Microsoft.AspNetCore.Hosting.IWebHostEnvironment,System.String,System.Guid,System.Guid,System.Guid)">
|
|
||||||
<summary>
|
|
||||||
上传截图
|
|
||||||
</summary>
|
|
||||||
<param name="_hostEnvironment"></param>
|
|
||||||
<param name="fileName"></param>
|
|
||||||
<param name="trialId"></param>
|
|
||||||
<param name="siteid"></param>
|
|
||||||
<param name="subjectId"></param>
|
|
||||||
<returns></returns>
|
|
||||||
</member>
|
|
||||||
<member name="M:IRaCIS.Core.Application.Helper.FileStoreHelper.GetFilePath(Microsoft.AspNetCore.Hosting.IWebHostEnvironment,System.String,System.Guid,System.Guid,System.String)">
|
|
||||||
<summary>
|
|
||||||
通用获取文件路径
|
|
||||||
</summary>
|
|
||||||
<param name="_hostEnvironment"></param>
|
|
||||||
<param name="fileName"></param>
|
|
||||||
<param name="trialId"></param>
|
|
||||||
<param name="id"></param>
|
|
||||||
<param name="type"></param>
|
|
||||||
<returns></returns>
|
|
||||||
</member>
|
|
||||||
<member name="M:IRaCIS.Core.Application.Helper.OSSService.UploadToOSSAsync(System.IO.Stream,System.String,System.String,System.Boolean)">
|
<member name="M:IRaCIS.Core.Application.Helper.OSSService.UploadToOSSAsync(System.IO.Stream,System.String,System.String,System.Boolean)">
|
||||||
<summary>
|
<summary>
|
||||||
oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder
|
oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder
|
||||||
|
|
|
@ -41,7 +41,7 @@ namespace IRaCIS.Core.Application.Service
|
||||||
.WhereIf(string.IsNullOrEmpty(queryCommonDocument.Name), t => t.Name.Contains(queryCommonDocument.Name))
|
.WhereIf(string.IsNullOrEmpty(queryCommonDocument.Name), t => t.Name.Contains(queryCommonDocument.Name))
|
||||||
.ProjectTo<CommonDocumentView>(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken, userId = _userInfo.Id });
|
.ProjectTo<CommonDocumentView>(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken, userId = _userInfo.Id });
|
||||||
|
|
||||||
return await commonDocumentQueryable.ToPagedListAsync(queryCommonDocument.PageIndex, queryCommonDocument.PageSize, String.IsNullOrEmpty(queryCommonDocument.SortField) ? nameof(CommonDocument.Code) : queryCommonDocument.SortField, queryCommonDocument.Asc); ;
|
return await commonDocumentQueryable.ToPagedListAsync(queryCommonDocument);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace IRaCIS.Core.Application.Contracts
|
||||||
Task<List<TrialUserDto>> GetTrialUserSelect(Guid trialId);
|
Task<List<TrialUserDto>> GetTrialUserSelect(Guid trialId);
|
||||||
|
|
||||||
|
|
||||||
PageOutput<DocumentUnionWithUserStatView> GetTrialSystemDocumentList(DocumentTrialUnionQuery querySystemDocument);
|
Task<PageOutput<DocumentUnionWithUserStatView>> GetTrialSystemDocumentList(DocumentTrialUnionQuery querySystemDocument);
|
||||||
List<TrialUserUnionDocumentView> GetTrialUserDocumentList(Guid trialId);
|
List<TrialUserUnionDocumentView> GetTrialUserDocumentList(Guid trialId);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -26,8 +26,8 @@ namespace IRaCIS.Core.Application.Services
|
||||||
private readonly IRepository<TrialDocument> _trialDocumentRepository;
|
private readonly IRepository<TrialDocument> _trialDocumentRepository;
|
||||||
private readonly IRepository<TrialDocConfirmedUser> _trialDocUserTypeConfirmedUserRepository;
|
private readonly IRepository<TrialDocConfirmedUser> _trialDocUserTypeConfirmedUserRepository;
|
||||||
private readonly IRepository<Trial> _trialRepository;
|
private readonly IRepository<Trial> _trialRepository;
|
||||||
private readonly ISystemDocumentService _systemDocumentService;
|
private readonly ISystemDocumentService _systemDocumentService;
|
||||||
private readonly IRepository<SystemDocConfirmedUser> _systemDocConfirmedUserRepository;
|
private readonly IRepository<SystemDocConfirmedUser> _systemDocConfirmedUserRepository;
|
||||||
private readonly IRepository<SystemDocument> _systemDocumentRepository;
|
private readonly IRepository<SystemDocument> _systemDocumentRepository;
|
||||||
private readonly IRepository<TrialCriterionAdditionalAssessmentType> _trialCriterionAdditionalAssessmentTypeRepository;
|
private readonly IRepository<TrialCriterionAdditionalAssessmentType> _trialCriterionAdditionalAssessmentTypeRepository;
|
||||||
private readonly IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository;
|
private readonly IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository;
|
||||||
|
@ -36,8 +36,8 @@ namespace IRaCIS.Core.Application.Services
|
||||||
public TrialDocumentService(IRepository<TrialDocument> trialDocumentRepository,
|
public TrialDocumentService(IRepository<TrialDocument> trialDocumentRepository,
|
||||||
IRepository<TrialDocConfirmedUser> trialDocUserTypeConfirmedUserRepository,
|
IRepository<TrialDocConfirmedUser> trialDocUserTypeConfirmedUserRepository,
|
||||||
IRepository<Trial> trialRepository,
|
IRepository<Trial> trialRepository,
|
||||||
ISystemDocumentService systemDocumentService,
|
ISystemDocumentService systemDocumentService,
|
||||||
IRepository<SystemDocConfirmedUser> systemDocConfirmedUserRepository,
|
IRepository<SystemDocConfirmedUser> systemDocConfirmedUserRepository,
|
||||||
IRepository<TrialCriterionAdditionalAssessmentType> trialCriterionAdditionalAssessmentTypeRepository,
|
IRepository<TrialCriterionAdditionalAssessmentType> trialCriterionAdditionalAssessmentTypeRepository,
|
||||||
IRepository<ReadingQuestionCriterionTrial> readingQuestionCriterionTrialRepository
|
IRepository<ReadingQuestionCriterionTrial> readingQuestionCriterionTrialRepository
|
||||||
, IRepository<SystemDocument> systemDocumentRepository)
|
, IRepository<SystemDocument> systemDocumentRepository)
|
||||||
|
@ -45,8 +45,8 @@ namespace IRaCIS.Core.Application.Services
|
||||||
_trialDocumentRepository = trialDocumentRepository;
|
_trialDocumentRepository = trialDocumentRepository;
|
||||||
this._trialDocUserTypeConfirmedUserRepository = trialDocUserTypeConfirmedUserRepository;
|
this._trialDocUserTypeConfirmedUserRepository = trialDocUserTypeConfirmedUserRepository;
|
||||||
this._trialRepository = trialRepository;
|
this._trialRepository = trialRepository;
|
||||||
this._systemDocumentService = systemDocumentService;
|
this._systemDocumentService = systemDocumentService;
|
||||||
this._systemDocConfirmedUserRepository = systemDocConfirmedUserRepository;
|
this._systemDocConfirmedUserRepository = systemDocConfirmedUserRepository;
|
||||||
_systemDocumentRepository = systemDocumentRepository;
|
_systemDocumentRepository = systemDocumentRepository;
|
||||||
_readingQuestionCriterionTrialRepository = readingQuestionCriterionTrialRepository;
|
_readingQuestionCriterionTrialRepository = readingQuestionCriterionTrialRepository;
|
||||||
_trialCriterionAdditionalAssessmentTypeRepository = trialCriterionAdditionalAssessmentTypeRepository;
|
_trialCriterionAdditionalAssessmentTypeRepository = trialCriterionAdditionalAssessmentTypeRepository;
|
||||||
|
@ -64,7 +64,7 @@ namespace IRaCIS.Core.Application.Services
|
||||||
var trialDocumentQueryable = _trialDocumentRepository.AsQueryable(true).Where(t => t.TrialId == queryTrialDocument.TrialId)
|
var trialDocumentQueryable = _trialDocumentRepository.AsQueryable(true).Where(t => t.TrialId == queryTrialDocument.TrialId)
|
||||||
.WhereIf(!string.IsNullOrEmpty(queryTrialDocument.Name), t => t.Name.Contains(queryTrialDocument.Name))
|
.WhereIf(!string.IsNullOrEmpty(queryTrialDocument.Name), t => t.Name.Contains(queryTrialDocument.Name))
|
||||||
.WhereIf(queryTrialDocument.FileTypeId != null, t => t.FileTypeId == queryTrialDocument.FileTypeId)
|
.WhereIf(queryTrialDocument.FileTypeId != null, t => t.FileTypeId == queryTrialDocument.FileTypeId)
|
||||||
.WhereIf(queryTrialDocument.UserTypeId != null, t => t.NeedConfirmedUserTypeList.Any(t=>t.NeedConfirmUserTypeId== queryTrialDocument.UserTypeId) )
|
.WhereIf(queryTrialDocument.UserTypeId != null, t => t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == queryTrialDocument.UserTypeId))
|
||||||
.WhereIf(queryTrialDocument.IsDeleted != null, t => t.IsDeleted == queryTrialDocument.IsDeleted)
|
.WhereIf(queryTrialDocument.IsDeleted != null, t => t.IsDeleted == queryTrialDocument.IsDeleted)
|
||||||
.ProjectTo<TrialDocumentView>(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken, isEn_Us = _userInfo.IsEn_Us });
|
.ProjectTo<TrialDocumentView>(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken, isEn_Us = _userInfo.IsEn_Us });
|
||||||
|
|
||||||
|
@ -75,17 +75,17 @@ namespace IRaCIS.Core.Application.Services
|
||||||
public async Task<PageOutput<TrialSignDocView>> GetTrialSignDocumentList(TrialDocQuery querySystemDocument)
|
public async Task<PageOutput<TrialSignDocView>> GetTrialSignDocumentList(TrialDocQuery querySystemDocument)
|
||||||
{
|
{
|
||||||
var trialDocQueryable = from trialDoc in _trialDocumentRepository.AsQueryable(true)
|
var trialDocQueryable = from trialDoc in _trialDocumentRepository.AsQueryable(true)
|
||||||
.WhereIf(querySystemDocument.TrialId!=null,t=>t.TrialId==querySystemDocument.TrialId)
|
.WhereIf(querySystemDocument.TrialId != null, t => t.TrialId == querySystemDocument.TrialId)
|
||||||
.Where(t => t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == _userInfo.UserTypeId) )
|
.Where(t => t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == _userInfo.UserTypeId))
|
||||||
|
|
||||||
join trialUser in _repository.Where<TrialUser>(t=>t.UserId==_userInfo.Id) on trialDoc.TrialId equals trialUser.TrialId
|
join trialUser in _repository.Where<TrialUser>(t => t.UserId == _userInfo.Id) on trialDoc.TrialId equals trialUser.TrialId
|
||||||
join confirm in _repository.Where<TrialDocConfirmedUser>() on
|
join confirm in _repository.Where<TrialDocConfirmedUser>() on
|
||||||
new { trialUser.UserId, TrialDocumentId = trialDoc.Id } equals new { UserId = confirm.ConfirmUserId, confirm.TrialDocumentId } into cc
|
new { trialUser.UserId, TrialDocumentId = trialDoc.Id } equals new { UserId = confirm.ConfirmUserId, confirm.TrialDocumentId } into cc
|
||||||
|
|
||||||
from confirm in cc.DefaultIfEmpty()
|
from confirm in cc.DefaultIfEmpty()
|
||||||
select new TrialSignDocView()
|
select new TrialSignDocView()
|
||||||
{
|
{
|
||||||
TrialCode=trialDoc.Trial.TrialCode,
|
TrialCode = trialDoc.Trial.TrialCode,
|
||||||
ResearchProgramNo = trialDoc.Trial.ResearchProgramNo,
|
ResearchProgramNo = trialDoc.Trial.ResearchProgramNo,
|
||||||
ExperimentName = trialDoc.Trial.ExperimentName,
|
ExperimentName = trialDoc.Trial.ExperimentName,
|
||||||
Id = trialDoc.Id,
|
Id = trialDoc.Id,
|
||||||
|
@ -116,7 +116,7 @@ namespace IRaCIS.Core.Application.Services
|
||||||
.WhereIf(querySystemDocument.IsSigned == false, t => t.ConfirmTime == null);
|
.WhereIf(querySystemDocument.IsSigned == false, t => t.ConfirmTime == null);
|
||||||
|
|
||||||
|
|
||||||
return await trialDocQueryable.ToPagedListAsync(querySystemDocument.PageIndex, querySystemDocument.PageSize, querySystemDocument.SortField, querySystemDocument.Asc);
|
return await trialDocQueryable.ToPagedListAsync(querySystemDocument.PageIndex, querySystemDocument.PageSize, querySystemDocument.SortField, querySystemDocument.Asc);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,19 +142,19 @@ namespace IRaCIS.Core.Application.Services
|
||||||
PageSize = 1,
|
PageSize = 1,
|
||||||
})).Data;
|
})).Data;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = await _systemDocumentService.getWaitSignSysDocList(new SystemDocumentQuery()
|
result = await _systemDocumentService.getWaitSignSysDocList(new SystemDocumentQuery()
|
||||||
{
|
{
|
||||||
PageIndex=1,
|
PageIndex = 1,
|
||||||
IsSigned = false,
|
IsSigned = false,
|
||||||
PageSize=1,
|
PageSize = 1,
|
||||||
Asc=false,
|
Asc = false,
|
||||||
SortField="UpdateTime",
|
SortField = "UpdateTime",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (result.CurrentPageData.Count > 0)
|
if (result.CurrentPageData.Count > 0)
|
||||||
{
|
{
|
||||||
|
@ -823,7 +823,7 @@ namespace IRaCIS.Core.Application.Services
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[Obsolete]
|
[Obsolete]
|
||||||
public PageOutput<DocumentUnionWithUserStatView> GetTrialSystemDocumentList(DocumentTrialUnionQuery querySystemDocument)
|
public async Task<PageOutput<DocumentUnionWithUserStatView>> GetTrialSystemDocumentList(DocumentTrialUnionQuery querySystemDocument)
|
||||||
{
|
{
|
||||||
var systemDocumentQueryable = _repository
|
var systemDocumentQueryable = _repository
|
||||||
.WhereIf<SystemDocument>(!_userInfo.IsAdmin, t => t.IsDeleted == false)
|
.WhereIf<SystemDocument>(!_userInfo.IsAdmin, t => t.IsDeleted == false)
|
||||||
|
@ -867,7 +867,7 @@ namespace IRaCIS.Core.Application.Services
|
||||||
.WhereIf(!string.IsNullOrEmpty(querySystemDocument.Name), t => t.Name.Contains(querySystemDocument.Name))
|
.WhereIf(!string.IsNullOrEmpty(querySystemDocument.Name), t => t.Name.Contains(querySystemDocument.Name))
|
||||||
.WhereIf(querySystemDocument.FileTypeId != null, t => t.FileTypeId == querySystemDocument.FileTypeId);
|
.WhereIf(querySystemDocument.FileTypeId != null, t => t.FileTypeId == querySystemDocument.FileTypeId);
|
||||||
|
|
||||||
return unionQuery.ToPagedList(querySystemDocument.PageIndex, querySystemDocument.PageSize, querySystemDocument.SortField, querySystemDocument.Asc);
|
return await unionQuery.ToPagedListAsync(querySystemDocument.PageIndex, querySystemDocument.PageSize, querySystemDocument.SortField, querySystemDocument.Asc);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
|
@ -103,8 +103,10 @@ namespace IRaCIS.Core.Application.Contracts
|
||||||
.OrderByDescending(x=>x.LanguageType)
|
.OrderByDescending(x=>x.LanguageType)
|
||||||
.ThenBy(t=>t.ShowOrder)
|
.ThenBy(t=>t.ShowOrder)
|
||||||
.ProjectTo<QCQuestionConfigureView>(_mapper.ConfigurationProvider);
|
.ProjectTo<QCQuestionConfigureView>(_mapper.ConfigurationProvider);
|
||||||
|
|
||||||
return await QCQuestionQueryable.ToPagedListAsync(queryQCQuestionConfigure.PageIndex, queryQCQuestionConfigure.PageSize, new string[2] { "LanguageType desc", "ShowOrder asc" });
|
var defalutSortArray = new string[] { nameof(QCQuestionConfigureView.LanguageType) + " desc", nameof(QCQuestionConfigureView.ShowOrder) };
|
||||||
|
|
||||||
|
return await QCQuestionQueryable.ToPagedListAsync(queryQCQuestionConfigure.PageIndex, queryQCQuestionConfigure.PageSize, new string[2] { "LanguageType desc", "ShowOrder asc" });
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IResponseOutput> AddOrUpdateQCQuestionConfigure(QCQuestionAddOrEdit addOrEditQCQuestionConfigure)
|
public async Task<IResponseOutput> AddOrUpdateQCQuestionConfigure(QCQuestionAddOrEdit addOrEditQCQuestionConfigure)
|
||||||
|
|
|
@ -637,8 +637,9 @@ namespace IRaCIS.Core.Application.Service
|
||||||
ModuleName=x.ModuleName,
|
ModuleName=x.ModuleName,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var defalutSortArray = new string[] { nameof(GetCRCConfirmListOutDto.SubjectCode) + " desc", nameof(GetCRCConfirmListOutDto.LatestScanDate) };
|
||||||
|
|
||||||
var result = await query.ToPagedListAsync(inDto.PageIndex, inDto.PageSize, new string[2] { "SubjectCode asc", "LatestScanDate asc" });
|
var result = await query.ToPagedListAsync(inDto.PageIndex, inDto.PageSize, new string[2] { "SubjectCode asc", "LatestScanDate asc" });
|
||||||
|
|
||||||
var formList = await _clinicalFormRepository.Where(x => x.TrialId == inDto.TrialId)
|
var formList = await _clinicalFormRepository.Where(x => x.TrialId == inDto.TrialId)
|
||||||
.Where(x => x.ClinicalDataTrialSet.UploadRole == UploadRole.CRC)
|
.Where(x => x.ClinicalDataTrialSet.UploadRole == UploadRole.CRC)
|
||||||
|
|
|
@ -65,7 +65,9 @@ namespace IRaCIS.Core.Application.Service
|
||||||
.WhereIf(inDto.LanguageType != null, x => x.LanguageType == inDto.LanguageType!.Value)
|
.WhereIf(inDto.LanguageType != null, x => x.LanguageType == inDto.LanguageType!.Value)
|
||||||
.ProjectTo<ReadingMedicineSystemQuestionView>(_mapper.ConfigurationProvider).OrderBy(x => x.ShowOrder);
|
.ProjectTo<ReadingMedicineSystemQuestionView>(_mapper.ConfigurationProvider).OrderBy(x => x.ShowOrder);
|
||||||
|
|
||||||
return await query.ToPagedListAsync(inDto.PageIndex, inDto.PageSize, new string[2] { "LanguageType desc", "ShowOrder asc" });
|
var defalutSortArray = new string[] { nameof(ReadingMedicineSystemQuestionView.LanguageType) + " desc", nameof(ReadingMedicineSystemQuestionView.ShowOrder) };
|
||||||
|
|
||||||
|
return await query.ToPagedListAsync(inDto.PageIndex, inDto.PageSize, new string[2] { "LanguageType desc", "ShowOrder asc" });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -51,8 +51,7 @@ namespace IRaCIS.Core.Application.Service
|
||||||
{
|
{
|
||||||
var verifyExp1 = new EntityVerifyExp<TrialSiteDicomAE>()
|
var verifyExp1 = new EntityVerifyExp<TrialSiteDicomAE>()
|
||||||
{
|
{
|
||||||
VerifyExp = u => u.IP == addOrEditTrialSiteDicomAE.IP && u.Port == addOrEditTrialSiteDicomAE.Port
|
VerifyExp = u => u.CallingAE == addOrEditTrialSiteDicomAE.CallingAE && u.TrialId == addOrEditTrialSiteDicomAE.TrialId
|
||||||
&& u.CallingAE == addOrEditTrialSiteDicomAE.CallingAE && u.TrialId == addOrEditTrialSiteDicomAE.TrialId
|
|
||||||
&& u.TrialSiteId == addOrEditTrialSiteDicomAE.TrialSiteId,
|
&& u.TrialSiteId == addOrEditTrialSiteDicomAE.TrialSiteId,
|
||||||
|
|
||||||
//"不允许添加相同的记录"
|
//"不允许添加相同的记录"
|
||||||
|
|
|
@ -511,7 +511,6 @@ namespace IRaCIS.Core.Infra.EFCore
|
||||||
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
|
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
|
||||||
{
|
{
|
||||||
// 采用触发器的方式 设置 CreateUserId CreateTime UpdateTime UpdateUserId 稽查实体里面没有这四个字段的值 因为先后顺序的原因
|
// 采用触发器的方式 设置 CreateUserId CreateTime UpdateTime UpdateUserId 稽查实体里面没有这四个字段的值 因为先后顺序的原因
|
||||||
SetCommonEntityAuditInfo();
|
|
||||||
await AddAudit();
|
await AddAudit();
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -595,85 +594,7 @@ namespace IRaCIS.Core.Infra.EFCore
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 重写savechange方式 统一增加审计信息 CreateUserId CreateTime UpdateTime Update UserId
|
|
||||||
/// </summary>
|
|
||||||
private void SetCommonEntityAuditInfo()
|
|
||||||
{
|
|
||||||
|
|
||||||
ChangeTracker.DetectChanges(); // Important!
|
|
||||||
|
|
||||||
// 获取所有更改,删除,新增的实体,但排除审计实体(避免死循环)
|
|
||||||
var entities = ChangeTracker.Entries()
|
|
||||||
.Where(u => (u.State == EntityState.Modified || u.State == EntityState.Deleted || u.State == EntityState.Added)).Where(x => !typeof(DataInspection).IsAssignableFrom(x.Entity.GetType())).ToList();
|
|
||||||
|
|
||||||
foreach (var t in entities)
|
|
||||||
{
|
|
||||||
switch (t.State)
|
|
||||||
{
|
|
||||||
|
|
||||||
case EntityState.Deleted:
|
|
||||||
|
|
||||||
break;
|
|
||||||
case EntityState.Modified:
|
|
||||||
|
|
||||||
if (t.Entity is IAuditUpdate updateEntity1)
|
|
||||||
{
|
|
||||||
updateEntity1.UpdateTime = DateTime.Now;
|
|
||||||
updateEntity1.UpdateUserId = _userInfo.Id;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t.Entity is ISoftDelete softDelete)
|
|
||||||
{
|
|
||||||
if (softDelete.IsDeleted)
|
|
||||||
{
|
|
||||||
softDelete.DeleteUserId = _userInfo.Id;
|
|
||||||
softDelete.DeletedTime = DateTime.Now;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
softDelete.DeletedTime = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
//添加的时候,更新审计字段也赋值
|
|
||||||
case EntityState.Added:
|
|
||||||
|
|
||||||
|
|
||||||
if (t.Entity is IAuditAdd addEntity)
|
|
||||||
{
|
|
||||||
if (addEntity.CreateTime == default(DateTime))
|
|
||||||
{
|
|
||||||
addEntity.CreateTime = DateTime.Now;
|
|
||||||
}
|
|
||||||
|
|
||||||
addEntity.CreateUserId = _userInfo.Id;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t.Entity is IAuditUpdate updateEntity)
|
|
||||||
{
|
|
||||||
updateEntity.UpdateTime = DateTime.Now;
|
|
||||||
updateEntity.UpdateUserId = _userInfo.Id;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t.Entity is IAuditAddWithUserName addEntity3)
|
|
||||||
{
|
|
||||||
if (addEntity3.CreateTime == default(DateTime))
|
|
||||||
{
|
|
||||||
addEntity3.CreateTime = DateTime.Now;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
addEntity3.CreateUserId = _userInfo.Id;
|
|
||||||
addEntity3.CreateUser = _userInfo.RealName;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public virtual DbSet<TaskAllocationRule> TaskAllocationRule { get; set; }
|
public virtual DbSet<TaskAllocationRule> TaskAllocationRule { get; set; }
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
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
|
||||||
|
{
|
||||||
|
public override InterceptionResult<int> SavingChanges(DbContextEventData eventData, InterceptionResult<int> result)
|
||||||
|
{
|
||||||
|
AuditEntities(eventData.Context);
|
||||||
|
|
||||||
|
return base.SavingChanges(eventData, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ValueTask<InterceptionResult<int>> SavingChangesAsync(DbContextEventData eventData,
|
||||||
|
InterceptionResult<int> result, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
AuditEntities(eventData.Context);
|
||||||
|
|
||||||
|
return base.SavingChangesAsync(eventData, result, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,44 +5,86 @@ using Microsoft.EntityFrameworkCore;
|
||||||
using System.Linq.Dynamic.Core;
|
using System.Linq.Dynamic.Core;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Internal;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Infrastructure.Extention
|
namespace IRaCIS.Core.Infrastructure.Extention
|
||||||
{
|
{
|
||||||
public static class QueryablePageListExtensions
|
public static class QueryablePageListExtensions
|
||||||
{
|
{
|
||||||
//单字段排序
|
|
||||||
public static PageOutput<T> ToPagedList<T>(this IQueryable<T> source, int pageIndex, int pageSize, string defaultSortFiled = "Id", bool isAsc = true)
|
//单字段排序 异步 (或者默认排序字段是空,多字段排序,传递了,就以传递的单字段为准)
|
||||||
|
public static async Task<PageOutput<T>> ToPagedListAsync<T>(this IQueryable<T> source, PageInput pageInput, bool isMultiSortFiled = false, string[] sortArray = default, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
if (pageIndex <= 0)
|
|
||||||
|
if (isMultiSortFiled && sortArray == default)
|
||||||
{
|
{
|
||||||
pageIndex = 1;
|
throw new InvalidOperationException("The sort field must be specified");
|
||||||
}
|
}
|
||||||
if (pageSize <= 0)
|
|
||||||
|
|
||||||
|
if (pageInput.PageIndex <= 0)
|
||||||
{
|
{
|
||||||
pageSize = 10;
|
pageInput.PageIndex = 1;
|
||||||
}
|
}
|
||||||
var count = source.Count();
|
if (pageInput.PageSize <= 0)
|
||||||
|
{
|
||||||
|
pageInput.PageSize = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
var count = await source.CountAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
{
|
{
|
||||||
return new PageOutput<T>() { CurrentPageData = new T[0] };
|
return new PageOutput<T>() { CurrentPageData = new T[0] };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var propName=string.Empty;
|
||||||
|
|
||||||
var propName = string.IsNullOrWhiteSpace(defaultSortFiled) ? "Id" : defaultSortFiled;
|
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();
|
||||||
|
|
||||||
source = isAsc ? source.OrderBy(propName) : source.OrderBy(propName + " desc");
|
if (propertyNameList.Count == 0)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("no default sort field.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
propName= propertyNameList.Contains("Id") ? "Id" : propertyNameList.FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//有值,以前段传输的为主
|
||||||
|
propName = pageInput.SortField;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
source = source.Skip((pageIndex - 1) * pageSize);
|
if (!isMultiSortFiled)
|
||||||
|
{
|
||||||
|
source = pageInput.Asc ? source.OrderBy(propName) : source.OrderBy(propName + " desc");
|
||||||
|
|
||||||
var items = source
|
}
|
||||||
.Take(pageSize)
|
else
|
||||||
.ToArray();
|
{
|
||||||
|
var sortString = string.Join(',', sortArray);
|
||||||
|
|
||||||
|
source = source.OrderBy(sortString);
|
||||||
|
}
|
||||||
|
|
||||||
|
source = source.Skip((pageInput.PageIndex - 1) * pageInput.PageSize);
|
||||||
|
var items = await source
|
||||||
|
.Take(pageInput.PageSize)
|
||||||
|
.ToArrayAsync(cancellationToken)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
var pagedList = new PageOutput<T>()
|
var pagedList = new PageOutput<T>()
|
||||||
{
|
{
|
||||||
PageIndex = pageIndex,
|
PageIndex = pageInput.PageIndex,
|
||||||
PageSize = pageSize,
|
PageSize = pageInput.PageSize,
|
||||||
TotalCount = count,
|
TotalCount = count,
|
||||||
CurrentPageData = items
|
CurrentPageData = items
|
||||||
};
|
};
|
||||||
|
@ -50,8 +92,10 @@ namespace IRaCIS.Core.Infrastructure.Extention
|
||||||
return pagedList;
|
return pagedList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//单字段排序 异步
|
//单字段排序 异步
|
||||||
public static async Task<PageOutput<T>> ToPagedListAsync<T>(this IQueryable<T> source, int pageNumber, int pageSize, string defaultSortFiled = "Id", bool isAsc = true, bool isMultiSortFiled = false, string[] sortArray = default, CancellationToken cancellationToken = default)
|
public static async Task<PageOutput<T>> ToPagedListAsync<T>(this IQueryable<T> source, int pageNumber, int pageSize, string defaultSortFiled = "Id", bool isAsc = true, bool isMultiSortFiled = false, string[] sortArray = default)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (isMultiSortFiled && sortArray == default)
|
if (isMultiSortFiled && sortArray == default)
|
||||||
|
@ -68,7 +112,7 @@ namespace IRaCIS.Core.Infrastructure.Extention
|
||||||
pageSize = 10;
|
pageSize = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
var count = await source.CountAsync(cancellationToken).ConfigureAwait(false);
|
var count = await source.CountAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
{
|
{
|
||||||
|
@ -90,7 +134,7 @@ namespace IRaCIS.Core.Infrastructure.Extention
|
||||||
source = source.Skip((pageNumber - 1) * pageSize);
|
source = source.Skip((pageNumber - 1) * pageSize);
|
||||||
var items = await source
|
var items = await source
|
||||||
.Take(pageSize)
|
.Take(pageSize)
|
||||||
.ToArrayAsync(cancellationToken)
|
.ToArrayAsync()
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
var pagedList = new PageOutput<T>()
|
var pagedList = new PageOutput<T>()
|
||||||
|
@ -105,85 +149,11 @@ 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();
|
|
||||||
|
|
||||||
if (count == 0)
|
|
||||||
{
|
|
||||||
return new PageOutput<T>() { CurrentPageData = new List<T>() };
|
|
||||||
}
|
|
||||||
|
|
||||||
var propName = string.IsNullOrWhiteSpace(defaultSortFiled) ? "Id" : defaultSortFiled;
|
|
||||||
|
|
||||||
IQueryable<T> sourceQuery = isAsc ? source.AsQueryable().OrderBy(propName) : source.AsQueryable().OrderBy(propName + " desc");
|
|
||||||
|
|
||||||
sourceQuery = sourceQuery.Skip((pageIndex - 1) * pageSize);
|
|
||||||
|
|
||||||
var items = sourceQuery
|
|
||||||
.Take(pageSize)
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
var pagedList = new PageOutput<T>()
|
|
||||||
{
|
|
||||||
PageIndex = pageIndex,
|
|
||||||
PageSize = pageSize,
|
|
||||||
TotalCount = count,
|
|
||||||
CurrentPageData = items
|
|
||||||
};
|
|
||||||
|
|
||||||
return pagedList;
|
|
||||||
}
|
|
||||||
|
|
||||||
//多字段排序 ["a asc", "b desc", "c asc"]
|
|
||||||
public static PageOutput<T> ToPagedList<T>(this IQueryable<T> source, int pageIndex, int pageSize, string[] sortArray)
|
|
||||||
{
|
|
||||||
if (pageIndex <= 0)
|
|
||||||
{
|
|
||||||
pageIndex = 1;
|
|
||||||
}
|
|
||||||
if (pageSize <= 0)
|
|
||||||
{
|
|
||||||
pageSize = 10;
|
|
||||||
}
|
|
||||||
var count = source.Count();
|
|
||||||
|
|
||||||
if (count == 0)
|
|
||||||
{
|
|
||||||
return new PageOutput<T>() { CurrentPageData = new T[0] };
|
|
||||||
}
|
|
||||||
|
|
||||||
var sortString = string.Join(',', sortArray);
|
|
||||||
|
|
||||||
source.OrderBy(sortString);
|
|
||||||
|
|
||||||
source = source.Skip((pageIndex - 1) * pageSize);
|
|
||||||
|
|
||||||
var items = source
|
|
||||||
.Take(pageSize)
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
var pagedList = new PageOutput<T>()
|
|
||||||
{
|
|
||||||
PageIndex = pageIndex,
|
|
||||||
PageSize = pageSize,
|
|
||||||
TotalCount = count,
|
|
||||||
CurrentPageData = items
|
|
||||||
};
|
|
||||||
|
|
||||||
return pagedList;
|
|
||||||
}
|
|
||||||
|
|
||||||
//多字段排序异步 ["a asc", "b desc", "c asc"]
|
//多字段排序异步 ["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)
|
public static async Task<PageOutput<T>> ToPagedListAsync<T>(this IQueryable<T> source, int pageNumber, int pageSize, string[] sortArray)
|
||||||
{
|
{
|
||||||
if (pageNumber <= 0)
|
if (pageNumber <= 0)
|
||||||
{
|
{
|
||||||
|
@ -194,7 +164,7 @@ namespace IRaCIS.Core.Infrastructure.Extention
|
||||||
pageSize = 10;
|
pageSize = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
var count = await source.CountAsync(cancellationToken).ConfigureAwait(false);
|
var count = await source.CountAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
{
|
{
|
||||||
|
@ -212,7 +182,7 @@ namespace IRaCIS.Core.Infrastructure.Extention
|
||||||
source = source.Skip((pageNumber - 1) * pageSize);
|
source = source.Skip((pageNumber - 1) * pageSize);
|
||||||
var items = await source
|
var items = await source
|
||||||
.Take(pageSize)
|
.Take(pageSize)
|
||||||
.ToArrayAsync(cancellationToken)
|
.ToArrayAsync()
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
var pagedList = new PageOutput<T>()
|
var pagedList = new PageOutput<T>()
|
||||||
|
@ -227,6 +197,127 @@ namespace IRaCIS.Core.Infrastructure.Extention
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#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 T[0] };
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// var propName = string.IsNullOrWhiteSpace(defaultSortFiled) ? "Id" : defaultSortFiled;
|
||||||
|
|
||||||
|
// source = isAsc ? source.OrderBy(propName) : source.OrderBy(propName + " desc");
|
||||||
|
|
||||||
|
// source = source.Skip((pageIndex - 1) * pageSize);
|
||||||
|
|
||||||
|
// var items = source
|
||||||
|
// .Take(pageSize)
|
||||||
|
// .ToArray();
|
||||||
|
|
||||||
|
// var pagedList = new PageOutput<T>()
|
||||||
|
// {
|
||||||
|
// PageIndex = pageIndex,
|
||||||
|
// PageSize = pageSize,
|
||||||
|
// TotalCount = count,
|
||||||
|
// CurrentPageData = items
|
||||||
|
// };
|
||||||
|
|
||||||
|
// return pagedList;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//public static PageOutput<T> ToPagedList<T>(this IList<T> source, int pageIndex, int pageSize, string defaultSortFiled = "Id", bool isAsc = true)
|
||||||
|
//{
|
||||||
|
// if (pageIndex <= 0)
|
||||||
|
// {
|
||||||
|
// pageIndex = 1;
|
||||||
|
// }
|
||||||
|
// if (pageSize <= 0)
|
||||||
|
// {
|
||||||
|
// pageSize = 10;
|
||||||
|
// }
|
||||||
|
// var count = source.Count();
|
||||||
|
|
||||||
|
// if (count == 0)
|
||||||
|
// {
|
||||||
|
// return new PageOutput<T>() { CurrentPageData = new List<T>() };
|
||||||
|
// }
|
||||||
|
|
||||||
|
// var propName = string.IsNullOrWhiteSpace(defaultSortFiled) ? "Id" : defaultSortFiled;
|
||||||
|
|
||||||
|
// IQueryable<T> sourceQuery = isAsc ? source.AsQueryable().OrderBy(propName) : source.AsQueryable().OrderBy(propName + " desc");
|
||||||
|
|
||||||
|
// sourceQuery = sourceQuery.Skip((pageIndex - 1) * pageSize);
|
||||||
|
|
||||||
|
// var items = sourceQuery
|
||||||
|
// .Take(pageSize)
|
||||||
|
// .ToArray();
|
||||||
|
|
||||||
|
// var pagedList = new PageOutput<T>()
|
||||||
|
// {
|
||||||
|
// PageIndex = pageIndex,
|
||||||
|
// PageSize = pageSize,
|
||||||
|
// TotalCount = count,
|
||||||
|
// CurrentPageData = items
|
||||||
|
// };
|
||||||
|
|
||||||
|
// return pagedList;
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
////多字段排序 ["a asc", "b desc", "c asc"]
|
||||||
|
//public static PageOutput<T> ToPagedList<T>(this IQueryable<T> source, int pageIndex, int pageSize, string[] sortArray)
|
||||||
|
//{
|
||||||
|
// if (pageIndex <= 0)
|
||||||
|
// {
|
||||||
|
// pageIndex = 1;
|
||||||
|
// }
|
||||||
|
// if (pageSize <= 0)
|
||||||
|
// {
|
||||||
|
// pageSize = 10;
|
||||||
|
// }
|
||||||
|
// var count = source.Count();
|
||||||
|
|
||||||
|
// if (count == 0)
|
||||||
|
// {
|
||||||
|
// return new PageOutput<T>() { CurrentPageData = new T[0] };
|
||||||
|
// }
|
||||||
|
|
||||||
|
// var sortString = string.Join(',', sortArray);
|
||||||
|
|
||||||
|
// source.OrderBy(sortString);
|
||||||
|
|
||||||
|
// source = source.Skip((pageIndex - 1) * pageSize);
|
||||||
|
|
||||||
|
// var items = source
|
||||||
|
// .Take(pageSize)
|
||||||
|
// .ToArray();
|
||||||
|
|
||||||
|
// var pagedList = new PageOutput<T>()
|
||||||
|
// {
|
||||||
|
// PageIndex = pageIndex,
|
||||||
|
// PageSize = pageSize,
|
||||||
|
// TotalCount = count,
|
||||||
|
// CurrentPageData = items
|
||||||
|
// };
|
||||||
|
|
||||||
|
// return pagedList;
|
||||||
|
//}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
|
|
||||||
public string LocalizedInfo { get; set; }
|
public string LocalizedInfo { get; set; }
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -72,11 +72,9 @@ namespace IRaCIS.Core.Application.Service
|
||||||
var <#=char.ToLower(tableName[0]) + tableName.Substring(1)#>Queryable =
|
var <#=char.ToLower(tableName[0]) + tableName.Substring(1)#>Queryable =
|
||||||
|
|
||||||
_<#=char.ToLower(tableName[0]) + tableName.Substring(1)#>Repository
|
_<#=char.ToLower(tableName[0]) + tableName.Substring(1)#>Repository
|
||||||
.ProjectTo<<#=tableName#>View>(_mapper.ConfigurationProvider);
|
.ProjectTo<<#=tableName#>View>(_mapper.ConfigurationProvider);
|
||||||
|
|
||||||
var pageList= await <#=char.ToLower(tableName[0]) + tableName.Substring(1)#>Queryable
|
var pageList= await <#=char.ToLower(tableName[0]) + tableName.Substring(1)#>Queryable.ToPagedListAsync(<#=tableName#>Query);
|
||||||
.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrWhiteSpace(inQuery.SortField) ? nameof(<#=tableName#>View.Id) : inQuery.SortField,
|
|
||||||
inQuery.Asc);
|
|
||||||
|
|
||||||
return pageList;
|
return pageList;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue