diff --git a/.editorconfig b/.editorconfig index e8bd25dfd..4f2f9fb27 100644 --- a/.editorconfig +++ b/.editorconfig @@ -126,6 +126,47 @@ csharp_style_deconstructed_variable_declaration = true:suggestion csharp_style_unused_value_assignment_preference = discard_variable:suggestion csharp_style_unused_value_expression_statement_preference = discard_variable:silent +# SA0001: XML comment analysis disabled +dotnet_diagnostic.SA0001.severity = suggestion + +# SA1002: Semicolons should be spaced correctly +dotnet_diagnostic.SA1002.severity = suggestion + +# SA1005: Single line comments should begin with single space +dotnet_diagnostic.SA1005.severity = none +dotnet_diagnostic.CS8618.severity = none +dotnet_diagnostic.CS8604.severity = none +dotnet_diagnostic.CS8600.severity = none +dotnet_diagnostic.CS1570.severity = none +dotnet_diagnostic.CS8601.severity = none +dotnet_diagnostic.CS8632.severity = none +dotnet_diagnostic.CS8625.severity = none + +dotnet_diagnostic.CS8603.severity = none +dotnet_diagnostic.CS8602.severity = none +dotnet_diagnostic.CS1998.severity = none +dotnet_diagnostic.CS0168.severity = none +dotnet_diagnostic.CS0219.severity = none +dotnet_diagnostic.CS0108.severity = none +dotnet_diagnostic.CS0120.severity = none + +dotnet_diagnostic.CS8620.severity = none +dotnet_diagnostic.CS8619.severity = none +dotnet_diagnostic.CS0162.severity = none +dotnet_diagnostic.CS0472.severity = none + +dotnet_diagnostic.CS8629.severity = none +dotnet_diagnostic.CS8073.severity = none +dotnet_diagnostic.CS0414.severity = none +dotnet_diagnostic.CS1573.severity = none +dotnet_diagnostic.CS0109.severity = none + +csharp_style_prefer_method_group_conversion = true:silent +csharp_style_prefer_top_level_statements = true:silent +dotnet_diagnostic.SA1003.severity = silent +dotnet_diagnostic.SA1108.severity = silent +dotnet_diagnostic.SA1107.severity = silent + [*.vb] #### 命名样式 #### diff --git a/IRaCIS.Core.API/Controllers/ExtraController.cs b/IRaCIS.Core.API/Controllers/ExtraController.cs index 1234a2e45..75698ad6b 100644 --- a/IRaCIS.Core.API/Controllers/ExtraController.cs +++ b/IRaCIS.Core.API/Controllers/ExtraController.cs @@ -26,6 +26,8 @@ using Aliyun.Acs.Core.Profile; using Aliyun.Acs.Sts.Model.V20150401; using Microsoft.AspNetCore.Hosting; using MassTransit; +using IRaCIS.Core.Application.Helper; +using Microsoft.Extensions.Options; namespace IRaCIS.Api.Controllers { @@ -134,25 +136,82 @@ namespace IRaCIS.Api.Controllers return returnModel; } - [Authorize] - [HttpGet("user/GenerateSTS")] - public IResponseOutput GenerateSTS( [FromServices] IWebHostEnvironment webHostEnvironment) + [HttpGet("user/GetObjectStoreToken")] + public IResponseOutput GetObjectStoreToken([FromServices] IOptionsMonitor options) { - + var serviceOption = options.CurrentValue; - var configuration = new ConfigurationBuilder() - .AddJsonFile($"appsettings.{webHostEnvironment.EnvironmentName}.json") - .Build(); + if (Enum.TryParse(serviceOption.ObjectStoreUse, out var parsedEnum) && parsedEnum == ObjectStoreUse.AliyunOSS) + { + + var ossOptions = serviceOption.AliyunOSS; + + return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse = serviceOption.ObjectStoreUse, MinIO = serviceOption.MinIO, AliyunOSS = serviceOption.AliyunOSS, AWS = serviceOption.AWS }); + + #region 临时token 屏蔽 + //IClientProfile profile = DefaultProfile.GetProfile(ossOptions.RegionId, ossOptions.AccessKeyId, ossOptions.AccessKeySecret); + //DefaultAcsClient client = new DefaultAcsClient(profile); - IClientProfile profile = DefaultProfile.GetProfile("cn-shanghai", configuration["AliyunOSS:accessKeyId"], configuration["AliyunOSS:accessKeySecret"]); + //// 创建一个STS请求 + //AssumeRoleRequest request = new AssumeRoleRequest + //{ + // RoleArn = ossOptions.RoleArn, // 角色ARN,需要替换为你的角色ARN + // RoleSessionName = $"session-name-{NewId.NextGuid()}", // 角色会话名称,可自定义 + // DurationSeconds = 900, // 令牌有效期(单位:秒),这里设置为1小时 + //}; + + + //AssumeRoleResponse response = client.GetAcsResponse(request); + + //// 返回STS令牌信息给前端 + //var stsToken = new ObjectStoreDTO() + //{ + // ObjectStoreUse = serviceOption.ObjectStoreUse, + // AliyunOSS = new AliyunOSSTempToken() + // { + // AccessKeyId = response.Credentials.AccessKeyId, + // AccessKeySecret = response.Credentials.AccessKeySecret, + // SecurityToken = response.Credentials.SecurityToken, + // Expiration = response.Credentials.Expiration, + + // Region = ossOptions.Region, + // BucketName = ossOptions.BucketName, + // ViewEndpoint = ossOptions.ViewEndpoint, + + // }, + // MinIO = serviceOption.MinIO + //}; + //return ResponseOutput.Ok(stsToken); + + #endregion + + } + else if (Enum.TryParse(serviceOption.ObjectStoreUse, out var parsedValue) && parsedValue == ObjectStoreUse.MinIO) + { + return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse = serviceOption.ObjectStoreUse, MinIO = serviceOption.MinIO, AWS = serviceOption.AWS }); + } + else + { + return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse = serviceOption.ObjectStoreUse, MinIO = serviceOption.MinIO, AWS = serviceOption.AWS }); + } + + } + + [HttpGet("user/GenerateSTS")] + public IResponseOutput GenerateSTS([FromServices] IOptionsMonitor options) + { + var ossOptions = options.CurrentValue; + + + IClientProfile profile = DefaultProfile.GetProfile(ossOptions.regionId, ossOptions.accessKeyId, ossOptions.accessKeySecret); DefaultAcsClient client = new DefaultAcsClient(profile); // 创建一个STS请求 AssumeRoleRequest request = new AssumeRoleRequest { - RoleArn = "acs:ram::1899121822495495:role/oss-upload", // 角色ARN,需要替换为你的角色ARN + RoleArn = ossOptions.roleArn, // 角色ARN,需要替换为你的角色ARN RoleSessionName = $"session-name-{NewId.NextGuid()}", // 角色会话名称,可自定义 DurationSeconds = 900, // 令牌有效期(单位:秒),这里设置为1小时 }; @@ -168,9 +227,9 @@ namespace IRaCIS.Api.Controllers SecurityToken = response.Credentials.SecurityToken, Expiration = response.Credentials.Expiration, - Region= configuration["AliyunOSS:region"], - BucketName = configuration["AliyunOSS:bucketName"], - ViewEndpoint = configuration["AliyunOSS:viewEndpoint"], + Region = ossOptions.region , + BucketName = ossOptions.bucketName , + ViewEndpoint = ossOptions.viewEndpoint , }; diff --git a/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs b/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs index 0a7430625..bc182817f 100644 --- a/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs +++ b/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs @@ -24,6 +24,7 @@ using Magicodes.ExporterAndImporter.Excel; using MassTransit; using MediatR; using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Cors.Infrastructure; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -37,7 +38,7 @@ using Microsoft.Net.Http.Headers; using MiniExcelLibs; using Newtonsoft.Json; using SharpCompress.Archives; -using SharpCompress.Common; +using SkiaSharp; using System; using System.Collections.Generic; using System.Data; @@ -134,6 +135,32 @@ namespace IRaCIS.Core.API.Controllers } } + [Route("base")] + public virtual async Task FileUploadToOSSAsync(Func> toMemoryStreamFunc) + { + var boundary = HeaderUtilities.RemoveQuotes(MediaTypeHeaderValue.Parse(Request.ContentType).Boundary).Value; + + var reader = new MultipartReader(boundary, HttpContext.Request.Body); + + var section = await reader.ReadNextSectionAsync(); + + while (section != null) + { + var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition); + if (hasContentDispositionHeader) + { + var fileName = contentDisposition.FileName.Value; + + await toMemoryStreamFunc(fileName, section.Body); + + } + + section = await reader.ReadNextSectionAsync(); + + } + + } + /// 流式上传 Dicom上传 @@ -280,9 +307,6 @@ namespace IRaCIS.Core.API.Controllers - - - if (!HttpContext.Request.HasFormContentType || !MediaTypeHeaderValue.TryParse(HttpContext.Request.ContentType, out var mediaTypeHeader) || string.IsNullOrEmpty(mediaTypeHeader.Boundary.Value)) @@ -756,11 +780,13 @@ namespace IRaCIS.Core.API.Controllers [HttpPost("QCOperation/UploadVisitCheckExcel/{trialId:guid}")] [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] //[Authorize(Policy = IRaCISPolicy.PM_APM)] - public async Task UploadVisitCheckExcel(Guid trialId) + public async Task UploadVisitCheckExcel(Guid trialId, [FromServices] IOSSService oSSService) { - var (serverFilePath, relativePath, fileName) = (string.Empty, string.Empty, string.Empty); - await FileUploadAsync(async (realFileName) => + var fileName = string.Empty; + var templateFileStream = new MemoryStream(); + + await FileUploadToOSSAsync(async (realFileName, fileStream) => { fileName = realFileName; @@ -770,19 +796,16 @@ namespace IRaCIS.Core.API.Controllers throw new BusinessValidationFailedException(StaticData.International("UploadDownLoad_SupportedFormats")); } - (serverFilePath, relativePath) = FileStoreHelper.GetTrialCheckFilePath(_hostEnvironment, fileName, trialId); + fileStream.CopyTo(templateFileStream); + templateFileStream.Seek(0, SeekOrigin.Begin); - await _repository.AddAsync(new UserUploadFile() - { - TrialId = trialId, - CreateTime = DateTime.Now, - FileName = fileName, - FilePath = relativePath, - RelativePath = relativePath, - CreateUserId = _userInfo.Id - }); - return serverFilePath; + var ossRelativePath = await oSSService.UploadToOSSAsync(fileStream, "InspectionUpload/Check", realFileName); + + await _repository.AddAsync(new InspectionFile() { FileName = realFileName, RelativePath = ossRelativePath, TrialId = trialId }); + + return ossRelativePath; + }); @@ -814,7 +837,7 @@ namespace IRaCIS.Core.API.Controllers { var Importer = new ExcelImporter(); - var import = await Importer.Import(System.IO.File.OpenRead(serverFilePath)); + var import = await Importer.Import(templateFileStream); if (import.Exception != null) return ResponseOutput.NotOk(import.Exception.ToString()); @@ -829,7 +852,7 @@ namespace IRaCIS.Core.API.Controllers #region 临时方案 MiniExcel读取 然后保存为xlsx 再用 Magicodes验证数据 //因为csv 需要加配置文件 不然都是null - etcCheckList = MiniExcel.Query(serverFilePath, null, configuration: new MiniExcelLibs.Csv.CsvConfiguration() + etcCheckList = MiniExcel.Query(templateFileStream, null, configuration: new MiniExcelLibs.Csv.CsvConfiguration() { StreamReaderFunc = (stream) => new StreamReader(stream, Encoding.GetEncoding("gb2312")) }).ToList(); @@ -874,35 +897,35 @@ namespace IRaCIS.Core.API.Controllers else { //为了支持 xls 引入新的组件库 - using (var stream = System.IO.File.Open(serverFilePath, FileMode.Open, FileAccess.Read)) + //using (var stream = System.IO.File.Open(templateFileStream, FileMode.Open, FileAccess.Read)) + //{ + // Auto-detect format, supports: + // - Binary Excel files (2.0-2003 format; *.xls) + // - OpenXml Excel files (2007 format; *.xlsx, *.xlsb) + using (var reader = ExcelReaderFactory.CreateReader(templateFileStream)) { - // Auto-detect format, supports: - // - Binary Excel files (2.0-2003 format; *.xls) - // - OpenXml Excel files (2007 format; *.xlsx, *.xlsb) - using (var reader = ExcelReaderFactory.CreateReader(stream)) + + // 2. Use the AsDataSet extension method + var dateset = reader.AsDataSet(); + + foreach (DataRow col in dateset.Tables[0].Rows) { - // 2. Use the AsDataSet extension method - var dateset = reader.AsDataSet(); - - foreach (DataRow col in dateset.Tables[0].Rows) + etcCheckList.Add(new CheckViewModel() { - - etcCheckList.Add(new CheckViewModel() - { - SiteCode = col[0].ToString(), - SubjectCode = col[1].ToString(), - VisitName = col[2].ToString(), - StudyDate = col[3].ToString(), - Modality = col[4].ToString(), - }); - } - - etcCheckList.Remove(etcCheckList[0]); - - // The result of each spreadsheet is in result.Tables + SiteCode = col[0].ToString(), + SubjectCode = col[1].ToString(), + VisitName = col[2].ToString(), + StudyDate = col[3].ToString(), + Modality = col[4].ToString(), + }); } + + etcCheckList.Remove(etcCheckList[0]); + + // The result of each spreadsheet is in result.Tables } + } if (etcCheckList == null || etcCheckList.Count == 0) @@ -940,7 +963,6 @@ namespace IRaCIS.Core.API.Controllers return ResponseOutput.Ok(); } - } @@ -948,6 +970,8 @@ namespace IRaCIS.Core.API.Controllers + + #region 项目 系统 基本文件 上传 下载 预览 [ApiExplorerSettings(GroupName = "Common")] @@ -980,30 +1004,38 @@ namespace IRaCIS.Core.API.Controllers [DisableFormValueModelBinding] [UnitOfWork] public async Task UploadTrialSiteSurveyUser(Guid trialId, string baseUrl, string routeUrl, - [FromServices] IRepository _trialSiteRepository, - [FromServices] IRepository _usertypeRepository, - [FromServices] ITrialSiteSurveyService _trialSiteSurveyService) + [FromServices] IRepository _trialSiteRepository, + [FromServices] IRepository _usertypeRepository, + [FromServices] ITrialSiteSurveyService _trialSiteSurveyService, + [FromServices] IOSSService oSSService, + [FromServices] IRepository _inspectionFileRepository) { - var (serverFilePath, relativePath, fileName) = (string.Empty, string.Empty, string.Empty); - await FileUploadAsync(async (realFileName) => - { - fileName = realFileName; + var templateFileStream = new MemoryStream(); - if (!fileName.EndsWith(".xlsx", StringComparison.OrdinalIgnoreCase)) + + await FileUploadToOSSAsync(async (realFileName, fileStream) => + { + await fileStream.CopyToAsync(templateFileStream); + templateFileStream.Seek(0, SeekOrigin.Begin); + + if (!realFileName.EndsWith(".xlsx", StringComparison.OrdinalIgnoreCase)) { // 请用提供格式的模板excel上传需要处理的数据 throw new BusinessValidationFailedException(StaticData.International("UploadDownLoad_TemplateUploadData")); } - (serverFilePath, relativePath) = FileStoreHelper.GetOtherFileUploadPath(_hostEnvironment, StaticData.Folder.TempFile, fileName); + var ossRelativePath = await oSSService.UploadToOSSAsync(fileStream, "InspectionUpload/SiteSurvey", realFileName); - //FileStoreHelper.UploadOOS(serverFilePath, "testc/test", true); + await _inspectionFileRepository.AddAsync(new InspectionFile() { FileName = realFileName, RelativePath = ossRelativePath, TrialId = trialId }); + + + + return ossRelativePath; - return serverFilePath; }); //去掉空白行 - var excelList = MiniExcel.Query(serverFilePath).ToList() + var excelList = MiniExcel.Query(templateFileStream,excelType:ExcelType.XLSX).ToList() .Where(t => !(string.IsNullOrWhiteSpace(t.TrialSiteCode) && string.IsNullOrWhiteSpace(t.FirstName) && string.IsNullOrWhiteSpace(t.LastName) && string.IsNullOrWhiteSpace(t.Email) && string.IsNullOrWhiteSpace(t.Phone) && string.IsNullOrWhiteSpace(t.UserTypeStr) && string.IsNullOrWhiteSpace(t.OrganizationName))).ToList(); @@ -1033,7 +1065,7 @@ namespace IRaCIS.Core.API.Controllers //有邮箱不符合邮箱格式,请核查Excel数据 throw new BusinessValidationFailedException(StaticData.International("UploadDownLoad_InvalidEmail")); } - var generateUserTypeList = new List() { "CRC", "SR", "CRA" }; + var generateUserTypeList = new List() { "CRC", "CRA","SR" }; if (excelList.Any(t => !generateUserTypeList.Contains(t.UserTypeStr.ToUpper()))) { diff --git a/IRaCIS.Core.API/Dockerfile b/IRaCIS.Core.API/Dockerfile deleted file mode 100644 index 4cb188d79..000000000 --- a/IRaCIS.Core.API/Dockerfile +++ /dev/null @@ -1,26 +0,0 @@ -#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging. - -FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base -WORKDIR /app -EXPOSE 80 - -FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build -WORKDIR /src -COPY ["IRaCIS.Core.API/IRaCIS.Core.API.csproj", "IRaCIS.Core.API/"] -COPY ["IRaCIS.Core.Application/IRaCIS.Core.Application.csproj", "IRaCIS.Core.Application/"] -COPY ["IRaCIS.Core.Infra.EFCore/IRaCIS.Core.Infra.EFCore.csproj", "IRaCIS.Core.Infra.EFCore/"] -COPY ["IRaCIS.Core.Domain/IRaCIS.Core.Domain.csproj", "IRaCIS.Core.Domain/"] -COPY ["IRaCIS.Core.Domain.Share/IRaCIS.Core.Domain.Share.csproj", "IRaCIS.Core.Domain.Share/"] -COPY ["IRaCIS.Core.Infrastructure/IRaCIS.Core.Infrastructure.csproj", "IRaCIS.Core.Infrastructure/"] -RUN dotnet restore "IRaCIS.Core.API/IRaCIS.Core.API.csproj" -COPY . . -WORKDIR "/src/IRaCIS.Core.API" -RUN dotnet build "IRaCIS.Core.API.csproj" -c Release -o /app/build - -FROM build AS publish -RUN dotnet publish "IRaCIS.Core.API.csproj" -c Release -o /app/publish /p:UseAppHost=false - -FROM base AS final -WORKDIR /app -COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "IRaCIS.Core.API.dll"] \ No newline at end of file diff --git a/IRaCIS.Core.API/GrpcToken.proto b/IRaCIS.Core.API/GrpcToken.proto index ace5d4240..f14d65a66 100644 --- a/IRaCIS.Core.API/GrpcToken.proto +++ b/IRaCIS.Core.API/GrpcToken.proto @@ -1,16 +1,16 @@ -// ʹõproto3汾 +// 使用的是proto3版本 syntax = "proto3"; -// ռ䣬ɴʱͻɶӦռ +// 定义命名空间,后续生成代码时就会生成对应的命名空间 option csharp_namespace = "gRPC.ZHiZHUN.AuthServer.protos"; /* -ÿһҪ÷ֺŽβ -message ͷݸʽ -tag messageִֵֶεıʶ(tag),Ǹֵ +每一句需要用分号结尾 +message 用来定义请求和返回数据格式 +tag message后面的值数字代表是字段的标识(tag),不是赋值, */ -// ûʱҪϢ Ϊһ +// 新增用户时需要传递数据消息, 可理解为一个类 message GetTokenReuqest{ string id=1; string userName=2; @@ -22,48 +22,48 @@ message GetTokenReuqest{ } -// ʱصϢʽ +// 新增时返回的消息格式 message GetTokenResponse { int32 code=1; string token =2; } -// service ñʶģдӦķ +// service 用标识定义服务的,里面写对应的方法 service TokenGrpcService{ - // ȡtoken + // 获取token rpc GetUserToken(GetTokenReuqest) returns (GetTokenResponse); } /* -// ûʱҪϢ Ϊһ +// 新增用户时需要传递数据消息, 可理解为一个类 message AddUserReuqest{ string name=1; int32 age=2; bool isBoy=3; } -// ʱصϢʽ +// 新增时返回的消息格式 message ResultResponse { int32 code=1; string msg =2; } -//ݵIJѯϢʽΪƽʱIJѯ +//传递的查询条件信息格式,可理解为平时传入的查询条件对象 message QueryUserReuqest{ string name=1; } -//ѯصûϢʽΪص +//查询返回的用户信息格式,可理解为返回的类 message UserInfoResponse { string name=1; int32 age=2; string gender=3; } -// service ñʶģдӦķ +// service 用标识定义服务的,里面写对应的方法 service UserService{ - // û + // 新增用户 rpc AddUser(AddUserReuqest) returns (ResultResponse); - // ѯû + // 查询用户 rpc GetAllUser(QueryUserReuqest) returns (UserInfoResponse); } */ diff --git a/IRaCIS.Core.API/IRaCIS.Core.API.xml b/IRaCIS.Core.API/IRaCIS.Core.API.xml index fe5eb4c96..11819a905 100644 --- a/IRaCIS.Core.API/IRaCIS.Core.API.xml +++ b/IRaCIS.Core.API/IRaCIS.Core.API.xml @@ -219,13 +219,16 @@ - + 一致性核查 excel上传 支持三种格式 + + 通用文件下载 + 上传通用文档 比如一致性核查的 比如导出的excel 模板 diff --git a/IRaCIS.Core.API/Program.cs b/IRaCIS.Core.API/Program.cs deleted file mode 100644 index cd37383b2..000000000 --- a/IRaCIS.Core.API/Program.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System; -using Autofac.Extensions.DependencyInjection; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Configuration; -using Serilog; -using MediatR; -using IRaCIS.Core.Application.MediatR.Handlers; -using System.Threading.Tasks; -using MassTransit; -using MassTransit.NewIdProviders; -using System.IO; -using IRaCIS.Core.Domain.Share; -using IRaCIS.Core.Infra.EFCore; -using IRaCIS.Core.Application.Helper; -using IRaCIS.Application.Services.BackGroundJob; -using Hangfire; - -namespace IRaCIS.Core.API -{ - public class Program - { - public readonly string environment; - public static async Task Main(string[] args) - { - try - { - //ļΪ׼ urlȡֵ(дݲļ˾ͲҪݻ) - var config = new ConfigurationBuilder() - .AddEnvironmentVariables() - .Build(); - - var enviromentName = config["ASPNETCORE_ENVIRONMENT"]; - - if (string.IsNullOrWhiteSpace(enviromentName)) - { - - var index = Array.IndexOf(args, "--env"); - enviromentName = index > -1 - ? args[index + 1] - : "Development"; - } - - //Dicom - //ImageManager.SetImplementation(WinFormsImageManager.Instance); - - var host = CreateHostBuilder(args) - .UseEnvironment(enviromentName) //д뻷 - .ConfigureAppConfiguration((hostContext, config) => - { - - //Console.WriteLine(hostContext.HostingEnvironment.EnvironmentName); - config.AddJsonFile("appsettings.json", false, true) - .AddJsonFile($"appsettings.{enviromentName}.json", false, true); - }) - .Build(); - - - //// Serilog - SerilogExtension.AddSerilogSetup(enviromentName, host.Services); - Log.Logger.Warning($"ǰ{enviromentName}"); - - - NewId.SetProcessIdProvider(new CurrentProcessIdProvider()); - - ////Ŀ״̬ - //await InitCache(host); - - host.Run(); - - - } - catch (Exception e) - { - - Log.Logger.Error(e.InnerException is null ? e.Message + e.StackTrace : e.InnerException?.Message + e.InnerException?.StackTrace); - } - - } - - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .UseWindowsService() - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.ConfigureKestrel((context, options) => - { - //Ӧ÷KestrelΪ1GB // if don't set default value is: 30 MB - options.Limits.MaxRequestBodySize = long.MaxValue; - options.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(30); - options.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(20); - - }); - //webBuilder.UseSerilog();//ʱserilog,΢ILogger - webBuilder.UseStartup(); - }).UseSerilog() - .UseServiceProviderFactory(new AutofacServiceProviderFactory()); - - - private static async Task InitCache(IHost host) - { - var _repository = host.Services.GetService(typeof(IRepository)) as IRepository; - - //ʼ ʻݣҼʻļ - //await InternationalizationHelper.InitInternationlizationDataAndWatchJsonFileAsync(_repository); - - } - - - - - - } -} diff --git a/IRaCIS.Core.API/Progranm.cs b/IRaCIS.Core.API/Progranm.cs new file mode 100644 index 000000000..87fab940c --- /dev/null +++ b/IRaCIS.Core.API/Progranm.cs @@ -0,0 +1,306 @@ +using System; +using Autofac.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Configuration; +using Serilog; +using MediatR; +using IRaCIS.Core.Application.MediatR.Handlers; +using System.Threading.Tasks; +using MassTransit; +using MassTransit.NewIdProviders; +using System.IO; +using IRaCIS.Core.Domain.Share; +using IRaCIS.Core.Infra.EFCore; +using IRaCIS.Core.Application.Helper; +using System.Runtime.InteropServices; +using Microsoft.AspNetCore.Builder; +using IRaCIS.Core.API; +using Autofac; +using Microsoft.AspNetCore.Http.Features; +using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.DependencyInjection; +using IRaCIS.Core.Application.Filter; +using Microsoft.AspNetCore.HttpOverrides; +using IRaCIS.Application.Services.BackGroundJob; +using LogDashboard; +using OfficeOpenXml.Utils; + + + +#region 获取环境变量 +//以配置文件为准,否则 从url中取环境值(服务以命令行传递参数启动,配置文件配置了就不需要传递环境参数) +var config = new ConfigurationBuilder() + .AddEnvironmentVariables() + .Build(); + +var enviromentName = config["ASPNETCORE_ENVIRONMENT"]; + +if (string.IsNullOrWhiteSpace(enviromentName)) +{ + + var index = Array.IndexOf(args, "--env"); + enviromentName = index > -1 + ? args[index + 1] + : "Development"; +} +#endregion + +var builder = WebApplication.CreateBuilder(new WebApplicationOptions +{ + EnvironmentName = enviromentName +}); + +#region 兼容windows 服务命令行的方式 + +//foreach (var arg in args) +//{ +// Console.WriteLine(arg); +//} + +int urlsIndex = Array.FindIndex(args, arg => arg != null && arg.StartsWith("--urls")); + +if (urlsIndex > -1) +{ + var url = args[urlsIndex].Substring("--urls=".Length); + Console.WriteLine(url); + builder.WebHost.UseUrls(url); +} + +#endregion + +#region 主机配置 + + +NewId.SetProcessIdProvider(new CurrentProcessIdProvider()); + +builder.Configuration.AddJsonFile("appsettings.json", false, true) + .AddJsonFile($"appsettings.{enviromentName}.json", false, true); + +builder.Host + .UseServiceProviderFactory(new AutofacServiceProviderFactory()) + .ConfigureContainer(containerBuilder => + { + containerBuilder.RegisterModule(); + }) + .UseWindowsService().UseSerilog(); +#endregion + + +#region 配置服务 +var _configuration = builder.Configuration; + +//健康检查 +builder.Services.AddHealthChecks(); +//本地化 +builder.Services.AddJsonLocalization(options => options.ResourcesPath = "Resources"); + +// 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim() +builder.Services.AddControllers(options => +{ + //options.Filters.Add(); + options.Filters.Add(); + options.Filters.Add(); + options.Filters.Add(); + + if (_configuration.GetSection("BasicSystemConfig").GetValue("OpenLoginLimit")) + { + options.Filters.Add(); + } + +}) + .AddNewtonsoftJsonSetup(); // NewtonsoftJson 序列化 处理 + +builder.Services.AddOptions().Configure(_configuration.GetSection("SystemEmailSendConfig")); +builder.Services.AddOptions().Configure(_configuration.GetSection("BasicSystemConfig")); +builder.Services.AddOptions().Configure(_configuration.GetSection("AliyunOSS")); +builder.Services.AddOptions().Configure(_configuration.GetSection("ObjectStoreService")); + + +//动态WebApi + UnifiedApiResultFilter 省掉控制器代码 +builder.Services.AddDynamicWebApiSetup(); +//AutoMapper +builder.Services.AddAutoMapperSetup(); +//EF ORM QueryWithNoLock +builder.Services.AddEFSetup(_configuration); +//Http 响应压缩 +builder.Services.AddResponseCompressionSetup(); +//Swagger Api 文档 +builder.Services.AddSwaggerSetup(); +//JWT Token 验证 +builder.Services.AddJWTAuthSetup(_configuration); + +// MediatR 进程内消息 事件解耦 从程序集中 注册命令和handler对应关系 +builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining()); +// EasyCaching 缓存 +builder.Services.AddEasyCachingSetup(_configuration); + +// hangfire 定时任务框架 有界面,更友好~ +builder.Services.AddhangfireSetup(_configuration); + +// +builder.Services.AddQuartZSetup(_configuration); + +//Serilog 日志可视化 LogDashboard日志 +builder.Services.AddLogDashboardSetup(); + + +builder.Services.AddJsonConfigSetup(_configuration); +//转发头设置 获取真实IP +builder.Services.Configure(options => +{ + options.ForwardedHeaders = + ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; +}); +//Dicom影像渲染图片 跨平台 +builder.Services.AddDicomSetup(); + +// 实时应用 +builder.Services.AddSignalR(); + +builder.Services.AddSingleton(); + +//builder.Services.AddMemoryCache(); + + + +#region 历史废弃配置 + +////上传限制 配置 +//builder.Services.Configure(options => +//{ +// options.MultipartBodyLengthLimit = int.MaxValue; +// options.ValueCountLimit = int.MaxValue; +// options.ValueLengthLimit = int.MaxValue; +//}); +//IP 限流 可设置白名单 或者黑名单 +//services.AddIpPolicyRateLimitSetup(_configuration); +// 用户类型 策略授权 +//services.AddAuthorizationPolicySetup(_configuration); +#endregion + +#endregion + +var app = builder.Build(); +var env = app.Environment; + +#region 配置中间件 + + +// Configure the HTTP request pipeline. + +//本地化 +app.UseLocalization(); + +app.UseForwardedHeaders(); + +//响应压缩 +app.UseResponseCompression(); + +//app.UseCors(t => t.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader()); + +//不需要 token 访问的静态文件 wwwroot css, JavaScript, and images don't require authentication. +app.UseStaticFiles(); + +//app.UseMiddleware(); + +//LogDashboard +app.UseLogDashboard("/LogDashboard"); + +//hangfire +app.UseHangfireConfig(env); + + +////限流 中间件 +//app.UseIpRateLimiting(); + + +if (env.IsDevelopment()) +{ + app.UseDeveloperExceptionPage(); +} +else +{ + //app.UseHsts(); +} + +// 特殊异常处理 比如 404 +app.UseStatusCodePagesWithReExecute("/Error/{0}"); + +SwaggerSetup.Configure(app, env); + + +////serilog 记录请求的用户信息 +app.UseSerilogConfig(env); + +app.UseRouting(); + +app.UseCors(t => t.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader()); + +//app.UseIRacisHostStaticFileStore(env); + + +app.UseAuthentication(); +app.UseAuthorization(); + +app.MapControllers(); + +app.MapHub("/UploadHub"); +app.MapHealthChecks("/health"); + + +// Serilog +SerilogExtension.AddSerilogSetup(enviromentName, app.Services); + + +var hangfireJobService = app.Services.GetRequiredService(); + +await hangfireJobService.InitHangfireJobTaskAsync(); + + +#endregion + +try +{ + #region 运行环境 部署平台 + + Log.Logger.Warning($"当前环境:{enviromentName}"); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + Log.Logger.Warning($"当前部署平台环境:windows"); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + Log.Logger.Warning($"当前部署平台环境:linux"); + } + else + { + Log.Logger.Warning($"当前部署平台环境:OSX or FreeBSD"); + } + + #endregion + + + Log.Logger.Warning($"ContentRootPath:{env.ContentRootPath}"); + + + string parentDirectory = Path.GetFullPath(Path.Combine(env.ContentRootPath, "..")); + + + Log.Logger.Warning($"ContentRootPath——parentDirectory:{parentDirectory}"); + + //Log.Logger.Warning($"ContentRootPath——GetParent:{Directory.GetParent(env.ContentRootPath).Parent.FullName}"); + //Log.Logger.Warning($"ContentRootPath——xx:{Path.GetDirectoryName(Path.GetDirectoryName(env.ContentRootPath))}"); + + app.Run(); + +} +catch (Exception e) +{ + + Log.Logger.Error(e.InnerException is null ? e.Message + e.StackTrace : e.InnerException?.Message + e.InnerException?.StackTrace); +} + + + diff --git a/IRaCIS.Core.API/Properties/launchSettings.json b/IRaCIS.Core.API/Properties/launchSettings.json index 6736bd9b9..343a2a304 100644 --- a/IRaCIS.Core.API/Properties/launchSettings.json +++ b/IRaCIS.Core.API/Properties/launchSettings.json @@ -1,11 +1,13 @@ { "$schema": "http://json.schemastore.org/launchsettings.json", - "profiles": { - "Docker": { - "commandName": "Docker", + "profiles": { + "Test_Study": { + "commandName": "Project", "launchBrowser": true, - "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}", - "publishAllPorts": true + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Test_Study" + }, + "applicationUrl": "http://localhost:6100" }, "Uat_Study": { "commandName": "Project", @@ -14,14 +16,6 @@ "ASPNETCORE_ENVIRONMENT": "Uat_Study" }, "applicationUrl": "http://localhost:6100" - }, - "Test_Study": { - "commandName": "Project", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Test_Study" - }, - "applicationUrl": "http://localhost:6100" } } } \ No newline at end of file diff --git a/IRaCIS.Core.API/Protos/GrpcToken.proto b/IRaCIS.Core.API/Protos/GrpcToken.proto index ace5d4240..f14d65a66 100644 --- a/IRaCIS.Core.API/Protos/GrpcToken.proto +++ b/IRaCIS.Core.API/Protos/GrpcToken.proto @@ -1,16 +1,16 @@ -// ʹõproto3汾 +// 使用的是proto3版本 syntax = "proto3"; -// ռ䣬ɴʱͻɶӦռ +// 定义命名空间,后续生成代码时就会生成对应的命名空间 option csharp_namespace = "gRPC.ZHiZHUN.AuthServer.protos"; /* -ÿһҪ÷ֺŽβ -message ͷݸʽ -tag messageִֵֶεıʶ(tag),Ǹֵ +每一句需要用分号结尾 +message 用来定义请求和返回数据格式 +tag message后面的值数字代表是字段的标识(tag),不是赋值, */ -// ûʱҪϢ Ϊһ +// 新增用户时需要传递数据消息, 可理解为一个类 message GetTokenReuqest{ string id=1; string userName=2; @@ -22,48 +22,48 @@ message GetTokenReuqest{ } -// ʱصϢʽ +// 新增时返回的消息格式 message GetTokenResponse { int32 code=1; string token =2; } -// service ñʶģдӦķ +// service 用标识定义服务的,里面写对应的方法 service TokenGrpcService{ - // ȡtoken + // 获取token rpc GetUserToken(GetTokenReuqest) returns (GetTokenResponse); } /* -// ûʱҪϢ Ϊһ +// 新增用户时需要传递数据消息, 可理解为一个类 message AddUserReuqest{ string name=1; int32 age=2; bool isBoy=3; } -// ʱصϢʽ +// 新增时返回的消息格式 message ResultResponse { int32 code=1; string msg =2; } -//ݵIJѯϢʽΪƽʱIJѯ +//传递的查询条件信息格式,可理解为平时传入的查询条件对象 message QueryUserReuqest{ string name=1; } -//ѯصûϢʽΪص +//查询返回的用户信息格式,可理解为返回的类 message UserInfoResponse { string name=1; int32 age=2; string gender=3; } -// service ñʶģдӦķ +// service 用标识定义服务的,里面写对应的方法 service UserService{ - // û + // 新增用户 rpc AddUser(AddUserReuqest) returns (ResultResponse); - // ѯû + // 查询用户 rpc GetAllUser(QueryUserReuqest) returns (UserInfoResponse); } */ diff --git a/IRaCIS.Core.API/Startup.cs b/IRaCIS.Core.API/Startup.cs deleted file mode 100644 index 498b34c37..000000000 --- a/IRaCIS.Core.API/Startup.cs +++ /dev/null @@ -1,257 +0,0 @@ -using Autofac; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http.Features; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using System; -using IRaCIS.Core.Application.Filter; -using LogDashboard; -using MediatR; -using IRaCIS.Core.Application.MediatR.Handlers; -using Microsoft.Extensions.Logging; -using AspNetCoreRateLimit; -using Microsoft.AspNetCore.HttpOverrides; -using IRaCIS.Core.Infra.EFCore; -using System.Globalization; -using Microsoft.AspNetCore.Localization; -using Localization; -using Magicodes.ExporterAndImporter.Core.Filters; -using IRaCIS.Core.Application.MediatR.CommandAndQueries; -using IRaCIS.Core.Infra.EFCore.Common; -using Invio.Extensions.Authentication.JwtBearer; -using Microsoft.AspNetCore.SignalR; -using IRaCIS.Core.Domain.Share; -using Microsoft.AspNetCore.StaticFiles; -using IRaCIS.Application.Services.BackGroundJob; -using IRaCIS.Core.Application.Helper; -using Microsoft.AspNetCore.Http; -using Autofac.Core; -using DocumentFormat.OpenXml.InkML; -using EasyCaching.Core; - -namespace IRaCIS.Core.API -{ - public class Startup - { - public Startup(IConfiguration configuration) - { - _configuration = configuration; - } - public ILogger _logger { get; } - - public IConfiguration _configuration { get; } - - //// ConfigureContainer is where you can register things directly - //// with Autofac. This runs after ConfigureServices so the things - //// here will override registrations made in ConfigureServices. - //// Don't build the container; that gets done for you by the factory. - // for castle - public void ConfigureContainer(ContainerBuilder containerBuilder) - { - containerBuilder.RegisterModule(); - - #region Test - //containerBuilder.RegisterType().PropertiesAutowired().InstancePerLifetimeScope();//עִ - - //var container = containerBuilder.Build(); - - //// Now you can resolve services using Autofac. For example, - //// this line will execute the lambda expression registered - //// to the IConfigReader service. - //using (var scope = container.BeginLifetimeScope()) - //{ - // var reader = scope.Resolve(); - - // var test = scope.Resolve(); - // var test2 = scope.Resolve(); - - // var test3 = scope.Resolve>(); - //} - #endregion - } - - // This method gets called by the runtime. Use this method to add services to the container. - public void ConfigureServices(IServiceCollection services) - { - //ػ - services.AddJsonLocalization(options => options.ResourcesPath = "Resources"); - - // 쳣ͳһ֤JsonлáַͳһTrim() - services.AddControllers(options => - { - //options.Filters.Add(); - options.Filters.Add(); - options.Filters.Add(); - options.Filters.Add(); - - if (_configuration.GetSection("BasicSystemConfig").GetValue("OpenLoginLimit")) - { - options.Filters.Add(); - } - - - }) - .AddNewtonsoftJsonSetup(); // NewtonsoftJson л - - services.AddOptions().Configure(_configuration.GetSection("SystemEmailSendConfig")); - services.AddOptions().Configure(_configuration.GetSection("BasicSystemConfig")); - - - - //̬WebApi + UnifiedApiResultFilter ʡ - services.AddDynamicWebApiSetup(); - //AutoMapper - services.AddAutoMapperSetup(); - //EF ORM QueryWithNoLock - services.AddEFSetup(_configuration); - //Http Ӧѹ - services.AddResponseCompressionSetup(); - //Swagger Api ĵ - services.AddSwaggerSetup(); - //JWT Token ֤ - services.AddJWTAuthSetup(_configuration); - // MediatR Ϣ ¼ ӳ עhandlerӦϵ - services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining()); - // EasyCaching - services.AddEasyCachingSetup(_configuration); - - //services.AddDistributedMemoryCache(); - - // hangfire ʱ н棬Ѻ~ - services.AddhangfireSetup(_configuration); - - // QuartZ ʱ ʹhangfire ʱãҪԴ򿪣Ѿ - services.AddQuartZSetup(_configuration); - - // ϴļ - //services.AddStaticFileAuthorizationSetup(); - - - ////HttpReports ʱ - //services.AddHttpReports().AddHttpTransport(); - //Serilog ־ӻ LogDashboard־ - services.AddLogDashboardSetup(); - //ϴ - services.Configure(options => - { - options.MultipartBodyLengthLimit = int.MaxValue; - options.ValueCountLimit = int.MaxValue; - options.ValueLengthLimit = int.MaxValue; - }); - //IP ð ߺ - //services.AddIpPolicyRateLimitSetup(_configuration); - // û Ȩ - //services.AddAuthorizationPolicySetup(_configuration); - - services.AddJsonConfigSetup(_configuration); - //תͷ ȡʵIP - services.Configure(options => - { - options.ForwardedHeaders = - ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; - }); - //DicomӰȾͼƬ ƽ̨ - services.AddDicomSetup(); - - // ʵʱӦ - services.AddSignalR(); - - - services.AddSingleton(); - - //services.AddSingleton(); - - services.AddMemoryCache(); - - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public async void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - //app.UsePathBase(PathString.FromUriComponent("/api")); - - //ػ - app.UseLocalization(); - - app.UseForwardedHeaders(); - - //Ӧѹ - app.UseResponseCompression(); - - //app.UseCors(t => t.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader()); - - //Ҫ token ʵľ̬ļ wwwroot css, JavaScript, and images don't require authentication. - app.UseStaticFiles(); - - - //LogDashboard - app.UseLogDashboard("/back/logs"); - - //hangfire - app.UseHangfireConfig(env); - - ////ʱ - //app.UseHttpReports(); - - //// м - //app.UseIpRateLimiting(); - - - - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - else - { - //app.UseHsts(); - } - Console.WriteLine("ǰ " + env.EnvironmentName); - - //app.UseMiddleware(); - - // 쳣 404 - app.UseStatusCodePagesWithReExecute("/Error/{0}"); - - SwaggerSetup.Configure(app, env); - - - - ////serilog ¼ûϢ - app.UseSerilogConfig(env); - - app.UseRouting(); - - app.UseCors(t => t.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader()); - - //app.UseIRacisHostStaticFileStore(env); - app.UseMiddleware(); - - - app.UseAuthentication(); - //app.UseJwtBearerQueryString(); - app.UseAuthorization(); - - ////ļŷ Token - ////app.UseIRacisHostStaticFileStore(env); - - app.UseEndpoints(endpoints => - { - endpoints.MapControllers(); - - endpoints.MapHub("/UploadHub"); - }); - - - var hangfireJobService = app.ApplicationServices.GetRequiredService(); - - await hangfireJobService.InitHangfireJobTaskAsync(); - //еʱÿ - //HangfireJobHelper.NotImmediatelyOnceOnlyJob(t => t.InitHangfireJobTaskAsync(),TimeSpan.FromSeconds(1)); - - - } - } -} diff --git a/IRaCIS.Core.API/_PipelineExtensions/Serilog/SerilogConfig.cs b/IRaCIS.Core.API/_PipelineExtensions/Serilog/SerilogConfig.cs index c5af7adbe..1f88b7746 100644 --- a/IRaCIS.Core.API/_PipelineExtensions/Serilog/SerilogConfig.cs +++ b/IRaCIS.Core.API/_PipelineExtensions/Serilog/SerilogConfig.cs @@ -17,7 +17,7 @@ namespace IRaCIS.Core.API app.UseSerilogRequestLogging(opts => { - opts.MessageTemplate = "{TokenUserRealName} {TokenUserType} {ClientIp} {RequestIP} {Host} {Protocol} {RequestMethod} {RequestPath} {RequestBody} responded {StatusCode} in {Elapsed:0.0000} ms"; + opts.MessageTemplate = "{TokenUserRealName} {TokenUserTypeShortName} {ClientIp} {LocalIP} {Host} {Protocol} {RequestMethod} {RequestPath} {RequestBody} responded {StatusCode} in {Elapsed:0.0000} ms"; opts.EnrichDiagnosticContext = SerilogHelper.EnrichFromRequest; }); diff --git a/IRaCIS.Core.API/_PipelineExtensions/Serilog/SerilogHelper.cs b/IRaCIS.Core.API/_PipelineExtensions/Serilog/SerilogHelper.cs index 1bb30e7bd..6699cb74b 100644 --- a/IRaCIS.Core.API/_PipelineExtensions/Serilog/SerilogHelper.cs +++ b/IRaCIS.Core.API/_PipelineExtensions/Serilog/SerilogHelper.cs @@ -1,4 +1,5 @@ -using IRaCIS.Core.Infrastructure.Extention; +using IRaCIS.Core.Domain.Share; +using IRaCIS.Core.Infrastructure.Extention; using Microsoft.AspNetCore.Http; using Serilog; using System; @@ -41,9 +42,9 @@ namespace IRaCIS.Core.API // Set the content-type of the Response at this point diagnosticContext.Set("ContentType", httpContext.Response.ContentType); - diagnosticContext.Set("TokenUserRealName", httpContext?.User?.FindFirst("realName")?.Value); + diagnosticContext.Set("TokenUserRealName", httpContext?.User?.FindFirst(JwtIRaCISClaimType.RealName)?.Value); - diagnosticContext.Set("TokenUserType", httpContext?.User?.FindFirst("userTypeEnumName")?.Value); + diagnosticContext.Set("TokenUserTypeShortName", httpContext?.User?.FindFirst(JwtIRaCISClaimType.UserTypeShortName)?.Value); // Retrieve the IEndpointFeature selected for the request var endpoint = httpContext.GetEndpoint(); diff --git a/IRaCIS.Core.API/_ServiceExtensions/AutofacModuleSetup.cs b/IRaCIS.Core.API/_ServiceExtensions/AutofacModuleSetup.cs index 9869271d4..6a11b1fb3 100644 --- a/IRaCIS.Core.API/_ServiceExtensions/AutofacModuleSetup.cs +++ b/IRaCIS.Core.API/_ServiceExtensions/AutofacModuleSetup.cs @@ -1,7 +1,6 @@ using Autofac; using Autofac.Extras.DynamicProxy; using IRaCIS.Core.Application; -using IRaCIS.Core.Application.AOP; using IRaCIS.Core.Application.BackGroundJob; using IRaCIS.Core.Infra.EFCore; using Microsoft.AspNetCore.Http; diff --git a/IRaCIS.Core.API/_ServiceExtensions/Serilog/SerilogSetup.cs b/IRaCIS.Core.API/_ServiceExtensions/Serilog/SerilogSetup.cs index a27de1505..6cd35a1ae 100644 --- a/IRaCIS.Core.API/_ServiceExtensions/Serilog/SerilogSetup.cs +++ b/IRaCIS.Core.API/_ServiceExtensions/Serilog/SerilogSetup.cs @@ -26,24 +26,26 @@ namespace IRaCIS.Core.API //控制台 方便调试 问题 我们显示记录日志 时 获取上下文的ip 和用户名 用户类型 .WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Warning, - outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3} ] {LocalIP} {ClientIp} {TokenUserRealName} {TokenUserType} {Message:lj} {Properties:j}{NewLine} {Exception}") + outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {SourceContext:l} || {Message} || {Exception} ||end {NewLine}") + .WriteTo.File($"{AppContext.BaseDirectory}Serilogs/.log", rollingInterval: RollingInterval.Day, - outputTemplate: "{Timestamp:HH:mm:ss} || {Level} || {SourceContext:l} || {Message} ||{Exception} ||end {NewLine}"); + outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {SourceContext:l} || {Message} || {Exception} ||end {NewLine}"); + //.WriteTo.MSSqlServer("Data Source=DESKTOP-4TU9A6M;Initial Catalog=CoreFrame;User ID=sa;Password=123456", "logs", autoCreateSqlTable: true, restrictedToMinimumLevel: LogEventLevel.Information)//从左至右四个参数分别是数据库连接字符串、表名、如果表不存在是否创建、最低等级。Serilog会默认创建一些列。 - if (environment == "Production") - { - config.WriteTo.Email(new EmailConnectionInfo() - { - EmailSubject = "系统警告,请速速查看!",//邮件标题 - FromEmail = "test@extimaging.com",//发件人邮箱 - MailServer = "smtp.qiye.aliyun.com",//smtp服务器地址 - NetworkCredentials = new NetworkCredential("test@extimaging.com", "SHzyyl2021"),//两个参数分别是发件人邮箱与客户端授权码 - Port = 465,//端口号 - ToEmail = "872297557@qq.com"//收件人 - }, restrictedToMinimumLevel: LogEventLevel.Error, - outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [ {Level} {ClientIp} {ClientAgent} {TokenUserRealName} {TokenUserType} ] || [path: {RequestPath} arguments: {RequestBody}] {SourceContext:l} || {Message} || {Exception} ||end {NewLine})"); - } + //if (environment == "Production") + //{ + // config.WriteTo.Email(new EmailConnectionInfo() + // { + // EmailSubject = "系统警告,请速速查看!",//邮件标题 + // FromEmail = "test@extimaging.com",//发件人邮箱 + // MailServer = "smtp.qiye.aliyun.com",//smtp服务器地址 + // NetworkCredentials = new NetworkCredential("test@extimaging.com", "SHzyyl2021"),//两个参数分别是发件人邮箱与客户端授权码 + // Port = 465,//端口号 + // ToEmail = "872297557@qq.com"//收件人 + // }, restrictedToMinimumLevel: LogEventLevel.Error, + // outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [ {Level} {ClientIp} {ClientAgent} {TokenUserRealName} {TokenUserType} ] || [path: {RequestPath} arguments: {RequestBody}] {SourceContext:l} || {Message} || {Exception} ||end {NewLine})"); + //} //扩展方法 获取上下文的ip 用户名 用户类型 Log.Logger = config.Enrich.WithHttpContextInfo(serviceProvider).CreateLogger(); diff --git a/IRaCIS.Core.API/appsettings.Prod_Study.json b/IRaCIS.Core.API/appsettings.Prod_Study.json index accbb9c34..c118bc8eb 100644 --- a/IRaCIS.Core.API/appsettings.Prod_Study.json +++ b/IRaCIS.Core.API/appsettings.Prod_Study.json @@ -6,19 +6,34 @@ "Microsoft.Hosting.Lifetime": "Information" } }, - "AliyunOSS": { - "regionId": "cn-shanghai", - "region": "oss-cn-shanghai", - "endpoint": "https://oss-cn-shanghai.aliyuncs.com", - "accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ", - "accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio", - "bucketName": "zy-sir-store", - "viewEndpoint": "https://zy-sir-cache.oss-cn-shanghai.aliyuncs.com" + "ObjectStoreService": { + "ObjectStoreUse": "AliyunOSS", + "AliyunOSS": { + "regionId": "cn-shanghai", + "endpoint": "https://oss-cn-shanghai.aliyuncs.com", + "accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ", + "accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio", + "bucketName": "zy-sir-store", + "roleArn": "acs:ram::1899121822495495:role/oss-upload", + "viewEndpoint": "https://zy-sir-cache.oss-cn-shanghai.aliyuncs.com", + "region": "oss-cn-shanghai" + }, + + "MinIO": { + "endpoint": "http://192.168.3.68", + "port": "8001", + "useSSL": false, + "accessKey": "IDFkwEpWej0b4DtiuThL", + "secretKey": "Lhuu83yMhVwu7c1SnjvGY6lq74jzpYqifK6Qtj4h", + "bucketName": "test" + } }, "ConnectionStrings": { - "RemoteNew": "Server=47.117.165.18,1434;Database=Prod_Study;User ID=sa;Password=WHxckj@2019;TrustServerCertificate=true", - "Hangfire": "Server=47.117.165.18,1434;Database=Prod_Study.hangfire;User ID=sa;Password=WHxckj@2019;TrustServerCertificate=true" + //"RemoteNew": "Server=47.117.165.18,1434;Database=Prod_Study;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true", + //"Hangfire": "Server=47.117.165.18,1434;Database=Prod_Study_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true", + "RemoteNew": "Server=prod_mssql_standard,1433;Database=Prod_Study;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true", + "Hangfire": "Server=prod_mssql_standard,1433;Database=Prod_Study_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true" }, "BasicSystemConfig": { diff --git a/IRaCIS.Core.API/appsettings.Test_Study.json b/IRaCIS.Core.API/appsettings.Test_Study.json index eb1ea2b23..765da7cfe 100644 --- a/IRaCIS.Core.API/appsettings.Test_Study.json +++ b/IRaCIS.Core.API/appsettings.Test_Study.json @@ -6,18 +6,42 @@ "Microsoft.Hosting.Lifetime": "Information" } }, - "AliyunOSS": { - "regionId": "cn-shanghai", - "region": "oss-cn-shanghai", - "endpoint": "https://oss-cn-shanghai.aliyuncs.com", - "accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ", - "accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio", - "bucketName": "zy-sir-test-store", - "viewEndpoint": "https://zy-sir-test-store.oss-cn-shanghai.aliyuncs.com" + "ObjectStoreService": { + "ObjectStoreUse": "AliyunOSS", + "AliyunOSS": { + "regionId": "cn-shanghai", + "endpoint": "https://oss-cn-shanghai.aliyuncs.com", + "accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ", + "accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio", + "bucketName": "zy-sir-test-store", + "roleArn": "acs:ram::1899121822495495:role/oss-upload", + "viewEndpoint": "https://zy-sir-test-store.oss-cn-shanghai.aliyuncs.com", + "region": "oss-cn-shanghai" + }, + + "MinIO": { + "endPoint": "192.168.3.68", + "port": "8001", + "useSSL": false, + "accessKey": "IDFkwEpWej0b4DtiuThL", + "secretKey": "Lhuu83yMhVwu7c1SnjvGY6lq74jzpYqifK6Qtj4h", + "bucketName": "test", + "viewEndpoint": "http://192.168.3.68:8001/test/" + }, + + "AWS": { + "endPoint": "s3.us-east-1.amazonaws.com", + "useSSL": false, + "accessKey": "AKIAZQ3DRSOHFPJJ6FEU", + "secretKey": "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", + "bucketName": "ei-irc-test-store", + "viewEndpoint": "https://ei-irc-test-store.s3.amazonaws.com/" + } }, + "ConnectionStrings": { - "RemoteNew": "Server=123.56.94.154,1433\\MSSQLSERVER;Database=Test.Study;User ID=sa;Password=dev123456DEV;TrustServerCertificate=true", - "Hangfire": "Server=123.56.94.154,1433\\MSSQLSERVER;Database=Test.Study.hangfire;User ID=sa;Password=dev123456DEV;TrustServerCertificate=true" + "RemoteNew": "Server=123.56.94.154,1435;Database=Test_Study;User ID=sa;Password=xc@123456;TrustServerCertificate=true", + "Hangfire": "Server=123.56.94.154,1435;Database=Test_Study_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true" }, "BasicSystemConfig": { @@ -41,7 +65,7 @@ "FromName": "Test_Study", "AuthorizationCode": "zhanying123", - "SiteUrl": "http://test.study.extimaging.com/login" + "SiteUrl": "http://study.test.extimaging.com/login" } } diff --git a/IRaCIS.Core.API/appsettings.Uat_Study.json b/IRaCIS.Core.API/appsettings.Uat_Study.json index d8e06127f..4a9458ecf 100644 --- a/IRaCIS.Core.API/appsettings.Uat_Study.json +++ b/IRaCIS.Core.API/appsettings.Uat_Study.json @@ -6,14 +6,27 @@ "Microsoft.Hosting.Lifetime": "Information" } }, - "AliyunOSS": { - "regionId": "cn-shanghai", - "region": "oss-cn-shanghai", - "endpoint": "https://oss-cn-shanghai.aliyuncs.com", - "accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ", - "accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio", - "bucketName": "zy-sir-uat-store", - "viewEndpoint": "https://zy-sir-uat-store.oss-cn-shanghai.aliyuncs.com" + "ObjectStoreService": { + "ObjectStoreUse": "AliyunOSS", + "AliyunOSS": { + "regionId": "cn-shanghai", + "endpoint": "https://oss-cn-shanghai.aliyuncs.com", + "accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ", + "accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio", + "bucketName": "zy-sir-uat-store", + "roleArn": "acs:ram::1899121822495495:role/oss-upload", + "viewEndpoint": "https://zy-sir-uat-store.oss-cn-shanghai.aliyuncs.com", + "region": "oss-cn-shanghai" + }, + + "MinIO": { + "endpoint": "http://192.168.3.68", + "port": "8001", + "useSSL": false, + "accessKey": "IDFkwEpWej0b4DtiuThL", + "secretKey": "Lhuu83yMhVwu7c1SnjvGY6lq74jzpYqifK6Qtj4h", + "bucketName": "test" + } }, "ConnectionStrings": { "RemoteNew": "Server=47.117.164.182,1434;Database=Uat.Study;User ID=sa;Password=xc@123456;TrustServerCertificate=true", @@ -40,7 +53,7 @@ "FromEmail": "uat-study@extimaging.com", "FromName": "Uat_Study", "AuthorizationCode": "zhanying123", - "SiteUrl": "http://uat.study.extimaging.com/login" + "SiteUrl": "http://study.uat.extimaging.com/login" } } diff --git a/IRaCIS.Core.API/wwwroot/EmailTemplate/AdminAddUser.html b/IRaCIS.Core.API/wwwroot/EmailTemplate/AdminAddUser.html index ba530acb4..728dde6fc 100644 --- a/IRaCIS.Core.API/wwwroot/EmailTemplate/AdminAddUser.html +++ b/IRaCIS.Core.API/wwwroot/EmailTemplate/AdminAddUser.html @@ -31,7 +31,7 @@
-
祝您顺利!/Best Regards
+
祝您顺利!
展影医疗
diff --git a/IRaCIS.Core.API/wwwroot/EmailTemplate/AdminResetUser.html b/IRaCIS.Core.API/wwwroot/EmailTemplate/AdminResetUser.html index ad1130293..045b2320f 100644 --- a/IRaCIS.Core.API/wwwroot/EmailTemplate/AdminResetUser.html +++ b/IRaCIS.Core.API/wwwroot/EmailTemplate/AdminResetUser.html @@ -28,7 +28,7 @@
-
祝您顺利!/Best Regards
+
祝您顺利!
展影医疗
diff --git a/IRaCIS.Core.API/wwwroot/EmailTemplate/SubjectEnrollConfirmOrPDProgress.html b/IRaCIS.Core.API/wwwroot/EmailTemplate/SubjectEnrollConfirmOrPDProgress.html index 368b1884c..7ba12b97a 100644 --- a/IRaCIS.Core.API/wwwroot/EmailTemplate/SubjectEnrollConfirmOrPDProgress.html +++ b/IRaCIS.Core.API/wwwroot/EmailTemplate/SubjectEnrollConfirmOrPDProgress.html @@ -18,7 +18,7 @@
-
祝您顺利!/Best Regards
+
祝您顺利!
展影医疗
diff --git a/IRaCIS.Core.API/wwwroot/EmailTemplate/SubjectEnrollConfirmOrPDProgress_US.html b/IRaCIS.Core.API/wwwroot/EmailTemplate/SubjectEnrollConfirmOrPDProgress_US.html index 4607c5af2..52fd9841e 100644 --- a/IRaCIS.Core.API/wwwroot/EmailTemplate/SubjectEnrollConfirmOrPDProgress_US.html +++ b/IRaCIS.Core.API/wwwroot/EmailTemplate/SubjectEnrollConfirmOrPDProgress_US.html @@ -14,7 +14,7 @@ Thank you for using our IRC imaging system.
- {0}。 + {0}.
diff --git a/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialDoctorExistJoin.html b/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialDoctorExistJoin.html index 8686d015e..46ea36656 100644 --- a/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialDoctorExistJoin.html +++ b/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialDoctorExistJoin.html @@ -34,12 +34,15 @@ 角色: {5}
- 系统登录地址:{6} + 系统登录地址: + + 点击跳转 +
-
祝您顺利!/Best Regards
+
祝您顺利!
展影医疗
diff --git a/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialDoctorExistJoin_US.html b/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialDoctorExistJoin_US.html index fcea3bd36..5dbc004ee 100644 --- a/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialDoctorExistJoin_US.html +++ b/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialDoctorExistJoin_US.html @@ -34,7 +34,10 @@ Role: {5}
- Login URL: {6} + Login URL: + + click redirect +
diff --git a/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialDoctorFirstJoin.html b/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialDoctorFirstJoin.html index 9f7422603..159216984 100644 --- a/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialDoctorFirstJoin.html +++ b/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialDoctorFirstJoin.html @@ -43,7 +43,7 @@
-
祝您顺利!/Best Regards
+
祝您顺利!
展影医疗
diff --git a/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialSiteSurveyReject.html b/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialSiteSurveyReject.html index a2b8f771c..3c182eddc 100644 --- a/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialSiteSurveyReject.html +++ b/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialSiteSurveyReject.html @@ -40,7 +40,7 @@
-
祝您顺利!/Best Regards
+
祝您顺利!
展影医疗
diff --git a/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialSiteSurveyReject_US.html b/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialSiteSurveyReject_US.html index caa38e3b7..e1a3b132e 100644 --- a/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialSiteSurveyReject_US.html +++ b/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialSiteSurveyReject_US.html @@ -8,7 +8,7 @@
- Dear {0} , + Dear {0} ,
The site survey questionnaire you filled in has been rejected. Details are as follows: diff --git a/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialUserExistJoin.html b/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialUserExistJoin.html index 5020ee521..8a0ae7fe1 100644 --- a/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialUserExistJoin.html +++ b/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialUserExistJoin.html @@ -34,13 +34,16 @@ 角色: {5}
- 系统登录地址:{6} + 系统登录地址: + + 点击跳转 +
-
祝您顺利!/Best Regards
+
祝您顺利!
展影医疗
diff --git a/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialUserExistJoin_US.html b/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialUserExistJoin_US.html index 6be54f794..7a3c19868 100644 --- a/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialUserExistJoin_US.html +++ b/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialUserExistJoin_US.html @@ -34,7 +34,10 @@ Role: {5}
- Login URL: {6} + Login URL: + + click redirect +
diff --git a/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialUserFirstJoin.html b/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialUserFirstJoin.html index 958d8fe83..32b64456d 100644 --- a/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialUserFirstJoin.html +++ b/IRaCIS.Core.API/wwwroot/EmailTemplate/TrialUserFirstJoin.html @@ -43,7 +43,7 @@
-
祝您顺利!/Best Regards
+
祝您顺利!
展影医疗
diff --git a/IRaCIS.Core.API/wwwroot/EmailTemplate/UserOptCommon.html b/IRaCIS.Core.API/wwwroot/EmailTemplate/UserOptCommon.html index d6bfd963e..4a549daa5 100644 --- a/IRaCIS.Core.API/wwwroot/EmailTemplate/UserOptCommon.html +++ b/IRaCIS.Core.API/wwwroot/EmailTemplate/UserOptCommon.html @@ -8,17 +8,17 @@
- 亲爱的用户 , + Hello {0},
感谢您使用展影云平台。
- {0},验证码是: {1},请在3分钟内输入该验证码,进行后续操作。如非本人操作,请忽略该邮件。 + {1},验证码是: {2},请在3分钟内输入该验证码,进行后续操作。如非本人操作,请忽略该邮件。
-
祝您顺利!/Best Regards
+
祝您顺利!
展影医疗
diff --git a/IRaCIS.Core.API/wwwroot/EmailTemplate/UserOptCommon_US.html b/IRaCIS.Core.API/wwwroot/EmailTemplate/UserOptCommon_US.html index 94ee774f1..1ebc451a8 100644 --- a/IRaCIS.Core.API/wwwroot/EmailTemplate/UserOptCommon_US.html +++ b/IRaCIS.Core.API/wwwroot/EmailTemplate/UserOptCommon_US.html @@ -8,13 +8,13 @@
- Dear Sir or Madam: + Hello {0},
Thank you for using our imaging system.
- {0}, the verification code is {1}. Please enter this code within 3 minutes for follow-up operations. + {1}, the verification code is {2}. Please enter this code within 3 minutes for follow-up operations.
If you are not the intended person, please ignore this email. diff --git a/IRaCIS.Core.Application/AOP/AsyncInterceptor.cs b/IRaCIS.Core.Application/AOP/AsyncInterceptor.cs deleted file mode 100644 index d08f1649f..000000000 --- a/IRaCIS.Core.Application/AOP/AsyncInterceptor.cs +++ /dev/null @@ -1,97 +0,0 @@ -using Castle.DynamicProxy; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; - -namespace IRaCIS.Core.Application.AOP -{ - public abstract class AsyncInterceptorBase : IInterceptor - { - public AsyncInterceptorBase() - { - } - - public void Intercept(IInvocation invocation) - { - BeforeProceed(invocation); - invocation.Proceed(); - if (IsAsyncMethod(invocation.MethodInvocationTarget)) - { - invocation.ReturnValue = InterceptAsync((dynamic)invocation.ReturnValue, invocation); - } - else - { - AfterProceedSync(invocation); - } - } - - private bool CheckMethodReturnTypeIsTaskType(MethodInfo method) - { - var methodReturnType = method.ReturnType; - if (methodReturnType.IsGenericType) - { - if (methodReturnType.GetGenericTypeDefinition() == typeof(Task<>) || - methodReturnType.GetGenericTypeDefinition() == typeof(ValueTask<>)) - return true; - } - else - { - if (methodReturnType == typeof(Task) || - methodReturnType == typeof(ValueTask)) - return true; - } - return false; - } - - private bool IsAsyncMethod(MethodInfo method) - { - bool isDefAsync = Attribute.IsDefined(method, typeof(AsyncStateMachineAttribute), false); - bool isTaskType = CheckMethodReturnTypeIsTaskType(method); - bool isAsync = isDefAsync && isTaskType; - - return isAsync; - } - - protected object ProceedAsyncResult { get; set; } - - - private async Task InterceptAsync(Task task, IInvocation invocation) - { - await task.ConfigureAwait(false); - await AfterProceedAsync(invocation, false); - } - - private async Task InterceptAsync(Task task, IInvocation invocation) - { - ProceedAsyncResult = await task.ConfigureAwait(false); - await AfterProceedAsync(invocation, true); - return (TResult)ProceedAsyncResult; - } - - private async ValueTask InterceptAsync(ValueTask task, IInvocation invocation) - { - await task.ConfigureAwait(false); - await AfterProceedAsync(invocation, false); - } - - private async ValueTask InterceptAsync(ValueTask task, IInvocation invocation) - { - ProceedAsyncResult = await task.ConfigureAwait(false); - await AfterProceedAsync(invocation, true); - return (TResult)ProceedAsyncResult; - } - - protected virtual void BeforeProceed(IInvocation invocation) { } - - protected virtual void AfterProceedSync(IInvocation invocation) { } - - protected virtual Task AfterProceedAsync(IInvocation invocation, bool hasAsynResult) - { - return Task.CompletedTask; - } - } -} diff --git a/IRaCIS.Core.Application/AOP/QANoticeAOP.cs b/IRaCIS.Core.Application/AOP/QANoticeAOP.cs deleted file mode 100644 index 0e80ae3a4..000000000 --- a/IRaCIS.Core.Application/AOP/QANoticeAOP.cs +++ /dev/null @@ -1,499 +0,0 @@ -//using System; -//using Castle.DynamicProxy; -//using IRaCIS.Core.Application.Contracts.Dicom.DTO; -//using IRaCIS.Core.Infra.EFCore; - -//using System.Linq; -//using IRaCIS.Core.Domain.Models; -//using IRaCIS.Core.Domain.Share; - -//namespace IRaCIS.Core.API.Utility.AOP -//{ -//#pragma warning disable -// public class QANoticeAOP : IInterceptor -// { -// private readonly IRepository _qaNoticeRepository; - -// private readonly IRepository _studyRepository; -// private readonly IRepository _userTrialRepository; -// private readonly IRepository _userTrialSiteRepository; -// private readonly IUserInfo _userInfo; - -// public QANoticeAOP(IRepository qaNoticeRepository, -// IUserInfo userInfo, IRepository studyRepository, IRepository userTrialRepository, IRepository userTrialSiteRepository) -// { -// _qaNoticeRepository = qaNoticeRepository; - -// _studyRepository = studyRepository; -// _userTrialRepository = userTrialRepository; -// _userTrialSiteRepository = userTrialSiteRepository; -// _userInfo = userInfo; -// } - -// public void Intercept(IInvocation invocation) -// { -// //处理拦截的方法 -// invocation.Proceed(); - -// if (invocation.Method.Name == "UpdateStudyStatus") -// { -// var studyStatus = invocation.Arguments[0] as StudyStatusDetailCommand; - -// var study = _studyRepository.FirstOrDefault(t=>t.Id==studyStatus.StudyId); - - -// if (study.Status == (int)StudyStatus.Uploaded) -// { -// _qaNoticeRepository.Add(new QANotice() -// { -// TrialId = study.TrialId, -// SubjectVisitId = study.Id, -// FromUser = _userInfo.RealName, -// FromUserId = _userInfo.Id, -// FromUserType = _userInfo.UserTypeShortName, - -// NoticeTypeEnum = NoticeType.NotNeedNotice, -// NeedDeal = false, -// StudyStatusStr = "Uploaded", -// Message = $"CRC : {_userInfo.RealName} has uploaded {study.StudyCode} ", -// SendTime = DateTime.Now, -// }); -// } - -// #region 处理QA通知模块 - -// //查询项目的参与者 和 负责site下CRC用户 -// var trialUserList = _userTrialRepository.Where(t => t.TrialId == study.TrialId).ToList(); - -// // 找到该study 关联Site 下的CRC - -// var crcList = _userTrialSiteRepository.Where(t => -// t.SiteId == study.SiteId && t.User.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator && t.TrialId == study.TrialId).ToList(); - - -// var qaList = trialUserList.Where(t => t.User.UserTypeEnum == UserTypeEnum.IQC).ToList(); - -// var pm = trialUserList.FirstOrDefault(t => t.User.UserTypeEnum == UserTypeEnum.ProjectManager); - - - - -// // CRC =>QA -// if (studyStatus.Status == (int)StudyStatus.QARequested) -// { -// //找出当前操作的CRC -// //PM 或者admin可以代替CRC角色 不能从CRC列表中查询用户 -// //var currentCRC = trialUserList.First(t => t.UserId == _userInfo.Id); - -// var notice = new QANotice() -// { -// TrialId = study.TrialId, -// SubjectVisitId = study.Id, -// FromUser = _userInfo.RealName, -// FromUserId = _userInfo.Id, -// FromUserType = _userInfo.UserTypeShortName, - -// //FromUser = currentCRC.UserRealName, -// //FromUserId = _userInfo.Id, -// //FromUserType = currentCRC.UserType, -// NoticeTypeEnum = NoticeType.CRC_RequestToQA_NoticeQA, -// NeedDeal = true, -// StudyStatusStr = "QA Requested", -// Message = -// $"CRC -> QA : {_userInfo.RealName} request QA {study.StudyCode} , Inquiry can be performed! ", -// SendTime = DateTime.Now, -// }; - -// qaList.ForEach(t => notice.QANoticeUserList.Add(new QANoticeUser() -// { -// QANoticeId = notice.Id, -// SubjectVisitId = study.Id, -// ToUser = t.User.LastName + " / " + t.User.FirstName, -// ToUserId = t.UserId, -// ToUserType = t.User.UserTypeRole.UserTypeShortName -// })); - -// _qaNoticeRepository.Add(notice); - -// //DealRequestToQA(study.Id); - -// var needDealNoticeList = _qaNoticeRepository.AsQueryable() -// .Where(t => t.SubjectVisitId == study.Id && t.NeedDeal && t.NoticeTypeEnum == NoticeType.CRC_RequestToQA_NoticeQA).ToList(); - -// needDealNoticeList.ForEach(t => -// { -// t.NeedDeal = false; -// t.DealTime = DateTime.Now; -// _qaNoticeRepository.Update(t); -// }); -// } - -// // QA =>CRC 向CRC推送消息影像有问题 同时作为 requestToQA 的边界 -// else if (studyStatus.Status == (int)StudyStatus.QAing) -// { -// //找出当前操作的QA 如果是pm 或者admin 代替操作 此时会有问题 所以 谁代替,就以谁的名义执行 -// //var currentQA = qaList.First(t => t.UserId == _userInfo.Id); -// //var currentQA = trialUserList.First(t => t.UserId == _userInfo.Id); - -// //在项目CRC列表中筛选出 负责该study关联 site的CRC -// var siteCRCList = _userTrialSiteRepository.Where(t => -// t.SiteId == study.SiteId && t.User.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator && t.TrialId == study.TrialId).ToList(); - -// //查询项目的参与者 和 负责site下CRC用户 - - - -// var notice = new QANotice() -// { -// TrialId = study.TrialId, -// SubjectVisitId = study.Id, -// //FromUser = currentQA.UserRealName, -// //FromUserId = _userInfo.Id, -// //FromUserType = currentQA.UserType, -// FromUser = _userInfo.RealName, -// FromUserId = _userInfo.Id, -// FromUserType = _userInfo.UserTypeShortName, -// NoticeTypeEnum = NoticeType.QA_InQA_NoticeCRC, -// NeedDeal = true, -// StudyStatusStr = "In QA", -// Message = $"QA -> CRC : {_userInfo.RealName} inquiry {study.StudyCode} ", -// SendTime = DateTime.Now, -// }; - -// siteCRCList.ForEach(t => notice.QANoticeUserList.Add(new QANoticeUser() -// { -// QANoticeId = notice.Id, -// SubjectVisitId = study.Id, -// ToUser = t.User.LastName + " / " + t.User.FirstName, -// ToUserId = t.UserId, -// ToUserType = t.UserTypeRole.UserTypeShortName -// })); - -// //添加 发送给CRC的消息 消息和CRC是 一对多 -// _qaNoticeRepository.Add(notice); - - -// //处理 消息 标记已处理 -// var needDealNoticeList = _qaNoticeRepository.AsQueryable() -// .Where(t => t.SubjectVisitId == study.Id && t.NeedDeal && -// (t.NoticeTypeEnum == NoticeType.CRC_RequestToQA_NoticeQA || -// t.NoticeTypeEnum == NoticeType.CRC_ReUpload_NoticeQA || -// t.NoticeTypeEnum == NoticeType.CRC_QARecordDialogPost_NoticeQA)).ToList(); - -// needDealNoticeList.ForEach(t => -// { -// t.NeedDeal = false; -// t.DealTime = DateTime.Now; -// _qaNoticeRepository.Update(t); -// }); - - -// } -// // QA =>QA 给自己的消息 通知需要匿名化 同时作为 requestToQA 的边界 -// else if (studyStatus.Status == (int)StudyStatus.QAFinish) -// { - -// //找出当前操作的QA 如果是pm 或者admin 代替操作 此时会有问题 所以 谁代替,就以谁的名义执行 -// //var currentQA = qaList.First(t => t.UserId == _userInfo.Id); -// //var currentQA = trialUserList.First(t => t.UserId == _userInfo.Id); - -// //发送给当前项目QA列表 - -// var notice = new QANotice() -// { -// TrialId = study.TrialId, -// SubjectVisitId = study.Id, -// //FromUser = currentQA.UserRealName, -// //FromUserId = _userInfo.Id, -// //FromUserType = currentQA.UserType, -// FromUser = _userInfo.RealName, -// FromUserId = _userInfo.Id, -// FromUserType = _userInfo.UserTypeShortName, -// NoticeTypeEnum = NoticeType.QA_QAPass_NoticeQA, -// NeedDeal = true, -// StudyStatusStr = "QA-Passed", -// Message = -// $"QA -> QA : {_userInfo.RealName} inquiry {study.StudyCode} finished,Anonymization can be performed!", -// SendTime = DateTime.Now, -// }; - -// qaList.ForEach(t => notice.QANoticeUserList.Add(new QANoticeUser() -// { -// QANoticeId = notice.Id, -// SubjectVisitId = study.Id, -// ToUser = t.User.LastName+" / "+t.User.FirstName, -// ToUserId = t.UserId, -// ToUserType = t.User.UserTypeRole.UserTypeShortName -// })); - -// _qaNoticeRepository.Add(notice); - -// //处理 消息 标记已处理 存在意外情况 qa发给CRC的 但是qa里面设置了 通过或者不通过 此时qa发送的消息也设置为已处理 -// var needDealNoticeList = _qaNoticeRepository.AsQueryable() -// .Where(t => t.SubjectVisitId == study.Id && t.NeedDeal && -// (t.NoticeTypeEnum == NoticeType.CRC_RequestToQA_NoticeQA || -// t.NoticeTypeEnum == NoticeType.CRC_ReUpload_NoticeQA || -// t.NoticeTypeEnum == NoticeType.CRC_QARecordDialogPost_NoticeQA || - -// t.NoticeTypeEnum == NoticeType.QA_QARecordDialogPost_NoticeCRC || -// t.NoticeTypeEnum == NoticeType.QA_InQA_NoticeCRC || -// t.NoticeTypeEnum == NoticeType.QA_AddQARecord_NoticeCRC)).ToList(); - -// needDealNoticeList.ForEach(t => -// { -// t.NeedDeal = false; -// t.DealTime = DateTime.Now; -// _qaNoticeRepository.Update(t); -// }); - - -// } -// // QA =>CRC 暂时不用发送消息给CRC 因为CRC 暂时没有入口回复 同时作为 requestToQA 的边界 -// else if (studyStatus.Status == (int)StudyStatus.QAFInishNotPass) -// { - -// _qaNoticeRepository.Add(new QANotice() -// { -// TrialId = study.TrialId, -// SubjectVisitId = study.Id, -// FromUser = _userInfo.RealName, -// FromUserId = _userInfo.Id, -// FromUserType = _userInfo.UserTypeShortName, -// NoticeTypeEnum = NoticeType.NotNeedNotice, -// NeedDeal = false, -// StudyStatusStr = "QA-Failed", -// Message = $"QA : {_userInfo.RealName} set {study.StudyCode} QA-Failed !", -// SendTime = DateTime.Now, -// }); - -// //处理 消息 标记已处理 -// var needDealNoticeList = _qaNoticeRepository.AsQueryable() -// .Where(t => t.SubjectVisitId == study.Id && t.NeedDeal && -// (t.NoticeTypeEnum == NoticeType.CRC_RequestToQA_NoticeQA || -// t.NoticeTypeEnum == NoticeType.CRC_ReUpload_NoticeQA || -// t.NoticeTypeEnum == NoticeType.CRC_QARecordDialogPost_NoticeQA || - - -// t.NoticeTypeEnum == NoticeType.QA_QARecordDialogPost_NoticeCRC || -// t.NoticeTypeEnum == NoticeType.QA_InQA_NoticeCRC || -// t.NoticeTypeEnum == NoticeType.QA_AddQARecord_NoticeCRC)).ToList(); - -// needDealNoticeList.ForEach(t => -// { -// t.NeedDeal = false; -// t.DealTime = DateTime.Now; -// _qaNoticeRepository.Update(t); -// }); -// } - -// #endregion - - -// } - -// else if (invocation.Method.Name == "ReUploadSameStudy") -// { -// var studyId = Guid.Parse(invocation.Arguments[0].ToString()); - -// var study = _studyRepository.FirstOrDefault(t => t.Id == studyId); -// var status = study.Status; - -// //处理CRC 重传时 QA消息 - -// if (status == (int)StudyStatus.QAing) -// { -// //查询项目的参与者 和 负责site下CRC用户 -// var trialUserList = _userTrialRepository.Where(t => t.TrialId == study.TrialId).ToList(); - -// // 找到该study 关联Site 下的CRC - -// var crcList = _userTrialSiteRepository.Where(t => -// t.SiteId == study.SiteId && t.User.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator && t.TrialId == study.TrialId).ToList(); - -// var qaList = trialUserList.Where(t => t.User.UserTypeEnum == UserTypeEnum.IQC).ToList(); - -// //CRC =>QA CRC的职能被PM 或者admin代替 -// //if (_userInfo.UserTypeEnumInt == (int)UserType.ClinicalResearchCoordinator) -// { -// //PM 或者admin可以代替CRC角色 不能从CRC列表中查询用户 -// //var currentCRC = trialUserList.First(t => t.UserId == _userInfo.Id); - -// var notice = new QANotice() -// { -// TrialId = study.TrialId, -// SubjectVisitId = study.Id, -// //FromUser = currentCRC.UserRealName, -// //FromUserId = _userInfo.Id, -// //FromUserType = currentCRC.UserType, -// FromUser = _userInfo.RealName, -// FromUserId = _userInfo.Id, -// FromUserType = _userInfo.UserTypeShortName, -// NoticeTypeEnum = NoticeType.CRC_ReUpload_NoticeQA, -// NeedDeal = true, -// Message = $"CRC -> QA :{_userInfo.RealName} has reuploaded {study.StudyCode} , Need to be inquiry again", -// SendTime = DateTime.Now -// }; - -// qaList.ForEach(t => notice.QANoticeUserList.Add(new QANoticeUser() -// { -// QANoticeId = notice.Id, -// SubjectVisitId = study.Id, -// ToUser = t.User.LastName+" / "+t.User.FirstName, -// ToUserId = t.UserId, -// ToUserType = t.User.UserTypeRole.UserTypeShortName -// })); - -// _qaNoticeRepository.Add(notice); - -// //这里作为 QA 设置 Inqa 状态的回复 或者QA和CRC对话的 -// var needDealNoticeList = _qaNoticeRepository.Where(t => t.SubjectVisitId == study.Id && t.NeedDeal -// && (t.NoticeTypeEnum == NoticeType.QA_InQA_NoticeCRC || t.NoticeTypeEnum == NoticeType.QA_QARecordDialogPost_NoticeCRC)) -// .ToList(); - -// needDealNoticeList.ForEach(t => -// { -// t.NeedDeal = false; -// t.DealTime = DateTime.Now; -// _qaNoticeRepository.Update(t); -// }); - -// } -// } -// else -// { -// //不是QAing 的重传 不发送qa消息 -// return; -// } - - - -// } - -// else if (invocation.Method.Name == "DicomAnonymize") -// { -// var studyId = Guid.Parse(invocation.Arguments[0].ToString()); - -// var study = _studyRepository.FirstOrDefault(t => t.Id == studyId); - -// #region 处理QA通知 匿名化完毕 通知PM - -// //查询项目的参与者 和 负责site下CRC用户 -// var trialUserList = _userTrialRepository.Where(t => t.TrialId == study.TrialId).ToList(); - -// // 找到该study 关联Site 下的CRC - -// var crcList = _userTrialSiteRepository.Where(t => -// t.SiteId == study.SiteId && t.User.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator && t.TrialId == study.TrialId).ToList(); - -// var qaList = trialUserList.Where(t => t.User.UserTypeEnum == UserTypeEnum.IQC).ToList(); - -// // -// var pm = trialUserList.FirstOrDefault(t => t.User.UserTypeEnum == UserTypeEnum.ProjectManager); - - -// //找出当前操作的QA 如果是pm 或者admin 代替操作 此时会有问题 所以 谁代替,就以谁的名义执行 -// //var currentQA = trialUserList.First(t => -// // t.UserTypeEnum == UserType.IQC && t.UserId == _userInfo.Id); -// //var currentQA = trialUserList.First(t => t.UserId == _userInfo.Id); - -// var notice = new QANotice() -// { -// TrialId = study.TrialId, -// SubjectVisitId = study.Id, -// //FromUser = currentQA.UserRealName, -// //FromUserId = _userInfo.Id, -// //FromUserType = currentQA.UserType, -// FromUser = _userInfo.RealName, -// FromUserId = _userInfo.Id, -// FromUserType = _userInfo.UserTypeShortName, -// NoticeTypeEnum = NoticeType.QA_Anonymized_NoticeQA, -// NeedDeal = true, -// StudyStatusStr = "Anonymized", -// //Message = $"QA -> PM :{_userInfo.RealName} has anonymized {study.StudyCode} ,Forward can be performed!!", -// Message = $"QA -> QA :{_userInfo.RealName} has anonymized {study.StudyCode} ,Forward can be performed!!", - -// SendTime = DateTime.Now, - -// }; - -// //notice.QANoticeUserList.Add(new QANoticeUser() -// //{ -// // QANoticeId = notice.Id, -// // StudyId = study.Id, -// // ToUser = pm.UserRealName, -// // ToUserId = pm.UserId, -// // ToUserType = pm.UserType -// //}); - -// qaList.ForEach(t => notice.QANoticeUserList.Add(new QANoticeUser() -// { -// QANoticeId = notice.Id, -// SubjectVisitId = study.Id, -// ToUser = t.User.LastName+" / "+t.User.FirstName, -// ToUserId = t.UserId, -// ToUserType = t.User.UserTypeRole.UserTypeShortName -// })); - -// _qaNoticeRepository.Add(notice); - -// var needDealNoticeList = _qaNoticeRepository.AsQueryable() -// .Where(t => t.SubjectVisitId == study.Id && t.NeedDeal && (t.NoticeTypeEnum == NoticeType.QA_QAPass_NoticeQA)).ToList(); - -// needDealNoticeList.ForEach(t => -// { -// t.NeedDeal = false; -// t.DealTime = DateTime.Now; -// _qaNoticeRepository.Update(t); -// }); - - -// #endregion -// } - -// else if (invocation.Method.Name == "ForwardStudy") -// { -// var studyId = Guid.Parse(invocation.Arguments[0].ToString()); - -// var study = _studyRepository.FirstOrDefault(t => t.Id == studyId); - -// //匿名化操作产生的消息 设置为已经处理 -// _qaNoticeRepository.Add(new QANotice() -// { -// TrialId = study.TrialId, -// SubjectVisitId = study.Id, -// //FromUser = currentQA.UserRealName, -// //FromUserId = _userInfo.Id, -// //FromUserType = currentQA.UserType, -// FromUser = _userInfo.RealName, -// FromUserId = _userInfo.Id, -// FromUserType = _userInfo.UserTypeShortName, -// NoticeTypeEnum = NoticeType.NotNeedNotice, -// NeedDeal = false, -// StudyStatusStr = "Forwarded", -// //Message = $"PM :{_userInfo.RealName} has forwarded {study.StudyCode} !", -// Message = $"QA :{_userInfo.RealName} has forwarded {study.StudyCode} !", -// SendTime = DateTime.Now, -// }); - -// var needDealList = _qaNoticeRepository.Where(t => -// t.SubjectVisitId == study.Id && t.NeedDeal && t.NoticeTypeEnum == NoticeType.QA_Anonymized_NoticeQA).ToList(); - -// needDealList.ForEach(t => -// { -// t.NeedDeal = false; -// t.DealTime = DateTime.Now; -// _qaNoticeRepository.Update(t); -// }); -// } - -// var success = _qaNoticeRepository.SaveChanges(); - -// if (!success) -// { -// throw new Exception("Send QA message failed"); -// } -// } - - -// } -//} \ No newline at end of file diff --git a/IRaCIS.Core.Application/AOP/TrialStatusAutofacAOP.cs b/IRaCIS.Core.Application/AOP/TrialStatusAutofacAOP.cs deleted file mode 100644 index e1523b6d9..000000000 --- a/IRaCIS.Core.Application/AOP/TrialStatusAutofacAOP.cs +++ /dev/null @@ -1,89 +0,0 @@ -using Castle.DynamicProxy; -using EasyCaching.Core; -using IRaCIS.Application.Contracts; -using IRaCIS.Core.Domain.Share; - -namespace IRaCIS.Core.Application.AOP -{ - public class TrialStatusAutofacAOP : IAsyncInterceptor - { - private readonly IEasyCachingProvider _provider; - - public TrialStatusAutofacAOP(IEasyCachingProvider provider) - { - _provider = provider; - } - - - - public void InterceptAsynchronous(IInvocation invocation) - { - invocation.Proceed(); - } - - //这里AOP 处理两个方法 分别是 项目的添加和更新、项目状态的变更 - - public void InterceptAsynchronous(IInvocation invocation) - { - - - //处理拦截的方法 - invocation.Proceed(); - - - - dynamic result = invocation.ReturnValue; - - //接口成功了,才修改缓存 - if (!result.IsSuccess) - { - return; - } - - #region 处理项目列表的查询 在前端界面已经在某个界面,但是服务器重置了,此时没有缓存项目信息,接口不能正确返回,因故采用,启动时查询,每天查询一次,缓存一天,然后项目添加、更改状态时,及时更新 - - //if (invocation.Method.Name == "GetTrialList") - //{ - // //在此 将当前查询的项目Id 和对应的项目状态进行缓存 - // dynamic result = invocation.ReturnValue; - // foreach (var item in result.CurrentPageData) - // { - // _provider.Remove(item.Id.ToString()); - // _provider.Set(item.Id.ToString(), item.TrialStatusStr.ToString(), TimeSpan.FromDays(1)); - // } - //} - - #endregion - - if (invocation.Method.Name == "AddOrUpdateTrial") - { - //如果是添加 那么将对应的初始状态加进去 更新状态是单独操作的 - - var trialModel = (invocation.Arguments[0] as TrialCommand).IfNullThrowConvertException(); - if (trialModel.Id == null || trialModel.Id == Guid.Empty) - { - _provider.Set(result.Data.Id.ToString(), StaticData.TrialState.TrialOngoing, TimeSpan.FromDays(1)); - } - - - } - // 更新缓存 - else if (invocation.Method.Name == "UpdateTrialStatus") - { - //项目状态更新,也需要及时更新 - _provider.Set(invocation.Arguments[0].ToString(), invocation.Arguments[1].ToString(), TimeSpan.FromDays(1)); - - ////Test参数是否符合要求 - //var tt = invocation.Arguments[0].ToString(); - //var cc = _provider.Get(invocation.Arguments[0].ToString()); - - } - - } - - public void InterceptSynchronous(IInvocation invocation) - { - invocation.Proceed(); - } - } -} \ No newline at end of file diff --git a/IRaCIS.Core.Application/BusinessFilter/LogActionFilter.cs b/IRaCIS.Core.Application/BusinessFilter/LogActionFilter.cs deleted file mode 100644 index 64f11585b..000000000 --- a/IRaCIS.Core.Application/BusinessFilter/LogActionFilter.cs +++ /dev/null @@ -1,81 +0,0 @@ -//using System.Diagnostics; -//using IRaCIS.Application.Interfaces; -//using IRaCIS.Application.Contracts; -//using IRaCIS.Core.Infra.EFCore; -//using IRaCIS.Core.Infrastructure.Extention; -//using Microsoft.AspNetCore.Mvc; -//using Microsoft.AspNetCore.Mvc.Filters; -//using Microsoft.Extensions.Logging; -//using Newtonsoft.Json; - -//namespace IRaCIS.Core.Application.Filter -//{ - -// [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] -// public class LogFilter : Attribute -// { -// } -// public class LogActionFilter : IAsyncActionFilter -// { -// private readonly ILogService _logService; -// private readonly IUserInfo _userInfo; -// private readonly ILogger _logger; - -// public LogActionFilter(ILogService logService, IUserInfo userInfo , ILogger logger) -// { -// _logService = logService; -// _userInfo = userInfo; -// _logger = logger; -// } - -// public Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) -// { - -// if (context.ActionDescriptor.EndpointMetadata!=null&& context.ActionDescriptor.EndpointMetadata.Any(m => m.GetType() == typeof(LogFilter))) -// { -// return LogAsync(context, next); -// } -// return next(); -// } - -// public async Task LogAsync(ActionExecutingContext context, ActionExecutionDelegate next) -// { -// var sw = new Stopwatch(); -// sw.Start(); - -// dynamic actionResult = (await next()).Result; -// sw.Stop(); -// var args = JsonConvert.SerializeObject(context.ActionArguments); -// var result = JsonConvert.SerializeObject(actionResult?.Value); - -// var attr = (ApiExplorerSettingsAttribute)context.ActionDescriptor.EndpointMetadata.FirstOrDefault(m => m.GetType() == typeof(ApiExplorerSettingsAttribute)); -// var groupName = attr?.GroupName; -// var res = actionResult?.Value as IResponseOutput; -// var input = new SystemLogDTO -// { -// ClientIP = string.Empty, -// OptUserId = _userInfo.Id, -// OptUserName = _userInfo.UserName, -// ApiPath = context.ActionDescriptor.AttributeRouteInfo.Template.ToLower(), -// Params = args, -// Result = result, -// RequestTime = DateTime.Now, -// ElapsedMilliseconds = sw.ElapsedMilliseconds, -// Status =res?.IsSuccess?? false, -// Message = res?.ErrorMessage, -// LogCategory = groupName -// }; - -// try -// { -// _logService.SaveLog2Db(input); -// } -// catch (Exception ex) -// { - -// _logger.LogError(ex.Message); -// } - -// } -// } -//} diff --git a/IRaCIS.Core.Application/BusinessFilter/TrialAuditFilter.cs b/IRaCIS.Core.Application/BusinessFilter/TrialAuditFilter.cs deleted file mode 100644 index a614a1e6d..000000000 --- a/IRaCIS.Core.Application/BusinessFilter/TrialAuditFilter.cs +++ /dev/null @@ -1,1575 +0,0 @@ -//using IRaCIS.Application.Contracts; -//using IRaCIS.Core.Application.Contracts.Dicom.DTO; -//using IRaCIS.Core.Application.Contracts.DTO; -//using IRaCIS.Core.Infra.EFCore; -//using IRaCIS.Core.Domain.Models; -//using IRaCIS.Core.Domain.Share; -//using IRaCIS.Core.Infrastructure.Extention; -//using Microsoft.AspNetCore.Mvc.Filters; -//using Microsoft.EntityFrameworkCore; -//using Microsoft.Extensions.Logging; -//using IRaCIS.Core.Infrastructure; -//using IRaCIS.Core.Application.Contracts; - -//namespace IRaCIS.Core.Application.Filter -//{ -//#pragma warning disable CS8618 - -//#pragma warning disable CS8062 -// //by zhouhang 2021.08 - - -//审计类型大类 -using Microsoft.AspNetCore.Mvc.Filters; - -public enum AuditType -{ - TrialAudit = 0, - SubjectAudit = 1, - StudyAudit = 2 -} - -//具体审计操作 -public enum AuditOptType -{ - //DeleteTrial = 2, - AddOrUpdateTrial = 0, - - AddTrialSiteSurvey = 1, - - //参与人员 - AddTrialStaff = 3, - DeleteTrailStaff = 4, - - //Site - AddTrialSite = 5, - DeleteTrialSite = 6, - - //Site CRC - AddTrialSiteCRC = 7, - DeleteTrialSiteCRC = 8, - - //访视计划 - AddOrUpdateTrialVisitPlanItem = 9, - DeleteTrialVisitPlanItem = 10, - ConfirmTrialVisitPlan = 11, - - //项目模板 - AddOrUpdateTrialTemplate = 12, - DeleteTrialTemplate = 13, - - //subject 访视计划 - AddOrUpdateSubjectOutPlanVisit = 14, - DeleteSubjectOutPlanVisit = 15, - SetSVExecuted = 16, - - AddOrUpdateSubject = 17, - DeleteSubject = 18, - - //影像上传 - UploadImage = 19, - - //变更QA状态 比如设置为QA中 QA结束通过、不通过 - ChangeStudyStatus = 20, - - //匿名化 - Anonymized = 22, - - //转发 - Forwarded = 24 -} - -[AttributeUsage(AttributeTargets.Method)] -public class TrialAuditAttribute : Attribute,/*IActionFilter, */IAsyncActionFilter -{ - private readonly AuditType _auditType; - private readonly AuditOptType _auditOptType; - public TrialAuditAttribute(AuditType auditType, AuditOptType auditOptType) - { - _auditType = auditType; - _auditOptType = auditOptType; - } - public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) - { - await next(); - - } -} - -// [AttributeUsage(AttributeTargets.Method)] -// public class TrialAuditAttribute : Attribute,/*IActionFilter, */IAsyncActionFilter -// { -// private readonly AuditType _auditType; -// private readonly AuditOptType _auditOptType; -// public IDictionary _actionArguments; - -// #region 根据不同接口构造的属性 - -// private TrialAuditAttribute _attr; - -// private string _userIdStr; - -// private string _userRealName; - -// private IRepository _auditRepository; - -// private TrialUser _userTrial; - -// private TrialSiteUser _userTrialSite; - -// private VisitStage _visitPlan; - -// //private QATrialTemplate _qATrailTemplate; - -// private Subject _subject; - -// private SubjectVisit _subjectVisit; - -// private TrialSite _trialSite; - -// private DicomStudy _study; - -// private IRepository _studyRepository; - -// //private IRaCISDBContext _dbContext; - -// //private IDbContextTransaction transaction; - - -// #endregion - -// public TrialAuditAttribute(AuditType auditType, AuditOptType auditOptType) -// { -// _auditType = auditType; -// _auditOptType = auditOptType; -// } - - -// #region 同步版本 废弃 - -// //public void OnActionExecuted(ActionExecutedContext executedcontext) -// //{ - -// // //上传影像接口返回值类型特殊 需要单独处理 -// // if (_attr._auditOptType == AuditOptType.UploadImage) -// // { -// // //接口参数 -// // var archiveStudyInfo = (ArchiveStudyCommand)_actionArguments.Values.ToList()[0]; - -// // //接口返回结果 因为上传成功和不成功 泛型类型不一样 -// // dynamic archive = executedcontext.Result; -// // if (archive == null) -// // { -// // var logger = (ILogger)executedcontext.HttpContext.RequestServices.GetService( -// // typeof(ILogger)); - -// // logger.LogError("影像上传,OnActionExecuted Reuslt 为null"); -// // return; -// // } -// // var archiveResult = (IResponseOutput)archive.Value; - - - -// // if (archiveResult.IsSuccess) -// // { -// // _studyRepository = (IRepository)executedcontext.HttpContext.RequestServices.GetService( -// // typeof(IRepository)); - -// // var successResult = (IResponseOutput)archiveResult; - -// // _study = _studyRepository.GetAll().First(t => -// // t.Id == successResult.Data.ArchivedDicomStudies.ToList()[0].Id); - -// // _auditRepository.Add(new TrialAudit() -// // { -// // TrialId = _study.TrialId, -// // SubjectId = _study.SubjectId, -// // StudyId = _study.Id, -// // AuditType = (int)AuditType.StudyAudit, -// // Note = $"{ _userRealName} 动作变更了 { _study.StudyCode} 检查状态为 {DealStudyStatus(_study.Status)} ", -// // Detail = string.Empty, -// // OptUserId = Guid.Parse(_userIdStr), -// // OptUser = _userRealName, -// // OptTime = DateTime.Now -// // }); - -// // _auditRepository.SaveChanges(); -// // } - -// // return; -// // } - -// // //接口返回结果 -// // dynamic actionResult = executedcontext.Result; -// // var result = (IResponseOutput)actionResult.Value;//此处审计只涉及到添加更新和删除, 统一了相关接口的返回结果,才能在此强制转换 - - - -// // switch (_attr._auditType) -// // { -// // //项目审计 -// // case AuditType.TrialAudit: - -// // switch (_attr._auditOptType) -// // { -// // //项目的添加和更新接口 -// // case AuditOptType.AddOrUpdateTrial: - -// // //接口参数 -// // var trialInfo = (TrialCommand)_actionArguments.Values.ToList()[0]; - -// // if (result.IsSuccess) -// // { -// // _auditRepository.Add(new TrialAudit() -// // { -// // //判断是添加还是更新 -// // TrialId = trialInfo.Id == null ? Guid.Parse(result.Data) : trialInfo.Id.Value, -// // SubjectId = Guid.Empty, -// // AuditType = (int)AuditType.TrialAudit, -// // Note = trialInfo.Id == null ? $"{ _userRealName} 添加了项目 {trialInfo.Code} " : $"{ _userRealName} 更新了项目 {trialInfo.Code} 基本信息 ", -// // Detail = string.Empty, -// // OptUserId = Guid.Parse(_userIdStr), -// // OptUser = _userRealName, -// // OptTime = DateTime.Now -// // }); -// // } - -// // break; -// // //添加项目运维人员 -// // case AuditOptType.AddTrialStaff: - -// // //接口参数 -// // var trialUsers = (List)_actionArguments.Values.ToList()[0]; - -// // if (result.IsSuccess) -// // { - -// // _auditRepository.Add(new TrialAudit() -// // { -// // TrialId = trialUsers[0].TrialId, -// // SubjectId = Guid.Empty, -// // AuditType = (int)AuditType.TrialAudit, -// // Note = $"{ _userRealName} 添加了项目运维人员 {string.Join(',', trialUsers.Select(t => t.UserRealName).ToList())} ", -// // Detail = string.Empty, -// // OptUserId = Guid.Parse(_userIdStr), -// // OptUser = _userRealName, -// // OptTime = DateTime.Now -// // }); -// // } - -// // break; - -// // //添加研究中心 -// // case AuditOptType.AddTrialSite: -// // //接口参数 -// // var trialSites = (List)_actionArguments.Values.ToList()[0]; - -// // if (result.IsSuccess) -// // { -// // //查询site信息 -// // var siteIds = trialSites.Select(t => t.SiteId).ToList(); -// // var _siteRepository = (IRepository)executedcontext.HttpContext.RequestServices.GetService(typeof(IRepository)); -// // var siteNames = _siteRepository.Where(t => siteIds.Contains(t.Id)).Select(u => u.SiteName); - -// // _auditRepository.Add(new TrialAudit() -// // { -// // //判断是添加还是更新 -// // TrialId = trialSites[0].TrialId, -// // SubjectId = Guid.Empty, -// // AuditType = (int)AuditType.TrialAudit, -// // Note = $"{ _userRealName} 添加了项目研究中心 {string.Join(',', siteNames)} ", -// // Detail = string.Empty, -// // OptUserId = Guid.Parse(_userIdStr), -// // OptUser = _userRealName, -// // OptTime = DateTime.Now -// // }); -// // } - -// // break; - -// // //研究中心添加运维人员 -// // case AuditOptType.AddTrialSiteCRC: -// // //接口参数 -// // var trialSiteCRCs = (List)_actionArguments.Values.ToList()[0]; - -// // if (result.IsSuccess) -// // { -// // //查询site信息 -// // var _siteRepository = (IRepository)executedcontext.HttpContext.RequestServices.GetService(typeof(IRepository)); -// // var siteName = _siteRepository.GetAll().First(t => t.Id == trialSiteCRCs[0].SiteId).SiteName; - -// // _auditRepository.Add(new TrialAudit() -// // { -// // TrialId = trialSiteCRCs[0].TrialId, -// // SubjectId = Guid.Empty, -// // AuditType = (int)AuditType.TrialAudit, -// // Note = $"{ _userRealName} 为{ siteName } 添加了运维人员 {string.Join(',', trialSiteCRCs.Select(t => t.UserRealName).ToList())}", -// // Detail = string.Empty, -// // OptUserId = Guid.Parse(_userIdStr), -// // OptUser = _userRealName, -// // OptTime = DateTime.Now -// // }); -// // } - -// // break; - -// // //删除项目运维人员 -// // case AuditOptType.DeleteTrailStaff: - -// // if (result.IsSuccess) -// // { -// // _auditRepository.Add(new TrialAudit() -// // { -// // TrialId = _userTrial.TrialId, -// // SubjectId = Guid.Empty, -// // AuditType = (int)AuditType.TrialAudit, -// // Note = $"{ _userRealName} 移除了项目参与人员 {_userTrial.UserRealName} ", -// // Detail = string.Empty, -// // OptUserId = Guid.Parse(_userIdStr), -// // OptUser = _userRealName, -// // OptTime = DateTime.Now -// // }); -// // } - -// // break; -// // //删除项目site -// // case AuditOptType.DeleteTrialSite: - -// // if (result.IsSuccess) -// // { -// // //查询site信息 -// // var _siteRepository = (IRepository)executedcontext.HttpContext.RequestServices.GetService(typeof(IRepository)); -// // var siteName = _siteRepository.GetAll().First(t => t.Id == _trialSite.SiteId).SiteName; - -// // _auditRepository.Add(new TrialAudit() -// // { -// // TrialId = _trialSite.TrialId, -// // SubjectId = Guid.Empty, -// // AuditType = (int)AuditType.TrialAudit, -// // Note = $"{ _userRealName} 移除了研究中心 {siteName} ", -// // Detail = string.Empty, -// // OptUserId = Guid.Parse(_userIdStr), -// // OptUser = _userRealName, -// // OptTime = DateTime.Now -// // }); -// // } - -// // break; -// // //删除项目Site CRC -// // case AuditOptType.DeleteTrialSiteCRC: - -// // if (result.IsSuccess) -// // { -// // //查询site信息 -// // var _siteRepository = (IRepository)executedcontext.HttpContext.RequestServices.GetService(typeof(IRepository)); -// // var siteName = _siteRepository.GetAll().First(t => t.Id == _userTrial.SiteId).SiteName; - -// // _auditRepository.Add(new TrialAudit() -// // { -// // TrialId = _userTrial.TrialId, -// // SubjectId = Guid.Empty, -// // AuditType = (int)AuditType.TrialAudit, -// // Note = $"{ _userRealName} 移除了 {siteName} 的运维人员 {_userTrial.UserRealName} ", -// // Detail = string.Empty, -// // OptUserId = Guid.Parse(_userIdStr), -// // OptUser = _userRealName, -// // OptTime = DateTime.Now -// // }); -// // } -// // break; - -// // //添加访视计划Item -// // case AuditOptType.AddOrUpdateTrialVisitPlanItem: -// // //接口参数 -// // var visitPlanItem = (VisitPlanCommand)_actionArguments.Values.ToList()[0]; - -// // if (result.IsSuccess) -// // { -// // _auditRepository.Add(new TrialAudit() -// // { -// // TrialId = visitPlanItem.TrialId, -// // SubjectId = Guid.Empty, -// // AuditType = (int)AuditType.TrialAudit, -// // Note = visitPlanItem.Id == null ? $"{ _userRealName} 添加了访视计划项 {visitPlanItem.VisitName} " : $"{ _userRealName} 更新了访视计划项为 {visitPlanItem.VisitName} ", -// // Detail = string.Empty, -// // OptUserId = Guid.Parse(_userIdStr), -// // OptUser = _userRealName, -// // OptTime = DateTime.Now -// // }); -// // } - -// // break; -// // //删除访视计划Item -// // case AuditOptType.DeleteTrialVisitPlanItem: - -// // if (result.IsSuccess) -// // { -// // _auditRepository.Add(new TrialAudit() -// // { -// // TrialId = _visitPlan.TrialId, -// // SubjectId = Guid.Empty, -// // AuditType = (int)AuditType.TrialAudit, -// // Note = $"{ _userRealName} 移除了访视计划项 {_visitPlan.VisitName} ", -// // Detail = string.Empty, -// // OptUserId = Guid.Parse(_userIdStr), -// // OptUser = _userRealName, -// // OptTime = DateTime.Now -// // }); -// // } -// // break; - -// // //确认了访视计划 -// // case AuditOptType.ConfirmTrialVisitPlan: -// // var trialId = (Guid)_actionArguments.Values.ToList()[0]; - -// // if (result.IsSuccess) -// // { -// // _auditRepository.Add(new TrialAudit() -// // { -// // TrialId = trialId, -// // SubjectId = Guid.Empty, -// // AuditType = (int)AuditType.TrialAudit, -// // Note = $"{ _userRealName} 确认了访视计划,不允许修改 ", -// // Detail = string.Empty, -// // OptUserId = Guid.Parse(_userIdStr), -// // OptUser = _userRealName, -// // OptTime = DateTime.Now -// // }); -// // } - -// // break; -// // //添加了QA模板 -// // case AuditOptType.AddOrUpdateTrialTemplate: -// // //接口参数 -// // var trialQATemplate = (TrialQATemplateAddCommand)_actionArguments.Values.ToList()[0]; - -// // if (result.IsSuccess) -// // { -// // _auditRepository.Add(new TrialAudit() -// // { - -// // TrialId = trialQATemplate.TrialId, -// // SubjectId = Guid.Empty, -// // AuditType = (int)AuditType.TrialAudit, -// // Note = trialQATemplate.Id == null ? $"{ _userRealName} 添加了QA模板 {trialQATemplate.Name} " : $"{ _userRealName} 更新了QA模板 {trialQATemplate.Name} ", -// // Detail = string.Empty, -// // OptUserId = Guid.Parse(_userIdStr), -// // OptUser = _userRealName, -// // OptTime = DateTime.Now -// // }); -// // } - - -// // break; -// // //删除项目模板 -// // case AuditOptType.DeleteTrialTemplate: - -// // if (result.IsSuccess) -// // { -// // _auditRepository.Add(new TrialAudit() -// // { - -// // TrialId = _qATrailTemplate.TrialId, -// // SubjectId = Guid.Empty, -// // AuditType = (int)AuditType.TrialAudit, -// // Note = $"{ _userRealName} 移除了QA模板 {_qATrailTemplate.Name} ", -// // Detail = string.Empty, -// // OptUserId = Guid.Parse(_userIdStr), -// // OptUser = _userRealName, -// // OptTime = DateTime.Now -// // }); -// // } -// // break; - -// // } - -// // break; -// // //受试者审计 -// // case AuditType.SubjectAudit: - - -// // switch (_attr._auditOptType) -// // { -// // // 添加或者更新受试者 -// // case AuditOptType.AddOrUpdateSubject: - -// // //接口参数 -// // var subject = (SubjectCommand)_actionArguments.Values.ToList()[0]; - -// // if (result.IsSuccess) -// // { -// // _auditRepository.Add(new TrialAudit() -// // { -// // TrialId = subject.TrialId, -// // SubjectId = subject.Id == null ? Guid.Parse(result.Data) : subject.Id.Value, -// // AuditType = (int)AuditType.SubjectAudit, -// // Note = subject.Id == null ? $"{ _userRealName} 添加了受试者 {subject.LastName + subject.FirstName} 并初始化了访视计划" : $"{ _userRealName} 对受试者 { subject.LastName + subject.FirstName} 信息进行了更新 ", -// // Detail = string.Empty, -// // OptUserId = Guid.Parse(_userIdStr), -// // OptUser = _userRealName, -// // OptTime = DateTime.Now -// // }); -// // } - -// // break; -// // // 删除受试者 -// // case AuditOptType.DeleteSubject: -// // if (result.IsSuccess) -// // { -// // _auditRepository.Add(new TrialAudit() -// // { -// // TrialId = _subject.TrialId, -// // SubjectId = _subject.Id, -// // AuditType = (int)AuditType.SubjectAudit, -// // Note = $"{ _userRealName} 移除了受试者 {_subject.LastName + _subject.FirstName} ", -// // Detail = string.Empty, -// // OptUserId = Guid.Parse(_userIdStr), -// // OptUser = _userRealName, -// // OptTime = DateTime.Now -// // }); -// // } - -// // break; -// // // 受试者计划外访视 -// // case AuditOptType.AddOrUpdateSubjectOutPlanVisit: - -// // //接口参数 -// // var subjectVisit = (SubjectVisitCommand)_actionArguments.Values.ToList()[0]; - -// // if (result.IsSuccess) -// // { -// // var _subjectRepository = -// // (IRepository)executedcontext.HttpContext.RequestServices.GetService( -// // typeof(IRepository)); - -// // _subject = _subjectRepository.FirstOrDefault(t => t.Id == subjectVisit.SubjectId); - -// // _auditRepository.Add(new TrialAudit() -// // { -// // TrialId = _subject.TrialId, -// // SubjectId = _subject.Id, -// // AuditType = (int)AuditType.SubjectAudit, -// // Note = subjectVisit.Id == null ? $"{ _userRealName} 为受试者 {_subject.LastName + _subject.FirstName} 添加了计划外访视 {subjectVisit.VisitName}" : $"{ _userRealName} 更新受试者 {_subject.LastName + _subject.FirstName} 计划外访视{subjectVisit.VisitName}", -// // Detail = string.Empty, -// // OptUserId = Guid.Parse(_userIdStr), -// // OptUser = _userRealName, -// // OptTime = DateTime.Now -// // }); -// // } - -// // break; -// // // 删除计划外访视 -// // case AuditOptType.DeleteSubjectOutPlanVisit: - -// // if (result.IsSuccess) -// // { -// // _auditRepository.Add(new TrialAudit() -// // { -// // TrialId = _subjectVisit.TrialId, -// // SubjectId = _subject.Id, -// // AuditType = (int)AuditType.SubjectAudit, -// // Note = $"{ _userRealName} 移除了受试者{_subject.LastName + _subject.FirstName} 计划外访视 {_subjectVisit.VisitName} ", -// // Detail = string.Empty, -// // OptUserId = Guid.Parse(_userIdStr), -// // OptUser = _userRealName, -// // OptTime = DateTime.Now -// // }); -// // } - -// // break; -// // // 人工设置已执行 -// // case AuditOptType.SetSVExecuted: - -// // if (result.IsSuccess) -// // { -// // _auditRepository.Add(new TrialAudit() -// // { -// // TrialId = _subjectVisit.TrialId, -// // SubjectId = _subject.Id, -// // AuditType = (int)AuditType.SubjectAudit, -// // Note = $"{ _userRealName} 将受试者 {_subject.LastName + _subject.FirstName} 访视 {_subjectVisit.VisitName} 设置为已执行 ", -// // Detail = string.Empty, -// // OptUserId = Guid.Parse(_userIdStr), -// // OptUser = _userRealName, -// // OptTime = DateTime.Now -// // }); -// // } - - -// // break; -// // } - -// // break; - -// // //检查审计 -// // case AuditType.StudyAudit: -// // _studyRepository = -// // (IRepository)executedcontext.HttpContext.RequestServices.GetService( -// // typeof(IRepository)); - -// // switch (_attr._auditOptType) -// // { - -// // case AuditOptType.ChangeStudyStatus: - -// // //接口参数 -// // var studyStatusInfo = (StudyStatusDetailCommand)_actionArguments.Values.ToList()[0]; - -// // _study = _studyRepository.FirstOrDefault(t => t.Id == studyStatusInfo.StudyId); - -// // if (result.IsSuccess) -// // { -// // _auditRepository.Add(new TrialAudit() -// // { -// // TrialId = _study.TrialId, -// // SubjectId = _study.SubjectId, -// // StudyId = _study.Id, -// // AuditType = (int)AuditType.StudyAudit, -// // Note = $"{ _userRealName} 动作变更了 { _study.StudyCode} 检查状态为 {DealStudyStatus(_study.Status)} ", -// // Detail = string.Empty, -// // OptUserId = Guid.Parse(_userIdStr), -// // OptUser = _userRealName, -// // OptTime = DateTime.Now -// // }); -// // } - -// // break; - -// // case AuditOptType.Anonymized: - -// // case AuditOptType.Forwarded: - -// // //接口参数 -// // var studyId = (Guid)_actionArguments.Values.ToList()[0]; - -// // _study = _studyRepository.FirstOrDefault(t => t.Id == studyId); - -// // if (result.IsSuccess) -// // { -// // _auditRepository.Add(new TrialAudit() -// // { -// // TrialId = _study.TrialId, -// // SubjectId = _study.SubjectId, -// // StudyId = _study.Id, -// // AuditType = (int)AuditType.StudyAudit, -// // Note = $"{ _userRealName} 动作变更了 { _study.StudyCode} 检查状态为 {DealStudyStatus(_study.Status)} ", -// // Detail = string.Empty, -// // OptUserId = Guid.Parse(_userIdStr), -// // OptUser = _userRealName, -// // OptTime = DateTime.Now -// // }); -// // } - - -// // break; -// // } - -// // break; - -// // } - -// // _auditRepository.SaveChanges(); - -// //} - - -// //public void OnActionExecuting(ActionExecutingContext context) -// //{ -// // //_dbContext = (IRaCISDBContext)context.HttpContext.RequestServices.GetService(typeof(IRaCISDBContext)); - - -// // _actionArguments = context.ActionArguments; - -// // _attr = (TrialAuditAttribute)context.ActionDescriptor.EndpointMetadata.First(m => m.GetType() == typeof(TrialAuditAttribute)); - -// // _userIdStr = context.HttpContext.User.Claims.First(t => t.Type == "id")?.Value ?? Guid.Empty.ToString(); -// // _userRealName = context.HttpContext.User.Claims.First(t => t.Type == "realName")?.Value ?? string.Empty; - -// // //获取接口仓储 -// // _auditRepository = (IRepository)context.HttpContext.RequestServices.GetService(typeof(IRepository)); - - - -// // switch (_attr._auditType) -// // { -// // //项目审计 -// // case AuditType.TrialAudit: - -// // switch (_attr._auditOptType) -// // { -// // //删除项目运维人员 -// // case AuditOptType.DeleteTrailStaff: - -// // // 删除项目Site CRC -// // case AuditOptType.DeleteTrialSiteCRC: - -// // //接口参数 -// // var userTrialId = (Guid)_actionArguments.Values.ToList()[0]; - -// // var _userTrialRepository = -// // (IRepository)context.HttpContext.RequestServices.GetService( -// // typeof(IRepository)); - -// // _userTrial = _userTrialRepository.GetAll().First(t => t.Id == userTrialId); -// // break; - - -// // //删除项目site -// // case AuditOptType.DeleteTrialSite: - -// // //接口参数 -// // var trialSiteId = (Guid)_actionArguments.Values.ToList()[0]; - -// // var _TrialsiteRepository = -// // (IRepository)context.HttpContext.RequestServices.GetService( -// // typeof(IRepository)); - -// // _trialSite = _TrialsiteRepository.GetAll().First(t => t.Id == trialSiteId); -// // break; - -// // case AuditOptType.DeleteTrialVisitPlanItem: - -// // //接口参数 -// // var visitPlanId = (Guid)_actionArguments.Values.ToList()[0]; - -// // var _visitPlanRepository = -// // (IRepository)context.HttpContext.RequestServices.GetService( -// // typeof(IRepository)); - -// // _visitPlan = _visitPlanRepository.GetAll().First(t => t.Id == visitPlanId); - -// // break; -// // case AuditOptType.DeleteTrialTemplate: - -// // //接口参数 -// // var qATrailTemplateId = (Guid)_actionArguments.Values.ToList()[0]; -// // var _qATrailTemplateRepository = -// // (IRepository)context.HttpContext.RequestServices.GetService( -// // typeof(IRepository)); - -// // _qATrailTemplate = _qATrailTemplateRepository.GetAll() -// // .FirstOrDefault(t => t.Id == qATrailTemplateId); - -// // break; - -// // } - -// // break; - -// // //受试者审计 -// // case AuditType.SubjectAudit: - -// // switch (_auditOptType) -// // { -// // case AuditOptType.DeleteSubject: -// // //接口参数 -// // var subjectId = (Guid)_actionArguments.Values.ToList()[0]; - -// // var _subjectRepository = -// // (IRepository)context.HttpContext.RequestServices.GetService( -// // typeof(IRepository)); - -// // _subject = _subjectRepository.FirstOrDefault(t => t.Id == subjectId); - -// // break; - -// // case AuditOptType.DeleteSubjectOutPlanVisit: -// // case AuditOptType.SetSVExecuted: - -// // //接口参数 -// // var subjectVisitId = (Guid)_actionArguments.Values.ToList()[0]; - -// // var _subjectVisitRepository = -// // (IRepository)context.HttpContext.RequestServices.GetService( -// // typeof(IRepository)); - -// // _subjectVisit = _subjectVisitRepository.FirstOrDefault(t => t.Id == subjectVisitId); - -// // _subjectRepository = -// // (IRepository)context.HttpContext.RequestServices.GetService( -// // typeof(IRepository)); - -// // _subject = _subjectRepository.FirstOrDefault(t => t.Id == _subjectVisit.SubjectId); - -// // break; -// // } -// // break; - - -// // //检查审计 -// // case AuditType.StudyAudit: - -// // switch (_attr._auditOptType) -// // { -// // case AuditOptType.UploadImage: - -// // break; -// // } -// // break; - -// // } - -// //} -// #endregion - -// public static string DealStudyStatus(int status) -// { - -// var message = string.Empty; -// switch (status) -// { -// case (int)StudyStatus.Uploaded: -// message = "Uploaded"; -// break; - -// case (int)StudyStatus.QARequested: - -// message = "QA Requested"; -// break; -// case (int)StudyStatus.QAing: - -// message = "In QA"; -// break; - -// //case (int)StudyStatus.Abandon: -// // message = "Study has abandon"; -// // break; - -// case (int)StudyStatus.QAFinish: -// message = "QA Completed Passed"; -// break; - -// case (int)StudyStatus.QAFInishNotPass: -// message = "QA Completed Failed"; -// break; - -// case (int)StudyStatus.Anonymizing: -// message = "Anonymizing"; -// break; - -// case (int)StudyStatus.Anonymized: -// message = "Anonymized"; -// break; - -// case (int)StudyStatus.AnonymizeFailed: -// message = "Anonymize Failed"; -// break; - -// case (int)StudyStatus.Forwarding: -// message = "Forwarding"; -// break; - -// case (int)StudyStatus.Forwarded: -// message = "Forwarded "; -// break; - -// case (int)StudyStatus.ForwardFailed: -// message = "Forward Failed "; -// break; -// } - -// return message; -// } - -// public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) -// { -// // 开启AOP事务(审计消息记录和 添加更新记录 在一个事务里面,不再是分开的事务) -// //var _dbContext = (IRaCISDBContext)context.HttpContext.RequestServices.GetService(typeof(IRaCISDBContext)); - -// //var strategy = _dbContext.Database.CreateExecutionStrategy(); - -// var _dbContext = (IRaCISDBContext)context.HttpContext.RequestServices.GetService(typeof(IRaCISDBContext)); - -// var strategy = _dbContext.Database.CreateExecutionStrategy(); - -// await strategy.Execute(async () => -// { -// var currentTransaction = _dbContext.Database.CurrentTransaction; - -// var transaction = currentTransaction ?? _dbContext.Database.BeginTransaction(System.Data.IsolationLevel.ReadUncommitted); - -// #region 执行方法前 - -// _actionArguments = context.ActionArguments; - -// _attr = (TrialAuditAttribute)context.ActionDescriptor.EndpointMetadata.First(m => m.GetType() == typeof(TrialAuditAttribute)); - -// _userIdStr = context.HttpContext.User.Claims.First(t => t.Type == "id")?.Value ?? Guid.Empty.ToString(); -// _userRealName = context.HttpContext.User.Claims.First(t => t.Type == "realName")?.Value ?? string.Empty; - -// //获取接口仓储 -// _auditRepository = (IRepository)context.HttpContext.RequestServices.GetService(typeof(IRepository)); - -// switch (_attr._auditType) -// { -// //项目审计 -// case AuditType.TrialAudit: - -// switch (_attr._auditOptType) -// { -// //删除项目运维人员 -// case AuditOptType.DeleteTrailStaff: - -// //接口参数 -// var userTrial = (Guid)_actionArguments.Values.ToList()[0]; - -// var _userTrialRepository = -// (IRepository)context.HttpContext.RequestServices.GetService( -// typeof(IRepository)); - -// _userTrial = _userTrialRepository.AsQueryable().Include(t => t.User).FirstOrDefault(t => t.Id == userTrial); -// break; - -// // 删除项目Site CRC -// case AuditOptType.DeleteTrialSiteCRC: - -// //接口参数 -// var userTrialSiteId = (Guid)_actionArguments.Values.ToList()[0]; - -// var _userTrialSiteRepository = -// (IRepository)context.HttpContext.RequestServices.GetService( -// typeof(IRepository)); - -// _userTrialSite = _userTrialSiteRepository.AsQueryable().Include(t => t.User).FirstOrDefault(t => t.Id == userTrialSiteId); -// break; - - -// //删除项目site -// case AuditOptType.DeleteTrialSite: - -// //接口参数 -// var trialSiteId = (Guid)_actionArguments.Values.ToList()[0]; - -// var _TrialsiteRepository = -// (IRepository)context.HttpContext.RequestServices.GetService( -// typeof(IRepository)); - -// _trialSite = _TrialsiteRepository.AsQueryable().Include(t => t.Site).FirstOrDefault(t => t.Id == trialSiteId); -// break; - -// case AuditOptType.DeleteTrialVisitPlanItem: - -// //接口参数 -// var visitPlanId = (Guid)_actionArguments.Values.ToList()[0]; - -// var _visitPlanRepository = -// (IRepository)context.HttpContext.RequestServices.GetService( -// typeof(IRepository)); - -// _visitPlan = _visitPlanRepository.FirstOrDefault(t => t.Id == visitPlanId).IfNullThrowException(); - -// break; -// case AuditOptType.DeleteTrialTemplate: - - - -// break; - -// } - -// break; - -// //受试者审计 -// case AuditType.SubjectAudit: - -// switch (_auditOptType) -// { -// case AuditOptType.DeleteSubject: -// //接口参数 -// var subjectId = (Guid)_actionArguments.Values.ToList()[0]; - -// var _subjectRepository = -// (IRepository)context.HttpContext.RequestServices.GetService( -// typeof(IRepository)); - -// _subject = _subjectRepository.FirstOrDefault(t => t.Id == subjectId).IfNullThrowException(); - -// break; - -// case AuditOptType.DeleteSubjectOutPlanVisit: -// case AuditOptType.SetSVExecuted: - -// //接口参数 -// var subjectVisitId = (Guid)_actionArguments.Values.ToList()[0]; - -// var _subjectVisitRepository = -// (IRepository)context.HttpContext.RequestServices.GetService( -// typeof(IRepository)); - -// _subjectVisit = _subjectVisitRepository.FirstOrDefault(t => t.Id == subjectVisitId).IfNullThrowException(); - -// _subjectRepository = -// (IRepository)context.HttpContext.RequestServices.GetService( -// typeof(IRepository)); - -// _subject = _subjectRepository.FirstOrDefault(t => t.Id == _subjectVisit.SubjectId).IfNullThrowException(); - -// break; -// } -// break; - - -// //检查审计 -// case AuditType.StudyAudit: - -// switch (_attr._auditOptType) -// { -// case AuditOptType.UploadImage: - -// break; -// } -// break; - -// } - -// #endregion - -// //获取实际执行方法next() 的结果 -// ActionExecutedContext executedcontext = await next(); - -// #region 方法执行后 - -// //上传影像接口返回值类型特殊 需要单独处理 -// if (_attr._auditOptType == AuditOptType.UploadImage) -// { - -// //接口参数 -// var archiveStudyInfo = (ArchiveStudyCommand)_actionArguments.Values.ToList()[0]; - -// if (executedcontext.Exception != null) -// { -// var logger = (ILogger)executedcontext.HttpContext.RequestServices.GetService( -// typeof(ILogger)); - -// logger!.LogError("影像上传 中间发生异常", executedcontext.Exception.StackTrace); - -// return; -// } - -// //接口返回结果 因为上传成功和不成功 泛型类型不一样 -// dynamic archive = executedcontext.Result; - - -// var archiveResult = (IResponseOutput)archive.Value; - -// if (archiveResult.IsSuccess) -// { - - -// _studyRepository = (IRepository)executedcontext.HttpContext.RequestServices.GetService(typeof(IRepository)); - -// _auditRepository = (IRepository)context.HttpContext.RequestServices.GetService(typeof(IRepository)); - -// var successResult = (IResponseOutput)archiveResult; - -// var studyList = _studyRepository.Where(t => t.SubjectVisitId == successResult.Data.ArchivedDicomStudies.ToList()[0].SubjectVisitId).ToList(); - -// studyList.ForEach(study => -// { -// var mes = study.Status == (int)StudyStatus.Uploaded ? "上传了" : "重传了"; -// _auditRepository.Add(new TrialAudit() -// { -// TrialId = study.TrialId, -// SubjectId = study.SubjectId, -// StudyId = study.Id, -// AuditType = (int)AuditType.StudyAudit, -// //Note = $"{ _userRealName} 动作变更了 { _study.StudyCode} 检查状态为 {DealStudyStatus(_study.Status)} ", -// Note = $"{ _userRealName} {mes} { study.StudyCode} ", -// Detail = string.Empty, -// OptUserId = Guid.Parse(_userIdStr), -// OptUser = _userRealName, -// OptTime = DateTime.Now -// }); -// }); - - - -// _auditRepository.SaveChanges(); - -// transaction.Commit(); - -// return; - -// } - - -// } - -// //接口返回结果 -// if (executedcontext.Result is null) -// { -// throw new BusinessValidationFailedException(executedcontext.Exception.Message); -// } -// dynamic actionResult = executedcontext.Result; - -// //此处审计只涉及到添加更新和删除, 统一了相关接口的返回结果,才能在此强制转换 -// //var result = (IResponseOutput)actionResult.Value; - -// var result = (IResponseOutput)actionResult.Value; - - -// switch (_attr._auditType) -// { -// //项目审计 -// case AuditType.TrialAudit: - -// switch (_attr._auditOptType) -// { -// //项目的添加和更新接口 -// case AuditOptType.AddOrUpdateTrial: - -// //接口参数 -// var trialInfo = (TrialCommand)_actionArguments.Values.ToList()[0]; - -// if (result.IsSuccess) -// { -// _auditRepository.Add(new TrialAudit() -// { -// //判断是添加还是更新 -// TrialId = trialInfo.Id == null ? Guid.Parse(result.Data) : trialInfo.Id.Value, -// SubjectId = Guid.Empty, -// AuditType = (int)AuditType.TrialAudit, -// Note = trialInfo.Id == null ? $"{ _userRealName} 添加了项目 {trialInfo.TrialCode} " : $"{ _userRealName} 更新了项目 {trialInfo.TrialCode} 基本信息 ", -// Detail = string.Empty, -// OptUserId = Guid.Parse(_userIdStr), -// OptUser = _userRealName, -// OptTime = DateTime.Now -// }); -// } - -// break; -// //添加项目运维人员 -// case AuditOptType.AddTrialStaff: - -// //接口参数 -// var trialUsers = (TrialUserAddCommand[])_actionArguments.Values.ToList()[0]; - -// if (result.IsSuccess) -// { - -// _auditRepository.Add(new TrialAudit() -// { -// TrialId = trialUsers[0].TrialId, -// SubjectId = Guid.Empty, -// AuditType = (int)AuditType.TrialAudit, -// //Note = $"{ _userRealName} 添加了项目运维人员 {string.Join(',', trialUsers.Select(t => t.UserRealName).ToList())} ", -// Detail = string.Empty, -// OptUserId = Guid.Parse(_userIdStr), -// OptUser = _userRealName, -// OptTime = DateTime.Now -// }); -// } - -// break; - -// //添加研究中心 -// case AuditOptType.AddTrialSite: -// //接口参数 -// var trialSites = (List)_actionArguments.Values.ToList()[0]; - -// if (result.IsSuccess) -// { -// //查询site信息 -// var siteIds = trialSites.Select(t => t.SiteId).ToList(); -// var _siteRepository = (IRepository)executedcontext.HttpContext.RequestServices.GetService(typeof(IRepository)); -// var siteNames = _siteRepository.Where(t => siteIds.Contains(t.Id)).Select(u => u.SiteName); - -// _auditRepository.Add(new TrialAudit() -// { -// //判断是添加还是更新 -// TrialId = trialSites[0].TrialId, -// SubjectId = Guid.Empty, -// AuditType = (int)AuditType.TrialAudit, -// Note = $"{ _userRealName} 添加了项目研究中心 {string.Join(',', siteNames)} ", -// Detail = string.Empty, -// OptUserId = Guid.Parse(_userIdStr), -// OptUser = _userRealName, -// OptTime = DateTime.Now -// }); -// } - -// break; - -// //研究中心添加运维人员 -// case AuditOptType.AddTrialSiteCRC: -// //接口参数 -// var trialSiteCRCs = (List)_actionArguments.Values.ToList()[0]; - -// if (result.IsSuccess) -// { -// //查询site信息 -// var _siteRepository = (IRepository)executedcontext.HttpContext.RequestServices.GetService(typeof(IRepository)); -// var siteName = _siteRepository.FirstOrDefault(t => t.Id == trialSiteCRCs[0].SiteId).IfNullThrowException().SiteName; - -// _auditRepository.Add(new TrialAudit() -// { -// TrialId = trialSiteCRCs[0].TrialId, -// SubjectId = Guid.Empty, -// AuditType = (int)AuditType.TrialAudit, -// Note = $"{ _userRealName} 为{ siteName } 添加了运维人员 {string.Join(',', trialSiteCRCs.Select(t => t.UserRealName).ToList())}", -// Detail = string.Empty, -// OptUserId = Guid.Parse(_userIdStr), -// OptUser = _userRealName, -// OptTime = DateTime.Now -// }); -// } - -// break; - -// //删除项目运维人员 -// case AuditOptType.DeleteTrailStaff: - -// if (result.IsSuccess) -// { -// _auditRepository.Add(new TrialAudit() -// { -// TrialId = _userTrial.TrialId, -// SubjectId = Guid.Empty, -// AuditType = (int)AuditType.TrialAudit, -// Note = $"{ _userRealName} 移除了项目参与人员 {_userTrial.User.LastName + " / " + _userTrial.User.FirstName} ", -// Detail = string.Empty, -// OptUserId = Guid.Parse(_userIdStr), -// OptUser = _userRealName, -// OptTime = DateTime.Now -// }); -// } - -// break; -// //删除项目site -// case AuditOptType.DeleteTrialSite: - -// if (result.IsSuccess) -// { -// //查询site信息 -// var _siteRepository = (IRepository)executedcontext.HttpContext.RequestServices.GetService(typeof(IRepository)); -// var siteName = _siteRepository.FirstOrDefault(t => t.Id == _trialSite.SiteId).IfNullThrowException().SiteName; - -// _auditRepository.Add(new TrialAudit() -// { -// TrialId = _trialSite.TrialId, -// SubjectId = Guid.Empty, -// AuditType = (int)AuditType.TrialAudit, -// Note = $"{ _userRealName} 移除了研究中心 {siteName} ", -// Detail = string.Empty, -// OptUserId = Guid.Parse(_userIdStr), -// OptUser = _userRealName, -// OptTime = DateTime.Now -// }); -// } - -// break; -// //删除项目Site CRC -// case AuditOptType.DeleteTrialSiteCRC: - -// if (result.IsSuccess) -// { -// //查询site信息 -// var _siteRepository = (IRepository)executedcontext.HttpContext.RequestServices.GetService(typeof(IRepository)); -// var siteName = _siteRepository.FirstOrDefault(t => t.Id == _userTrialSite.SiteId).IfNullThrowException().SiteName; - -// _auditRepository.Add(new TrialAudit() -// { -// TrialId = _userTrialSite.TrialId, -// SubjectId = Guid.Empty, -// AuditType = (int)AuditType.TrialAudit, -// Note = $"{ _userRealName} 移除了 {siteName} 的运维人员 {_userTrialSite.User.UserName} ", -// Detail = string.Empty, -// OptUserId = Guid.Parse(_userIdStr), -// OptUser = _userRealName, -// OptTime = DateTime.Now -// }); -// } -// break; - -// //添加访视计划Item -// case AuditOptType.AddOrUpdateTrialVisitPlanItem: -// //接口参数 -// var visitPlanItem = (VisitPlanCommand)_actionArguments.Values.ToList()[0]; - -// if (result.IsSuccess) -// { -// _auditRepository.Add(new TrialAudit() -// { -// TrialId = visitPlanItem.TrialId, -// SubjectId = Guid.Empty, -// AuditType = (int)AuditType.TrialAudit, -// Note = visitPlanItem.Id == null ? $"{ _userRealName} 添加了访视计划项 {visitPlanItem.VisitName} " : $"{ _userRealName} 更新了访视计划项为 {visitPlanItem.VisitName} ", -// Detail = string.Empty, -// OptUserId = Guid.Parse(_userIdStr), -// OptUser = _userRealName, -// OptTime = DateTime.Now -// }); -// } - -// break; -// //删除访视计划Item -// case AuditOptType.DeleteTrialVisitPlanItem: - -// if (result.IsSuccess) -// { -// _auditRepository.Add(new TrialAudit() -// { -// TrialId = _visitPlan.TrialId, -// SubjectId = Guid.Empty, -// AuditType = (int)AuditType.TrialAudit, -// Note = $"{ _userRealName} 移除了访视计划项 {_visitPlan.VisitName} ", -// Detail = string.Empty, -// OptUserId = Guid.Parse(_userIdStr), -// OptUser = _userRealName, -// OptTime = DateTime.Now -// }); -// } -// break; - -// //确认了访视计划 -// case AuditOptType.ConfirmTrialVisitPlan: -// var trialId = (Guid)_actionArguments.Values.ToList()[0]; - -// if (result.IsSuccess) -// { -// _auditRepository.Add(new TrialAudit() -// { -// TrialId = trialId, -// SubjectId = Guid.Empty, -// AuditType = (int)AuditType.TrialAudit, -// Note = $"{ _userRealName} 确认了访视计划,不允许修改 ", -// Detail = string.Empty, -// OptUserId = Guid.Parse(_userIdStr), -// OptUser = _userRealName, -// OptTime = DateTime.Now -// }); -// } - -// break; -// //添加了QA模板 -// case AuditOptType.AddOrUpdateTrialTemplate: -// //接口参数 - -// if (result.IsSuccess) -// { - -// } - - -// break; -// //删除项目模板 -// case AuditOptType.DeleteTrialTemplate: - -// if (result.IsSuccess) -// { - -// } -// break; - -// } - -// break; -// //受试者审计 -// case AuditType.SubjectAudit: - - -// switch (_attr._auditOptType) -// { -// // 添加或者更新受试者 -// case AuditOptType.AddOrUpdateSubject: - -// //接口参数 -// var subject = (SubjectCommand)_actionArguments.Values.ToList()[0]; - -// if (result.IsSuccess) -// { -// _auditRepository.Add(new TrialAudit() -// { -// TrialId = subject.TrialId, -// SubjectId = subject.Id == null ? Guid.Parse(result.Data) : subject.Id.Value, -// AuditType = (int)AuditType.SubjectAudit, -// Note = subject.Id == null ? $"{ _userRealName} 添加了受试者 {subject.ShortName } 并初始化了访视计划" : $"{ _userRealName} 对受试者 { subject.ShortName } 信息进行了更新 ", -// Detail = string.Empty, -// OptUserId = Guid.Parse(_userIdStr), -// OptUser = _userRealName, -// OptTime = DateTime.Now -// }); -// } - -// break; -// // 删除受试者 -// case AuditOptType.DeleteSubject: -// if (result.IsSuccess) -// { -// _auditRepository.Add(new TrialAudit() -// { -// TrialId = _subject.TrialId, -// SubjectId = _subject.Id, -// AuditType = (int)AuditType.SubjectAudit, -// Note = $"{ _userRealName} 移除了受试者 {_subject.LastName + _subject.FirstName} ", -// Detail = string.Empty, -// OptUserId = Guid.Parse(_userIdStr), -// OptUser = _userRealName, -// OptTime = DateTime.Now -// }); -// } - -// break; -// // 受试者计划外访视 -// case AuditOptType.AddOrUpdateSubjectOutPlanVisit: - -// //接口参数 -// var subjectVisit = (SubjectVisitCommand)_actionArguments.Values.ToList()[0]; - -// if (result.IsSuccess) -// { -// var _subjectRepository = -// (IRepository)executedcontext.HttpContext.RequestServices.GetService( -// typeof(IRepository)); - -// _subject = _subjectRepository.FirstOrDefault(t => t.Id == subjectVisit.SubjectId).IfNullThrowException(); - -// _auditRepository.Add(new TrialAudit() -// { -// TrialId = _subject.TrialId, -// SubjectId = _subject.Id, -// AuditType = (int)AuditType.SubjectAudit, -// Note = subjectVisit.Id == null ? $"{ _userRealName} 为受试者 {_subject.LastName + _subject.FirstName} 添加了计划外访视 {subjectVisit.VisitName}" : $"{ _userRealName} 更新受试者 {_subject.LastName + _subject.FirstName} 计划外访视{subjectVisit.VisitName}", -// Detail = string.Empty, -// OptUserId = Guid.Parse(_userIdStr), -// OptUser = _userRealName, -// OptTime = DateTime.Now -// }); -// } - -// break; -// // 删除计划外访视 -// case AuditOptType.DeleteSubjectOutPlanVisit: - -// if (result.IsSuccess) -// { -// _auditRepository.Add(new TrialAudit() -// { -// TrialId = _subjectVisit.TrialId, -// SubjectId = _subject.Id, -// AuditType = (int)AuditType.SubjectAudit, -// Note = $"{ _userRealName} 移除了受试者{_subject.LastName + _subject.FirstName} 计划外访视 {_subjectVisit.VisitName} ", -// Detail = string.Empty, -// OptUserId = Guid.Parse(_userIdStr), -// OptUser = _userRealName, -// OptTime = DateTime.Now -// }); -// } - -// break; -// // 人工设置已执行 -// case AuditOptType.SetSVExecuted: - -// if (result.IsSuccess) -// { -// _auditRepository.Add(new TrialAudit() -// { -// TrialId = _subjectVisit.TrialId, -// SubjectId = _subject.Id, -// AuditType = (int)AuditType.SubjectAudit, -// Note = $"{ _userRealName} 将受试者 {_subject.LastName + _subject.FirstName} 访视 {_subjectVisit.VisitName} 设置为已执行 ", -// Detail = string.Empty, -// OptUserId = Guid.Parse(_userIdStr), -// OptUser = _userRealName, -// OptTime = DateTime.Now -// }); -// } - - -// break; -// } - -// break; - -// //检查审计 -// case AuditType.StudyAudit: -// _studyRepository = -// (IRepository)executedcontext.HttpContext.RequestServices.GetService( -// typeof(IRepository)); - -// switch (_attr._auditOptType) -// { - -// case AuditOptType.ChangeStudyStatus: - -// //接口参数 -// var studyStatusInfo = (StudyStatusDetailCommand)_actionArguments.Values.ToList()[0]; - -// _study = _studyRepository.FirstOrDefault(t => t.Id == studyStatusInfo.StudyId).IfNullThrowException(); - -// if (result.IsSuccess) -// { -// _auditRepository.Add(new TrialAudit() -// { -// TrialId = _study.TrialId, -// SubjectId = _study.SubjectId, -// StudyId = _study.Id, -// AuditType = (int)AuditType.StudyAudit, -// Note = $"{ _userRealName} 动作变更了 { _study.StudyCode} 检查状态为 {DealStudyStatus(_study.Status)} ", -// Detail = string.Empty, -// OptUserId = Guid.Parse(_userIdStr), -// OptUser = _userRealName, -// OptTime = DateTime.Now -// }); -// } - -// break; - -// case AuditOptType.Anonymized: - -// case AuditOptType.Forwarded: - -// //接口参数 -// var studyId = (Guid)_actionArguments.Values.ToList()[0]; - -// _study = _studyRepository.FirstOrDefault(t => t.Id == studyId).IfNullThrowException(); - -// if (result.IsSuccess) -// { -// _auditRepository.Add(new TrialAudit() -// { -// TrialId = _study.TrialId, -// SubjectId = _study.SubjectId, -// StudyId = _study.Id, -// AuditType = (int)AuditType.StudyAudit, -// Note = $"{ _userRealName} 动作变更了 { _study.StudyCode} 检查状态为 {DealStudyStatus(_study.Status)} ", -// Detail = string.Empty, -// OptUserId = Guid.Parse(_userIdStr), -// OptUser = _userRealName, -// OptTime = DateTime.Now -// }); -// } - - -// break; -// } - -// break; - -// } - -// _auditRepository.SaveChanges(); - -// #endregion - - -// //提交事务 Commit transaction if all commands succeed, transaction will auto-rollback when disposed if either commands fails -// transaction.Commit(); -// } -// ); - - - - - - - - - -// } -// } -//} - - - - diff --git a/IRaCIS.Core.Application/Helper/ExcelExportHelper.cs b/IRaCIS.Core.Application/Helper/ExcelExportHelper.cs index fd280abf1..178109b5d 100644 --- a/IRaCIS.Core.Application/Helper/ExcelExportHelper.cs +++ b/IRaCIS.Core.Application/Helper/ExcelExportHelper.cs @@ -16,6 +16,7 @@ using NPOI.HPSF; using NPOI.HSSF.UserModel; using NPOI.XSSF.UserModel; using SkiaSharp; +using System.Collections; using System.IO; namespace IRaCIS.Core.Application.Service; @@ -52,20 +53,24 @@ public static class ExcelExportHelper var translateDataList = await _dictionaryService.GetBasicDataSelect(needTranslatePropertyList.Select(t => t.DicParentCode).Distinct().ToArray()); - var dic = JsonConvert.DeserializeObject>(data.ToJsonNotIgnoreNull()); + var dic = data.ConvertToDictionary(); + foreach (var key in dic.Keys) { //是数组 那么找到对应的属性 进行翻译 - if (dic[key].GetType().IsAssignableFrom(typeof(JArray))) + if (dic[key].GetType().GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList<>))) { var newObjList = new List(); var no = 1; - foreach (var item in dic[key] as JArray) + foreach (var item in dic[key] as IList ) { - var itemDic = JsonConvert.DeserializeObject>(item.ToJsonNotIgnoreNull()); + //var itemDic = JsonConvert.DeserializeObject>(item.ToJsonNotIgnoreNull()); + + var itemDic = item.ConvertToDictionary(); + foreach (var needTranslateProperty in needTranslatePropertyList) @@ -73,7 +78,7 @@ public static class ExcelExportHelper //翻译的属性依赖其他属性 if (needTranslateProperty.IsTranslateDenpendOtherProperty) { - if (item[needTranslateProperty.DependPropertyName]?.ToString().ToLower() == needTranslateProperty.DependPropertyValueStr.ToLower()) + if (itemDic[needTranslateProperty.DependPropertyName]?.ToString().ToLower() == needTranslateProperty.DependPropertyValueStr.ToLower()) { var beforeValue = itemDic[needTranslateProperty.Name]?.ToString(); @@ -231,29 +236,30 @@ public static class ExcelExportHelper var translateDataList = await _dictionaryService.GetBasicDataSelect(needTranslatePropertyList.Select(t => t.DicParentCode).Distinct().ToArray()); - - var dic = JsonConvert.DeserializeObject>(data.ToJsonNotIgnoreNull()); + var dic = data.ConvertToDictionary(); + //var dic = (JsonConvert.DeserializeObject>(data.ToJsonNotIgnoreNull())).IfNullThrowException(); foreach (var key in dic.Keys) { //是数组 那么找到对应的属性 进行翻译 - if (dic[key].GetType().IsAssignableFrom(typeof(JArray))) + if (dic[key].GetType().GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList<>))) + //if (dic[key].GetType().IsAssignableFrom(typeof(JArray))) { var newObjList = new List(); var no = 1; - - foreach (var item in dic[key] as JArray) + foreach (var item in dic[key] as IList) + //foreach (var item in dic[key] as JArray) { - var itemDic = JsonConvert.DeserializeObject>(item.ToJsonNotIgnoreNull()); - + //var itemDic = JsonConvert.DeserializeObject>(item.ToJsonNotIgnoreNull()); + var itemDic = item.ConvertToDictionary(); foreach (var needTranslateProperty in needTranslatePropertyList) { //翻译的属性依赖其他属性 if (needTranslateProperty.IsTranslateDenpendOtherProperty) { - if (item[needTranslateProperty.DependPropertyName]?.ToString().ToLower() == needTranslateProperty.DependPropertyValueStr.ToLower()) + if (itemDic[needTranslateProperty.DependPropertyName]?.ToString().ToLower() == needTranslateProperty.DependPropertyValueStr.ToLower()) { var beforeValue = itemDic[needTranslateProperty.Name]?.ToString(); diff --git a/IRaCIS.Core.Application/Helper/FileConvertHelper.cs b/IRaCIS.Core.Application/Helper/FileConvertHelper.cs new file mode 100644 index 000000000..fa6aa2324 --- /dev/null +++ b/IRaCIS.Core.Application/Helper/FileConvertHelper.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace IRaCIS.Core.Application.Helper +{ + public class FileConvertHelper + { + + + static public void ConvertWordToPdf(string inputWordFilePath, string outputPdfDir) + { + // 设置 libreoffice 命令行参数 + string arguments = $"--headless --invisible --convert-to pdf \"{inputWordFilePath}\" --outdir \"{outputPdfDir}\""; + + // 启动 libreoffice 进程 + using (Process process = new Process()) + { + process.StartInfo.FileName = "libreoffice"; + process.StartInfo.Arguments = arguments; + process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; + process.StartInfo.RedirectStandardOutput = true; + process.StartInfo.RedirectStandardError = true; + process.StartInfo.UseShellExecute = false; + process.StartInfo.CreateNoWindow = true; + + process.Start(); + + // 等待进程结束 + process.WaitForExit(); + } + } + + + } +} diff --git a/IRaCIS.Core.Application/Helper/FileStoreHelper.cs b/IRaCIS.Core.Application/Helper/FileStoreHelper.cs index ceaea5e16..9bb7afe8f 100644 --- a/IRaCIS.Core.Application/Helper/FileStoreHelper.cs +++ b/IRaCIS.Core.Application/Helper/FileStoreHelper.cs @@ -142,8 +142,9 @@ public static class FileStoreHelper //API vue 部署目录 public static string GetIRaCISRootPath(IWebHostEnvironment _hostEnvironment) { - var rootPath = (Directory.GetParent(_hostEnvironment.ContentRootPath.TrimEnd('\\'))).IfNullThrowException().FullName; - return rootPath; + string parentDirectory = Path.GetFullPath(Path.Combine(_hostEnvironment.ContentRootPath, "..")); + + return parentDirectory; } @@ -163,7 +164,7 @@ public static class FileStoreHelper { var rootPath = GetIRaCISRootPath(_hostEnvironment); - var physicalFilePath = Path.Combine(rootPath, relativePath.Trim('/')); + var physicalFilePath = Path.Combine(rootPath, relativePath.TrimStart('/')); return physicalFilePath; } @@ -539,7 +540,6 @@ public static class FileStoreHelper /// /// /// - /// /// public static (string PhysicalPath, string RelativePath, string FileRealName) GetUploadPrintscreenFilePath(IWebHostEnvironment _hostEnvironment, string fileName, Guid trialId, Guid siteid, Guid subjectId) { @@ -686,7 +686,7 @@ public static class FileStoreHelper var json = File.ReadAllText( Path.Combine(_hostEnvironment.ContentRootPath, "appsettings.json")); - JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load }); + JObject jsonObject = (JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load })).IfNullThrowException(); int switchingRatio = 80; diff --git a/IRaCIS.Core.Application/Helper/OSSService.cs b/IRaCIS.Core.Application/Helper/OSSService.cs new file mode 100644 index 000000000..26cbd2b3c --- /dev/null +++ b/IRaCIS.Core.Application/Helper/OSSService.cs @@ -0,0 +1,346 @@ +using Aliyun.OSS; +using IRaCIS.Core.Application.Contracts; +using IRaCIS.Core.Infrastructure; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Options; +using Minio.DataModel.Args; +using Minio; +using NPOI.HPSF; +using SharpCompress.Common; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Security.AccessControl; +using System.Text; +using System.Threading.Tasks; +using SkiaSharp; + +namespace IRaCIS.Core.Application.Helper +{ + public class MinIOOptions : AWSOptions + { + public int port { get; set; } + + } + + public class AWSOptions + { + public string endPoint { get; set; } + public bool useSSL { get; set; } + public string accessKey { get; set; } + public string secretKey { get; set; } + public string bucketName { get; set; } + public string viewEndpoint { get; set; } + } + + public class AliyunOSSOptions + { + public string regionId { get; set; } + public string accessKeyId { get; set; } + public string accessKeySecret { get; set; } + public string endPoint { get; set; } + public string bucketName { get; set; } + + public string roleArn { get; set; } + + public string region { get; set; } + + public string viewEndpoint { get; set; } + + } + + public class ObjectStoreServiceOptions + { + public string ObjectStoreUse { get; set; } + public AliyunOSSOptions AliyunOSS { get; set; } + public MinIOOptions MinIO { get; set; } + + public AWSOptions AWS { get; set; } + + } + + public class ObjectStoreDTO + { + public string ObjectStoreUse { get; set; } + + public AliyunOSSOptions AliyunOSS { get; set; } + + public MinIOOptions MinIO { get; set; } + + public AWSOptions AWS { get; set; } + + } + + public class AliyunOSSTempToken + { + public string AccessKeyId { get; set; } + public string AccessKeySecret { get; set; } + public string SecurityToken { get; set; } + public string Expiration { get; set; } + + public string Region { get; set; } + public string BucketName { get; set; } + public string ViewEndpoint { get; set; } + } + + + + public enum ObjectStoreUse + { + AliyunOSS = 0, + MinIO = 1, + AWS = 2, + } + + public interface IOSSService + { + public Task UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName); + public Task UploadToOSSAsync(string localFilePath, string oosFolderPath); + + public Task DownLoadFromOSSAsync(string ossRelativePath, string localFilePath); + + public ObjectStoreServiceOptions ObjectStoreServiceOptions { get; set; } + + } + + + public class OSSService : IOSSService + { + public ObjectStoreServiceOptions ObjectStoreServiceOptions { get; set; } + + + public OSSService(IOptionsMonitor options) + { + ObjectStoreServiceOptions = options.CurrentValue; + } + + /// + /// oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder + /// + /// + /// + /// + /// + public async Task UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName) + { + + + var ossRelativePath = $"{oosFolderPath}/{Guid.NewGuid()}_{fileRealName}"; + //var ossRelativePath = oosFolderPath + "/" + fileRealName; + + using (var memoryStream = new MemoryStream()) + { + fileStream.Seek(0, SeekOrigin.Begin); + + fileStream.CopyTo(memoryStream); + + memoryStream.Seek(0, SeekOrigin.Begin); + + + if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS") + { + var aliConfig = ObjectStoreServiceOptions.AliyunOSS; + + var _ossClient = new OssClient(aliConfig.endPoint, aliConfig.accessKeyId, aliConfig.accessKeySecret); + + + + // 上传文件 + var result = _ossClient.PutObject(aliConfig.bucketName, ossRelativePath, memoryStream); + + } + else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO") + { + var minIOConfig = ObjectStoreServiceOptions.MinIO; + + + var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.endPoint}:{minIOConfig.port}") + .WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL) + .Build(); + + var putObjectArgs = new PutObjectArgs() + .WithBucket(minIOConfig.bucketName) + .WithObject(ossRelativePath) + .WithStreamData(memoryStream) + .WithObjectSize(memoryStream.Length); + + await minioClient.PutObjectAsync(putObjectArgs); + } + else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS") + { + var minIOConfig = ObjectStoreServiceOptions.AWS; + + + var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.endPoint}") + .WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL) + .Build(); + + var putObjectArgs = new PutObjectArgs() + .WithBucket(minIOConfig.bucketName) + .WithObject(ossRelativePath) + .WithStreamData(memoryStream) + .WithObjectSize(memoryStream.Length); + + await minioClient.PutObjectAsync(putObjectArgs); + } + else + { + throw new BusinessValidationFailedException("未定义的存储介质类型"); + } + } + + + return "/" + ossRelativePath; + + } + + + + /// + /// oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder + /// + /// + /// + /// + /// + public async Task UploadToOSSAsync(string localFilePath, string oosFolderPath) + { + var localFileName = Path.GetFileName(localFilePath); + + var ossRelativePath = $"{oosFolderPath}/{Guid.NewGuid()}_{localFileName}"; + + //var ossRelativePath = oosFolderPath + "/" + localFileName; + + + if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS") + { + var aliConfig = ObjectStoreServiceOptions.AliyunOSS; + + var _ossClient = new OssClient(aliConfig.endPoint, aliConfig.accessKeyId, aliConfig.accessKeySecret); + + // 上传文件 + var result = _ossClient.PutObject(aliConfig.bucketName, ossRelativePath, localFilePath); + + } + else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO") + { + var minIOConfig = ObjectStoreServiceOptions.MinIO; + + + var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.endPoint}:{minIOConfig.port}") + .WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL) + .Build(); + + var putObjectArgs = new PutObjectArgs() + .WithBucket(minIOConfig.bucketName) + .WithObject(ossRelativePath) + .WithFileName(localFilePath); + + await minioClient.PutObjectAsync(putObjectArgs); + } + else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS") + { + var minIOConfig = ObjectStoreServiceOptions.AWS; + + + var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.endPoint}") + .WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL) + .Build(); + + var putObjectArgs = new PutObjectArgs() + .WithBucket(minIOConfig.bucketName) + .WithObject(ossRelativePath) + .WithFileName(localFilePath); + + await minioClient.PutObjectAsync(putObjectArgs); + } + else + { + throw new BusinessValidationFailedException("未定义的存储介质类型"); + } + return "/" + ossRelativePath; + + } + + public async Task DownLoadFromOSSAsync(string ossRelativePath, string localFilePath) + { + + ossRelativePath = ossRelativePath.TrimStart('/'); + try + { + + + if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS") + { + var aliConfig = ObjectStoreServiceOptions.AliyunOSS; + + var _ossClient = new OssClient(aliConfig.endPoint, aliConfig.accessKeyId, aliConfig.accessKeySecret); + + // 上传文件 + var result = _ossClient.GetObject(aliConfig.bucketName, ossRelativePath); + + // 将下载的文件流保存到本地文件 + using (var fs = File.OpenWrite(localFilePath)) + { + result.Content.CopyTo(fs); + fs.Close(); + } + + } + else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO") + { + var minIOConfig = ObjectStoreServiceOptions.MinIO; + + var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.endPoint}:{minIOConfig.port}") + .WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL) + .Build(); + + var getObjectArgs = new GetObjectArgs() + .WithBucket(minIOConfig.bucketName) + .WithObject(ossRelativePath) + .WithFile(localFilePath); + + await minioClient.GetObjectAsync(getObjectArgs); + + } + else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS") + { + var minIOConfig = ObjectStoreServiceOptions.AWS; + + var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.endPoint}") + .WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL) + .Build(); + + var getObjectArgs = new GetObjectArgs() + .WithBucket(minIOConfig.bucketName) + .WithObject(ossRelativePath) + .WithFile(localFilePath); + + await minioClient.GetObjectAsync(getObjectArgs); + } + else + { + throw new BusinessValidationFailedException("未定义的存储介质类型"); + } + } + catch (Exception ex) + { + + throw new BusinessValidationFailedException("oss下载失败!" + ex.Message); + } + + + + + + } + + + + + } + + +} diff --git a/IRaCIS.Core.Application/Helper/SendEmailHelper.cs b/IRaCIS.Core.Application/Helper/SendEmailHelper.cs index 57cb50bc1..8cffab084 100644 --- a/IRaCIS.Core.Application/Helper/SendEmailHelper.cs +++ b/IRaCIS.Core.Application/Helper/SendEmailHelper.cs @@ -40,7 +40,7 @@ public static class SendEmailHelper } } - catch (Exception ex) + catch (Exception ) { //---邮件发送失败,您进行的操作未能成功,请检查邮箱或联系维护人员 diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj b/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj index 7c5eedd25..38b149790 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj @@ -89,6 +89,7 @@ + true diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml index 0e30712ac..16d18b105 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -81,7 +81,6 @@ - @@ -95,17 +94,29 @@ + + + oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder + + + + + + + + + oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder + + + + + + 医学审核生成规则 废弃 - - - 产生医学审核 - - - 任务医学审核 @@ -281,6 +292,7 @@ + @@ -490,7 +502,6 @@ - @@ -536,6 +547,32 @@ InternationalizationService + + + 前端国际化内容接口 + + + + + + 前端批量提交,后端判断不存在就添加,存在就更新 + + + + + + 后端之前批量添加接口 + + + + + + + 前后端添加的时候,区分了,前端判断重复多了多了一个路由 路由+标识唯一 + + + + PublishLogService @@ -937,7 +974,8 @@ 翻译稽查数据 - 传入Dto + + @@ -1131,7 +1169,6 @@ 获取阅片报告 - @@ -2468,6 +2505,8 @@ + + @@ -10689,6 +10728,7 @@ + @@ -10697,6 +10737,7 @@ + @@ -10714,6 +10755,7 @@ + @@ -10722,14 +10764,16 @@ + - 加急影像提交 --CRC 待办 + 加急影像提交 --CRC 待办 + @@ -10738,14 +10782,16 @@ + - QC 质疑 + QC 质疑 + @@ -10763,6 +10809,7 @@ IR医学反馈 + @@ -10771,6 +10818,7 @@ + @@ -11019,7 +11067,7 @@ 构造函数注入 - + 构造函数注入 @@ -11556,7 +11604,6 @@ 新增修改系统表格问题 - @@ -11581,11 +11628,12 @@ - 验证计算关系 + 验证计算关系 + @@ -11851,6 +11899,8 @@ + + @@ -11893,11 +11943,18 @@ - 获取子元素 + 获取子元素 + + + + + + + @@ -12382,6 +12439,12 @@ + + + 维护OSS 影像数据 + + + Reviewer 列表查询参数 diff --git a/IRaCIS.Core.Application/Service/Allocation/TaskMedicalReviewRuleService.cs b/IRaCIS.Core.Application/Service/Allocation/TaskMedicalReviewRuleService.cs index 8b27e8f75..1c25af2f0 100644 --- a/IRaCIS.Core.Application/Service/Allocation/TaskMedicalReviewRuleService.cs +++ b/IRaCIS.Core.Application/Service/Allocation/TaskMedicalReviewRuleService.cs @@ -78,120 +78,7 @@ namespace IRaCIS.Core.Application.Service return ResponseOutput.Ok(); } - /// - /// 产生医学审核 - /// - /// - [Obsolete] - public async Task GenerateMedicalReviewTask(GenerateMedicalReviewTaskCommand generateCommand) - { - var trialId = generateCommand.TrialId; - //var mimUserList = await _trialUserRepository.Where(t => t.User.UserTypeEnum == Domain.Share.UserTypeEnum.MIM && t.TrialId == trialId).Select(t => t.User).ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); - - - - Guid? defalutMIMUserId = null /*mimUserList.FirstOrDefault()?.UserId*/; - - //获取当前医生数据 已经生成的,和配置的数量 - var taskTaskMedicalReviewRuleList = await _taskMedicalReviewRuleRepository.Where(t => t.TrialId == trialId).ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); - - foreach (var item in taskTaskMedicalReviewRuleList) - { - - if (item.IsEnable) - { - - if (item.PlanGlobalCount > item.GeneratedGlobalCount) - { - var needGenerateCount = item.PlanGlobalCount - item.GeneratedGlobalCount; - - var canGenerateCount = item.ActualGlobalCount - item.GeneratedGlobalCount; - - var toGenerateCount = canGenerateCount > needGenerateCount ? needGenerateCount : canGenerateCount; - - //分配给MIM - - if (toGenerateCount > 0) - { - var toGenerateTaskList = item.ActualGlobalTaskList.ExceptBy(item.GeneratedGlobalTaskList.Select(t => t.TaskId), t => t.TaskId).Take(toGenerateCount).ToList(); - - foreach (var toGenerateTask in toGenerateTaskList) - { - await _taskMedicalReviewRepository.AddAsync(new TaskMedicalReview() { DoctorUserId = toGenerateTask.DoctorUserId!.Value, TrialId = toGenerateTask.TrialId, VisitTaskId = toGenerateTask.TaskId, MedicalManagerUserId = defalutMIMUserId }); - } - } - - - } - if (item.PlanJudgeCount > item.GeneratedJudgeCount) - { - var needGenerateCount = item.PlanJudgeCount - item.GeneratedJudgeCount; - - var canGenerateCount = item.ActualJudgeCount - item.GeneratedGlobalCount; - - var toGenerateCount = canGenerateCount > needGenerateCount ? needGenerateCount : canGenerateCount; - - if (toGenerateCount > 0) - { - var toGenerateTaskList = item.ActualJudgeTaskList.ExceptBy(item.GeneratedJudgeTaskList.Select(t => t.TaskId), t => t.TaskId).Take(toGenerateCount).ToList(); - - foreach (var toGenerateTask in toGenerateTaskList) - { - await _taskMedicalReviewRepository.AddAsync(new TaskMedicalReview() { DoctorUserId = toGenerateTask.DoctorUserId!.Value, TrialId = toGenerateTask.TrialId, VisitTaskId = toGenerateTask.TaskId, MedicalManagerUserId = defalutMIMUserId }); - } - } - - } - if (item.PlanTumorCount > item.GeneratedTumorCount) - { - var needGenerateCount = item.PlanTumorCount - item.GeneratedTumorCount; - - var canGenerateCount = item.ActualTumorCount - item.GeneratedGlobalCount; - - var toGenerateCount = canGenerateCount > needGenerateCount ? needGenerateCount : canGenerateCount; - - if (toGenerateCount > 0) - { - var toGenerateTaskList = item.ActualTumorTaskList.ExceptBy(item.GeneratedTumorTaskList.Select(t => t.TaskId), t => t.TaskId).Take(toGenerateCount).ToList(); - - foreach (var toGenerateTask in toGenerateTaskList) - { - await _taskMedicalReviewRepository.AddAsync(new TaskMedicalReview() { DoctorUserId = toGenerateTask.DoctorUserId!.Value, TrialId = toGenerateTask.TrialId, VisitTaskId = toGenerateTask.TaskId, MedicalManagerUserId = defalutMIMUserId }); - } - } - - } - if (item.PlanVisitCount > item.GeneratedVisitCount) - { - var needGenerateCount = item.PlanVisitCount - item.GeneratedVisitCount; - - var canGenerateCount = item.ActualVisitCount - item.GeneratedGlobalCount; - - var toGenerateCount = canGenerateCount > needGenerateCount ? needGenerateCount : canGenerateCount; - - if (toGenerateCount > 0) - { - - var toGenerateTaskList = item.ActualVisitTaskList.ExceptBy(item.GeneratedVisitTaskList.Select(t => t.TaskId), t => t.TaskId).Take(toGenerateCount).ToList(); - - foreach (var toGenerateTask in toGenerateTaskList) - { - await _taskMedicalReviewRepository.AddAsync(new TaskMedicalReview() { DoctorUserId = toGenerateTask.DoctorUserId!.Value, TrialId = toGenerateTask.TrialId, VisitTaskId = toGenerateTask.TaskId, MedicalManagerUserId = defalutMIMUserId }); - } - } - - } - - } - - } - - - await _taskMedicalReviewRepository.SaveChangesAsync(); - return ResponseOutput.Ok(); - - } } diff --git a/IRaCIS.Core.Application/Service/Allocation/VisitTaskHelpeService.cs b/IRaCIS.Core.Application/Service/Allocation/VisitTaskHelpeService.cs index 548987b2b..a8a98d348 100644 --- a/IRaCIS.Core.Application/Service/Allocation/VisitTaskHelpeService.cs +++ b/IRaCIS.Core.Application/Service/Allocation/VisitTaskHelpeService.cs @@ -233,83 +233,8 @@ namespace IRaCIS.Core.Application.Service && t.TrialReadingCriterionId == trialReadingCriterionConfig.TrialReadingCriterionId && t.TaskState == TaskState.Effect && t.SourceSubjectVisitId == subjectVisit.Id).ToList(); - if (trialReadingCriterionConfig.ReadingType == ReadingMethod.Double) - { - - - VisitTask? task1 = existCurrentVisitTaskList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm1); - VisitTask? task2 = existCurrentVisitTaskList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm2); - - if (!existCurrentVisitTaskList.Any(t => t.ArmEnum == Arm.DoubleReadingArm1)) - { - currentMaxCodeInt = currentMaxCodeInt + 1; - - - - - task1 = await _visitTaskRepository.AddAsync(new VisitTask() - { - TrialId = trialId, - SubjectId = subjectVisit.SubjectId, - IsUrgent = subjectVisit.IsUrgent, - TaskBlindName = blindTaskName, - TaskName = subjectVisit.VisitName, - VisitTaskNum = subjectVisit.VisitNum, - TaskUrgentType = taskUrgentType, - IsCanEditUrgentState = isCanEditUrgentState, - //CheckPassedTime = subjectVisit.CheckPassedTime, - ArmEnum = Arm.DoubleReadingArm1,//特殊 - Code = currentMaxCodeInt, - SourceSubjectVisitId = subjectVisit.Id, - TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt, nameof(VisitTask)), - ReadingCategory = ReadingCategory.Visit, - - TrialReadingCriterionId = trialReadingCriterionConfig.TrialReadingCriterionId, - IsNeedClinicalDataSign = isNeedClinicalDataSign, - IsClinicalDataSign = isClinicalDataSign - }); - - } - - if (!existCurrentVisitTaskList.Any(t => t.ArmEnum == Arm.DoubleReadingArm2)) - { - currentMaxCodeInt = currentMaxCodeInt + 1; - - - task2 = await _visitTaskRepository.AddAsync(new VisitTask() - { - TrialId = trialId, - SubjectId = subjectVisit.SubjectId, - IsUrgent = subjectVisit.IsUrgent, - TaskBlindName = blindTaskName, - TaskName = subjectVisit.VisitName, - TaskUrgentType = taskUrgentType, - IsCanEditUrgentState = isCanEditUrgentState, - VisitTaskNum = subjectVisit.VisitNum, - //CheckPassedTime = subjectVisit.CheckPassedTime, - ArmEnum = Arm.DoubleReadingArm2,//特殊 - Code = currentMaxCodeInt, - SourceSubjectVisitId = subjectVisit.Id, - TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt, nameof(VisitTask)), - ReadingCategory = ReadingCategory.Visit, - - TrialReadingCriterionId = trialReadingCriterionConfig.TrialReadingCriterionId, - IsNeedClinicalDataSign = isNeedClinicalDataSign, - IsClinicalDataSign = isClinicalDataSign - }); - - - } - - _provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30)); - - - - - var defaultState = trialReadingCriterionConfig.FollowVisitAutoAssignDefaultState == TaskAllocateDefaultState.InitAllocated ? TaskAllocationState.InitAllocated : TaskAllocationState.Allocated; - - } - else if (trialReadingCriterionConfig.ReadingType == ReadingMethod.Single) + //只有单重阅片 + if (trialReadingCriterionConfig.ReadingType == ReadingMethod.Single) { VisitTask? singleTask = existCurrentVisitTaskList.FirstOrDefault(t => t.ArmEnum == Arm.SingleReadingArm); @@ -336,8 +261,12 @@ namespace IRaCIS.Core.Application.Service ReadingCategory = ReadingCategory.Visit, TrialReadingCriterionId = trialReadingCriterionConfig.TrialReadingCriterionId, IsNeedClinicalDataSign = isNeedClinicalDataSign, - IsClinicalDataSign = isClinicalDataSign - }); + IsClinicalDataSign = isClinicalDataSign, + + SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget) + + + }); } @@ -620,6 +549,7 @@ namespace IRaCIS.Core.Application.Service var isNeedClinicalDataSign = IsNeedClinicalDataSign(ReadingCategory.Visit, subjectVisit.IsBaseLine, trialReadingCriterionId, clinicalDataConfirmList); var isClinicalDataSign = IsClinicalDataSign(ReadingCategory.Visit, subjectVisit.IsBaseLine, trialReadingCriterionId, clinicalDataConfirmList, subjectVisit.Id, trialId); + var isFrontTaskNeedSignButNotSign = await _visitTaskRepository.AnyAsync(t => t.TrialReadingCriterionId == trialReadingCriterionId && t.SubjectId == subjectVisit.SubjectId && t.TaskState == TaskState.Effect && t.VisitTaskNum < subjectVisit.VisitNum && t.IsNeedClinicalDataSign == true && t.IsClinicalDataSign == false); if (visitNumList.IndexOf(subjectVisit.VisitNum) == 0) { @@ -661,7 +591,8 @@ namespace IRaCIS.Core.Application.Service TrialReadingCriterionId = trialReadingCriterionConfig.TrialReadingCriterionId, IsNeedClinicalDataSign = isNeedClinicalDataSign, - IsClinicalDataSign = isClinicalDataSign + IsClinicalDataSign = isClinicalDataSign, + IsFrontTaskNeedSignButNotSign= isFrontTaskNeedSignButNotSign }); @@ -681,11 +612,11 @@ namespace IRaCIS.Core.Application.Service //之前有回退到影像上传的访视 那么当前访视一致性核查通过的时候,当前访视生成但是不分配出去(排除失访的) var beforeBackVisitTask = await _visitTaskRepository.Where(t => t.TrialId == trialId && t.SubjectId == subjectVisit.SubjectId && t.TrialReadingCriterionId== trialReadingCriterionId && t.VisitTaskNum < subjectVisit.VisitNum && t.ReadingCategory == ReadingCategory.Visit && t.SourceSubjectVisit.CheckState != CheckStateEnum.CVPassed && t.SourceSubjectVisit.IsLostVisit == false).OrderBy(t => t.VisitTaskNum).FirstOrDefaultAsync(); + singleTask.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget); if (beforeBackVisitTask == null) { - singleTask.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget); var followBackVisitTask = await _visitTaskRepository.Where(t => t.TrialId == trialId && t.SubjectId == subjectVisit.SubjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.VisitTaskNum > subjectVisit.VisitNum && t.ReadingCategory == ReadingCategory.Visit && t.SourceSubjectVisit.CheckState != CheckStateEnum.CVPassed && t.SourceSubjectVisit.IsLostVisit == false).OrderBy(t => t.VisitTaskNum).FirstOrDefaultAsync(); @@ -765,7 +696,11 @@ namespace IRaCIS.Core.Application.Service } + else + { + singleTask.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget); + } #endregion @@ -876,6 +811,8 @@ namespace IRaCIS.Core.Application.Service // AllocateTime = DateTime.Now, //DoctorUserId = reReadingVisitTask.DoctorUserId, + SuggesteFinishedTime= reReadingVisitTask.SuggesteFinishedTime, + }); generateTaskCommand.Action(newTask); diff --git a/IRaCIS.Core.Application/Service/Allocation/VisitTaskService.cs b/IRaCIS.Core.Application/Service/Allocation/VisitTaskService.cs index 55c545aee..1df7e3627 100644 --- a/IRaCIS.Core.Application/Service/Allocation/VisitTaskService.cs +++ b/IRaCIS.Core.Application/Service/Allocation/VisitTaskService.cs @@ -642,13 +642,11 @@ namespace IRaCIS.Core.Application.Service.Allocation /// 获取有序阅片IQuery对象 /// /// - /// public async Task<(int, List)> GetOrderReadingIQueryable(GetOrderReadingIQueryableInDto inDto) { var trialReadingCriterionId = inDto.TrialReadingCriterionId; - //Expression> visitTaskLambda = x => x.DoctorUserId == _userInfo.Id && x.TaskState == TaskState.Effect && x.TrialReadingCriterionId == inDto.TrialReadingCriterionId; var critrion = await _trialReadingCriterionRepository.FindAsync(trialReadingCriterionId); @@ -844,7 +842,7 @@ namespace IRaCIS.Core.Application.Service.Allocation var requestRecordList = await _visitTaskReReadingRepository.Where(t => baseLineTaskIdList.Contains(t.OriginalReReadingTaskId) && t.RequestReReadingUserId == _userInfo.Id && t.RequestReReadingReason == "AIR自动重阅基线").ToListAsync(); - if (requestRecordList.Count() != baseLineTaskIdList.Count()) + if (requestRecordList.Count != baseLineTaskIdList.Count) { //---后台数据有错误 return ResponseOutput.NotOk(_localizer["VisitTask_DoctorConfiguration"]); @@ -967,6 +965,7 @@ namespace IRaCIS.Core.Application.Service.Allocation /// /// /// + /// private void ReReadingTaskTrackingDeal(VisitTask origenalTask, ConfirmReReadingCommand agreeReReadingCommand) { if (origenalTask.ReReadingApplyState == ReReadingApplyState.DocotorHaveApplyed || origenalTask.ReReadingApplyState == ReReadingApplyState.TrialGroupHaveApplyed) @@ -1548,7 +1547,10 @@ namespace IRaCIS.Core.Application.Service.Allocation #region 方式二 - var origenalTask = influenceTaskList.Where(t => t.Id == task.Id).FirstOrDefault(); + //var origenalTask = influenceTaskList.Where(t => t.Id == task.Id).FirstOrDefault(); + + var origenalTask = await _visitTaskRepository.FindAsync(task.Id); + foreach (var influenceTask in influenceTaskList) { @@ -1611,7 +1613,9 @@ namespace IRaCIS.Core.Application.Service.Allocation await SetMedicalReviewInvalidAsync(currentVisitList); - var origenalTask = currentVisitList.Where(t => t.Id == task.Id).First(); + //var origenalTask = currentVisitList.Where(t => t.Id == task.Id).First(); + + var origenalTask = await _visitTaskRepository.FindAsync(task.Id); foreach (var influenceTask in currentVisitList) { diff --git a/IRaCIS.Core.Application/Service/Common/CommonDocumentService.cs b/IRaCIS.Core.Application/Service/Common/CommonDocumentService.cs index bc7db9531..0171c67c2 100644 --- a/IRaCIS.Core.Application/Service/Common/CommonDocumentService.cs +++ b/IRaCIS.Core.Application/Service/Common/CommonDocumentService.cs @@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Mvc; using IRaCIS.Core.Application.Interfaces; using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Application.Helper; +using IRaCIS.Application.Contracts; namespace IRaCIS.Core.Application.Service { @@ -99,14 +100,36 @@ namespace IRaCIS.Core.Application.Service //---读取模板内容失败, 请将文件另存为docx格式尝试! return ResponseOutput.NotOk(_localizer["Document_ TemplateRead"]); } - - } } - var entity = await _commonDocumentRepository.InsertOrUpdateAsync(addOrEditCommonDocument, true, verifyExp1, verifyExp2); + + if (addOrEditCommonDocument.Id == null) //insert + { - return ResponseOutput.Ok(entity.Id.ToString()); + + var entity = await _commonDocumentRepository.InsertFromDTOAsync(addOrEditCommonDocument, true, verifyExp1, verifyExp2); + + return ResponseOutput.Ok(entity.Id.ToString()); + } + else //update + { + + var dbbeforeEntity = await _commonDocumentRepository.UpdateFromDTOAsync(addOrEditCommonDocument, true, true, verifyExp1, verifyExp2); + + var filePath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, dbbeforeEntity.Path); + + if (File.Exists(filePath)) + { + File.Delete(filePath); + } + + return ResponseOutput.Ok(); + + } + + + } @@ -114,7 +137,20 @@ namespace IRaCIS.Core.Application.Service [HttpDelete("{commonDocumentId:guid}")] public async Task DeleteCommonDocument(Guid commonDocumentId) { + var find= await _commonDocumentRepository.FirstOrDefaultNoTrackingAsync(t=>t.Id== commonDocumentId); + var success = await _commonDocumentRepository.DeleteFromQueryAsync(t => t.Id == commonDocumentId, true,true); + + if (find != null) + { + var filePath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, find.Path); + + if (File.Exists(filePath)) + { + File.Delete(filePath); + } + } + return ResponseOutput.Ok(); } diff --git a/IRaCIS.Core.Application/Service/Common/DTO/InternationalizationViewModel.cs b/IRaCIS.Core.Application/Service/Common/DTO/InternationalizationViewModel.cs index 16ed714b1..c6b7567b3 100644 --- a/IRaCIS.Core.Application/Service/Common/DTO/InternationalizationViewModel.cs +++ b/IRaCIS.Core.Application/Service/Common/DTO/InternationalizationViewModel.cs @@ -42,6 +42,8 @@ namespace IRaCIS.Core.Application.ViewModel public string Value { get; set; } = string.Empty; public string ValueCN { get; set; } = string.Empty; + public string FrontType { get; set; } = string.Empty; + public int InternationalizationType { get; set; } } @@ -55,19 +57,23 @@ namespace IRaCIS.Core.Application.ViewModel } - public class BatchAddInternationalizationDto + public class BatchInternationalizationDto { public string Description { get; set; } = string.Empty; public string Code { get; set; } = string.Empty; public string Value { get; set; } = string.Empty; + public string FrontType { get; set; } = string.Empty; public string ValueCN { get; set; } = string.Empty; } - public class InternationalizationSimpleDto + public class BatchAddInternationalizationDto : BatchInternationalizationDto { - public string Code { get; set; } = string.Empty; - public string Value { get; set; } = string.Empty; - public string ValueCN { get; set; } = string.Empty; + + } + + public class InternationalizationSimpleDto: BatchInternationalizationDto + { + } } diff --git a/IRaCIS.Core.Application/Service/Common/DictionaryService.cs b/IRaCIS.Core.Application/Service/Common/DictionaryService.cs index 82a48b05a..dc975abe1 100644 --- a/IRaCIS.Core.Application/Service/Common/DictionaryService.cs +++ b/IRaCIS.Core.Application/Service/Common/DictionaryService.cs @@ -25,7 +25,6 @@ namespace IRaCIS.Application.Services private readonly IRepository _readingCriterionDictionaryRepository; private readonly IRepository _readingQuestionCriterionSystem; private readonly IRepository _readingQuestionCriterionTrial; - private readonly IReadingQuestionService _readingQuestionService; public DictionaryService(IRepository sysDicRepository, IRepository trialDictionaryRepository, IRepository trialRepository, @@ -35,8 +34,7 @@ namespace IRaCIS.Application.Services IRepository readingTrialCriterionDictionaryRepository, IRepository readingCriterionDictionaryRepository, IRepository readingQuestionCriterionSystem, - IRepository readingQuestionCriterionTrial, - IReadingQuestionService readingQuestionService + IRepository readingQuestionCriterionTrial ) @@ -52,7 +50,6 @@ namespace IRaCIS.Application.Services this._readingCriterionDictionaryRepository = readingCriterionDictionaryRepository; this._readingQuestionCriterionSystem = readingQuestionCriterionSystem; this._readingQuestionCriterionTrial = readingQuestionCriterionTrial; - this._readingQuestionService = readingQuestionService; } /// diff --git a/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs b/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs index fe9b30582..f8ae0b644 100644 --- a/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs +++ b/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs @@ -970,7 +970,6 @@ namespace IRaCIS.Core.Application.Service.Common /// /// /// - /// /// [HttpPost] public async Task GetGroupAnalysisTaskList_Export(VisitTaskQuery queryVisitTask, diff --git a/IRaCIS.Core.Application/Service/Common/InternationalizationService.cs b/IRaCIS.Core.Application/Service/Common/InternationalizationService.cs index efdcd51e5..46ed1e447 100644 --- a/IRaCIS.Core.Application/Service/Common/InternationalizationService.cs +++ b/IRaCIS.Core.Application/Service/Common/InternationalizationService.cs @@ -10,6 +10,9 @@ using IRaCIS.Core.Application.Interfaces; using IRaCIS.Core.Application.ViewModel; using Microsoft.AspNetCore.Authorization; using IRaCIS.Core.Application.Helper; +using EasyCaching.Core; +using IRaCIS.Core.Domain.Share; +using OfficeOpenXml.FormulaParsing.Utilities; namespace IRaCIS.Core.Application.Service { @@ -19,28 +22,77 @@ namespace IRaCIS.Core.Application.Service [ApiExplorerSettings(GroupName = "Common")] public class InternationalizationService : BaseService, IInternationalizationService { - + private readonly IEasyCachingProvider _provider; private readonly IRepository _internationalizationRepository; - public InternationalizationService(IRepository internationalizationRepository) + public InternationalizationService(IRepository internationalizationRepository, IEasyCachingProvider provider) { _internationalizationRepository = internationalizationRepository; + _provider = provider; } - + /// + /// 前端国际化内容接口 + /// + /// [AllowAnonymous] - - public async Task> GetFrontInternationalizationList() + [HttpGet] + public async Task> GetFrontInternationalizationList() { + var cacheList= _provider.Get>(StaticData.InternationalData.Front).Value; - var list = await _internationalizationRepository.Where(t => t.InternationalizationType == 0).Select(t => new InternationalizationSimpleDto() + if(cacheList != null && cacheList.Count!=0) { - Code = t.Code, - Value = t.Value, - ValueCN = t.ValueCN - }).ToListAsync(); + return cacheList; + } + else + { + var list = await _internationalizationRepository.Where(t => t.InternationalizationType == 0).Select(t => new InternationalizationSimpleDto() + { + Code = t.Code, + Value = t.Value, + ValueCN = t.ValueCN, + FrontType = t.FrontType, + Description = t.Description, + }).ToListAsync(); - return list; + _provider.Set>(StaticData.InternationalData.Front, list, TimeSpan.FromDays(1)); + + return list; + } + + } + + /// + /// 前端批量提交,后端判断不存在就添加,存在就更新 + /// + /// + [AllowAnonymous] + public async Task BatchAddOrUpdateFrontInternationalization(List batchList) + { + foreach (var item in batchList) + { + var find = await _internationalizationRepository.FirstOrDefaultAsync(t => t.Code == item.Code && t.Description == item.Description && t.InternationalizationType == 0); + + if (find != null) + { + _mapper.Map(item, find); + } + else + { + var mapItem = _mapper.Map(item); + mapItem.InternationalizationType = 0; + mapItem.State = 1; + + await _internationalizationRepository.AddAsync(mapItem); + } + } + await _internationalizationRepository.SaveChangesAsync(); + + //清理缓存 + _provider.Set>(StaticData.InternationalData.Front, new List(), TimeSpan.FromDays(1)); + + return ResponseOutput.Ok(); } [HttpPost] @@ -63,6 +115,11 @@ namespace IRaCIS.Core.Application.Service return pageList; } + /// + /// 后端之前批量添加接口 + /// + /// + /// [HttpPost] public async Task BatchAddInternationalization(BatchAddInternationalization batchAdd) { @@ -91,17 +148,34 @@ namespace IRaCIS.Core.Application.Service return ResponseOutput.Ok(); } + /// + /// 前后端添加的时候,区分了,前端判断重复多了多了一个路由 路由+标识唯一 + /// + /// + /// public async Task AddOrUpdateInternationalization(InternationalizationAddOrEdit addOrEditInternationalization) { + var internationalizationType = addOrEditInternationalization.InternationalizationType; + + //后端验证标识重复与否 var verifyExp1 = new EntityVerifyExp() { VerifyExp = t => t.Code == addOrEditInternationalization.Code && t.InternationalizationType == addOrEditInternationalization.InternationalizationType, VerifyMsg = $"该类型已有{addOrEditInternationalization.Code}名称的国际化标识", - IsVerify = true + IsVerify = internationalizationType == 1 }; - var entity = await _internationalizationRepository.InsertOrUpdateAsync(addOrEditInternationalization, true, verifyExp1); + //前端验证标识重复与否 + var verifyExp2 = new EntityVerifyExp() + { + VerifyExp = t => t.Code == addOrEditInternationalization.Code && t.InternationalizationType == addOrEditInternationalization.InternationalizationType && t.Description == addOrEditInternationalization.Description, + + VerifyMsg = $"该类型已有{addOrEditInternationalization.Description}下的{addOrEditInternationalization.Code}名称的国际化标识", + IsVerify = internationalizationType == 0 + }; + + var entity = await _internationalizationRepository.InsertOrUpdateAsync(addOrEditInternationalization, true, verifyExp1, verifyExp2); if (addOrEditInternationalization.InternationalizationType == 1) { diff --git a/IRaCIS.Core.Application/Service/Common/MailService.cs b/IRaCIS.Core.Application/Service/Common/MailService.cs index d821708b6..e8be06736 100644 --- a/IRaCIS.Core.Application/Service/Common/MailService.cs +++ b/IRaCIS.Core.Application/Service/Common/MailService.cs @@ -42,12 +42,10 @@ namespace IRaCIS.Application.Services private readonly IRepository _systemBasicDatarepository; - private readonly IWebHostEnvironment _hostEnvironment; private readonly IRepository _userRepository; private readonly ITokenService _tokenService; - private readonly IMapper _mapper; private readonly IRepository _trialRepository; private readonly IRepository _userTypeRepository; @@ -61,7 +59,6 @@ namespace IRaCIS.Application.Services public MailVerificationService(IRepository verificationCodeRepository, IRepository systemBasicDatarepository, - IWebHostEnvironment hostEnvironment, IRepository userRepository, ITokenService tokenService, IRepository trialRepository, @@ -72,9 +69,7 @@ namespace IRaCIS.Application.Services _verificationCodeRepository = verificationCodeRepository; _systemBasicDatarepository = systemBasicDatarepository; - _hostEnvironment = hostEnvironment; - _mapper = mapper; _tokenService = tokenService; _userRepository = userRepository; @@ -163,7 +158,7 @@ namespace IRaCIS.Application.Services messageToSend.To.Add(new MailboxAddress(String.Empty, emailAddress)); //主题 //---[来自展影IRC] 关于重置密码的提醒 - messageToSend.Subject = _localizer["Mail_IRCResettingPassword "]; + messageToSend.Subject = _localizer["Mail_IRCResettingPassword"]; @@ -182,8 +177,9 @@ namespace IRaCIS.Application.Services builder.HtmlBody = string.Format(templateInfo, + "", //---您正在进行邮箱重置密码操作 - _localizer["Mail_ResettingPassword "], + _localizer["Mail_ResettingPassword"], verificationCode ); } @@ -249,6 +245,7 @@ namespace IRaCIS.Application.Services builder.HtmlBody = string.Format(templateInfo, + "", //---您正在参与展影医疗IRC项目 _localizer["Mail_IRCProject"], verificationCode @@ -315,6 +312,7 @@ namespace IRaCIS.Application.Services builder.HtmlBody = string.Format(templateInfo, + "", //---您正在参与展影医疗IRC项目中心调研工作 _localizer["Mail_CenterResearchReminder"], verificationCode diff --git a/IRaCIS.Core.Application/Service/Common/_MapConfig.cs b/IRaCIS.Core.Application/Service/Common/_MapConfig.cs index f157924cb..c8c297ede 100644 --- a/IRaCIS.Core.Application/Service/Common/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/Common/_MapConfig.cs @@ -74,6 +74,9 @@ namespace IRaCIS.Core.Application.Service CreateMap(); CreateMap().ReverseMap(); + CreateMap().ReverseMap(); + + CreateMap(); diff --git a/IRaCIS.Core.Application/Service/Document/EmailSendService.cs b/IRaCIS.Core.Application/Service/Document/EmailSendService.cs index bb89f92f1..0e92fb158 100644 --- a/IRaCIS.Core.Application/Service/Document/EmailSendService.cs +++ b/IRaCIS.Core.Application/Service/Document/EmailSendService.cs @@ -31,6 +31,8 @@ namespace IRaCIS.Core.Application.Service Task SendTrialQCQuestionEmailAsync(Guid trialId); Task SendTrialImageQuestionAsync(Guid trialId); Task SendPIAuditResultAsync(Guid visitTaskId); + + Task<(TrialEmailNoticeConfig?, SMTPEmailConfig?)> BuildEmailConfig(Guid trialId, EmailBusinessScenario businessScenario, Func topicAndHtmlFunc, Guid? siteId = null, Guid? trialReadingCriterionId = null); } public class EmailSendService : BaseService, IEmailSendService @@ -41,18 +43,19 @@ namespace IRaCIS.Core.Application.Service private readonly IRepository _trialRepository; - private readonly IDictionaryService _dictionaryService; private readonly IOptionsMonitor _SystemEmailSendConfig; public readonly static string EmailNamePlaceholder = "EmailNamePlaceholder"; - public EmailSendService(IRepository trialEmailNoticeConfigRepository, IRepository emailNoticeConfigRepository, IRepository trialRepository, IOptionsMonitor systemEmailSendConfig, IDictionaryService dictionaryService) + private readonly IRepository _dictionaryRepository; + + public EmailSendService(IRepository trialEmailNoticeConfigRepository, IRepository emailNoticeConfigRepository, IRepository trialRepository, IOptionsMonitor systemEmailSendConfig,IRepository dictionaryRepository) { _trialEmailNoticeConfigRepository = trialEmailNoticeConfigRepository; _emailNoticeConfigRepository = emailNoticeConfigRepository; _trialRepository = trialRepository; _SystemEmailSendConfig = systemEmailSendConfig; - _dictionaryService = dictionaryService; + _dictionaryRepository=dictionaryRepository; } //入组确认/PD确认 @@ -309,7 +312,11 @@ namespace IRaCIS.Core.Application.Service var needTranslateDicNameList = answerList.Where(t => !string.IsNullOrEmpty(t.DictionaryCode)).Select(t => t.DictionaryCode).ToList(); - var translateDataList = await _dictionaryService.GetBasicDataSelect(needTranslateDicNameList.ToArray()); + + var searchList = await _dictionaryRepository.Where(t => needTranslateDicNameList.ToArray().Contains(t.Parent.Code) && t.ParentId != null && t.IsEnable).ProjectTo(_mapper.ConfigurationProvider, new { isEn_Us = _userInfo.IsEn_Us }).ToListAsync(); + + var translateDataList = searchList.GroupBy(t => t.ParentCode).ToDictionary(g => g.Key, g => g.OrderBy(t => t.ShowOrder).ToList()); + Func transFunc = (bool isNeedTranslate, string dicCode, string answer) => @@ -349,7 +356,7 @@ namespace IRaCIS.Core.Application.Service .Include(t => t.TrialEmailNoticeUserList).Include(t => t.TrialEmailBlackUserList).FirstOrDefaultAsync(); - if (trialEmailConfig == null || trialEmailConfig.IsAutoSend == false) + if (trialEmailConfig == null || trialEmailConfig.IsAutoSend == false || trialEmailConfig.IsEnable==false) { return; } @@ -414,7 +421,7 @@ namespace IRaCIS.Core.Application.Service sendEmailConfig.HtmlBodyStr = htmlBodyStr.Replace(EmailNamePlaceholder, string.Join(isEn_us ? ", " : "、", toUserList.Select(t => t.FullName).ToList())); } - if (toUserList.Count() == 0) + if (toUserList.Count == 0) { //---没有收件人,无法发送邮件 throw new BusinessValidationFailedException(_localizer["TrialEmailN_NoRecipient"]); @@ -463,6 +470,142 @@ namespace IRaCIS.Core.Application.Service } } + public async Task<(TrialEmailNoticeConfig?, SMTPEmailConfig?)> BuildEmailConfig(Guid trialId, EmailBusinessScenario businessScenario, Func topicAndHtmlFunc, Guid? siteId = null, Guid? trialReadingCriterionId = null) + { + //找到配置 + var trialEmailConfig = await _trialEmailNoticeConfigRepository.Where(t => t.TrialId == trialId && t.TrialReadingCriterionId == trialReadingCriterionId && t.BusinessScenarioEnum == businessScenario, ignoreQueryFilters: true) + .Include(t => t.TrialEmailNoticeUserList).Include(t => t.TrialEmailBlackUserList).FirstOrDefaultAsync(); + + + if (trialEmailConfig == null || trialEmailConfig.IsAutoSend == false || trialEmailConfig.IsEnable==false) + { + return (null, null); + } + else + { + var sendEmailConfig = new SMTPEmailConfig(); + + var (topicStr, htmlBodyStr, isEn_us, onlyToUserId) = topicAndHtmlFunc(trialEmailConfig); + + + sendEmailConfig.TopicDescription = topicStr; + sendEmailConfig.HtmlBodyStr = htmlBodyStr; + + + var blackUserIdList = trialEmailConfig.TrialEmailBlackUserList.Select(t => t.UserId).ToList(); + + + var toUserTypeEnumList = trialEmailConfig.TrialEmailNoticeUserList.Where(t => t.EmailUserType == EmailUserType.To).Select(c => c.UserType).ToList(); + + var copyUserTypeEnumList = trialEmailConfig.TrialEmailNoticeUserList.Where(t => t.EmailUserType == EmailUserType.Copy).Select(c => c.UserType).ToList(); + + var allUserTypeEnumList = toUserTypeEnumList.Union(copyUserTypeEnumList).Distinct().ToList(); + + var allUserList = await _repository.Where(t => t.TrialId == trialId && allUserTypeEnumList.Contains(t.User.UserTypeEnum)).Select(t => new { t.UserId, t.User.EMail, t.User.FullName, t.User.UserTypeEnum }).ToListAsync(); + + + var toUserList = allUserList.Where(t => toUserTypeEnumList.Contains(t.UserTypeEnum)) + .ToList(); + + //收件人 有CRC CRA , CRC CRA的账户要按照中心发送 + if (siteId == null && toUserTypeEnumList.Any(t => t == UserTypeEnum.ClinicalResearchCoordinator || t == UserTypeEnum.CRA) && onlyToUserId == null) + { + throw new BusinessValidationFailedException("当前场景收件人包含CRC CRA,但是没有siteId,请联系后端开发"); + } + if (siteId != null && toUserTypeEnumList.Any(t => t == UserTypeEnum.ClinicalResearchCoordinator || t == UserTypeEnum.CRA)) + { + var curentSiteUserIdList = _repository.Where(t => t.TrialId == trialId && t.SiteId == siteId).Select(t => t.UserId).ToList(); + + toUserList = toUserList.Where(t => (t.UserTypeEnum != UserTypeEnum.CRA && t.UserTypeEnum != UserTypeEnum.ClinicalResearchCoordinator) || curentSiteUserIdList.Contains(t.UserId)).ToList(); + } + + + //去除黑名单 + toUserList = toUserList.Where(t => !blackUserIdList.Contains(t.UserId)).ToList(); + + var copyUserList = allUserList.Where(t => copyUserTypeEnumList.Contains(t.UserTypeEnum)) + .Where(t => !blackUserIdList.Contains(t.UserId)).ToList(); + + if (siteId != null && copyUserTypeEnumList.Any(t => t == UserTypeEnum.ClinicalResearchCoordinator || t == UserTypeEnum.CRA)) + { + var curentSiteUserIdList = _repository.Where(t => t.TrialId == trialId && t.SiteId == siteId).Select(t => t.UserId).ToList(); + + copyUserList = copyUserList.Where(t => (t.UserTypeEnum != UserTypeEnum.CRA && t.UserTypeEnum != UserTypeEnum.ClinicalResearchCoordinator) || curentSiteUserIdList.Contains(t.UserId)).ToList(); + } + + if (onlyToUserId != null) + { + toUserList = toUserList.Where(t => t.UserId == onlyToUserId).ToList(); + } + else + { + sendEmailConfig.HtmlBodyStr = htmlBodyStr.Replace(EmailNamePlaceholder, string.Join(isEn_us ? ", " : "、", toUserList.Select(t => t.FullName).ToList())); + } + + if (toUserList.Count == 0) + { + //---没有收件人,无法发送邮件 + throw new BusinessValidationFailedException(_localizer["TrialEmailN_NoRecipient"]); + } + + + if (trialEmailConfig.FromEmail.Contains("@") && !string.IsNullOrEmpty(trialEmailConfig.FromEmail)) + { + + sendEmailConfig.FromEmailAddress = new MimeKit.MailboxAddress(trialEmailConfig.FromName, trialEmailConfig.FromEmail); + sendEmailConfig.AuthorizationCode = trialEmailConfig.AuthorizationCode; + sendEmailConfig.UserName = trialEmailConfig.FromEmail; + + sendEmailConfig.Host = trialEmailConfig.SMTPServerAddress; + sendEmailConfig.Port = trialEmailConfig.SMTPServerPort; + } + else + { + //---项目发件邮箱配置有误,请核实 + throw new BusinessValidationFailedException(_localizer["TrialEmailN_InvalidEmailConfig"]); + } + + foreach (var item in toUserList) + { + + if (item.EMail.Contains("@") && !string.IsNullOrEmpty(item.EMail)) + { + + sendEmailConfig.ToMailAddressList.Add(new MimeKit.MailboxAddress(item.FullName, item.EMail)); + + } + } + foreach (var item in copyUserList) + { + + if (item.EMail.Contains("@") && !string.IsNullOrEmpty(item.EMail)) + { + + sendEmailConfig.CopyToMailAddressList.Add(new MimeKit.MailboxAddress(item.FullName, item.EMail)); + + } + } + + //邮件附件 这里是原格式发送,不是PDF + + //if (trialEmailConfig.AttachCNPath != string.Empty && trialEmailConfig.AttachPath != string.Empty) + //{ + // var phyPath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, isEn_us? trialEmailConfig.AttachName: trialEmailConfig.AttachNameCN); + + // //先预先生成了邮件,发送预先生成的邮件 + // sendEmailConfig.EmailAttachMentConfigList.Add(new EmailAttachMentConfig() + // { + // FileName = $"{attachPrefix}_{Path.GetFileName(_userInfo.IsEn_Us ? trialEmailConfig.AttachName : trialEmailConfig.AttachNameCN)}", + + // FileStream = File.OpenRead(phyPath), + // }); + //} + + return (trialEmailConfig, sendEmailConfig); + + + } + } } } diff --git a/IRaCIS.Core.Application/Service/Document/TrialDocumentService.cs b/IRaCIS.Core.Application/Service/Document/TrialDocumentService.cs index c4629983e..403151fc0 100644 --- a/IRaCIS.Core.Application/Service/Document/TrialDocumentService.cs +++ b/IRaCIS.Core.Application/Service/Document/TrialDocumentService.cs @@ -658,7 +658,7 @@ namespace IRaCIS.Core.Application.Services /// /// [HttpPut("{documentId:guid}/{isSystemDoc:bool}")] - [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "BeforeOngoingCantOpt", "AfterStopCannNotOpt" })] + [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "BeforeOngoingCantOpt", "AfterStopCannNotOpt", "SignSystemDocNoTrialId" })] public async Task UserAbandonDoc(Guid documentId, bool isSystemDoc) { if (isSystemDoc) diff --git a/IRaCIS.Core.Application/Service/Document/TrialEmailNoticeConfigService.cs b/IRaCIS.Core.Application/Service/Document/TrialEmailNoticeConfigService.cs index 519545509..2df1d2848 100644 --- a/IRaCIS.Core.Application/Service/Document/TrialEmailNoticeConfigService.cs +++ b/IRaCIS.Core.Application/Service/Document/TrialEmailNoticeConfigService.cs @@ -21,6 +21,11 @@ using IRaCIS.Core.Domain.Share.Common; using System.IO; using System.Linq; using Spire.Doc; +using Microsoft.AspNetCore.Http; +using System; +using System.Runtime.InteropServices; +using SharpCompress.Common; +using SkiaSharp; namespace IRaCIS.Core.Application.Service { @@ -42,7 +47,7 @@ namespace IRaCIS.Core.Application.Service private readonly IRepository _trialUserRepository; private readonly IRepository _subjectRepository; private readonly IRepository _subjectVisitRepository; - + private readonly IEmailSendService _emailSendService; @@ -56,6 +61,7 @@ namespace IRaCIS.Core.Application.Service IRepository subjectVisitRepository, IRepository trialEmailBlackUserRepository, IRepository emailNoticeConfigRepository +, IEmailSendService emailSendService ) { _trialEmailNoticeConfigRepository = trialEmailNoticeConfigRepository; @@ -67,6 +73,7 @@ namespace IRaCIS.Core.Application.Service _subjectVisitRepository = subjectVisitRepository; _trialEmailBlackUserRepository = trialEmailBlackUserRepository; _emailNoticeConfigRepository = emailNoticeConfigRepository; + _emailSendService = emailSendService; } /// @@ -255,8 +262,8 @@ namespace IRaCIS.Core.Application.Service /// public async Task BaseBusinessScenarioSendEmailAsync(Guid visitTaskId, bool? isHandSend, EmailStoreSendMode emailStoreMode, string sendFileRelativePath) { - - EmailBusinessScenario? businessScenarioEnum = null; + var isEn_us = _userInfo.IsEn_Us; + EmailBusinessScenario businessScenarioEnum = EmailBusinessScenario.None; #region 任务关联的项目配置 标准信息及配置,subject 信息 var taskInfo = await _visitTaskRepository.Where(t => t.Id == visitTaskId).Select(t => new @@ -352,286 +359,119 @@ namespace IRaCIS.Core.Application.Service #endregion - #region 发收件人配置 确保无误 + #region 邮件内容装配 - - var emailConfig = await _trialEmailNoticeConfigRepository.Where(t => t.TrialId == taskInfo.TrialId && t.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId && t.BusinessScenarioEnum == businessScenarioEnum) - .Include(t => t.TrialEmailNoticeUserList).FirstOrDefaultAsync(); - - - if (emailConfig == null || (emailConfig.IsAutoSend == false && isHandSend == null)) + Func topicAndHtmlFunc = trialEmailConfig => { - //throw new BusinessValidationFailedException("找不到该项目标准场景下邮件的配置"); + var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, taskInfo.ResearchProgramNo, taskInfo.SubjectCode); - return string.Empty; - } + var htmlBodyStr = string.Format(isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN, + StaticData.EmailSend.EmailNamePlaceholder, taskInfo.ResearchProgramNo, taskInfo.SubjectCode); - var sendEmailConfig = new SMTPEmailConfig(); - - //收件人 如果是CRC CRA 要按照中心发送 - var toUserTypeEnumList = emailConfig.TrialEmailNoticeUserList.Where(t => t.EmailUserType == EmailUserType.To).Select(c => c.UserType).ToList(); + return (topicStr, htmlBodyStr, isEn_us, null); + }; - - var toUserList = _repository.Where(t => t.TrialId == taskInfo.TrialId && toUserTypeEnumList.Contains(t.User.UserTypeEnum) && t.SiteId == taskInfo.SiteId).Select(t => new { t.User.EMail, t.User.FullName }).ToList(); - - var copyUserTypeEnumList = emailConfig.TrialEmailNoticeUserList.Where(t => t.EmailUserType == EmailUserType.Copy).Select(c => c.UserType).ToList(); - var copyUserList = _repository.Where(t => t.TrialId == taskInfo.TrialId && copyUserTypeEnumList.Contains(t.User.UserTypeEnum)).Select(t => new { t.User.EMail, t.User.FullName }).ToList(); - - - if (toUserList.Count() == 0) - { - //---没有收件人,无法发送邮件 - throw new BusinessValidationFailedException(_localizer["TrialEmailN_NoRecipient"]); - } - - - if (emailConfig.FromEmail.Contains("@") && !string.IsNullOrEmpty(emailConfig.FromEmail)) - { - - sendEmailConfig.FromEmailAddress = new MimeKit.MailboxAddress(emailConfig.FromName, emailConfig.FromEmail); - sendEmailConfig.AuthorizationCode = emailConfig.AuthorizationCode; - sendEmailConfig.UserName = emailConfig.FromEmail; - - sendEmailConfig.Host = emailConfig.SMTPServerAddress; - sendEmailConfig.Port = emailConfig.SMTPServerPort; - - - //测试 - //sendEmailConfig.ToMailAddressList.Add(new MimeKit.MailboxAddress("ddd", "872297557@qq.com")); - - } - else - { - //---项目发件邮箱配置有误,请核实 - throw new BusinessValidationFailedException(_localizer["TrialEmailN_InvalidEmailConfig"]); - } - - foreach (var item in toUserList) - { - - if (item.EMail.Contains("@") && !string.IsNullOrEmpty(item.EMail)) - { - - sendEmailConfig.ToMailAddressList.Add(new MimeKit.MailboxAddress(item.FullName, item.EMail)); - - } - } - foreach (var item in copyUserList) - { - - if (item.EMail.Contains("@") && !string.IsNullOrEmpty(item.EMail)) - { - - sendEmailConfig.CopyToMailAddressList.Add(new MimeKit.MailboxAddress(item.FullName, item.EMail)); - - } - } - #endregion - - #region 确保 邮件Html存在 - - //邮件附件 - var path = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, _userInfo.IsEn_Us ? emailConfig.AttachPath : emailConfig.AttachCNPath); - - if (!File.Exists(path)) - { - //---找不到该项目标准场景下邮件模板 - throw new BusinessValidationFailedException(_localizer["TrialEmailN_EmailTemplateNotFound"]); - } - - - var pathToFile = _hostEnvironment.WebRootPath - + Path.DirectorySeparatorChar.ToString() - + "EmailTemplate" - + Path.DirectorySeparatorChar.ToString() - //+ "SubjectEnrollConfirmOrPDProgress.html"; - + (_userInfo.IsEn_Us ? "SubjectEnrollConfirmOrPDProgress_US.html" : "SubjectEnrollConfirmOrPDProgress.html"); + var (trialEmailConfig, sendEmailConfig) = await _emailSendService.BuildEmailConfig(taskInfo.TrialId, businessScenarioEnum, topicAndHtmlFunc, taskInfo.SiteId); #endregion - #region 不同场景 Tile 设置 - if (businessScenarioEnum == EmailBusinessScenario.EnrollConfirmed) + //自动发送 + if (sendEmailConfig != null && trialEmailConfig !=null) { - sendEmailConfig.TopicDescription = _localizer["TrialEmailN_EnrollmentConfirmation", taskInfo.ResearchProgramNo, taskInfo.SubjectCode]; + #region 不同标准 不同项目配置 发送邮件的时机 处理具体逻辑 - using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile)) + var answer = "否"; + var isNeedSend = true; + var minUserIdList = _trialUserRepository.Where(t => t.User.UserTypeEnum == Domain.Share.UserTypeEnum.MIM && t.TrialId == taskInfo.TrialId).Select(t => t.UserId).ToList(); + + + + //入组确认 根据每个标准配置的是否自动发送,发送邮件与否 + if (businessScenarioEnum == EmailBusinessScenario.EnrollConfirmed) { - var templateInfo = SourceReader.ReadToEnd(); - - - sendEmailConfig.HtmlBodyStr = string.Format(templateInfo, - //--- 附件为疾病进展确认报告,请查收 - _localizer["TrialEmailN_SubjectDiseaseProgression"] - ); - } - } - else if (businessScenarioEnum == EmailBusinessScenario.PDConfirmed) - { - sendEmailConfig.TopicDescription = _localizer["TrialEmailN_PDReport", taskInfo.ResearchProgramNo, taskInfo.SubjectCode]; - - using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile)) - { - var templateInfo = SourceReader.ReadToEnd(); - - - sendEmailConfig.HtmlBodyStr = string.Format(templateInfo, - //--- 附件为疾病进展确认报告,请查收 - _localizer["TrialEmailN_SubjectDiseaseProgression"] - ); - } - } - else - { - // - } - - #endregion - - - #region 不同标准 不同项目配置 发送邮件的时机 处理具体逻辑 - - var answer = "否"; - var isNeedSend = true; - var minUserIdList = _trialUserRepository.Where(t => t.User.UserTypeEnum == Domain.Share.UserTypeEnum.MIM && t.TrialId == taskInfo.TrialId).Select(t => t.UserId).ToList(); - - - - //入组确认 根据每个标准配置的是否自动发送,发送邮件与否 - if (businessScenarioEnum == EmailBusinessScenario.EnrollConfirmed) - { - if (await _repository.Where().AnyAsync(x => x.VisitTaskId == visitTaskId && x.Answer == TargetState.Exist.GetEnumInt() && - x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.State && x.ReadingQuestionTrial.LesionType == LesionType.TargetLesion)) - { - answer = "是"; - } - - - //如果其他阅片人已经做了,说明发送了入组确认报告,第二个人做完就不发送了 - - //入组确认一直交给第一个人,如果第一个人重阅 还未做完,第二个人先做完了,此时不发 - - var existFirstEnrollTask = await _visitTaskRepository.Where(t => t.SourceSubjectVisitId == taskInfo.SourceSubjectVisitId && t.IsAnalysisCreate == false - && t.ReadingTaskState == ReadingTaskState.HaveSigned && t.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId).OrderBy(t => t.SignTime).FirstOrDefaultAsync(); - - //入组确认的医生已确定 - if ((existFirstEnrollTask != null) && (taskInfo.DoctorUserId != existFirstEnrollTask.DoctorUserId)) - { - isNeedSend = false; - } - else - { - isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, new List() { visitTaskId }, minUserIdList); - - - if (answer == "是") + if (await _repository.Where().AnyAsync(x => x.VisitTaskId == visitTaskId && x.Answer == TargetState.Exist.GetEnumInt() && + x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.State && x.ReadingQuestionTrial.LesionType == LesionType.TargetLesion)) { - //把另外一个人的任务设置为不加急(如果项目加急是否 subject 加急是否) - var urgent = _repository.Where(t => t.Id == taskInfo.SourceSubjectVisitId).Select(t => new { IsSubjectUrgent = t.Subject.IsUrgent, t.Trial.IsUrgent }).FirstOrDefault(); - - if (urgent?.IsUrgent == false || urgent?.IsSubjectUrgent == false) - { - await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => t.SourceSubjectVisitId == taskInfo.SourceSubjectVisitId && t.TaskState == TaskState.Effect && t.IsAnalysisCreate == false && - t.Id != visitTaskId && t.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId, u => new VisitTask() { IsUrgent = false }); - } + answer = "是"; } + //如果其他阅片人已经做了,说明发送了入组确认报告,第二个人做完就不发送了 + + //入组确认一直交给第一个人,如果第一个人重阅 还未做完,第二个人先做完了,此时不发 + + var existFirstEnrollTask = await _visitTaskRepository.Where(t => t.SourceSubjectVisitId == taskInfo.SourceSubjectVisitId && t.IsAnalysisCreate == false + && t.ReadingTaskState == ReadingTaskState.HaveSigned && t.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId).OrderBy(t => t.SignTime).FirstOrDefaultAsync(); + + //入组确认的医生已确定 + if ((existFirstEnrollTask != null) && (taskInfo.DoctorUserId != existFirstEnrollTask.DoctorUserId)) + { + isNeedSend = false; + } + else + { + isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, new List() { visitTaskId }, minUserIdList); + + + if (answer == "是") + { + //把另外一个人的任务设置为不加急(如果项目加急是否 subject 加急是否) + var urgent = _repository.Where(t => t.Id == taskInfo.SourceSubjectVisitId).Select(t => new { IsSubjectUrgent = t.Subject.IsUrgent, t.Trial.IsUrgent }).FirstOrDefault(); + + if (urgent?.IsUrgent == false || urgent?.IsSubjectUrgent == false) + { + await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => t.SourceSubjectVisitId == taskInfo.SourceSubjectVisitId && t.TaskState == TaskState.Effect && t.IsAnalysisCreate == false && + t.Id != visitTaskId && t.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId, u => new VisitTask() { IsUrgent = false }); + } + } + + + } } - - - - - } - else if (businessScenarioEnum == EmailBusinessScenario.PDConfirmed) - { - - - //有序 - - if (taskInfo.IsReadingTaskViewInOrder) + else if (businessScenarioEnum == EmailBusinessScenario.PDConfirmed) { + //有序 - //双重 - if (taskInfo.ReadingType == ReadingMethod.Double) + if (taskInfo.IsReadingTaskViewInOrder) { - //仲裁在访视上 就没有全局阅片 没有阅片期 - if (taskInfo.ArbitrationRule == ArbitrationRule.Visit) + + //双重 + if (taskInfo.ReadingType == ReadingMethod.Double) { - //找到 访视,裁判 所有有效任务(不可能有全局的) 访视和裁判任务的SourceSubjectVisitId 一样 - var taskList = await _visitTaskRepository.Where(t => t.SourceSubjectVisitId == taskInfo.SourceSubjectVisitId && t.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId && t.IsAnalysisCreate == false && t.TaskState == TaskState.Effect && - (t.ReadingCategory == ReadingCategory.Visit || t.ReadingCategory == ReadingCategory.Judge)).ToListAsync(); - //这里要求 到这里已经如果有裁判 已经生成裁判了保存数据库 - //双人阅片,没有产生裁判 第二个人读完发 - if (taskList.Count == 2 && taskList.Count(t => t.ReadingTaskState == ReadingTaskState.HaveSigned && t.ReadingCategory == ReadingCategory.Visit) == 2) + //仲裁在访视上 就没有全局阅片 没有阅片期 + if (taskInfo.ArbitrationRule == ArbitrationRule.Visit) { - - answer = await TranslatePdStateAsync(visitTaskId, taskInfo.ReadingCategory, taskInfo.CriterionType); + //找到 访视,裁判 所有有效任务(不可能有全局的) 访视和裁判任务的SourceSubjectVisitId 一样 + var taskList = await _visitTaskRepository.Where(t => t.SourceSubjectVisitId == taskInfo.SourceSubjectVisitId && t.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId && t.IsAnalysisCreate == false && t.TaskState == TaskState.Effect && + (t.ReadingCategory == ReadingCategory.Visit || t.ReadingCategory == ReadingCategory.Judge)).ToListAsync(); - isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, taskList.Select(t => t.Id).ToList(), minUserIdList); - - } - //双人 产生裁判,并且裁判完成 发 - else if (taskList.Count == 3 && taskList.Count(t => t.ReadingTaskState == ReadingTaskState.HaveSigned) == 3 && taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).Count() == 1) - { - var judgeResultId = taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).First().JudgeResultTaskId.Value; - answer = await TranslatePdStateAsync(judgeResultId, ReadingCategory.Visit, taskInfo.CriterionType); - - isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).Select(t => t.Id).ToList(), minUserIdList); - - } - else - { - isNeedSend = false; - - } - - - - - } - //仲裁在阅片期 - else if (taskInfo.ArbitrationRule == ArbitrationRule.Reading) - { - //是访视任务 不可能是裁判任务(访视上不会生成裁判),也不会是全局任务(全局任务 SourceSubjectVisitId=null ) - if (taskInfo.SourceSubjectVisitId != null) - { - - //访视类型的任务 根本就不需要发送邮件 - - isNeedSend = false; - - } - //是全局任务 或者全局的裁判任务 (如果是全局任务,那么此时裁判任务已经生成) - else if (taskInfo.SouceReadModuleId != null) - { - var taskList = await _visitTaskRepository.Where(t => t.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId && t.IsAnalysisCreate == false && t.TaskState == TaskState.Effect && t.SouceReadModuleId == taskInfo.SouceReadModuleId - && (t.ReadingCategory == ReadingCategory.Global || t.ReadingCategory == ReadingCategory.Judge)).ToListAsync(); - - //两个全局没有裁判 - if (taskList.Count == 2 && taskList.Count(t => t.ReadingTaskState == ReadingTaskState.HaveSigned && t.ReadingCategory == ReadingCategory.Global) == 2) + //这里要求 到这里已经如果有裁判 已经生成裁判了保存数据库 + //双人阅片,没有产生裁判 第二个人读完发 + if (taskList.Count == 2 && taskList.Count(t => t.ReadingTaskState == ReadingTaskState.HaveSigned && t.ReadingCategory == ReadingCategory.Visit) == 2) { answer = await TranslatePdStateAsync(visitTaskId, taskInfo.ReadingCategory, taskInfo.CriterionType); - isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, taskList.Select(t => t.Id).ToList(), minUserIdList); - } - //双人全局产生裁判 - else if (taskList.Count == 3 && taskList.Count(t => t.ReadingTaskState == ReadingTaskState.HaveSigned) == 3 && taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).Count() == 1 && taskList.Where(t => t.ReadingCategory == ReadingCategory.Global).Count() == 2) - { - var judgeResultId = taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).First().JudgeResultTaskId.Value; - answer = await TranslatePdStateAsync(judgeResultId, ReadingCategory.Global, taskInfo.CriterionType); + isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, taskList.Select(t => t.Id).ToList(), minUserIdList); + + } + //双人 产生裁判,并且裁判完成 发 + else if (taskList.Count == 3 && taskList.Count(t => t.ReadingTaskState == ReadingTaskState.HaveSigned) == 3 && taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).Count() == 1) + { + var judgeResultId = taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).First()!.JudgeResultTaskId!.Value; + answer = await TranslatePdStateAsync(judgeResultId, ReadingCategory.Visit, taskInfo.CriterionType); isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).Select(t => t.Id).ToList(), minUserIdList); @@ -641,256 +481,350 @@ namespace IRaCIS.Core.Application.Service isNeedSend = false; } + + + + + } + //仲裁在阅片期 + else if (taskInfo.ArbitrationRule == ArbitrationRule.Reading) + { + //是访视任务 不可能是裁判任务(访视上不会生成裁判),也不会是全局任务(全局任务 SourceSubjectVisitId=null ) + if (taskInfo.SourceSubjectVisitId != null) + { + + //访视类型的任务 根本就不需要发送邮件 + + isNeedSend = false; + + } + //是全局任务 或者全局的裁判任务 (如果是全局任务,那么此时裁判任务已经生成) + else if (taskInfo.SouceReadModuleId != null) + { + var taskList = await _visitTaskRepository.Where(t => t.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId && t.IsAnalysisCreate == false && t.TaskState == TaskState.Effect && t.SouceReadModuleId == taskInfo.SouceReadModuleId + && (t.ReadingCategory == ReadingCategory.Global || t.ReadingCategory == ReadingCategory.Judge)).ToListAsync(); + + //两个全局没有裁判 + if (taskList.Count == 2 && taskList.Count(t => t.ReadingTaskState == ReadingTaskState.HaveSigned && t.ReadingCategory == ReadingCategory.Global) == 2) + { + + answer = await TranslatePdStateAsync(visitTaskId, taskInfo.ReadingCategory, taskInfo.CriterionType); + + isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, taskList.Select(t => t.Id).ToList(), minUserIdList); + } + //双人全局产生裁判 + else if (taskList.Count == 3 && taskList.Count(t => t.ReadingTaskState == ReadingTaskState.HaveSigned) == 3 && taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).Count() == 1 && taskList.Where(t => t.ReadingCategory == ReadingCategory.Global).Count() == 2) + { + + var judgeResultId = taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).First().JudgeResultTaskId!.Value; + answer = await TranslatePdStateAsync(judgeResultId, ReadingCategory.Global, taskInfo.CriterionType); + + isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).Select(t => t.Id).ToList(), minUserIdList); + + } + else + { + isNeedSend = false; + + } + } + else + { + //---发送PD 进展邮件中发现任务数据有问题! + throw new BusinessValidationFailedException(_localizer["TrialEmailN_PDProgressEmailTask"]); + } + + + } else { - //---发送PD 进展邮件中发现任务数据有问题! - throw new BusinessValidationFailedException(_localizer["TrialEmailN_PDProgressEmailTask"]); + + //---双重有序阅片 没有定义该仲裁规则处理逻辑,请联系业务和后台开发核查! + throw new BusinessValidationFailedException(_localizer["TrialEmailN_DoubleBlindedError"]); } - } + + //屏蔽单重阅片添加 else { - - //---双重有序阅片 没有定义该仲裁规则处理逻辑,请联系业务和后台开发核查! - throw new BusinessValidationFailedException(_localizer["TrialEmailN_DoubleBlindedError"]); + isNeedSend = false; + return string.Empty; } + #region 发邮件屏蔽单重的 + ////单重 + //else if (taskInfo.ReadingType == ReadingMethod.Single) + //{ + // //仲裁在访视上 或者在阅片期 + // if (taskInfo.ArbitrationRule != ArbitrationRule.None) + // { + + //---单重有序阅片配置有误(不应该有仲裁对象配置),请核查! + // throw new BusinessValidationFailedException(_localizer["TrialEmailN_SingleBlindedSet"]); + // } + + + // //要求PD 确认的访视 是截止访视 还是非截止访视(根据该访视有没有配置阅片期来判断) + + // if (taskInfo.ReadingCategory == ReadingCategory.Visit) + // { + // //存在阅片期 那么就是截止访视 + // if (await _repository.Where(t => t.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId && t.SubjectVisitId == taskInfo.SourceSubjectVisitId && t.ReadingSetType == ReadingSetType.ImageReading).AnyAsync()) + // { + // isNeedSend = false; + // } + // else//非截止访视 在访视读完后,发送 + // { + // answer = await TranslatePdStateAsync(visitTaskId, ReadingCategory.Visit, taskInfo.CriterionType); + // } + // } + // //截止访视 在访视读完,并完成全局阅片后发送全局的结果 + // else if (taskInfo.ReadingCategory == ReadingCategory.Global) + // { + // answer = await TranslatePdStateAsync(visitTaskId, ReadingCategory.Global, taskInfo.CriterionType); + // } + // else + // { + //---单重有序阅片 该类型的任务不应进入此处逻辑,请联系后台开发核查! + // throw new BusinessValidationFailedException(_localizer["TrialEmailN_SingleBlindedSequenced"]); + // } + + // isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, new List() { visitTaskId }, minUserIdList); + + + //} + //else + //{ + //---有序阅片配置有误(应为单重或者双重阅片),请核查! + // throw new BusinessValidationFailedException(_localizer["TrialEmailN_BlindedSequencedReading"]); + //} + + #endregion + + + } - - //屏蔽单重阅片添加 + //屏蔽无序阅片添加 else { isNeedSend = false; return string.Empty; } - #region 发邮件屏蔽单重的 - ////单重 - //else if (taskInfo.ReadingType == ReadingMethod.Single) + #region 发送邮件屏蔽无序的 + // //无序 + //else //{ - // //仲裁在访视上 或者在阅片期 - // if (taskInfo.ArbitrationRule != ArbitrationRule.None) - // { + // //单重 - //---单重有序阅片配置有误(不应该有仲裁对象配置),请核查! - // throw new BusinessValidationFailedException(_localizer["TrialEmailN_SingleBlindedSet"]); + + // if (taskInfo.ReadingType == ReadingMethod.Single && taskInfo.ArbitrationRule == ArbitrationRule.None) + // { + // answer = await TranslatePdStateAsync(visitTaskId, taskInfo.ReadingCategory, taskInfo.CriterionType); + + // isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, new List() { visitTaskId }, minUserIdList); // } - - - // //要求PD 确认的访视 是截止访视 还是非截止访视(根据该访视有没有配置阅片期来判断) - - // if (taskInfo.ReadingCategory == ReadingCategory.Visit) + // //双重 截止访视只在阅片期的时候存在 要求PD确认的访视 肯定是非截止访视 + // else if (taskInfo.ReadingType == ReadingMethod.Double && taskInfo.ArbitrationRule == ArbitrationRule.Visit) // { - // //存在阅片期 那么就是截止访视 - // if (await _repository.Where(t => t.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId && t.SubjectVisitId == taskInfo.SourceSubjectVisitId && t.ReadingSetType == ReadingSetType.ImageReading).AnyAsync()) + // //在两位阅片人读完访视后,如果有裁判者等裁判读完,如果无裁判则等第二个人的读完 + + // var taskList = await _visitTaskRepository.Where(t => t.SourceSubjectVisitId == taskInfo.SourceSubjectVisitId && t.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId && t.IsAnalysisCreate == false && t.TaskState == TaskState.Effect + // && (t.ReadingCategory == ReadingCategory.Visit || t.ReadingCategory == ReadingCategory.Judge)).ToListAsync(); + + // //这里要求 到这里已经如果有裁判 已经生成裁判了保存数据库 + // if (taskList.Count == 2 && taskList.Count(t => t.ReadingTaskState == ReadingTaskState.HaveSigned && t.ReadingCategory == ReadingCategory.Visit) == 2) + // { + + // answer = await TranslatePdStateAsync(visitTaskId, taskInfo.ReadingCategory, taskInfo.CriterionType); + + // isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, taskList.Select(t => t.Id).ToList(), minUserIdList); + // } + // else if (taskList.Count == 3 && taskList.Count(t => t.ReadingTaskState == ReadingTaskState.HaveSigned) == 3 && taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).Count() == 1) + // { + // var judgeResultId = taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).First().JudgeResultTaskId.Value; + // answer = await TranslatePdStateAsync(judgeResultId, ReadingCategory.Visit, taskInfo.CriterionType); + + // isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).Select(t => t.Id).ToList(), minUserIdList); + + + // } + // else // { // isNeedSend = false; // } - // else//非截止访视 在访视读完后,发送 - // { - // answer = await TranslatePdStateAsync(visitTaskId, ReadingCategory.Visit, taskInfo.CriterionType); - // } - // } - // //截止访视 在访视读完,并完成全局阅片后发送全局的结果 - // else if (taskInfo.ReadingCategory == ReadingCategory.Global) - // { - // answer = await TranslatePdStateAsync(visitTaskId, ReadingCategory.Global, taskInfo.CriterionType); + // } // else // { - //---单重有序阅片 该类型的任务不应进入此处逻辑,请联系后台开发核查! - // throw new BusinessValidationFailedException(_localizer["TrialEmailN_SingleBlindedSequenced"]); + //---无序阅片配置有误(应为单重无仲裁对象,双重针对访视仲裁),请核查! + // throw new BusinessValidationFailedException(_localizer["TrialEmailN_UnblindedSequencedReading"]); // } - // isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, new List() { visitTaskId }, minUserIdList); - - - //} - //else - //{ - //---有序阅片配置有误(应为单重或者双重阅片),请核查! - // throw new BusinessValidationFailedException(_localizer["TrialEmailN_BlindedSequencedReading"]); //} #endregion - - - - } - //屏蔽无序阅片添加 else { isNeedSend = false; + } + + #endregion + + + #region MiniWord 组织字典 发送 + + + if (emailStoreMode == EmailStoreSendMode.NotStoreLocalOnlySentEmail) + { + + var phyPath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, sendFileRelativePath); + + var attachPrefix = $"{taskInfo.SubjectCode}"; + + //先预先生成了邮件,发送预先生成的邮件 + sendEmailConfig.EmailAttachMentConfigList.Add(new EmailAttachMentConfig() + { + FileName = $"{attachPrefix}_{Path.GetFileNameWithoutExtension(_userInfo.IsEn_Us ? trialEmailConfig.AttachName : trialEmailConfig!.AttachNameCN)}.pdf", + + FileStream = File.OpenRead(phyPath), + }); + + + await SendEmailHelper.SendEmailAsync(sendEmailConfig); + return string.Empty; } - #region 发送邮件屏蔽无序的 - // //无序 - //else - //{ - // //单重 + var value = new Dictionary() + { + ["SponsorName"] = taskInfo.SponsorName, + ["ResearchProgramNo"] = taskInfo.ResearchProgramNo, + ["TrialSiteCode"] = taskInfo.TrialSiteCode, + ["SubjectCode"] = taskInfo.SubjectCode, + ["VisitName"] = taskInfo.SourceSubjectVisitId != null ? taskInfo.VisitName : taskInfo.ModuleVisitName, + ["EarliestScanDate"] = taskInfo.SourceSubjectVisitId != null ? taskInfo.VisitEarliestScanDate?.ToString("yyyy-MM-dd") : taskInfo.ModuleEarliestScanDate?.ToString("yyyy-MM-dd"), + ["SignTime"] = taskInfo.SignTime?.ToString("yyyy-MM-dd"), + ["Result"] = answer + + }; + + var path = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, _userInfo.IsEn_Us ? trialEmailConfig.AttachPath : trialEmailConfig.AttachCNPath); + + var (serverFilePath, relativePath, fileRealName) = FileStoreHelper.GetSubjectEnrollConfirmOrPDEmailPath(_hostEnvironment, Path.GetFileName(path), taskInfo.TrialId, taskInfo.SiteId, taskInfo.SubjectId, true); + + if (emailStoreMode == EmailStoreSendMode.StoreLocalSend || emailStoreMode == EmailStoreSendMode.OnlyStoreLocalNotSentEmail) + { + + MemoryStream wordMemoryStream = new MemoryStream(); - // if (taskInfo.ReadingType == ReadingMethod.Single && taskInfo.ArbitrationRule == ArbitrationRule.None) - // { - // answer = await TranslatePdStateAsync(visitTaskId, taskInfo.ReadingCategory, taskInfo.CriterionType); - - // isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, new List() { visitTaskId }, minUserIdList); - // } - // //双重 截止访视只在阅片期的时候存在 要求PD确认的访视 肯定是非截止访视 - // else if (taskInfo.ReadingType == ReadingMethod.Double && taskInfo.ArbitrationRule == ArbitrationRule.Visit) - // { - // //在两位阅片人读完访视后,如果有裁判者等裁判读完,如果无裁判则等第二个人的读完 - - // var taskList = await _visitTaskRepository.Where(t => t.SourceSubjectVisitId == taskInfo.SourceSubjectVisitId && t.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId && t.IsAnalysisCreate == false && t.TaskState == TaskState.Effect - // && (t.ReadingCategory == ReadingCategory.Visit || t.ReadingCategory == ReadingCategory.Judge)).ToListAsync(); - - // //这里要求 到这里已经如果有裁判 已经生成裁判了保存数据库 - // if (taskList.Count == 2 && taskList.Count(t => t.ReadingTaskState == ReadingTaskState.HaveSigned && t.ReadingCategory == ReadingCategory.Visit) == 2) - // { - - // answer = await TranslatePdStateAsync(visitTaskId, taskInfo.ReadingCategory, taskInfo.CriterionType); - - // isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, taskList.Select(t => t.Id).ToList(), minUserIdList); - // } - // else if (taskList.Count == 3 && taskList.Count(t => t.ReadingTaskState == ReadingTaskState.HaveSigned) == 3 && taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).Count() == 1) - // { - // var judgeResultId = taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).First().JudgeResultTaskId.Value; - // answer = await TranslatePdStateAsync(judgeResultId, ReadingCategory.Visit, taskInfo.CriterionType); - - // isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).Select(t => t.Id).ToList(), minUserIdList); + MiniSoftware.MiniWord.SaveAsByTemplate(wordMemoryStream, path, value); + + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + Document document = new Document(); + + document.LoadFromStream(wordMemoryStream, FileFormat.Docx); + + document.SaveToFile(serverFilePath, FileFormat.PDF); + } + else + { + var wordStoreServerPath = Path.Combine(Path.GetDirectoryName(serverFilePath), Path.GetFileNameWithoutExtension(serverFilePath) + ".docx"); + + using (FileStream fileStream = new FileStream(wordStoreServerPath, FileMode.Create, FileAccess.Write)) + { + wordMemoryStream.WriteTo(fileStream); + } + FileConvertHelper.ConvertWordToPdf(wordStoreServerPath, Path.GetDirectoryName(serverFilePath)); + + File.Delete(wordStoreServerPath); + } + + + + } + //手动生成发送的邮件内容,但是并不发送 + if (emailStoreMode == EmailStoreSendMode.OnlyStoreLocalNotSentEmail) + { + isNeedSend = false; + + return relativePath; + } + + + //正常的即时生成邮件 并发送邮件 + if (isNeedSend) + { + + + MemoryStream wordMemoryStream = new MemoryStream(); + MemoryStream pdfMemoryStream = new MemoryStream(); + + + MiniSoftware.MiniWord.SaveAsByTemplate(wordMemoryStream, path, value); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + Document document = new Document(); + document.LoadFromStream(wordMemoryStream, FileFormat.Docx); + document.SaveToStream(pdfMemoryStream, FileFormat.PDF); + + } + else + { + var wordStoreServerPath = Path.Combine(Path.GetDirectoryName(serverFilePath), Path.GetFileNameWithoutExtension(serverFilePath) + ".docx"); + + using (FileStream fileStream = new FileStream(wordStoreServerPath, FileMode.Create, FileAccess.Write)) + { + wordMemoryStream.WriteTo(fileStream); + } + FileConvertHelper.ConvertWordToPdf(wordStoreServerPath, Path.GetDirectoryName(serverFilePath)); + + File.Delete(wordStoreServerPath); + + using (FileStream fileStream = new FileStream(serverFilePath, FileMode.Open, FileAccess.Read)) + { + fileStream.CopyTo(pdfMemoryStream); + } + + } + + pdfMemoryStream.Seek(0, SeekOrigin.Begin); + sendEmailConfig.EmailAttachMentConfigList.Add(new EmailAttachMentConfig() + { + FileName = $"{taskInfo.SubjectCode}_{Path.GetFileNameWithoutExtension(_userInfo.IsEn_Us ? trialEmailConfig.AttachName : trialEmailConfig.AttachNameCN)}.pdf", + + FileStream = pdfMemoryStream + }); + + + await SendEmailHelper.SendEmailAsync(sendEmailConfig); + + } + + + + return string.Empty; - // } - // else - // { - // isNeedSend = false; - // } - // } - // else - // { - //---无序阅片配置有误(应为单重无仲裁对象,双重针对访视仲裁),请核查! - // throw new BusinessValidationFailedException(_localizer["TrialEmailN_UnblindedSequencedReading"]); - // } - //} #endregion } else { - isNeedSend = false; - } - - #endregion - - - #region MiniWord 组织字典 发送 - - - if (emailStoreMode == EmailStoreSendMode.NotStoreLocalOnlySentEmail) - { - - var phyPath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, sendFileRelativePath); - - - //先预先生成了邮件,发送预先生成的邮件 - sendEmailConfig.EmailAttachMentConfigList.Add(new EmailAttachMentConfig() - { - FileName = $"{taskInfo.SubjectCode}_{Path.GetFileNameWithoutExtension(_userInfo.IsEn_Us ? emailConfig.AttachName : emailConfig.AttachNameCN)}.pdf", - - FileStream = File.OpenRead(phyPath), - }); - - - await SendEmailHelper.SendEmailAsync(sendEmailConfig); - return string.Empty; } - var value = new Dictionary() - { - ["SponsorName"] = taskInfo.SponsorName, - ["ResearchProgramNo"] = taskInfo.ResearchProgramNo, - ["TrialSiteCode"] = taskInfo.TrialSiteCode, - ["SubjectCode"] = taskInfo.SubjectCode, - ["VisitName"] = taskInfo.SourceSubjectVisitId != null ? taskInfo.VisitName : taskInfo.ModuleVisitName, - ["EarliestScanDate"] = taskInfo.SourceSubjectVisitId != null ? taskInfo.VisitEarliestScanDate?.ToString("yyyy-MM-dd") : taskInfo.ModuleEarliestScanDate?.ToString("yyyy-MM-dd"), - ["SignTime"] = taskInfo.SignTime?.ToString("yyyy-MM-dd"), - ["Result"] = answer - - }; - - var (serverFilePath, relativePath, fileRealName) = FileStoreHelper.GetSubjectEnrollConfirmOrPDEmailPath(_hostEnvironment, Path.GetFileName(path), taskInfo.TrialId, taskInfo.SiteId, taskInfo.SubjectId, true); - - if (emailStoreMode == EmailStoreSendMode.StoreLocalSend || emailStoreMode == EmailStoreSendMode.OnlyStoreLocalNotSentEmail) - { - - MemoryStream wordMemoryStream = new MemoryStream(); - - Document document = new Document(); - - MiniSoftware.MiniWord.SaveAsByTemplate(wordMemoryStream, path, value); - - document.LoadFromStream(wordMemoryStream, FileFormat.Docx); - - document.SaveToFile(serverFilePath, FileFormat.PDF); - - - } - //手动生成发送的邮件内容,但是并不发送 - if (emailStoreMode == EmailStoreSendMode.OnlyStoreLocalNotSentEmail) - { - isNeedSend = false; - - return relativePath; - } - - - //正常的即时生成邮件 并发送邮件 - if (isNeedSend) - { - - - MemoryStream memoryStream = new MemoryStream(); - MemoryStream pdfMemoryStream = new MemoryStream(); - - - MiniSoftware.MiniWord.SaveAsByTemplate(memoryStream, path, value); - Document document = new Document(); - - document.LoadFromStream(memoryStream, FileFormat.Docx); - document.SaveToStream(pdfMemoryStream, FileFormat.PDF); - pdfMemoryStream.Seek(0, SeekOrigin.Begin); - - sendEmailConfig.EmailAttachMentConfigList.Add(new EmailAttachMentConfig() - { - FileName = $"{taskInfo.SubjectCode}_{Path.GetFileNameWithoutExtension(_userInfo.IsEn_Us ? emailConfig.AttachName : emailConfig.AttachNameCN)}.pdf", - - FileStream = pdfMemoryStream - }); - - - await SendEmailHelper.SendEmailAsync(sendEmailConfig); - - } - - - - return string.Empty; - - - - - - #endregion - } @@ -1027,7 +961,7 @@ namespace IRaCIS.Core.Application.Service { var task = taskList.FirstOrDefault(t => t.ReadingCategory == ReadingCategory.Visit); - var filePath = await BaseBusinessScenarioSendEmailAsync(task.Id, true, EmailStoreSendMode.OnlyStoreLocalNotSentEmail, string.Empty); + var filePath = await BaseBusinessScenarioSendEmailAsync(task!.Id, true, EmailStoreSendMode.OnlyStoreLocalNotSentEmail, string.Empty); return ResponseOutput.Ok(new { RelativePath = filePath, TaskName = task.TaskName, VisitTaskId = task.Id }); } @@ -1036,7 +970,7 @@ namespace IRaCIS.Core.Application.Service { var task = taskList.FirstOrDefault(t => t.ReadingCategory == ReadingCategory.Judge); - var filePath = await BaseBusinessScenarioSendEmailAsync(task.Id, true, EmailStoreSendMode.OnlyStoreLocalNotSentEmail, string.Empty); + var filePath = await BaseBusinessScenarioSendEmailAsync(task!.Id, true, EmailStoreSendMode.OnlyStoreLocalNotSentEmail, string.Empty); return ResponseOutput.Ok(new { RelativePath = filePath, TaskName = task.TaskName, VisitTaskId = task.Id }); } @@ -1073,7 +1007,7 @@ namespace IRaCIS.Core.Application.Service { var task = taskList.FirstOrDefault(t => t.ReadingCategory == ReadingCategory.Global); - var filePath = await BaseBusinessScenarioSendEmailAsync(task.Id, true, EmailStoreSendMode.OnlyStoreLocalNotSentEmail, string.Empty); + var filePath = await BaseBusinessScenarioSendEmailAsync(task!.Id, true, EmailStoreSendMode.OnlyStoreLocalNotSentEmail, string.Empty); return ResponseOutput.Ok(new { RelativePath = filePath, TaskName = task.TaskName, VisitTaskId = task.Id }); } @@ -1082,7 +1016,7 @@ namespace IRaCIS.Core.Application.Service { var task = taskList.FirstOrDefault(t => t.ReadingCategory == ReadingCategory.Judge); - var filePath = await BaseBusinessScenarioSendEmailAsync(task.Id, true, EmailStoreSendMode.OnlyStoreLocalNotSentEmail, string.Empty); + var filePath = await BaseBusinessScenarioSendEmailAsync(task!.Id, true, EmailStoreSendMode.OnlyStoreLocalNotSentEmail, string.Empty); return ResponseOutput.Ok(new { RelativePath = filePath, TaskName = task.TaskName, VisitTaskId = task.Id }); } diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/DicomInstanceModel.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/DicomInstanceModel.cs index b25b34119..a7accd3a0 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/DicomInstanceModel.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/DicomInstanceModel.cs @@ -38,8 +38,8 @@ namespace IRaCIS.Core.Application.Contracts public class DicomTrialSiteSubjectInfo { public string TrialSiteCode { get; set; } = string.Empty; - public string SiteCode { get; set; } = string.Empty; - public string SiteName { get; set; } = string.Empty; + public string TrialSiteAliasName { get; set; } = string.Empty; + public string SubjectCode { get; set; } = string.Empty; public int? SubjectAge { get; set; } public string SubjectSex { get; set; } = string.Empty; diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs index 75f6d7d81..572b71ba1 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs @@ -42,6 +42,7 @@ namespace IRaCIS.Core.Application.Contracts //[JsonIgnore] //public int NoneDicomCode { get; set; } + public string RecordPath { get; set; } = string.Empty; public bool IsDicom { get; set; } } @@ -173,7 +174,16 @@ namespace IRaCIS.Core.Application.Contracts public string[]? VisitPlanArray { get; set; } - } + public Guid? VisitTaskId { get; set; } + + public bool? IsDicom { get; set; } + + public string? Uploader { get; set; } + + public bool? IsSuccess { get; set; } + + public string? StudyCode { get; set; } + } public class PreArchiveDicomStudyCommand @@ -215,6 +225,8 @@ namespace IRaCIS.Core.Application.Contracts public int FailedFileCount { get; set; } + public string RecordPath { get; set; } + public AddOrUpdateStudyDto Study { get; set; } diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/DicomArchiveService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/DicomArchiveService.cs index f34ac28db..688deed0c 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/DicomArchiveService.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/DicomArchiveService.cs @@ -21,7 +21,6 @@ namespace IRaCIS.Core.Application.Services private readonly IRepository _dictionaryRepository; private readonly IEasyCachingProvider _provider; - private readonly IWebHostEnvironment _hostEnvironment; private readonly IDistributedLockProvider _distributedLockProvider; @@ -31,12 +30,10 @@ namespace IRaCIS.Core.Application.Services public DicomArchiveService(IRepository studyRepository, IRepository seriesRepository, IRepository instanceRepository, - IWebHostEnvironment hostEnvironment, IRepository dictionaryRepository, IEasyCachingProvider provider, IDistributedLockProvider distributedLockProvider) { _distributedLockProvider = distributedLockProvider; - _hostEnvironment = hostEnvironment; _studyRepository = studyRepository; _seriesRepository = seriesRepository; diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs index adb1f224a..d0ba6166b 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs @@ -151,7 +151,8 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc studyMonitor.UploadFinishedTime = DateTime.Now; studyMonitor.ArchiveFinishedTime = DateTime.Now; studyMonitor.FailedFileCount = incommand.FailedFileCount; - studyMonitor.IsSuccess = true; + studyMonitor.IsSuccess = incommand.FailedFileCount==0; + studyMonitor.RecordPath=incommand.RecordPath; //上传 if (studyMonitor.IsDicomReUpload == false) @@ -209,6 +210,9 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc series.SubjectId = incommand.SubjectId; series.SubjectVisitId = incommand.SubjectVisitId; + //前端传递的数量不准,上传的时候,把失败的也加进来了,以实际数组的数字为准 + series.InstanceCount = seriesItem.InstanceList.Count; + await _dicomSeriesRepository.AddAsync(series); foreach (var instanceItem in seriesItem.InstanceList) @@ -241,6 +245,9 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc var study = await _dicomstudyRepository.FirstOrDefaultAsync(t => t.Id == studyId); + //重传的时候也要赋值检查Id + studyMonitor.StudyId = study.Id; + studyMonitor.StudyCode = study.StudyCode; //特殊处理逻辑 study.Modalities = string.Join("、", incommand.Study.SeriesList.Select(t => t.Modality).Union(study.Modalities.Split("、", StringSplitOptions.RemoveEmptyEntries)).Distinct()); @@ -457,6 +464,10 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc .WhereIf(studyQuery.SubjectId != null, t => t.SubjectId == studyQuery.SubjectId) .WhereIf(studyQuery.SubjectVisitId != null, t => t.SubjectId == studyQuery.SubjectVisitId) .WhereIf(studyQuery.SiteId != null, t => t.SiteId == studyQuery.SiteId) + .WhereIf(studyQuery.IsDicom != null, t => t.IsDicom == studyQuery.IsDicom ) + .WhereIf(!string.IsNullOrWhiteSpace(studyQuery.Uploader), t => t.Uploader.UserName.Contains(studyQuery.Uploader)) + .WhereIf(studyQuery.IsSuccess != null, t => t.IsSuccess == studyQuery.IsSuccess) + .WhereIf(!string.IsNullOrWhiteSpace(studyQuery.StudyCode), t => t.StudyCode.Contains(studyQuery.StudyCode)) .Select(t => new UnionStudyMonitorModel() { TrialId = t.TrialId, @@ -489,7 +500,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc ArchiveFinishedTime = t.ArchiveFinishedTime, - + RecordPath=t.RecordPath, IsDicomReUpload = t.IsDicomReUpload, StudyId = t.Id, @@ -723,7 +734,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc { // $"当前访视检查时间{waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")}不能早于前序访视检查时间{before?.ToString("yyyy-MM-dd")},请核对检查数据是否有误", - result.Add(new VerifyStudyUploadResult() { ErrorMesseage = _localizer["Study_VisitBeforePrevError", waitUploadItem.StudyDate?.ToString("yyyy-MM-dd"), before?.ToString("yyyy-MM-dd")], StudyInstanceUid = waitUploadItem.StudyInstanceUid }); + result.Add(new VerifyStudyUploadResult() { ErrorMesseage = _localizer["Study_VisitBeforePrevError", waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")!, before?.ToString("yyyy-MM-dd")!], StudyInstanceUid = waitUploadItem.StudyInstanceUid }); return; } @@ -733,7 +744,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc if (after != null && waitUploadItem.StudyDate != null && after < waitUploadItem.StudyDate) { // $"当前访视检查时间{waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")}不能晚于该访视之后的检查时间{after?.ToString("yyyy-MM-dd")},请核对检查数据是否有误" - result.Add(new VerifyStudyUploadResult() { ErrorMesseage = _localizer["Study_VisitAfterSubseqError", waitUploadItem.StudyDate?.ToString("yyyy-MM-dd"), after?.ToString("yyyy-MM-dd")], StudyInstanceUid = waitUploadItem.StudyInstanceUid }); + result.Add(new VerifyStudyUploadResult() { ErrorMesseage = _localizer["Study_VisitAfterSubseqError", waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")!, after?.ToString("yyyy-MM-dd")!], StudyInstanceUid = waitUploadItem.StudyInstanceUid }); return; } } diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/_MapConfig.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/_MapConfig.cs index ef437c37a..5fb7e3610 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/_MapConfig.cs @@ -62,6 +62,7 @@ namespace IRaCIS.Core.Application.Service .ForMember(o => o.UploadedTime, t => t.MapFrom(u => u.CreateTime)) .ForMember(o => o.Uploader, t => t.MapFrom(u => u.Uploader.LastName + " / " + u.Uploader.FirstName)) .ForMember(o => o.StudyId, t => t.MapFrom(u => u.Id)) + .ForMember(o => o.IsHaveUploadFailed, t => t.MapFrom(u => u.DicomStudyMonitorList.Any(t=>t.FailedFileCount>0))) .ForMember(o => o.Modalities, t => t.MapFrom(u => string.Join('、', u.SeriesList.Select(t => t.Modality).Distinct()) )); diff --git a/IRaCIS.Core.Application/Service/Inspection/DTO/InspectionModel.cs b/IRaCIS.Core.Application/Service/Inspection/DTO/InspectionModel.cs index dfd96079c..412f1026d 100644 --- a/IRaCIS.Core.Application/Service/Inspection/DTO/InspectionModel.cs +++ b/IRaCIS.Core.Application/Service/Inspection/DTO/InspectionModel.cs @@ -298,7 +298,7 @@ namespace IRaCIS.Core.Application.Service.Inspection.DTO public T Data { get; set; } - public SignDTO SignInfo { get; set; } + public SignDTO? SignInfo { get; set; } } diff --git a/IRaCIS.Core.Application/Service/Inspection/FrontAuditConfigService.cs b/IRaCIS.Core.Application/Service/Inspection/FrontAuditConfigService.cs index dd130c66b..95b543718 100644 --- a/IRaCIS.Core.Application/Service/Inspection/FrontAuditConfigService.cs +++ b/IRaCIS.Core.Application/Service/Inspection/FrontAuditConfigService.cs @@ -197,7 +197,7 @@ namespace IRaCIS.Core.Application.Service //找到上一条Id - var currentInspection = await _dataInspectionRepository.Where(t => t.Id == id).Select(t => new { t.GeneralId, t.ObjectRelationParentId, t.CreateTime }).FirstOrDefaultAsync(); + var currentInspection = await _dataInspectionRepository.Where(t => t.Id == id).Select(t => new { t.GeneralId, t.ObjectRelationParentId, t.CreateTime }).FirstNotNullAsync(); var beforeId = await _dataInspectionRepository.Where(x => x.GeneralId == currentInspection.GeneralId && x.CreateTime <= currentInspection.CreateTime && x.Id != id).OrderByDescending(x => x.CreateTime).Select(t => t.Id) .FirstOrDefaultAsync(); @@ -214,11 +214,11 @@ namespace IRaCIS.Core.Application.Service - /// /// 翻译稽查数据 /// - /// 传入Dto + /// + /// /// private async Task> SetInspectionEnumValueDataList(SetInspectionEnumValueDto dto, Guid currentInspectionId) { @@ -241,7 +241,7 @@ namespace IRaCIS.Core.Application.Service var listIdentification = auditDatas.Select(x => x.Identification).Distinct().ToList(); foreach (var item in auditDatas) { - Dictionary jsonDict = JsonConvert.DeserializeObject>(item.JsonStr); + Dictionary jsonDict = (JsonConvert.DeserializeObject>(item.JsonStr)).IfNullThrowException(); if (!jsonDict.ContainsKey(nameof(InspectionJsonDetail.CommonData))) { @@ -366,7 +366,7 @@ namespace IRaCIS.Core.Application.Service resultJsonStrList.Add(auditData?.JsonStr); }); - if (resultJsonStrList.Count() < 2) + if (resultJsonStrList.Count < 2) { resultJsonStrList.Add(String.Empty); } @@ -386,7 +386,7 @@ namespace IRaCIS.Core.Application.Service if (relationParentInspection != null) { - Dictionary jsonDic = JsonConvert.DeserializeObject>(relationParentInspection.JsonDetail); + Dictionary jsonDic = (JsonConvert.DeserializeObject>(relationParentInspection.JsonDetail)).IfNullThrowConvertException(); //避免对象信息记录 把 Data里面的信息也取过去 但是加上稽查对象的前缀 @@ -539,7 +539,7 @@ namespace IRaCIS.Core.Application.Service }).ToList(); - var jsonDataValueDic = JsonConvert.DeserializeObject>(jsonStr); + var jsonDataValueDic = (JsonConvert.DeserializeObject>(jsonStr)).IfNullThrowConvertException(); foreach (var item in list) { if (!jsonDataValueDic.ContainsKey(item.Key)) @@ -881,7 +881,7 @@ namespace IRaCIS.Core.Application.Service DateType = child.DateType, }).ToListAsync(); - var JsonData = JsonConvert.DeserializeObject>(Data.JsonDetail); + var JsonData = (JsonConvert.DeserializeObject>(Data.JsonDetail)).IfNullThrowException(); foreach (var item in JsonData.Keys) { @@ -892,12 +892,12 @@ namespace IRaCIS.Core.Application.Service { if (datefirst.DateType == FrontAuditDateType.Date.GetDescription()) { - JsonData[item] = DateTime.Parse(JsonData[item].ToString()).ToString("yyyy-MM-dd"); + JsonData[item] = DateTime.Parse(JsonData[item].ToString()!).ToString("yyyy-MM-dd"); } if (datefirst.DateType == FrontAuditDateType.DateTime.GetDescription()) { - JsonData[item] = DateTime.Parse(JsonData[item].ToString()).ToString("yyyy-MM-dd HH:mm:ss"); + JsonData[item] = DateTime.Parse(JsonData[item].ToString()!).ToString("yyyy-MM-dd HH:mm:ss"); } } catch (Exception) diff --git a/IRaCIS.Core.Application/Service/Inspection/InspectionService.cs b/IRaCIS.Core.Application/Service/Inspection/InspectionService.cs index faa794da4..f3bb5cb61 100644 --- a/IRaCIS.Core.Application/Service/Inspection/InspectionService.cs +++ b/IRaCIS.Core.Application/Service/Inspection/InspectionService.cs @@ -29,7 +29,7 @@ namespace IRaCIS.Core.Application.Service.Inspection { //_repository.GetQueryable.GetQueryable < DataInspection > - var trialData = await _repository.GetQueryable().Where(x => x.Id == dto.TrialId).AsNoTracking().FirstOrDefaultAsync(); + var trialData = await _repository.GetQueryable().Where(x => x.Id == dto.TrialId).AsNoTracking().FirstNotNullAsync(); trialData.TrialFinishTime = trialData.TrialFinishTime == null ? DateTime.Now : trialData.TrialFinishTime; @@ -84,9 +84,9 @@ namespace IRaCIS.Core.Application.Service.Inspection data.Identification.ToLower() equals leftfrontAuditConfig.Identification.ToLower() - join moduleTypec in _repository.GetQueryable() on new { ModuleType = leftfrontAuditConfig.ModuleTypeId.Value } equals new { ModuleType = moduleTypec.Id } into moduleTypectemp + join moduleTypec in _repository.GetQueryable() on new { ModuleType = leftfrontAuditConfig.ModuleTypeId!.Value } equals new { ModuleType = moduleTypec.Id } into moduleTypectemp from leftmoduleTypec in moduleTypectemp.DefaultIfEmpty() - join OptTypec in _repository.GetQueryable() on new { ModuleType = leftfrontAuditConfig.OptTypeId.Value } equals new { ModuleType = OptTypec.Id } into optTypetemp + join OptTypec in _repository.GetQueryable() on new { ModuleType = leftfrontAuditConfig.OptTypeId!.Value } equals new { ModuleType = OptTypec.Id } into optTypetemp from leftOptType in optTypetemp.DefaultIfEmpty() select new GetDataInspectionOutDto() diff --git a/IRaCIS.Core.Application/Service/Institution/SiteService.cs b/IRaCIS.Core.Application/Service/Institution/SiteService.cs index b65b2379f..9d77f48ed 100644 --- a/IRaCIS.Core.Application/Service/Institution/SiteService.cs +++ b/IRaCIS.Core.Application/Service/Institution/SiteService.cs @@ -31,8 +31,8 @@ namespace IRaCIS.Application.Services .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)) - .WhereIf(!string.IsNullOrWhiteSpace(searchModel.Province), t => t.Country.Contains(searchModel.Province)) - .ProjectTo(_mapper.ConfigurationProvider); + .WhereIf(!string.IsNullOrWhiteSpace(searchModel.Province), t => t.Province.Contains(searchModel.Province)) + .ProjectTo(_mapper.ConfigurationProvider, new { isEn_Us = _userInfo.IsEn_Us }); return await siteQueryable.ToPagedListAsync(searchModel.PageIndex, searchModel.PageSize, string.IsNullOrWhiteSpace(searchModel.SortField) ? "SiteName" : searchModel.SortField, searchModel.Asc); @@ -67,7 +67,7 @@ namespace IRaCIS.Application.Services siteCommand.Code = await _siteRepository.Select(t => t.Code).DefaultIfEmpty().MaxAsync() + 1; - siteCommand.SiteCode = AppSettings.GetCodeStr(siteCommand.Code, nameof(User)); + siteCommand.SiteCode = AppSettings.GetCodeStr(siteCommand.Code, nameof(Site)); } var site = await _siteRepository.InsertOrUpdateAsync(siteCommand, true, exp); @@ -76,11 +76,6 @@ namespace IRaCIS.Application.Services } - - - - - } /// 删除研究中心 diff --git a/IRaCIS.Core.Application/Service/Management/UserService.cs b/IRaCIS.Core.Application/Service/Management/UserService.cs index 3a6af0f62..9fc51f6b4 100644 --- a/IRaCIS.Core.Application/Service/Management/UserService.cs +++ b/IRaCIS.Core.Application/Service/Management/UserService.cs @@ -12,6 +12,7 @@ using Microsoft.Identity.Client; using static IRaCIS.Core.Domain.Share.StaticData; using IRaCIS.Core.Application.ViewModel; using Medallion.Threading; +using EasyCaching.Core; namespace IRaCIS.Application.Services { @@ -25,7 +26,7 @@ namespace IRaCIS.Application.Services private readonly IRepository _userLogRepository; private readonly IDistributedLockProvider _distributedLockProvider; - private readonly IMemoryCache _cache; + private readonly IEasyCachingProvider _cache; private readonly IOptionsMonitor _verifyConfig; @@ -34,7 +35,7 @@ namespace IRaCIS.Application.Services IMailVerificationService mailVerificationService, IRepository verificationCodeRepository, - IMemoryCache cache, + IEasyCachingProvider cache, IRepository userTrialRepository, IOptionsMonitor verifyConfig, IRepository userLogRepository @@ -629,7 +630,7 @@ namespace IRaCIS.Application.Services string cacheKey = $"{cachePrefix}{userName}"; // 从缓存中获取登录失败次数 - int? failCount = _cache.Get(cacheKey); + int? failCount = _cache.Get(cacheKey).Value; if (failCount == null) { @@ -644,7 +645,8 @@ namespace IRaCIS.Application.Services { await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = Guid.Empty, OptUserId = Guid.Empty, LoginFaildName = userName,LoginPassword=password, OptType = UserOptType.AccountLocked }, true); - throw new BusinessValidationFailedException($"密码连续错误{maxFailures}次,当前账号已被限制登录,请等待 {lockoutMinutes} 分钟后再试。"); + //$"密码连续错误{maxFailures}次,当前账号已被限制登录,请等待 {lockoutMinutes} 分钟后再试。" + throw new BusinessValidationFailedException(_localizer["User_ErrorLimit", maxFailures, lockoutMinutes]); } var userLoginReturnModel = new LoginReturnDTO(); @@ -699,8 +701,8 @@ namespace IRaCIS.Application.Services .WhereIf(inQuery.OptType != null, t => t.OptType == inQuery.OptType) .WhereIf(inQuery.BeginDate != null, t => t.CreateTime >= inQuery.BeginDate) .WhereIf(inQuery.EndDate != null, t => t.CreateTime <= inQuery.EndDate) - .WhereIf(!string.IsNullOrEmpty(inQuery.LoginFaildName), t => t.LoginFaildName.Contains(inQuery.LoginFaildName)) - .WhereIf(!string.IsNullOrEmpty(inQuery.IP), t => t.IP.Contains(inQuery.IP)) + .WhereIf(!string.IsNullOrEmpty(inQuery.LoginFaildName), t => t.LoginFaildName.Contains(inQuery.LoginFaildName!)) + .WhereIf(!string.IsNullOrEmpty(inQuery.IP), t => t.IP.Contains(inQuery.IP!)) .ProjectTo(_mapper.ConfigurationProvider); var pageList = await userLogQueryable.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrWhiteSpace(inQuery.SortField) ? "Id" : inQuery.SortField, inQuery.Asc); diff --git a/IRaCIS.Core.Application/Service/QC/DTO/QARecordViewModel.cs b/IRaCIS.Core.Application/Service/QC/DTO/QARecordViewModel.cs index 490f23911..33157b4d2 100644 --- a/IRaCIS.Core.Application/Service/QC/DTO/QARecordViewModel.cs +++ b/IRaCIS.Core.Application/Service/QC/DTO/QARecordViewModel.cs @@ -386,7 +386,7 @@ namespace IRaCIS.Core.Application.Contracts.DTO public string ModalityForEdit { get; set; } = string.Empty; - + public bool IsHaveUploadFailed { get; set; } } public class QASeriesInfoDto diff --git a/IRaCIS.Core.Application/Service/QC/DTO/QCListViewModel.cs b/IRaCIS.Core.Application/Service/QC/DTO/QCListViewModel.cs index 61e990f2a..9b768d332 100644 --- a/IRaCIS.Core.Application/Service/QC/DTO/QCListViewModel.cs +++ b/IRaCIS.Core.Application/Service/QC/DTO/QCListViewModel.cs @@ -547,7 +547,7 @@ namespace IRaCIS.Core.Application.Contracts [DictionaryTranslateAttribute("YesOrNo")] public bool IsSuccess { get; set; } - public string Note = string.Empty; + public string Note { get; set; } } @@ -1099,6 +1099,8 @@ namespace IRaCIS.Core.Application.Contracts public int? Age { get; set; } public string Sex { get; set; } = string.Empty; + public bool IsHaveUploadFailed { get; set; } + } @@ -1383,6 +1385,10 @@ namespace IRaCIS.Core.Application.Contracts public DateTime? SubmitTime { get; set; } + public string SubmitUserName { get; set; } = String.Empty; + + public string SubmitUserRealName { get; set; } = String.Empty; + public string CurrentActionUserName { get; set; } = String.Empty; public string PreliminaryAuditUserName { get; set; } = String.Empty; diff --git a/IRaCIS.Core.Application/Service/QC/QCListService.cs b/IRaCIS.Core.Application/Service/QC/QCListService.cs index 41c6c8df8..171a83016 100644 --- a/IRaCIS.Core.Application/Service/QC/QCListService.cs +++ b/IRaCIS.Core.Application/Service/QC/QCListService.cs @@ -19,7 +19,7 @@ namespace IRaCIS.Core.Application.Image.QA private readonly IRepository _clinicalDataTrialSet; private readonly IRepository _trialQCQuestionAnswerRepository; private readonly IRepository _trialQCQuestionRepository; - private readonly IRepository _UserUploadFileRepository; + private readonly IRepository _consistencyCheckFileRepository; private IReadingImageTaskService _IReadingImageTaskService; @@ -30,14 +30,14 @@ namespace IRaCIS.Core.Application.Image.QA IRepository trialQCQuestionAnswerRepository, IRepository trialQCQuestionRepository, IReadingImageTaskService IReadingImageTaskService, - IRepository UserUploadFileRepository + IRepository consistencyCheckFileRepository ) { this._IReadingImageTaskService = IReadingImageTaskService; _subjectVisitRepository = subjectVisitRepository; this._trialQCQuestionAnswerRepository = trialQCQuestionAnswerRepository; this._trialQCQuestionRepository = trialQCQuestionRepository; - this._UserUploadFileRepository = UserUploadFileRepository; + this._consistencyCheckFileRepository = consistencyCheckFileRepository; _trialRepository = trialRepository; this._clinicalDataTrialSet = clinicalDataTrialSet; } @@ -851,7 +851,7 @@ namespace IRaCIS.Core.Application.Image.QA [HttpPost] public async Task> GetUserUploadFile(GetUserUploadFileInDto indto) { - var query = _repository.Where(t => t.TrialId == indto.TrialId) + var query = _repository.Where(t => t.TrialId == indto.TrialId) .ProjectTo(_mapper.ConfigurationProvider); return await query.ToPagedListAsync(indto.PageIndex, indto.PageSize, "CreateTime", false); diff --git a/IRaCIS.Core.Application/Service/QC/QCOperationService.cs b/IRaCIS.Core.Application/Service/QC/QCOperationService.cs index bb7f99c52..4cb37bf78 100644 --- a/IRaCIS.Core.Application/Service/QC/QCOperationService.cs +++ b/IRaCIS.Core.Application/Service/QC/QCOperationService.cs @@ -891,7 +891,7 @@ namespace IRaCIS.Core.Application.Image.QA if (nextIQCQuality.VisitId != null) { - var visit = await _subjectVisitRepository.Where(x => x.Id == nextIQCQuality.VisitId).FirstOrDefaultAsync(); + var visit = await _subjectVisitRepository.Where(x => x.Id == nextIQCQuality.VisitId).FirstNotNullAsync(); if (!visit.IsTake) { await ObtainOrCancelQCTask(inDto.TrialId, nextIQCQuality.VisitId.Value, true); @@ -925,7 +925,7 @@ namespace IRaCIS.Core.Application.Image.QA return new GetNextIQCQualityOutDto() { }; break; case TrialQCProcess.SingleAudit: - visitList = await _subjectVisitRepository.Where(x => x.SubmitState != SubmitStateEnum.None && x.TrialId == inDto.TrialId && x.PreliminaryAuditUserId!= _userInfo.Id&&(x.CurrentActionUserId == _userInfo.Id || (x.AuditState != AuditStateEnum.PrimaryQCPassed && !x.IsTake))).Include(x => x.Subject).ToListAsync(); + visitList = await _subjectVisitRepository.Where(x => x.SubmitState == SubmitStateEnum.Submitted && x.TrialId == inDto.TrialId && x.PreliminaryAuditUserId!= _userInfo.Id&&(x.CurrentActionUserId == _userInfo.Id || (x.AuditState != AuditStateEnum.PrimaryQCPassed && !x.IsTake))).Include(x => x.Subject).ToListAsync(); subjectVisit = visitList.Where(x => x.SubjectId == inDto.SubjectId).OrderBy(x => x.VisitNum).FirstOrDefault(); if (subjectVisit != null) @@ -953,7 +953,7 @@ namespace IRaCIS.Core.Application.Image.QA break; case TrialQCProcess.DoubleAudit: - visitList = await _subjectVisitRepository.Where(x => x.SubmitState != SubmitStateEnum.None && x.TrialId == inDto.TrialId && + visitList = await _subjectVisitRepository.Where(x => x.SubmitState == SubmitStateEnum.Submitted && x.TrialId == inDto.TrialId && ((x.CurrentActionUserId == _userInfo.Id)||(!x.IsTake&& x.AuditState != AuditStateEnum.QCPassed&& (x.PreliminaryAuditUserId != _userInfo.Id))) ).Include(x => x.Subject).ToListAsync(); if (subjectVisit != null) @@ -1174,7 +1174,7 @@ namespace IRaCIS.Core.Application.Image.QA var dbSubjectVisitList = await _subjectVisitRepository.Where(t => cRCRequestToQCCommand.SubjectVisitIds.Contains(t.Id), true).ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); //普通提交 - if (dbSubjectVisitList.Count() == 1) + if (dbSubjectVisitList.Count == 1) { var sv = dbSubjectVisitList[0]; @@ -1183,7 +1183,7 @@ namespace IRaCIS.Core.Application.Image.QA if (sv.PDState == PDStateEnum.PDProgress) { - if (nameList.Count() > 0) + if (nameList.Count > 0) { //$"当前访视要求进行疾病进展确认。请在提交当前访视前,先处理未提交的前序访视:{string.Join('、', nameList)}。" return ResponseOutput.NotOk(_localizer["QCOperation_DiseaseProgressConfirmation", string.Join('、', nameList)], 1, ApiResponseCodeEnum.NeedTips); @@ -1191,7 +1191,7 @@ namespace IRaCIS.Core.Application.Image.QA } else { - if (nameList.Count() > 0) + if (nameList.Count > 0) { //$"在提交当前访视后,请尽快处理尚未提交的前序访视:{string.Join('、', nameList)}。" return ResponseOutput.NotOk(_localizer["QCOperation_UnsubmittedVisits", string.Join('、', nameList)], 0, ApiResponseCodeEnum.NeedTips); @@ -1247,7 +1247,7 @@ namespace IRaCIS.Core.Application.Image.QA } //单个提交提示信息 - if (dbSubjectVisitList.Count() == 1 && dbSubjectVisitList.First().SubmitState == SubmitStateEnum.Submitted) + if (dbSubjectVisitList.Count == 1 && dbSubjectVisitList.First().SubmitState == SubmitStateEnum.Submitted) { //---当前访视的影像数据,已经由其他CRC提交。 return ResponseOutput.NotOk(_localizer["QCOperation_ImagesSubmitted"], 3, ApiResponseCodeEnum.NeedTips); diff --git a/IRaCIS.Core.Application/Service/QC/_MapConfig.cs b/IRaCIS.Core.Application/Service/QC/_MapConfig.cs index f0f5cec09..afde027f9 100644 --- a/IRaCIS.Core.Application/Service/QC/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/QC/_MapConfig.cs @@ -364,6 +364,10 @@ namespace IRaCIS.Core.Application.Service .ForMember(d => d.QCProcessEnum, u => u.MapFrom(s => s.Trial.QCProcessEnum)) .ForMember(d => d.SubjectStatus, u => u.MapFrom(s => s.Subject.Status)) .ForMember(d => d.StudyCount, u => u.MapFrom(s => s.StudyList.Count())) + + .ForMember(d => d.SubmitUserName, u => u.MapFrom(s => s.SubmitUser.UserName)) + .ForMember(d => d.SubmitUserRealName, u => u.MapFrom(s => s.SubmitUser.FullName)) + .ForMember(d => d.CurrentActionUserName, u => u.MapFrom(s => s.CurrentActionUser.UserName)) .ForMember(d => d.PreliminaryAuditUserName, u => u.MapFrom(s => s.PreliminaryAuditUser.UserName)) .ForMember(d => d.ReviewAuditUserName, u => u.MapFrom(s => s.ReviewAuditUser.UserName)) @@ -391,6 +395,8 @@ namespace IRaCIS.Core.Application.Service || t.ReadingClinicalDataList.Any(x => x.ClinicalDataTrialSet.UploadRole == Domain.Share.UploadRole.CRC && x.ReadingClinicalDataPDFList.Count() > 0) || t.PreviousSurgeryList.Any())) + .ForMember(d => d.IsHaveUploadFailed, u => u.MapFrom(t => t.StudyList.SelectMany(c=>c.DicomStudyMonitorList).Any(h => h.FailedFileCount>0) )) + //.ForMember(d => d.VisitName, u => u.MapFrom(t =>t.InPlan? t.VisitStage.VisitName : t.VisitName)) //.ForMember(d => d.VisitNum, u => u.MapFrom(t => t.InPlan ? t.VisitStage.VisitNum : t.VisitNum)) //.ForMember(d => d.VisitDay, u => u.MapFrom(t => t.InPlan ? t.VisitStage.VisitDay : t.VisitDay)) @@ -494,7 +500,7 @@ namespace IRaCIS.Core.Application.Service ; // 一致性核查文件 - CreateMap() + CreateMap() .ForMember(d => d.CreateUserName, u => u.MapFrom(t => t.User.FirstName + "/" + t.User.LastName)); diff --git a/IRaCIS.Core.Application/Service/Reading/ClinicalData/ClinicalAnswerService.cs b/IRaCIS.Core.Application/Service/Reading/ClinicalData/ClinicalAnswerService.cs index d5055d242..e5993175f 100644 --- a/IRaCIS.Core.Application/Service/Reading/ClinicalData/ClinicalAnswerService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ClinicalData/ClinicalAnswerService.cs @@ -523,7 +523,28 @@ namespace IRaCIS.Core.Application.Service var readModule = await _readModuleRepository.Where(x => x.Id == inDto.ReadModuleId).FirstNotNullAsync(); inDto.TrialReadingCriterionId = readModule.TrialReadingCriterionId; } + + // 有全局就查全局 有肿瘤学就查肿瘤学 + + var clinicalDataLevelList = await _clinicalDataTrialSetRepository.Where(x => x.TrialId == inDto.TrialId && x.IsConfirm && x.UploadRole == UploadRole.CRC && x.ClinicalUploadType == ClinicalUploadType.Structuring).Select(x => x.ClinicalDataLevel).Distinct().ToListAsync(); + + var existsCRCStructuring = clinicalDataLevelList.Any(x=>x== ClinicalLevel.OncologyRead|| x == ClinicalLevel.ImageRead); + + + ReadingSetType? readingSetType = null; + if (clinicalDataLevelList.Contains(ClinicalLevel.ImageRead) && !clinicalDataLevelList.Contains(ClinicalLevel.OncologyRead)) + { + readingSetType = ReadingSetType.ImageReading; + } + else if (clinicalDataLevelList.Contains(ClinicalLevel.OncologyRead) && !clinicalDataLevelList.Contains(ClinicalLevel.ImageRead)) + { + readingSetType = ReadingSetType.TumorReading; + } + + var query = _readModuleRepository.Where(x => x.TrialId == inDto.TrialId) + .Where(x=> existsCRCStructuring) + .WhereIf(inDto.ReadModuleId==null,x=>x.TrialReadingCriterion.IsConfirm) .WhereIf(inDto.ReadModuleId != null, x => x.Id == inDto.ReadModuleId) .WhereIf(inDto.IsCRCConfirm != null, x => x.IsCRCConfirm == inDto.IsCRCConfirm) .WhereIf(inDto.IsPMConfirm != null, x => x.IsPMConfirm == inDto.IsPMConfirm) @@ -532,6 +553,7 @@ namespace IRaCIS.Core.Application.Service .WhereIf(inDto.SubjectId != null, x => x.SubjectId == inDto.SubjectId) .WhereIf(inDto.StartTime != null, x => x.SubjectVisit.LatestScanDate >= inDto.StartTime) .WhereIf(inDto.EndTime != null, x => x.SubjectVisit.LatestScanDate <= inDto.EndTime) + .WhereIf(readingSetType != null, x => x.ReadingSetType== readingSetType) .Select(x => new GetCRCConfirmListOutDto() { diff --git a/IRaCIS.Core.Application/Service/Reading/ClinicalData/ClinicalQuestionService.cs b/IRaCIS.Core.Application/Service/Reading/ClinicalData/ClinicalQuestionService.cs index f7429b26b..2de31793d 100644 --- a/IRaCIS.Core.Application/Service/Reading/ClinicalData/ClinicalQuestionService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ClinicalData/ClinicalQuestionService.cs @@ -169,6 +169,8 @@ namespace IRaCIS.Core.Application.Service /// /// /// + /// + /// public void FindChildQuestion(ClinicalQuestionPreviewDto item, List questions, List tableQuestions,List answers, List tableAnswers) { item.Childrens = questions.Where(x => (x.ParentId == item.Id)||(x.GroupId== item.Id&&x.ParentId==null)).OrderBy(x => x.ShowOrder).ToList(); diff --git a/IRaCIS.Core.Application/Service/Reading/ClinicalData/ReadingClinicalDataService.cs b/IRaCIS.Core.Application/Service/Reading/ClinicalData/ReadingClinicalDataService.cs index bd20071e1..57ef41677 100644 --- a/IRaCIS.Core.Application/Service/Reading/ClinicalData/ReadingClinicalDataService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ClinicalData/ReadingClinicalDataService.cs @@ -111,7 +111,7 @@ namespace IRaCIS.Application.Services entity.ReadingClinicalDataState = ReadingClinicalDataStatus.HaveUploaded; entity.IsBlind = null; entity.IsComplete = null; - entity.FileCount = entity.ReadingClinicalDataPDFList.Count(); + entity.FileCount = entity.ReadingClinicalDataPDFList.Count; await _readingClinicalDataRepository.AddAsync(entity, true); var success = await _readingClinicalDataRepository.SaveChangesAsync(); return ResponseOutput.Ok(entity.Id); @@ -366,7 +366,7 @@ namespace IRaCIS.Application.Services //影像学 if (readModule.ReadingSetType == ReadingSetType.ImageReading) { - needSignCount = trialClinicalDataSetList.Where(t => t.TrialClinicalDataSetCriteriaList.Any(c => c.TrialReadingCriterionId == trialReadingCritrialId) && t.ClinicalDataLevel == ClinicalLevel.ImageRead).Count(); + needSignCount = trialClinicalDataSetList.Where(t => t.TrialClinicalDataSetCriteriaList.Any(c => c.TrialReadingCriterionId == trialReadingCritrialId) && t.ClinicalDataLevel == ClinicalLevel.ImageRead && t.UploadRole == UploadRole.PM).Count(); // 不存在需要CRC上传的临床数据 或者 PM已确认 crcReadModuleSign = @@ -376,12 +376,11 @@ namespace IRaCIS.Application.Services && x.ClinicalUploadType == ClinicalUploadType.Structuring && x.TrialClinicalDataSetCriteriaList.Any(c => c.TrialReadingCriterionId == trialReadingCritrialId)) || readModule.IsPMConfirm; - } //肿瘤学 else { - needSignCount = trialClinicalDataSetList.Where(t => t.TrialClinicalDataSetCriteriaList.Any(c => c.TrialReadingCriterionId == trialReadingCritrialId) && t.ClinicalDataLevel == ClinicalLevel.OncologyRead).Count(); + needSignCount = trialClinicalDataSetList.Where(t => t.TrialClinicalDataSetCriteriaList.Any(c => c.TrialReadingCriterionId == trialReadingCritrialId) && t.ClinicalDataLevel == ClinicalLevel.OncologyRead && t.UploadRole == UploadRole.PM).Count(); // 不存在需要CRC上传的临床数据 或者 PM已确认 crcReadModuleSign = @@ -512,7 +511,7 @@ namespace IRaCIS.Application.Services inDto.UploadRole = UploadRole.PM; } - ReadModule readModule = null; + ReadModule? readModule = null; if (inDto.IsVisit == false) { readModule = await _readModuleRepository.Where(x => x.Id == inDto.ReadingId).FirstOrDefaultAsync(); @@ -537,7 +536,7 @@ namespace IRaCIS.Application.Services .WhereIf(inDto.IsVisit && inDto.IsBaseLine, x => x.ClinicalDataLevel == ClinicalLevel.Subject || x.ClinicalDataLevel == ClinicalLevel.SubjectVisit) .WhereIf(inDto.IsVisit && !inDto.IsBaseLine, x => x.ClinicalDataLevel == ClinicalLevel.SubjectVisit) .WhereIf(!inDto.IsVisit, x => x.ClinicalDataLevel == ClinicalLevel.ImageRead || x.ClinicalDataLevel == ClinicalLevel.OncologyRead) - .WhereIf(readModule != null, x => x.ClinicalDataLevel == keyValuePairs[readModule.ModuleType]) + .WhereIf(readModule != null, x => x.ClinicalDataLevel == keyValuePairs[readModule!.ModuleType]) .WhereIf(inDto.TrialReadingCriterionId!=null,x=>x.TrialClinicalDataSetCriteriaList.Any(y=>y.TrialReadingCriterionId== inDto.TrialReadingCriterionId)) //.WhereIf(criterion!=null,x=>x.CriterionEnumListStr.Contains($"|{(int)criterion.CriterionType}|")) .Select(x => new GetTrialClinicalDataSelectOutDto() @@ -659,7 +658,7 @@ namespace IRaCIS.Application.Services return (result, new { - IsCanAddClinicalData = clinicalDataList.Count() > 0, + IsCanAddClinicalData = clinicalDataList.Count > 0, }); } @@ -718,7 +717,7 @@ namespace IRaCIS.Application.Services CheckDate = y.CheckDate, ClinicalFormId = y.Id }).ToList(); - x.FileCount = x.ClinicalFromList.Count(); + x.FileCount = x.ClinicalFromList.Count; }); @@ -763,6 +762,7 @@ namespace IRaCIS.Application.Services IsCRCUpload = x.UploadRole == UploadRole.CRC, IsNeedMerge = true, ReadModuleId = readModule.Id, + TrialClinicalDataSetCriteriaList=x.TrialClinicalDataSetCriteriaList, //FileCount = x.FileCount, //ReadingClinicalDataState = x.ReadingClinicalDataState, @@ -891,7 +891,7 @@ namespace IRaCIS.Application.Services CheckDate = y.CheckDate, ClinicalFormId = y.Id }).ToList(); - x.FileCount = x.ClinicalFromList.Count(); + x.FileCount = x.ClinicalFromList.Count; }); // 这里处理CRC上传 阅片期的临床数据 diff --git a/IRaCIS.Core.Application/Service/Reading/Dto/ReadingMedicalReviewDto.cs b/IRaCIS.Core.Application/Service/Reading/Dto/ReadingMedicalReviewDto.cs index 9a730f4b6..a626d7023 100644 --- a/IRaCIS.Core.Application/Service/Reading/Dto/ReadingMedicalReviewDto.cs +++ b/IRaCIS.Core.Application/Service/Reading/Dto/ReadingMedicalReviewDto.cs @@ -395,6 +395,9 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto public Arm ArmEnum { get; set; } + public bool IsExistsClinicalData { get; set; } + + public MedicalReviewAuditState AuditState { get; set; } diff --git a/IRaCIS.Core.Application/Service/Reading/Dto/ReadingQuestionViewModel.cs b/IRaCIS.Core.Application/Service/Reading/Dto/ReadingQuestionViewModel.cs index 6843367cd..3bac6c7a3 100644 --- a/IRaCIS.Core.Application/Service/Reading/Dto/ReadingQuestionViewModel.cs +++ b/IRaCIS.Core.Application/Service/Reading/Dto/ReadingQuestionViewModel.cs @@ -346,6 +346,11 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto /// public LimitEdit LimitEdit { get; set; } = LimitEdit.None; + /// + /// 限制显示 + /// + public LimitShow LimitShow { get; set; } = LimitShow.AllShow; + /// /// 最大答案长度 /// @@ -454,6 +459,11 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto /// public LimitEdit LimitEdit { get; set; } = LimitEdit.None; + /// + /// 限制显示 + /// + public LimitShow LimitShow { get; set; } = LimitShow.AllShow; + /// /// 最大答案长度 /// @@ -1000,6 +1010,11 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto /// public LimitEdit LimitEdit { get; set; } = LimitEdit.None; + /// + /// 限制显示 + /// + public LimitShow LimitShow { get; set; } = LimitShow.AllShow; + /// /// 最大答案长度 /// @@ -1058,6 +1073,11 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto /// public LimitEdit LimitEdit { get; set; } = LimitEdit.None; + /// + /// 限制显示 + /// + public LimitShow LimitShow { get; set; } = LimitShow.AllShow; + /// /// 最大答案长度 /// @@ -1560,6 +1580,11 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto /// public LimitEdit LimitEdit { get; set; } = LimitEdit.None; + /// + /// 限制显示 + /// + public LimitShow LimitShow { get; set; } = LimitShow.AllShow; + /// /// 最大答案长度 /// @@ -1916,6 +1941,11 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto /// public LimitEdit LimitEdit { get; set; } = LimitEdit.None; + /// + /// 限制显示 + /// + public LimitShow LimitShow { get; set; } = LimitShow.AllShow; + /// /// 最大答案长度 /// diff --git a/IRaCIS.Core.Application/Service/Reading/Interface/IClinicalAnswerService.cs b/IRaCIS.Core.Application/Service/Reading/Interface/IClinicalAnswerService.cs index a7b15aee6..0553e985a 100644 --- a/IRaCIS.Core.Application/Service/Reading/Interface/IClinicalAnswerService.cs +++ b/IRaCIS.Core.Application/Service/Reading/Interface/IClinicalAnswerService.cs @@ -21,5 +21,7 @@ namespace IRaCIS.Core.Application.Service.Reading.Interface Task CRCCancelConfirmClinical(CRCCancelConfirmClinicalInDto inDto); + Task> GetCRCConfirmList(GetCRCConfirmListInDto inDto); + } } diff --git a/IRaCIS.Core.Application/Service/Reading/MedicalAudit/ReadingMedicalReviewService.cs b/IRaCIS.Core.Application/Service/Reading/MedicalAudit/ReadingMedicalReviewService.cs index b0815aecd..fb8a70f37 100644 --- a/IRaCIS.Core.Application/Service/Reading/MedicalAudit/ReadingMedicalReviewService.cs +++ b/IRaCIS.Core.Application/Service/Reading/MedicalAudit/ReadingMedicalReviewService.cs @@ -33,6 +33,7 @@ namespace IRaCIS.Core.Application.Service private readonly IReadingImageTaskService _iReadingImageTaskService; private readonly IRepository _userTaskRepository; private readonly IVisitTaskService _visitTaskService; + private readonly IReadingClinicalDataService _readingClinicalDataService; private readonly IRepository _taskMedicalReviewRepository; private readonly IRepository _readingMedicalReviewDialogRepository; private readonly IRepository _readingQuestionCriterionTrial; @@ -52,6 +53,7 @@ namespace IRaCIS.Core.Application.Service IRepository readingCriterionDictionaryRepository, IRepository userTaskRepository, IVisitTaskService visitTaskService, + IReadingClinicalDataService readingClinicalDataService, IRepository taskMedicalReviewRepository, IRepository readingMedicalReviewDialogRepository, IRepository readingQuestionCriterionTrial, @@ -71,6 +73,7 @@ namespace IRaCIS.Core.Application.Service this._readingCriterionDictionaryRepository = readingCriterionDictionaryRepository; this._userTaskRepository = userTaskRepository; this._visitTaskService = visitTaskService; + this._readingClinicalDataService = readingClinicalDataService; this._taskMedicalReviewRepository = taskMedicalReviewRepository; this._readingMedicalReviewDialogRepository = readingMedicalReviewDialogRepository; this._readingQuestionCriterionTrial = readingQuestionCriterionTrial; @@ -109,6 +112,17 @@ namespace IRaCIS.Core.Application.Service medicalReviewInfo.VisitTaskId = taskInfo.Id; + + var clinicalDataList = await _readingClinicalDataService.GetClinicalDataList(new GetReadingOrTaskClinicalDataListInDto() + { + + SubjectId = taskInfo.SubjectId, + TrialId = taskInfo.TrialId, + VisitTaskId = taskInfo.Id, + }); + + medicalReviewInfo.IsExistsClinicalData = clinicalDataList.Count > 0; + medicalReviewInfo.ArmEnum = taskInfo.ArmEnum; medicalReviewInfo.SubjectCode = taskInfo.IsAnalysisCreate?taskInfo.BlindSubjectCode: taskInfo.Subject.Code; medicalReviewInfo.TaskBlindName = taskInfo.TaskBlindName; @@ -466,8 +480,12 @@ namespace IRaCIS.Core.Application.Service { throw new BusinessValidationFailedException(_localizer["MedicalReview_SaveQuestion"]); } + var medicalReview = await _taskMedicalReviewRepository.Where(x => x.Id == inDto.TaskMedicalReviewId).FirstNotNullAsync(); + await _taskMedicalReviewRepository.UpdatePartialFromQueryAsync(inDto.TaskMedicalReviewId, x => new TaskMedicalReview() { + + LatestReplyUserId = (inDto.IsSendDialog && !medicalReview.IsSendMessage && inDto.IsHaveQuestion) ? _userInfo.Id : null, IsHaveQuestion = inDto.IsHaveQuestion, Questioning = inDto.Questioning, IsSendMessage = inDto.IsSendDialog && inDto.IsHaveQuestion, @@ -476,9 +494,8 @@ namespace IRaCIS.Core.Application.Service AuditAdviceEnum = inDto.AuditAdviceEnum, SaveConclusionTime = DateTime.Now, - }); + }); ; - var medicalReview = await _taskMedicalReviewRepository.Where(x => x.Id == inDto.TaskMedicalReviewId).FirstNotNullAsync(); if (inDto.IsSendDialog&& !medicalReview.IsSendMessage && inDto.IsHaveQuestion) { @@ -511,6 +528,7 @@ namespace IRaCIS.Core.Application.Service { await _taskMedicalReviewRepository.UpdatePartialFromQueryAsync(inDto.TaskMedicalReviewId, x => new TaskMedicalReview() { + LatestReplyUserId=_userInfo.Id, IsClosedDialog = inDto.IsClosedDialog, MedicalDialogCloseEnum=inDto.MedicalDialogCloseEnum, DialogCloseReason=inDto.DialogCloseReason, @@ -547,6 +565,11 @@ namespace IRaCIS.Core.Application.Service throw new BusinessValidationFailedException(_localizer["MedicalReview_invalid"]); } + await _taskMedicalReviewRepository.UpdatePartialFromQueryAsync(inDto.TaskMedicalReviewId, x => new TaskMedicalReview() + { + LatestReplyUserId = _userInfo.Id, + }); + var visitTaskId = await _taskMedicalReviewRepository.Where(x => x.Id == inDto.TaskMedicalReviewId).Select(x => x.VisitTaskId).FirstOrDefaultAsync(); ReadingMedicalReviewDialog dialog = new ReadingMedicalReviewDialog() { @@ -600,6 +623,7 @@ namespace IRaCIS.Core.Application.Service await _taskMedicalReviewRepository.UpdatePartialFromQueryAsync(x => !x.IsClosedDialog && x.Id == inDto.TaskMedicalReviewId, x => new TaskMedicalReview() { + LatestReplyUserId=_userInfo.Id, IsClosedDialog = true, MedicalDialogCloseEnum = MedicalDialogClose.IRApplyReReading, @@ -613,6 +637,7 @@ namespace IRaCIS.Core.Application.Service await _taskMedicalReviewRepository.UpdatePartialFromQueryAsync(inDto.TaskMedicalReviewId, x => new TaskMedicalReview() { + LatestReplyUserId=_userInfo.Id, DoctorUserIdeaEnum = inDto.DoctorUserIdeaEnum, }); ReadingMedicalReviewDialog dialog = new ReadingMedicalReviewDialog() @@ -740,10 +765,11 @@ namespace IRaCIS.Core.Application.Service await _taskMedicalReviewRepository.UpdatePartialFromQueryAsync(inDto.TaskMedicalReviewId, x => new TaskMedicalReview() { + LatestReplyUserId = _userInfo.Id, DoctorUserIdeaEnum = inDto.DoctorUserIdeaEnum, DisagreeReason = inDto.DisagreeReason, - IsApplyHeavyReading=inDto.IsApplyHeavyReading, - }); + IsApplyHeavyReading = inDto.IsApplyHeavyReading, + }); ; var visitTaskId = await _taskMedicalReviewRepository.Where(x => x.Id == inDto.TaskMedicalReviewId).Select(x => x.VisitTaskId).FirstOrDefaultAsync(); await _readingMedicalReviewDialogRepository.AddAsync(new ReadingMedicalReviewDialog() diff --git a/IRaCIS.Core.Application/Service/Reading/MedicalAudit/ReadingMedicineQuestionService.cs b/IRaCIS.Core.Application/Service/Reading/MedicalAudit/ReadingMedicineQuestionService.cs index d63618cb3..806c53078 100644 --- a/IRaCIS.Core.Application/Service/Reading/MedicalAudit/ReadingMedicineQuestionService.cs +++ b/IRaCIS.Core.Application/Service/Reading/MedicalAudit/ReadingMedicineQuestionService.cs @@ -59,7 +59,7 @@ namespace IRaCIS.Core.Application.Service .WhereIf(inDto.CriterionTypeEnum != null, x => x.CriterionTypeEnum==inDto.CriterionTypeEnum) .WhereIf(inDto.TrialReadingCriterionId != null, x => x.CriterionTypeEnum== criterionEnum || x.IsGeneral==true) .WhereIf(inDto.IsGeneral != null, x => x.IsGeneral == inDto.IsGeneral) - .WhereIf(inDto.LanguageType != null, x => x.LanguageType == inDto.LanguageType.Value) + .WhereIf(inDto.LanguageType != null, x => x.LanguageType == inDto.LanguageType!.Value) .ProjectTo(_mapper.ConfigurationProvider).OrderBy(x => x.ShowOrder); return await query.ToPagedListAsync(inDto.PageIndex, inDto.PageSize, new string[2] { "LanguageType desc", "ShowOrder asc" }); @@ -516,7 +516,7 @@ namespace IRaCIS.Core.Application.Service } } - await _readingMedicineTrialQuestionRepository.AddRangeAsync(needList); + await _readingMedicineTrialQuestionRepository.AddRangeAsync(_mapper.Map>(needList)); var result = await _readingMedicineTrialQuestionRepository.SaveChangesAsync(); return ResponseOutput.Ok(); } diff --git a/IRaCIS.Core.Application/Service/Reading/ReadingCriterion/ReadingQuestionService.cs b/IRaCIS.Core.Application/Service/Reading/ReadingCriterion/ReadingQuestionService.cs index 4e227fb40..47561fa4f 100644 --- a/IRaCIS.Core.Application/Service/Reading/ReadingCriterion/ReadingQuestionService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ReadingCriterion/ReadingQuestionService.cs @@ -368,7 +368,6 @@ namespace IRaCIS.Application.Services /// /// 新增修改系统表格问题 /// - /// /// [HttpPost] public async Task AddOrUpdateReadingTableQuestionSystem(ReadingTableQuestionSystemAddOrEdit addOrEditReadingTableQuestionSystem) @@ -481,11 +480,12 @@ namespace IRaCIS.Application.Services } /// - /// 验证计算关系 + /// 验证计算关系 /// /// /// /// + /// /// private void VerifyCalculateRelation(List relationList,Guid QuestionId,Guid originalId,int count=1) { @@ -877,7 +877,7 @@ namespace IRaCIS.Application.Services { var question = x.Clone(); question.ReadingQuestionCriterionSystemId = inDto.ToSystemCriterionId; - question.Id = questionRelation[question.Id.Value]; + question.Id = questionRelation[question.Id!.Value]; if (question.ParentId != null) { question.ParentId = questionRelation[question.ParentId ?? default(Guid)]; diff --git a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs index 32265b84d..6f5196d56 100644 --- a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs @@ -64,12 +64,10 @@ namespace IRaCIS.Application.Services private readonly IRepository _noneDicomStudyFileSystem; private readonly IRepository _readingQuestionTrialRepository; private readonly ISchedulerFactory _schedulerFactory; - private readonly IMemoryCache _cache; private readonly ITrialEmailNoticeConfigService _trialEmailNoticeConfigService; public ReadingImageTaskService( - IMapper mapper, IRepository noneDicomStudyRepository, IRepository visitTaskRepository, IRepository TrialRepository, @@ -92,7 +90,6 @@ namespace IRaCIS.Application.Services IRepository userRepository, IEasyCachingProvider provider, IRepository readingCustomTagRepository, - IMemoryCache cache, IRepository readingCriterionDictionaryRepository, IRepository readingTrialCriterionDictionaryRepository, IRepository tumorAssessmentRepository, @@ -110,7 +107,6 @@ namespace IRaCIS.Application.Services ) { _schedulerFactory = schedulerFactory; - base._mapper = mapper; this._noneDicomStudyRepository = noneDicomStudyRepository; this._visitTaskRepository = visitTaskRepository; this._trialRepository = TrialRepository; @@ -146,7 +142,6 @@ namespace IRaCIS.Application.Services this._readingQuestionSystem = ReadingQuestionSystem; this._noneDicomStudyFileSystem = noneDicomStudyFileSystem; this._readingQuestionTrialRepository = readingQuestionTrialRepository; - this._cache = cache; this._trialEmailNoticeConfigService = trialEmailNoticeConfigService; } @@ -709,9 +704,9 @@ namespace IRaCIS.Application.Services { //await AddDefaultValueToTask(inDto.VisitTaskId); var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync(); - var result = await GetReadingQuestion(taskInfo.TrialReadingCriterionId, taskInfo.Id); + var result = await GetReadingQuestion(taskInfo.TrialReadingCriterionId, taskInfo.Id); - return (result, new + return (result, new { ReadingTaskState = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Select(x => x.ReadingTaskState).FirstOrDefaultAsync() @@ -723,6 +718,8 @@ namespace IRaCIS.Application.Services /// /// /// + /// + /// /// [NonDynamicMethod] public async Task> GetReadingQuestion(Guid trialReadingCriterionId, Guid? visitTaskId) @@ -752,6 +749,16 @@ namespace IRaCIS.Application.Services var taskinfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).ProjectTo(_mapper.ConfigurationProvider).FirstNotNullAsync(); + if (taskinfo.VisitTaskNum == 0) + { + questions = questions.Where(x => x.LimitShow == LimitShow.AllShow || x.LimitShow == LimitShow.BaseLineShow).ToList(); + + } + else + { + questions = questions.Where(x => x.LimitShow == LimitShow.AllShow || x.LimitShow == LimitShow.FollowShow).ToList(); + } + questions.ForEach(x => { x.CrterionDictionaryGroup = ReadingCommon.GetCrterionDictionaryGroup(taskinfo.IsConvertedTask); @@ -827,10 +834,7 @@ namespace IRaCIS.Application.Services [HttpGet] public async Task> GetTableAnswerRowInfoList(GetTableAnswerRowInfoInDto inDto) { - await _readingCalculateService.AddTaskLesionAnswerFromLastTask(new AddTaskLesionAnswerFromLastTaskInDto() - { - VisitTaskId = inDto.VisitTaskId - }); + var result = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId) .WhereIf(inDto.QuestionId != null, x => x.QuestionId == inDto.QuestionId) .ProjectTo(_mapper.ConfigurationProvider).OrderBy(x => x.ShowOrder).ThenBy(x => x.RowIndex) @@ -979,8 +983,18 @@ namespace IRaCIS.Application.Services if (inDto.TaskId != null) { taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.TaskId).ProjectTo(_mapper.ConfigurationProvider).FirstNotNullAsync(); + if (taskInfo.VisitTaskNum == 0) + { + qusetionList = qusetionList.Where(x => x.LimitShow == LimitShow.AllShow || x.LimitShow == LimitShow.BaseLineShow).ToList(); - qusetionList.ForEach(x => + } + else + { + qusetionList = qusetionList.Where(x => x.LimitShow == LimitShow.AllShow || x.LimitShow == LimitShow.FollowShow).ToList(); + } + + + qusetionList.ForEach(x => { x.CrterionDictionaryGroup = ReadingCommon.GetCrterionDictionaryGroup(taskInfo.IsConvertedTask); }); @@ -1112,7 +1126,7 @@ namespace IRaCIS.Application.Services var firstData = newPageQusetionList.FirstOrDefault(); var page = new TrialReadQuestionData() { - PageName = firstData.PageName, + PageName = firstData!.PageName, IsPage = true, IsPublicPage = firstData.IsPublicPage, }; @@ -1127,8 +1141,8 @@ namespace IRaCIS.Application.Services groupList.Add(page); } - result.PublicPage = groupList.Where(x => x.IsPublicPage.Value).ToList(); - result.MultiPage = groupList.Where(x => !x.IsPublicPage.Value).ToList(); + result.PublicPage = groupList.Where(x => x.IsPublicPage!.Value).ToList(); + result.MultiPage = groupList.Where(x => !x.IsPublicPage!.Value).ToList(); } else { @@ -1152,12 +1166,19 @@ namespace IRaCIS.Application.Services } /// - /// 获取子元素 + /// 获取子元素 /// /// /// /// - private async void FindChildQuestion(TrialReadQuestionData item, List questionlists, List tableQuestionLists, List tableAnswers, List tableAnsweRowInfos, List organInfos, List baseLineTableAnswer, bool isFirstChangeTask, List lastTaskTableAnswer, Guid? TaskId) + /// + /// + /// + /// + /// + /// + /// + private async void FindChildQuestion(TrialReadQuestionData item, List questionlists, List tableQuestionLists, List tableAnswers, List tableAnsweRowInfos, List organInfos, List baseLineTableAnswer,bool isFirstChangeTask, List lastTaskTableAnswer,Guid? TaskId) { item.Childrens = questionlists.Where(x => x.ParentId == item.Id || (x.GroupId == item.Id && x.ParentId == null)).ToList(); item.TableQuestions = new TrialReadTableQuestion(); @@ -2088,11 +2109,6 @@ namespace IRaCIS.Application.Services } - await _visitTaskRepository.UpdatePartialFromQueryAsync(inDto.VisitTaskId, x => new VisitTask() - { - ReadingTaskState = ReadingTaskState.Reading, - - }); await _readingTableAnswerRowInfoRepository.SaveChangesAsync(); await this._readingCalculateService.CalculateTask(new CalculateTaskInDto() { @@ -2292,7 +2308,7 @@ namespace IRaCIS.Application.Services VisitNum = x.VisitTaskNum, TrialReadingCriterionId = x.TrialReadingCriterionId, - }).FirstOrDefaultAsync(); + }).FirstNotNullAsync(); } else if (inDto.SubjectId != null && trialReadingCriterion.IsReadingTaskViewInOrder) @@ -2300,7 +2316,7 @@ namespace IRaCIS.Application.Services var subjectTaskList = (await _visitTaskService.GetOrderReadingIQueryable(new GetOrderReadingIQueryableInDto() { TrialId = inDto.TrialId, - TrialReadingCriterionId = trialReadingCriterionId.Value, + TrialReadingCriterionId = trialReadingCriterionId!.Value, Page = new PageInput() { PageIndex = 1, @@ -2453,6 +2469,15 @@ namespace IRaCIS.Application.Services task.IsNeedReadClinicalData = clinicalDataList.Where(x => x.ClinicalDataLevel != ClinicalLevel.Subject).Count() > 0; } + if (visitTaskInfo.ReadingTaskState == ReadingTaskState.WaitReading) + { + await _readingCalculateService.AddTaskLesionAnswerFromLastTask(new AddTaskLesionAnswerFromLastTaskInDto() + { + VisitTaskId = task.VisitTaskId + }); + } + + // 如果已经签名 就不需要再读了 task.IsNeedReadClinicalData = visitTaskInfo.ReadingTaskState == ReadingTaskState.HaveSigned ? false : task.IsNeedReadClinicalData; task.DigitPlaces = criterionInfo.DigitPlaces; @@ -2474,51 +2499,51 @@ namespace IRaCIS.Application.Services [HttpPost] public async Task VerifyReadingRestTime() { - var cacheKey = _userInfo.Id.ToString() + "RestTime"; + //var cacheKey = _userInfo.Id.ToString() + "RestTime"; - var value = _provider.Get(cacheKey).Value; - if (value == null) - { - _provider.Set(cacheKey, DateTime.Now.ToString(), TimeSpan.FromHours(5)); - // _cache.Set(cacheKey, DateTime.Now.ToString(), TimeSpan.FromHours(5)); + //var value = _provider.Get(cacheKey).Value; + //if (value == null) + //{ + // _provider.Set(cacheKey, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromHours(5)); + // // _cache.Set(cacheKey, DateTime.Now.ToString(), TimeSpan.FromHours(5)); - } - else - { - #region 两小时 - var cacheDate = DateTime.Parse(value.ToString()); - int timespanMin = (DateTime.Now - cacheDate).Minutes; - if (timespanMin > 120 && timespanMin < 140) - { - throw new BusinessValidationFailedException(_localizer["ReadingImage_NeedRest", 2, 20]); - } - else if (timespanMin > 140) - { - cacheDate = cacheDate.AddMinutes((Math.Floor((double)(timespanMin / 140))) * 140); - _provider.Set(cacheKey, cacheDate.ToString(), TimeSpan.FromHours(5)); - // _cache.Set(cacheKey, cacheDate.ToString(), TimeSpan.FromHours(5)); + //} + //else + //{ + // #region 两小时 + // var cacheDate = DateTime.Parse(value.ToString()); + // int timespanMin = (DateTime.Now - cacheDate).Minutes; + // if (timespanMin > 120 && timespanMin < 140) + // { + // throw new BusinessValidationFailedException(_localizer["ReadingImage_NeedRest", 2, 20]); + // } + // else if (timespanMin > 140) + // { + // cacheDate = cacheDate.AddMinutes((Math.Floor((double)(timespanMin / 140))) * 140); + // _provider.Set(cacheKey, cacheDate.ToString(), TimeSpan.FromHours(5)); + // // _cache.Set(cacheKey, cacheDate.ToString(), TimeSpan.FromHours(5)); - } - #endregion + // } + // #endregion - #region 测试用的5分钟 - //var cacheDate = DateTime.Parse(value.ToString()); - //int timespanMin = (DateTime.Now - cacheDate).Minutes; - //if (timespanMin >= 5 && timespanMin <= 10) - //{ - // throw new BusinessValidationFailedException("您已连续阅片2个小时,请休息20分钟后,再继续阅片。"); - //} - //else if (timespanMin > 10) - //{ - // cacheDate = cacheDate.AddMinutes((Math.Floor((double)(timespanMin / 10))) * 10); - // _cache.Set(cacheKey, cacheDate.ToString(), TimeSpan.FromHours(5)); + // #region 测试用的5分钟 + // //var cacheDate = DateTime.Parse(value.ToString()); + // //int timespanMin = (DateTime.Now - cacheDate).Minutes; + // //if (timespanMin >= 5 && timespanMin <= 10) + // //{ + // // throw new BusinessValidationFailedException("您已连续阅片2个小时,请休息20分钟后,再继续阅片。"); + // //} + // //else if (timespanMin > 10) + // //{ + // // cacheDate = cacheDate.AddMinutes((Math.Floor((double)(timespanMin / 10))) * 10); + // // _cache.Set(cacheKey, cacheDate.ToString(), TimeSpan.FromHours(5)); - //} - #endregion + // //} + // #endregion - } + //} diff --git a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingNoDicomTaskService.cs b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingNoDicomTaskService.cs index 4328fa62a..c069570fb 100644 --- a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingNoDicomTaskService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingNoDicomTaskService.cs @@ -55,11 +55,6 @@ namespace IRaCIS.Application.Services TrialId = inDto.TrialId }).ToList(); - await _visitTaskRepository.UpdatePartialFromQueryAsync(inDto.VisitTaskId, x => new VisitTask() - { - ReadingTaskState = ReadingTaskState.Reading, - - }); await _readingTaskQuestionAnswerRepository.AddRangeAsync(readingTaskAnswerList); var result = await _visitTaskRepository.SaveChangesAsync(); return ResponseOutput.Ok(result); diff --git a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingOncologyTaskService.cs b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingOncologyTaskService.cs index 70bb92f7e..7db32b19c 100644 --- a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingOncologyTaskService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingOncologyTaskService.cs @@ -191,7 +191,6 @@ namespace IRaCIS.Application.Services await _readingOncologyTaskInfoRepository.AddRangeAsync(readingOncologies); - await _visitTaskRepository.UpdatePartialFromQueryAsync(t => t.Id == inDto.OncologyTaskId, u => new VisitTask() { ReadingTaskState = ReadingTaskState.Reading }); var result = await _readingOncologyTaskInfoRepository.SaveChangesAsync(); diff --git a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingTaskQuestionService.cs b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingTaskQuestionService.cs index 874a2545f..82a62dead 100644 --- a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingTaskQuestionService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingTaskQuestionService.cs @@ -85,7 +85,7 @@ namespace IRaCIS.Application.Services var firstData = newPageQusetionList.FirstOrDefault(); var page = new GetTrialReadingQuestionOutDto() { - PageName = firstData.PageName, + PageName = firstData!.PageName, IsPage = true, IsPublicPage = firstData.IsPublicPage, }; @@ -100,8 +100,8 @@ namespace IRaCIS.Application.Services groupList.Add(page); } - result.PublicPage = groupList.Where(x => x.IsPublicPage.Value).ToList(); - result.MultiPage = groupList.Where(x => !x.IsPublicPage.Value).ToList(); + result.PublicPage = groupList.Where(x => x.IsPublicPage!.Value).ToList(); + result.MultiPage = groupList.Where(x => !x.IsPublicPage!.Value).ToList(); } else { diff --git a/IRaCIS.Core.Application/Service/Reading/_MapConfig.cs b/IRaCIS.Core.Application/Service/Reading/_MapConfig.cs index 1cc0def3a..caf0c7959 100644 --- a/IRaCIS.Core.Application/Service/Reading/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/Reading/_MapConfig.cs @@ -57,7 +57,7 @@ namespace IRaCIS.Core.Application.Service CreateMap(); CreateMap(); - + CreateMap(); CreateMap(); CreateMap(); diff --git a/IRaCIS.Core.Application/Service/ReadingCalculate/General/ReadingCalculateService.cs b/IRaCIS.Core.Application/Service/ReadingCalculate/General/ReadingCalculateService.cs index 6b37448c4..53aea15cb 100644 --- a/IRaCIS.Core.Application/Service/ReadingCalculate/General/ReadingCalculateService.cs +++ b/IRaCIS.Core.Application/Service/ReadingCalculate/General/ReadingCalculateService.cs @@ -126,36 +126,35 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate { var service = await this.GetService(inDto.VisitTaskId); var visitTaskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync(); - if (service != null && visitTaskInfo.SourceSubjectVisitId != null) + var result = new AddTaskLesionAnswerFromLastTaskOutDto(); + var readingTaskState = visitTaskInfo.ReadingTaskState; + if (service != null && visitTaskInfo.SourceSubjectVisitId != null) { - var readingTaskState = visitTaskInfo.ReadingTaskState; - var result = new AddTaskLesionAnswerFromLastTaskOutDto(); - if (readingTaskState == ReadingTaskState.WaitReading) { - result = await service.AddTaskLesionAnswerFromLastTask(inDto); - await service.CalculateTask(new CalculateTaskInDto() + if (visitTaskInfo.ReadingCategory == ReadingCategory.Visit) { - IsChangeOtherTask = false, - VisitTaskId = inDto.VisitTaskId, - }); - - await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => x.Id == inDto.VisitTaskId, x => new VisitTask() - { - ReadingTaskState = ReadingTaskState.Reading, - - }); - + result = await service.AddTaskLesionAnswerFromLastTask(inDto); + await service.CalculateTask(new CalculateTaskInDto() + { + IsChangeOtherTask = false, + VisitTaskId = inDto.VisitTaskId, + }); + } } - - return result; - } - else - { - return new AddTaskLesionAnswerFromLastTaskOutDto(); } + if (readingTaskState == ReadingTaskState.WaitReading) + { + await _visitTaskRepository.UpdatePartialFromQueryAsync(inDto.VisitTaskId, x => new VisitTask() + { + ReadingTaskState = ReadingTaskState.Reading, + },true); + } - } + return result; + + + } /// /// 获取报告验证的信息(这里每个标准可能不一样 返回用object) @@ -181,7 +180,6 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate /// /// 获取阅片报告 /// - /// /// public async Task GetReadingReportEvaluation(GetReadingReportEvaluationInDto inDto) { diff --git a/IRaCIS.Core.Application/Service/ReadingCalculate/IRECIST1Point1CalculateService.cs b/IRaCIS.Core.Application/Service/ReadingCalculate/IRECIST1Point1CalculateService.cs index c03e760e7..15f9dc136 100644 --- a/IRaCIS.Core.Application/Service/ReadingCalculate/IRECIST1Point1CalculateService.cs +++ b/IRaCIS.Core.Application/Service/ReadingCalculate/IRECIST1Point1CalculateService.cs @@ -149,7 +149,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate result.LesionCountList = tableAnsweRowInfos.GroupBy(x => x.LesionType).Select(x => new LesionDto { - LesionType = x.Key.Value, + LesionType = x.Key!.Value, Count = x.ToList().Count() }).ToList(); @@ -711,7 +711,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate if (valueOfTypes.Contains(item.ValueType)) { - item.Answer = decimal.Round(decimal.Parse(item.Answer ?? "0"), inDto.DigitPlaces).ToString(); + item.Answer = decimal.Round(decimal.Parse(item.Answer ?? "0"), inDto.DigitPlaces).ToString("F" + inDto.DigitPlaces.ToString()); } } catch (Exception) @@ -1775,7 +1775,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate { VisitTaskId = x.VisitTaskId, Answer = x.Answer, - QuestionType = x.ReadingQuestionTrial.QuestionType.Value + QuestionType = x.ReadingQuestionTrial.QuestionType!.Value }).ToListAsync(); compareTaskList.ForEach(y => diff --git a/IRaCIS.Core.Application/Service/ReadingCalculate/PCWG3CalculateService.cs b/IRaCIS.Core.Application/Service/ReadingCalculate/PCWG3CalculateService.cs index 26d2dd314..555d26336 100644 --- a/IRaCIS.Core.Application/Service/ReadingCalculate/PCWG3CalculateService.cs +++ b/IRaCIS.Core.Application/Service/ReadingCalculate/PCWG3CalculateService.cs @@ -2,7 +2,6 @@ using IRaCIS.Core.Domain.Share; using Microsoft.AspNetCore.Mvc; using IRaCIS.Core.Domain.Models; -using Microsoft.AspNetCore.Mvc; using IRaCIS.Core.Application.Interfaces; using IRaCIS.Core.Application.ViewModel; using Panda.DynamicWebApi.Attributes; @@ -650,7 +649,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate if (valueOfTypes.Contains(item.ValueType)) { - item.Answer = decimal.Round(decimal.Parse(item.Answer.IsNullOrEmpty() ? "0": item.Answer), inDto.DigitPlaces).ToString(); + item.Answer = decimal.Round(decimal.Parse(item.Answer.IsNullOrEmpty() ? "0": item.Answer), inDto.DigitPlaces).ToString("F" + inDto.DigitPlaces.ToString()); } } catch (Exception) diff --git a/IRaCIS.Core.Application/Service/ReadingCalculate/RECIST1Point1CalculateService.cs b/IRaCIS.Core.Application/Service/ReadingCalculate/RECIST1Point1CalculateService.cs index b3176136a..27709adc0 100644 --- a/IRaCIS.Core.Application/Service/ReadingCalculate/RECIST1Point1CalculateService.cs +++ b/IRaCIS.Core.Application/Service/ReadingCalculate/RECIST1Point1CalculateService.cs @@ -2,7 +2,6 @@ using IRaCIS.Core.Domain.Share; using Microsoft.AspNetCore.Mvc; using IRaCIS.Core.Domain.Models; -using Microsoft.AspNetCore.Mvc; using IRaCIS.Core.Application.Interfaces; using IRaCIS.Core.Application.ViewModel; using Panda.DynamicWebApi.Attributes; @@ -550,7 +549,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate if (valueOfTypes.Contains(item.ValueType)) { - item.Answer = decimal.Round(decimal.Parse(item.Answer ?? "0"), inDto.DigitPlaces).ToString(); + item.Answer = decimal.Round(decimal.Parse(item.Answer ?? "0"), inDto.DigitPlaces).ToString("F" + inDto.DigitPlaces.ToString()); } } catch (Exception) diff --git a/IRaCIS.Core.Application/Service/ReadingCalculate/RECIST1Point1_BMCalculateService.cs b/IRaCIS.Core.Application/Service/ReadingCalculate/RECIST1Point1_BMCalculateService.cs index 84fa1de05..8447d64eb 100644 --- a/IRaCIS.Core.Application/Service/ReadingCalculate/RECIST1Point1_BMCalculateService.cs +++ b/IRaCIS.Core.Application/Service/ReadingCalculate/RECIST1Point1_BMCalculateService.cs @@ -2,7 +2,6 @@ using IRaCIS.Core.Domain.Share; using Microsoft.AspNetCore.Mvc; using IRaCIS.Core.Domain.Models; -using Microsoft.AspNetCore.Mvc; using IRaCIS.Core.Application.Interfaces; using IRaCIS.Core.Application.ViewModel; using Panda.DynamicWebApi.Attributes; @@ -546,7 +545,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate if (valueOfTypes.Contains(item.ValueType)) { - item.Answer = decimal.Round(decimal.Parse(item.Answer ?? "0"), inDto.DigitPlaces).ToString(); + item.Answer = decimal.Round(decimal.Parse(item.Answer ?? "0"), inDto.DigitPlaces).ToString("F" + inDto.DigitPlaces.ToString()); } } catch (Exception) diff --git a/IRaCIS.Core.Application/Service/ReadingCalculate/SelfDefineCalculateService.cs b/IRaCIS.Core.Application/Service/ReadingCalculate/SelfDefineCalculateService.cs index 3e0bf3ea9..9f74d91ef 100644 --- a/IRaCIS.Core.Application/Service/ReadingCalculate/SelfDefineCalculateService.cs +++ b/IRaCIS.Core.Application/Service/ReadingCalculate/SelfDefineCalculateService.cs @@ -2,7 +2,6 @@ using IRaCIS.Core.Domain.Share; using Microsoft.AspNetCore.Mvc; using IRaCIS.Core.Domain.Models; -using Microsoft.AspNetCore.Mvc; using IRaCIS.Core.Application.Interfaces; using IRaCIS.Core.Application.ViewModel; using Panda.DynamicWebApi.Attributes; diff --git a/IRaCIS.Core.Application/Service/SiteSurvey/DTO/TrialSiteUserSurveyViewModel.cs b/IRaCIS.Core.Application/Service/SiteSurvey/DTO/TrialSiteUserSurveyViewModel.cs index d272c3cba..20115971f 100644 --- a/IRaCIS.Core.Application/Service/SiteSurvey/DTO/TrialSiteUserSurveyViewModel.cs +++ b/IRaCIS.Core.Application/Service/SiteSurvey/DTO/TrialSiteUserSurveyViewModel.cs @@ -104,6 +104,8 @@ namespace IRaCIS.Core.Application.Contracts [DictionaryTranslateAttribute("YesOrNo")] public bool IsGenerateAccount { get; set; } + + [DictionaryTranslateAttribute("SiteSurvey_UserRoles")] public int TrialRoleCode { get; set; } public string OrganizationName { get; set; } = string.Empty; diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/UserTrialViewModel.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/UserTrialViewModel.cs index cbd35d4d0..6e0e3fe84 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/UserTrialViewModel.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/UserTrialViewModel.cs @@ -22,14 +22,14 @@ namespace IRaCIS.Application.Contracts [DictionaryTranslateAttribute("IsUserExitTrial")] public bool IsDeleted { get; set; } - [ExcelFormat("yyyy-MM-dd hh:mm:ss")] + [ExcelFormat("yyyy-MM-dd HH:mm:ss")] public DateTime? DeletedTime { get; set; } public Guid? SiteId { get; set; } public string Phone { get; set; } = String.Empty; public DateTime UpdateTime { get; set; } - [ExcelFormat("yyyy-MM-dd hh:mm:ss")] + [ExcelFormat("yyyy-MM-dd HH:mm:ss")] public DateTime CreateTime { get; set; } @@ -84,7 +84,7 @@ namespace IRaCIS.Application.Contracts [ExporterHeader(Format = "yyyy-mm-DD hh:mm:ss")] - [ExcelFormat("yyyy-MM-dd hh:mm:ss")] + [ExcelFormat("yyyy-MM-dd HH:mm:ss")] public DateTime CreateTime { get; set; } @@ -118,7 +118,8 @@ namespace IRaCIS.Application.Contracts public class ExcelExportInfo : TrialSelectDTO { - public DateTime CurrentTime { get; set; } = DateTime.Now; + + public string CurrentTime { get; set; } = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); public bool IsEn_US { get; set; } diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/PersonalWorkstation.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/PersonalWorkstation.cs index c0cef017d..35a614438 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/PersonalWorkstation.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/PersonalWorkstation.cs @@ -1,6 +1,7 @@ using IRaCIS.Application.Contracts; using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Application.Interfaces; +using IRaCIS.Core.Application.Service.Reading.Interface; using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Share; @@ -21,11 +22,13 @@ namespace IRaCIS.Core.Application private readonly IRepository _trialDocumentRepository; private readonly IRepository _systemDocumentRepository; private readonly IRepository _readModuleRepository; + private readonly IClinicalAnswerService _clinicalAnswerService; private readonly IRepository _systemNoticeRepository; public PersonalWorkstation(IRepository trialRepository, IRepository trialUserRepository, IRepository trialDocumentRepository, IRepository systemDocumentRepository, IRepository readModuleRepository, + IClinicalAnswerService clinicalAnswerService, IRepository systemNoticeRepository) { _trialRepository = trialRepository; @@ -33,6 +36,7 @@ namespace IRaCIS.Core.Application _trialDocumentRepository = trialDocumentRepository; _systemDocumentRepository = systemDocumentRepository; this._readModuleRepository = readModuleRepository; + this._clinicalAnswerService = clinicalAnswerService; _systemNoticeRepository = systemNoticeRepository; } @@ -48,11 +52,11 @@ namespace IRaCIS.Core.Application //正参与的数量 TrialCount = _userInfo.UserTypeEnumInt == (int)UserTypeEnum.SuperAdmin ? await _trialRepository.CountAsync() - : await _trialUserRepository.Where(t => t.UserId == _userInfo.Id).CountAsync(), + : await _trialUserRepository.Where(t => t.UserId == _userInfo.Id && t.Trial.IsDeleted == false).CountAsync(), DeletedCount = _userInfo.UserTypeEnumInt == (int)UserTypeEnum.SuperAdmin ? await _trialRepository.AsQueryable(true).CountAsync(t => t.IsDeleted) - : await _trialUserRepository.AsQueryable(true).Where(t => t.UserId == _userInfo.Id && t.IsDeleted) + : await _trialUserRepository.AsQueryable(true).Where(t => t.UserId == _userInfo.Id && t.Trial.IsDeleted) .CountAsync(), @@ -204,11 +208,12 @@ namespace IRaCIS.Core.Application ToBeRepliedCount = t.SubjectVisitList.Where(u => u.CheckState == CheckStateEnum.CVIng && u.CheckChallengeDialogList.OrderByDescending(t => t.CreateTime).First().UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Count(), - }).Where(x => x.ToBeRepliedCount > 0); + }).Where(x => x.ToBeRepliedCount > 0); + var defalutSortArray = new string[] { nameof(CheckToBeDoneDto.UrgentCount) + " desc", nameof(CheckToBeDoneDto.ToBeCheckedCount) + " desc" }; - var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrEmpty(inQuery.SortField) ? nameof(CheckToBeDoneDto.TrialId) : inQuery.SortField, inQuery.Asc); + var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField, inQuery.Asc, string.IsNullOrWhiteSpace(inQuery.SortField), defalutSortArray); var totalToBeCheckedCount = await _subjectVisitRepository.Where(t => t.Trial.TrialUserList.Any(t => t.UserId == _userInfo.Id)) .Where(u => u.CheckState == CheckStateEnum.ToCheck).CountAsync(); @@ -250,7 +255,9 @@ namespace IRaCIS.Core.Application }).Where(x => x.ToBeApprovalCount > 0); - var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrEmpty(inQuery.SortField) ? nameof(ReReadingApplyToBeDoneDto.TrialId) : inQuery.SortField, inQuery.Asc); + var defalutSortArray = new string[] { nameof(ReReadingApplyToBeDoneDto.UrgentCount) + " desc", nameof(ReReadingApplyToBeDoneDto.ToBeApprovalCount) + " desc" }; + + var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField, inQuery.Asc, string.IsNullOrWhiteSpace(inQuery.SortField), defalutSortArray); var toBeApprovalCount = _visitTaskReReadingRepository @@ -271,7 +278,7 @@ namespace IRaCIS.Core.Application [HttpPost] public async Task>> GetPMClinicalDataToBeDoneList(ReviewerSelectToBeDoneQuery inQuery) { - + var query = _trialRepository .Where(t => t.TrialUserList.Any(t => t.UserId == _userInfo.Id)) .Select(t => new GetPMClinicalDataToBeDoneListOutDto() @@ -281,14 +288,18 @@ namespace IRaCIS.Core.Application ExperimentName = t.ExperimentName, TrialCode = t.TrialCode, - - ToBeApprovalCount = t.ReadModuleList.Where(u => u.IsCRCConfirm&&!u.IsPMConfirm).Count() + + ToBeApprovalCount = t.ReadModuleList.Where(u => u.IsCRCConfirm && !u.IsPMConfirm).Count() }).Where(x => x.ToBeApprovalCount > 0); - var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrEmpty(inQuery.SortField) ? nameof(ReviewerSelectToBeDoneDto.TrialId) : inQuery.SortField, inQuery.Asc); - - var all =await _trialRepository + var defalutSortArray = new string[] { nameof(GetPMClinicalDataToBeDoneListOutDto.ToBeApprovalCount) + " desc" }; + + var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField, inQuery.Asc, string.IsNullOrWhiteSpace(inQuery.SortField), defalutSortArray); + + + + var all = await _trialRepository .Where(t => t.TrialUserList.Any(t => t.UserId == _userInfo.Id)) .Select(t => new GetPMClinicalDataToBeDoneListOutDto() { @@ -297,7 +308,7 @@ namespace IRaCIS.Core.Application ToBeApprovalCount = t.ReadModuleList.Where(u => u.IsCRCConfirm && !u.IsPMConfirm).Count() }).ToListAsync(); - return ResponseOutput.Ok(result, new { ToBeApprovalCount = all.Sum(x=>x.ToBeApprovalCount) }); ; + return ResponseOutput.Ok(result, new { ToBeApprovalCount = all.Sum(x => x.ToBeApprovalCount) }); ; } #endregion @@ -335,7 +346,10 @@ namespace IRaCIS.Core.Application }).Where(x => x.ToBeApprovalCount > 0); - var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrEmpty(inQuery.SortField) ? nameof(ReReadingApprovalToBeDoneDto.TrialId) : inQuery.SortField, inQuery.Asc); + var defalutSortArray = new string[] { nameof(ReReadingApprovalToBeDoneDto.UrgentCount) + " desc", nameof(ReReadingApprovalToBeDoneDto.ToBeApprovalCount) + " desc" }; + + var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField, inQuery.Asc, string.IsNullOrWhiteSpace(inQuery.SortField), defalutSortArray); + var toBeApprovalCount = _visitTaskReReadingRepository .Where(t => t.OriginalReReadingTask.Trial.TrialUserList.Any(t => t.UserId == _userInfo.Id)) @@ -356,6 +370,7 @@ namespace IRaCIS.Core.Application /// /// /// + /// /// [HttpPost] public async Task>> GetImageClinicalDataToBeDoneList(ImageClinicalDataToBeDoneQuery inQuery, @@ -373,13 +388,15 @@ namespace IRaCIS.Core.Application ExperimentName = t.ExperimentName, TrialCode = t.TrialCode, UrgentCount = t.SubjectVisitList.Where(u => u.IsBaseLine && u.SubmitState != SubmitStateEnum.Submitted && u.IsUrgent).Count(), - ToBeDealedCount = t.ReadingClinicalDataList.Where(x=>!x.IsSign&& x.ClinicalDataTrialSet.UploadRole == UploadRole.CRC && x.ClinicalDataTrialSet.ClinicalDataLevel != ClinicalLevel.SubjectVisit&& x.ClinicalDataTrialSet.ClinicalDataLevel != ClinicalLevel.Subject).Count(), - ToBeVisitCount= t.ReadingClinicalDataList.Where(x => !x.IsSign && x.ClinicalDataTrialSet.UploadRole == UploadRole.CRC && x.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.SubjectVisit).Count(), - ToAllCount= t.ReadingClinicalDataList.Where(x => !x.IsSign && x.ClinicalDataTrialSet.UploadRole == UploadRole.CRC ).Count(), - ReadModuleCount =t.ReadModuleList.Where(x=>!x.IsPMConfirm).Count(), - }).Where(x=>x.ToBeDealedCount > 0); + ToBeDealedCount = t.ReadingClinicalDataList.Where(x => !x.IsSign && x.ClinicalDataTrialSet.UploadRole == UploadRole.CRC && x.ClinicalDataTrialSet.ClinicalDataLevel != ClinicalLevel.SubjectVisit && x.ClinicalDataTrialSet.ClinicalDataLevel != ClinicalLevel.Subject).Count(), + ToBeVisitCount = t.ReadingClinicalDataList.Where(x => !x.IsSign && x.ClinicalDataTrialSet.UploadRole == UploadRole.CRC && x.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.SubjectVisit).Count(), + ToAllCount = t.ReadingClinicalDataList.Where(x => !x.IsSign && x.ClinicalDataTrialSet.UploadRole == UploadRole.CRC).Count(), + ReadModuleCount = t.ReadModuleList.Where(x => !x.IsPMConfirm).Count(), + }).Where(x => x.ToBeDealedCount > 0); - var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrEmpty(inQuery.SortField) ? nameof(ImageClinicalDataToBeDoneDto.TrialId) : inQuery.SortField, inQuery.Asc); + var defalutSortArray = new string[] { nameof(ImageClinicalDataToBeDoneDto.UrgentCount) + " desc", nameof(ImageClinicalDataToBeDoneDto.ReadModuleCount) + " desc" }; + + var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField, inQuery.Asc, string.IsNullOrWhiteSpace(inQuery.SortField), defalutSortArray); var toBeDealedCount = _subjectVisitRepository //.Where(t => t.Trial.TrialUserList.Any(t => t.UserId == _userInfo.Id) && t.Trial.clinicalDataTrialSets.Any(t => t.ClinicalDataLevel == ClinicalLevel.Subject && t.IsConfirm)) @@ -395,6 +412,7 @@ namespace IRaCIS.Core.Application /// /// /// + /// /// [HttpPost] public async Task>> GetImageClinicalDataToBeConfirmList(ImageClinicalDataToBeDoneQuery inQuery, @@ -415,10 +433,29 @@ namespace IRaCIS.Core.Application ToBeDealedCount = t.ReadingClinicalDataList.Where(x => !x.IsSign && x.ClinicalDataTrialSet.UploadRole == UploadRole.CRC && x.ClinicalDataTrialSet.ClinicalDataLevel != ClinicalLevel.SubjectVisit && x.ClinicalDataTrialSet.ClinicalDataLevel != ClinicalLevel.Subject).Count(), ToBeVisitCount = t.ReadingClinicalDataList.Where(x => !x.IsSign && x.ClinicalDataTrialSet.UploadRole == UploadRole.CRC && x.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.SubjectVisit).Count(), ToAllCount = t.ReadingClinicalDataList.Where(x => !x.IsSign && x.ClinicalDataTrialSet.UploadRole == UploadRole.CRC).Count(), - ReadModuleCount = t.ReadModuleList.Where(x => !x.IsPMConfirm).Count(), + ReadModuleCount = t.ReadModuleList.Where(x => !x.IsCRCConfirm).Count(), }).Where(x => x.ReadModuleCount > 0); - var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrEmpty(inQuery.SortField) ? nameof(ImageClinicalDataToBeDoneDto.TrialId) : inQuery.SortField, inQuery.Asc); + var defalutSortArray = new string[] { nameof(ImageClinicalDataToBeDoneDto.UrgentCount) + " desc", nameof(ImageClinicalDataToBeDoneDto.ToBeDealedCount) + " desc" }; + + var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField, inQuery.Asc, string.IsNullOrWhiteSpace(inQuery.SortField), defalutSortArray); + + + // ReadModuleCount情况太多了 暂时用之前的方法 + foreach (var item in result.CurrentPageData) + { + item.ReadModuleCount = (await _clinicalAnswerService.GetCRCConfirmList(new Service.Reading.Dto.GetCRCConfirmListInDto() + { + TrialId = item.TrialId, + IsPMConfirm = false, + PageIndex = 1, + PageSize = 9999, + + })).CurrentPageData.Count(); + } + + + result.CurrentPageData = result.CurrentPageData.Where(x => x.ReadModuleCount != 0).ToList(); var toBeDealedCount = _subjectVisitRepository //.Where(t => t.Trial.TrialUserList.Any(t => t.UserId == _userInfo.Id) && t.Trial.clinicalDataTrialSets.Any(t => t.ClinicalDataLevel == ClinicalLevel.Subject && t.IsConfirm)) @@ -461,11 +498,14 @@ namespace IRaCIS.Core.Application ToBeDealedCount = t.SubjectVisitList.Where(c => c.TrialSite.CRCUserList.Any(u => u.UserId == _userInfo.Id)) .SelectMany(c => c.QCChallengeList) - .Where(u => u.IsClosed == false && u.LatestReplyUser.UserTypeEnum == UserTypeEnum.IQC).Count(), + .Where(u => u.IsClosed == false && (u.LatestReplyUser.UserTypeEnum == UserTypeEnum.IQC || u.LatestReplyUserId == null)).Count(), }).Where(x => x.ToBeDealedCount > 0); ; - var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrEmpty(inQuery.SortField) ? nameof(ImageQuestionToBeDoneDto.TrialId) : inQuery.SortField, inQuery.Asc); + var defalutSortArray = new string[] { nameof(ImageQuestionToBeDoneDto.UrgentCount) + " desc", nameof(ImageQuestionToBeDoneDto.ToBeDealedCount) + " desc" }; + + var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField, inQuery.Asc, string.IsNullOrWhiteSpace(inQuery.SortField), defalutSortArray); + var toBeDealedCount = _subjectVisitRepository .Where(t => t.Trial.TrialUserList.Any(t => t.UserId == _userInfo.Id)) @@ -482,6 +522,7 @@ namespace IRaCIS.Core.Application /// /// /// + /// /// [HttpPost] public async Task>> GetImageCheckQuestionToBeDoneList(ImageCheckQuestionToBeDoneQuery inQuery, @@ -507,9 +548,10 @@ namespace IRaCIS.Core.Application }).Where(x => x.ToBeReplyedCount > 0); + var defalutSortArray = new string[] { nameof(ImageCheckQuestionToBeDoneDto.UrgentCount) + " desc", nameof(ImageCheckQuestionToBeDoneDto.ToBeReplyedCount) + " desc" }; + var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField, inQuery.Asc, string.IsNullOrWhiteSpace(inQuery.SortField), defalutSortArray); - var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrEmpty(inQuery.SortField) ? nameof(ImageCheckQuestionToBeDoneDto.TrialId) : inQuery.SortField, inQuery.Asc); var toBeDealedCount = _subjectVisitRepository .Where(t => t.Trial.TrialUserList.Any(t => t.UserId == _userInfo.Id)) @@ -521,12 +563,12 @@ namespace IRaCIS.Core.Application } - /// /// 影像重传 --CRC 待办 /// /// /// + /// /// [HttpPost] public async Task>> GetImageReUploadToBeDoneList(ImageReUploadToBeDoneQuery inQuery, @@ -544,19 +586,22 @@ namespace IRaCIS.Core.Application TrialCode = t.TrialCode, UrgentCount = t.SubjectVisitList .Where(c => c.TrialSite.CRCUserList.Any(u => u.UserId == _userInfo.Id)) - .Where(u => u.SubmitState == SubmitStateEnum.ToSubmit && u.IsUrgent && u.IsPMBackOrReReading).Count(), + .Where(u => u.IsUrgent && ((u.SubmitState == SubmitStateEnum.ToSubmit && u.IsPMBackOrReReading) || u.IsQCConfirmedReupload)).Count(), ToBeReUploadCount = t.SubjectVisitList .Where(c => c.TrialSite.CRCUserList.Any(u => u.UserId == _userInfo.Id)) - .Where(u => u.SubmitState == SubmitStateEnum.ToSubmit && u.IsPMBackOrReReading).Count(), + .Where(u => (u.SubmitState == SubmitStateEnum.ToSubmit && u.IsPMBackOrReReading) || (u.IsQCConfirmedReupload)).Count(), }).Where(x => x.ToBeReUploadCount > 0); - var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrEmpty(inQuery.SortField) ? nameof(ImageReUploadToBeDoneDto.TrialId) : inQuery.SortField, inQuery.Asc); + + var defalutSortArray = new string[] { nameof(ImageReUploadToBeDoneDto.UrgentCount) + " desc", nameof(ImageReUploadToBeDoneDto.ToBeReUploadCount) + " desc" }; + + var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField, inQuery.Asc, string.IsNullOrWhiteSpace(inQuery.SortField), defalutSortArray); var toBeDealedCount = _subjectVisitRepository .Where(t => t.Trial.TrialUserList.Any(t => t.UserId == _userInfo.Id)) - .Where(u => u.SubmitState == SubmitStateEnum.ToSubmit && u.IsPMBackOrReReading).Count(); + .Where(u => (u.SubmitState == SubmitStateEnum.ToSubmit && u.IsPMBackOrReReading) || (u.IsQCConfirmedReupload)).Count(); return ResponseOutput.Ok(result, new { TotalToBeReUploadCount = toBeDealedCount }); @@ -566,10 +611,11 @@ namespace IRaCIS.Core.Application /// - /// 加急影像提交 --CRC 待办 + /// 加急影像提交 --CRC 待办 /// /// /// + /// /// [HttpPost] public async Task>> GetImageSubmittedToBeDoneList(ImageSubmittedToBeDoneQuery inQuery, @@ -587,7 +633,7 @@ namespace IRaCIS.Core.Application TrialCode = t.TrialCode, UrgentCount = t.SubjectVisitList .Where(c => c.TrialSite.CRCUserList.Any(u => u.UserId == _userInfo.Id)) - .Where(u => u.SubmitState == SubmitStateEnum.ToSubmit && u.IsUrgent).Count(), + .Where(u => u.SubmitState == SubmitStateEnum.ToSubmit && (u.IsEnrollmentConfirm || u.PDState == PDStateEnum.PDProgress || u.Trial.IsUrgent || u.Subject.IsUrgent)/*u.IsUrgent*/).Count(), ToBeDealedCount = t.SubjectVisitList @@ -596,7 +642,12 @@ namespace IRaCIS.Core.Application }).Where(x => x.ToBeDealedCount > 0); ; - var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrEmpty(inQuery.SortField) ? nameof(ImageSubmittedToBeDoneDto.TrialId) : inQuery.SortField, inQuery.Asc); + + + var defalutSortArray = new string[] { nameof(ImageSubmittedToBeDoneDto.UrgentCount) + " desc", nameof(ImageSubmittedToBeDoneDto.ToBeDealedCount) + " desc" }; + + var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField, inQuery.Asc, string.IsNullOrWhiteSpace(inQuery.SortField), defalutSortArray); + var toBeDealedCount = _subjectVisitRepository .Where(t => t.Trial.TrialUserList.Any(t => t.UserId == _userInfo.Id)) @@ -620,6 +671,7 @@ namespace IRaCIS.Core.Application /// /// /// + /// /// [HttpPost] public async Task>> GetImageQualityToBeDoneList(ImageQualityToBeDoneQuery inQuery, @@ -642,18 +694,23 @@ namespace IRaCIS.Core.Application //待领取量 - ToBeClaimedCount = t.SubjectVisitList.Where(u => u.CurrentActionUserId == null && (u.PreliminaryAuditUserId == null || (u.PreliminaryAuditUserId != _userInfo.Id && u.ReviewAuditUserId == null))).Count(), + ToBeClaimedCount = t.SubjectVisitList.Where(t => t.SubmitState == SubmitStateEnum.Submitted && t.AuditState!=AuditStateEnum.QCPassed) + .Where(u => u.CurrentActionUserId == null && (u.PreliminaryAuditUserId == null || (u.PreliminaryAuditUserId != _userInfo.Id && u.ReviewAuditUserId == null))).Count(), //待审核通过,统计从已领取到QC提交之间的 已领取 待审核 审核中 (审核完成 领取人就会清理 所以只用查询当前领取人是自己的就好了) ToBeReviewedCount = t.SubjectVisitList.Where(u => u.CurrentActionUserId == _userInfo.Id).Count() - }).Where(x => x.UrgentCount > 0); + }).Where(x => x.ToBeClaimedCount + x.ToBeReviewedCount > 0); + + + var defalutSortArray = new string[] { nameof(ImageQualityToBeDoneDto.UrgentCount) + " desc", nameof(ImageQualityToBeDoneDto.ToBeClaimedCount) + " desc" }; + + var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField, inQuery.Asc, string.IsNullOrWhiteSpace(inQuery.SortField), defalutSortArray); - var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrEmpty(inQuery.SortField) ? nameof(ImageQualityToBeDoneDto.TrialId) : inQuery.SortField, inQuery.Asc); var toBeClaimedCount = _subjectVisitRepository - .Where(t => t.Trial.TrialUserList.Any(t => t.UserId == _userInfo.Id)) + .Where(t => t.Trial.TrialUserList.Any(t => t.UserId == _userInfo.Id)&& t.SubmitState == SubmitStateEnum.Submitted && t.AuditState != AuditStateEnum.QCPassed) .Where(u => u.CurrentActionUserId == null && (u.PreliminaryAuditUserId == null || (u.PreliminaryAuditUserId != _userInfo.Id && u.ReviewAuditUserId == null))).Count(); @@ -667,10 +724,11 @@ namespace IRaCIS.Core.Application /// - /// QC 质疑 + /// QC 质疑 /// /// /// + /// /// [HttpPost] public async Task>> GetQCImageQuestionToBeDoneList(ImageQuestionToBeDoneQuery inQuery, @@ -694,7 +752,10 @@ namespace IRaCIS.Core.Application }).Where(x => x.ToBeDealedCount > 0); ; - var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrEmpty(inQuery.SortField) ? nameof(ImageQuestionToBeDoneDto.TrialId) : inQuery.SortField, inQuery.Asc); + var defalutSortArray = new string[] { nameof(ImageQuestionToBeDoneDto.UrgentCount) + " desc", nameof(ImageQuestionToBeDoneDto.ToBeDealedCount) + " desc" }; + + var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField, inQuery.Asc, string.IsNullOrWhiteSpace(inQuery.SortField), defalutSortArray); + var toBeDealedCount = _subjectVisitRepository .Where(t => t.Trial.TrialUserList.Any(t => t.UserId == _userInfo.Id)) @@ -835,8 +896,9 @@ namespace IRaCIS.Core.Application #endregion + var defalutSortArray = new string[] { nameof(IRImageReadingToBeDoneDto.UrgentCount) + " desc", nameof(IRImageReadingToBeDoneDto.UnReadCount) + " desc" }; - var result = await newQuery.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrEmpty(inQuery.SortField) ? nameof(IRImageReadingToBeDoneDto.TrialId) : inQuery.SortField, inQuery.Asc); + var result = await newQuery.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField, inQuery.Asc, string.IsNullOrWhiteSpace(inQuery.SortField), defalutSortArray); var toBeDealedCount = _trialRepository .Where(t => t.TrialUserList.Any(t => t.UserId == _userInfo.Id)) @@ -857,7 +919,7 @@ namespace IRaCIS.Core.Application /// IR医学反馈 /// /// - + /// /// [HttpPost] public async Task>> GetIRMedicalCommentsToBeDoneList(MedicalCommentsToBeDoneQuery inQuery, @@ -885,20 +947,35 @@ namespace IRaCIS.Core.Application CriterionName = g.Key.CriterionName, TrialReadingCriterionId = g.Key.TrialReadingCriterionId, + #region 不能对包含聚合或子查询的表达式执行聚合函数 + + + UrgentCount = g.Where(u => u.VisitTask.IsUrgent && u.LatestReplyUser.UserTypeEnum== UserTypeEnum.MIM).Count(), + + ToBeReplyedCount = g.Where(u => u.LatestReplyUser.UserTypeEnum == UserTypeEnum.MIM).Count(), + + #endregion //UrgentCount = g.Where(u => u.VisitTask.IsUrgent //&& u.ReadingMedicalReviewDialogList.OrderByDescending(l => l.CreateTime).First().UserTypeEnumInt == (int)UserTypeEnum.MIM).Count(), //ToBeReplyedCount = g.Where(u => // u.ReadingMedicalReviewDialogList.OrderByDescending(l => l.CreateTime).First().UserTypeEnumInt == (int)UserTypeEnum.MIM).Count(), - }); + }).Where(t => t.ToBeReplyedCount > 0); + + + var defalutSortArray = new string[] { nameof(MedicalCommentsToBeDoneDto.UrgentCount) + " desc", nameof(MedicalCommentsToBeDoneDto.ToBeReplyedCount) + " desc" }; + + var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField, inQuery.Asc, string.IsNullOrWhiteSpace(inQuery.SortField), defalutSortArray); + - var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrEmpty(inQuery.SortField) ? nameof(MedicalCommentsToBeDoneDto.TrialId) : inQuery.SortField, inQuery.Asc); var toBeDealedCount = _taskMedicalReviewRepository .Where(t => t.Trial.TrialUserList.Any(t => t.UserId == _userInfo.Id)) .Where(t => t.IsClosedDialog == false && t.VisitTask.DoctorUserId == _userInfo.Id) - .Where(u => u.ReadingMedicalReviewDialogList.OrderByDescending(l => l.CreateTime).First().UserTypeEnumInt == (int)UserTypeEnum.MIM).Count(); + .Where(u => u.LatestReplyUser.UserTypeEnum == UserTypeEnum.MIM) + //.Where(u => u.ReadingMedicalReviewDialogList.OrderByDescending(l => l.CreateTime).First().UserTypeEnumInt == (int)UserTypeEnum.MIM) + .Count(); return ResponseOutput.Ok(result, new { TotalToBeReplyedCount = toBeDealedCount }); @@ -916,7 +993,7 @@ namespace IRaCIS.Core.Application /// /// /// - + /// /// [HttpPost] public async Task>> GetMIMMedicalCommentsToBeDoneList(MedicalCommentsToBeDoneQuery inQuery, @@ -945,24 +1022,33 @@ namespace IRaCIS.Core.Application TrialCode = g.Key.TrialCode, CriterionName = g.Key.CriterionName, + UrgentCount = g.Where(u => u.VisitTask.IsUrgent).Select(u => u.VisitTask.IsUrgent && u.LatestReplyUser.UserTypeEnum == UserTypeEnum.IndependentReviewer).Count(), + + ToBeReplyedCount = g.Select(u => u.LatestReplyUser.UserTypeEnum == UserTypeEnum.IndependentReviewer).Count(), + //UrgentCount = g.Where(u => u.VisitTask.IsUrgent).Select(u => u.ReadingMedicalReviewDialogList.OrderByDescending(l => l.CreateTime).First()).Count(t => t.UserTypeEnumInt == (int)UserTypeEnum.IndependentReviewer), //ToBeReplyedCount = g.Select(t => t.ReadingMedicalReviewDialogList.OrderByDescending(l => l.CreateTime).First()).Count(t => t.UserTypeEnumInt == (int)UserTypeEnum.IndependentReviewer), ToBeReviewedCount = g.Where(u => !u.IsInvalid && u.AuditState != MedicalReviewAuditState.HaveSigned).Count() - }); + }).Where(t => t.ToBeReplyedCount > 0); #endregion + var defalutSortArray = new string[] { nameof(MedicalCommentsToBeDoneDto.UrgentCount) + " desc", nameof(MedicalCommentsToBeDoneDto.ToBeReplyedCount) + " desc" }; + + var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField, inQuery.Asc, string.IsNullOrWhiteSpace(inQuery.SortField), defalutSortArray); + - var result = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrEmpty(inQuery.SortField) ? nameof(MedicalCommentsToBeDoneDto.TrialId) : inQuery.SortField, inQuery.Asc); var toBeReplyedQuery = _taskMedicalReviewRepository .Where(t => t.Trial.TrialUserList.Any(t => t.UserId == _userInfo.Id)) .Where(t => t.IsClosedDialog == false) - .Where(u => u.ReadingMedicalReviewDialogList.OrderByDescending(l => l.CreateTime).First().UserTypeEnumInt == (int)UserTypeEnum.IndependentReviewer); + .Where(u => u.LatestReplyUser.UserTypeEnum == UserTypeEnum.IndependentReviewer); + + //.Where(u => u.ReadingMedicalReviewDialogList.OrderByDescending(l => l.CreateTime).First().UserTypeEnumInt == (int)UserTypeEnum.IndependentReviewer); var toBeReplyedCount = toBeReplyedQuery.Count(); diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs index 039a80267..d00f86b81 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs @@ -18,7 +18,6 @@ using IRaCIS.Core.Application.Filter; using static IRaCIS.Core.Domain.Share.StaticData; using IRaCIS.Core.Application.Service; using DocumentFormat.OpenXml.Office.CustomUI; -using IRaCIS.Core.Application.Service; using IRaCIS.Core.Domain.Models; namespace IRaCIS.Core.Application @@ -105,7 +104,7 @@ namespace IRaCIS.Core.Application [HttpPost] public async Task TrialReadingInfoSignVerify(TrialReadingInfoSignInDto inDto) { - var trialCriterion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inDto.TrialReadingCriterionId).FirstOrDefaultAsync(); + var trialCriterion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inDto.TrialReadingCriterionId).FirstNotNullAsync(); var existsJudge = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == trialCriterion.Id && x.IsJudgeQuestion && x.JudgeType == JudgeTypeEnum.None) .WhereIf(trialCriterion.FormType == FormType.SinglePage, x => x.ReadingCriterionPageId == null) .WhereIf(trialCriterion.FormType == FormType.MultiplePage, x => x.ReadingCriterionPageId != null) @@ -145,7 +144,7 @@ namespace IRaCIS.Core.Application [NonDynamicMethod] public async Task TrialReadingInfoSign(TrialReadingInfoSignInDto inDto) { - var trialCriterion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inDto.TrialReadingCriterionId).FirstOrDefaultAsync(); + var trialCriterion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inDto.TrialReadingCriterionId).FirstNotNullAsync(); var existsJudge = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == trialCriterion.Id && x.IsJudgeQuestion && x.JudgeType == JudgeTypeEnum.None) .WhereIf(trialCriterion.FormType == FormType.SinglePage, x => x.ReadingCriterionPageId == null) @@ -437,7 +436,7 @@ namespace IRaCIS.Core.Application [HttpPost] public async Task<(List, object)> GetTrialReadingJudgeList(GetTrialReadingInfoInDto inDto) { - var trialCriterion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inDto.TrialReadingCriterionId).FirstOrDefaultAsync(); + var trialCriterion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inDto.TrialReadingCriterionId).FirstNotNullAsync(); var judgeQuestionList = await _readingQuestionTrialRepository .WhereIf(trialCriterion.FormType == FormType.SinglePage, x => x.ReadingCriterionPageId == null) @@ -485,7 +484,7 @@ namespace IRaCIS.Core.Application { GetTrialReadingCriterionInfoOutDto result = new GetTrialReadingCriterionInfoOutDto(); result.ReadingCriterionPageList = await _readingCriterionPageRepository.Where(x => x.TrialId == inDto.TrialId).ProjectTo(_mapper.ConfigurationProvider).OrderBy(x => x.ShowOrder).ToListAsync(); - var trialCriterion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inDto.TrialReadingCriterionId).FirstOrDefaultAsync(); + var trialCriterion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inDto.TrialReadingCriterionId).FirstNotNullAsync(); result.ReadingInfoSignTime = trialCriterion.ReadingInfoSignTime; result.DigitPlaces = trialCriterion.DigitPlaces; @@ -662,7 +661,7 @@ namespace IRaCIS.Core.Application } } - if (showOrderList.Count() != showOrderList.Select(t => t.ShowOrder).Distinct().Count()) + if (showOrderList.Count != showOrderList.Select(t => t.ShowOrder).Distinct().Count()) { //---影像质控审核问题显示序号不能重复。 throw new BusinessValidationFailedException(_localizer["TrialConfig_DuplicateAuditQuestionId"]); @@ -732,7 +731,7 @@ namespace IRaCIS.Core.Application } } - if (showOrderList.Count() != showOrderList.Select(t => t.ShowOrder).Distinct().Count()) + if (showOrderList.Count != showOrderList.Select(t => t.ShowOrder).Distinct().Count()) { //---影像质控审核问题显示序号不能重复。 throw new BusinessValidationFailedException(_localizer["TrialConfig_DuplicateAuditQuestionId"]); diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialService.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialService.cs index 62849f626..c46592ff5 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialService.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialService.cs @@ -306,11 +306,15 @@ namespace IRaCIS.Application.Services await _repository.BatchDeleteAsync(o => o.ClinicalForm.TrialId == trialId); await _repository.BatchDeleteAsync(o => o.TrialId == trialId); - await _repository.BatchDeleteAsync(o => o.TrialId == trialId); + await _repository.BatchDeleteAsync(o => o.TrialReadingCriterion.TrialId == trialId); await _repository.BatchDeleteAsync(o => o.TrialReadingCriterion.TrialId == trialId); + await _repository.BatchDeleteAsync(o => o.SubjectVisit.TrialId == trialId); + await _repository.BatchDeleteAsync(o => o.TrialId == trialId); + await _repository.BatchDeleteAsync(o => o.TrialId == trialId); + await _repository.BatchDeleteAsync(o => o.TrialReadingCriterion.TrialId == trialId); await _repository.BatchDeleteAsync(o => o.TrialId == trialId); await _repository.BatchDeleteAsync(t => t.TrialId == trialId); await _repository.BatchDeleteAsync(t => t.TrialId == trialId); diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialSiteService.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialSiteService.cs index e3dc9b5c9..2054c1e6e 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialSiteService.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialSiteService.cs @@ -194,10 +194,10 @@ namespace IRaCIS.Core.Application.Services var siteQueryable = _siteRepository.AsQueryable(true) - .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) || t.AliasName.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)) + .WhereIf(!string.IsNullOrWhiteSpace(searchModel.City), t => t.City.Contains(searchModel.City)) + .WhereIf(!string.IsNullOrWhiteSpace(searchModel.Country), t => t.Country.Contains(searchModel.Country)) .ProjectTo(_mapper.ConfigurationProvider, new { trialId = searchModel.TrialId , isEn_Us =_userInfo.IsEn_Us}); @@ -323,7 +323,7 @@ namespace IRaCIS.Core.Application.Services { //CRC只看到他负责的 - var list = await _trialSiteRepository.Where(t => t.TrialId == trialId) + var list = await _trialSiteRepository.Where(t => t.TrialId == trialId).IgnoreQueryFilters() .WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA, t => t.CRCUserList.Any(t => t.UserId == _userInfo.Id)) .ProjectTo(_mapper.ConfigurationProvider).OrderBy(t => t.TrialSiteCode).ToListAsync(); @@ -348,7 +348,6 @@ namespace IRaCIS.Core.Application.Services /// 删除 项目 下某一site [HttpDelete("{id:guid}/{trialId:guid}")] - [TrialAudit(AuditType.TrialAudit, AuditOptType.DeleteTrialSite)] [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] [Obsolete] public async Task DeleteTrialSite(Guid id) diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/_MapConfig.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/_MapConfig.cs index c8fde011f..6952678f0 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/_MapConfig.cs @@ -108,7 +108,7 @@ namespace IRaCIS.Core.Application.Service .ForMember(d => d.IsSelect, u => u.MapFrom(t => t.UserTrials.Any(t => t.TrialId == trialId))); CreateMap() - .ForMember(d => d.HospitalName, u => u.MapFrom(s => s.Hospital.HospitalName)); + .ForMember(d => d.HospitalName, u => u.MapFrom(s => isEn_Us? s.Hospital.HospitalName:s.Hospital.HospitalNameCN)); //trial site 选择列表 subjectVisit pannel 模式添加的时候 diff --git a/IRaCIS.Core.Application/Service/Visit/SubjectService.cs b/IRaCIS.Core.Application/Service/Visit/SubjectService.cs index aa51292bb..cacda9104 100644 --- a/IRaCIS.Core.Application/Service/Visit/SubjectService.cs +++ b/IRaCIS.Core.Application/Service/Visit/SubjectService.cs @@ -26,7 +26,6 @@ namespace IRaCIS.Application.Services /// state:1-访视中,2-出组。0-全部 /// - [TrialAudit(AuditType.SubjectAudit, AuditOptType.AddOrUpdateSubject)] [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] //[Authorize(Policy = IRaCISPolicy.PM_APM_CRC_QC)] public async Task> AddOrUpdateSubject([FromBody] SubjectCommand subjectCommand) diff --git a/IRaCIS.Core.Application/Service/Visit/SubjectVisitService.cs b/IRaCIS.Core.Application/Service/Visit/SubjectVisitService.cs index f1702dd28..8a3a2ecdb 100644 --- a/IRaCIS.Core.Application/Service/Visit/SubjectVisitService.cs +++ b/IRaCIS.Core.Application/Service/Visit/SubjectVisitService.cs @@ -295,7 +295,7 @@ namespace IRaCIS.Core.Application.Services ); //设置为阅片与否 不更改数据库检查 的instance数量 和 SeriesCount 所以这里要实时统计 - t.SeriesCount = t.SeriesList.Count(); + t.SeriesCount = t.SeriesList.Count; t.InstanceCount = t.SeriesList.SelectMany(t => t.InstanceList).Count(); } @@ -330,8 +330,8 @@ namespace IRaCIS.Core.Application.Services var tag = await _readingCustomTagRepository.Where(x => x.VisitTaskId == indto.VisitTaskId && x.StudyId != null).Select(x => new { - ShowOrder= 0, - RowIndex= 0m, + ShowOrder = 0, + RowIndex = 0m, x.SeriesId, x.StudyId, x.InstanceId, @@ -370,7 +370,7 @@ namespace IRaCIS.Core.Application.Services { item.SeriesInstanceUid = string.Empty; - item.InstanceList = thisRowinfo.Where(y => y.InstanceId != null).OrderBy(x => x.ShowOrder).ThenBy(x => x.RowIndex).Select(y => y.InstanceId.Value).Distinct().ToList(); + item.InstanceList = thisRowinfo.Where(y => y.InstanceId != null).OrderBy(x => x.ShowOrder).ThenBy(x => x.RowIndex).Select(y => y.InstanceId!.Value).Distinct().ToList(); var tempInstanceList = await _repository.Where(t => item.InstanceList.Contains(t.Id)).OrderBy(t => t.InstanceNumber) .Select(t => new TempInstance @@ -417,7 +417,7 @@ namespace IRaCIS.Core.Application.Services }) .ToList(); - item.InstanceCount = item.InstanceList.Count(); + item.InstanceCount = item.InstanceList.Count; item.Description = "Key Series"; @@ -425,7 +425,7 @@ namespace IRaCIS.Core.Application.Services ThenBy(s => s.SeriesTime).Select(x => x.Modality).Distinct().ToListAsync(); ; item.Modality = string.Join(",", modalityList); thisVisitTaskStudy.SeriesList.Add(item); - thisVisitTaskStudy.SeriesCount = thisVisitTaskStudy.SeriesList.Count(); + thisVisitTaskStudy.SeriesCount = thisVisitTaskStudy.SeriesList.Count; @@ -447,23 +447,23 @@ namespace IRaCIS.Core.Application.Services var studyList = await _repository.Where(t => t.TrialId == indto.TrialId && t.SubjectVisitId == indto.SujectVisitId) .Select(k => new VisitStudyDTO() - { - InstanceCount = k.InstanceCount, - Modalities = k.Modalities, - SeriesCount = k.SeriesCount, - StudyCode = k.StudyCode, - StudyId = k.Id, + { + InstanceCount = k.InstanceCount, + Modalities = k.Modalities, + SeriesCount = k.SeriesCount, + StudyCode = k.StudyCode, + StudyId = k.Id, - }).ToListAsync(); + }).ToListAsync(); var studyIds = studyList.Select(t => t.StudyId).ToList(); var instanceList = await _repository.Where(t => studyIds.Contains(t.StudyId)) - .Select(t => new { t.SeriesId, t.Id, t.InstanceNumber, t.Path, t.NumberOfFrames,t.WindowCenter,t.WindowWidth }).ToListAsync(); + .Select(t => new { t.SeriesId, t.Id, t.InstanceNumber, t.Path, t.NumberOfFrames, t.WindowCenter, t.WindowWidth }).ToListAsync(); List seriesLists = await _repository.Where(s => studyIds.Contains(s.StudyId) /*&& s.IsReading*/) - .WhereIf(isManualGenerate==false, t => t.IsReading) + .WhereIf(isManualGenerate == false, t => t.IsReading) .OrderBy(s => s.SeriesNumber). ThenBy(s => s.SeriesTime) .ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); @@ -502,12 +502,12 @@ namespace IRaCIS.Core.Application.Services }) .ToList(); - series.WindowWidth = instanceList.FirstOrDefault()?.WindowWidth; - series.WindowCenter = instanceList.FirstOrDefault()?.WindowCenter; + series.WindowWidth = instanceList.FirstOrDefault()!.WindowWidth; + series.WindowCenter = instanceList.FirstOrDefault()!.WindowCenter; }); //设置为阅片与否 不更改数据库检查 的instance数量 和 SeriesCount 所以这里要实时统计 - t.SeriesCount = t.SeriesList.Count(); + t.SeriesCount = t.SeriesList.Count; t.InstanceCount = t.SeriesList.SelectMany(t => t.InstanceList).Count(); } @@ -530,24 +530,36 @@ namespace IRaCIS.Core.Application.Services foreach (var item in noDicomStudyList) { - var nodicom = noDicomList.Where(x => x.Id == item.StudyId).FirstOrDefault(); - item.SeriesList = new List() - { - new DicomSeriesDTO (){ - IsDicom=false, - Id=item.StudyId, - InstanceCount=await _noneDicomStudyFileRepository.Where(x=>x.NoneDicomStudyId==item.StudyId).CountAsync(), - Modality=item.Modalities, - StudyId=item.StudyId, - TrialId=nodicom.TrialId, - SiteId=nodicom.SiteId, - SubjectVisitId=nodicom.SubjectVisitId, - SubjectId=nodicom.SubjectId, - SeriesNumber=1, - NoneDicomFileFirstFile=await _noneDicomStudyFileRepository.Where(x=>x.NoneDicomStudyId==item.StudyId).Select(x=>x.Path).FirstOrDefaultAsync(), - } + var nodicom = noDicomList.Where(x => x.Id == item.StudyId).First(); - }; + var instanceCount = await _noneDicomStudyFileRepository.Where(x => x.NoneDicomStudyId == item.StudyId).CountAsync(); + + if (instanceCount == 0) + { + item.SeriesList = new List(); + item.SeriesCount = 0; + } + else + { + item.SeriesList = new List() + { + new DicomSeriesDTO (){ + IsDicom=false, + Id=item.StudyId, + InstanceCount=instanceCount, + Modality=item.Modalities, + StudyId=item.StudyId, + TrialId=nodicom.TrialId, + SiteId=nodicom.SiteId, + SubjectVisitId=nodicom.SubjectVisitId, + SubjectId=nodicom.SubjectId, + SeriesNumber=1, + NoneDicomFileFirstFile=await _noneDicomStudyFileRepository.Where(x=>x.NoneDicomStudyId==item.StudyId).Select(x=>x.Path).FirstOrDefaultAsync(), + } + + }; + } + } diff --git a/IRaCIS.Core.Application/Service/Visit/_MapConfig.cs b/IRaCIS.Core.Application/Service/Visit/_MapConfig.cs index 48c3005ac..92c369979 100644 --- a/IRaCIS.Core.Application/Service/Visit/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/Visit/_MapConfig.cs @@ -35,7 +35,7 @@ namespace IRaCIS.Core.Application.Service CreateMap(); CreateMap() - .ForMember(d => d.SiteName, u => u.MapFrom(s => s.TrialSite.Site.SiteName)) + .ForMember(d => d.SiteName, u => u.MapFrom(s => s.TrialSite.TrialSiteAliasName)) .ForMember(d => d.TrialSiteCode, u => u.MapFrom(s => s.TrialSite.TrialSiteCode)) .ForMember(d => d.LatestBlindName, u => u.MapFrom(s => s.LatestSubjectVisit.BlindName)) .ForMember(d => d.LatestVisitName, u => u.MapFrom(s => s.LatestSubjectVisit.VisitName)) @@ -88,8 +88,7 @@ namespace IRaCIS.Core.Application.Service CreateMap().IncludeMembers(t=>t.Trial) - .ForMember(d => d.SiteName, u => u.MapFrom(s => s.Site.SiteName)) - .ForMember(d => d.SiteCode, u => u.MapFrom(s => s.Site.SiteCode)) + .ForMember(d => d.TrialSiteAliasName, u => u.MapFrom(s => s.TrialSite.TrialSiteAliasName)) .ForMember(d => d.SubjectVisitId, u => u.MapFrom(s => s.Id)) .ForMember(d => d.TrialSiteCode, u => u.MapFrom(s => s.TrialSite.TrialSiteCode)) .ForMember(d => d.TrialCode, u => u.MapFrom(s => s.Trial.TrialCode)) diff --git a/IRaCIS.Core.Application/TestService.cs b/IRaCIS.Core.Application/TestService.cs index 6de525061..ffd97ded6 100644 --- a/IRaCIS.Core.Application/TestService.cs +++ b/IRaCIS.Core.Application/TestService.cs @@ -1,4 +1,6 @@ -using DocumentFormat.OpenXml.Office2010.Excel; +using Aliyun.OSS; +using Castle.DynamicProxy.Generators.Emitters.SimpleAST; +using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.Service; using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Domain.Share; @@ -12,8 +14,15 @@ using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using MiniExcelLibs; +using Minio; +using Minio.DataModel.Args; +using NPOI.HPSF; +using NPOI.POIFS.Crypt; +using SharpCompress.Common; +using Spire.Doc; using System.Linq.Expressions; using System.Reflection.Metadata; +using System.Security.AccessControl; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; @@ -25,7 +34,7 @@ namespace IRaCIS.Application.Services public class TestService : BaseService { - public static int IntValue = 100; + public static int IntValue = 100; private readonly IRepository _dicRepository; private readonly IRepository _trialRepository; @@ -40,7 +49,7 @@ namespace IRaCIS.Application.Services private readonly ILogger _logger; - public TestService(IRepository dicRepository, IRepository trialRepository,ILogger logger + public TestService(IRepository dicRepository, IRepository trialRepository, ILogger logger , IOptionsMonitor systemEmailConfig, IOptionsMonitor basicConfig, IRepository visitTaskRepository, IDistributedLockProvider distributedLockProvider) { @@ -52,31 +61,56 @@ namespace IRaCIS.Application.Services _dicRepository = dicRepository; _trialRepository = trialRepository; - _distributedLockProvider= distributedLockProvider; + _distributedLockProvider = distributedLockProvider; - _logger= logger; + _logger = logger; //_cache = cache; } - [AllowAnonymous] - public async Task TestDistributedLock( ) + public async Task TestEFcore8() { - _repository.Where().Select(t => t.FullName).FirstOrDefault(); + + //var aa= _dicRepository._dbContext.Subject.Where(t => t.Id == Guid.Empty).ExecuteUpdate("FirstName","ddd"); + + await _repository.BatchUpdateAsync(t => t.Id == Guid.Empty, u => new Subject() { FirstName = "fddd", LastName = "sss", UpdateTime = DateTime.Now }); + + await _repository.Where().ExecuteUpdateAsync(t => t.SetProperty(t => t.UpdateTime, u => DateTime.Now)); + + return ResponseOutput.Ok(); + } + // 设置 Ne + + [AllowAnonymous] + public async Task TestMinIO([FromServices] IOSSService oSSService) + { + + await oSSService.UploadToOSSAsync("C:\\Users\\Administrator\\Desktop\\TrialSiteUserImportTemplate.xlsx", "myfolder"); + + await oSSService.DownLoadFromOSSAsync("/myfolder/TrialSiteUserImportTemplate.xlsx", "C:\\Users\\Administrator\\Desktop\\aws.xlsx"); + + return ResponseOutput.Ok(); + } + + [AllowAnonymous] + public async Task TestDistributedLock() + { + + await _repository.Where().Select(t => t.FullName).FirstNotNullAsync(); Console.WriteLine($"我进来了当前值是:" + IntValue); _logger.LogWarning($"我进来了当前值是:" + IntValue); var @lock = _distributedLockProvider.CreateLock($"UserAccount"); - using (await @lock.AcquireAsync()) + using (await @lock.AcquireAsync()) { await Task.Delay(4); IntValue--; - _logger.LogWarning( IntValue.ToString()); + _logger.LogWarning(IntValue.ToString()); Console.WriteLine(IntValue); } @@ -85,86 +119,126 @@ namespace IRaCIS.Application.Services [AllowAnonymous] - public async Task GetMemoryStoreData() + public async Task InternationazitionInit() { - + var rows = await MiniExcel.QueryAsync(@"C:\Users\Administrator\Desktop\i18n-new2.xlsx"); - return ResponseOutput.Ok(new { StaticData.En_US_Dic , StaticData.Zh_CN_Dic }); + rows = rows.Where(t => !string.IsNullOrEmpty(t.Code)).ToList(); + + foreach (var row in rows) + { + await _repository.InsertOrUpdateAsync(row); + + } + + await _repository.SaveChangesAsync(); + + return ResponseOutput.Ok(); } - - //[AllowAnonymous] - //public async Task InternationazitionInit() - //{ - - - // var rows = await MiniExcel.QueryAsync(@"C:\Users\Administrator\Desktop\Export\vue.xlsx"); - - // foreach (var row in rows) - // { - // await _repository.InsertOrUpdateAsync(row); - - // } - - // await _repository.SaveChangesAsync(); - - // return ResponseOutput.Ok(); - //} - [AllowAnonymous] [UnitOfWork] public async Task Get() { - - return "修改服务器时间自动发布测试--我又修改了"; + + //Expression> visitTaskLambda = x => x.TrialId == Guid.Empty && x.SubjectId == Guid.Empty && x.TrialReadingCriterionId == Guid.Empty; + + //var visitTaskIdQueryable = _visitTaskRepositoryy.Where(visitTaskLambda).Where(t => t.Subject.SubjectVisitTaskList.AsQueryable().Where(visitTaskLambda).Any(c => c.IsNeedClinicalDataSign == true && c.IsClinicalDataSign == false && c.VisitTaskNum < t.VisitTaskNum)).Select(t => t.Id); + + //await _visitTaskRepositoryy.BatchUpdateNoTrackingAsync(t => visitTaskIdQueryable.Contains(t.Id), u => new VisitTask() + //{ + // IsFrontTaskNeedSignButNotSign = true + //}); + + + //var a = ((Decimal)1.00).ToString().TrimEnd(new char[] { '.', '0' }); + //var b = ((Decimal)1.01).ToString().TrimEnd(new char[] { '.', '0' }); + //var c = ((Decimal)100).ToString().TrimEnd(new char[] { '.', '0' }); + //var subject1 = Guid.Parse("431D0C58-ABC5-4166-B9BC-08DA0E391693"); + //var subject2 = Guid.Parse("431D0C58-ABC5-4166-B9BC-08DA0E391694"); + + // var subjectList = new List() { Guid.Parse("431D0C58-ABC5-4166-B9BC-08DA0E391693") , + // Guid.Parse("431D0C58-ABC5-4166-B9BC-08DA0E391694") , + // Guid.Parse("431D0C58-ABC5-4166-B9BC-08DA0E391695") + // }; + + //string[] citys = new string[] { "广州", "深圳", "上海", "北京" }; + //foreach (var item in subjectList) + //{ + // Console.WriteLine(await BNRFactory.Default.Create($"[CN:{item}][N:[CN:{item}]/0000000]")); + //} + //foreach (var item in subjectList) + //{ + // Console.WriteLine(await BNRFactory.Default.Create($"[N:[CN:{item}]/0000000]")); + //} + + //foreach (var item in subjectList) + //{ + // Console.WriteLine(await BNRFactory.Default.Create($"[CN:{item}][redis:city/0000000]")); + //} + + //var needAddVisitList = await _repository.Where(t => t.TrialId == Guid.Empty).DistinctBy(t => t.VisitTaskNum).ToListAsync(); + + + //await _repository.BatchUpdateAsync(t => t.Id == Guid.Empty, u => new VisitTask() + //{ + // SuggesteFinishedTime = u.IsUrgent ? DateTime.Now.AddDays(2) : DateTime.Now.AddDays(7), + + // Code = u.Code + 1 + //}); + + //var query = from item1 in _repository.Where() + // join item2 in _repository.Where() on item1.ValueType equals item2.ValueType + // select new + // { + // item1.ValueType, + // dd = item2.ValueType + // }; + + //var list2 = query.ToList(); + + //await Task.CompletedTask; + + //var list = await _repository.Where(t => t.TrialId == Guid.Parse("40400000-3e2c-0016-239b-08da581f0e74")).ToListAsync(); + + ////await _repository.BatchDeleteAsync(t => t.TrialId == Guid.Parse("40400000-3e2c-0016-239b-08da581f0e74")); + + //await _repository.AddRangeAsync(list, true); + + //await _repository.SaveChangesAsync(); + + //await _repository.BatchUpdateAsync(t => t.TrialId == Guid.Parse("40400000-3e2c-0016-239b-08da581f0e74") && t.EntityName== "ClinicalDataTrialSet", t => new DataInspection() { CreateTime= DateTime.Now.AddMonths(-2) } ); + + //await _visitTaskRepositoryy.UpdatePartialFromQueryAsync( Guid.Parse("78360000-3E2C-0016-9B53-08DA6A002040"), c => new VisitTask() { UpdateTime = DateTime.Now }); + + //await _visitTaskRepositoryy.UpdatePartialFromQueryAsync( Guid.Parse("78360000-3E2C-0016-9B53-08DA6A002040"), c => new VisitTask() { UpdateTime = DateTime.Now.AddMinutes(1) }); + + //var a = _userInfo.IsTestUser; + + //var list1 = await _repository.Where().Select(t => t.TranslateValue(t.Value, t.ValueCN, true)).ToListAsync(); + //var list2 = await _repository.Where().Select(t => t.TranslateValue(t.Value, t.ValueCN, false)).ToListAsync(); + + return "测试自动发布--再次提交"; } - private static Dictionary _replacePatterns = new Dictionary() - { - { "test", "Atlanta Knight" }, - { "GAME_TIME", "7:30pm" }, - { "GAME_NUMBER", "161" }, - { "DATE", "October 18 2018" }, - }; - - private static string ReplaceFunc(string findStr) - { - if (_replacePatterns.ContainsKey(findStr)) - { - return _replacePatterns[findStr]; - } - return findStr; - } - - [AllowAnonymous] - public async Task> testwwwww([FromServices] IWebHostEnvironment env) + public async Task testwwwww([FromServices] IWebHostEnvironment env) { - int count = 200; - - var list=new List(); - - for (int i = 0; i < count; i++) - { - Guid guid = NewId.NextGuid(); - list.Add(guid); - } - - return list; + await Task.CompletedTask; } [AllowAnonymous] public async Task GetEnvironmentName([FromServices] IWebHostEnvironment env) { - var a = IdentifierHelper.CreateGuid("1.2.840.113619.2.416.3358551739363725609857319676326094825431.2.840.113619.2.80.2338912612.50499.1563432834.1.4.11.2.840.113619.2.80.2338912612.50499.1563432835.4b8340000-3e2c-0016-fbdd-08db883b137f"); + var a = IdentifierHelper.CreateGuid("123456"); + var k = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes("123456")); - var c = MD5Helper.Md5("1.2.840.113619.2.416.3358551739363725609857319676326094825431.2.840.113619.2.80.2338912612.50499.1563432834.1.4.11.2.840.113619.2.80.2338912612.50499.1563432835.4b8340000-3e2c-0016-fbdd-08db883b137f"); - + var c = MD5Helper.Md5("123456"); //update DicomInstance set Path = '/IRaCISData/TrialData/' + cast(DicomInstance.TrialId as varchar) + '/' + DicomInstance.SiteId + '/' + DicomInstance.SubjectId + '/' + DicomInstance.SubjectVisitId + '/Dicom/' + DicomInstance.StudyId + '/' + DicomInstance.Id + '.dcm' @@ -255,11 +329,7 @@ namespace IRaCIS.Application.Services - public string PostData(TestModel testModelList) - { - return String.Empty; - } - + #region 历史维护 /// /// 维护临床数据 --一定要在同步表前同步数据才行 /// @@ -299,6 +369,89 @@ namespace IRaCIS.Application.Services } + /// + /// 维护OSS 影像数据 + /// + /// + [AllowAnonymous] + [UnitOfWork] + public async Task OldLocalImageResizeJpg([FromServices] IOSSService oSSService, [FromServices] IRepository _repository, [FromServices] IWebHostEnvironment _hostEnvironment) + { + + var aliConfig = oSSService.ObjectStoreServiceOptions.AliyunOSS; + var _ossClient = new OssClient(aliConfig.endPoint, aliConfig.accessKeyId, aliConfig.accessKeySecret); + + var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment); + + var studyList = _repository.Where(t => t.SeriesList.Any(t => t.ImageResizePath.Length < 10)).Select(t => new { t.TrialId, t.SiteId, t.SubjectId, t.SubjectVisitId, t.Id }).ToList(); + + foreach (var studyitem in studyList) + { + + var relativePath = $"{studyitem.TrialId}/{studyitem.SiteId}/{studyitem.SubjectId}/{studyitem.SubjectVisitId}/{StaticData.Folder.DicomFolder}/{studyitem.Id}/"; + + try + { + string nextMarker = null; + do + { + // 使用 prefix 模拟目录结构,设置 MaxKeys 和 NextMarker + var objectListing = _ossClient.ListObjects(new ListObjectsRequest(aliConfig.bucketName) + { + Prefix = relativePath, + MaxKeys = 1000, + Marker = nextMarker + }); + + var jpgInfoList = objectListing.ObjectSummaries + .Where(summary => summary.Key.EndsWith(".jpg")) + .Select(summary => + { + string fileName = summary.Key.Split('/').Last(); // 提取文件夹名 + return new + { + + Key = summary.Key, + InstanceId = Guid.TryParse( + fileName.Split('.')[0], + out Guid instanceId) + ? instanceId + : Guid.Empty + }; + }) + .Where(info => info.InstanceId != Guid.Empty) + .ToList(); + + foreach (var jpg in jpgInfoList) + { + var seriesId = _repository.Where(t => t.Id == jpg.InstanceId).Select(t => t.SeriesId).FirstOrDefault(); + + await _repository.BatchUpdateAsync(t => t.Id == seriesId, t => new DicomSeries() { ImageResizePath = "/" + jpg.Key }); + } + + // 设置 NextMarker 以获取下一页的数据 + nextMarker = objectListing.NextMarker; + + } while (!string.IsNullOrEmpty(nextMarker)); + } + catch (Exception ex) + { + Console.WriteLine($"Error: {ex.Message}"); + } + + await _repository.SaveChangesAsync(); + } + + + + return ResponseOutput.Ok(); + } + + + #endregion + + + } public class TestModel diff --git a/IRaCIS.Core.Application/Triggers/AddlTrialUserTrigger.cs b/IRaCIS.Core.Application/Triggers/AddlTrialUserTrigger.cs index b89ffbf42..6f5082e6e 100644 --- a/IRaCIS.Core.Application/Triggers/AddlTrialUserTrigger.cs +++ b/IRaCIS.Core.Application/Triggers/AddlTrialUserTrigger.cs @@ -1,6 +1,7 @@ using EntityFrameworkCore.Triggered; using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Infrastructure; +using Microsoft.Extensions.Localization; using System; using System.Collections.Generic; using System.Linq; @@ -11,18 +12,19 @@ namespace IRaCIS.Core.Application.Triggers { // 统一处理 外部用户、中心调研(先添加 再发送邮件)、参与医生加入到项目 ----废弃 - public class AddlTrialUserTrigger :BaseService, IBeforeSaveTrigger + public class AddlTrialUserTrigger :IBeforeSaveTrigger { + public IStringLocalizer _localizer; private readonly IRepository _trialRepository; private readonly IRepository _userRepository; - public AddlTrialUserTrigger(IRepository trialRepository, IRepository userRepository) + public AddlTrialUserTrigger(IRepository trialRepository, IRepository userRepository, IStringLocalizer localizer) { _trialRepository = trialRepository; _userRepository = userRepository; - + _localizer = localizer; } public async Task BeforeSave(ITriggerContext context, CancellationToken cancellationToken) { diff --git a/IRaCIS.Core.Application/Triggers/SubjectStateTrigger.cs b/IRaCIS.Core.Application/Triggers/SubjectStateTrigger.cs index a6e41756f..884a0e8ec 100644 --- a/IRaCIS.Core.Application/Triggers/SubjectStateTrigger.cs +++ b/IRaCIS.Core.Application/Triggers/SubjectStateTrigger.cs @@ -1,25 +1,27 @@ using AutoMapper; using EntityFrameworkCore.Triggered; using IRaCIS.Core.Domain.Share; +using IRaCIS.Core.Infra.EFCore; using IRaCIS.Core.Infrastructure; using MassTransit; +using Microsoft.Extensions.Localization; namespace IRaCIS.Core.Application.Triggers { /// /// /// - public class SubjectStateTrigger :BaseService, IAfterSaveTrigger + public class SubjectStateTrigger : IAfterSaveTrigger { - private readonly IRepository _subjectVisitRepository; + public IStringLocalizer _localizer; private readonly IRepository _repository; - private readonly IMapper _mapper; + private readonly IRepository _subjectVisitRepository; - public SubjectStateTrigger(IRepository subjectVisitRepository, IRepository repository, IMapper mapper) + public SubjectStateTrigger(IRepository subjectVisitRepository, IStringLocalizer localizer, IRepository repository) { - _subjectVisitRepository = subjectVisitRepository; _repository = repository; - _mapper = mapper; + _localizer = localizer; + _subjectVisitRepository = subjectVisitRepository; } public async Task AfterSave(ITriggerContext context, CancellationToken cancellationToken) diff --git a/IRaCIS.Core.Application/Triggers/SubjectVisitFinalVisitTrigger.cs b/IRaCIS.Core.Application/Triggers/SubjectVisitFinalVisitTrigger.cs index 7483c9b7b..791e17704 100644 --- a/IRaCIS.Core.Application/Triggers/SubjectVisitFinalVisitTrigger.cs +++ b/IRaCIS.Core.Application/Triggers/SubjectVisitFinalVisitTrigger.cs @@ -2,15 +2,17 @@ using IRaCIS.Core.Application.Service; using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Domain.Share; +using IRaCIS.Core.Infra.EFCore; using IRaCIS.Core.Infrastructure; using MassTransit; +using Microsoft.Extensions.Localization; namespace IRaCIS.Core.Application.Triggers { /// /// 处理 访视 末次评估 会影响Subject 状态 /// - public class SubjectVisitFinalVisitTrigger :BaseService, IAfterSaveTrigger + public class SubjectVisitFinalVisitTrigger :IAfterSaveTrigger { private readonly IRepository _subjectVisitRepository; private readonly IRepository _readingPeriodSetRepository; @@ -19,8 +21,8 @@ namespace IRaCIS.Core.Application.Triggers private readonly IRepository _subjectRepository; private readonly IRepository _visitTaskRepository; private readonly IVisitTaskHelpeService _ivisitTaskHelpeService; + public IStringLocalizer _localizer; private readonly IRepository _repository; - public SubjectVisitFinalVisitTrigger(IRepository subjectVisitRepository, IRepository readingPeriodSetRepository, @@ -28,7 +30,9 @@ namespace IRaCIS.Core.Application.Triggers IRepository visitTaskRepository, IVisitTaskHelpeService visitTaskHelpeService, IRepository readModuleRepository, - IRepository subjectRepository, IRepository repository) + IRepository subjectRepository, + IStringLocalizer localizer, + IRepository repository) { _subjectVisitRepository = subjectVisitRepository; this._readingPeriodSetRepository = readingPeriodSetRepository; @@ -38,6 +42,7 @@ namespace IRaCIS.Core.Application.Triggers this._readModuleRepository = readModuleRepository; _subjectRepository = subjectRepository; _repository = repository; + _localizer = localizer; } public async Task AfterSave(ITriggerContext context, CancellationToken cancellationToken) diff --git a/IRaCIS.Core.Application/Triggers/VisitTaskIsFrontTaskNeedSignButNotSignTrigger.cs b/IRaCIS.Core.Application/Triggers/VisitTaskIsFrontTaskNeedSignButNotSignTrigger.cs index f72acc924..034dd3c69 100644 --- a/IRaCIS.Core.Application/Triggers/VisitTaskIsFrontTaskNeedSignButNotSignTrigger.cs +++ b/IRaCIS.Core.Application/Triggers/VisitTaskIsFrontTaskNeedSignButNotSignTrigger.cs @@ -22,13 +22,13 @@ namespace IRaCIS.Core.Application.Triggers private readonly IRepository _readingTaskQuestionAnswerRepository; - + private readonly IRepository _readingJudgeInfoRepository; public VisitTaskIsFrontTaskNeedSignButNotSignTrigger( IRepository visitTaskRepository, IRepository trialReadingCriterionRepository, IRepository trialReadingQuestionRepository - , IRepository readingTaskQuestionAnswerRepository) + , IRepository readingTaskQuestionAnswerRepository, IRepository readingJudgeInfoRepository) { _trialReadingCriterionRepository = trialReadingCriterionRepository; @@ -36,6 +36,7 @@ namespace IRaCIS.Core.Application.Triggers _trialReadingQuestionRepository = trialReadingQuestionRepository; _readingTaskQuestionAnswerRepository = readingTaskQuestionAnswerRepository; + _readingJudgeInfoRepository = readingJudgeInfoRepository; } @@ -48,7 +49,7 @@ namespace IRaCIS.Core.Application.Triggers Expression> visitTaskLambda = x => x.TrialId == visitTask.TrialId && x.SubjectId == visitTask.SubjectId && x.TrialReadingCriterionId == visitTask.TrialReadingCriterionId; if (context.ChangeType == ChangeType.Added) { - + //判断是否需要临床数据签名 不需要 就不用维护 if (visitTask.IsNeedClinicalDataSign) { @@ -93,12 +94,125 @@ namespace IRaCIS.Core.Application.Triggers }); } - + } } + else if (context.ChangeType == ChangeType.Modified) + { + if (visitTask.ReadingCategory == ReadingCategory.Judge && (visitTask.TaskState == TaskState.Adbandon || visitTask.TaskState == TaskState.HaveReturned)) + { + var find = _readingJudgeInfoRepository.Where(t => t.JudgeTaskId == visitTask.Id).FirstOrDefault(); + if (find != null) + { + var ids = new Guid[] { find.TaskIdOne, find.TaskIdTwo }; + await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => ids.Contains(t.Id), u => new VisitTask() { JudgeVisitTaskId = null }); + } + } + } + #region 附加评估 暂时废弃 + // //从未签名状态 改为签名状态时 判断是否进行了附加评估,将附加评估的结果冗余 + // if (context.ChangeType == ChangeType.Modified && visitTask.ReadingTaskState == ReadingTaskState.HaveSigned && context.UnmodifiedEntity.ReadingTaskState != ReadingTaskState.HaveSigned) + // { + + // var criterion = _trialReadingCriterionRepository.Where(t => t.Id == visitTask.TrialReadingCriterionId).FirstOrDefault(); + + // //如果是附加评估 + // if (criterion.IsAdditionalAssessment) + // { + + + // if (visitTask.ReadingCategory == ReadingCategory.Visit) + // { + + + // switch (criterion.CriterionType) + // { + // case CriterionType.RECIST1Point1: + // var isbaseLine = _visitTaskRepository.Where(t => t.Id == visitTask.Id).Select(t => t.SourceSubjectVisit.IsBaseLine).FirstOrDefault(); + + + + // if (isbaseLine) + // { + // var currentTaskAdditionarlAnswer = await _readingTaskQuestionAnswerRepository.Where(t => t.VisitTaskId == visitTask.Id && + // t.ReadingQuestionTrial.IsAdditional == true && t.ReadingQuestionTrial.Type != "group" + // ).Include(t => t.ReadingQuestionTrial).FirstOrDefaultAsync(); + + + // //双重阅片完成了 + // if (criterion.ReadingType == ReadingMethod.Double && + //(_visitTaskRepository.Where(t => t.SubjectId == visitTask.SubjectId && t.TaskName == visitTask.TaskName && t.TaskState == TaskState.Effect && t.ReadingTaskState == ReadingTaskState.HaveSigned).Count() == 2) + // ) + // { + + // var otherTaskId = await _visitTaskRepository.Where(t => t.SubjectId == visitTask.SubjectId && t.TaskName == visitTask.TaskName && t.TaskState == TaskState.Effect && t.ReadingTaskState == ReadingTaskState.HaveSigned && t.Id != visitTask.Id) + // .Select(t => t.Id).FirstOrDefaultAsync(); + + + // var otherTaskAdditionarlAnswer = await _readingTaskQuestionAnswerRepository.Where(t => t.VisitTaskId == otherTaskId && + // t.ReadingQuestionTrial.IsAdditional == true && t.ReadingQuestionTrial.Type != "group" + // ).Include(t => t.ReadingQuestionTrial).FirstOrDefaultAsync(); + + + + // await _subjectAdditionalEvaluationResultRepository.AddAsync(new SubjectAdditionalEvaluationResult() + // { + // TrialReadingCriterionId = visitTask.TrialReadingCriterionId, + // IsFinalResult = true, + // SubjectId = visitTask.SubjectId, + // TrialReadingQuestionId = currentTaskAdditionarlAnswer.ReadingQuestionTrialId, + // FinalAnswer = currentTaskAdditionarlAnswer.Answer, + // FinalTranslateDictionaryCode = currentTaskAdditionarlAnswer.ReadingQuestionTrial.DictionaryCode, + + // }); + + // } + // if (criterion.ReadingType == ReadingMethod.Single) + // { + + // await _subjectAdditionalEvaluationResultRepository.AddAsync(new SubjectAdditionalEvaluationResult() + // { + // TrialReadingCriterionId = visitTask.TrialReadingCriterionId, + // IsFinalResult = true, + // SubjectId = visitTask.SubjectId, + // TrialReadingQuestionId = currentTaskAdditionarlAnswer.ReadingQuestionTrialId, + // FinalAnswer = currentTaskAdditionarlAnswer.Answer, + // FinalTranslateDictionaryCode = currentTaskAdditionarlAnswer.ReadingQuestionTrial.DictionaryCode, + + // }); + + // } + + + + // } + + // break; + // default: + // break; + // } + + + + + + // } + + + + + + + + + // } + // } + + + #endregion } diff --git a/IRaCIS.Core.Application/_MediatR/CommandAndQueries/ConsistencyVerificationRequest.cs b/IRaCIS.Core.Application/_MediatR/CommandAndQueries/ConsistencyVerificationRequest.cs index a0b97d911..06387c87c 100644 --- a/IRaCIS.Core.Application/_MediatR/CommandAndQueries/ConsistencyVerificationRequest.cs +++ b/IRaCIS.Core.Application/_MediatR/CommandAndQueries/ConsistencyVerificationRequest.cs @@ -92,10 +92,10 @@ namespace IRaCIS.Core.Application.MediatR.CommandAndQueries //[Required(ErrorMessage = "检查日期不能为空")] - [CanConvertToTime(ErrorMessage = "Does not conform to Stusy Date format")] + [CanConvertToTime(ErrorMessage = "Does not conform to Study Date format")] - [ImporterHeader(Name = "Stusy Date", AutoTrim = true)] - [ExcelColumnName("Stusy Date")] + [ImporterHeader(Name = "Study Date", AutoTrim = true)] + [ExcelColumnName("Study Date")] public string StudyDate { get; set; } = string.Empty; diff --git a/IRaCIS.Core.Application/_MediatR/Handlers/ConsistencyVerificationHandler.cs b/IRaCIS.Core.Application/_MediatR/Handlers/ConsistencyVerificationHandler.cs index 46b8e1861..5603cb53f 100644 --- a/IRaCIS.Core.Application/_MediatR/Handlers/ConsistencyVerificationHandler.cs +++ b/IRaCIS.Core.Application/_MediatR/Handlers/ConsistencyVerificationHandler.cs @@ -5,6 +5,7 @@ using Newtonsoft.Json; using MediatR; using System.Linq.Expressions; using System.Text; +using Microsoft.Extensions.Localization; namespace IRaCIS.Core.Application.MediatR.Handlers { @@ -17,6 +18,7 @@ namespace IRaCIS.Core.Application.MediatR.Handlers private readonly IRepository _trialSiteRepository; private readonly IMapper _mapper; private readonly IRepository _noneDicomStudyRepository; + public IStringLocalizer _localizer { get; set; } /// /// 构造函数注入 @@ -25,7 +27,7 @@ namespace IRaCIS.Core.Application.MediatR.Handlers public ConsistencyVerificationHandler(IRepository studyRepository, IUserInfo userInfo, IRepository subjectRepository, IRepository subjectVisitRepository, IRepository trialSiteRepository, IRepository noneDicomStudyRepository, - IMapper mapper) + IMapper mapper, IStringLocalizer localizer) { _noneDicomStudyRepository = noneDicomStudyRepository; _studyRepository = studyRepository; @@ -34,6 +36,7 @@ namespace IRaCIS.Core.Application.MediatR.Handlers _subjectVisitRepository = subjectVisitRepository; _trialSiteRepository = trialSiteRepository; _mapper = mapper; + _localizer = localizer; } async Task IRequestHandler.Handle(ConsistencyVerificationRequest request, CancellationToken cancellationToken) @@ -112,14 +115,18 @@ namespace IRaCIS.Core.Application.MediatR.Handlers StringBuilder dialogMsg = new StringBuilder(); - //---您好,根据本系统自动识别,该受试者当前访视在IRC系统中已提交的影像检查情况如下: - dialogMsg.Append(StaticData.International("ConsistencyVerification_Img")); + //---您好,根据本系统自动识别,该受试者当前访视在IRC系统中已提交的影像检查情况如下: + dialogMsg.Append($"
{_localizer["ConsistencyVerification_Img"]}
"); var num = 0; List paramInfoList = new List(); + foreach (var item in dbVisitStudyList) { num++; - dialogMsg.AppendLine($"
{num}.{item.StudyDate}{StaticData.International("ConsistencyVerification_Of")}{item.Modality}{StaticData.International("ConsistencyVerification_ImgC")}"); + + dialogMsg.AppendLine($"
{num}. {_localizer["ConsistencyVerification_ImgC", item.StudyDate, item.Modality]}
"); + + paramInfoList.Add(new ParamInfoDto() { Modality = item.Modality, @@ -127,7 +134,7 @@ namespace IRaCIS.Core.Application.MediatR.Handlers }); } - var subjectVisitId = dbVisitStudyList.FirstOrDefault().SubjectVisitId; + var subjectVisitId = dbVisitStudyList.First().SubjectVisitId; var dbSV = (await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId)).IfNullThrowException(); #region 更换核对的顺序 以Excel 数据为准 注释 @@ -176,18 +183,18 @@ namespace IRaCIS.Core.Application.MediatR.Handlers if (dbExceptExcel.Count() == 0 && excelExceptDB.Count() == 0) { dialogMsg.AppendLine($"
"); - //---核对EDC数据,完全一致, 审核通过 - dialogMsg.AppendLine(StaticData.International("ConsistencyVerification_EDCA")); + //---核对EDC数据,完全一致, 审核通过 + dialogMsg.AppendLine(_localizer["ConsistencyVerification_EDCA"]); // dialogMsg.AppendLine(@$"
说明:为高效解决/处理以上全部质疑问题,麻烦您准确核实实际影像检查情况。请注意影像日期与实际检查的日期可能会不一致,部分检查(如PET -CT)可能同时存在多种模态影像。准确核实后,请回复该访视正确的影像检查情况。"); dbSV.CheckState = CheckStateEnum.CVPassed; dbSV.CheckUserId = _userInfo.Id; dbSV.CheckPassedTime = DateTime.Now; - //---核对EDC数据,完全一致 - dbSV.CheckResult = StaticData.International("ConsistencyVerification_EDCB"); - //---自动核查通过 - dbSV.ManualPassReason = StaticData.International("ConsistencyVerification_Auto"); + //---核对EDC数据,完全一致 + dbSV.CheckResult = _localizer["ConsistencyVerification_EDCB"]; + //---自动核查通过 + dbSV.ManualPassReason = _localizer["ConsistencyVerification_Auto"]; //维护状态 dbSV.ReadingStatus = ReadingStatusEnum.TaskAllocate; @@ -205,34 +212,34 @@ namespace IRaCIS.Core.Application.MediatR.Handlers // ETC 和系统的有区别 else { - dialogMsg.AppendLine($"
"); - //存在问题如下: - dialogMsg.AppendLine($"
{StaticData.International("ConsistencyVerification_Prob")}"); + //"Problems are as follows: + dialogMsg.AppendLine($"
{_localizer["ConsistencyVerification_Prob"]}
"); num = 0; foreach (var item in dbExceptExcel) { num++; //影像检查(EDC 缺少) ConsistencyVerification_EdcL - dialogMsg.AppendLine($"
{num}.{item.StudyDate}{StaticData.International("ConsistencyVerification_Of")}{item.Modality}{StaticData.International("ConsistencyVerification_EdcL")} "); + dialogMsg.AppendLine($"
{num}. {_localizer["ConsistencyVerification_EdcL", item.StudyDate, item.Modality]}
"); + } foreach (var item in excelExceptDB) { num++; // 影像检查(IRC 缺少) - dialogMsg.AppendLine($"
{num}.{item.StudyDate}{StaticData.International("ConsistencyVerification_Of")}{item.Modality}{StaticData.International("ConsistencyVerification_IrcL")} "); + dialogMsg.AppendLine($"
{num}. {_localizer["ConsistencyVerification_IrcLi", item.StudyDate, item.Modality]}
"); } dialogMsg.AppendLine($"
"); - dialogMsg.AppendLine(@$"
{StaticData.International("ConsistencyVerification_Desc")}"); + dialogMsg.AppendLine(@$"
{_localizer["ConsistencyVerification_Desc"]}
"); + + dbSV.CheckResult = _localizer["ConsistencyVerification_Conf"] + + String.Join(" | ", dbExceptExcel.Select(t => $"{_localizer["ConsistencyVerification_EdcL", t.StudyDate, t.Modality]}")) + " | " + + String.Join(" | ", excelExceptDB.Select(t => $"{_localizer["ConsistencyVerification_IrcLi", t.StudyDate, t.Modality]}")); - //---根据导入的一致性核查数据,请确认本访视以下不一致检查项信息: - dbSV.CheckResult = StaticData.International("ConsistencyVerification_Conf") + String.Join(" | ", dbExceptExcel.Select(t => $"{StaticData.International("ConsistencyVerification_Edc")}{t.StudyDate} {t.Modality} ")) + " | " - + String.Join(" | ", excelExceptDB.Select(t => $"{StaticData.International("ConsistencyVerification_IrcLi")}{t.StudyDate} {t.Modality}")); //新增一致性核查质疑记录 - dbSV.CheckState = CheckStateEnum.CVIng; dbSV.CheckChallengeState = CheckChanllengeTypeEnum.PMWaitCRCReply; diff --git a/IRaCIS.Core.Domain.Share/Common/EmailScenarioEnum.cs b/IRaCIS.Core.Domain.Share/Common/EmailScenarioEnum.cs index b85e862bc..b86eac726 100644 --- a/IRaCIS.Core.Domain.Share/Common/EmailScenarioEnum.cs +++ b/IRaCIS.Core.Domain.Share/Common/EmailScenarioEnum.cs @@ -46,6 +46,7 @@ namespace IRaCIS.Core.Domain.Share public enum EmailBusinessScenario { + None = -1, EnrollConfirmed = 1, PDConfirmed = 2, diff --git a/IRaCIS.Core.Domain.Share/Reading/ReadEnum.cs b/IRaCIS.Core.Domain.Share/Reading/ReadEnum.cs index 99889d0b2..93aeccd3c 100644 --- a/IRaCIS.Core.Domain.Share/Reading/ReadEnum.cs +++ b/IRaCIS.Core.Domain.Share/Reading/ReadEnum.cs @@ -1811,10 +1811,34 @@ namespace IRaCIS.Core.Domain.Share } - /// - /// 限制编辑 - /// - public enum LimitEdit + + + /// + /// 显示限制 + /// + public enum LimitShow + { + /// + /// 全都显示 + /// + AllShow = 0, + + /// + /// 基线显示 + /// + BaseLineShow = 1, + + /// + /// 随访显示 + /// + FollowShow = 2, + + } + + /// + /// 限制编辑 + /// + public enum LimitEdit { /// diff --git a/IRaCIS.Core.Domain/Allocation/TaskMedicalReview.cs b/IRaCIS.Core.Domain/Allocation/TaskMedicalReview.cs index 901e4c984..83a31484f 100644 --- a/IRaCIS.Core.Domain/Allocation/TaskMedicalReview.cs +++ b/IRaCIS.Core.Domain/Allocation/TaskMedicalReview.cs @@ -19,7 +19,10 @@ namespace IRaCIS.Core.Domain.Models [Table("TaskMedicalReview")] public class TaskMedicalReview : Entity, IAuditUpdate, IAuditAdd { + [JsonIgnore] + public User LatestReplyUser { get; set; } + public Guid? LatestReplyUserId { get; set; } /// /// CreateUserId diff --git a/IRaCIS.Core.Domain/Common/Internationalization.cs b/IRaCIS.Core.Domain/Common/Internationalization.cs index dc3292224..e4a7be5e9 100644 --- a/IRaCIS.Core.Domain/Common/Internationalization.cs +++ b/IRaCIS.Core.Domain/Common/Internationalization.cs @@ -33,16 +33,18 @@ namespace IRaCIS.Core.Domain.Models public int State { get; set; } - public string Description { get; set; } + public string Description { get; set; } = string.Empty; - public string Code { get; set; } + public string Code { get; set; } = string.Empty; - public string Value { get; set; } + public string Value { get; set; } = string.Empty; - public string ValueCN { get; set; } + public string ValueCN { get; set; } = string.Empty; public int InternationalizationType { get; set; } + public string FrontType { get; set; }=string.Empty; + } } diff --git a/IRaCIS.Core.Domain/Image/DicomStudyMonitor.cs b/IRaCIS.Core.Domain/Image/DicomStudyMonitor.cs index 39d940765..734865204 100644 --- a/IRaCIS.Core.Domain/Image/DicomStudyMonitor.cs +++ b/IRaCIS.Core.Domain/Image/DicomStudyMonitor.cs @@ -85,7 +85,9 @@ namespace IRaCIS.Core.Domain.Models public bool IsSuccess { get; set; } - public string Note = string.Empty; + public string Note { get; set; } = string.Empty; + + public string RecordPath { get; set; }=string.Empty; } diff --git a/IRaCIS.Core.Domain/Institution/Site.cs b/IRaCIS.Core.Domain/Institution/Site.cs index feeeaa044..7bfbbbf7c 100644 --- a/IRaCIS.Core.Domain/Institution/Site.cs +++ b/IRaCIS.Core.Domain/Institution/Site.cs @@ -8,6 +8,7 @@ namespace IRaCIS.Core.Domain.Models public partial class Site : Entity, IAuditUpdate, IAuditAdd { [JsonIgnore] + [ForeignKey("HospitalId")] public Hospital Hospital { get; set; } public string SiteName { get; set; } = string.Empty; public string SiteNameCN{ get; set; } = string.Empty; diff --git a/IRaCIS.Core.Domain/Management/Role.cs b/IRaCIS.Core.Domain/Management/Role.cs index e110af3df..20d75daa4 100644 --- a/IRaCIS.Core.Domain/Management/Role.cs +++ b/IRaCIS.Core.Domain/Management/Role.cs @@ -13,7 +13,7 @@ namespace IRaCIS.Core.Domain.Models public string RoleDescription { get; set; } = string.Empty; public int Status { get; set; } - public int PrivilegeLevel { get; set; } //Ȩ޼ + public int PrivilegeLevel { get; set; } //权限级别 public DateTime CreateTime { get; set; } = DateTime.Now; public Guid CreateUserId { get; set; } = Guid.Empty; diff --git a/IRaCIS.Core.Domain/QC/UserUploadFile.cs b/IRaCIS.Core.Domain/QC/UserUploadFile.cs index 78f34a959..2cc382da9 100644 --- a/IRaCIS.Core.Domain/QC/UserUploadFile.cs +++ b/IRaCIS.Core.Domain/QC/UserUploadFile.cs @@ -7,18 +7,15 @@ namespace IRaCIS.Core.Domain.Models /// /// 一致性核查文件 /// - [Table("UserUploadFile")] - public class UserUploadFile : Entity, IAuditAdd + [Table("InspectionFile")] + public class InspectionFile : Entity, IAuditAdd { /// /// 文件名称 /// public string FileName { get; set; } - /// - /// 文件路径 - /// - public string FilePath { get; set; } + /// /// 相对路径 diff --git a/IRaCIS.Core.Domain/Reading/ReadingCriterionQuestion/ReadingQuestionSystem.cs b/IRaCIS.Core.Domain/Reading/ReadingCriterionQuestion/ReadingQuestionSystem.cs index fee763d72..1b2849c4e 100644 --- a/IRaCIS.Core.Domain/Reading/ReadingCriterionQuestion/ReadingQuestionSystem.cs +++ b/IRaCIS.Core.Domain/Reading/ReadingCriterionQuestion/ReadingQuestionSystem.cs @@ -181,6 +181,10 @@ namespace IRaCIS.Core.Domain.Models /// public LimitEdit LimitEdit { get; set; } = LimitEdit.None; + /// + /// 限制显示 + /// + public LimitShow LimitShow { get; set; } = LimitShow.AllShow; /// /// 数据来源 diff --git a/IRaCIS.Core.Domain/Reading/ReadingCriterionQuestion/ReadingQuestionTrial.cs b/IRaCIS.Core.Domain/Reading/ReadingCriterionQuestion/ReadingQuestionTrial.cs index 8af84fed2..1f7307fe3 100644 --- a/IRaCIS.Core.Domain/Reading/ReadingCriterionQuestion/ReadingQuestionTrial.cs +++ b/IRaCIS.Core.Domain/Reading/ReadingCriterionQuestion/ReadingQuestionTrial.cs @@ -231,6 +231,11 @@ namespace IRaCIS.Core.Domain.Models /// public LimitEdit LimitEdit { get; set; } = LimitEdit.None; + /// + /// 限制显示 + /// + public LimitShow LimitShow { get; set; } = LimitShow.AllShow; + /// /// 自定义计算标记 /// diff --git a/IRaCIS.Core.Domain/Trial/Trial.cs b/IRaCIS.Core.Domain/Trial/Trial.cs index 54cb8ba39..751903e6f 100644 --- a/IRaCIS.Core.Domain/Trial/Trial.cs +++ b/IRaCIS.Core.Domain/Trial/Trial.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; @@ -87,12 +87,12 @@ namespace IRaCIS.Core.Domain.Models [StringLength(512)] public string Indication { get; set; } = string.Empty; - //һ״̬ + //入组那一块的状态 //[ConcurrencyCheck] public int TrialEnrollStatus { get; set; } - //״̬ + //启动状态 [StringLength(500)] public string TrialStatusStr { get; set; } = StaticData.TrialState.TrialInitializing; @@ -142,15 +142,15 @@ namespace IRaCIS.Core.Domain.Models - // - //public AttendedReviewerType AttendedReviewerType { get; set; } = AttendedReviewerType.CN;//0ȫйҽ 1ҽ 2йҽҲҽ + //废弃 + //public AttendedReviewerType AttendedReviewerType { get; set; } = AttendedReviewerType.CN;//0全部中国医生 1美国医生 2既有中国医生,也有美国医生 - //// + ////废弃 //[JsonIgnore] //[ForeignKey("DeclarationTypeId")] //public Dictionary DeclarationType { get; set; } - // + //废弃 //public Guid DeclarationTypeId { get; set; } = Guid.Empty; @@ -173,66 +173,66 @@ namespace IRaCIS.Core.Domain.Models public bool VisitPlanConfirmed { get; set; } /// - /// ߱ž + /// 受试者编号具体规则 /// public string SubjectCodeRule { get; set; } = StaticData.International("Trial_number"); /// - /// Ƿ ߱Ź + /// 是否 提醒受试者编号规则 /// public bool IsNoticeSubjectCodeRule { get; set; } = true; /// - /// Ƿ л׼ʱ䣨״θҩʱ䣩 + /// 是否 有基准时间(首次给药时间) /// public bool IsHaveFirstGiveMedicineDate { get; set; } = true; /// - /// Ƿ + /// 是否有 受试者年龄 /// public bool IsHaveSubjectAge { get; set; } = false; /// - /// Ƿ ȷ + /// 是否有 入组性确认 /// public bool IsEnrollementQualificationConfirm { get; set; } = false; /// - /// ƻ + /// 出组后计划外访视名称 /// public string OutEnrollmentVisitName { get; set; } = "EOT"; /// - /// Ƿ ֤Ƭ + /// 是否 验证拍片日期 /// public bool IsVerifyVisitImageDate { get; set; } = true; /// - /// ٴϢ 1ϵͳ¼ 2ϵͳ¼+PDF 0 + /// 临床信息传输 1:系统录入 2:系统录入+PDF 0:无 /// public int ClinicalInformationTransmissionEnum { get; set; } = 1; /// - /// Ƿ ٴϢ + /// 是否审核 临床信息 /// public bool IsCRAAuditClinicalInformation { get; set; } = false; /// - /// QC 0 1 2˫ + /// QC流程 0 不审,1 单审,2双审 /// public TrialQCProcess QCProcessEnum { get; set; } = TrialQCProcess.NotAudit; /// - /// ӰһԺ˲ + /// 影像一致性核查 /// public bool IsImageConsistencyVerification { get; set; } = false; /// - /// Ӱ񵼳 + /// 影像导出 /// public bool IsImageExport { get; set; } = false; @@ -241,7 +241,7 @@ namespace IRaCIS.Core.Domain.Models - //Ƭʽ + //阅片方式 public int ReadingMode { get; set; } = 1; @@ -249,12 +249,12 @@ namespace IRaCIS.Core.Domain.Models public int ChangeDefalutDays { get; set; } = 5; /// - /// Ŀ + /// 跨项目复制 /// public bool IsImageReplicationAcrossTrial { get; set; } = false; - public string BodyPartTypes { get; set; } = "ʲ|Բ||ز|/¸|ǻ|ȫ|"; + public string BodyPartTypes { get; set; } = "鼻咽部|脑部|颈部|胸部|上/下腹部|盆腔|全身|其他"; @@ -270,25 +270,25 @@ namespace IRaCIS.Core.Domain.Models - //PD չǷʾ ÷ Ƿʾ PDչ (Ӷ״̬) + //PD 进展是否显示 配置访视 是否显示 PD进展 (从而可以设置状态) public bool IsPDProgressView { get; set; } - //о + //研究方案号 public string ResearchProgramNo { get; set; } - //ʵ + //实验名称 public string ExperimentName { get; set; } - //еλ + //主研单位 public string MainResearchUnit { get; set; } - // PI + // 负责人PI public string HeadPI { get; set; } public bool IsUrgent { get; set; } /// - /// Ŀ 1 ʽĿ0 ʽĿ 2ѵĿ + /// 项目类型 1 正式项目、0 非正式项目 2是培训项目 /// time public TrialType TrialType { get; set; } @@ -306,7 +306,7 @@ namespace IRaCIS.Core.Domain.Models public bool IsSubjectSexView { get; set; } = false; - //Suject Editҳ Ƿʾ Ӽ + //配置Suject Edit页面 是否显示 加急 public bool IsSubjectExpeditedView { get; set; } = false; @@ -314,14 +314,14 @@ namespace IRaCIS.Core.Domain.Models public bool IsDeleted { get; set; } - //QC + //QC 问题流程 public User QCQuestionConfirmedUser { get; set; } public Guid? QCQuestionConfirmedUserId { get; set; } public DateTime? QCQuestionConfirmedTime { get; set; } /// - /// Ŀʱ + /// 项目完成时间 /// public DateTime? TrialFinishTime { get; set; } @@ -340,7 +340,7 @@ namespace IRaCIS.Core.Domain.Models public Guid? DeleteUserId { get; set; } /// - /// ͬٴʱ + /// 同步临床数据时间 /// public DateTime? SyncClinicalDataTime { get; set; } @@ -359,34 +359,34 @@ namespace IRaCIS.Core.Domain.Models public UserTypeEnum? PDProgressDefaultUserType { get; set; } - #region ʼ + #region 邮件配置 /// - /// ˺ + /// 发件箱账号 /// public string EmailFromEmail { get; set; } = string.Empty; /// - /// + /// 发件人 /// public string EmailFromName { get; set; } = string.Empty; /// - /// /Ȩ + /// 密码/授权码 /// public string EmailAuthorizationCode { get; set; } = string.Empty; /// - /// SMTP + /// SMTP服务器 /// public string EmailSMTPServerAddress { get; set; } = string.Empty; /// - /// SMTP˿ + /// SMTP端口 /// public int EmailSMTPServerPort { get; set; } /// - /// Ƿù + /// 是否配置过邮箱 /// public bool IsConfigureEmail { get; set; } = false; #endregion @@ -395,20 +395,20 @@ namespace IRaCIS.Core.Domain.Models ///// - ///// ͼǷбע + ///// 图像是否有标注 ///// //public bool IsImageIabeled { get; set; } - ////Ƭ + ////阅片类型 //public ReadingMethod ReadingType { get; set; } = ReadingMethod.Double; //public bool IsGlobalReading { get; set; } = true; ///// - ///// ٲƬ + ///// 仲裁阅片 ///// //public bool? IsArbitrationReading { get; set; } = true; @@ -416,50 +416,50 @@ namespace IRaCIS.Core.Domain.Models ///// - ///// 1 Mint2 PACS + ///// 1 Mint、2 PACS ///// //public int ImagePlatform { get; set; } = 1; ///// - ///// ٲù + ///// 仲裁规则 ///// //public ArbitrationRule ArbitrationRule { get; set; } = ArbitrationRule.None; - //// + ////任务分配对象 //public TaskAllocateObj TaskAllocateObjEnum { get; set; } - ////Զ + ////后续访视任务自动分配 //public bool IsFollowVisitAutoAssign { get; set; } = true; - ////ȫԶ + ////后续全局自动分配 //public bool IsFollowGlobalVisitAutoAssign { get; set; } = true; //public bool IsFollowJudgeTaskAutoAssign { get; set; } = true; //public TaskAllocateDefaultState FollowJudgeTaskAutoAssignDefaultState { get; set; } = TaskAllocateDefaultState.Allocated; - ////ԶĬ״̬ + ////后续访视自动分配默认状态 //public TaskAllocateDefaultState FollowVisitAutoAssignDefaultState { get; set; } = TaskAllocateDefaultState.Allocated; - ////ȫԶĬ״̬ + ////后续全局自动分配默认状态 //public TaskAllocateDefaultState FollowGlobalVisitAutoAssignDefaultState { get; set; } = TaskAllocateDefaultState.Allocated; - ////Ƭʾ + ////读片任务显示规则 //public ReadingTaskViewMethod ReadingTaskViewEnum { get; set; } - ////ƬʾǷ˳ + ////读片任务显示是否顺序 //public bool IsReadingTaskViewInOrder { get; set; } = true; ///// - ///// ƬǷʾϢ + ///// 阅片是否显示受试者信息 ///// //public bool IsReadingShowSubjectInfo { get; set; } = false; ///// - ///// ƬǷʾ + ///// 阅片是否显示既往结果 ///// //public bool IsReadingShowPreviousResults { get; set; } = false; @@ -467,7 +467,7 @@ namespace IRaCIS.Core.Domain.Models ///// - ///// ȷҽѧ + ///// 是确认医学审核问题 ///// //public bool IsConfirmMedicineQuestion { get; set; } = false; @@ -476,12 +476,12 @@ namespace IRaCIS.Core.Domain.Models ///// - ///// ƬϢǩʱ + ///// 阅片信息签名时间 ///// //public DateTime? ReadingInfoSignTime { get; set; } ///// - ///// Ƭ + ///// 阅片工具 ///// //public ReadingTool? ReadingTool { get; set; } diff --git a/IRaCIS.Core.Domain/TrialSiteUser/TrialUser.cs b/IRaCIS.Core.Domain/TrialSiteUser/TrialUser.cs index d1c5de42d..5bd0f4904 100644 --- a/IRaCIS.Core.Domain/TrialSiteUser/TrialUser.cs +++ b/IRaCIS.Core.Domain/TrialSiteUser/TrialUser.cs @@ -6,7 +6,7 @@ using IRaCIS.Core.Domain.Share; namespace IRaCIS.Core.Domain.Models { /// - /// άԱĿϵ - ʵ + /// 运维人员与项目关联关系表 - 实体 /// [Table("TrialUser")] public partial class TrialUser : Entity, IAuditUpdate, IAuditAdd ,ISoftDelete diff --git a/IRaCIS.Core.Domain/Visit/SubjectVisit.cs b/IRaCIS.Core.Domain/Visit/SubjectVisit.cs index e00d65c47..46f1c9370 100644 --- a/IRaCIS.Core.Domain/Visit/SubjectVisit.cs +++ b/IRaCIS.Core.Domain/Visit/SubjectVisit.cs @@ -82,6 +82,8 @@ namespace IRaCIS.Core.Domain.Models public DateTime? PreliminaryAuditTime { get; set; } public Guid? ForwardUserId { get; set; } public DateTime? ForwardTime { get; set; } + + // 质控领取人 public Guid? CurrentActionUserId { get; set; } public DateTime? CurrentActionUserExpireTime { get; set; } diff --git a/IRaCIS.Core.Domain/_Config/_StaticData.cs b/IRaCIS.Core.Domain/_Config/_StaticData.cs index 964bc42c5..2791b6f50 100644 --- a/IRaCIS.Core.Domain/_Config/_StaticData.cs +++ b/IRaCIS.Core.Domain/_Config/_StaticData.cs @@ -121,7 +121,10 @@ public static class StaticData public static readonly string UploadFileFolder = "UploadFile"; } - + public static class EmailSend + { + public static string EmailNamePlaceholder = "EmailNamePlaceholder"; + } public static class TrialOpt { @@ -180,7 +183,10 @@ public static class StaticData - + public static class InternationalData + { + public const string Front = "Front"; + } /// /// 匿名化配置 key diff --git a/IRaCIS.Core.IdentityServer4/appsettings.json b/IRaCIS.Core.IdentityServer4/appsettings.json index 46b2381b7..8994bd51f 100644 --- a/IRaCIS.Core.IdentityServer4/appsettings.json +++ b/IRaCIS.Core.IdentityServer4/appsettings.json @@ -5,10 +5,10 @@ "RemoteNew": "Server=123.56.181.144,14333\\MSSQLExpress14;Database=IRaCIS_New;User ID=sa;Password=dev123456DEV;" }, "JwtSetting": { - "SecurityKey": "3e6dbfa227234a03977a2f421bdb7f4f", // Կ - "Issuer": "IRaCIS", // ䷢ - "Audience": "ZhiZhun", // - "TokenExpireDays": "7" // ʱ䣨7day + "SecurityKey": "3e6dbfa227234a03977a2f421bdb7f4f", // 密钥 + "Issuer": "IRaCIS", // 颁发者 + "Audience": "ZhiZhun", // 接收者 + "TokenExpireDays": "7" // 过期时间(7day) }, "IpRateLimiting": { "EnableEndpointRateLimiting": true, //False: globally executed, true: executed for each @@ -69,7 +69,7 @@ }, - //վַΪ˷ļ dicom ϴĵ... ʵֲⷢýƴӷأԶϵǰip˶໷ȡļ + //网站根地址,为了访问文件 dicom 和上传的文档... 实测发现不用将域名拼接返回,浏览器会自动加上当前ip,避免了多环境读取环境配置文件 //"RootUrl": "http://localhost:8060", "GrpcAddress": "http://123.56.181.144:7200", @@ -83,7 +83,7 @@ "UserCodePrefix": "U", "Share": false, // "FileSizeLimit": 1073741824, - "LoginExpiredTimeSpan": "15", // Minute + "LoginExpiredTimeSpan": ":15", // Minute "OpenLog": true, "AddClinicalInfo": true diff --git a/IRaCIS.Core.Infra.EFCore/Common/AuditingData.cs b/IRaCIS.Core.Infra.EFCore/Common/AuditingData.cs index eff31d601..032dd2f80 100644 --- a/IRaCIS.Core.Infra.EFCore/Common/AuditingData.cs +++ b/IRaCIS.Core.Infra.EFCore/Common/AuditingData.cs @@ -1130,7 +1130,10 @@ namespace IRaCIS.Core.Infra.EFCore.Common await InsertInspection(entity, type, x => new InspectionConvertDTO() { IsDistinctionInterface = false, - ObjectRelationParentId = x.TrialId + + ObjectRelationParentId = entity.TrialId, + TrialReadingCriterionId = x.TrialReadingCriterionId, + }, new { ParentQuestionName = parentQuestionName }); } @@ -1353,11 +1356,11 @@ namespace IRaCIS.Core.Infra.EFCore.Common // 一致性核查文件 是否需要单独一个表记录? - foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(UserUploadFile))) + foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(InspectionFile))) { var type = GetEntityAuditOpt(item); - await InsertInspection(item.Entity as UserUploadFile, type, x => new InspectionConvertDTO() + await InsertInspection(item.Entity as InspectionFile, type, x => new InspectionConvertDTO() { ObjectRelationParentId = x.TrialId @@ -1408,6 +1411,30 @@ namespace IRaCIS.Core.Infra.EFCore.Common }); } + foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(TrialSiteUserSurvey))) + { + var type = GetEntityAuditOpt(item); + + var entity = item.Entity as TrialSiteUserSurvey; + + await InsertInspection(entity, type, x => new InspectionConvertDTO() + { + IsDistinctionInterface = false + + }); + } + foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(TrialSiteEquipmentSurvey))) + { + var type = GetEntityAuditOpt(item); + + var entity = item.Entity as TrialSiteEquipmentSurvey; + + await InsertInspection(entity, type, x => new InspectionConvertDTO() + { + IsDistinctionInterface = false + + }); + } #endregion @@ -1516,6 +1543,7 @@ namespace IRaCIS.Core.Infra.EFCore.Common } await InsertInspection(entity, type, x => new InspectionConvertDTO() { + IsDistinctionInterface= type == AuditOpt.Update ? true : false, TrialId = x.TrialId, ObjectRelationParentId = x.TrialId @@ -1566,6 +1594,7 @@ namespace IRaCIS.Core.Infra.EFCore.Common await InsertInspection(item.Entity as TrialSiteUser, type, x => new InspectionConvertDTO { + IsDistinctionInterface= type == AuditOpt.Update ? true : false, TrialId = x.TrialId, ObjectRelationParentId = entity.TrialSite.Id, ObjectRelationParentId2 = x.UserId, @@ -1709,6 +1738,8 @@ namespace IRaCIS.Core.Infra.EFCore.Common SubjectVisitId = x.Id, SiteId = x.SiteId, + ExtraIndentification = extraIdentification, + }, //兼容之前的配置名 new { SubjectVisitName = entity.VisitName } @@ -2106,12 +2137,12 @@ namespace IRaCIS.Core.Infra.EFCore.Common if (entity.RequestReReadingResultEnum == RequestReReadingResult.Agree) { - extraIdentification = "/" + 1; + extraIdentification = extraIdentification+"/" + 1; } else if (entity.RequestReReadingResultEnum == RequestReReadingResult.Reject) { - extraIdentification = "/" + 2; + extraIdentification = extraIdentification+ "/" + 2; } break; } diff --git a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs index bf54cfa5a..1bbbced54 100644 --- a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs +++ b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs @@ -466,7 +466,7 @@ namespace IRaCIS.Core.Infra.EFCore public virtual DbSet FrontAuditConfig { get; set; } - public virtual DbSet UserUploadFile { get; set; } + public virtual DbSet InspectionFile { get; set; } public virtual DbSet CommonDocument { get; set; } @@ -558,12 +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); + //catch (Exception ex) + //{ + // _logger.LogError(ex.InnerException is null ? ex.Message : ex.InnerException?.Message); - throw new DBSaveFailedException("数据保存异常。"); - } + // throw new DBSaveFailedException(ex.Message); + //} } diff --git a/IRaCIS.Core.Infra.EFCore/Repository/DynamicRelationalExtensions.cs b/IRaCIS.Core.Infra.EFCore/Repository/DynamicRelationalExtensions.cs new file mode 100644 index 000000000..b2ebb10f0 --- /dev/null +++ b/IRaCIS.Core.Infra.EFCore/Repository/DynamicRelationalExtensions.cs @@ -0,0 +1,120 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Query; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace IRaCIS.Core.Infra.EFCore +{ + + public static class DynamicRelationalExtensions + { + static MethodInfo UpdateMethodInfo = + typeof(RelationalQueryableExtensions).GetMethod(nameof(RelationalQueryableExtensions.ExecuteUpdate)); + + static MethodInfo UpdateAsyncMethodInfo = + typeof(RelationalQueryableExtensions).GetMethod(nameof(RelationalQueryableExtensions.ExecuteUpdateAsync)); + + #region 避免使用 + + public static int ExecuteUpdate(this IQueryable query, string fieldName, object? fieldValue) + { + var updateBody = BuildUpdateBody(query.ElementType, + new Dictionary { { fieldName, fieldValue } }); + + return (int)UpdateMethodInfo.MakeGenericMethod(query.ElementType).Invoke(null, new object?[] { query, updateBody }); + } + + public static int ExecuteUpdate(this IQueryable query, IReadOnlyDictionary fieldValues) + { + var updateBody = BuildUpdateBody(query.ElementType, fieldValues); + + return (int)UpdateMethodInfo.MakeGenericMethod(query.ElementType).Invoke(null, new object?[] { query, updateBody }); + } + public static Task ExecuteUpdateAsync(this IQueryable query, string fieldName, object? fieldValue, CancellationToken cancellationToken = default) + { + var updateBody = BuildUpdateBody(query.ElementType, + new Dictionary { { fieldName, fieldValue } }); + + return (Task)UpdateAsyncMethodInfo.MakeGenericMethod(query.ElementType).Invoke(null, new object?[] { query, updateBody, cancellationToken })!; + } + #endregion + + public static Dictionary ExtractFieldValues(this Expression> updateFactory) + { + var dic = new Dictionary(); + var obj = (TSource)Activator.CreateInstance(typeof(TSource)); + + Func func = updateFactory.Compile(); + + TSource applyObj = func(obj); + + var propList = ((MemberInitExpression)updateFactory.Body).Bindings.Select(mb => mb.Member.Name) + .Select(propName => typeof(TSource).GetProperty(propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)).ToList(); + + + foreach (PropertyInfo prop in propList) + { + object value = prop.GetValue(applyObj); + dic.Add(prop.Name, value); + } + + return dic; + } + + + + public static Task ExecuteUpdateAsync(this IQueryable query, IReadOnlyDictionary fieldValues, CancellationToken cancellationToken = default) + { + var updateBody = BuildUpdateBody(query.ElementType, fieldValues); + + return (Task)UpdateAsyncMethodInfo.MakeGenericMethod(query.ElementType).Invoke(null, new object?[] { query, updateBody, cancellationToken })!; + } + + + static LambdaExpression BuildUpdateBody(Type entityType, IReadOnlyDictionary fieldValues) + { + var setParam = Expression.Parameter(typeof(SetPropertyCalls<>).MakeGenericType(entityType), "s"); + var objParam = Expression.Parameter(entityType, "e"); + + Expression setBody = setParam; + + foreach (var pair in fieldValues) + { + var propExpression = Expression.PropertyOrField(objParam, pair.Key); + var valueExpression = ValueForType(propExpression.Type, pair.Value); + + // s.SetProperty(e => e.SomeField, value) + setBody = Expression.Call(setBody, nameof(SetPropertyCalls.SetProperty), + new[] { propExpression.Type }, Expression.Lambda(propExpression, objParam), valueExpression); + + } + + // s => s.SetProperty(e => e.SomeField, value) + var updateBody = Expression.Lambda(setBody, setParam); + + return updateBody; + } + + static Expression ValueForType(Type desiredType, object? value) + { + if (value == null) + { + return Expression.Default(desiredType); + } + + if (value.GetType() != desiredType) + { + return Expression.Convert(Expression.Constant(value), desiredType); + } + + return Expression.Constant(value); + } + } + +} diff --git a/IRaCIS.Core.Infra.EFCore/Repository/IRaCISContextExtension.cs b/IRaCIS.Core.Infra.EFCore/Repository/IRaCISContextExtension.cs index 5428578f6..c20c0704c 100644 --- a/IRaCIS.Core.Infra.EFCore/Repository/IRaCISContextExtension.cs +++ b/IRaCIS.Core.Infra.EFCore/Repository/IRaCISContextExtension.cs @@ -157,7 +157,7 @@ namespace IRaCIS.Core.Infra.EFCore { if (deleteFilter == null) throw new ArgumentNullException(nameof(deleteFilter)); - return await _dbContext.Set().IgnoreQueryFilters().Where(deleteFilter).BatchDeleteAsync() > 0; + return await _dbContext.Set().IgnoreQueryFilters().Where(deleteFilter).ExecuteDeleteAsync() > 0; } @@ -166,34 +166,64 @@ namespace IRaCIS.Core.Infra.EFCore { if (where == null) throw new ArgumentNullException(nameof(where)); - var bindings = ((MemberInitExpression)updateFactory.Body).Bindings.ToList(); - var hasPropNameList = bindings.Select(t => t.Member.Name).ToList(); + #region history 使用扩展删除包,同时自动赋值更新人 更新时间 + + //var bindings = ((MemberInitExpression)updateFactory.Body).Bindings.ToList(); + + //var hasPropNameList = bindings.Select(t => t.Member.Name).ToList(); - if (typeof(IAuditUpdate).IsAssignableFrom(typeof(T))) + //if (typeof(IAuditUpdate).IsAssignableFrom(typeof(T))) + //{ + + // if (!hasPropNameList.Contains(nameof(IAuditUpdate.UpdateTime))) + // { + // bindings.Add(Expression.Bind(typeof(T).GetMember(nameof(IAuditUpdate.UpdateTime))[0], Expression.Constant(DateTime.Now))); + + // } + + // if (!hasPropNameList.Contains(nameof(IAuditUpdate.UpdateUserId))) + // { + // bindings.Add(Expression.Bind(typeof(T).GetMember(nameof(IAuditUpdate.UpdateUserId))[0], Expression.Constant(updateUserId))); + + // } + //} + + //var member = Expression.MemberInit(Expression.New(typeof(T)), bindings); + + //var factory = Expression.Lambda>(member, Expression.Parameter(typeof(T), "x")); + + //return await _dbContext.Set().IgnoreQueryFilters().Where(where).BatchUpdateAsync(factory).ConfigureAwait(false) > 0; + + #endregion + + + #region efcore 7 & 8 { + var fieldValues = updateFactory.ExtractFieldValues(); - if (!hasPropNameList.Contains(nameof(IAuditUpdate.UpdateTime))) + var hasPropNameList = ((MemberInitExpression)updateFactory.Body).Bindings.Select(t => t.Member.Name).ToList(); + + if (typeof(IAuditUpdate).IsAssignableFrom(typeof(T))) { - bindings.Add(Expression.Bind(typeof(T).GetMember(nameof(IAuditUpdate.UpdateTime))[0], Expression.Constant(DateTime.Now))); + if (!hasPropNameList.Contains(nameof(IAuditUpdate.UpdateTime))) + { + fieldValues.Add(nameof(IAuditUpdate.UpdateTime), DateTime.Now); + } + + if (!hasPropNameList.Contains(nameof(IAuditUpdate.UpdateUserId))) + { + fieldValues.Add(nameof(IAuditUpdate.UpdateUserId), updateUserId); + } } - if (!hasPropNameList.Contains(nameof(IAuditUpdate.UpdateUserId))) - { - bindings.Add(Expression.Bind(typeof(T).GetMember(nameof(IAuditUpdate.UpdateUserId))[0], Expression.Constant(updateUserId))); - - } + return await _dbContext.Set().IgnoreQueryFilters().Where(where).ExecuteUpdateAsync(fieldValues).ConfigureAwait(false) > 0; } - var member = Expression.MemberInit(Expression.New(typeof(T)), bindings); - - var factory = Expression.Lambda>(member, Expression.Parameter(typeof(T), "x")); - - - return await _dbContext.Set().IgnoreQueryFilters().Where(where).BatchUpdateAsync(factory).ConfigureAwait(false) > 0; + #endregion diff --git a/IRaCIS.Core.Infrastructure/_IRaCIS/NUllCheckExtension.cs b/IRaCIS.Core.Infrastructure/_IRaCIS/NUllCheckExtension.cs index 9023d7030..f4a8aae3c 100644 --- a/IRaCIS.Core.Infrastructure/_IRaCIS/NUllCheckExtension.cs +++ b/IRaCIS.Core.Infrastructure/_IRaCIS/NUllCheckExtension.cs @@ -12,7 +12,7 @@ namespace IRaCIS.Core.Infrastructure.Extention { if(businessObject == null) { - throw new QueryBusinessObjectNotExistException($"The query object {typeof(TEntity).Name} does not exist in database, Please check the query parameters"); + throw new QueryBusinessObjectNotExistException($"The query object {typeof(TEntity).Name} is null, Please check "); } else { @@ -25,7 +25,7 @@ namespace IRaCIS.Core.Infrastructure.Extention { if (businessStruct == null) { - throw new QueryBusinessObjectNotExistException($"The query object {typeof(TEntity).Name} does not exist in database, Please check the query parameters"); + throw new QueryBusinessObjectNotExistException($"The query object {typeof(TEntity).Name} is null, Please check "); } else { @@ -38,7 +38,7 @@ namespace IRaCIS.Core.Infrastructure.Extention { if (businessObject == null) { - throw new QueryBusinessObjectNotExistException($" Can not Convert to {typeof(TEntity).Name} Type, Please check parameter"); + throw new QueryBusinessObjectNotExistException($" {typeof(TEntity).Name} Type object should not null, Please check "); } else { diff --git a/IRaCIS.Core.Infrastructure/_IRaCIS/ObjectExtension.cs b/IRaCIS.Core.Infrastructure/_IRaCIS/ObjectExtension.cs index adfc82153..62463e1f3 100644 --- a/IRaCIS.Core.Infrastructure/_IRaCIS/ObjectExtension.cs +++ b/IRaCIS.Core.Infrastructure/_IRaCIS/ObjectExtension.cs @@ -1,5 +1,7 @@ using Newtonsoft.Json; using System; +using System.Collections.Generic; +using System.Reflection; namespace IRaCIS.Core.Infrastructure.Extention { @@ -38,7 +40,38 @@ namespace IRaCIS.Core.Infrastructure.Extention public static string ToJsonNotIgnoreNull(this object obj) { - return JsonConvert.SerializeObject(obj, new JsonSerializerSettings { DateFormatString = "yyyy-MM-dd HH:mm:ss", ReferenceLoopHandling = ReferenceLoopHandling.Ignore, NullValueHandling = NullValueHandling.Include }); + return JsonConvert.SerializeObject(obj, new JsonSerializerSettings { DateFormatString = "yyyy-MM-dd HH:mm:ss", Formatting = Formatting.Indented, ReferenceLoopHandling = ReferenceLoopHandling.Ignore, NullValueHandling = NullValueHandling.Include }); } - } + + public static Dictionary ConvertToDictionary(this object obj) + { + if (obj == null) + { + throw new ArgumentNullException(nameof(obj)); + } + + Type type = obj.GetType(); + PropertyInfo[] properties = type.GetProperties(); + + Dictionary dictionary = new Dictionary(); + + foreach (PropertyInfo property in properties) + { + string propertyName = property.Name; + object propertyValue = property.GetValue(obj); + + // 如果属性的类型是枚举,将其值保留为整数 + if (property.PropertyType.IsEnum) + { + dictionary.Add(propertyName, (int)propertyValue); + } + else + { + dictionary.Add(propertyName, propertyValue); + } + } + + return dictionary; + } + } } diff --git a/IRaCIS.Core.Test/DbHelper.ttinclude b/IRaCIS.Core.Test/DbHelper.ttinclude index 24c236c0c..2ef79dec6 100644 --- a/IRaCIS.Core.Test/DbHelper.ttinclude +++ b/IRaCIS.Core.Test/DbHelper.ttinclude @@ -3,9 +3,9 @@ { public static readonly string ConnectionString = "Server=123.56.94.154,1433\\MSSQLSERVER;Database=Test.Study;User ID=sa;Password=dev123456DEV;TrustServerCertificate=true"; public static readonly string DbDatabase = "Test.Study"; - //ַ,ƴ + //表名称用字符串,拼接 public static readonly string TableName = "SubjectVisitClinicalDialog"; - //ļ service Ƿҳ + //具体文件里面 例如service 可以配置是否分页 } #> <#+ diff --git a/ZhiZhunAuthenticationCenter/Protos/GrpcToken.proto b/ZhiZhunAuthenticationCenter/Protos/GrpcToken.proto index ace5d4240..f14d65a66 100644 --- a/ZhiZhunAuthenticationCenter/Protos/GrpcToken.proto +++ b/ZhiZhunAuthenticationCenter/Protos/GrpcToken.proto @@ -1,16 +1,16 @@ -// ʹõproto3汾 +// 使用的是proto3版本 syntax = "proto3"; -// ռ䣬ɴʱͻɶӦռ +// 定义命名空间,后续生成代码时就会生成对应的命名空间 option csharp_namespace = "gRPC.ZHiZHUN.AuthServer.protos"; /* -ÿһҪ÷ֺŽβ -message ͷݸʽ -tag messageִֵֶεıʶ(tag),Ǹֵ +每一句需要用分号结尾 +message 用来定义请求和返回数据格式 +tag message后面的值数字代表是字段的标识(tag),不是赋值, */ -// ûʱҪϢ Ϊһ +// 新增用户时需要传递数据消息, 可理解为一个类 message GetTokenReuqest{ string id=1; string userName=2; @@ -22,48 +22,48 @@ message GetTokenReuqest{ } -// ʱصϢʽ +// 新增时返回的消息格式 message GetTokenResponse { int32 code=1; string token =2; } -// service ñʶģдӦķ +// service 用标识定义服务的,里面写对应的方法 service TokenGrpcService{ - // ȡtoken + // 获取token rpc GetUserToken(GetTokenReuqest) returns (GetTokenResponse); } /* -// ûʱҪϢ Ϊһ +// 新增用户时需要传递数据消息, 可理解为一个类 message AddUserReuqest{ string name=1; int32 age=2; bool isBoy=3; } -// ʱصϢʽ +// 新增时返回的消息格式 message ResultResponse { int32 code=1; string msg =2; } -//ݵIJѯϢʽΪƽʱIJѯ +//传递的查询条件信息格式,可理解为平时传入的查询条件对象 message QueryUserReuqest{ string name=1; } -//ѯصûϢʽΪص +//查询返回的用户信息格式,可理解为返回的类 message UserInfoResponse { string name=1; int32 age=2; string gender=3; } -// service ñʶģдӦķ +// service 用标识定义服务的,里面写对应的方法 service UserService{ - // û + // 新增用户 rpc AddUser(AddUserReuqest) returns (ResultResponse); - // ѯû + // 查询用户 rpc GetAllUser(QueryUserReuqest) returns (UserInfoResponse); } */ diff --git a/irc_api.drone.yml b/irc_api.drone.yml index 7fc06efa3..2ca805375 100644 --- a/irc_api.drone.yml +++ b/irc_api.drone.yml @@ -2,105 +2,139 @@ kind: pipeline type: docker name: irc-netcore-api -steps: - - name: docker-build - image: docker - pull: if-not-exists - volumes: - - name: dockersock - path: /var/run/docker.sock - - name: cached_nuget_packages - path: /drone/nuget_packages - commands: - - date +%H:%M:%S - - pwd - - docker build -t Test_Study . - - date +%H:%M:%S +clone: + disable: true #禁用默认克隆 + +steps: +- name: clone-repo + image: alpine/git + pull: if-not-exists + volumes: + - name: irc-test-work + path: /work + commands: + - if [ ! -e /work/netcore-repo/.git ]; then + git clone -b Test.IRC http://192.168.3.68:2000/XCKJ/irc-netcore-api.git /work/netcore-repo; + else + cd /work/netcore-repo; + git pull; + fi + + - | + if [ ! -e Dockerfile ]; then + echo 'FROM mcr.microsoft.com/dotnet/aspnet:6.0 + EXPOSE 80 + WORKDIR /app + COPY publish . + ENTRYPOINT ["dotnet", "IRaCIS.Core.API.dll"]' > /work/Dockerfile + fi + +- name: restore-publish + image: mcr.microsoft.com/dotnet/sdk:6.0 + pull: if-not-exists + depends_on: + - clone-repo + volumes: + - name: nuget-packages + path: /root/.nuget/packages + - name: irc-test-work + path: /work + commands: + - cd /work/netcore-repo/IRaCIS.Core.API + - dotnet restore ./IRaCIS.Core.API.csproj + - rm -rf /work/publish + - cd /work/netcore-repo/IRaCIS.Core.API + - dotnet publish ./IRaCIS.Core.API.csproj -c Release --no-restore -o /work/publish + + +- name: docker-build + image: docker + pull: if-not-exists + depends_on: + - restore-publish + commands: + - cd /work + - docker build -t test-irc:v${DRONE_BUILD_NUMBER} . + volumes: + - name: irc-test-work + path: /work + - name: dockersock + path: /var/run/docker.sock - - name: docker-deploy - image: docker - pull: if-not-exists - depends_on: - - docker-build - volumes: - - name: dockersock - path: /var/run/docker.sock - commands: - - date +%H:%M:%S - - docker rm -f test-study-container - - docker run -itd -e TZ=Asia/Shanghai -e ASPNETCORE_ENVIRONMENT=Test_Study --restart=always --name test-study-container -p 8030:80 Test_Study - - date +%H:%M:%S volumes: - - name: cached_nuget_packages + - name: nuget-packages host: - path: /mnt/d/docker_publish/nuget_packages + path: /opt/cicd/nuget/packages + - name: irc-test-work + host: + path: /opt/cicd/irc-test - name: dockersock host: path: /var/run/docker.sock trigger: branch: - - master - + - master + +--- +kind: pipeline +type: ssh +name: ssh-linux-test-irc-publish + +platform: + os: Linux + arch: 386 + +clone: + disable: true #禁用默认克隆 + +server: + host: 123.56.94.154 + user: root + password: + from_secret: test_ssh_pwd + +steps: +- name: publish-test-irc + commands: + - echo start publish test-irc-api + - cd /opt/1panel/hang/devops/test-irc + - sh test-irc.sh v${DRONE_BUILD_NUMBER} + +trigger: + branch: + - Test.IRC + --- kind: pipeline type: ssh -name: ssh-windows-test-study-publish +name: ssh-linux-test-study-publish platform: - os: windows - arch: amd64 + os: Linux + arch: 386 clone: disable: true #禁用默认克隆 server: host: 123.56.94.154 - user: Administrator - password: WHxckj2019 + user: root + password: + from_secret: test_ssh_pwd steps: -- name: publish-test-study +- name: publish-test-study commands: - #拉取代码 并停止服务 - - Start-Process "C:\CICD\Test.Study\netcore_Publish.bat" -Wait - - cd C:\CICD\Test.Study\netcore_repo - - dotnet restore .\IRaCIS.Core.API\IRaCIS.Core.API.csproj --packages C:\Users\Administrator\.nuget\packages - - dotnet publish .\IRaCIS.Core.API\IRaCIS.Core.API.csproj -c Release --no-restore --packages C:\Users\Administrator\.nuget\packages -o D:\Develop\Test_Study_PublishSite\IRaCIS.NetCore.API - - Start-Service -Name "Test_Study_API" + - echo start publish test-study-api + - cd /opt/1panel/hang/devops/test-study + - sh test-study.sh v${DRONE_BUILD_NUMBER} trigger: branch: - Test.Study - ---- - - -kind: pipeline -type: ssh -name: ssh-windows-test-irc-publish - -platform: - os: windows - arch: amd64 - -clone: - disable: true #禁用默认克隆 - -server: - host: 123.56.94.154 - user: Administrator - password: WHxckj2019 - -steps: -- name: publish-test-irc - commands: - - Start-Process "C:\CICD\Test.IRC\netcore_Publish.bat" -Wait - -trigger: - branch: - - Test.IRC \ No newline at end of file + \ No newline at end of file