diff --git a/IRaCIS.Core.API/Controllers/ExtraController.cs b/IRaCIS.Core.API/Controllers/ExtraController.cs index 3722593db..5685f2b87 100644 --- a/IRaCIS.Core.API/Controllers/ExtraController.cs +++ b/IRaCIS.Core.API/Controllers/ExtraController.cs @@ -25,6 +25,7 @@ using Aliyun.Acs.Core; using Aliyun.Acs.Core.Profile; using Aliyun.Acs.Sts.Model.V20150401; using Microsoft.AspNetCore.Hosting; +using MassTransit; namespace IRaCIS.Api.Controllers { @@ -144,16 +145,16 @@ namespace IRaCIS.Api.Controllers .Build(); - IClientProfile profile = DefaultProfile.GetProfile("cn-shanghai", configuration["AliyunOSS:accessKeyId"], configuration["AliyunOSS:accessKeySecret"]); DefaultAcsClient client = new DefaultAcsClient(profile); + // 创建一个STS请求 AssumeRoleRequest request = new AssumeRoleRequest { RoleArn = "acs:ram::1899121822495495:role/oss-upload", // 角色ARN,需要替换为你的角色ARN - RoleSessionName = "session-name", // 角色会话名称,可自定义 - DurationSeconds = 3600, // 令牌有效期(单位:秒),这里设置为1小时 + RoleSessionName = $"session-name-{NewId.NextGuid()}", // 角色会话名称,可自定义 + DurationSeconds = 900, // 令牌有效期(单位:秒),这里设置为1小时 }; diff --git a/IRaCIS.Core.API/IRaCIS.Core.API.csproj b/IRaCIS.Core.API/IRaCIS.Core.API.csproj index a823da33e..8419b93f5 100644 --- a/IRaCIS.Core.API/IRaCIS.Core.API.csproj +++ b/IRaCIS.Core.API/IRaCIS.Core.API.csproj @@ -66,28 +66,27 @@ - - + + - - - - + + + + - - - - - - - + + + + + + - + diff --git a/IRaCIS.Core.API/Startup.cs b/IRaCIS.Core.API/Startup.cs index b095f6b07..498b34c37 100644 --- a/IRaCIS.Core.API/Startup.cs +++ b/IRaCIS.Core.API/Startup.cs @@ -29,6 +29,7 @@ using IRaCIS.Core.Application.Helper; using Microsoft.AspNetCore.Http; using Autofac.Core; using DocumentFormat.OpenXml.InkML; +using EasyCaching.Core; namespace IRaCIS.Core.API { @@ -112,9 +113,9 @@ namespace IRaCIS.Core.API //JWT Token ֤ services.AddJWTAuthSetup(_configuration); // MediatR Ϣ ¼ ӳ עhandlerӦϵ - services.AddMediatR(typeof(ConsistencyVerificationHandler).Assembly); + services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining()); // EasyCaching - services.AddEasyCachingSetup(); + services.AddEasyCachingSetup(_configuration); //services.AddDistributedMemoryCache(); diff --git a/IRaCIS.Core.API/_ServiceExtensions/EFSetup.cs b/IRaCIS.Core.API/_ServiceExtensions/EFSetup.cs index 2f2890712..6c679d676 100644 --- a/IRaCIS.Core.API/_ServiceExtensions/EFSetup.cs +++ b/IRaCIS.Core.API/_ServiceExtensions/EFSetup.cs @@ -1,8 +1,12 @@ -using IRaCIS.Core.Application.Triggers; +using Hangfire.SqlServer; +using IRaCIS.Core.Application.Triggers; using IRaCIS.Core.Infra.EFCore; +using Medallion.Threading; +using Medallion.Threading.SqlServer; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using StackExchange.Redis; namespace IRaCIS.Core.API { @@ -52,6 +56,13 @@ namespace IRaCIS.Core.API }); + //注意区分 easy caching 也有 IDistributedLockProvider + services.AddSingleton(sp => + { + //var connection = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!); + + return new SqlDistributedSynchronizationProvider(configuration.GetSection("ConnectionStrings:RemoteNew").Value); + }); //services.AddAssemblyTriggers(typeof(SubjectVisitImageDateTrigger).Assembly); } diff --git a/IRaCIS.Core.API/_ServiceExtensions/EasyCachingSetup.cs b/IRaCIS.Core.API/_ServiceExtensions/EasyCachingSetup.cs index 7d7a28c6a..63be01d92 100644 --- a/IRaCIS.Core.API/_ServiceExtensions/EasyCachingSetup.cs +++ b/IRaCIS.Core.API/_ServiceExtensions/EasyCachingSetup.cs @@ -1,17 +1,26 @@ using EasyCaching.Core; +using EasyCaching.Core.Configurations; using EasyCaching.Interceptor.Castle; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; namespace IRaCIS.Core.API { public static class EasyCachingSetup { - public static void AddEasyCachingSetup(this IServiceCollection services) + public static void AddEasyCachingSetup(this IServiceCollection services, IConfiguration configuration) { services.AddEasyCaching(options => { options.UseInMemory(); + + //options.UseRedis(configuration, EasyCachingConstValue.DefaultRedisName).WithMessagePack(EasyCachingConstValue.DefaultRedisName); + + }); + + //services.ConfigureCastleInterceptor(options => options.CacheProviderName = EasyCachingConstValue.DefaultRedisName); + services.ConfigureCastleInterceptor(options => options.CacheProviderName = EasyCachingConstValue.DefaultInMemoryName); } } diff --git a/IRaCIS.Core.API/_ServiceExtensions/Serilog/SerilogSetup.cs b/IRaCIS.Core.API/_ServiceExtensions/Serilog/SerilogSetup.cs index f0740dbbf..a27de1505 100644 --- a/IRaCIS.Core.API/_ServiceExtensions/Serilog/SerilogSetup.cs +++ b/IRaCIS.Core.API/_ServiceExtensions/Serilog/SerilogSetup.cs @@ -21,7 +21,7 @@ namespace IRaCIS.Core.API .MinimumLevel.Override("Hangfire", LogEventLevel.Warning) .MinimumLevel.Override("System.Net.Http.HttpClient.HttpReports", LogEventLevel.Warning) .Enrich.WithClientIp() - .Enrich.WithClientAgent() + .Enrich.FromLogContext() //控制台 方便调试 问题 我们显示记录日志 时 获取上下文的ip 和用户名 用户类型 diff --git a/IRaCIS.Core.API/_ServiceExtensions/Swagger/JsonPatchDocumentFilter.cs b/IRaCIS.Core.API/_ServiceExtensions/Swagger/JsonPatchDocumentFilter.cs deleted file mode 100644 index 9f3562072..000000000 --- a/IRaCIS.Core.API/_ServiceExtensions/Swagger/JsonPatchDocumentFilter.cs +++ /dev/null @@ -1,55 +0,0 @@ -using Microsoft.OpenApi.Models; -using Swashbuckle.AspNetCore.SwaggerGen; -using System.Collections.Generic; -using System.Linq; - -namespace IRaCIS.Core.API -{ - public class JsonPatchDocumentFilter : IDocumentFilter - { - public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) - { - var schemas = swaggerDoc.Components.Schemas.ToList(); - foreach (var item in schemas) - { - if (item.Key.StartsWith("Operation") || item.Key.StartsWith("JsonPatchDocument")) - swaggerDoc.Components.Schemas.Remove(item.Key); - } - - swaggerDoc.Components.Schemas.Add("Operation", new OpenApiSchema - { - Type = "object", - Properties = new Dictionary - { - { "op", new OpenApiSchema { Type = "string" } }, - {"value", new OpenApiSchema{ Type = "object", Nullable = true } }, - { "path", new OpenApiSchema { Type = "string" } } - } - }); - - swaggerDoc.Components.Schemas.Add("JsonPatchDocument", new OpenApiSchema - { - Type = "array", - Items = new OpenApiSchema - { - Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "Operation" } - }, - Description = "Array of operations to perform" - }); - - foreach (var path in swaggerDoc.Paths.SelectMany(p => p.Value.Operations) - .Where(p => p.Key == Microsoft.OpenApi.Models.OperationType.Patch)) - { - foreach (var item in path.Value.RequestBody.Content.Where(c => c.Key != "application/json-patch+json")) - path.Value.RequestBody.Content.Remove(item.Key); - - var response = path.Value.RequestBody.Content.SingleOrDefault(c => c.Key == "application/json-patch+json"); - - response.Value.Schema = new OpenApiSchema - { - Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "JsonPatchDocument" } - }; - } - } - } -} diff --git a/IRaCIS.Core.API/_ServiceExtensions/Swagger/SwaggerSetup.cs b/IRaCIS.Core.API/_ServiceExtensions/Swagger/SwaggerSetup.cs index 4a16162e7..a5c53cd7f 100644 --- a/IRaCIS.Core.API/_ServiceExtensions/Swagger/SwaggerSetup.cs +++ b/IRaCIS.Core.API/_ServiceExtensions/Swagger/SwaggerSetup.cs @@ -18,7 +18,6 @@ namespace IRaCIS.Core.API { public static void AddSwaggerSetup(this IServiceCollection services) { - services.AddSwaggerExamplesFromAssemblyOf(); services.AddSwaggerGen(options => { @@ -63,7 +62,6 @@ namespace IRaCIS.Core.API // 在header中添加token,传递到后台 options.OperationFilter(); - options.DocumentFilter(); // 添加登录按钮 options.AddSecurityDefinition("bearerAuth", new OpenApiSecurityScheme() diff --git a/IRaCIS.Core.API/appsettings.Prod_Study.json b/IRaCIS.Core.API/appsettings.Prod_Study.json new file mode 100644 index 000000000..72cf72b24 --- /dev/null +++ b/IRaCIS.Core.API/appsettings.Prod_Study.json @@ -0,0 +1,48 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AliyunOSS": { + "regionId": "cn-shanghai", + "region": "oss-cn-shanghai", + "endpoint": "https://oss-cn-shanghai.aliyuncs.com", + "accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ", + "accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio", + "bucketName": "zy-sir-store", + "viewEndpoint": "https://zy-sir-cache.oss-cn-shanghai.aliyuncs.com" + }, + + "ConnectionStrings": { + "RemoteNew": "Server=47.117.165.18,1434;Database=Prod_Study;User ID=sa;Password=WHxckj@2019;TrustServerCertificate=true", + "Hangfire": "Server=47.117.165.18,1434;Database=Prod_Study.hangfire;User ID=sa;Password=WHxckj@2019;TrustServerCertificate=true" + }, + + "BasicSystemConfig": { + + "OpenUserComplexPassword": false, + + "OpenSignDocumentBeforeWork": false, + + "OpenTrialRelationDelete": true, + + "OpenLoginLimit": false, + "LoginMaxFailCount": 5, + + "LoginFailLockMinutes": 30 + + }, + + "SystemEmailSendConfig": { + "Port": 465, + "Host": "smtp.qiye.aliyun.com", + "FromEmail": "study@extimaging.com", + "FromName": "研究单位阅片系统", + "AuthorizationCode": "zhanying123", + "SiteUrl": "https://study.extimaging.com/login" + } + +} diff --git a/IRaCIS.Core.API/appsettings.json b/IRaCIS.Core.API/appsettings.json index b363c8ad5..dee559b4c 100644 --- a/IRaCIS.Core.API/appsettings.json +++ b/IRaCIS.Core.API/appsettings.json @@ -5,6 +5,7 @@ "Audience": "ZhiZhun", "TokenExpireDays": "7" }, + //ip "IpRateLimiting": { "EnableEndpointRateLimiting": true, "StackBlockedRequests": false, @@ -56,6 +57,26 @@ "EnableReadDeepClone": true, "EnableWriteDeepClone": false } + }, + "redis": { + "MaxRdSecond": 120, + "EnableLogging": false, + "LockMs": 5000, + "SleepMs": 300, + "dbconfig": { + "Password": "xc@123456", + "IsSsl": false, + "SslHost": null, + "ConnectionTimeout": 5000, + "AllowAdmin": true, + "Endpoints": [ + { + "Host": "47.117.164.182", + "Port": 6379 + } + ], + "Database": 0 + } } }, "IRaCISImageStore": { diff --git a/IRaCIS.Core.Application/BusinessFilter/TrialResourceFilter.cs b/IRaCIS.Core.Application/BusinessFilter/TrialResourceFilter.cs index 555e3aa35..38ab75156 100644 --- a/IRaCIS.Core.Application/BusinessFilter/TrialResourceFilter.cs +++ b/IRaCIS.Core.Application/BusinessFilter/TrialResourceFilter.cs @@ -58,10 +58,14 @@ namespace IRaCIS.Core.Application.Filter // 后期列举出具体的类型,其他任何用户类型,都不允许操作 if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA) { - //---对不起,您的账户没有操作权限。 - context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"])); + if (!_userInfo.RequestUrl.Contains("TrialDocument/userConfirm")) + { + //---对不起,您的账户没有操作权限。 + context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"])); - return; + return; + + } } #endregion diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj b/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj index bf608d946..7c5eedd25 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj @@ -15,14 +15,14 @@ - 1701;1702;1591;1587 + 1701;1702;1591;1587 - + @@ -50,60 +50,56 @@ - - PreserveNewest - true - PreserveNewest - - - Always - true - PreserveNewest - + + PreserveNewest + true + PreserveNewest + + + Always + true + PreserveNewest + - - + + + + - + - - true - - - - + + + + - - - true + + + true - - true + + true - - - - - - true - - - - + + + + + + - true + true - - - - - - + + + + + + diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml index 587a426ad..0e30712ac 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -9509,11 +9509,6 @@ TrialSiteUserSurveyAddOrEdit 列表查询参数模型 - - - 实测 标注在服务方法上 没用 - - TrialSiteEquipmentSurveyService @@ -10884,20 +10879,6 @@ - - - 获取附加评估选项列表 - - - - - - - 保存附加评估设置 (自动添加 或者删除附加评估问题) - - - - 获取签名文本 diff --git a/IRaCIS.Core.Application/Service/Allocation/DTO/VisitTaskViewModel.cs b/IRaCIS.Core.Application/Service/Allocation/DTO/VisitTaskViewModel.cs index d94c9f5ad..7ec04337f 100644 --- a/IRaCIS.Core.Application/Service/Allocation/DTO/VisitTaskViewModel.cs +++ b/IRaCIS.Core.Application/Service/Allocation/DTO/VisitTaskViewModel.cs @@ -479,9 +479,17 @@ namespace IRaCIS.Core.Application.ViewModel } - public class PIAuditDialogListView : PIAuditTaskCommand + public class PIAuditDialogListView { + public Guid VisitTaskId { get; set; } + public string NotAgreeReason { get; set; } + public string PIAuditNote { get; set; } = string.Empty; + + public List PIAuditImagePathList { get; set; } + + public PIAuditState? PIAuditState { get; set; } + public string ReplyContent { get; set; } = string.Empty; public bool? IsEnrollment { get; set; } diff --git a/IRaCIS.Core.Application/Service/Allocation/VisitTaskService.cs b/IRaCIS.Core.Application/Service/Allocation/VisitTaskService.cs index 0c11cc06d..55c545aee 100644 --- a/IRaCIS.Core.Application/Service/Allocation/VisitTaskService.cs +++ b/IRaCIS.Core.Application/Service/Allocation/VisitTaskService.cs @@ -25,6 +25,7 @@ using Quartz; using IRaCIS.Application.Services.BackGroundJob; using Magicodes.ExporterAndImporter.Core.Extension; using Hangfire; +using MassTransit; namespace IRaCIS.Core.Application.Service.Allocation { @@ -275,6 +276,8 @@ namespace IRaCIS.Core.Application.Service.Allocation //发送对话 var addDialig = _mapper.Map(incommand); + addDialig.PIAuditState = incommand.PIAuditState; + addDialig.PIAuditImagePath = visitTask.PIAuditImagePath; await _PIAuditRepository.AddAsync(addDialig); @@ -1227,18 +1230,9 @@ namespace IRaCIS.Core.Application.Service.Allocation { if (origenalTask.ReadingCategory == ReadingCategory.Visit) { - var list = _readingTaskQuestionAnswerRepository.Where(t => t.VisitTaskId == origenalTask.Id).ToList(); - - foreach (var item in list) - { - item.Id = Guid.Empty; - item.VisitTaskId = newTask.Id; - } - - _ = _readingTaskQuestionAnswerRepository.AddRangeAsync(list).Result; + CopyForms(newTask, origenalTask); } - } //拷贝后续表单 @@ -1246,15 +1240,7 @@ namespace IRaCIS.Core.Application.Service.Allocation { if (origenalTask.ReadingCategory == ReadingCategory.Visit) { - var list = _readingTaskQuestionAnswerRepository.Where(t => t.VisitTaskId == origenalTask.Id).ToList(); - - foreach (var item in list) - { - item.Id = Guid.Empty; - item.VisitTaskId = newTask.Id; - } - - _ = _readingTaskQuestionAnswerRepository.AddRangeAsync(list).Result; + CopyForms(newTask, origenalTask); } } @@ -1350,15 +1336,7 @@ namespace IRaCIS.Core.Application.Service.Allocation { if (origenalTask.ReadingCategory == ReadingCategory.Visit) { - var list = _readingTaskQuestionAnswerRepository.Where(t => t.VisitTaskId == origenalTask.Id).ToList(); - - foreach (var item in list) - { - item.Id = Guid.Empty; - item.VisitTaskId = newTask.Id; - } - - _ = _readingTaskQuestionAnswerRepository.AddRangeAsync(list).Result; + CopyForms(newTask, origenalTask); } } @@ -1368,15 +1346,7 @@ namespace IRaCIS.Core.Application.Service.Allocation { if (origenalTask.ReadingCategory == ReadingCategory.Visit) { - var list = _readingTaskQuestionAnswerRepository.Where(t => t.VisitTaskId == origenalTask.Id).ToList(); - - foreach (var item in list) - { - item.Id = Guid.Empty; - item.VisitTaskId = newTask.Id; - } - - _ = _readingTaskQuestionAnswerRepository.AddRangeAsync(list).Result; + CopyForms(newTask, origenalTask); } } @@ -1435,7 +1405,69 @@ namespace IRaCIS.Core.Application.Service.Allocation return ResponseOutput.Ok(); } + private void CopyForms(VisitTask newTask, VisitTask origenalTask) + { + //自定义 + var readingCustomTagList = _repository.Where(t => t.VisitTaskId == origenalTask.Id).ToList(); + + foreach (var item in readingCustomTagList) + { + item.Id = Guid.Empty; + item.VisitTaskId = newTask.Id; + } + + _ = _repository.AddRangeAsync(readingCustomTagList).Result; + + + //var readingTaskQuestionMarkList = _repository.Where(t => t.VisitTaskId == origenalTask.Id).ToList(); + + //foreach (var item in readingTaskQuestionMarkList) + //{ + // item.Id = Guid.Empty; + // item.VisitTaskId = newTask.Id; + //} + + //_ = _repository.AddRangeAsync(readingTaskQuestionMarkList).Result; + + var readingTaskQuestionAnswerList = _repository.Where(t => t.VisitTaskId == origenalTask.Id).ToList(); + + foreach (var item in readingTaskQuestionAnswerList) + { + item.Id = Guid.Empty; + item.VisitTaskId = newTask.Id; + } + _ = _repository.AddRangeAsync(readingTaskQuestionAnswerList).Result; + + + + //ReadingTableAnswerRowInfo ReadingTableQuestionAnswer 一起加 + var readingTableAnswerRowInfoList = _repository.Where(t => t.VisitTaskId == origenalTask.Id).Include(t => t.LesionAnswerList).ToList(); + + foreach (var item in readingTableAnswerRowInfoList) + { + var originalVisitTaskId = item.VisitTaskId; + var originalFristAddTaskId = item.FristAddTaskId; + + item.Id = NewId.NextSequentialGuid(); + item.VisitTaskId = newTask.Id; + item.FristAddTaskId = originalVisitTaskId == originalFristAddTaskId ? newTask.Id : item.FristAddTaskId; + + foreach (var item2 in item.LesionAnswerList) + { + item2.Id = Guid.Empty; + item2.RowId = item.Id; + item2.VisitTaskId = newTask.Id; + } + } + + _ = _repository.AddRangeAsync(readingTableAnswerRowInfoList).Result; + + + + + + } /// /// PM 设置任务 退回 /// diff --git a/IRaCIS.Core.Application/Service/Allocation/_MapConfig.cs b/IRaCIS.Core.Application/Service/Allocation/_MapConfig.cs index dc05bd84b..fa4e39cf7 100644 --- a/IRaCIS.Core.Application/Service/Allocation/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/Allocation/_MapConfig.cs @@ -251,7 +251,7 @@ namespace IRaCIS.Core.Application.Service CreateMap() .ForMember(o => o.CreateUserName, t => t.MapFrom(u => u.CreateUser.UserName)) .ForMember(o => o.UserTypeEnum, t => t.MapFrom(u => u.CreateUser.UserTypeEnum)) - .ForMember(o => o.PIAuditState, t => t.MapFrom(u => u.VisitTask.PIAuditState)) + //.ForMember(o => o.PIAuditState, t => t.MapFrom(u => u.VisitTask.PIAuditState)) ; diff --git a/IRaCIS.Core.Application/Service/Common/DictionaryService.cs b/IRaCIS.Core.Application/Service/Common/DictionaryService.cs index 9d5aa7e7f..82a48b05a 100644 --- a/IRaCIS.Core.Application/Service/Common/DictionaryService.cs +++ b/IRaCIS.Core.Application/Service/Common/DictionaryService.cs @@ -249,7 +249,7 @@ namespace IRaCIS.Application.Services public async Task>> GetBasicDataSelect(string[] searchArray) { - var searchList = await _dicRepository.Where(t => searchArray.Contains(t.Parent.Code) && t.ParentId != null && t.IsEnable).ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); + var searchList = await _dicRepository.Where(t => searchArray.Contains(t.Parent.Code) && t.ParentId != null && t.IsEnable).ProjectTo(_mapper.ConfigurationProvider,new { isEn_Us = _userInfo.IsEn_Us}).ToListAsync(); return searchList.GroupBy(t => t.ParentCode).ToDictionary(g => g.Key, g => g.OrderBy(t => t.ShowOrder).ToList()); diff --git a/IRaCIS.Core.Application/Service/Common/MailService.cs b/IRaCIS.Core.Application/Service/Common/MailService.cs index 2a4e0bb2d..d821708b6 100644 --- a/IRaCIS.Core.Application/Service/Common/MailService.cs +++ b/IRaCIS.Core.Application/Service/Common/MailService.cs @@ -6,7 +6,6 @@ using Microsoft.AspNetCore.Hosting; using IRaCIS.Core.Application.Auth; using AutoMapper; using IRaCIS.Application.Contracts; -using Nito.AsyncEx; using Microsoft.Extensions.Options; namespace IRaCIS.Application.Services @@ -55,7 +54,6 @@ namespace IRaCIS.Application.Services - private readonly AsyncLock _mutex = new AsyncLock(); private readonly SystemEmailSendConfig _systemEmailConfig; diff --git a/IRaCIS.Core.Application/Service/Common/_MapConfig.cs b/IRaCIS.Core.Application/Service/Common/_MapConfig.cs index 9c2c3c95c..f157924cb 100644 --- a/IRaCIS.Core.Application/Service/Common/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/Common/_MapConfig.cs @@ -58,7 +58,7 @@ namespace IRaCIS.Core.Application.Service CreateMap() .ForMember(o => o.ParentChildCodeEnum, t => t.MapFrom(u => u.Parent.ChildCodeEnum)) - .ForMember(o => o.Value, t => t.MapFrom(u => u.MappedValue)) + .ForMember(o => o.Value, t => t.MapFrom(u => isEn_Us? u.Value : u.ValueCN )) .ForMember(o => o.ParentCode, t => t.MapFrom(u => u.Parent.Code)); CreateMap() diff --git a/IRaCIS.Core.Application/Service/Document/EmailSendService.cs b/IRaCIS.Core.Application/Service/Document/EmailSendService.cs index 79465b686..bb89f92f1 100644 --- a/IRaCIS.Core.Application/Service/Document/EmailSendService.cs +++ b/IRaCIS.Core.Application/Service/Document/EmailSendService.cs @@ -103,7 +103,7 @@ namespace IRaCIS.Core.Application.Service return (topicStr, htmlBodyStr, isEn_us, null); }; - await SendTrialEmailAsync(taskInfo.TrialId, businessScenarioEnum, topicAndHtmlFunc); + await SendTrialEmailAsync(taskInfo.TrialId, businessScenarioEnum, topicAndHtmlFunc, taskInfo.SiteId); } else { diff --git a/IRaCIS.Core.Application/Service/Document/SystemDocumentService.cs b/IRaCIS.Core.Application/Service/Document/SystemDocumentService.cs index 4d3003ad9..21480bae3 100644 --- a/IRaCIS.Core.Application/Service/Document/SystemDocumentService.cs +++ b/IRaCIS.Core.Application/Service/Document/SystemDocumentService.cs @@ -170,7 +170,7 @@ namespace IRaCIS.Core.Application.Services SignViewMinimumMinutes = sysDoc.SignViewMinimumMinutes, Name = sysDoc.Name, Path = sysDoc.Path, - FileType = sysDoc.FileType.MappedValue, + FileType = _userInfo.IsEn_Us? sysDoc.FileType.Value: sysDoc.FileType.ValueCN, UpdateTime = sysDoc.UpdateTime, FullFilePath = sysDoc.Path , diff --git a/IRaCIS.Core.Application/Service/Document/TrialDocumentService.cs b/IRaCIS.Core.Application/Service/Document/TrialDocumentService.cs index 64556463d..c4629983e 100644 --- a/IRaCIS.Core.Application/Service/Document/TrialDocumentService.cs +++ b/IRaCIS.Core.Application/Service/Document/TrialDocumentService.cs @@ -27,7 +27,6 @@ namespace IRaCIS.Core.Application.Services private readonly IRepository _trialRepository; private readonly IRepository _systemDocConfirmedUserRepository; private readonly IRepository _systemDocumentRepository; - private readonly IRepository _trialCriterionAdditionalAssessmentTypeRepository; private readonly IRepository _readingQuestionCriterionTrialRepository; @@ -35,7 +34,6 @@ namespace IRaCIS.Core.Application.Services IRepository trialDocUserTypeConfirmedUserRepository, IRepository trialRepository, IRepository systemDocConfirmedUserRepository, - IRepository trialCriterionAdditionalAssessmentTypeRepository, IRepository readingQuestionCriterionTrialRepository , IRepository systemDocumentRepository) { @@ -45,7 +43,6 @@ namespace IRaCIS.Core.Application.Services this._systemDocConfirmedUserRepository = systemDocConfirmedUserRepository; _systemDocumentRepository = systemDocumentRepository; _readingQuestionCriterionTrialRepository = readingQuestionCriterionTrialRepository; - _trialCriterionAdditionalAssessmentTypeRepository = trialCriterionAdditionalAssessmentTypeRepository; } /// @@ -60,7 +57,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) - .ProjectTo(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken }); + .ProjectTo(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken, isEn_Us=_userInfo.IsEn_Us }); return await trialDocumentQueryable.ToPagedListAsync(queryTrialDocument.PageIndex, queryTrialDocument.PageSize, queryTrialDocument.SortField, queryTrialDocument.Asc); } @@ -160,7 +157,7 @@ namespace IRaCIS.Core.Application.Services Name = needConfirmedUserType.SystemDocument.Name, Path = needConfirmedUserType.SystemDocument.Path, FileTypeId = needConfirmedUserType.SystemDocument.FileTypeId, - FileType = needConfirmedUserType.SystemDocument.FileType.MappedValue, + FileType = _userInfo.IsEn_Us? needConfirmedUserType.SystemDocument.FileType.Value: needConfirmedUserType.SystemDocument.FileType.ValueCN, UpdateTime = needConfirmedUserType.SystemDocument.UpdateTime, FullFilePath = needConfirmedUserType.SystemDocument.Path , @@ -192,7 +189,7 @@ namespace IRaCIS.Core.Application.Services Name = trialDoc.Name, Path = trialDoc.Path, FileTypeId = trialDoc.FileTypeId, - FileType = trialDoc.FileType.MappedValue, + FileType = _userInfo.IsEn_Us ? trialDoc.FileType.Value: trialDoc.FileType.ValueCN, UpdateTime = trialDoc.UpdateTime, SignViewMinimumMinutes = trialDoc.SignViewMinimumMinutes, @@ -206,13 +203,35 @@ namespace IRaCIS.Core.Application.Services }; + #region 报错 奇怪的bug var unionQuery = systemDocumentQueryable.Union(trialDocQueryable) - .WhereIf(!string.IsNullOrEmpty(querySystemDocument.Name), t => t.Name.Contains(querySystemDocument.Name)) - .WhereIf(querySystemDocument.FileTypeId != null, t => t.FileTypeId == querySystemDocument.FileTypeId) - .WhereIf(querySystemDocument.IsSign == true, t => t.ConfirmTime != null) - .WhereIf(querySystemDocument.IsSign == false, t => t.ConfirmTime == null); + .WhereIf(!string.IsNullOrEmpty(querySystemDocument.Name), t => t.Name.Contains(querySystemDocument.Name)) + .WhereIf(querySystemDocument.FileTypeId != null, t => t.FileTypeId == querySystemDocument.FileTypeId) + .WhereIf(querySystemDocument.IsSign == true, t => t.ConfirmTime != null) + .WhereIf(querySystemDocument.IsSign == false, t => t.ConfirmTime == null); var result = await unionQuery.ToPagedListAsync(querySystemDocument.PageIndex, querySystemDocument.PageSize, querySystemDocument.SortField, querySystemDocument.Asc); + #endregion + + #region 临时方案 + + //var list1 = systemDocumentQueryable + // .WhereIf(!string.IsNullOrEmpty(querySystemDocument.Name), t => t.Name.Contains(querySystemDocument.Name)) + // .WhereIf(querySystemDocument.FileTypeId != null, t => t.FileTypeId == querySystemDocument.FileTypeId) + // .WhereIf(querySystemDocument.IsSign == true, t => t.ConfirmTime != null) + // .WhereIf(querySystemDocument.IsSign == false, t => t.ConfirmTime == null).ToList(); + + //var list2 = trialDocQueryable + // .WhereIf(!string.IsNullOrEmpty(querySystemDocument.Name), t => t.Name.Contains(querySystemDocument.Name)) + //.WhereIf(querySystemDocument.FileTypeId != null, t => t.FileTypeId == querySystemDocument.FileTypeId) + //.WhereIf(querySystemDocument.IsSign == true, t => t.ConfirmTime != null) + //.WhereIf(querySystemDocument.IsSign == false, t => t.ConfirmTime == null).ToList(); + + //var list3 = list1.Union(list2).ToList(); + + //var result = list3.ToPagedList(querySystemDocument.PageIndex, querySystemDocument.PageSize, querySystemDocument.SortField, querySystemDocument.Asc); + + #endregion var needSignTrialDocCount = await _trialDocumentRepository.AsQueryable(true).Where(t => t.TrialId== querySystemDocument.TrialId && t.Trial.TrialStatusStr != StaticData.TrialState.TrialStopped) .Where(t => t.Trial.TrialUserList.Any(t => t.UserId == _userInfo.Id)) @@ -227,13 +246,11 @@ namespace IRaCIS.Core.Application.Services var trialTaskConfig = _trialRepository.Where(t => t.Id == querySystemDocument.TrialId).ProjectTo(_mapper.ConfigurationProvider).FirstOrDefault(); - //var trialCriterionAdditionalAssessmentTypeList = _trialCriterionAdditionalAssessmentTypeRepository - // .Where(t => t.TrialReadingCriterion.TrialId == trialId && t.IsSelected == true && t.TrialReadingCriterion.IsSigned).Select(t=>new { t.CriterionType,t.AdditionalAssessmentType}).ToList(); var isManualGenerateTask= _readingQuestionCriterionTrialRepository.Where(t=>t.TrialId==trialId && t.IsSigned && t.IsAutoCreate==false).Any(); - var isAdditionalAssessment = _readingQuestionCriterionTrialRepository.Where(t => t.TrialId == trialId && t.IsSigned && t.IsAdditionalAssessment == true - &&t.TrialCriterionAdditionalAssessmentTypeList.Any(c=>/*c.AdditionalAssessmentType==Domain.Share.Reading.AdditionalAssessmentType.BrainMetastasis &&*/ c.IsSelected==true)).Any(); + + var isAdditionalAssessment =false; var isAllOnlySRReading = _readingQuestionCriterionTrialRepository.Where(t => t.TrialId == trialId && t.IsSigned).All(t => t.ReadingDivisionEnum == ReadingDivisionEnum.OnlySR); @@ -316,7 +333,7 @@ namespace IRaCIS.Core.Application.Services Name = trialDocumentNeedConfirmedUserType.TrialDocument.Name, Path = trialDocumentNeedConfirmedUserType.TrialDocument.Path, FileTypeId = trialDocumentNeedConfirmedUserType.TrialDocument.FileTypeId, - FileType = trialDocumentNeedConfirmedUserType.TrialDocument.FileType.MappedValue, + FileType = _userInfo.IsEn_Us ? trialDocumentNeedConfirmedUserType.TrialDocument.FileType.Value : trialDocumentNeedConfirmedUserType.TrialDocument.FileType.ValueCN, UpdateTime = trialDocumentNeedConfirmedUserType.TrialDocument.UpdateTime, @@ -350,7 +367,7 @@ namespace IRaCIS.Core.Application.Services SignViewMinimumMinutes = needConfirmEdUserType.SystemDocument.SignViewMinimumMinutes, Name = needConfirmEdUserType.SystemDocument.Name, Path = needConfirmEdUserType.SystemDocument.Path, - FileType = needConfirmEdUserType.SystemDocument.FileType.MappedValue, + FileType = _userInfo.IsEn_Us ? needConfirmEdUserType.SystemDocument.FileType.Value : needConfirmEdUserType.SystemDocument.FileType.ValueCN, FileTypeId = needConfirmEdUserType.SystemDocument.FileTypeId, UpdateTime = needConfirmEdUserType.SystemDocument.UpdateTime, diff --git a/IRaCIS.Core.Application/Service/Document/_MapConfig.cs b/IRaCIS.Core.Application/Service/Document/_MapConfig.cs index 3f0c411bd..225e4284b 100644 --- a/IRaCIS.Core.Application/Service/Document/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/Document/_MapConfig.cs @@ -14,12 +14,13 @@ namespace IRaCIS.Core.Application.Service var userId = Guid.Empty; var token = string.Empty; + var isEn_Us = false; CreateMap() .ForMember(d => d.FileType, u => u.MapFrom(s => s.FileType.Value)) .ForMember(d => d.FullFilePath, u => u.MapFrom(s => s.Path)); CreateMap() - .ForMember(d => d.FileType, u => u.MapFrom(s => s.FileType.MappedValue)) + .ForMember(d => d.FileType, u => u.MapFrom(s => isEn_Us ? s.FileType.Value : s.FileType.ValueCN )) .ForMember(d => d.IsSomeUserSigned, u => u.MapFrom(s => s.TrialDocConfirmedUserList.Any(t=>t.ConfirmTime!=null))) .ForMember(d => d.FullFilePath, u => u.MapFrom(s => s.Path )); diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/DicomArchiveService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/DicomArchiveService.cs index f797c8ca4..f34ac28db 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/DicomArchiveService.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/DicomArchiveService.cs @@ -1,5 +1,4 @@ -using Dicom; -using Dicom.Imaging.Codec; + using EasyCaching.Core; using IRaCIS.Core.Application.Contracts.Dicom; using IRaCIS.Core.Domain.Share; @@ -8,10 +7,13 @@ using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Application.Helper; using Microsoft.AspNetCore.Hosting; using IRaCIS.Core.Infrastructure; +using FellowOakDicom; +using FellowOakDicom.Imaging.Codec; +using Medallion.Threading; namespace IRaCIS.Core.Application.Services { - public class DicomArchiveService :BaseService, IDicomArchiveService + public class DicomArchiveService : BaseService, IDicomArchiveService { private readonly IRepository _studyRepository; private readonly IRepository _seriesRepository; @@ -21,7 +23,7 @@ namespace IRaCIS.Core.Application.Services private readonly IWebHostEnvironment _hostEnvironment; - private static object lockCodeGenerate = new object(); + private readonly IDistributedLockProvider _distributedLockProvider; private List _instanceIdList = new List(); @@ -31,8 +33,9 @@ namespace IRaCIS.Core.Application.Services IRepository instanceRepository, IWebHostEnvironment hostEnvironment, IRepository dictionaryRepository, - IEasyCachingProvider provider) + IEasyCachingProvider provider, IDistributedLockProvider distributedLockProvider) { + _distributedLockProvider = distributedLockProvider; _hostEnvironment = hostEnvironment; _studyRepository = studyRepository; @@ -50,7 +53,7 @@ namespace IRaCIS.Core.Application.Services return success; } - + public async Task<(Guid StudyId, string StudyCode)> ArchiveDicomStreamAsync(Stream dicomStream, @@ -129,7 +132,7 @@ namespace IRaCIS.Core.Application.Services DicomStudy dicomStudy = CreateDicomStudy(dataset, addtionalInfo, out bool isStudyNeedAdd); DicomSeries dicomSeries = CreateDicomSeries(dataset, dicomStudy, out bool isSeriesNeedAdd); - DicomInstance dicomInstance = CreateDicomInstance(dataset, dicomStudy, dicomSeries,out bool isInstanceNeedAdd); + DicomInstance dicomInstance = CreateDicomInstance(dataset, dicomStudy, dicomSeries, out bool isInstanceNeedAdd); dicomSeries.DicomStudy = dicomStudy; @@ -183,7 +186,7 @@ namespace IRaCIS.Core.Application.Services //正常保存 不做处理 await dicomFile.SaveAsync(physicalPath); } - else + else { //RLELossless 保存 await dicomFile.Clone(DicomTransferSyntax.RLELossless).SaveAsync(physicalPath); //RLELossless @@ -235,7 +238,7 @@ namespace IRaCIS.Core.Application.Services { modalityForEdit = "PET"; } - if(modality== "PT、CT") + if (modality == "PT、CT") { modalityForEdit = "PET-CT"; } @@ -282,9 +285,10 @@ namespace IRaCIS.Core.Application.Services dicomStudy.PatientBirthDate = $"{dicomStudy.PatientBirthDate[0]}{dicomStudy.PatientBirthDate[1]}{dicomStudy.PatientBirthDate[2]}{dicomStudy.PatientBirthDate[3]}-{dicomStudy.PatientBirthDate[4]}{dicomStudy.PatientBirthDate[5]}-{dicomStudy.PatientBirthDate[6]}{dicomStudy.PatientBirthDate[7]}"; } - lock (lockCodeGenerate) - { + var @lock = _distributedLockProvider.CreateLock($"StudyCode"); + using (@lock.Acquire()) + { //查询数据库获取最大的Code 没有记录则为0 var dbStudyCodeIntMax = _studyRepository.Where(s => s.TrialId == addtionalInfo.TrialId).Select(t => t.Code).DefaultIfEmpty().Max(); @@ -298,9 +302,9 @@ namespace IRaCIS.Core.Application.Services dicomStudy.StudyCode = AppSettings.GetCodeStr(currentNextCodeInt, nameof(DicomStudy)); _provider.Set($"{addtionalInfo.TrialId}_{StaticData.CacheKey.StudyMaxCode}", dicomStudy.Code, TimeSpan.FromMinutes(30)); - } + #region Setting Code old //var studyCode = _studyRepository.Where(s => s.TrialId == addtionalInfo.TrialId).Select(t => t.StudyCode).OrderByDescending(c => c).FirstOrDefault(); @@ -468,7 +472,7 @@ namespace IRaCIS.Core.Application.Services _instanceIdList.Add(instanceId); } - + return dicomInstance; } diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/ImageShareService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/ImageShareService.cs index e84fb9df6..ab21ac4fd 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/ImageShareService.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/ImageShareService.cs @@ -5,25 +5,27 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using IRaCIS.Core.Application.Auth; +using EasyCaching.Core; namespace IRaCIS.Core.Application.Services { [AllowAnonymous, ApiExplorerSettings(GroupName = "Image")] public class ImageShareService : BaseService, IImageShareService { - + private readonly IEasyCachingProvider _provider; private readonly IRepository _imageShareRepository; private readonly IRepository _studyRepository; private readonly IConfiguration _configuration; private readonly ITokenService _tokenService; - public ImageShareService(IRepository imageShareRepository, IRepository studyRepository, IConfiguration configuration, ITokenService tokenService) + public ImageShareService(IRepository imageShareRepository, IRepository studyRepository, IConfiguration configuration, ITokenService tokenService, IEasyCachingProvider provider) { _imageShareRepository = imageShareRepository; _studyRepository = studyRepository; _configuration = configuration; _tokenService = tokenService; + _provider = provider; } [HttpPost] @@ -110,6 +112,7 @@ namespace IRaCIS.Core.Application.Services return ResponseOutput.NotOk(_localizer["ISS_ShareExpiration"]); } + var vitrualUserId = Guid.NewGuid(); var resource = new ResourceInfo() { StudyId = imageShare.StudyId, @@ -127,7 +130,7 @@ namespace IRaCIS.Core.Application.Services })) }; - + await _provider.SetAsync(vitrualUserId.ToString(), resource.Token, TimeSpan.FromDays(7)); return ResponseOutput.Ok(resource); } diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs index 173c643f1..adb1f224a 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs @@ -14,16 +14,13 @@ using IRaCIS.Core.Application.MediatR.Handlers; using Microsoft.AspNetCore.Http; using Newtonsoft.Json; using System.Threading; -using Nito.AsyncEx; +using Medallion.Threading; namespace IRaCIS.Core.Application.Service.ImageAndDoc { [ApiExplorerSettings(GroupName = "Image")] public class StudyService : BaseService, IStudyService { - private static object lockObj = new object(); - private static readonly AsyncLock _mutex = new AsyncLock(); - private static readonly AsyncLock _mutex2 = new AsyncLock(); private readonly IEasyCachingProvider _provider; @@ -35,12 +32,12 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc private readonly IRepository _dictionaryRepository; private readonly IRepository _studyMonitorRepository; - + private readonly IDistributedLockProvider _distributedLockProvider; public StudyService(IEasyCachingProvider provider , IRepository subjectVisitRepository, IRepository dicomInstanceRepository, - IRepository dicomSeriesRepository, IRepository dicomstudyRepository, IRepository dictionaryRepository, IRepository studyMonitorRepository) + IRepository dicomSeriesRepository, IRepository dicomstudyRepository, IRepository dictionaryRepository, IRepository studyMonitorRepository, IDistributedLockProvider distributedLockProvider) { _provider = provider; _subjectVisitRepository = subjectVisitRepository; @@ -49,6 +46,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc _dicomstudyRepository = dicomstudyRepository; _dictionaryRepository = dictionaryRepository; _studyMonitorRepository = studyMonitorRepository; + _distributedLockProvider = distributedLockProvider; } @@ -160,7 +158,9 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc { var study = _mapper.Map(incommand.Study); - using (await _mutex.LockAsync()) + var @lock = _distributedLockProvider.CreateLock($"StudyCode"); + + using (await @lock.AcquireAsync()) { //查询数据库获取最大的Code 没有记录则为0 var dbStudyCodeIntMax = _dicomstudyRepository.Where(s => s.TrialId == trialId).Select(t => t.Code).DefaultIfEmpty().Max(); @@ -306,11 +306,11 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc } - using (await _mutex2.LockAsync()) + var @lock2 = _distributedLockProvider.CreateLock($"StudyCommit"); + + using (await @lock2.AcquireAsync()) { await _dicomInstanceRepository.SaveChangesAsync(); - - } } catch (Exception ex) @@ -765,7 +765,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc if (_provider.Exists($"StudyUid_{trialId}_{studyInstanceUid}")) { - + result.AllowUpload = false; result.AllowReUpload = false; @@ -826,22 +826,22 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc } result.StudyInstanceUid = studyInstanceUid; + var @lock = _distributedLockProvider.CreateLock($"StudyUpload"); - if (result.AllowReUpload || result.AllowUpload) + using (@lock.Acquire()) { - lock (lockObj) + if (result.AllowReUpload || result.AllowUpload) { _provider.Set($"StudyUid_{trialId}_{studyInstanceUid}", _userInfo.Id, TimeSpan.FromSeconds(30)); } - } - else - { - lock (lockObj) + else { _provider.Remove($"StudyUid_{trialId}_{studyInstanceUid}"); } } + + return result; } diff --git a/IRaCIS.Core.Application/Service/Institution/SiteService.cs b/IRaCIS.Core.Application/Service/Institution/SiteService.cs index 3ccc8139f..b65b2379f 100644 --- a/IRaCIS.Core.Application/Service/Institution/SiteService.cs +++ b/IRaCIS.Core.Application/Service/Institution/SiteService.cs @@ -3,7 +3,7 @@ using IRaCIS.Application.Contracts; using IRaCIS.Core.Infra.EFCore; using Microsoft.AspNetCore.Mvc; using IRaCIS.Core.Domain.Share; -using Nito.AsyncEx; +using Medallion.Threading; namespace IRaCIS.Application.Services { @@ -12,13 +12,13 @@ namespace IRaCIS.Application.Services { private readonly IRepository _siteRepository; private readonly IRepository _trialSiteUserRepository; + private readonly IDistributedLockProvider _distributedLockProvider; - private readonly AsyncLock _mutex = new AsyncLock(); - - public SiteService(IRepository siteRepository, IRepository trialSiteUserRepository) + public SiteService(IRepository siteRepository, IRepository trialSiteUserRepository, IDistributedLockProvider distributedLockProvider) { _siteRepository = siteRepository; - this._trialSiteUserRepository = trialSiteUserRepository; + _trialSiteUserRepository = trialSiteUserRepository; + _distributedLockProvider = distributedLockProvider; } /// 分页获取研究中心列表 @@ -27,7 +27,7 @@ namespace IRaCIS.Application.Services { var siteQueryable = _siteRepository - .WhereIf(!string.IsNullOrWhiteSpace(searchModel.SiteName), t => t.SiteName.Contains(searchModel.SiteName)) + .WhereIf(!string.IsNullOrWhiteSpace(searchModel.SiteName), t => t.SiteName.Contains(searchModel.SiteName) || t.SiteNameCN.Contains(searchModel.SiteName)) .WhereIf(!string.IsNullOrWhiteSpace(searchModel.AliasName), t => t.AliasName.Contains(searchModel.AliasName)) .WhereIf(!string.IsNullOrWhiteSpace(searchModel.City), t => t.City.Contains(searchModel.City)) .WhereIf(!string.IsNullOrWhiteSpace(searchModel.Country), t => t.Country.Contains(searchModel.Country)) @@ -58,7 +58,9 @@ namespace IRaCIS.Application.Services VerifyMsg = _localizer["Site_DupName"] }; - using (await _mutex.LockAsync()) + var @lock = _distributedLockProvider.CreateLock($"SiteAdd"); + + using (await @lock.AcquireAsync()) { if (siteCommand.Id == null) { diff --git a/IRaCIS.Core.Application/Service/Management/UserService.cs b/IRaCIS.Core.Application/Service/Management/UserService.cs index 32df5fa15..3a6af0f62 100644 --- a/IRaCIS.Core.Application/Service/Management/UserService.cs +++ b/IRaCIS.Core.Application/Service/Management/UserService.cs @@ -8,10 +8,10 @@ using Panda.DynamicWebApi.Attributes; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.Options; using Microsoft.Extensions.Caching.Memory; -using IRaCIS.Core.Infra.Common.Cache; using Microsoft.Identity.Client; using static IRaCIS.Core.Domain.Share.StaticData; using IRaCIS.Core.Application.ViewModel; +using Medallion.Threading; namespace IRaCIS.Application.Services { @@ -24,7 +24,7 @@ namespace IRaCIS.Application.Services private readonly IRepository _userTrialRepository; private readonly IRepository _userLogRepository; - + private readonly IDistributedLockProvider _distributedLockProvider; private readonly IMemoryCache _cache; private readonly IOptionsMonitor _verifyConfig; @@ -38,7 +38,8 @@ namespace IRaCIS.Application.Services IRepository userTrialRepository, IOptionsMonitor verifyConfig, IRepository userLogRepository - ) +, + IDistributedLockProvider distributedLockProvider) { _userLogRepository = userLogRepository; @@ -47,9 +48,10 @@ namespace IRaCIS.Application.Services _userRepository = userRepository; _mailVerificationService = mailVerificationService; _verificationCodeRepository = verificationCodeRepository; - + _userTrialRepository = userTrialRepository; _userLogRepository = userLogRepository; + _distributedLockProvider = distributedLockProvider; } @@ -502,29 +504,32 @@ namespace IRaCIS.Application.Services var saveItem = _mapper.Map(userAddModel); - saveItem.Code = await _userRepository.Select(t => t.Code).DefaultIfEmpty().MaxAsync() + 1; + var @lock = _distributedLockProvider.CreateLock($"UserAccount"); - saveItem.UserCode = AppSettings.GetCodeStr(saveItem.Code, nameof(User)); - - if (saveItem.IsZhiZhun) + using (await @lock.AcquireAsync()) { - saveItem.OrganizationName = AppSettings.DefaultInternalOrganizationName; + saveItem.Code = await _userRepository.Select(t => t.Code).DefaultIfEmpty().MaxAsync() + 1; + + saveItem.UserCode = AppSettings.GetCodeStr(saveItem.Code, nameof(User)); + + if (saveItem.IsZhiZhun) + { + saveItem.OrganizationName = AppSettings.DefaultInternalOrganizationName; + } + + + saveItem.Password = MD5Helper.Md5("123456"); + + await _userRepository.AddAsync(saveItem); + + var success = await _userRepository.SaveChangesAsync(); } - - saveItem.Password = MD5Helper.Md5("123456"); - - await _userRepository.AddAsync(saveItem); - - var success = await _userRepository.SaveChangesAsync(); - - + await _mailVerificationService.AddUserSendEmailAsync(saveItem.Id, userAddModel.BaseUrl, userAddModel.RouteUrl); - - - return ResponseOutput.Result(success, new UserAddedReturnDTO { Id = saveItem.Id, UserCode = saveItem.UserCode }); + return ResponseOutput.Ok( new UserAddedReturnDTO { Id = saveItem.Id, UserCode = saveItem.UserCode }); } diff --git a/IRaCIS.Core.Application/Service/QC/NoneDicomStudyService.cs b/IRaCIS.Core.Application/Service/QC/NoneDicomStudyService.cs index fa912838f..e6a40c3bf 100644 --- a/IRaCIS.Core.Application/Service/QC/NoneDicomStudyService.cs +++ b/IRaCIS.Core.Application/Service/QC/NoneDicomStudyService.cs @@ -5,10 +5,10 @@ //-------------------------------------------------------------------- using Microsoft.AspNetCore.Mvc; using IRaCIS.Core.Application.Filter; -using Nito.AsyncEx; using System.ComponentModel.DataAnnotations; using IRaCIS.Core.Application.Service; using IRaCIS.Core.Domain.Share; +using Medallion.Threading; namespace IRaCIS.Core.Application.Contracts { @@ -20,19 +20,19 @@ namespace IRaCIS.Core.Application.Contracts { private readonly IRepository _noneDicomStudyRepository; private readonly IRepository _noneDicomStudyFileRepository; - private readonly AsyncLock _mutex = new AsyncLock(); + private readonly IDistributedLockProvider _distributedLockProvider; private readonly QCCommon _qCCommon; public NoneDicomStudyService(IRepository noneDicomStudyRepository, QCCommon qCCommon, - IRepository noneDicomStudyFileRepository) + IRepository noneDicomStudyFileRepository, IDistributedLockProvider distributedLockProvider) { _qCCommon = qCCommon; _noneDicomStudyRepository = noneDicomStudyRepository; _noneDicomStudyFileRepository = noneDicomStudyFileRepository; - + _distributedLockProvider = distributedLockProvider; } @@ -62,7 +62,9 @@ namespace IRaCIS.Core.Application.Contracts } NoneDicomStudy? optEntity = null; - using (await _mutex.LockAsync()) + var @lock = _distributedLockProvider.CreateLock($"NoneDicomCode"); + + using (await @lock.AcquireAsync()) { if (addOrEditNoneDicomStudy.Id == Guid.Empty || addOrEditNoneDicomStudy.Id == null) { diff --git a/IRaCIS.Core.Application/Service/QC/QCOperationService.cs b/IRaCIS.Core.Application/Service/QC/QCOperationService.cs index 85c7f3f49..5f8e7e621 100644 --- a/IRaCIS.Core.Application/Service/QC/QCOperationService.cs +++ b/IRaCIS.Core.Application/Service/QC/QCOperationService.cs @@ -10,13 +10,13 @@ using WinSCP; using Newtonsoft.Json; using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Application.Service.Inspection.DTO; -using Nito.AsyncEx; using System.ComponentModel.DataAnnotations; using IRaCIS.Core.Application.Auth; using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Application.Service; +using Medallion.Threading; namespace IRaCIS.Core.Application.Image.QA { @@ -35,8 +35,7 @@ namespace IRaCIS.Core.Application.Image.QA private readonly IRepository _trialRepository; private readonly IRepository _visitTaskRepository; private readonly IVisitTaskHelpeService _IVisitTaskHelpeService; - - private readonly AsyncLock _mutex = new AsyncLock(); + private readonly IDistributedLockProvider _distributedLockProvider; public QCOperationService(IRepository subjectVisitRepository, IRepository qcChallengeRepository, @@ -48,7 +47,8 @@ namespace IRaCIS.Core.Application.Image.QA IRepository readingClinicalDataRepository, IRepository qCChallengeDialogrepository, IRepository checkChallengeDialogrepository, - IVisitTaskHelpeService visitTaskHelpeService + IVisitTaskHelpeService visitTaskHelpeService, + IDistributedLockProvider distributedLockProvider ) { _subjectVisitRepository = subjectVisitRepository; @@ -62,6 +62,7 @@ namespace IRaCIS.Core.Application.Image.QA _trialRepository = trialRepository; this._visitTaskRepository = visitTaskRepository; _IVisitTaskHelpeService = visitTaskHelpeService; + _distributedLockProvider = distributedLockProvider; } #region QC质疑 以及回复 关闭 @@ -108,9 +109,9 @@ namespace IRaCIS.Core.Application.Image.QA var trialConfig = (await _trialRepository.Where(t => t.Id == trialId).Select(t => new { TrialId = t.Id, t.QCProcessEnum, t.IsImageConsistencyVerification }).FirstOrDefaultAsync()).IfNullThrowException(); + var @lock = _distributedLockProvider.CreateLock($"QCChallengeCode"); - - using (await _mutex.LockAsync()) + using (await @lock.AcquireAsync()) { //获取编号 var code = _qcChallengeRepository.Where(t => t.TrialId == trialId).Select(t => t.Code).DefaultIfEmpty().Max(); @@ -1968,6 +1969,18 @@ namespace IRaCIS.Core.Application.Image.QA //已确认临床数据完整性 dbSubjectVisit.IsConfirmedClinicalData = true; + + await _readingClinicalDataRepository.UpdatePartialFromQueryAsync(x => + + (x.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.Subject || x.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.SubjectVisit) && + + + x.ClinicalDataTrialSet.UploadRole == UploadRole.CRC && x.ReadingId == dbSubjectVisit.Id && x.IsSign == false, x => new ReadingClinicalData() + { + IsSign = true, + ReadingClinicalDataState = ReadingClinicalDataStatus.HaveSigned + }); + //var signSuccess = await _repository.BatchUpdateAsync(t => t.Id == cRCReuploadFinishedCommand.SignId, u => new TrialSign() { IsCompleted = true }); } diff --git a/IRaCIS.Core.Application/Service/Reading/ClinicalData/ReadingClinicalDataService.cs b/IRaCIS.Core.Application/Service/Reading/ClinicalData/ReadingClinicalDataService.cs index d65654bf4..bd20071e1 100644 --- a/IRaCIS.Core.Application/Service/Reading/ClinicalData/ReadingClinicalDataService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ClinicalData/ReadingClinicalDataService.cs @@ -148,6 +148,7 @@ namespace IRaCIS.Application.Services var fileCount = await _readingClinicalDataPDFRepository.Where(t => t.ReadingClinicalDataId == indto.Id).CountAsync(); entity.ReadingClinicalDataState = ReadingClinicalDataStatus.HaveUploaded; + entity.IsSign = false; entity.FileCount = fileCount; var success = await _readingClinicalDataRepository.SaveChangesAsync(); return ResponseOutput.Ok(entity.Id); diff --git a/IRaCIS.Core.Application/Service/Reading/Dto/ReadingMedicalReviewDto.cs b/IRaCIS.Core.Application/Service/Reading/Dto/ReadingMedicalReviewDto.cs index f9f6b0f38..9a730f4b6 100644 --- a/IRaCIS.Core.Application/Service/Reading/Dto/ReadingMedicalReviewDto.cs +++ b/IRaCIS.Core.Application/Service/Reading/Dto/ReadingMedicalReviewDto.cs @@ -266,7 +266,7 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto public string ImagePath { get; set; } = string.Empty; - public List FileList { get; set; } = new List(); + public List FileList { get; set; } = new List(); } @@ -314,7 +314,7 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto - public List FileList { get; set; } = new List(); + public List FileList { get; set; } = new List(); @@ -455,7 +455,7 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto public Guid TaskMedicalReviewId { get; set; } - public List FileList { get; set; } = new List(); + public List FileList { get; set; } = new List(); /// @@ -502,7 +502,7 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto public string Questioning { get; set; } = string.Empty; - public List FileList { get; set; } = new List(); + public List FileList { get; set; } = new List(); /// /// 审核建议 diff --git a/IRaCIS.Core.Application/Service/SiteSurvey/Interface/JsonPatchUserRequestExample.cs b/IRaCIS.Core.Application/Service/SiteSurvey/Interface/JsonPatchUserRequestExample.cs deleted file mode 100644 index 0fa6ff834..000000000 --- a/IRaCIS.Core.Application/Service/SiteSurvey/Interface/JsonPatchUserRequestExample.cs +++ /dev/null @@ -1,51 +0,0 @@ -using Microsoft.AspNetCore.JsonPatch.Operations; -using Swashbuckle.AspNetCore.Filters; - -namespace IRaCIS.Core.Application.Contracts -{ - /// - /// 实测 标注在服务方法上 没用 - /// - public class JsonPatchUserRequestExample : IExamplesProvider - { - public Operation[] GetExamples() - { - return new[] - { - new Operation - { - op = "replace", - path = "/name", - value = "Gordon" - }, - new Operation - { - op = "replace", - path = "/surname", - value = "Freeman" - } - }; - } - - object IExamplesProvider.GetExamples() - { - return new[] - { - new Operation - { - op = "replace", - path = "/name", - value = "Gordon" - }, - new Operation - { - op = "replace", - path = "/surname", - value = "Freeman" - } - }; - } - } - - -} diff --git a/IRaCIS.Core.Application/Service/SiteSurvey/TrialSiteSurveyService.cs b/IRaCIS.Core.Application/Service/SiteSurvey/TrialSiteSurveyService.cs index eeb90d390..e5c673fbd 100644 --- a/IRaCIS.Core.Application/Service/SiteSurvey/TrialSiteSurveyService.cs +++ b/IRaCIS.Core.Application/Service/SiteSurvey/TrialSiteSurveyService.cs @@ -20,7 +20,7 @@ using Microsoft.VisualBasic; using DocumentFormat.OpenXml.Spreadsheet; using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Application.ViewModel; -using Dicom; +using Medallion.Threading; namespace IRaCIS.Core.Application.Contracts { @@ -36,13 +36,14 @@ namespace IRaCIS.Core.Application.Contracts private readonly IRepository _trialSiteRepository; private readonly IRepository _trialUserRepository; private readonly IRepository _trialSiteUserRepository; + private readonly IDistributedLockProvider _distributedLockProvider; private readonly ITokenService _tokenService; private readonly IMailVerificationService _mailVerificationService; public TrialSiteSurveyService(IRepository trialSiteSurveyRepository, IRepository trialUserRepository, IRepository trialSiteUserSurveyRepository, IRepository userRepository, IRepository trialSiteRepository, ITokenService tokenService, - IMailVerificationService mailVerificationService, IRepository trialSiteUserRepository) + IMailVerificationService mailVerificationService, IRepository trialSiteUserRepository, IDistributedLockProvider distributedLockProvider) { _trialSiteSurveyRepository = trialSiteSurveyRepository; _trialSiteUserSurveyRepository = trialSiteUserSurveyRepository; @@ -52,9 +53,9 @@ namespace IRaCIS.Core.Application.Contracts _tokenService = tokenService; _mailVerificationService = mailVerificationService; _trialSiteUserRepository = trialSiteUserRepository; + _distributedLockProvider = distributedLockProvider; } - private object lockObj { get; set; } = new object(); /// /// 发送验证码 @@ -503,7 +504,7 @@ namespace IRaCIS.Core.Application.Contracts .WhereIf(surveyQueryDTO.UpdateTimeBegin != null, t => t.UpdateTime >= surveyQueryDTO.UpdateTimeBegin) .WhereIf(surveyQueryDTO.UpdateTimeEnd != null, t => t.UpdateTime <= surveyQueryDTO.UpdateTimeEnd) - .ProjectTo(_mapper.ConfigurationProvider); + .ProjectTo(_mapper.ConfigurationProvider,new { isEn_Us =_userInfo.IsEn_Us}); return await trialSiteSurveyQueryable.ToPagedListAsync(surveyQueryDTO.PageIndex, surveyQueryDTO.PageSize, surveyQueryDTO.SortField, surveyQueryDTO.Asc); } @@ -792,7 +793,9 @@ namespace IRaCIS.Core.Application.Contracts if (sysUserInfo == null) { - lock (lockObj) + var @lock = _distributedLockProvider.CreateLock($"UserCode"); + + using (await @lock.AcquireAsync()) { var saveItem = _mapper.Map(item); @@ -972,7 +975,9 @@ namespace IRaCIS.Core.Application.Contracts if (sysUserInfo == null) { - lock (lockObj) + var @lock = _distributedLockProvider.CreateLock($"UserCode"); + + using (await @lock.AcquireAsync()) { var saveItem = _mapper.Map(item); diff --git a/IRaCIS.Core.Application/Service/SiteSurvey/_MapConfig.cs b/IRaCIS.Core.Application/Service/SiteSurvey/_MapConfig.cs index ea2453623..1ad12fa3a 100644 --- a/IRaCIS.Core.Application/Service/SiteSurvey/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/SiteSurvey/_MapConfig.cs @@ -12,6 +12,7 @@ namespace IRaCIS.Core.Application.AutoMapper { public SiteSurveyConfig() { + var isEn_Us = false; //编辑 CreateMap().ReverseMap(); @@ -47,12 +48,12 @@ namespace IRaCIS.Core.Application.AutoMapper CreateMap() .ForMember(d => d.TrialSiteAliasName, u => u.MapFrom(s => s.TrialSite.TrialSiteAliasName)) - .ForMember(d => d.SiteName, u => u.MapFrom(s => s.Site.SiteName)) + .ForMember(d => d.SiteName, u => u.MapFrom(s => isEn_Us? s.Site.SiteName:s.Site.SiteNameCN)) .ForMember(d => d.TrialSiteCode, u => u.MapFrom(s => s.TrialSite.TrialSiteCode)); CreateMap(); - var isEn_Us = false; + CreateMap() .ForMember(d => d.UserType, u => u.MapFrom(s => s.UserTypeRole.UserTypeShortName)) .ForMember(d => d.UserTypeEnum, u => u.MapFrom(s => s.UserTypeRole.UserTypeEnum)); diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialConfigDTO.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialConfigDTO.cs index cebb72bfa..a912aff0a 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialConfigDTO.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialConfigDTO.cs @@ -518,7 +518,7 @@ namespace IRaCIS.Core.Application.Contracts public bool IsAutoCreate { get; set; } - public List TrialCriterionAdditionalAssessmentTypeList { get; set; } = new List(); + public int ReadingDivisionEnum { get; set; } @@ -986,7 +986,6 @@ namespace IRaCIS.Core.Application.Contracts /// public bool IsUrgent { get; set; } = false; - public List TrialCriterionAdditionalAssessmentTypeList { get; set; }=new List(); public ReadingDivisionEnum ReadingDivisionEnum { get; set; } diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialSiteViewModel.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialSiteViewModel.cs index 4d6f03f16..f7597e0ad 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialSiteViewModel.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialSiteViewModel.cs @@ -115,8 +115,9 @@ namespace IRaCIS.Core.Application.Contracts.DTO public string SiteCode { get; set; } = String.Empty; public string City { get; set; } = String.Empty; public string Country { get; set; } = String.Empty; - public Guid? HospitalId { get; set; } + public Guid? HospitalId { get; set; } + public string Address { get; set; } = String.Empty; public string HospitalName { get; set; } = String.Empty; diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/PersonalWorkstation.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/PersonalWorkstation.cs index 71cd81d3c..f9caadb9e 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/PersonalWorkstation.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/PersonalWorkstation.cs @@ -1031,7 +1031,7 @@ namespace IRaCIS.Core.Application .WhereIf(!string.IsNullOrEmpty(inQuery.Code), o => o.TrialCode.Contains(inQuery.Code)) .WhereIf(!string.IsNullOrEmpty(inQuery.ResearchProgramNo), o => o.ResearchProgramNo.Contains(inQuery.ResearchProgramNo)) .WhereIf(!string.IsNullOrWhiteSpace(inQuery.ExperimentName), o => o.ExperimentName.Contains(inQuery.ExperimentName)) - .WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin, t => t.TrialUserList.Any(t => t.UserId == _userInfo.Id && t.IsDeleted == false) && t.IsDeleted == false) + .WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin && _userInfo.UserTypeEnumInt != (int)UserTypeEnum.Admin, t => t.TrialUserList.Any(t => t.UserId == _userInfo.Id && t.IsDeleted == false) && t.IsDeleted == false) .Select(t => new TrialToBeDoneDto() { TrialId = t.Id, diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs index 3b2e23a57..039a80267 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs @@ -40,7 +40,6 @@ namespace IRaCIS.Core.Application private readonly IRepository _readingCriterionDictionaryRepository; private readonly IRepository _readingTrialCriterionDictionaryRepository; private readonly IReadingQuestionService iReadingQuestionService; - private readonly IRepository _trialCriterionAdditionalAssessmentTypeRepository; private readonly IRepository _readingTaskQuestionAnswer; @@ -65,7 +64,6 @@ namespace IRaCIS.Core.Application IReadingQuestionService iReadingQuestionService, IEasyCachingProvider provider, IOrganInfoService iOrganInfoService, - IRepository trialCriterionAdditionalAssessmentTypeRepository, IRepository visitTaskRepository, IRepository readingTableQuestionTrialRepository, IRepository readingTableQuestionAnswerRepository, @@ -74,7 +72,6 @@ namespace IRaCIS.Core.Application ) { - _trialCriterionAdditionalAssessmentTypeRepository = trialCriterionAdditionalAssessmentTypeRepository; _trialRepository = trialRepository; this._readingCriterionDictionaryRepository = readingCriterionDictionaryRepository; @@ -188,7 +185,6 @@ namespace IRaCIS.Core.Application trialInfo.ReadingTool = ReadingTool.Dicom; } - trialInfo.TrialCriterionAdditionalAssessmentTypeList = await _trialCriterionAdditionalAssessmentTypeRepository.Where(t => t.TrialReadingCriterionId == inDto.TrialReadingCriterionId).ToListAsync(); return trialInfo; @@ -212,23 +208,7 @@ namespace IRaCIS.Core.Application if (trialCriterion.SynchronizeOriginalTime == null) { - //同步附加评估类型 - if (!await _trialCriterionAdditionalAssessmentTypeRepository.AnyAsync(t => t.TrialReadingCriterionId == inDto.TrialReadingCriterionId)) - { - AdditionalAssessment additional = new AdditionalAssessment(); - var addList = additional.GetSystemDefeaultAdditionalAssessmentList(trialCriterion.CriterionType); - - foreach (var addItem in addList) - { - await _trialCriterionAdditionalAssessmentTypeRepository.AddAsync(new TrialCriterionAdditionalAssessmentType() - { - CriterionType = trialCriterion.CriterionType, - TrialReadingCriterionId = inDto.TrialReadingCriterionId, - AdditionalAssessmentType = addItem.AdditionalAssessmentType - }); - } - } @@ -604,72 +584,7 @@ namespace IRaCIS.Core.Application }); - //判断是否存在附加评估 - if (inDto.IsAdditionalAssessment) - { - #region 存在,就将标准对应的附加评估选项加进去--废弃 修改到同步标准的地方去了,不管存在附加评估与否,都增加附加评估类型 - //if (!await _trialCriterionAdditionalAssessmentTypeRepository.AnyAsync(t => t.TrialReadingCriterionId == inDto.TrialReadingCriterionId)) - //{ - // AdditionalAssessment additional = new AdditionalAssessment(); - // var addList = additional.GetSystemDefeaultAdditionalAssessmentList(inDto.CriterionType); - // foreach (var addItem in addList) - // { - // await _trialCriterionAdditionalAssessmentTypeRepository.AddAsync(new TrialCriterionAdditionalAssessmentType() - // { - // CriterionType = inDto.CriterionType, - // TrialReadingCriterionId = inDto.TrialReadingCriterionId, - // AdditionalAssessmentType = addItem.AdditionalAssessmentType - // }); - // } - //} - #endregion - - - if (inDto.TrialCriterionAdditionalAssessmentTypeList.All(t => t.IsSelected != true)) - { - //---选择了附加评估,必须勾选附加评估类型 - throw new BusinessValidationFailedException(_localizer["TrialConfig_AddEvalReq"]); - } - - var trialId = _readingQuestionTrialRepository.Where(t => t.ReadingQuestionCriterionTrialId == inDto.TrialReadingCriterionId).Select(t => t.TrialId).FirstOrDefault(); - - - if (inDto.TrialCriterionAdditionalAssessmentTypeList.Count != 0) - { - foreach (var updateItem in inDto.TrialCriterionAdditionalAssessmentTypeList) - { - if (updateItem.IsSelected == true) - { - //添加默认问题 - AdditionalAssessment additional = new AdditionalAssessment(); - var addTypeList = additional.GetSystemDefeaultAdditionalAssessmentList(updateItem.CriterionType, updateItem.AdditionalAssessmentType); - - if (!await _readingQuestionTrialRepository.AsQueryable().IgnoreQueryFilters().AnyAsync(t => t.ReadingQuestionCriterionTrialId == updateItem.TrialReadingCriterionId && t.IsAdditional == true)) - { - foreach (var addType in addTypeList) - { - foreach (var question in addType.AdditionalQuestionList) - { - question.ReadingQuestionCriterionTrialId = updateItem.TrialReadingCriterionId; - question.TrialId = trialId; - - await _readingQuestionTrialRepository.AddAsync(question); - } - } - } - } - - await _trialCriterionAdditionalAssessmentTypeRepository.UpdatePartialFromQueryAsync(updateItem.Id, t => new TrialCriterionAdditionalAssessmentType() { IsSelected = updateItem.IsSelected }); - } - } - - } - else - { - //删除附加问题 - await _readingQuestionTrialRepository.BatchDeleteNoTrackingAsync(t => t.ReadingQuestionCriterionTrialId == inDto.TrialReadingCriterionId && t.IsAdditional == true); - } var result = await _readingQuestionCriterionTrialRepository.SaveChangesAsync(); @@ -677,67 +592,9 @@ namespace IRaCIS.Core.Application return ResponseOutput.Ok(result); } - /// - /// 获取附加评估选项列表 - /// - /// - /// - [Obsolete] - public async Task> GetTrialCriterionAdditionalAssessmentOptionList(Guid trialReadingCriterionId) - { - return await _trialCriterionAdditionalAssessmentTypeRepository.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId).ToListAsync(); - } - /// - /// 保存附加评估设置 (自动添加 或者删除附加评估问题) - /// - /// - /// - [Obsolete] - public async Task SetTrialCriterionAdditionalAssessment(List updateList) - { - if (updateList.Count == 0) - { - return ResponseOutput.Ok(); - } - - var trialId = _readingQuestionTrialRepository.Where(t => t.ReadingQuestionCriterionTrialId == updateList.First().TrialReadingCriterionId).Select(t => t.TrialId).FirstOrDefault(); - - foreach (var updateItem in updateList) - { - if (updateItem.IsSelected == true) - { - //添加默认问题 - AdditionalAssessment additional = new AdditionalAssessment(); - var addTypeList = additional.GetSystemDefeaultAdditionalAssessmentList(updateItem.CriterionType, updateItem.AdditionalAssessmentType); - - foreach (var addType in addTypeList) - { - foreach (var question in addType.AdditionalQuestionList) - { - question.ReadingQuestionCriterionTrialId = updateItem.TrialReadingCriterionId; - question.TrialId = trialId; - - await _readingQuestionTrialRepository.AddAsync(question); - } - } - } - else - { - //删除附加问题 - - await _readingQuestionTrialRepository.BatchDeleteNoTrackingAsync(t => t.ReadingQuestionCriterionTrialId == updateItem.TrialReadingCriterionId && t.IsAdditional == true); - } - - await _trialCriterionAdditionalAssessmentTypeRepository.UpdatePartialFromQueryAsync(updateItem.Id, t => new TrialCriterionAdditionalAssessmentType() { IsSelected = updateItem.IsSelected }); - } - - - await _readingQuestionTrialRepository.SaveChangesAsync(); - return ResponseOutput.Ok(); - } /// diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialExternalUserService.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialExternalUserService.cs index 6bf00a16e..96704f954 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialExternalUserService.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialExternalUserService.cs @@ -16,6 +16,7 @@ using Panda.DynamicWebApi.Attributes; using IRaCIS.Core.Application.Auth; using IRaCIS.Application.Services; using IRaCIS.Core.Application.Filter; +using Medallion.Threading; namespace IRaCIS.Core.Application.Service { @@ -31,10 +32,11 @@ namespace IRaCIS.Core.Application.Service private readonly IRepository _trialSiteSurveyUserRepository; private readonly IRepository _trialSiteUserRepository; private readonly IMailVerificationService _mailVerificationService; + private readonly IDistributedLockProvider _distributedLockProvider; public TrialExternalUserService(IRepository trialExternalUseRepository, IRepository userRepository, IRepository trialUserRepository, IRepository trialSiteSurveyUserRepository, IRepository trialSiteUserRepository, - IMailVerificationService mailVerificationService) + IMailVerificationService mailVerificationService, IDistributedLockProvider distributedLockProvider) { _trialExternalUseRepository = trialExternalUseRepository; _userRepository = userRepository; @@ -43,6 +45,7 @@ namespace IRaCIS.Core.Application.Service _trialSiteUserRepository = trialSiteUserRepository; _mailVerificationService = mailVerificationService; + _distributedLockProvider = distributedLockProvider; } @@ -75,121 +78,125 @@ namespace IRaCIS.Core.Application.Service if (addOrEditTrialExternalUser.Id == null) { - var existSysUser = await _userRepository.FirstOrDefaultAsync(t => t.EMail == addOrEditTrialExternalUser.Email && t.UserTypeId == addOrEditTrialExternalUser.UserTypeId); + var @lock = _distributedLockProvider.CreateLock($"UserCode"); - if (existSysUser != null) + using (await @lock.AcquireAsync()) { - if (existSysUser.LastName != addOrEditTrialExternalUser.LastName || existSysUser.FirstName != addOrEditTrialExternalUser.FirstName) + var existSysUser = await _userRepository.FirstOrDefaultAsync(t => t.EMail == addOrEditTrialExternalUser.Email && t.UserTypeId == addOrEditTrialExternalUser.UserTypeId); + + if (existSysUser != null) { - //$"该用户在系统中的用户名为:{existSysUser.LastName + " / " + existSysUser.FirstName} 电话:{existSysUser.Phone},与填写信息存在不一致项, 请将界面信息修改为与系统一致,再进行保存", - return ResponseOutput.NotOk(_localizer["TrialExternalUser_Inconsistency", existSysUser.LastName + " / " + existSysUser.FirstName, existSysUser.Phone], new { existSysUser.LastName, existSysUser.FirstName, existSysUser.Phone, existSysUser.IsZhiZhun, existSysUser.IsTestUser }, ApiResponseCodeEnum.NeedTips); + if (existSysUser.LastName != addOrEditTrialExternalUser.LastName || existSysUser.FirstName != addOrEditTrialExternalUser.FirstName) + { + //$"该用户在系统中的用户名为:{existSysUser.LastName + " / " + existSysUser.FirstName} 电话:{existSysUser.Phone},与填写信息存在不一致项, 请将界面信息修改为与系统一致,再进行保存", + return ResponseOutput.NotOk(_localizer["TrialExternalUser_Inconsistency", existSysUser.LastName + " / " + existSysUser.FirstName, existSysUser.Phone], new { existSysUser.LastName, existSysUser.FirstName, existSysUser.Phone, existSysUser.IsZhiZhun, existSysUser.IsTestUser }, ApiResponseCodeEnum.NeedTips); + } + } - } + //处理 生成账户 - //处理 生成账户 - - if (await _trialExternalUseRepository.AnyAsync(t => - t.Email == addOrEditTrialExternalUser.Email && - t.UserTypeId == addOrEditTrialExternalUser.UserTypeId && t.TrialId == addOrEditTrialExternalUser.TrialId)) - { - //---系统已经存在与列表中填写的邮箱和用户类型相同的账户,请确认。 - return ResponseOutput.NotOk(_localizer["TrialExternalUser_EmailTypeDuplicate"]); - } + if (await _trialExternalUseRepository.AnyAsync(t => + t.Email == addOrEditTrialExternalUser.Email && + t.UserTypeId == addOrEditTrialExternalUser.UserTypeId && t.TrialId == addOrEditTrialExternalUser.TrialId)) + { + //---系统已经存在与列表中填写的邮箱和用户类型相同的账户,请确认。 + return ResponseOutput.NotOk(_localizer["TrialExternalUser_EmailTypeDuplicate"]); + } - var addEntity = _mapper.Map(addOrEditTrialExternalUser); + var addEntity = _mapper.Map(addOrEditTrialExternalUser); - await _trialExternalUseRepository.AddAsync(addEntity); + await _trialExternalUseRepository.AddAsync(addEntity); - var existUser = await _userRepository.FirstOrDefaultAsync(t => t.EMail == addOrEditTrialExternalUser.Email && t.UserTypeId == addOrEditTrialExternalUser.UserTypeId); - var trialType = await _repository.Where(t => t.Id == addOrEditTrialExternalUser.TrialId).Select(t => t.TrialType).FirstOrDefaultAsync(); + var existUser = await _userRepository.FirstOrDefaultAsync(t => t.EMail == addOrEditTrialExternalUser.Email && t.UserTypeId == addOrEditTrialExternalUser.UserTypeId); + var trialType = await _repository.Where(t => t.Id == addOrEditTrialExternalUser.TrialId).Select(t => t.TrialType).FirstOrDefaultAsync(); - if (existUser != null) - { - addEntity.IsSystemUser = true; - addEntity.SystemUserId = existUser.Id; + if (existUser != null) + { + addEntity.IsSystemUser = true; + addEntity.SystemUserId = existUser.Id; - } - else - { + } + else + { - //生成账户 并插入 + //生成账户 并插入 - var generateUser = _mapper.Map(addOrEditTrialExternalUser); + var generateUser = _mapper.Map(addOrEditTrialExternalUser); + + if (trialType == TrialType.NoneOfficial) + { + generateUser.IsTestUser = true; + } + + // 外部人员生成账号 都是外部的 + generateUser.IsZhiZhun = false; + + generateUser.Code = _userRepository.Select(t => t.Code).DefaultIfEmpty().Max() + 1; + + + generateUser.UserCode = AppSettings.GetCodeStr(generateUser.Code, nameof(User)); + + generateUser.UserName = generateUser.UserCode; + + generateUser.UserTypeEnum = _repository.Where(t => t.Id == generateUser.UserTypeId).Select(t => t.UserTypeEnum).First(); + + generateUser.Password = MD5Helper.Md5("123456"); + + generateUser.Status = UserStateEnum.Disable; + + var newAddUser = await _repository.AddAsync(generateUser); + + + addEntity.IsSystemUser = false; + addEntity.SystemUserId = newAddUser.Id; + + + existUser = newAddUser; + + } + + #region 验证用户 能否加入 + + if (trialType == TrialType.OfficialTrial || trialType == TrialType.Training) + { + + if (existUser.IsTestUser) + { + //---正式类型 、培训类型的项目 不允许加入测试用户 + throw new BusinessValidationFailedException(_localizer["TrialExternalUser_TestUserNotAllowed"]); + + } + } if (trialType == TrialType.NoneOfficial) { - generateUser.IsTestUser = true; + + if (existUser.IsTestUser == false) + { + //---测试项目 不允许加入正式用户 + throw new BusinessValidationFailedException(_localizer["TrialExternalUser_FormalUserNotAllowed"]); + } } - // 外部人员生成账号 都是外部的 - generateUser.IsZhiZhun = false; - - generateUser.Code = _userRepository.Select(t => t.Code).DefaultIfEmpty().Max() + 1; + #endregion - generateUser.UserCode = AppSettings.GetCodeStr(generateUser.Code, nameof(User)); - - generateUser.UserName = generateUser.UserCode; - - generateUser.UserTypeEnum = _repository.Where(t => t.Id == generateUser.UserTypeId).Select(t => t.UserTypeEnum).First(); - - generateUser.Password = MD5Helper.Md5("123456"); - - generateUser.Status = UserStateEnum.Disable; - - var newAddUser = await _repository.AddAsync(generateUser); + await _trialExternalUseRepository.SaveChangesAsync(); - addEntity.IsSystemUser = false; - addEntity.SystemUserId = newAddUser.Id; - - - existUser = newAddUser; - - } - - #region 验证用户 能否加入 - - if (trialType == TrialType.OfficialTrial || trialType == TrialType.Training) - { - - if (existUser.IsTestUser) + //添加的时候就发邮件 现在省略 + if (addOrEditTrialExternalUser.IsSendEmail) { - //---正式类型 、培训类型的项目 不允许加入测试用户 - throw new BusinessValidationFailedException(_localizer["TrialExternalUser_TestUserNotAllowed"]); - - } - } - - if (trialType == TrialType.NoneOfficial) - { - - if (existUser.IsTestUser == false ) - { - //---测试项目 不允许加入正式用户 - throw new BusinessValidationFailedException(_localizer["TrialExternalUser_FormalUserNotAllowed"]); - } - } - - #endregion - - - await _trialExternalUseRepository.SaveChangesAsync(); - - - //添加的时候就发邮件 现在省略 - if (addOrEditTrialExternalUser.IsSendEmail) - { - await SendExternalUserJoinEmail(new TrialExternalUserSendEmail() - { - BaseUrl = addOrEditTrialExternalUser.BaseUrl, - RouteUrl = addOrEditTrialExternalUser.RouteUrl, - TrialId = addOrEditTrialExternalUser.TrialId, - SendUsers = new List() + await SendExternalUserJoinEmail(new TrialExternalUserSendEmail() + { + BaseUrl = addOrEditTrialExternalUser.BaseUrl, + RouteUrl = addOrEditTrialExternalUser.RouteUrl, + TrialId = addOrEditTrialExternalUser.TrialId, + SendUsers = new List() { new UserEmail() { @@ -199,12 +206,13 @@ namespace IRaCIS.Core.Application.Service SystemUserId=addEntity.SystemUserId } } - }); + }); + } + + + return ResponseOutput.Ok(addEntity.Id.ToString()); } - - return ResponseOutput.Ok(addEntity.Id.ToString()); - } else { diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialService.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialService.cs index 6fad583bd..b92b011ad 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialService.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialService.cs @@ -25,13 +25,17 @@ namespace IRaCIS.Application.Services private readonly IRepository _trialUserRepository; private readonly IOptionsMonitor _verifyConfig; + private readonly IOptionsMonitor _systemEmailSendConfig; + public bool TrialExpeditedChange { get; set; } = false; public TrialService(IEasyCachingProvider provider, IRepository trialRepository, IRepository trialUserRepository, IOptionsMonitor verifyConfig + , IOptionsMonitor systemEmailSendConfig ) { + _systemEmailSendConfig = systemEmailSendConfig; _verifyConfig = verifyConfig; _provider = provider; _trialRepository = trialRepository; @@ -92,7 +96,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(_mapper.ConfigurationProvider, new { userTypeEnumInt = _userInfo.UserTypeEnumInt, userId = _userInfo.Id }); + .ProjectTo(_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); @@ -118,7 +122,7 @@ namespace IRaCIS.Application.Services [HttpGet("{projectId:guid}")] public async Task GetTrialInfoAndLockState(Guid projectId) { - return (await _trialRepository.Where(o => o.Id == projectId).IgnoreQueryFilters().ProjectTo(_mapper.ConfigurationProvider).FirstOrDefaultAsync()).IfNullThrowException(); + return (await _trialRepository.Where(o => o.Id == projectId).IgnoreQueryFilters().ProjectTo(_mapper.ConfigurationProvider, new {isEn_Us = _userInfo.IsEn_Us }).FirstOrDefaultAsync()).IfNullThrowException(); } @@ -213,6 +217,15 @@ namespace IRaCIS.Application.Services await _repository.AddAsync(new VisitStage { TrialId = trial.Id, VisitNum = 0, BlindName = "B" + 0.ToString("D3"), VisitDay = 0, VisitName = "Baseline", IsBaseLine = true }); await _repository.AddAsync(new VisitStage { TrialId = trial.Id, VisitNum = 1, BlindName = "B" + 10.ToString("D3"), VisitDay = 30, VisitName = "Visit 1" }); + //默认采用系统邮件 + + trial.EmailAuthorizationCode = _systemEmailSendConfig.CurrentValue.AuthorizationCode; + trial.EmailFromEmail = _systemEmailSendConfig.CurrentValue.FromEmail; + trial.EmailFromName = _systemEmailSendConfig.CurrentValue.FromName; + trial.EmailSMTPServerAddress = _systemEmailSendConfig.CurrentValue.Host; + trial.EmailSMTPServerPort = _systemEmailSendConfig.CurrentValue.Port; + trial.IsConfigureEmail = true; + var success = await _repository.SaveChangesAsync(); @@ -286,8 +299,16 @@ namespace IRaCIS.Application.Services await _repository.BatchDeleteAsync(o => o.SubjectVisit.TrialId == trialId); await _repository.BatchDeleteAsync(o => o.TrialId == trialId); + + await _repository.BatchDeleteAsync(o => o.ClinicalForm.TrialId == trialId); + await _repository.BatchDeleteAsync(o => o.ClinicalForm.TrialId == trialId); + await _repository.BatchDeleteAsync(o => o.TrialId == trialId); + await _repository.BatchDeleteAsync(o => o.TrialId == trialId); await _repository.BatchDeleteAsync(o => o.TrialReadingCriterion.TrialId == trialId); + + await _repository.BatchDeleteAsync(o => o.TrialReadingCriterion.TrialId == trialId); + await _repository.BatchDeleteAsync(o => o.TrialId == trialId); await _repository.BatchDeleteAsync(t => t.TrialId == trialId); await _repository.BatchDeleteAsync(t => t.TrialId == trialId); @@ -374,8 +395,7 @@ namespace IRaCIS.Application.Services await _repository.BatchDeleteAsync(t => t.TrialId == trialId); await _repository.BatchDeleteAsync(t => t.TrialId == trialId); - - + await _repository.BatchDeleteAsync(t => t.TrialId == trialId); diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialSiteService.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialSiteService.cs index 9145bcad1..e3dc9b5c9 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialSiteService.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialSiteService.cs @@ -194,7 +194,7 @@ namespace IRaCIS.Core.Application.Services var siteQueryable = _siteRepository.AsQueryable(true) - .WhereIf(!string.IsNullOrWhiteSpace(searchModel.SiteName), t => t.SiteName.Contains(searchModel.SiteName)) + .WhereIf(!string.IsNullOrWhiteSpace(searchModel.SiteName), t => t.SiteName.Contains(searchModel.SiteName)|| t.SiteNameCN.Contains(searchModel.SiteName)) .WhereIf(!string.IsNullOrWhiteSpace(searchModel.AliasName), t => t.AliasName.Contains(searchModel.AliasName)) .WhereIf(!string.IsNullOrWhiteSpace(searchModel.City), t => t.City.Contains(searchModel.City)) .WhereIf(!string.IsNullOrWhiteSpace(searchModel.Country), t => t.Country.Contains(searchModel.Country)) diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/_MapConfig.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/_MapConfig.cs index c3cbf70e9..c8fde011f 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/_MapConfig.cs @@ -65,16 +65,17 @@ namespace IRaCIS.Core.Application.Service var userId = Guid.Empty; var userTypeEnumInt = 0; + var isEn_Us = false; CreateMap() .ForMember(x=>x.CriterionList,y=>y.MapFrom(z=>z.ReadingQuestionCriterionTrialList.Where(n=>n.IsConfirm).Select(m=>m.CriterionName))) .ForMember(d => d.DictionaryList, u => u.MapFrom(s => s.TrialDicList.Select(t => t.Dictionary).OrderBy(t => t.ShowOrder))) //.ForMember(d => d.Code, u => u.MapFrom(s => s.TrialCode)) .ForMember(d => d.Sponsor, u => u.MapFrom(s => s.Sponsor.SponsorName)) - .ForMember(d => d.Phase, u => u.MapFrom(s => s.Phase.MappedValue)) + .ForMember(d => d.Phase, u => u.MapFrom(s => isEn_Us? s.Phase.Value: s.Phase.ValueCN)) //.ForMember(d => d.DeclarationType, u => u.MapFrom(s => s.DeclarationType.MappedValue)) - .ForMember(d => d.IndicationType, u => u.MapFrom(s => s.IndicationType.MappedValue)) + .ForMember(d => d.IndicationType, u => u.MapFrom(s => isEn_Us ? s.IndicationType.Value:s.IndicationType.ValueCN)) .ForMember(d => d.CRO, u => u.MapFrom(s => s.CRO.CROName)) - .ForMember(d => d.ReviewMode, u => u.MapFrom(s => s.ReviewMode.MappedValue)) + .ForMember(d => d.ReviewMode, u => u.MapFrom(s => isEn_Us ? s.ReviewMode.Value:s.ReviewMode.ValueCN)) //.ForMember(d => d.ReviewType, u => u.MapFrom(s => s.ReviewType.Value)) //.ForMember(d => d.SiteCount, u => u.MapFrom(s => userTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator ? s.TrialSiteUserList.Count(k => k.UserId == userId) : s.TrialSiteList.Count())) @@ -106,12 +107,10 @@ namespace IRaCIS.Core.Application.Service .ForMember(d => d.TrialId, u => u.MapFrom(s => trialId)) .ForMember(d => d.IsSelect, u => u.MapFrom(t => t.UserTrials.Any(t => t.TrialId == trialId))); - CreateMap() .ForMember(d => d.HospitalName, u => u.MapFrom(s => s.Hospital.HospitalName)); //trial site 选择列表 subjectVisit pannel 模式添加的时候 - var isEn_Us = false; CreateMap() .ForMember(d => d.IsSelect, u => u.MapFrom(s => s.TrialSiteList.Any(k => k.TrialId == trialId))) diff --git a/IRaCIS.Core.Application/TestService.cs b/IRaCIS.Core.Application/TestService.cs index aea881b0c..6de525061 100644 --- a/IRaCIS.Core.Application/TestService.cs +++ b/IRaCIS.Core.Application/TestService.cs @@ -1,15 +1,19 @@ -using IRaCIS.Core.Application.Service; +using DocumentFormat.OpenXml.Office2010.Excel; +using IRaCIS.Core.Application.Service; using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Infrastructure; using MassTransit; +using Medallion.Threading; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Caching.Distributed; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using MiniExcelLibs; using System.Linq.Expressions; +using System.Reflection.Metadata; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; @@ -20,6 +24,8 @@ namespace IRaCIS.Application.Services [ApiExplorerSettings(GroupName = "Institution")] public class TestService : BaseService { + + public static int IntValue = 100; private readonly IRepository _dicRepository; private readonly IRepository _trialRepository; @@ -30,10 +36,13 @@ namespace IRaCIS.Application.Services private readonly IOptionsMonitor _basicConfig; private readonly IRepository _visitTaskRepositoryy; + private readonly IDistributedLockProvider _distributedLockProvider; - public TestService(IRepository dicRepository, IRepository trialRepository/*, IDistributedCache cache*/ + private readonly ILogger _logger; - , IOptionsMonitor systemEmailConfig, IOptionsMonitor basicConfig, IRepository visitTaskRepository) + public TestService(IRepository dicRepository, IRepository trialRepository,ILogger logger + + , IOptionsMonitor systemEmailConfig, IOptionsMonitor basicConfig, IRepository visitTaskRepository, IDistributedLockProvider distributedLockProvider) { _visitTaskRepositoryy = visitTaskRepository; @@ -42,10 +51,39 @@ namespace IRaCIS.Application.Services _dicRepository = dicRepository; _trialRepository = trialRepository; + + _distributedLockProvider= distributedLockProvider; + + _logger= logger; //_cache = cache; } + + [AllowAnonymous] + public async Task TestDistributedLock( ) + { + + _repository.Where().Select(t => t.FullName).FirstOrDefault(); + + Console.WriteLine($"我进来了当前值是:" + IntValue); + _logger.LogWarning($"我进来了当前值是:" + IntValue); + + var @lock = _distributedLockProvider.CreateLock($"UserAccount"); + + using (await @lock.AcquireAsync()) + { + await Task.Delay(4); + IntValue--; + + _logger.LogWarning( IntValue.ToString()); + Console.WriteLine(IntValue); + } + + return ResponseOutput.Ok(IntValue); + } + + [AllowAnonymous] public async Task GetMemoryStoreData() { diff --git a/IRaCIS.Core.Application/Triggers/VisitTaskIsFrontTaskNeedSignButNotSignTrigger.cs b/IRaCIS.Core.Application/Triggers/VisitTaskIsFrontTaskNeedSignButNotSignTrigger.cs index 86fb420db..f72acc924 100644 --- a/IRaCIS.Core.Application/Triggers/VisitTaskIsFrontTaskNeedSignButNotSignTrigger.cs +++ b/IRaCIS.Core.Application/Triggers/VisitTaskIsFrontTaskNeedSignButNotSignTrigger.cs @@ -22,14 +22,13 @@ namespace IRaCIS.Core.Application.Triggers private readonly IRepository _readingTaskQuestionAnswerRepository; - private readonly IRepository _subjectAdditionalEvaluationResultRepository; public VisitTaskIsFrontTaskNeedSignButNotSignTrigger( IRepository visitTaskRepository, IRepository trialReadingCriterionRepository, IRepository trialReadingQuestionRepository - , IRepository readingTaskQuestionAnswerRepository, IRepository subjectAdditionalEvaluationResultRepository) + , IRepository readingTaskQuestionAnswerRepository) { _trialReadingCriterionRepository = trialReadingCriterionRepository; @@ -37,7 +36,6 @@ namespace IRaCIS.Core.Application.Triggers _trialReadingQuestionRepository = trialReadingQuestionRepository; _readingTaskQuestionAnswerRepository = readingTaskQuestionAnswerRepository; - _subjectAdditionalEvaluationResultRepository = subjectAdditionalEvaluationResultRepository; } diff --git a/IRaCIS.Core.Domain.Share/IRaCIS.Core.Domain.Share.csproj b/IRaCIS.Core.Domain.Share/IRaCIS.Core.Domain.Share.csproj index 85a1db3cc..1c168175c 100644 --- a/IRaCIS.Core.Domain.Share/IRaCIS.Core.Domain.Share.csproj +++ b/IRaCIS.Core.Domain.Share/IRaCIS.Core.Domain.Share.csproj @@ -8,8 +8,4 @@ ..\bin - - - - diff --git a/IRaCIS.Core.Domain/Allocation/PIAudit.cs b/IRaCIS.Core.Domain/Allocation/PIAudit.cs index e4f83d6dd..f2afa8db4 100644 --- a/IRaCIS.Core.Domain/Allocation/PIAudit.cs +++ b/IRaCIS.Core.Domain/Allocation/PIAudit.cs @@ -35,6 +35,8 @@ namespace IRaCIS.Core.Domain.Models public string NotAgreeReason { get; set; } = string.Empty; + public PIAuditState? PIAuditState { get; set; } + public string PIAuditImagePath { get; set; } = string.Empty; diff --git a/IRaCIS.Core.Domain/Allocation/TaskMedicalReview.cs b/IRaCIS.Core.Domain/Allocation/TaskMedicalReview.cs index 7c77ea807..901e4c984 100644 --- a/IRaCIS.Core.Domain/Allocation/TaskMedicalReview.cs +++ b/IRaCIS.Core.Domain/Allocation/TaskMedicalReview.cs @@ -178,7 +178,7 @@ namespace IRaCIS.Core.Domain.Models /// 文件 /// [NotMapped] - public List FileList + public List FileList { get { @@ -186,13 +186,13 @@ namespace IRaCIS.Core.Domain.Models try { - var result= JsonConvert.DeserializeObject>(this.ImagePath); - return result==null?new List() : result; + var result= JsonConvert.DeserializeObject>(this.ImagePath); + return result==null?new List() : result; } catch (Exception) { - return new List(); + return new List(); } } @@ -210,7 +210,7 @@ namespace IRaCIS.Core.Domain.Models #region 文件对象 - public class ImageInfo + public class OSSImageInfo { public string FileName { get; set; } diff --git a/IRaCIS.Core.Domain/Common/Dictionary.cs b/IRaCIS.Core.Domain/Common/Dictionary.cs index 2117bd7cc..c0b4d6b07 100644 --- a/IRaCIS.Core.Domain/Common/Dictionary.cs +++ b/IRaCIS.Core.Domain/Common/Dictionary.cs @@ -1,4 +1,3 @@ -using EntityFrameworkCore.Projectables; using IRaCIS.Core.Domain.Share; using System; using System.Collections.Generic; @@ -56,12 +55,6 @@ namespace IRaCIS.Core.Domain.Models public List ChildList { get; set; } = new List(); - [NotMapped] - public string MappedValue { get; set; } - - - [Projectable] - public string TranslateValue( string value, string valueCN,bool isCN) => isCN?valueCN:value; } diff --git a/IRaCIS.Core.Domain/IRaCIS.Core.Domain.csproj b/IRaCIS.Core.Domain/IRaCIS.Core.Domain.csproj index 1397d105f..1648985a9 100644 --- a/IRaCIS.Core.Domain/IRaCIS.Core.Domain.csproj +++ b/IRaCIS.Core.Domain/IRaCIS.Core.Domain.csproj @@ -1,29 +1,27 @@  - - net6.0 - + + net6.0 + - - ..\bin - + + ..\bin + - - - - - - + + + - - - + + + + + + + + + - - - - - - + diff --git a/IRaCIS.Core.Domain/Management/User.cs b/IRaCIS.Core.Domain/Management/User.cs index 07a572a50..42bf5689b 100644 --- a/IRaCIS.Core.Domain/Management/User.cs +++ b/IRaCIS.Core.Domain/Management/User.cs @@ -87,7 +87,8 @@ namespace IRaCIS.Core.Domain.Models /// public bool AutoCutNextTask { get; set; } = false; - [Projectable] public string FullName => LastName + " / " + FirstName; + [Projectable] + public string FullName => LastName + " / " + FirstName; //[Projectable] public string FullName => $"{LastName} / {FirstName}"; } diff --git a/IRaCIS.Core.Domain/Reading/AdditionalEvaluate/SubjectAdditionalEvaluationResult.cs b/IRaCIS.Core.Domain/Reading/AdditionalEvaluate/SubjectAdditionalEvaluationResult.cs deleted file mode 100644 index bb5b63628..000000000 --- a/IRaCIS.Core.Domain/Reading/AdditionalEvaluate/SubjectAdditionalEvaluationResult.cs +++ /dev/null @@ -1,79 +0,0 @@ - -//-------------------------------------------------------------------- -// 此代码由T4模板自动生成 byzhouhang 20210918 -// 生成时间 2023-03-17 11:50:31 -// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 -using System; -using IRaCIS.Core.Domain.Share; -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; -namespace IRaCIS.Core.Domain.Models -{ - /// - ///SubjectAdditionalEvaluationResult - /// - [Table("SubjectAdditionalEvaluationResult")] - public class SubjectAdditionalEvaluationResult : Entity, IAuditUpdate, IAuditAdd - { - - - [JsonIgnore] - [ForeignKey("TrialReadingQuestionId")] - public ReadingQuestionTrial TrialReadingQuestion { get; set; } - - - public Guid TrialReadingQuestionId { get; set; } - - - - - public Guid SubjectId { get; set; } - - - public Guid TrialReadingCriterionId { get; set; } - - - public DateTime CreateTime { get; set; } - - - public Guid CreateUserId { get; set; } - - - public Guid UpdateUserId { get; set; } - - - public DateTime UpdateTime { get; set; } - - - public Guid? VisitTaskId { get; set; } - - - public string Answer { get; set; } - - /// - /// 附加评估答案翻译字典 - /// - [Required] - public string TranslateDictionaryCode { get; set; }=string.Empty; - - /// - /// 是否是最终结果 - /// - [Required] - public bool IsFinalResult { get; set; } - - /// - /// 最终结果 - /// - [Required] - public string FinalAnswer { get; set; } - - /// - /// 最终结果翻字典 - /// - [Required] - public string FinalTranslateDictionaryCode { get; set; } - - } - -} diff --git a/IRaCIS.Core.Domain/Reading/MedicalAudit/ReadingMedicalReviewDialog.cs b/IRaCIS.Core.Domain/Reading/MedicalAudit/ReadingMedicalReviewDialog.cs index c3f46259f..e00db79c7 100644 --- a/IRaCIS.Core.Domain/Reading/MedicalAudit/ReadingMedicalReviewDialog.cs +++ b/IRaCIS.Core.Domain/Reading/MedicalAudit/ReadingMedicalReviewDialog.cs @@ -113,7 +113,7 @@ namespace IRaCIS.Core.Domain.Models /// 文件 /// [NotMapped] - public List FileList + public List FileList { get { @@ -121,13 +121,13 @@ namespace IRaCIS.Core.Domain.Models try { - var result = JsonConvert.DeserializeObject>(this.ImagePath); - return result == null ? new List() : result; + var result = JsonConvert.DeserializeObject>(this.ImagePath); + return result == null ? new List() : result; } catch (Exception) { - return new List(); + return new List(); } } diff --git a/IRaCIS.Core.Domain/Reading/ReadingCriterion/CriterionNidusTrial.cs b/IRaCIS.Core.Domain/Reading/ReadingCriterion/CriterionNidusTrial.cs index 7ead42443..37f656f98 100644 --- a/IRaCIS.Core.Domain/Reading/ReadingCriterion/CriterionNidusTrial.cs +++ b/IRaCIS.Core.Domain/Reading/ReadingCriterion/CriterionNidusTrial.cs @@ -15,11 +15,14 @@ namespace IRaCIS.Core.Domain.Models [Table("CriterionNidusTrial")] public class CriterionNidusTrial : Entity, IAuditAdd { - - /// + [JsonIgnore] + [ForeignKey("CriterionId")] + public ReadingQuestionCriterionTrial TrialReadingCriterion { get; set; } + + /// /// CriterionId /// - [Required] + [Required] public Guid CriterionId { get; set; } /// diff --git a/IRaCIS.Core.Domain/Reading/ReadingCriterion/ReadingQuestionCriterionTrial.cs b/IRaCIS.Core.Domain/Reading/ReadingCriterion/ReadingQuestionCriterionTrial.cs index cda0d91d1..36163fa6b 100644 --- a/IRaCIS.Core.Domain/Reading/ReadingCriterion/ReadingQuestionCriterionTrial.cs +++ b/IRaCIS.Core.Domain/Reading/ReadingCriterion/ReadingQuestionCriterionTrial.cs @@ -264,9 +264,7 @@ namespace IRaCIS.Core.Domain.Models public List ReadingQuestionTrialList = new List(); - [JsonIgnore] - public List TrialCriterionAdditionalAssessmentTypeList { get; set; } = new List(); [JsonIgnore] diff --git a/IRaCIS.Core.Domain/SQLFile/20230713删除表.sql b/IRaCIS.Core.Domain/SQLFile/20230713删除表.sql index 20de530f0..8b5965d2e 100644 --- a/IRaCIS.Core.Domain/SQLFile/20230713删除表.sql +++ b/IRaCIS.Core.Domain/SQLFile/20230713删除表.sql @@ -1,6 +1,7 @@ --医生相关 DROP TABLE Attachment; DROP TABLE Doctor; +DROP TABLE DoctorPayInformation DROP TABLE Postgraduate; DROP TABLE Education; DROP TABLE ResearchPublication; @@ -9,6 +10,8 @@ DROP TABLE Vacation; DROP TABLE DoctorCriterionFile; DROP TABLE DoctorDictionary; +DROP TABLE TrialExperienceCriteria + --费用相关 @@ -22,6 +25,10 @@ DROP TABLE TrialRevenuesPrice; DROP TABLE TrialRevenuesPriceVerification; DROP TABLE VolumeReward; +--new +DROP TABLE Payment +DROP TABLE PaymentDetail + --工作量 DROP TABLE [Workload]; @@ -48,6 +55,11 @@ DROP TABLE SubjectCriteriaEvaluation; DROP TABLE SubjectCriteriaEvaluationVisitFilter; DROP TABLE SubjectCriteriaEvaluationVisitStudyFilter; +--new +DROP TABLE SubjectAdditionalEvaluationResult +DROP TABLE TrialCriterionAdditionalAssessmentType + + diff --git a/IRaCIS.Core.Domain/Visit/Subject.cs b/IRaCIS.Core.Domain/Visit/Subject.cs index 9b1d0c066..dcece25c9 100644 --- a/IRaCIS.Core.Domain/Visit/Subject.cs +++ b/IRaCIS.Core.Domain/Visit/Subject.cs @@ -26,11 +26,6 @@ namespace IRaCIS.Core.Domain.Models - [JsonIgnore] - - public List SubjectAdditionalEvaluationResult { get; set; } - - [JsonIgnore] public List ReadingTaskQuestionAnswerList { get; set; } diff --git a/IRaCIS.Core.Domain.Share/AuthUser/IUserInfo.cs b/IRaCIS.Core.Infra.EFCore/AuthUser/IUserInfo.cs similarity index 100% rename from IRaCIS.Core.Domain.Share/AuthUser/IUserInfo.cs rename to IRaCIS.Core.Infra.EFCore/AuthUser/IUserInfo.cs diff --git a/IRaCIS.Core.Domain.Share/AuthUser/UserInfo.cs b/IRaCIS.Core.Infra.EFCore/AuthUser/UserInfo.cs similarity index 90% rename from IRaCIS.Core.Domain.Share/AuthUser/UserInfo.cs rename to IRaCIS.Core.Infra.EFCore/AuthUser/UserInfo.cs index 890033cda..eddead0fd 100644 --- a/IRaCIS.Core.Domain.Share/AuthUser/UserInfo.cs +++ b/IRaCIS.Core.Infra.EFCore/AuthUser/UserInfo.cs @@ -212,7 +212,7 @@ namespace IRaCIS.Core.Domain.Share get { - return _accessor?.HttpContext?.Connection.RemoteIpAddress.ToString(); + return _accessor?.HttpContext.GetClientIP(); } } @@ -341,4 +341,33 @@ namespace IRaCIS.Core.Domain.Share } + + public static class HttpContextExtension + { + public static string GetClientIP(this HttpContext context) + { + var ip = context.Request.Headers["Cdn-Src-Ip"].FirstOrDefault(); + if (!string.IsNullOrEmpty(ip)) + return IpReplace(ip); + + ip = context.Request.Headers["X-Forwarded-For"].FirstOrDefault(); + if (!string.IsNullOrEmpty(ip)) + return IpReplace(ip); + + ip = context.Connection.RemoteIpAddress.ToString(); + + return IpReplace(ip); + } + + static string IpReplace(string inip) + { + //::ffff: + //::ffff:192.168.2.131 这种IP处理 + if (inip.Contains("::ffff:")) + { + inip = inip.Replace("::ffff:", ""); + } + return inip; + } + } } diff --git a/IRaCIS.Core.Infra.EFCore/Common/AuditingData.cs b/IRaCIS.Core.Infra.EFCore/Common/AuditingData.cs index ae3bc93d8..eff31d601 100644 --- a/IRaCIS.Core.Infra.EFCore/Common/AuditingData.cs +++ b/IRaCIS.Core.Infra.EFCore/Common/AuditingData.cs @@ -249,10 +249,6 @@ namespace IRaCIS.Core.Infra.EFCore.Common dicValueList = await _dbContext.Dictionary.Where(t => dicIdList.Contains(t.Id)).Select(t => t.Value).ToListAsync(); } - // 附加评估 - - var addtionalAssesementList = await _dbContext.TrialCriterionAdditionalAssessmentType.Where(t => t.TrialReadingCriterionId == entity.Id && t.IsSelected != null) - .Select(t => new { t.AdditionalAssessmentType, t.IsSelected }).ToListAsync(); await InsertInspection(entity, type, x => new InspectionConvertDTO() @@ -268,7 +264,7 @@ namespace IRaCIS.Core.Infra.EFCore.Common }, new { EvaluationResultTypes = dicValueList.Count > 0 ? string.Join(",", dicValueList) : string.Empty, - AdditionalAssessmentTypeList = addtionalAssesementList + }); } diff --git a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs index fd26a923c..bf54cfa5a 100644 --- a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs +++ b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs @@ -122,14 +122,15 @@ namespace IRaCIS.Core.Infra.EFCore modelBuilder.Entity().HasMany(t => t.ChildList).WithOne(t => t.Parent); - if (_userInfo.IsEn_Us) - { - modelBuilder.Entity().Property(t => t.MappedValue).HasColumnName(nameof(Domain.Models.Dictionary.Value)); - } - else - { - modelBuilder.Entity().Property(t => t.MappedValue).HasColumnName(nameof(Domain.Models.Dictionary.ValueCN)); - } + + //if (_userInfo.IsEn_Us) + //{ + // modelBuilder.Entity().Property(t => t.MappedValue).HasColumnName(nameof(Domain.Models.Dictionary.Value)); + //} + //else + //{ + // modelBuilder.Entity().Property(t => t.MappedValue).HasColumnName(nameof(Domain.Models.Dictionary.ValueCN)); + //} //遍历实体模型手动配置 @@ -260,10 +261,8 @@ namespace IRaCIS.Core.Infra.EFCore public virtual DbSet TrialClinicalDataSetCriterion { get; set; } - public virtual DbSet TrialCriterionAdditionalAssessmentType { get; set; } - public virtual DbSet SubjectAdditionalEvaluationResult { get; set; } @@ -513,54 +512,60 @@ namespace IRaCIS.Core.Infra.EFCore } catch (UniqueConstraintException ex) { - _logger.LogError(ex.Message); + _logger.LogError(ex.InnerException is null? ex.Message :ex.InnerException?.Message); throw new DBSaveFailedException("该唯一键已经存在于数据库中。"); } catch (TimeoutException ex) { - _logger.LogError(ex.Message); + _logger.LogError(ex.InnerException is null ? ex.Message : ex.InnerException?.Message); throw new DBSaveFailedException("数据库操作已经超时,请稍后重试。"); } catch (CannotInsertNullException ex) { - _logger.LogError(ex.Message); + _logger.LogError(ex.InnerException is null ? ex.Message : ex.InnerException?.Message); throw new DBSaveFailedException("无法在非空列上插入空值。"); } catch (MaxLengthExceededException ex) { - _logger.LogError(ex.Message); + _logger.LogError(ex.InnerException is null ? ex.Message : ex.InnerException?.Message); throw new DBSaveFailedException("字符串超过了数据库列的最大长度。"); } catch (NumericOverflowException ex) { - _logger.LogError(ex.Message); - + _logger.LogError(ex.InnerException is null ? ex.Message : ex.InnerException?.Message); throw new DBSaveFailedException("数值超过了数据类型的范围。"); } catch (SyntaxErrorException ex) { - _logger.LogError(ex.Message); + _logger.LogError(ex.InnerException is null ? ex.Message : ex.InnerException?.Message); throw new DBSaveFailedException("SQL 查询中存在语法错误。"); } catch (ReferenceConstraintException ex) { - _logger.LogError(ex.Message); + _logger.LogError(ex.InnerException is null ? ex.Message : ex.InnerException?.Message); throw new DBSaveFailedException("无法进行当前操作,当前数据不符合外键约束。"); } catch (DbUpdateConcurrencyException ex) { - _logger.LogError(ex.Message); + _logger.LogError(ex.InnerException is null ? ex.Message : ex.InnerException?.Message); throw new DBSaveFailedException("SQL 事务失败,请检查环境。"); } + catch (Exception ex) + { + _logger.LogError(ex.InnerException is null ? ex.Message : ex.InnerException?.Message); + + throw new DBSaveFailedException("数据保存异常。"); + } } + public async Task AddAudit() diff --git a/IRaCIS.Core.Infra.EFCore/EntityConfigration/StudyConfigration.cs b/IRaCIS.Core.Infra.EFCore/EntityConfigration/StudyConfigration.cs index 7caa43966..de9adcb08 100644 --- a/IRaCIS.Core.Infra.EFCore/EntityConfigration/StudyConfigration.cs +++ b/IRaCIS.Core.Infra.EFCore/EntityConfigration/StudyConfigration.cs @@ -36,8 +36,7 @@ namespace IRaCIS.Core.Infra.EFCore.EntityConfigration public void Configure(EntityTypeBuilder builder) { - builder.Property(e => e.MappedValue).Metadata.SetBeforeSaveBehavior(PropertySaveBehavior.Ignore); - builder.Property(e => e.MappedValue).Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Ignore); + } } diff --git a/IRaCIS.Core.Infra.EFCore/IRaCIS.Core.Infra.EFCore.csproj b/IRaCIS.Core.Infra.EFCore/IRaCIS.Core.Infra.EFCore.csproj index 4baefc5d5..b58b2ac05 100644 --- a/IRaCIS.Core.Infra.EFCore/IRaCIS.Core.Infra.EFCore.csproj +++ b/IRaCIS.Core.Infra.EFCore/IRaCIS.Core.Infra.EFCore.csproj @@ -8,7 +8,9 @@ ..\bin - + + + @@ -17,15 +19,13 @@ - - - - - - - - - + + + + + + + diff --git a/IRaCIS.Core.Infrastructure/Cache/CacheType.cs b/IRaCIS.Core.Infrastructure/Cache/CacheType.cs deleted file mode 100644 index 5f64f0cc8..000000000 --- a/IRaCIS.Core.Infrastructure/Cache/CacheType.cs +++ /dev/null @@ -1,18 +0,0 @@ - -namespace IRaCIS.Core.Infra.Common.Cache -{ - /// - /// 缓存类型 - /// - public enum CacheType - { - /// - /// 内存缓存 - /// - Memory, - /// - /// Redis缓存 - /// - Redis - } -} diff --git a/IRaCIS.Core.Infrastructure/Cache/ICache.cs b/IRaCIS.Core.Infrastructure/Cache/ICache.cs deleted file mode 100644 index defd2dd98..000000000 --- a/IRaCIS.Core.Infrastructure/Cache/ICache.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System; -using System.Threading.Tasks; - -namespace IRaCIS.Core.Infra.Common.Cache -{ - /// - /// 缓存接口 - /// - public interface ICache - { - /// - /// 用于在 key 存在时删除 key - /// - /// 键 - long Del(params string[] key); - - /// - /// 用于在 key 存在时删除 key - /// - /// 键 - /// - Task DelAsync(params string[] key); - - /// - /// 用于在 key 模板存在时删除 - /// - /// key模板 - /// - Task DelByPatternAsync(string pattern); - - /// - /// 检查给定 key 是否存在 - /// - /// 键 - /// - bool Exists(string key); - - /// - /// 检查给定 key 是否存在 - /// - /// 键 - /// - Task ExistsAsync(string key); - - /// - /// 获取指定 key 的值 - /// - /// 键 - /// - string Get(string key); - - /// - /// 获取指定 key 的值 - /// - /// byte[] 或其他类型 - /// 键 - /// - T Get(string key); - - /// - /// 获取指定 key 的值 - /// - /// 键 - /// - Task GetAsync(string key); - - /// - /// 获取指定 key 的值 - /// - /// byte[] 或其他类型 - /// 键 - /// - Task GetAsync(string key); - - /// - /// 设置指定 key 的值,所有写入参数object都支持string | byte[] | 数值 | 对象 - /// - /// 键 - /// 值 - bool Set(string key, object value); - - /// - /// 设置指定 key 的值,所有写入参数object都支持string | byte[] | 数值 | 对象 - /// - /// 键 - /// 值 - /// 有效期 - bool Set(string key, object value, TimeSpan expire); - - /// - /// 设置指定 key 的值,所有写入参数object都支持string | byte[] | 数值 | 对象 - /// - /// 键 - /// 值 - /// - Task SetAsync(string key, object value); - - /// - /// 设置指定 key 的值,所有写入参数object都支持string | byte[] | 数值 | 对象 - /// - /// 键 - /// 值 - /// 有效期 - /// - Task SetAsync(string key, object value, TimeSpan expire); - } -} diff --git a/IRaCIS.Core.Infrastructure/Cache/MemoryCache.cs b/IRaCIS.Core.Infrastructure/Cache/MemoryCache.cs deleted file mode 100644 index 16ffd5760..000000000 --- a/IRaCIS.Core.Infrastructure/Cache/MemoryCache.cs +++ /dev/null @@ -1,127 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using Microsoft.Extensions.Caching.Memory; - -namespace IRaCIS.Core.Infra.Common.Cache -{ - /// - /// 内存缓存 - /// - public class MemoryCache : ICache - { - private readonly IMemoryCache _memoryCache; - public MemoryCache(IMemoryCache memoryCache) - { - _memoryCache = memoryCache; - } - - public long Del(params string[] key) - { - foreach(var k in key) - { - _memoryCache.Remove(k); - } - return key.Length; - } - - public Task DelAsync(params string[] key) - { - foreach (var k in key) - { - _memoryCache.Remove(k); - } - - return Task.FromResult((long)key.Length); - } - - public async Task DelByPatternAsync(string pattern) - { - if (string.IsNullOrEmpty(pattern)) - return default; - - pattern = Regex.Replace(pattern, @"\{.*\}", "(.*)"); - - var keys = GetAllKeys().Where(k => Regex.IsMatch(k, pattern)); - - if(keys != null && keys.Count() > 0) - { - return await DelAsync(keys.ToArray()); - } - - return default; - } - - public bool Exists(string key) - { - return _memoryCache.TryGetValue(key, out _); - } - - public Task ExistsAsync(string key) - { - return Task.FromResult(_memoryCache.TryGetValue(key, out _)); - } - - public string Get(string key) - { - return _memoryCache.Get(key)?.ToString(); - } - - public T Get(string key) - { - return _memoryCache.Get(key); - } - - public Task GetAsync(string key) - { - return Task.FromResult(Get(key)); - } - - public Task GetAsync(string key) - { - return Task.FromResult(Get(key)); - } - - public bool Set(string key, object value) - { - _memoryCache.Set(key, value); - return true; - } - - public bool Set(string key, object value, TimeSpan expire) - { - _memoryCache.Set(key, value, expire); - return true; - } - - public Task SetAsync(string key, object value) - { - Set(key, value); - return Task.FromResult(true); - } - - public Task SetAsync(string key, object value, TimeSpan expire) - { - Set(key, value, expire); - return Task.FromResult(true); - } - - private List GetAllKeys() - { - const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic; - var entries = _memoryCache.GetType().GetField("_entries", flags).GetValue(_memoryCache); - var cacheItems = entries as IDictionary; - var keys = new List(); - if (cacheItems == null) return keys; - foreach (DictionaryEntry cacheItem in cacheItems) - { - keys.Add(cacheItem.Key.ToString()); - } - return keys; - } - } -} diff --git a/IRaCIS.Core.Infrastructure/Cache/RedisCache.cs b/IRaCIS.Core.Infrastructure/Cache/RedisCache.cs deleted file mode 100644 index 1c540178f..000000000 --- a/IRaCIS.Core.Infrastructure/Cache/RedisCache.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System; -using System.Text.RegularExpressions; -using System.Threading.Tasks; - -namespace IRaCIS.Core.Infra.Common.Cache -{ - /// - /// Redis缓存 - /// - public class RedisCache : ICache - { - public long Del(params string[] key) - { - return RedisHelper.Del(key); - } - - public Task DelAsync(params string[] key) - { - return RedisHelper.DelAsync(key); - } - - public async Task DelByPatternAsync(string pattern) - { - if (string.IsNullOrEmpty(pattern)) - return default; - - pattern = Regex.Replace(pattern, @"\{.*\}", "*"); - - var keys = (await RedisHelper.KeysAsync(pattern)); - if(keys != null && keys.Length > 0) - { - return await RedisHelper.DelAsync(keys); - } - - return default; - } - - public bool Exists(string key) - { - return RedisHelper.Exists(key); - } - - public Task ExistsAsync(string key) - { - return RedisHelper.ExistsAsync(key); - } - - public string Get(string key) - { - return RedisHelper.Get(key); - } - - public T Get(string key) - { - return RedisHelper.Get(key); - } - - public Task GetAsync(string key) - { - return RedisHelper.GetAsync(key); - } - - public Task GetAsync(string key) - { - return RedisHelper.GetAsync(key); - } - - public bool Set(string key, object value) - { - return RedisHelper.Set(key, value); - } - - public bool Set(string key, object value, TimeSpan expire) - { - return RedisHelper.Set(key, value, expire); - } - - public Task SetAsync(string key, object value) - { - return RedisHelper.SetAsync(key, value); - } - - public Task SetAsync(string key, object value, TimeSpan expire) - { - return RedisHelper.SetAsync(key, value, expire); - } - } -} diff --git a/IRaCIS.Core.Infrastructure/Extention/RequestExtension.cs b/IRaCIS.Core.Infrastructure/Extention/RequestExtension.cs deleted file mode 100644 index 1aecdeb67..000000000 --- a/IRaCIS.Core.Infrastructure/Extention/RequestExtension.cs +++ /dev/null @@ -1,158 +0,0 @@ -using Microsoft.AspNetCore.Http; -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; - -namespace IRaCIS.Core.Infrastructure.Extention -{ - public static class HttpContextExtension - { - - public static T GetService(this HttpContext context) where T : class - { - return context.RequestServices.GetService(typeof(T)) as T; - } - - - public static string GetUserIp(this HttpContext context) - { - string realIP = null; - string forwarded = null; - string remoteIpAddress = context.Connection.RemoteIpAddress.ToString(); - if (context.Request.Headers.ContainsKey("X-Real-IP")) - { - realIP = context.Request.Headers["X-Real-IP"].ToString(); - if (realIP != remoteIpAddress) - { - remoteIpAddress = realIP; - } - } - if (context.Request.Headers.ContainsKey("X-Forwarded-For")) - { - forwarded = context.Request.Headers["X-Forwarded-For"].ToString(); - if (forwarded != remoteIpAddress) - { - remoteIpAddress = forwarded; - } - } - return remoteIpAddress; - } - - - - /// - /// 获取Request值 - /// - /// - /// - /// - public static string Request(this HttpContext context, string parameter) - { - try - { - if (context == null) - return null; - if (context.Request.Method == "POST") - return context.Request.Form[parameter].ToString(); - else - return context.Request.Query[parameter].ToString(); - } - catch (System.Exception ex) - { - Console.Write(ex.Message + ex.InnerException); - return context.RequestString(parameter); - } - } - - public static T Request(this HttpContext context, string parameter) where T : class - { - return context.RequestString(parameter)?.DeserializeObject(); - } - public static string RequestString(this HttpContext context, string parameter) - { - string requestParam = context.GetRequestParameters(); - if (string.IsNullOrEmpty(requestParam)) return null; - Dictionary keyValues = requestParam.DeserializeObject>(); - if (keyValues == null || keyValues.Count == 0) return null; - if (keyValues.TryGetValue(parameter, out object value)) - { - if (value == null) return null; - if (value.GetType() == typeof(string)) - { - return value?.ToString(); - } - return value.Serialize(); - } - return null; - } - /// - /// 是否为ajax请求 - /// - /// - /// - public static bool IsAjaxRequest(this HttpContext context) - { - return context.Request("X-Requested-With") == "XMLHttpRequest" - || (context.Request.Headers != null - && context.Request.Headers["X-Requested-With"] == "XMLHttpRequest"); - } - - public static UserAgent GetAgentType(this HttpContext context) - { - string agent = context.Request.Headers["User-Agent"].ToString().ToLower(); - - if (agent.Contains("ios") || agent.Contains("ipod") || agent.Contains("ipad")) - { - return UserAgent.IOS; - } - if (agent.Contains("windows")) - { - return UserAgent.Windows; - } - return UserAgent.Android; - - } - - /// - /// 获取请求的参数 - /// net core 2.0已增加回读方法 context.Request.EnableRewind(); - /// - /// - /// - /// - - public static string GetRequestParameters(this HttpContext context) - { - if (context.Request.Body == null || !context.Request.Body.CanRead || !context.Request.Body.CanSeek) - return null; - if (context.Request.Body.Length == 0) - return null; - if (context.Request.Body.Position > 0) - context.Request.Body.Position = 0; - - string prarameters = null; - var bodyStream = context.Request.Body; - - using (var buffer = new MemoryStream()) - { - bodyStream.CopyToAsync(buffer); - buffer.Position = 0L; - bodyStream.Position = 0L; - using (var reader = new StreamReader(buffer, Encoding.UTF8)) - { - buffer.Seek(0, SeekOrigin.Begin); - prarameters = reader.ReadToEnd(); - } - } - return prarameters; - } - } - public enum UserAgent - { - IOS = 0, - Android = 1, - Windows = 2, - Linux - } -} diff --git a/IRaCIS.Core.Infrastructure/Helper/IPHelper.cs b/IRaCIS.Core.Infrastructure/Helper/IPHelper.cs deleted file mode 100644 index c8827eab0..000000000 --- a/IRaCIS.Core.Infrastructure/Helper/IPHelper.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System.Linq; -using System.Text.RegularExpressions; -using Microsoft.AspNetCore.Http; - -namespace IRaCIS.Core.Infrastructure -{ - public class IPHelper - { - /// - /// 是否为ip - /// - /// - /// - public static bool IsIP(string ip) - { - return Regex.IsMatch(ip, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$"); - } - - public static string GetIP(HttpRequest request) - { - if (request == null) - { - return ""; - } - - string ip = request.Headers["X-Real-IP"].FirstOrDefault(); - if (string.IsNullOrEmpty(ip)) - { - ip = request.Headers["X-Forwarded-For"].FirstOrDefault(); - } - if (string.IsNullOrEmpty(ip)) - { - ip = request.HttpContext?.Connection?.RemoteIpAddress?.ToString(); - } - if (string.IsNullOrEmpty(ip) || !IsIP(ip)) - { - ip = "127.0.0.1"; - } - - return ip; - } - } -} \ No newline at end of file diff --git a/IRaCIS.Core.Infrastructure/IRaCIS.Core.Infrastructure.csproj b/IRaCIS.Core.Infrastructure/IRaCIS.Core.Infrastructure.csproj index 7d0a4080a..db54dbbe4 100644 --- a/IRaCIS.Core.Infrastructure/IRaCIS.Core.Infrastructure.csproj +++ b/IRaCIS.Core.Infrastructure/IRaCIS.Core.Infrastructure.csproj @@ -1,27 +1,29 @@  - - net6.0 - + + net6.0 + - - ..\bin - + + ..\bin + - - - - - - - - + + + + + + + + + + - - - + + + diff --git a/IRaCIS.Core.Infrastructure/_IRaCIS/IQueryablePageListExtensions.cs b/IRaCIS.Core.Infrastructure/_IRaCIS/IQueryablePageListExtensions.cs index bb102cd7d..2fa3db58a 100644 --- a/IRaCIS.Core.Infrastructure/_IRaCIS/IQueryablePageListExtensions.cs +++ b/IRaCIS.Core.Infrastructure/_IRaCIS/IQueryablePageListExtensions.cs @@ -3,11 +3,50 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using System.Linq.Dynamic.Core; +using System.Collections.Generic; namespace IRaCIS.Core.Infrastructure.Extention { public static class QueryablePageListExtensions { + //内存排序 后期删除 + public static PageOutput ToPagedList(this IList 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() { CurrentPageData = new List() }; + } + + var propName = string.IsNullOrWhiteSpace(defaultSortFiled) ? "Id" : defaultSortFiled; + + IQueryable 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() + { + PageIndex = pageIndex, + PageSize = pageSize, + TotalCount = count, + CurrentPageData = items + }; + + return pagedList; + } //单字段排序 public static PageOutput ToPagedList(this IQueryable source, int pageIndex, int pageSize, string defaultSortFiled = "Id", bool isAsc = true) { diff --git a/IRaCIS.Core.Test/IRaCIS.Core.Test.csproj b/IRaCIS.Core.Test/IRaCIS.Core.Test.csproj index 16b11378d..ef69f8834 100644 --- a/IRaCIS.Core.Test/IRaCIS.Core.Test.csproj +++ b/IRaCIS.Core.Test/IRaCIS.Core.Test.csproj @@ -13,10 +13,9 @@ - - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/IRaCIS.Core.Test/Test/Audit/AuditContext.cs b/IRaCIS.Core.Test/Test/Audit/AuditContext.cs deleted file mode 100644 index 2fc55e0ea..000000000 --- a/IRaCIS.Core.Test/Test/Audit/AuditContext.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using System.Collections.Generic; -using Microsoft.EntityFrameworkCore; - -#region AuditContext -public class AuditContext : DbContext -{ - private readonly string _connectionString; - - public AuditContext(string connectionString) - { - _connectionString = connectionString; - } - - //protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - // => optionsBuilder.Usesq(_connectionString); - - public DbSet SaveChangesAudits { get; set; } -} - - -public class SaveChangesAudit -{ - public int Id { get; set; } - public Guid AuditId { get; set; } - public DateTime StartTime { get; set; } - public DateTime EndTime { get; set; } - public bool Succeeded { get; set; } - public string ErrorMessage { get; set; } - - public ICollection Entities { get; } = new List(); -} - -public class EntityAudit -{ - public int Id { get; set; } - public EntityState State { get; set; } - public string AuditMessage { get; set; } - - public SaveChangesAudit SaveChangesAudit { get; set; } -} - -#endregion \ No newline at end of file