diff --git a/IRaCIS.Core.API/Controllers/ExtraController.cs b/IRaCIS.Core.API/Controllers/ExtraController.cs index 5685f2b87..1234a2e45 100644 --- a/IRaCIS.Core.API/Controllers/ExtraController.cs +++ b/IRaCIS.Core.API/Controllers/ExtraController.cs @@ -134,7 +134,7 @@ namespace IRaCIS.Api.Controllers return returnModel; } - + [Authorize] [HttpGet("user/GenerateSTS")] public IResponseOutput GenerateSTS( [FromServices] IWebHostEnvironment webHostEnvironment) { diff --git a/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs b/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs index d8028d2b1..0a7430625 100644 --- a/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs +++ b/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs @@ -1083,122 +1083,18 @@ namespace IRaCIS.Core.API.Controllers } - #region 废弃 + /// 通用文件下载 + [AllowAnonymous] + [HttpGet("CommonDocument/DownloadCommonDoc")] + public async Task DownloadCommonFile(string code, [FromServices] IRepository _commonDocumentRepository) + { + var (filePath, fileName) = await FileStoreHelper.GetCommonDocPhysicalFilePathAsync(_hostEnvironment, _commonDocumentRepository, code); - ///// 缩略图 - //[AllowAnonymous] - //[HttpGet("Common/LocalFilePreview")] - //public async Task LocalFilePreview(string relativePath) - //{ - - // var _fileStorePath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, relativePath); - - // var storePreviewPath = _fileStorePath + ".preview.jpeg"; - - // if (!System.IO.File.Exists(storePreviewPath)) - // { - // ImageHelper.ResizeSave(_fileStorePath, storePreviewPath); - // } - - // return new FileContentResult(await System.IO.File.ReadAllBytesAsync(storePreviewPath), "image/jpeg"); - - //} - - - ///// 通用文件下载 - //[AllowAnonymous] - //[HttpGet("CommonDocument/DownloadCommonDoc")] - //public async Task DownloadCommonFile(string code, [FromServices] IRepository _commonDocumentRepository) - //{ - // var (filePath, fileName) = await FileStoreHelper.GetCommonDocPhysicalFilePathAsync(_hostEnvironment, _commonDocumentRepository, code); - - // new FileExtensionContentTypeProvider().Mappings.TryGetValue(Path.GetExtension(filePath), out var contentType); - - // return File(System.IO.File.OpenRead(filePath), contentType ?? "application/octet-stream", fileName); - - //} - - ///// - ///// 下载项目临床数据文件 - ///// - ///// - ///// - ///// - //[AllowAnonymous] - //[HttpGet("CommonDocument/DownloadTrialClinicalFile")] - //public async Task DownloadTrialClinicalFile(Guid clinicalDataTrialSetId, [FromServices] IRepository _clinicalDataTrialSetRepository) - //{ - // var (filePath, fileName) = await FileStoreHelper.GetTrialClinicalPathAsync(_hostEnvironment, _clinicalDataTrialSetRepository, clinicalDataTrialSetId); - - // new FileExtensionContentTypeProvider().Mappings.TryGetValue(Path.GetExtension(filePath), out var contentType); - - // return File(System.IO.File.OpenRead(filePath), contentType ?? "application/octet-stream", fileName); - - //} - - - ///// - ///// 下载系统临床数据文件 - ///// - ///// - ///// - ///// - //[AllowAnonymous] - //[HttpGet("CommonDocument/DownloadSystemClinicalFile")] - //public async Task DownloadSystemClinicalFile(Guid clinicalDataSystemSetId, [FromServices] IRepository _clinicalDataSystemSetRepository) - //{ - // var (filePath, fileName) = await FileStoreHelper.GetSystemClinicalPathAsync(_hostEnvironment, _clinicalDataSystemSetRepository, clinicalDataSystemSetId); - - // new FileExtensionContentTypeProvider().Mappings.TryGetValue(Path.GetExtension(filePath), out var contentType); - - // return File(System.IO.File.OpenRead(filePath), contentType ?? "application/octet-stream", fileName); - - //} - - ///// - /////上传项目签名文档 - ///// - ///// - ///// - //[HttpPost("TrialDocument/UploadTrialDoc/{trialId:guid}")] - //[DisableRequestSizeLimit] - //[DisableFormValueModelBinding] - //public async Task UploadTrialDoc(Guid trialId) - //{ - - // return await SingleFileUploadAsync((fileName) => FileStoreHelper.GetTrialSignDocPath(_hostEnvironment, trialId, fileName)); - - //} - - ///// - ///// 上传系统签名文档 - ///// - ///// - //[HttpPost("TrialDocument/UploadSystemDoc")] - //[DisableRequestSizeLimit] - //[DisableFormValueModelBinding] - //public async Task UploadSysTemDoc() - //{ - - // return await SingleFileUploadAsync((fileName) => FileStoreHelper.GetSystemSignDocPath(_hostEnvironment, fileName)); - - //} - ///// - ///// 上传系统通知文档 - ///// - ///// - //[HttpPost("SystemNotice/UploadSystemNoticeDoc")] - //[DisableRequestSizeLimit] - //[DisableFormValueModelBinding] - //public async Task UploadSystemNoticeDoc() - //{ - - // return await SingleFileUploadAsync((fileName) => FileStoreHelper.GetSystemNoticePath(_hostEnvironment, fileName)); - - //} - #endregion + new FileExtensionContentTypeProvider().Mappings.TryGetValue(Path.GetExtension(filePath), out var contentType); + return File(System.IO.File.OpenRead(filePath), contentType ?? "application/octet-stream", fileName); + } /// /// 上传通用文档 比如一致性核查的 比如导出的excel 模板 diff --git a/IRaCIS.Core.API/IRaCIS.Core.API.csproj b/IRaCIS.Core.API/IRaCIS.Core.API.csproj index a823da33e..d00bf4bd9 100644 --- a/IRaCIS.Core.API/IRaCIS.Core.API.csproj +++ b/IRaCIS.Core.API/IRaCIS.Core.API.csproj @@ -66,28 +66,28 @@ - - + + - - - - + + + + - - - - - - - + + + + + + + - + 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 index b04f38c44..accbb9c34 100644 --- a/IRaCIS.Core.API/appsettings.Prod_Study.json +++ b/IRaCIS.Core.API/appsettings.Prod_Study.json @@ -23,13 +23,13 @@ "BasicSystemConfig": { - "OpenUserComplexPassword": false, + "OpenUserComplexPassword": true, - "OpenSignDocumentBeforeWork": false, + "OpenSignDocumentBeforeWork": true, "OpenTrialRelationDelete": true, - "OpenLoginLimit": false, + "OpenLoginLimit": true, "LoginMaxFailCount": 5, "LoginFailLockMinutes": 30 @@ -40,7 +40,7 @@ "Port": 465, "Host": "smtp.qiye.aliyun.com", "FromEmail": "study@extimaging.com", - "FromName": "study.extimaging", + "FromName": "研究单位阅片系统", "AuthorizationCode": "zhanying123", "SiteUrl": "https://study.extimaging.com/login" } diff --git a/IRaCIS.Core.API/appsettings.json b/IRaCIS.Core.API/appsettings.json index a773c1174..dee559b4c 100644 --- a/IRaCIS.Core.API/appsettings.json +++ b/IRaCIS.Core.API/appsettings.json @@ -57,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.API/resultTemplate b/IRaCIS.Core.API/resultTemplate new file mode 100644 index 000000000..556bbb59a Binary files /dev/null and b/IRaCIS.Core.API/resultTemplate differ diff --git a/IRaCIS.Core.Application/Helper/ExcelExportHelper.cs b/IRaCIS.Core.Application/Helper/ExcelExportHelper.cs index a7ea86977..fd280abf1 100644 --- a/IRaCIS.Core.Application/Helper/ExcelExportHelper.cs +++ b/IRaCIS.Core.Application/Helper/ExcelExportHelper.cs @@ -12,6 +12,7 @@ using MiniExcelLibs; using MiniExcelLibs.OpenXml; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using NPOI.HPSF; using NPOI.HSSF.UserModel; using NPOI.XSSF.UserModel; using SkiaSharp; @@ -145,8 +146,12 @@ public static class ExcelExportHelper workbook.RemoveSheetAt(1); } + + FileStream fileOut = new FileStream("resultTemplate", FileMode.Create, FileAccess.ReadWrite); + workbook.Write(fileOut); + var memoryStream2 = new MemoryStream(); - workbook.Write(memoryStream2); + workbook.Write(memoryStream2,true); memoryStream2.Seek(0, SeekOrigin.Begin); @@ -316,7 +321,7 @@ public static class ExcelExportHelper } var memoryStream2 = new MemoryStream(); - workbook.Write(memoryStream2); + workbook.Write(memoryStream2,true); memoryStream2.Seek(0, SeekOrigin.Begin); 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 81d47f5b6..0e30712ac 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -9509,11 +9509,6 @@ TrialSiteUserSurveyAddOrEdit 列表查询参数模型 - - - 实测 标注在服务方法上 没用 - - TrialSiteEquipmentSurveyService diff --git a/IRaCIS.Core.Application/Service/Allocation/VisitTaskService.cs b/IRaCIS.Core.Application/Service/Allocation/VisitTaskService.cs index 7eb28540c..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 { @@ -1229,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); } - } //拷贝后续表单 @@ -1248,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); } } @@ -1352,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); } } @@ -1370,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); } } @@ -1437,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/Common/CommonDocumentService.cs b/IRaCIS.Core.Application/Service/Common/CommonDocumentService.cs index d9e1cfe9f..bc7db9531 100644 --- a/IRaCIS.Core.Application/Service/Common/CommonDocumentService.cs +++ b/IRaCIS.Core.Application/Service/Common/CommonDocumentService.cs @@ -110,5 +110,13 @@ namespace IRaCIS.Core.Application.Service } + + [HttpDelete("{commonDocumentId:guid}")] + public async Task DeleteCommonDocument(Guid commonDocumentId) + { + var success = await _commonDocumentRepository.DeleteFromQueryAsync(t => t.Id == commonDocumentId, true,true); + return ResponseOutput.Ok(); + } + } } 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/ExcelExportService.cs b/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs index abdba14f3..fe9b30582 100644 --- a/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs +++ b/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs @@ -490,7 +490,7 @@ namespace IRaCIS.Core.Application.Service.Common } var memoryStream2 = new MemoryStream(); - wb.Write(memoryStream2); + wb.Write(memoryStream2,true); memoryStream2.Seek(0, SeekOrigin.Begin); return new FileStreamResult(memoryStream2, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") 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/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 620998555..c4629983e 100644 --- a/IRaCIS.Core.Application/Service/Document/TrialDocumentService.cs +++ b/IRaCIS.Core.Application/Service/Document/TrialDocumentService.cs @@ -57,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); } @@ -157,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 , @@ -189,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, @@ -203,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)) @@ -311,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, @@ -345,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/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 137d4ffd0..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)||t.SiteNameCN.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 0e905e2f8..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(); 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/Reading/ReadingImageTask/ReadingImageTaskService.cs b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs index 21d0d949e..32265b84d 100644 --- a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs @@ -15,6 +15,7 @@ using Newtonsoft.Json.Linq; using Microsoft.Extensions.Caching.Memory; using IRaCIS.Core.Application.Filter; using DocumentFormat.OpenXml.Drawing; +using EasyCaching.Core; using Quartz; using IRaCIS.Application.Services.BackGroundJob; using EasyCaching.Core; 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 0984a186b..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(); /// /// 发送验证码 @@ -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/TrialSiteUser/PersonalWorkstation.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/PersonalWorkstation.cs index 71cd81d3c..c0cef017d 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 && _userInfo.UserTypeEnumInt != (int)UserTypeEnum.OP, 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/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 27338466c..62849f626 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; @@ -91,8 +95,9 @@ namespace IRaCIS.Application.Services .WhereIf(multiModalityIdSelectCount > 0, t => t.TrialDicList.Count(t => t.KeyName == StaticData.Modality) == multiModalityIdSelectCount) .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 }); + .WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin && _userInfo.UserTypeEnumInt != (int)UserTypeEnum.Admin + && _userInfo.UserTypeEnumInt != (int)UserTypeEnum.OP, t => t.TrialUserList.Any(t => t.UserId == _userInfo.Id && t.IsDeleted == false) && t.IsDeleted == false) + .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); @@ -103,7 +108,8 @@ namespace IRaCIS.Application.Services public async Task> GetTrialSelect() { return await _trialRepository.AsQueryable().IgnoreQueryFilters() - .WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin, t => t.TrialUserList.Any(t => t.UserId == _userInfo.Id) && t.IsDeleted == false) + .WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin && _userInfo.UserTypeEnumInt !=(int)UserTypeEnum.Admin && _userInfo.UserTypeEnumInt != (int)UserTypeEnum.OP + , t => t.TrialUserList.Any(t => t.UserId == _userInfo.Id) && t.IsDeleted == false) .ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); } @@ -118,7 +124,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 +219,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(); diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/_MapConfig.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/_MapConfig.cs index ed95fb96a..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,7 +107,6 @@ 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))); - var isEn_Us = false; CreateMap() .ForMember(d => d.HospitalName, u => u.MapFrom(s => s.Hospital.HospitalName)); 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.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.Share/User/UserType.cs b/IRaCIS.Core.Domain.Share/User/UserType.cs index a5f449f12..5d2221939 100644 --- a/IRaCIS.Core.Domain.Share/User/UserType.cs +++ b/IRaCIS.Core.Domain.Share/User/UserType.cs @@ -42,7 +42,7 @@ QA = 12, - + OP=13, SPM=20, APM=21, 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/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.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/Context/IRaCISDBContext.cs b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs index 849440fd9..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)); + //} //遍历实体模型手动配置 @@ -557,6 +558,12 @@ namespace IRaCIS.Core.Infra.EFCore throw new DBSaveFailedException("SQL 事务失败,请检查环境。"); } + catch (Exception ex) + { + _logger.LogError(ex.InnerException is null ? ex.Message : ex.InnerException?.Message); + + throw new DBSaveFailedException("数据保存异常。"); + } } 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