Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing Details

IRC_NewDev
he 2024-08-05 13:32:17 +08:00
commit 2d8cb0c818
23 changed files with 341 additions and 88 deletions

View File

@ -45,8 +45,8 @@ namespace IRaCIS.Core.SCP
.PropertiesAutowired().AsImplementedInterfaces(); .PropertiesAutowired().AsImplementedInterfaces();
containerBuilder.RegisterType<HttpContextAccessor>().As<IHttpContextAccessor>().SingleInstance(); //containerBuilder.RegisterType<HttpContextAccessor>().As<IHttpContextAccessor>().SingleInstance();
containerBuilder.RegisterType<UserInfo>().As<IUserInfo>().InstancePerLifetimeScope(); //containerBuilder.RegisterType<UserInfo>().As<IUserInfo>().InstancePerLifetimeScope();

View File

@ -1,4 +1,6 @@
using IRaCIS.Core.Infra.EFCore; using EntityFramework.Exceptions.SqlServer;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore;
using Medallion.Threading; using Medallion.Threading;
using Medallion.Threading.SqlServer; using Medallion.Threading.SqlServer;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
@ -11,15 +13,25 @@ namespace IRaCIS.Core.SCP
{ {
public static void AddEFSetup( this IServiceCollection services, IConfiguration configuration) public static void AddEFSetup( this IServiceCollection services, IConfiguration configuration)
{ {
//services.AddScoped<DbContext, IRaCISDBContext>(); services.AddHttpContextAccessor();
services.AddScoped<IUserInfo, UserInfo>();
//这个注入没有成功--注入是没问题的构造函数也只是支持参数就好错在注入的地方不能写DbContext //这个注入没有成功--注入是没问题的构造函数也只是支持参数就好错在注入的地方不能写DbContext
//Web程序中通过重用池中DbContext实例可提高高并发场景下的吞吐量 这在概念上类似于ADO.NET Provider原生的连接池操作方式具有节省DbContext实例化成本的优点 //Web程序中通过重用池中DbContext实例可提高高并发场景下的吞吐量 这在概念上类似于ADO.NET Provider原生的连接池操作方式具有节省DbContext实例化成本的优点
services.AddDbContext<IRaCISDBContext>(options => services.AddDbContextPool<IRaCISDBContext>(options =>
{ {
// 在控制台
//public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); });
var logFactory = LoggerFactory.Create(builder => { builder.AddDebug(); });
options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value, options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value,
contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure()); contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure());
options.UseLoggerFactory(logFactory);
options.UseExceptionProcessor();
options.EnableSensitiveDataLogging(); options.EnableSensitiveDataLogging();
options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor()); options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor());
@ -30,6 +42,12 @@ namespace IRaCIS.Core.SCP
}); });
//// Register an additional context factory as a Scoped service, which gets a pooled context from the Singleton factory we registered above,
//services.AddScoped<IRaCISDBScopedFactory>();
//// Finally, arrange for a context to get injected from our Scoped factory:
//services.AddScoped(sp => sp.GetRequiredService<IRaCISDBScopedFactory>().CreateDbContext());
//注意区分 easy caching 也有 IDistributedLockProvider //注意区分 easy caching 也有 IDistributedLockProvider
services.AddSingleton<IDistributedLockProvider>(sp => services.AddSingleton<IDistributedLockProvider>(sp =>
{ {
@ -38,7 +56,6 @@ namespace IRaCIS.Core.SCP
return new SqlDistributedSynchronizationProvider(configuration.GetSection("ConnectionStrings:RemoteNew").Value); return new SqlDistributedSynchronizationProvider(configuration.GetSection("ConnectionStrings:RemoteNew").Value);
}); });
//services.AddAssemblyTriggers(typeof(SubjectVisitImageDateTrigger).Assembly);
} }
} }
} }

View File

@ -55,8 +55,8 @@ namespace IRaCIS.Core.API
containerBuilder.RegisterType<HttpContextAccessor>().As<IHttpContextAccessor>().SingleInstance(); //containerBuilder.RegisterType<HttpContextAccessor>().As<IHttpContextAccessor>().SingleInstance();
containerBuilder.RegisterType<UserInfo>().As<IUserInfo>().InstancePerLifetimeScope(); //containerBuilder.RegisterType<UserInfo>().As<IUserInfo>().InstancePerLifetimeScope();
//注册hangfire任务 依赖注入 //注册hangfire任务 依赖注入

View File

@ -1,11 +1,15 @@
using Hangfire.SqlServer; using Castle.Core.Logging;
using EntityFramework.Exceptions.SqlServer;
using Hangfire.SqlServer;
using IRaCIS.Core.Application.Triggers; using IRaCIS.Core.Application.Triggers;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore; using IRaCIS.Core.Infra.EFCore;
using Medallion.Threading; using Medallion.Threading;
using Medallion.Threading.SqlServer; using Medallion.Threading.SqlServer;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using StackExchange.Redis; using StackExchange.Redis;
namespace IRaCIS.Core.API namespace IRaCIS.Core.API
@ -14,15 +18,28 @@ namespace IRaCIS.Core.API
{ {
public static void AddEFSetup( this IServiceCollection services, IConfiguration configuration) public static void AddEFSetup( this IServiceCollection services, IConfiguration configuration)
{ {
//services.AddScoped<DbContext, IRaCISDBContext>();
services.AddHttpContextAccessor();
services.AddScoped<IUserInfo, UserInfo>();
// First, register a pooling context factory as a Singleton service, as usual:
//这个注入没有成功--注入是没问题的构造函数也只是支持参数就好错在注入的地方不能写DbContext //这个注入没有成功--注入是没问题的构造函数也只是支持参数就好错在注入的地方不能写DbContext
//Web程序中通过重用池中DbContext实例可提高高并发场景下的吞吐量 这在概念上类似于ADO.NET Provider原生的连接池操作方式具有节省DbContext实例化成本的优点 //Web程序中通过重用池中DbContext实例可提高高并发场景下的吞吐量 这在概念上类似于ADO.NET Provider原生的连接池操作方式具有节省DbContext实例化成本的优点
services.AddDbContext<IRaCISDBContext>(options => services.AddDbContext<IRaCISDBContext>(options =>
{ {
// 在控制台
//public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); });
var logFactory = LoggerFactory.Create(builder => { builder.AddDebug(); });
options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value, options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value,
contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure()); contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure());
options.UseLoggerFactory(logFactory);
options.UseExceptionProcessor();
options.EnableSensitiveDataLogging(); options.EnableSensitiveDataLogging();
options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor()); options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor());
@ -62,6 +79,12 @@ namespace IRaCIS.Core.API
}); });
// Register an additional context factory as a Scoped service, which gets a pooled context from the Singleton factory we registered above,
//services.AddScoped<IRaCISDBScopedFactory>();
//// Finally, arrange for a context to get injected from our Scoped factory:
//services.AddScoped(sp => sp.GetRequiredService<IRaCISDBScopedFactory>().CreateDbContext());
//注意区分 easy caching 也有 IDistributedLockProvider //注意区分 easy caching 也有 IDistributedLockProvider
services.AddSingleton<IDistributedLockProvider>(sp => services.AddSingleton<IDistributedLockProvider>(sp =>
{ {

View File

@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.ResponseCompression; using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using System.IO.Compression;
namespace IRaCIS.Core.API namespace IRaCIS.Core.API
{ {
@ -10,9 +11,20 @@ namespace IRaCIS.Core.API
{ {
services.AddResponseCompression(options => services.AddResponseCompression(options =>
{ {
options.EnableForHttps = true;
options.Providers.Add<BrotliCompressionProvider>(); options.Providers.Add<BrotliCompressionProvider>();
options.Providers.Add<GzipCompressionProvider>(); options.Providers.Add<GzipCompressionProvider>();
}); });
services.Configure<BrotliCompressionProviderOptions>(options =>
{
options.Level = CompressionLevel.Optimal;
});
services.Configure<GzipCompressionProviderOptions>(options =>
{
options.Level = CompressionLevel.Optimal;
});
} }
} }
} }

View File

@ -885,6 +885,16 @@
<param name="isAnonymize"></param> <param name="isAnonymize"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.ImageAndDoc.DownloadAndUploadService.GetSubejectOrVisitZipInfo(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Subject},IRaCIS.Core.Application.Contracts.SubejctZipInfoQuery)">
<summary>
受试者级别所有的影像
访视级别的影响 传递subjectVisitId
标准Id是可选的 不同标准有些检查可能有过滤
</summary>
<param name="_subjectRepository"></param>
<param name="inQuery"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ImageAndDoc.DownloadAndUploadService.PackageAndAnonymizImage(System.Guid,System.Guid,System.Boolean,System.Boolean)"> <member name="M:IRaCIS.Core.Application.Service.ImageAndDoc.DownloadAndUploadService.PackageAndAnonymizImage(System.Guid,System.Guid,System.Boolean,System.Boolean)">
<summary> <summary>
后台任务调用,前端忽略该接口 后台任务调用,前端忽略该接口
@ -5178,6 +5188,16 @@
是否是正在转化 是否是正在转化
</summary> </summary>
</member> </member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.SignConsistencyAnalysisReadingClinicalDataInDto.IsBlind">
<summary>
是否盲化
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.SignConsistencyAnalysisReadingClinicalDataInDto.IsComplete">
<summary>
是否完整
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.AddOrUpdateReadingClinicalDataDto.TrialId"> <member name="P:IRaCIS.Core.Application.Service.Reading.Dto.AddOrUpdateReadingClinicalDataDto.TrialId">
<summary> <summary>
项目ID 项目ID
@ -14148,6 +14168,20 @@
<param name="indto"></param> <param name="indto"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Application.Services.ReadingClinicalDataService.SignConsistencyAnalysisReadingClinicalData(IRaCIS.Core.Application.Service.Reading.Dto.SignConsistencyAnalysisReadingClinicalDataInDto)">
<summary>
一致性分析临床数据签名
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Application.Services.ReadingClinicalDataService.SetTaskValid(IRaCIS.Core.Application.Service.Reading.Dto.SetTaskValidInDto)">
<summary>
一致性分析临床数据签名完设置任务为有效
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Application.Services.ReadingClinicalDataService.GetReadingClinicalDataPDFList(IRaCIS.Core.Application.Service.Reading.Dto.GetReadingClinicalDataPDFListIndto)"> <member name="M:IRaCIS.Application.Services.ReadingClinicalDataService.GetReadingClinicalDataPDFList(IRaCIS.Core.Application.Service.Reading.Dto.GetReadingClinicalDataPDFListIndto)">
<summary> <summary>
获取单个阅片临床数据的所有文件 获取单个阅片临床数据的所有文件

View File

@ -201,6 +201,8 @@ namespace IRaCIS.Core.Application.ViewModel
public Guid? SourceSubjectVisitId { get; set; } public Guid? SourceSubjectVisitId { get; set; }
public Guid? SouceReadModuleId { get; set; } public Guid? SouceReadModuleId { get; set; }
public bool IsHaveFeedBack { get; set; }
//public bool IsAfterConvertedTask { get; set; } //public bool IsAfterConvertedTask { get; set; }
} }

View File

@ -254,6 +254,17 @@ namespace IRaCIS.Core.Application.Service
TaskBlindName = lastTask.TaskBlindName + "_Global", TaskBlindName = lastTask.TaskBlindName + "_Global",
TrialReadingCriterionId = trialReadingCriterionId, TrialReadingCriterionId = trialReadingCriterionId,
}; };
var afterGlobal = _visitTaskRepository.Where(t => t.SubjectId == lastTask.SubjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.TaskState == TaskState.Effect && t.ReadingCategory == ReadingCategory.Global && t.VisitTaskNum > lastTask.VisitTaskNum).ProjectTo<VisitTaskSimpleDTO>(_mapper.ConfigurationProvider).FirstOrDefault();
if (afterGlobal == null)
{
throw new BusinessValidationFailedException("联系后台排查数据,没找到后续全局");
}
else
{
existGlobal.SouceReadModuleId = afterGlobal.SouceReadModuleId;
}
} }

View File

@ -145,7 +145,7 @@ namespace IRaCIS.Core.Application.Service
.ForMember(o => o.HistoryReadingDoctorUserList, t => t.MapFrom(u => u.JudgeVisitList)); .ForMember(o => o.HistoryReadingDoctorUserList, t => t.MapFrom(u => u.JudgeVisitList));
CreateMap<VisitTask, ReadingTaskView>().IncludeBase<VisitTask, VisitTaskView>() CreateMap<VisitTask, ReadingTaskView>().IncludeBase<VisitTask, VisitTaskView>()
.ForMember(o => o.IsHaveFeedBack, t => t.MapFrom(u => u.UserFeedBackList.Any(t=>t.State==0)))
; ;
CreateMap<VisitTask, AnalysisTaskView>().IncludeBase<VisitTask, VisitTaskView>() CreateMap<VisitTask, AnalysisTaskView>().IncludeBase<VisitTask, VisitTaskView>()

View File

@ -177,9 +177,7 @@ namespace IRaCIS.Application.Services
var topicStr = string.Format(input.topicStr, companyName); var topicStr = string.Format(input.topicStr, companyName);
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
userName, userName,
_localizer[mfaType == UserMFAType.Login ? "Mail_EmailMFALoginEmail" : "Mail_EmailMFAUnlockEmail"],
verificationCode verificationCode
); );
@ -218,7 +216,6 @@ namespace IRaCIS.Application.Services
userName, userName,
//---您正在进行邮箱重置操作 //---您正在进行邮箱重置操作
_localizer["Mail_ResettingEmail"],
verificationCode verificationCode
); );
@ -258,7 +255,6 @@ namespace IRaCIS.Application.Services
"Sir/Madam", "Sir/Madam",
//---您正在进行邮箱重置密码操作 //---您正在进行邮箱重置密码操作
_localizer["Mail_ResettingPassword"],
verificationCode verificationCode
); );
@ -302,7 +298,7 @@ namespace IRaCIS.Application.Services
"Sir/Madam", "Sir/Madam",
//---您正在参与展影医疗IRC项目 //---您正在参与展影医疗IRC项目
_localizer["Mail_IRCProject", companyName], companyName,
verificationCode verificationCode
); );
@ -344,7 +340,7 @@ namespace IRaCIS.Application.Services
"Sir/Madam", "Sir/Madam",
//---您正在参与展影医疗IRC项目中心调研工作 //---您正在参与展影医疗IRC项目中心调研工作
_localizer["Mail_CenterResearchReminder", companyName], companyName,
verificationCode verificationCode
); );

View File

@ -214,6 +214,20 @@ namespace IRaCIS.Core.Application.Contracts
public int FileCount { get; set; } public int FileCount { get; set; }
} }
public class SubejctZipInfoQuery
{
public Guid? SubejctId { get; set; }
public string? SubjectCode { get; set; }
public Guid? SubejectVisitId { get; set; }
public Guid? TrialReadingCriterionId { get; set; }
}
public class TaskArchiveStudyCommand public class TaskArchiveStudyCommand
{ {
[NotDefault] [NotDefault]

View File

@ -4,6 +4,7 @@ using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Filter; using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.Service.ImageAndDoc.DTO; using IRaCIS.Core.Application.Service.ImageAndDoc.DTO;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Infrastructure.Extention; using IRaCIS.Core.Infrastructure.Extention;
@ -11,6 +12,7 @@ using MassTransit;
using MathNet.Numerics; using MathNet.Numerics;
using Medallion.Threading; using Medallion.Threading;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
using Newtonsoft.Json; using Newtonsoft.Json;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -536,15 +538,43 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
public async Task<IResponseOutput> GetSubejectVisitPathInfo(Guid subjectVisitId) /// <summary>
/// 受试者级别所有的影像
/// 访视级别的影响 传递subjectVisitId
/// 标准Id是可选的 不同标准有些检查可能有过滤
/// </summary>
/// <param name="_subjectRepository"></param>
/// <param name="inQuery"></param>
/// <returns></returns>
public async Task<IResponseOutput> GetSubejectOrVisitZipInfo([FromServices] IRepository<Subject> _subjectRepository, SubejctZipInfoQuery inQuery)
{ {
var query = from sv in _subjectVisitRepository.Where(t => t.Id == subjectVisitId) var isImageFilter = false;
var criterionModalitys = string.Empty;
if (inQuery.TrialReadingCriterionId != null)
{
var criterionInfo = await _repository.Where<ReadingQuestionCriterionTrial>(t => t.Id == inQuery.TrialReadingCriterionId).Select(t => new { t.IsImageFilter, t.CriterionModalitys }).FirstOrDefaultAsync();
if (criterionInfo != null)
{
isImageFilter = criterionInfo.IsImageFilter;
criterionModalitys = criterionInfo.CriterionModalitys;
}
}
if (inQuery.SubejectVisitId != null)
{
var query = from sv in _subjectVisitRepository.Where(t => t.Id == inQuery.SubejectVisitId)
select new select new
{ {
SubjectCode = sv.Subject.Code, SubjectCode = sv.Subject.Code,
VisitName = sv.VisitName, VisitName = sv.VisitName,
StudyList = sv.StudyList.Select(u => new StudyList = sv.StudyList.AsQueryable().WhereIf(isImageFilter, t => ("|" + criterionModalitys + "|").Contains("|" + t.ModalityForEdit + "|"))
.Select(u => new
{ {
u.PatientId, u.PatientId,
u.StudyTime, u.StudyTime,
@ -560,12 +590,82 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
}) })
}) })
}),
NoneDicomStudyList = sv.NoneDicomStudyList.AsQueryable().WhereIf(isImageFilter, t => ("|" + criterionModalitys + "|").Contains("|" + t.Modality + "|"))
.Select(nd => new
{
nd.Modality,
nd.StudyCode,
nd.ImageDate,
FileList = nd.NoneDicomFileList.Select(file => new
{
file.FileName,
file.Path,
file.FileType
})
}) })
}; };
var info = query.FirstOrDefault(); var result = query.ToList();
return ResponseOutput.Ok(result);
}
else if (inQuery.SubejctId != null)
{
var query = from sv in _subjectRepository.Where(t => t.Id == inQuery.SubejctId).SelectMany(t=>t.SubjectVisitList)
select new
{
SubjectCode = sv.Subject.Code,
VisitName = sv.VisitName,
StudyList = sv.StudyList.AsQueryable().WhereIf(isImageFilter, t => ("|" + criterionModalitys + "|").Contains("|" + t.ModalityForEdit + "|"))
.Select(u => new
{
u.PatientId,
u.StudyTime,
u.StudyCode,
SeriesList = u.SeriesList.Select(z => new
{
z.Modality,
InstancePathList = z.DicomInstanceList.Select(k => new
{
k.Path
})
})
}),
NoneDicomStudyList = sv.NoneDicomStudyList.AsQueryable().WhereIf(isImageFilter, t => ("|" + criterionModalitys + "|").Contains("|" + t.Modality + "|"))
.Select(nd => new
{
nd.Modality,
nd.StudyCode,
nd.ImageDate,
FileList = nd.NoneDicomFileList.Select(file => new
{
file.FileName,
file.Path,
file.FileType
})
})
};
var result = query.ToList();
return ResponseOutput.Ok(result);
}
else
{
return ResponseOutput.NotOk("不允许 subjectId subjectId 都不传递");
}
return ResponseOutput.Ok(info);
} }
/// <summary> /// <summary>

View File

@ -67,6 +67,8 @@ namespace IRaCIS.Core.Application.ViewModel
public DateTime? EndCreatime { get; set; } public DateTime? EndCreatime { get; set; }
public Guid? TrialId { get; set; }
} }

View File

@ -36,6 +36,7 @@ namespace IRaCIS.Core.Application.Service
var userFeedBackQueryable = _userFeedBackRepository var userFeedBackQueryable = _userFeedBackRepository
.WhereIf(isCRCOrIR, t => t.CreateUserId == _userInfo.Id) .WhereIf(isCRCOrIR, t => t.CreateUserId == _userInfo.Id)
.WhereIf(inQuery.State != null, t => t.State == inQuery.State) .WhereIf(inQuery.State != null, t => t.State == inQuery.State)
.WhereIf(inQuery.TrialId != null, t => t.TrialId == inQuery.TrialId)
.WhereIf(inQuery.QuestionType != null, t => t.QuestionType == inQuery.QuestionType) .WhereIf(inQuery.QuestionType != null, t => t.QuestionType == inQuery.QuestionType)
.WhereIf(inQuery.BeginCreatime != null, t => t.CreateTime >= inQuery.BeginCreatime) .WhereIf(inQuery.BeginCreatime != null, t => t.CreateTime >= inQuery.BeginCreatime)

View File

@ -62,6 +62,10 @@ namespace IRaCIS.Core.Application.Contracts
//public string VisitPlanInfo { get; set; } = String.Empty; //public string VisitPlanInfo { get; set; } = String.Empty;
public Guid? HandleUserId { get; set; } public Guid? HandleUserId { get; set; }
public DateTime? BeginAuditTime { get; set; }
public DateTime? EndAuditTime { get; set; }
} }
public class GetNextIQCQualityInDto public class GetNextIQCQualityInDto
@ -187,6 +191,13 @@ namespace IRaCIS.Core.Application.Contracts
public string SubmitUserName { get; set; } public string SubmitUserName { get; set; }
public TrialQCProcess QCProcessEnum { get; set; }
public DateTime? ReviewAuditTime { get; set; }
public DateTime? PreliminaryAuditTime { get; set; }
public DateTime? AuditTime => QCProcessEnum == TrialQCProcess.SingleAudit ? PreliminaryAuditTime : (QCProcessEnum == TrialQCProcess.DoubleAudit ? ReviewAuditTime : null);
} }
@ -1110,6 +1121,9 @@ namespace IRaCIS.Core.Application.Contracts
public bool IsHaveUploadFailed { get; set; } public bool IsHaveUploadFailed { get; set; }
} }
public class GetNextCRCChallengeInDto public class GetNextCRCChallengeInDto
@ -1415,8 +1429,7 @@ namespace IRaCIS.Core.Application.Contracts
public string ReviewAuditUserName { get; set; } = String.Empty; public string ReviewAuditUserName { get; set; } = String.Empty;
public DateTime? ReviewAuditTime { get; set; }
public DateTime? PreliminaryAuditTime { get; set; }
public bool IsEnrollmentConfirm { get; set; } = false; public bool IsEnrollmentConfirm { get; set; } = false;
public DateTime? SubjectFirstGiveMedicineTime { get; set; } public DateTime? SubjectFirstGiveMedicineTime { get; set; }
@ -1491,6 +1504,12 @@ namespace IRaCIS.Core.Application.Contracts
public PackState PackState { get; set; } public PackState PackState { get; set; }
//public Guid? ClinicalDataSignUserId { get; set; } //public Guid? ClinicalDataSignUserId { get; set; }
public DateTime? ReviewAuditTime { get; set; }
public DateTime? PreliminaryAuditTime { get; set; }
public DateTime? AuditTime => QCProcessEnum == TrialQCProcess.SingleAudit ? PreliminaryAuditTime : (QCProcessEnum == TrialQCProcess.DoubleAudit ? ReviewAuditTime : null);
} }

View File

@ -235,7 +235,7 @@ namespace IRaCIS.Core.Application.Image.QA
PageSize = 1, PageSize = 1,
}); });
return result.Item1.CurrentPageData.Count > 0 ? result.Item1.CurrentPageData[0] : null; return result.Data.CurrentPageData.Count > 0 ? result.Data.CurrentPageData[0] : null;
} }
/// <summary> /// <summary>
@ -244,7 +244,7 @@ namespace IRaCIS.Core.Application.Image.QA
/// <param name="visitSearchDTO"></param> /// <param name="visitSearchDTO"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost] [HttpPost]
public async Task<(PageOutput<QCVisitViewModel>, TrialSubjectAndSVConfig)> GetQCVisitList(QCVisitSearchDTO visitSearchDTO) public async Task<IResponseOutput<PageOutput<QCVisitViewModel>>> GetQCVisitList(QCVisitSearchDTO visitSearchDTO)
{ {
var svExpression = QCCommon.GetSubjectVisitFilter(visitSearchDTO.VisitPlanArray); var svExpression = QCCommon.GetSubjectVisitFilter(visitSearchDTO.VisitPlanArray);
@ -266,6 +266,12 @@ namespace IRaCIS.Core.Application.Image.QA
|| t.QCChallengeDialogList.Any(t => t.CreateUserId == visitSearchDTO.HandleUserId)) || t.QCChallengeDialogList.Any(t => t.CreateUserId == visitSearchDTO.HandleUserId))
.WhereIf(visitSearchDTO.IsUrgent != null, t => t.IsUrgent == visitSearchDTO.IsUrgent) .WhereIf(visitSearchDTO.IsUrgent != null, t => t.IsUrgent == visitSearchDTO.IsUrgent)
.Where(t => t.SubmitState != SubmitStateEnum.None) .Where(t => t.SubmitState != SubmitStateEnum.None)
.WhereIf(visitSearchDTO.BeginAuditTime != null, t => t.Trial.QCProcessEnum==TrialQCProcess.SingleAudit? t.PreliminaryAuditTime>= visitSearchDTO.BeginAuditTime:
(t.Trial.QCProcessEnum == TrialQCProcess.DoubleAudit?t.ReviewAuditTime>= visitSearchDTO.BeginAuditTime:true))
.WhereIf(visitSearchDTO.EndAuditTime != null, t => t.Trial.QCProcessEnum == TrialQCProcess.SingleAudit ? t.PreliminaryAuditTime <= visitSearchDTO.EndAuditTime :
(t.Trial.QCProcessEnum == TrialQCProcess.DoubleAudit ? t.ReviewAuditTime <= visitSearchDTO.EndAuditTime : true))
//.WhereIf(visitSearchDTO.SubmitState != null, t => t.SubmitState == visitSearchDTO.SubmitState) //.WhereIf(visitSearchDTO.SubmitState != null, t => t.SubmitState == visitSearchDTO.SubmitState)
//.WhereIf(visitSearchDTO.ChallengeState != null, t => t.ChallengeState == visitSearchDTO.ChallengeState) //.WhereIf(visitSearchDTO.ChallengeState != null, t => t.ChallengeState == visitSearchDTO.ChallengeState)
.ProjectTo<QCVisitViewModel>(_mapper.ConfigurationProvider); .ProjectTo<QCVisitViewModel>(_mapper.ConfigurationProvider);
@ -279,7 +285,7 @@ namespace IRaCIS.Core.Application.Image.QA
var config = await _repository.Where<Trial>(t => t.Id == visitSearchDTO.TrialId).ProjectTo<TrialSubjectAndSVConfig>(_mapper.ConfigurationProvider).FirstOrDefaultAsync().IfNullThrowException(); var config = await _repository.Where<Trial>(t => t.Id == visitSearchDTO.TrialId).ProjectTo<TrialSubjectAndSVConfig>(_mapper.ConfigurationProvider).FirstOrDefaultAsync().IfNullThrowException();
return (pageList, config); return ResponseOutput.Ok (pageList, config);
} }

View File

@ -707,7 +707,7 @@ namespace IRaCIS.Core.Application.Image.QA
} }
else else
{ {
if (await _subjectVisitRepository.AnyAsync(t => t.Id == updateModalityCommand.SubjectVisitId && t.SubmitState == SubmitStateEnum.Submitted)) if (await _subjectVisitRepository.AnyAsync(t => t.Id == updateModalityCommand.SubjectVisitId && t.SubmitState == SubmitStateEnum.Submitted && !t.QCChallengeList.Any(c=>c.ReuploadEnum==QCChanllengeReuploadEnum.QCAgreeUpload)) )
{ {
//---提交之后,不允许修改! //---提交之后,不允许修改!
throw new BusinessValidationFailedException(_localizer["QCOperation_NoModifyAfterSubmit"]); throw new BusinessValidationFailedException(_localizer["QCOperation_NoModifyAfterSubmit"]);

View File

@ -22,6 +22,7 @@ namespace IRaCIS.Core.Application.Service
CreateMap<Trial, ExcelExportInfo>(); CreateMap<Trial, ExcelExportInfo>();
CreateMap<SubjectVisit, CRCVisitExportDTO>() CreateMap<SubjectVisit, CRCVisitExportDTO>()
.ForMember(d => d.TrialSiteCode, u => u.MapFrom(s => s.TrialSite.TrialSiteCode)) .ForMember(d => d.TrialSiteCode, u => u.MapFrom(s => s.TrialSite.TrialSiteCode))
.ForMember(d => d.QCProcessEnum, u => u.MapFrom(s => s.Trial.QCProcessEnum))
.ForMember(d => d.SubjectCode, u => u.MapFrom(s => s.Subject.Code)) .ForMember(d => d.SubjectCode, u => u.MapFrom(s => s.Subject.Code))
.ForMember(d => d.SubmitUserName, u => u.MapFrom(s => s.SubmitUser.FullName)) .ForMember(d => d.SubmitUserName, u => u.MapFrom(s => s.SubmitUser.FullName))

View File

@ -159,6 +159,7 @@ namespace IRaCIS.Application.Contracts
//public int? StudyCount { get; set; } = 0; //public int? StudyCount { get; set; } = 0;
//public int? SiteCount { get; set; } = 0; //public int? SiteCount { get; set; } = 0;
public int? UserFeedBackUnDealedCount { get; set; }
} }

View File

@ -77,6 +77,9 @@ namespace IRaCIS.Core.Application.Service
.ForMember(d => d.ReviewMode, u => u.MapFrom(s => isEn_Us ? s.ReviewMode.Value : s.ReviewMode.ValueCN)) .ForMember(d => d.ReviewMode, u => u.MapFrom(s => isEn_Us ? s.ReviewMode.Value : s.ReviewMode.ValueCN))
//.ForMember(d => d.ReviewType, u => u.MapFrom(s => s.ReviewType.Value)) //.ForMember(d => d.ReviewType, u => u.MapFrom(s => s.ReviewType.Value))
.ForMember(d => d.IsLocked, u => u.MapFrom(s => s.WorkloadList.Any(u => u.DataFrom == (int)WorkLoadFromStatus.FinalConfirm))) .ForMember(d => d.IsLocked, u => u.MapFrom(s => s.WorkloadList.Any(u => u.DataFrom == (int)WorkLoadFromStatus.FinalConfirm)))
.ForMember(d => d.UserFeedBackUnDealedCount, u => u.MapFrom(s => s.UserFeedBackList.Count(t=>t.State==0)))
//.ForMember(d => d.SiteCount, u => u.MapFrom(s => userTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator ? s.TrialSiteUserList.Count(k => k.UserId == userId) : s.TrialSiteList.Count())) //.ForMember(d => d.SiteCount, u => u.MapFrom(s => userTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator ? s.TrialSiteUserList.Count(k => k.UserId == userId) : s.TrialSiteList.Count()))
//.ForMember(d => d.StudyCount, u => u.MapFrom(s => userTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator ? s.StudyList.Count(t => t.TrialSite.CRCUserList.Any(t => t.UserId == userId)) : s.StudyList.Count())) //.ForMember(d => d.StudyCount, u => u.MapFrom(s => userTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator ? s.StudyList.Count(t => t.TrialSite.CRCUserList.Any(t => t.UserId == userId)) : s.StudyList.Count()))
//.ForMember(d => d.SubjectCount, u => u.MapFrom(s => userTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator ? s.SubjectList.Count(t => t.TrialSite.CRCUserList.Any(t => t.UserId == userId)) : s.SubjectList.Count())) //.ForMember(d => d.SubjectCount, u => u.MapFrom(s => userTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator ? s.SubjectList.Count(t => t.TrialSite.CRCUserList.Any(t => t.UserId == userId)) : s.SubjectList.Count()))

View File

@ -436,5 +436,8 @@ namespace IRaCIS.Core.Domain.Models
public int ImageStudyState { get; set; } public int ImageStudyState { get; set; }
[JsonIgnore]
public List<UserFeedBack> UserFeedBackList { get; set; }
} }
} }

View File

@ -59,8 +59,8 @@ namespace IRaCIS.Core.Domain.Models
public List<TrialSiteUser> TrialSiteUserList { get; set; } = new List<TrialSiteUser>(); public List<TrialSiteUser> TrialSiteUserList { get; set; } = new List<TrialSiteUser>();
[JsonIgnore] [JsonIgnore]
public List<ReadModule> ReadModuleList { get; set; } = new List<ReadModule>(); public List<ReadModule> ReadModuleList { get; set; } = new List<ReadModule>();
[JsonIgnore]
public List<UserFeedBack> UserFeedBackList { get; set; } = new List<UserFeedBack>();
public Guid IndicationTypeId { get; set; } = Guid.Empty; public Guid IndicationTypeId { get; set; } = Guid.Empty;
public Guid? PhaseId { get; set; } = Guid.Empty; public Guid? PhaseId { get; set; } = Guid.Empty;

View File

@ -24,33 +24,41 @@ using IRaCIS.Core.Infrastructure;
namespace IRaCIS.Core.Infra.EFCore namespace IRaCIS.Core.Infra.EFCore
{ {
/// <summary>
/// 报错添加subject 报错,重复添加访视
/// </summary>
//public class IRaCISDBScopedFactory : IDbContextFactory<IRaCISDBContext>
//{
// private readonly IDbContextFactory<IRaCISDBContext> _pooledFactory;
// private readonly IUserInfo _userInfo;
// public IRaCISDBScopedFactory(IDbContextFactory<IRaCISDBContext> pooledFactory,IUserInfo userInfo)
// {
// _pooledFactory = pooledFactory;
// _userInfo = userInfo;
// }
// public IRaCISDBContext CreateDbContext()
// {
// var context = _pooledFactory.CreateDbContext();
// context._userInfo = _userInfo;
// return context;
// }
//}
public class IRaCISDBContext : DbContext public class IRaCISDBContext : DbContext
{ {
public readonly IUserInfo _userInfo; private IUserInfo _userInfo;
public readonly ILogger<IRaCISDBContext> _logger; private readonly ILogger<IRaCISDBContext> _logger;
// 在控制台
//public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); });
// 调试窗口
public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddDebug(); });
public IRaCISDBContext(DbContextOptions<IRaCISDBContext> options, IUserInfo userInfo, ILogger<IRaCISDBContext> logger public IRaCISDBContext(DbContextOptions<IRaCISDBContext> options, IUserInfo userInfo, ILogger<IRaCISDBContext> logger
) : base(options) ) : base(options)
{ {
_logger= logger;
_userInfo= userInfo; _userInfo= userInfo;
_logger = logger;
}
//比数据库上下文构造函数先执行 不能构造函数注入的方式使用配置文件
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseLoggerFactory(MyLoggerFactory);
optionsBuilder.UseExceptionProcessor();
} }