diff --git a/IRaCIS.Core.API/Controllers/ExtraController.cs b/IRaCIS.Core.API/Controllers/ExtraController.cs
index 7a3b3504d..7e8c111be 100644
--- a/IRaCIS.Core.API/Controllers/ExtraController.cs
+++ b/IRaCIS.Core.API/Controllers/ExtraController.cs
@@ -30,6 +30,8 @@ using IRaCIS.Core.Application.Helper;
using Microsoft.Extensions.Options;
using IRaCIS.Core.Application.Contracts;
using LoginReturnDTO = IRaCIS.Application.Contracts.LoginReturnDTO;
+using DocumentFormat.OpenXml.Spreadsheet;
+using AutoMapper.QueryableExtensions;
namespace IRaCIS.Api.Controllers
{
@@ -53,8 +55,8 @@ namespace IRaCIS.Api.Controllers
///
///
[HttpGet, Route("doctor/getDetail/{doctorId:guid}")]
-
- public async Task> GetDoctorDetail([FromServices] IAttachmentService attachmentService, [FromServices] IDoctorService _doctorService,
+
+ public async Task> GetDoctorDetail([FromServices] IAttachmentService attachmentService, [FromServices] IDoctorService _doctorService,
[FromServices] IEducationService _educationService, [FromServices] ITrialExperienceService _trialExperienceService,
[FromServices] IResearchPublicationService _researchPublicationService, [FromServices] IVacationService _vacationService, Guid doctorId)
@@ -66,7 +68,7 @@ namespace IRaCIS.Api.Controllers
var doctorDetail = new DoctorDetailDTO
{
- AuditView =await _doctorService.GetAuditState(doctorId),
+ AuditView = await _doctorService.GetAuditState(doctorId),
BasicInfoView = await _doctorService.GetBasicInfo(doctorId),
EmploymentView = await _doctorService.GetEmploymentInfo(doctorId),
AttachmentList = await attachmentService.GetAttachments(doctorId),
@@ -77,7 +79,7 @@ namespace IRaCIS.Api.Controllers
TrialExperienceView = await _trialExperienceService.GetTrialExperience(doctorId),
ResearchPublicationView = await _researchPublicationService.GetResearchPublication(doctorId),
- SpecialtyView =await _doctorService.GetSpecialtyInfo(doctorId),
+ SpecialtyView = await _doctorService.GetSpecialtyInfo(doctorId),
InHoliday = (await _vacationService.OnVacation(doctorId)).IsSuccess,
IntoGroupInfo = _doctorService.GetDoctorIntoGroupInfo(doctorId),
SowList = sowList,
@@ -96,80 +98,31 @@ namespace IRaCIS.Api.Controllers
/// 系统用户登录接口[New]
[HttpPost, Route("user/login")]
[AllowAnonymous]
- public async Task> Login(UserLoginDTO loginUser, [FromServices] IEasyCachingProvider provider, [FromServices] IUserService _userService,
- [FromServices] ITokenService _tokenService,
-
- [FromServices] IReadingImageTaskService readingImageTaskService,
- [FromServices] IConfiguration configuration)
+ public async Task Login(UserLoginDTO loginUser,
+ [FromServices] IEasyCachingProvider provider,
+ [FromServices] IUserService _userService,
+ [FromServices] ITokenService _tokenService,
+ [FromServices] IReadingImageTaskService readingImageTaskService,
+ IOptionsMonitor _verifyConfig,
+ IMailVerificationService _mailVerificationService)
{
-
- var returnModel = await _userService.Login(loginUser.UserName, loginUser.Password);
-
- if (returnModel.IsSuccess)
+ //MFA 邮箱验证 前端传递用户Id 和MFACode
+ if (loginUser.UserId != null && _verifyConfig.CurrentValue.OpenLoginMFA)
{
- #region GRPC 调用鉴权中心,因为服务器IIS问题 http/2 故而没法使用
+ Guid userId = (Guid)loginUser.UserId;
- ////重试策略
- //var defaultMethodConfig = new MethodConfig
- //{
- // Names = { MethodName.Default },
- // RetryPolicy = new RetryPolicy
- // {
- // MaxAttempts = 3,
- // InitialBackoff = TimeSpan.FromSeconds(1),
- // MaxBackoff = TimeSpan.FromSeconds(5),
- // BackoffMultiplier = 1.5,
- // RetryableStatusCodes = { Grpc.Core.StatusCode.Unavailable }
- // }
- //};
+ //验证MFA 编码是否有问题 ,前端要拆开,自己调用验证的逻辑
+ //await _userService.VerifyMFACodeAsync(userId, loginUser.MFACode);
- //#region unable to trust the certificate then the gRPC client can be configured to ignore the invalid certificate
+ //var loginUser = await _userRepository.Where(u => u.UserName.Equals(userName) && u.Password == password).ProjectTo(_mapper.ConfigurationProvider).FirstOrDefaultAsync();
- //var httpHandler = new HttpClientHandler();
- //// Return `true` to allow certificates that are untrusted/invalid
- //httpHandler.ServerCertificateCustomValidationCallback =
- // HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
+ var basicInfo = await _userService.GetUserBasicInfo(userId, loginUser.Password);
+ var loginReturn = new LoginReturnDTO() { BasicInfo = basicInfo };
- //////这一句是让grpc支持本地 http 如果本地访问部署在服务器上,那么是访问不成功的
- //AppContext.SetSwitch(
- // "System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
+ loginReturn.JWTStr = _tokenService.GetToken(IRaCISClaims.Create(loginReturn.BasicInfo));
- //#endregion
-
-
-
- //var grpcAdress = configuration.GetValue("GrpcAddress");
- ////var grpcAdress = "http://localhost:7200";
-
- //var channel = GrpcChannel.ForAddress(grpcAdress, new GrpcChannelOptions
- //{
- // HttpHandler = httpHandler,
- // ServiceConfig = new ServiceConfig { MethodConfigs = { defaultMethodConfig } }
-
- //});
- ////var channel = GrpcChannel.ForAddress(grpcAdress);
- //var grpcClient = new TokenGrpcService.TokenGrpcServiceClient(channel);
-
- //var userInfo = returnModel.Data.BasicInfo;
-
- //var tokenResponse = grpcClient.GetUserToken(new GetTokenReuqest()
- //{
- // Id = userInfo.Id.ToString(),
- // ReviewerCode = userInfo.ReviewerCode,
- // IsAdmin = userInfo.IsAdmin,
- // RealName = userInfo.RealName,
- // UserTypeEnumInt = (int)userInfo.UserTypeEnum,
- // UserTypeShortName = userInfo.UserTypeShortName,
- // UserName = userInfo.UserName
- //});
-
- //returnModel.Data.JWTStr = tokenResponse.Token;
-
- #endregion
-
- returnModel.Data.JWTStr = _tokenService.GetToken(IRaCISClaims.Create(returnModel.Data.BasicInfo));
// 创建一个 CookieOptions 对象,用于设置 Cookie 的属性
var option = new CookieOptions
@@ -180,20 +133,161 @@ namespace IRaCIS.Api.Controllers
Secure = false // 确保 cookie 只能通过 HTTPS 访问
};
- HttpContext.Response.Cookies.Append("access_token", returnModel.Data.JWTStr, option);
+ HttpContext.Response.Cookies.Append("access_token", loginReturn.JWTStr, option);
+
+ // 验证阅片休息时间
+ await readingImageTaskService.ResetReadingRestTime(userId);
+
+ await provider.SetAsync(userId.ToString(), loginReturn.JWTStr, TimeSpan.FromDays(7));
+
+ await provider.SetAsync($"{userId.ToString()}_Online", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(_verifyConfig.CurrentValue.AutoLoginOutMinutes));
+
+ return ResponseOutput.Ok(loginReturn);
+
+ }
+ else
+ {
+ var returnModel = await _userService.Login(loginUser.UserName, loginUser.Password);
+
+ if (returnModel.IsSuccess)
+ {
+ #region GRPC 调用鉴权中心,因为服务器IIS问题 http/2 故而没法使用
+
+ ////重试策略
+ //var defaultMethodConfig = new MethodConfig
+ //{
+ // Names = { MethodName.Default },
+ // RetryPolicy = new RetryPolicy
+ // {
+ // MaxAttempts = 3,
+ // InitialBackoff = TimeSpan.FromSeconds(1),
+ // MaxBackoff = TimeSpan.FromSeconds(5),
+ // BackoffMultiplier = 1.5,
+ // RetryableStatusCodes = { Grpc.Core.StatusCode.Unavailable }
+ // }
+ //};
+
+ //#region unable to trust the certificate then the gRPC client can be configured to ignore the invalid certificate
+
+ //var httpHandler = new HttpClientHandler();
+ //// Return `true` to allow certificates that are untrusted/invalid
+ //httpHandler.ServerCertificateCustomValidationCallback =
+ // HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
+
+
+ //////这一句是让grpc支持本地 http 如果本地访问部署在服务器上,那么是访问不成功的
+ //AppContext.SetSwitch(
+ // "System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
+
+ //#endregion
+
+
+
+ //var grpcAdress = configuration.GetValue("GrpcAddress");
+ ////var grpcAdress = "http://localhost:7200";
+
+ //var channel = GrpcChannel.ForAddress(grpcAdress, new GrpcChannelOptions
+ //{
+ // HttpHandler = httpHandler,
+ // ServiceConfig = new ServiceConfig { MethodConfigs = { defaultMethodConfig } }
+
+ //});
+ ////var channel = GrpcChannel.ForAddress(grpcAdress);
+ //var grpcClient = new TokenGrpcService.TokenGrpcServiceClient(channel);
+
+ //var userInfo = returnModel.Data.BasicInfo;
+
+ //var tokenResponse = grpcClient.GetUserToken(new GetTokenReuqest()
+ //{
+ // Id = userInfo.Id.ToString(),
+ // ReviewerCode = userInfo.ReviewerCode,
+ // IsAdmin = userInfo.IsAdmin,
+ // RealName = userInfo.RealName,
+ // UserTypeEnumInt = (int)userInfo.UserTypeEnum,
+ // UserTypeShortName = userInfo.UserTypeShortName,
+ // UserName = userInfo.UserName
+ //});
+
+ //returnModel.Data.JWTStr = tokenResponse.Token;
+
+ #endregion
+
+ var userId = returnModel.Data.BasicInfo.Id;
+
+ if (_verifyConfig.CurrentValue.OpenLoginMFA)
+ {
+ //发版屏蔽
+
+ returnModel.Data.JWTStr = _tokenService.GetToken(IRaCISClaims.Create(returnModel.Data.BasicInfo));
+
+ //MFA 发送邮件
+
+ returnModel.Data.IsMFA = true;
+
+ var email = returnModel.Data.BasicInfo.EMail;
+
+ #region 隐藏Email
+ // 找到 "@" 符号的位置
+ int atIndex = email.IndexOf('@');
+
+ // 替换 "@" 符号前的中间两位为星号
+ string visiblePart = email.Substring(0, atIndex);
+
+ int startIndex = (visiblePart.Length - 2) / 2;
+
+ // 替换中间两位字符为星号
+ string hiddenPartBeforeAt = visiblePart.Substring(0, startIndex) + "**" + visiblePart.Substring(startIndex + 2);
+
+ string afterAt = email.Substring(atIndex + 1);
+
+ // 组合隐藏和可见部分
+ string hiddenEmail = hiddenPartBeforeAt + "@" + afterAt;
+ #endregion
+
+ returnModel.Data.BasicInfo.EMail = hiddenEmail;
+
+ await _userService.SendMFAEmail(userId);
+
+ }
+ else
+ {
+ returnModel.Data.JWTStr = _tokenService.GetToken(IRaCISClaims.Create(returnModel.Data.BasicInfo));
+
+ // 创建一个 CookieOptions 对象,用于设置 Cookie 的属性
+ var option = new CookieOptions
+ {
+ Expires = DateTime.Now.AddMonths(1), // 设置过期时间为 30 分钟之后
+ HttpOnly = false, // 确保 cookie 只能通过 HTTP 访问
+ SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None, // 设置 SameSite 属性
+ Secure = false // 确保 cookie 只能通过 HTTPS 访问
+ };
+
+ HttpContext.Response.Cookies.Append("access_token", returnModel.Data.JWTStr, option);
+
+
+
+ // 验证阅片休息时间
+ await readingImageTaskService.ResetReadingRestTime(returnModel.Data.BasicInfo.Id);
+
+ await provider.SetAsync(userId.ToString(), returnModel.Data.JWTStr, TimeSpan.FromDays(7));
+
+ await provider.SetAsync($"{userId.ToString()}_Online", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(_verifyConfig.CurrentValue.AutoLoginOutMinutes));
+ }
+
+ }
+ return returnModel;
}
- var userId = returnModel.Data.BasicInfo.Id.ToString();
- //provider.Set(userId, userId, TimeSpan.FromMinutes(AppSettings.LoginExpiredTimeSpan));
- // 验证阅片休息时间
- await readingImageTaskService.ResetReadingRestTime(returnModel.Data.BasicInfo.Id);
- await provider.SetAsync(userId.ToString(), returnModel.Data.JWTStr, TimeSpan.FromDays(7));
- return returnModel;
+
+
+
}
+
+
[HttpGet, Route("imageShare/ShareImage")]
[AllowAnonymous]
public IResponseOutput ShareImage([FromServices] ITokenService _tokenService)
@@ -223,7 +317,7 @@ namespace IRaCIS.Api.Controllers
var ossOptions = serviceOption.AliyunOSS;
- return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse = serviceOption.ObjectStoreUse, MinIO = serviceOption.MinIO ,AliyunOSS= serviceOption.AliyunOSS,AWS=serviceOption.AWS });
+ 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);
@@ -264,19 +358,19 @@ namespace IRaCIS.Api.Controllers
#endregion
}
- else if(Enum.TryParse(serviceOption.ObjectStoreUse, out var parsedValue) && parsedValue == ObjectStoreUse.MinIO)
+ 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 });
+ 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 )
+ [HttpGet("user/GenerateSTS")]
+ public IResponseOutput GenerateSTS([FromServices] IOptionsMonitor options)
{
var ossOptions = options.CurrentValue;
@@ -304,9 +398,9 @@ namespace IRaCIS.Api.Controllers
SecurityToken = response.Credentials.SecurityToken,
Expiration = response.Credentials.Expiration,
- Region = ossOptions.region ,
- BucketName = ossOptions.bucketName ,
- ViewEndpoint = ossOptions.viewEndpoint ,
+ Region = ossOptions.region,
+ BucketName = ossOptions.bucketName,
+ ViewEndpoint = ossOptions.viewEndpoint,
};
@@ -318,12 +412,12 @@ namespace IRaCIS.Api.Controllers
[HttpGet("User/UserRedirect")]
[AllowAnonymous]
- public async Task UserRedirect([FromServices] IRepository _userRepository, string url ,[FromServices]ILogger _logger)
+ public async Task UserRedirect([FromServices] IRepository _userRepository, string url, [FromServices] ILogger _logger)
{
var decodeUrl = System.Web.HttpUtility.UrlDecode(url);
- var userId = decodeUrl.Substring(decodeUrl.IndexOf("UserId=") + "UserId=".Length , 36) ;
+ var userId = decodeUrl.Substring(decodeUrl.IndexOf("UserId=") + "UserId=".Length, 36);
var token = decodeUrl.Substring(decodeUrl.IndexOf("access_token=") + "access_token=".Length);
@@ -331,12 +425,12 @@ namespace IRaCIS.Api.Controllers
var domainStrList = decodeUrl.Split("/").ToList().Take(3).ToList();
- var errorUrl = domainStrList[0]+"//"+ domainStrList[2]+ "/error";
+ var errorUrl = domainStrList[0] + "//" + domainStrList[2] + "/error";
- if (!await _userRepository.AnyAsync(t => t.Id == Guid.Parse(userId) && t.EmailToken == token && t.IsFirstAdd))
+ if (!await _userRepository.AnyAsync(t => t.Id == Guid.Parse(userId) && t.EmailToken == token && t.IsFirstAdd))
{
- decodeUrl = errorUrl+ $"?lang={lang}&ErrorMessage={System.Web.HttpUtility.UrlEncode(lang=="zh"? "您的初始化链接已过期": "Error!The initialization link has expired. Return")} ";
+ decodeUrl = errorUrl + $"?lang={lang}&ErrorMessage={System.Web.HttpUtility.UrlEncode(lang == "zh" ? "您的初始化链接已过期" : "Error!The initialization link has expired. Return")} ";
}
return Redirect(decodeUrl);
diff --git a/IRaCIS.Core.API/IRaCIS.Core.API.xml b/IRaCIS.Core.API/IRaCIS.Core.API.xml
index 3580ca96a..ddbe96072 100644
--- a/IRaCIS.Core.API/IRaCIS.Core.API.xml
+++ b/IRaCIS.Core.API/IRaCIS.Core.API.xml
@@ -29,7 +29,7 @@
-
+
系统用户登录接口[New]
diff --git a/IRaCIS.Core.API/appsettings.Test_IRC.json b/IRaCIS.Core.API/appsettings.Test_IRC.json
index 9e91ec0c2..e27b7194c 100644
--- a/IRaCIS.Core.API/appsettings.Test_IRC.json
+++ b/IRaCIS.Core.API/appsettings.Test_IRC.json
@@ -60,7 +60,10 @@
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 1,
- "AutoLoginOutMinutes": 1
+
+ "AutoLoginOutMinutes": 1,
+
+ "OpenLoginMFA": false
},
"SystemEmailSendConfig": {
diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
index d49fea38a..b4aa35307 100644
--- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
+++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
@@ -853,11 +853,22 @@
后台托管服务的方式运行
-
+
+
+ 受试者随机阅片,任务进行随机编号
+ 进入阅片任务前,随机挑选出该受试者的一个任务,然后给该任务一个编号,编号给的逻辑是:TimePoint Ran+ 已阅任务数量+1
+ 根据当前受试者该标准已阅任务数量(生效失效的任务都算,考虑重阅,最后编号不重复) 第一个就是TimePoint Ran1,后面依次随机挑选出来的阅片序号依次递增
+
+
+
+
+
+
获取该受试者任务上传列表(展示已上传情况)
+
@@ -13254,6 +13265,22 @@
+
+
+ 发送MFA 验证邮件
+
+
+
+
+
+
+ 验证MFA 邮件
+
+
+
+
+
+
用户登陆
diff --git a/IRaCIS.Core.Application/Service/Allocation/VisitTaskHelpeService.cs b/IRaCIS.Core.Application/Service/Allocation/VisitTaskHelpeService.cs
index 976ebf9d4..cdb8a02e2 100644
--- a/IRaCIS.Core.Application/Service/Allocation/VisitTaskHelpeService.cs
+++ b/IRaCIS.Core.Application/Service/Allocation/VisitTaskHelpeService.cs
@@ -155,6 +155,8 @@ namespace IRaCIS.Core.Application.Service
await _visitTaskRepository.SaveChangesAsync();
}
+
+
//基于标准签名 产生任务 (或者手动选择某些访视生成该标准的任务)
public async Task BaseCritrionGenerateVisitTask(Guid trialId, Guid confirmedTrialReadingCriterionId, bool? isManualSelectVisit = null, List? subjectVisitIdList = null)
{
@@ -197,26 +199,29 @@ namespace IRaCIS.Core.Application.Service
foreach (var subjectVisit in subjectGroup.SubjectVisitList)
{
- var blindTaskName = string.Empty;
var isNeedClinicalDataSign = IsNeedClinicalDataSign(ReadingCategory.Visit, subjectVisit.IsBaseLine, trialReadingCriterionConfig.TrialReadingCriterionId, clinicalDataConfirmList);
var isClinicalDataSign = IsClinicalDataSign(ReadingCategory.Visit, subjectVisit.IsBaseLine, trialReadingCriterionConfig.TrialReadingCriterionId, clinicalDataConfirmList, subjectVisit.Id, trialId);
- if (visitNumList.IndexOf(subjectVisit.VisitNum) == 0)
+ var blindTaskName = string.Empty;
+
+ if (trialReadingCriterionConfig.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
{
- blindTaskName = visitBlindConfig.BlindBaseLineName;
- }
- else
- {
- if (trialReadingCriterionConfig.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
+ if (visitNumList.IndexOf(subjectVisit.VisitNum) == 0 && subjectVisit.VisitNum==0)
{
- blindTaskName = visitBlindConfig.BlindFollowUpPrefix + " " + visitNumList.IndexOf(subjectVisit.VisitNum);
+ blindTaskName = visitBlindConfig.BlindBaseLineName;
}
else
{
- blindTaskName = visitBlindConfig.BlindFollowUpPrefix;
+ blindTaskName = visitBlindConfig.BlindFollowUpPrefix + " " + visitNumList.IndexOf(subjectVisit.VisitNum);
+
}
}
+ else
+ {
+ blindTaskName ="Timepoint";
+ }
+
//每个访视 根据项目配置生成任务 双审生成两个
@@ -661,17 +666,16 @@ namespace IRaCIS.Core.Application.Service
var assignConfigList = await _subjectUserRepository.Where(t => t.TrialId == trialId && t.TrialReadingCriterionId == trialReadingCriterionConfig.TrialReadingCriterionId && t.SubjectId == subjectVisit.SubjectId && t.OrignalSubjectUserId == null && t.IsConfirmed).Select(u => new { u.DoctorUserId, u.ArmEnum }).ToListAsync();
-
- var blindTaskName = string.Empty;
-
var isNeedClinicalDataSign = IsNeedClinicalDataSign(ReadingCategory.Visit, subjectVisit.IsBaseLine, trialReadingCriterionConfig.TrialReadingCriterionId, clinicalDataConfirmList);
var isClinicalDataSign = IsClinicalDataSign(ReadingCategory.Visit, subjectVisit.IsBaseLine, trialReadingCriterionConfig.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);
+ var blindTaskName = string.Empty;
+
if (trialReadingCriterionConfig.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
{
- if (visitNumList.IndexOf(subjectVisit.VisitNum) == 0)
+ if (visitNumList.IndexOf(subjectVisit.VisitNum) == 0 && subjectVisit.VisitNum == 0)
{
blindTaskName = visitBlindConfig.BlindBaseLineName;
}
@@ -683,7 +687,7 @@ namespace IRaCIS.Core.Application.Service
}
else
{
- blindTaskName = visitBlindConfig.BlindFollowUpPrefix;
+ blindTaskName = "Timepoint";
}
diff --git a/IRaCIS.Core.Application/Service/Allocation/VisitTaskService.cs b/IRaCIS.Core.Application/Service/Allocation/VisitTaskService.cs
index f0a826372..4450a2779 100644
--- a/IRaCIS.Core.Application/Service/Allocation/VisitTaskService.cs
+++ b/IRaCIS.Core.Application/Service/Allocation/VisitTaskService.cs
@@ -105,21 +105,22 @@ namespace IRaCIS.Core.Application.Service.Allocation
var list = await _repository.Where(t => t.TrialId == trialId && t.IsConfirm)
.OrderBy(t => t.ShowOrder)
- .Select(t => new TrialReadingCriterionDto() {
- TrialReadingCriterionId = t.Id,
+ .Select(t => new TrialReadingCriterionDto()
+ {
+ TrialReadingCriterionId = t.Id,
IsAutoCreate = t.IsAutoCreate,
- IsAdditionalAssessment = t.IsAdditionalAssessment,
+ IsAdditionalAssessment = t.IsAdditionalAssessment,
TrialReadingCriterionName = t.CriterionName,
- CriterionType = t.CriterionType,
- ReadingType = t.ReadingType,
- ReadingInfoSignTime = t.ReadingInfoSignTime ,
- IsReadingPeriod= t.IsReadingPeriod,
- IsArbitrationReading=t.IsArbitrationReading,
- IsGlobalReading=t.IsGlobalReading,
- IsOncologyReading=t.IsOncologyReading,
- ImageDownloadEnum=t.ImageDownloadEnum,
- ImageUploadEnum=t.ImageUploadEnum,
- IsReadingTaskViewInOrder= t.IsReadingTaskViewInOrder
+ CriterionType = t.CriterionType,
+ ReadingType = t.ReadingType,
+ ReadingInfoSignTime = t.ReadingInfoSignTime,
+ IsReadingPeriod = t.IsReadingPeriod,
+ IsArbitrationReading = t.IsArbitrationReading,
+ IsGlobalReading = t.IsGlobalReading,
+ IsOncologyReading = t.IsOncologyReading,
+ ImageDownloadEnum = t.ImageDownloadEnum,
+ ImageUploadEnum = t.ImageUploadEnum,
+ IsReadingTaskViewInOrder = t.IsReadingTaskViewInOrder
})
.ToListAsync();
@@ -154,12 +155,12 @@ namespace IRaCIS.Core.Application.Service.Allocation
.WhereIf(querySubjectAssign.DoctorUserId != null, t => t.SubjectDoctorList.Any(t => t.DoctorUserId == querySubjectAssign.DoctorUserId && t.TrialReadingCriterionId == querySubjectAssign.TrialReadingCriterionId))
.WhereIf(!string.IsNullOrEmpty(querySubjectAssign.SubjectCode), t => t.Code.Contains(querySubjectAssign.SubjectCode))
//未分配
- .WhereIf(querySubjectAssign.SubjectAllocateState == 0, t => !t.SubjectDoctorList.Any(t => t.AssignTime!=null && t.TrialReadingCriterionId == querySubjectAssign.TrialReadingCriterionId))
- //已分配
+ .WhereIf(querySubjectAssign.SubjectAllocateState == 0, t => !t.SubjectDoctorList.Any(t => t.AssignTime != null && t.TrialReadingCriterionId == querySubjectAssign.TrialReadingCriterionId))
+ //已分配
.WhereIf(querySubjectAssign.SubjectAllocateState == 1, t => t.SubjectDoctorList.Any(t => t.AssignTime != null && t.TrialReadingCriterionId == querySubjectAssign.TrialReadingCriterionId))
- .WhereIf(querySubjectAssign.ArmList.Count >0 , t => !querySubjectAssign.ArmList.Except(t.SubjectDoctorList.Where(t => t.AssignTime != null && t.TrialReadingCriterionId == querySubjectAssign.TrialReadingCriterionId).Select(c => c.ArmEnum)).Any() )
-
+ .WhereIf(querySubjectAssign.ArmList.Count > 0, t => !querySubjectAssign.ArmList.Except(t.SubjectDoctorList.Where(t => t.AssignTime != null && t.TrialReadingCriterionId == querySubjectAssign.TrialReadingCriterionId).Select(c => c.ArmEnum)).Any())
+
.WhereIf(isAddtinoarlCriterion, t => t.SubjectCriteriaEvaluationList.Where(t => t.TrialReadingCriterionId == querySubjectAssign.TrialReadingCriterionId).Any(t => t.IsJoinEvaluation))
@@ -173,7 +174,7 @@ namespace IRaCIS.Core.Application.Service.Allocation
var criterionConfig = (await _trialReadingCriterionRepository.Where(x => x.Id == querySubjectAssign.TrialReadingCriterionId).Select(x => new { x.ReadingTool, x.IsReadingTaskViewInOrder, x.ReadingType, x.IsArbitrationReading, x.IsOncologyReading, x.IsGlobalReading }).FirstOrDefaultAsync()).IfNullThrowException();
- return ResponseOutput.Ok (pageList, criterionConfig);
+ return ResponseOutput.Ok(pageList, criterionConfig);
}
///
@@ -307,7 +308,7 @@ namespace IRaCIS.Core.Application.Service.Allocation
var subjectId = cancelCommand.CancelList.First().SubjectId;
- await _repository.AddAsync(new SubjectCanceDoctor() { SubjectId = subjectId, Note = cancelCommand.Note,TrialReadingCriterionId=cancelCommand.TrialReadingCriterionId });
+ await _repository.AddAsync(new SubjectCanceDoctor() { SubjectId = subjectId, Note = cancelCommand.Note, TrialReadingCriterionId = cancelCommand.TrialReadingCriterionId });
await _visitTaskRepository.SaveChangesAsync();
@@ -757,12 +758,12 @@ namespace IRaCIS.Core.Application.Service.Allocation
///
///
[HttpPost]
- public async Task>> GetReadingTaskList(VisitTaskQuery queryVisitTask)
+ public async Task>> GetReadingTaskList(VisitTaskQuery queryVisitTask)
{
var visitTaskQueryable = _visitTaskRepository.Where(t => t.TrialId == queryVisitTask.TrialId && t.IsAnalysisCreate == false)
//.Where(t => t.IsAnalysisCreate == false && t.DoctorUserId != null)
- .WhereIf(queryVisitTask.IsEffect ==true, t => t.TaskState ==TaskState.Effect || t.TaskState == TaskState.Freeze)
+ .WhereIf(queryVisitTask.IsEffect == true, t => t.TaskState == TaskState.Effect || t.TaskState == TaskState.Freeze)
.WhereIf(queryVisitTask.IsEffect == false, t => t.TaskState == TaskState.Adbandon || t.TaskState == TaskState.HaveReturned)
.WhereIf(queryVisitTask.TaskState != null, t => t.TaskState == queryVisitTask.TaskState)
@@ -784,9 +785,9 @@ namespace IRaCIS.Core.Application.Service.Allocation
.WhereIf(!string.IsNullOrEmpty(queryVisitTask.SubjectCode), t => (t.Subject.Code.Contains(queryVisitTask.SubjectCode) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(queryVisitTask.SubjectCode) && t.IsAnalysisCreate))
.WhereIf(queryVisitTask.BeginAllocateDate != null, t => t.AllocateTime > queryVisitTask.BeginAllocateDate)
.WhereIf(queryVisitTask.EndAllocateDate != null, t => t.AllocateTime < queryVisitTask.EndAllocateDate)
- .WhereIf(queryVisitTask.BeginSignTime != null, t => t.SignTime > queryVisitTask.BeginSignTime)
- .WhereIf(queryVisitTask.EndSignTime != null, t => t.SignTime < queryVisitTask.EndSignTime)
- .ProjectTo(_mapper.ConfigurationProvider);
+ .WhereIf(queryVisitTask.BeginSignTime != null, t => t.SignTime > queryVisitTask.BeginSignTime)
+ .WhereIf(queryVisitTask.EndSignTime != null, t => t.SignTime < queryVisitTask.EndSignTime)
+ .ProjectTo(_mapper.ConfigurationProvider);
var defalutSortArray = new string[] { nameof(VisitTask.IsUrgent) + " desc", nameof(VisitTask.SubjectId), nameof(VisitTask.VisitTaskNum) };
@@ -794,7 +795,7 @@ namespace IRaCIS.Core.Application.Service.Allocation
var trialTaskConfig = _trialRepository.Where(t => t.Id == queryVisitTask.TrialId).ProjectTo(_mapper.ConfigurationProvider).FirstOrDefault();
- return ResponseOutput.Ok (pageList, trialTaskConfig);
+ return ResponseOutput.Ok(pageList, trialTaskConfig);
}
@@ -826,13 +827,13 @@ namespace IRaCIS.Core.Application.Service.Allocation
.WhereIf(queryVisitTask.ReadingCategory != null, t => t.OriginalReReadingTask.ReadingCategory == queryVisitTask.ReadingCategory)
.WhereIf(!string.IsNullOrEmpty(queryVisitTask.RequestReReadingReason), t => t.RequestReReadingReason.Contains(queryVisitTask.RequestReReadingReason))
-
+
.WhereIf(queryVisitTask.RequestReReadingResultEnum != null, t => t.RequestReReadingResultEnum == queryVisitTask.RequestReReadingResultEnum)
.WhereIf(!string.IsNullOrEmpty(queryVisitTask.TrialSiteCode), t => (t.OriginalReReadingTask.BlindTrialSiteCode.Contains(queryVisitTask.TrialSiteCode!) && t.OriginalReReadingTask.IsAnalysisCreate) || (t.OriginalReReadingTask.Subject.TrialSite.TrialSiteCode.Contains(queryVisitTask.TrialSiteCode!) && t.OriginalReReadingTask.IsAnalysisCreate == false))
.WhereIf(!string.IsNullOrEmpty(queryVisitTask.TaskName), t => t.OriginalReReadingTask.TaskName.Contains(queryVisitTask.TaskName) || t.OriginalReReadingTask.TaskBlindName.Contains(queryVisitTask.TaskName))
- .WhereIf(!string.IsNullOrEmpty(queryVisitTask.SubjectCode), t => ((t.OriginalReReadingTask.Subject.Code.Contains(queryVisitTask.SubjectCode)|| t.OriginalReReadingTask.Subject.MedicalNo.Contains(queryVisitTask.SubjectCode)) && t.OriginalReReadingTask.IsAnalysisCreate == false) || (t.OriginalReReadingTask.BlindSubjectCode.Contains(queryVisitTask.SubjectCode) && t.OriginalReReadingTask.IsAnalysisCreate))
+ .WhereIf(!string.IsNullOrEmpty(queryVisitTask.SubjectCode), t => ((t.OriginalReReadingTask.Subject.Code.Contains(queryVisitTask.SubjectCode) || t.OriginalReReadingTask.Subject.MedicalNo.Contains(queryVisitTask.SubjectCode)) && t.OriginalReReadingTask.IsAnalysisCreate == false) || (t.OriginalReReadingTask.BlindSubjectCode.Contains(queryVisitTask.SubjectCode) && t.OriginalReReadingTask.IsAnalysisCreate))
.WhereIf(queryVisitTask.BeginAllocateDate != null, t => t.OriginalReReadingTask.AllocateTime > queryVisitTask.BeginAllocateDate)
.WhereIf(queryVisitTask.EndAllocateDate != null, t => t.OriginalReReadingTask.AllocateTime < queryVisitTask.EndAllocateDate!.Value.AddDays(1))
@@ -870,12 +871,12 @@ namespace IRaCIS.Core.Application.Service.Allocation
.Where(t => t.RequestReReadingType == RequestReReadingType.DocotorApply)
.Where(t => t.OriginalReReadingTask.DoctorUserId == _userInfo.Id)
.Where(t => t.OriginalReReadingTask.TrialId == queryVisitTask.TrialId)
- .WhereIf(queryVisitTask.RequestReReadingResultEnum != null, t => t.RequestReReadingResultEnum == queryVisitTask.RequestReReadingResultEnum)
- .WhereIf(queryVisitTask.RootReReadingTaskId != null, t => t.RootReReadingTaskId == queryVisitTask.RootReReadingTaskId || t.OriginalReReadingTaskId == queryVisitTask.RootReReadingTaskId)
+ .WhereIf(queryVisitTask.RequestReReadingResultEnum != null, t => t.RequestReReadingResultEnum == queryVisitTask.RequestReReadingResultEnum)
+ .WhereIf(queryVisitTask.RootReReadingTaskId != null, t => t.RootReReadingTaskId == queryVisitTask.RootReReadingTaskId || t.OriginalReReadingTaskId == queryVisitTask.RootReReadingTaskId)
.WhereIf(!string.IsNullOrEmpty(queryVisitTask.TaskCode), t => t.OriginalReReadingTask.TaskCode.Contains(queryVisitTask.TaskCode!) || t.RootReReadingTask.TaskCode.Contains(queryVisitTask.TaskCode!))
.WhereIf(queryVisitTask.TaskState != null, t => t.OriginalReReadingTask.TaskState == queryVisitTask.TaskState)
- .WhereIf(queryVisitTask.ReadingCategory != null, t => t.OriginalReReadingTask.ReadingCategory == queryVisitTask.ReadingCategory)
- .WhereIf(queryVisitTask.ReReadingApplyState != null, t => t.OriginalReReadingTask.ReReadingApplyState == queryVisitTask.ReReadingApplyState)
+ .WhereIf(queryVisitTask.ReadingCategory != null, t => t.OriginalReReadingTask.ReadingCategory == queryVisitTask.ReadingCategory)
+ .WhereIf(queryVisitTask.ReReadingApplyState != null, t => t.OriginalReReadingTask.ReReadingApplyState == queryVisitTask.ReReadingApplyState)
.WhereIf(queryVisitTask.TrialSiteId != null, t => t.OriginalReReadingTask.Subject.TrialSiteId == queryVisitTask.TrialSiteId)
.WhereIf(queryVisitTask.SubjectId != null, t => t.OriginalReReadingTask.SubjectId == queryVisitTask.SubjectId)
.WhereIf(queryVisitTask.IsUrgent != null, t => t.OriginalReReadingTask.IsUrgent == queryVisitTask.IsUrgent)
@@ -943,14 +944,15 @@ namespace IRaCIS.Core.Application.Service.Allocation
///
///
[HttpPost]
- public async Task<(PageOutput, object)> GetIRUnReadSubjectTaskList(IRUnReadSubjectQuery iRUnReadSubjectQuery)
+ public async Task>> GetIRUnReadSubjectTaskList(IRUnReadSubjectQuery inQuery)
{
- var trialId = iRUnReadSubjectQuery.TrialId;
+ var trialId = inQuery.TrialId;
+ var subjectCode = inQuery.SubjectCode;
- var trialReadingCriterionId = iRUnReadSubjectQuery.TrialReadingCriterionId;
+ var trialReadingCriterionId = inQuery.TrialReadingCriterionId;
- var criterionConfig = await _trialReadingCriterionRepository.Where(x => x.Id == iRUnReadSubjectQuery.TrialReadingCriterionId).FirstNotNullAsync();
+ var criterionConfig = await _trialReadingCriterionRepository.Where(x => x.Id == inQuery.TrialReadingCriterionId).FirstNotNullAsync();
var readingTool = criterionConfig.ReadingTool;
var isReadingTaskViewInOrder = criterionConfig.IsReadingTaskViewInOrder;
@@ -964,13 +966,13 @@ namespace IRaCIS.Core.Application.Service.Allocation
{
TrialId = trialId,
TrialReadingCriterionId = trialReadingCriterionId,
- SubjectCode = iRUnReadSubjectQuery.SubjectCode,
+ SubjectCode = inQuery.SubjectCode,
Page = new PageInput()
{
- PageIndex = iRUnReadSubjectQuery.PageIndex,
- PageSize = iRUnReadSubjectQuery.PageSize,
- Asc = iRUnReadSubjectQuery.Asc,
- SortField = iRUnReadSubjectQuery.SortField,
+ PageIndex = inQuery.PageIndex,
+ PageSize = inQuery.PageSize,
+ Asc = inQuery.Asc,
+ SortField = inQuery.SortField,
}
@@ -984,15 +986,15 @@ namespace IRaCIS.Core.Application.Service.Allocation
var result = new PageOutput()
{
- PageSize = iRUnReadSubjectQuery.PageSize,
- PageIndex = iRUnReadSubjectQuery.PageIndex,
+ PageSize = inQuery.PageSize,
+ PageIndex = inQuery.PageIndex,
TotalCount = totalCount,
CurrentPageData = currentPageData,
};
// 封装的方法有问题
//var result = await visitQuery.ToPagedListAsync(iRUnReadSubjectQuery.PageIndex, iRUnReadSubjectQuery.PageSize, String.IsNullOrEmpty(iRUnReadSubjectQuery.SortField) ? nameof(IRUnReadSubjectView.SubjectId) : iRUnReadSubjectQuery.SortField, iRUnReadSubjectQuery.Asc);
- return (result, new
+ return ResponseOutput.Ok(result, new
{
RandomReadInfo = new IRUnReadOutDto(),
IsReadingTaskViewInOrder = isReadingTaskViewInOrder,
@@ -1004,26 +1006,15 @@ namespace IRaCIS.Core.Application.Service.Allocation
CriterionType = criterionConfig.CriterionType,
});
}
- else
+ else if(isReadingTaskViewInOrder == ReadingOrder.SubjectRandom)
{
- var taskQuery = _visitTaskRepository.Where(x => x.TrialId == iRUnReadSubjectQuery.TrialId && x.DoctorUserId == _userInfo.Id && x.TaskState == TaskState.Effect && x.TrialReadingCriterionId == trialReadingCriterionId)
- // .Where(x=>x.Subject.ClinicalDataList.Any(c => c.IsSign && (c.ReadingId == x.SouceReadModuleId || c.ReadingId == x.SourceSubjectVisitId)))
- .Where(x => !x.Subject.IsDeleted).Where(x => (x.IsNeedClinicalDataSign && x.IsClinicalDataSign) || !x.IsNeedClinicalDataSign);
-
- IRUnReadOutDto iRUnReadOut = new IRUnReadOutDto()
- {
- FinishJudgeTaskCount = await taskQuery.Where(x => x.ReadingCategory == ReadingCategory.Judge && x.ReadingTaskState == ReadingTaskState.HaveSigned).CountAsync(),
- FinishTaskCount = await taskQuery.Where(x => x.ReadingCategory != ReadingCategory.Judge && x.ReadingTaskState == ReadingTaskState.HaveSigned).CountAsync(),
- SuggesteFinishedTime = await taskQuery.Where(x => x.ReadingTaskState != ReadingTaskState.HaveSigned).MaxAsync(x => x.SuggesteFinishedTime),
- UnReadJudgeTaskCount = await taskQuery.Where(x => x.ReadingCategory == ReadingCategory.Judge && x.ReadingTaskState != ReadingTaskState.HaveSigned).CountAsync(),
- UnReadTaskCount = await taskQuery.Where(x => x.ReadingCategory != ReadingCategory.Judge && x.ReadingTaskState != ReadingTaskState.HaveSigned).CountAsync(),
- };
-
-
-
- var visitGroupQuery = taskQuery.GroupBy(x => new { x.SubjectId, x.Subject.Code, x.BlindSubjectCode });
+ var critrion = await _trialReadingCriterionRepository.FindAsync(trialReadingCriterionId);
+ var visitQuery = _visitTaskRepository.Where(x => x.TrialId == trialId && x.DoctorUserId == _userInfo.Id && x.TaskState == TaskState.Effect)
+
+ .WhereIf(!string.IsNullOrEmpty(subjectCode), t => (t.Subject.Code.Contains(subjectCode!) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(subjectCode!) && t.IsAnalysisCreate));
+ var visitGroupQuery = visitQuery.GroupBy(x => new { x.SubjectId, x.Subject.Code, x.BlindSubjectCode });
var visitTaskQuery = visitGroupQuery.Select(x => new IRUnReadSubjectView()
{
@@ -1033,22 +1024,17 @@ namespace IRaCIS.Core.Application.Service.Allocation
SuggesteFinishedTime = x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned).Min(x => x.SuggesteFinishedTime),
//未读任务量
- UnReadTaskCount = x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned).Count(),
-
- //未读 里可读任务量
- UnReadCanReadTaskCount = x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned && y.IsFrontTaskNeedSignButNotSign == false && (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true)
- //不能对包含聚合或子查询的表达式执行聚合函数
- //&& !x.Any(t => t.ReadingTaskState != ReadingTaskState.HaveSigned && t.IsNeedClinicalDataSign == true && t.IsClinicalDataSign == false && t.VisitTaskNum y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned).Count(),
+ UrgentCount = x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned).Where(x => x.IsUrgent).Count(),
//已读任务量
HaveReadTaskCount = x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState == ReadingTaskState.HaveSigned).Count(),
ExistReadingApply = x.Any(y => (y.ReReadingApplyState == ReReadingApplyState.DocotorHaveApplyed && y.TrialReadingCriterionId == trialReadingCriterionId) || y.ReReadingApplyState == ReReadingApplyState.TrialGroupHaveApplyed),
-
- //查出所有未读的 未读的可读的 在这个列表基础上 过滤下 y.IsFrontTaskNeedSignButNotSign==false && (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true) 这样容易排错 确认这三个字段是否维护有误
- UnReadTaskList = x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned).OrderBy(x => x.VisitTaskNum)
+
+ UnReadCanReadTaskList = x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned)
+ .OrderBy(x => x.VisitTaskNum)
.Select(u => new IRUnreadTaskView()
{
Id = u.Id,
@@ -1065,22 +1051,48 @@ namespace IRaCIS.Core.Application.Service.Allocation
IsClinicalDataSign = u.IsClinicalDataSign,
IsFrontTaskNeedSignButNotSign = u.IsFrontTaskNeedSignButNotSign
})
- .ToList(),
+ .ToList()
}).Where(x => x.UnReadCanReadTaskCount > 0);
+ var pageList = await visitTaskQuery.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrWhiteSpace(inQuery.SortField)? nameof(IRUnReadSubjectView.UnReadCanReadTaskCount) : inQuery.SortField, inQuery.Asc );
- var totalCount = await visitGroupQuery.CountAsync();
- var currentPageData = await visitTaskQuery.ToListAsync();
+
+ return ResponseOutput.Ok(pageList, new
+ {
+ RandomReadInfo = new IRUnReadOutDto(),
+ IsReadingTaskViewInOrder = isReadingTaskViewInOrder,
+ ReadingTool = readingTool,
+ IseCRFShowInDicomReading = criterionConfig.IseCRFShowInDicomReading,
+ IsReadingShowSubjectInfo = criterionConfig.IsReadingShowSubjectInfo,
+ IsReadingShowPreviousResults = criterionConfig.IsReadingShowPreviousResults,
+ DigitPlaces = criterionConfig.DigitPlaces,
+ CriterionType = criterionConfig.CriterionType,
+ });
+ }
+ else
+ {
+ var taskQuery = _visitTaskRepository.Where(x => x.TrialId == inQuery.TrialId && x.DoctorUserId == _userInfo.Id && x.TaskState == TaskState.Effect && x.TrialReadingCriterionId == trialReadingCriterionId)
+ // .Where(x=>x.Subject.ClinicalDataList.Any(c => c.IsSign && (c.ReadingId == x.SouceReadModuleId || c.ReadingId == x.SourceSubjectVisitId)))
+ .Where(x => !x.Subject.IsDeleted).Where(x => (x.IsNeedClinicalDataSign && x.IsClinicalDataSign) || !x.IsNeedClinicalDataSign);
+
+ IRUnReadOutDto iRUnReadOut = new IRUnReadOutDto()
+ {
+ FinishJudgeTaskCount = await taskQuery.Where(x => x.ReadingCategory == ReadingCategory.Judge && x.ReadingTaskState == ReadingTaskState.HaveSigned).CountAsync(),
+ FinishTaskCount = await taskQuery.Where(x => x.ReadingCategory != ReadingCategory.Judge && x.ReadingTaskState == ReadingTaskState.HaveSigned).CountAsync(),
+ SuggesteFinishedTime = await taskQuery.Where(x => x.ReadingTaskState != ReadingTaskState.HaveSigned).MaxAsync(x => x.SuggesteFinishedTime),
+ UnReadJudgeTaskCount = await taskQuery.Where(x => x.ReadingCategory == ReadingCategory.Judge && x.ReadingTaskState != ReadingTaskState.HaveSigned).CountAsync(),
+ UnReadTaskCount = await taskQuery.Where(x => x.ReadingCategory != ReadingCategory.Judge && x.ReadingTaskState != ReadingTaskState.HaveSigned).CountAsync(),
+ };
var result = new PageOutput()
{
- PageSize = iRUnReadSubjectQuery.PageSize,
- PageIndex = iRUnReadSubjectQuery.PageIndex,
- TotalCount = totalCount,
- CurrentPageData = currentPageData,
+ PageSize = inQuery.PageSize,
+ PageIndex = inQuery.PageIndex,
+ TotalCount = 0,
+ CurrentPageData = null,
};
- return (result, new
+ return ResponseOutput.Ok(result, new
{
IsReadingTaskViewInOrder = isReadingTaskViewInOrder,
RandomReadInfo = iRUnReadOut,
@@ -1114,8 +1126,7 @@ namespace IRaCIS.Core.Application.Service.Allocation
var critrion = await _trialReadingCriterionRepository.FindAsync(trialReadingCriterionId);
- var visitQuery = _visitTaskRepository.Where(x => x.TrialId == inDto.TrialId && x.DoctorUserId == _userInfo.Id
- && x.TaskState == TaskState.Effect /*&& x.TrialReadingCriterionId== inDto.TrialReadingCriterionId*/)
+ var visitQuery = _visitTaskRepository.Where(x => x.TrialId == inDto.TrialId && x.DoctorUserId == _userInfo.Id && x.TaskState == TaskState.Effect)
.WhereIf(inDto.SubjectId!=null,x=>x.SubjectId==inDto.SubjectId)
//前序 不存在 未生成任务的访视
@@ -1151,34 +1162,34 @@ namespace IRaCIS.Core.Application.Service.Allocation
).Count(),
- UnReadCanReadTaskList= x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned)
- .Where(y => y.IsFrontTaskNeedSignButNotSign == false && (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true))
- .OrderBy(x => x.VisitTaskNum)
- .Select(u => new IRUnreadTaskView()
- {
- Id = u.Id,
- IsUrgent = u.IsUrgent,
- VisitNum = u.VisitTaskNum,
- TaskBlindName = u.TaskBlindName,
- VisistId = u.SourceSubjectVisitId,
- SuggesteFinishedTime = u.SuggesteFinishedTime,
- ReadingCategory = u.ReadingCategory,
- IsAnalysisCreate = u.IsAnalysisCreate,
- ArmEnum = u.ArmEnum,
- TrialReadingCriterionId = u.TrialReadingCriterionId,
- IsNeedClinicalDataSign = u.IsNeedClinicalDataSign,
- IsClinicalDataSign = u.IsClinicalDataSign,
- IsFrontTaskNeedSignButNotSign = u.IsFrontTaskNeedSignButNotSign
- })
- .ToList(),
+ UnReadCanReadTaskList = x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned)
+ .Where(y => y.IsFrontTaskNeedSignButNotSign == false && (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true))
+ .OrderBy(x => x.VisitTaskNum)
+ .Select(u => new IRUnreadTaskView()
+ {
+ Id = u.Id,
+ IsUrgent = u.IsUrgent,
+ VisitNum = u.VisitTaskNum,
+ TaskBlindName = u.TaskBlindName,
+ VisistId = u.SourceSubjectVisitId,
+ SuggesteFinishedTime = u.SuggesteFinishedTime,
+ ReadingCategory = u.ReadingCategory,
+ IsAnalysisCreate = u.IsAnalysisCreate,
+ ArmEnum = u.ArmEnum,
+ TrialReadingCriterionId = u.TrialReadingCriterionId,
+ IsNeedClinicalDataSign = u.IsNeedClinicalDataSign,
+ IsClinicalDataSign = u.IsClinicalDataSign,
+ IsFrontTaskNeedSignButNotSign = u.IsFrontTaskNeedSignButNotSign
+ })
+ .ToList(),
- UrgentCount = x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned)
- .Where(y => y.IsFrontTaskNeedSignButNotSign == false && (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true))
- .Where(x=>x.IsUrgent).Count(),
+ UrgentCount = x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned)
+ .Where(y => y.IsFrontTaskNeedSignButNotSign == false && (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true))
+ .Where(x => x.IsUrgent).Count(),
- //已读任务量
- HaveReadTaskCount = x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState == ReadingTaskState.HaveSigned).Count(),
+ //已读任务量
+ HaveReadTaskCount = x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState == ReadingTaskState.HaveSigned).Count(),
ExistReadingApply = x.Any(y => (y.ReReadingApplyState == ReReadingApplyState.DocotorHaveApplyed && y.TrialReadingCriterionId == trialReadingCriterionId) || y.ReReadingApplyState == ReReadingApplyState.TrialGroupHaveApplyed),
@@ -1211,7 +1222,7 @@ namespace IRaCIS.Core.Application.Service.Allocation
var result = new List();
- var propName = string.IsNullOrWhiteSpace(inDto.Page!.SortField) ? "UnReadCanReadTaskCount" : inDto.Page.SortField;
+ var propName = string.IsNullOrWhiteSpace(inDto.Page!.SortField) ? nameof(IRUnReadSubjectView.UnReadCanReadTaskCount) : inDto.Page.SortField;
var visitTaskOrderQuery = inDto.Page.Asc ? visitTaskQuery.OrderBy(propName) : visitTaskQuery.OrderBy(propName + " desc");
if (inDto.Page != null)
@@ -1276,14 +1287,14 @@ namespace IRaCIS.Core.Application.Service.Allocation
var baseLineTaskList = await _visitTaskRepository.Where(t => t.TrialId == command.TrialId && t.TrialReadingCriterionId == command.TrialReadingCriterionId && t.DoctorUserId == _userInfo.Id
&& t.TaskState == TaskState.Effect && t.ReadingCategory == ReadingCategory.Visit && t.ReadingTaskState == ReadingTaskState.HaveSigned && t.SourceSubjectVisit.IsBaseLine == true).ToListAsync();
- var judegeList= await _visitTaskRepository.Where(t => t.TrialId == command.TrialId && t.TrialReadingCriterionId == command.TrialReadingCriterionId && t.DoctorUserId == _userInfo.Id
+ var judegeList = await _visitTaskRepository.Where(t => t.TrialId == command.TrialId && t.TrialReadingCriterionId == command.TrialReadingCriterionId && t.DoctorUserId == _userInfo.Id
&& t.TaskState == TaskState.Effect && t.ReadingCategory == ReadingCategory.Judge && t.ReadingTaskState == ReadingTaskState.HaveSigned).ToListAsync();
foreach (var item in judegeList)
{
if (!baseLineTaskList.Any(t => t.SubjectId == item.SubjectId))
{
- baseLineTaskList.Add(item);
+ baseLineTaskList.Add(item);
}
}
@@ -2191,8 +2202,8 @@ namespace IRaCIS.Core.Application.Service.Allocation
foreach (var item in readingTableAnswerRowInfoList)
{
- var originalVisitTaskId= item.VisitTaskId;
- var originalFristAddTaskId= item.FristAddTaskId;
+ var originalVisitTaskId = item.VisitTaskId;
+ var originalFristAddTaskId = item.FristAddTaskId;
item.Id = NewId.NextSequentialGuid();
item.VisitTaskId = newTask.Id;
diff --git a/IRaCIS.Core.Application/Service/Common/MailService.cs b/IRaCIS.Core.Application/Service/Common/MailService.cs
index 4ebc148eb..3acfa9ebd 100644
--- a/IRaCIS.Core.Application/Service/Common/MailService.cs
+++ b/IRaCIS.Core.Application/Service/Common/MailService.cs
@@ -21,6 +21,8 @@ namespace IRaCIS.Application.Services
Task SiteSurveyRejectEmail(MimeMessage messageToSend);
+ Task SenMFAVerifyEmail(Guid userId, string userName, string emailAddress, int verificationCode);
+
Task SendMailEditEmail(Guid userId, string userName, string emailAddress, int verificationCode);
Task AnolymousSendEmailForResetAccount(string emailAddress, int verificationCode);
@@ -91,6 +93,66 @@ namespace IRaCIS.Application.Services
return str;
}
+ //MFA
+ public async Task SenMFAVerifyEmail(Guid userId, string userName, string emailAddress, int verificationCode)
+ {
+ var messageToSend = new MimeMessage();
+ //发件地址
+ messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
+ //收件地址
+ messageToSend.To.Add(new MailboxAddress(userName, emailAddress));
+ //主题
+ //---[来自{0}] 关于MFA邮箱验证的提醒
+ messageToSend.Subject = _localizer["Mail_EmailMFATopic", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN];
+
+ var builder = new BodyBuilder();
+
+
+ var pathToFile = _hostEnvironment.WebRootPath
+ + Path.DirectorySeparatorChar.ToString()
+ + "EmailTemplate"
+ + Path.DirectorySeparatorChar.ToString()
+ //+ "UserOptCommon.html";
+ + (_userInfo.IsEn_Us ? "UserOptCommon_US.html" : "UserOptCommon.html");
+
+ using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
+ {
+ var templateInfo = SourceReader.ReadToEnd();
+
+
+ builder.HtmlBody = string.Format(ReplaceCompanyName(templateInfo),
+
+ userName,
+ _localizer["Mail_MFAEmail"],
+ verificationCode
+ );
+ }
+
+
+ messageToSend.Body = builder.ToMessageBody();
+
+
+
+ EventHandler sucessHandle = (sender, args) =>
+ {
+ // args.Response
+ var code = verificationCode.ToString();
+ _ = _verificationCodeRepository.AddAsync(new VerificationCode()
+ {
+ CodeType = 0,
+ HasSend = true,
+ Code = code,
+ UserId = userId,
+ ExpirationTime = DateTime.Now.AddMinutes(3)
+ }).Result;
+ _ = _verificationCodeRepository.SaveChangesAsync().Result;
+
+ };
+
+
+ await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, sucessHandle);
+ }
+
//重置邮箱
public async Task SendMailEditEmail(Guid userId, string userName, string emailAddress, int verificationCode)
{
diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/DownloadAndUploadDTO.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/DownloadAndUploadDTO.cs
index 744f8dbc5..6f3910b2d 100644
--- a/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/DownloadAndUploadDTO.cs
+++ b/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/DownloadAndUploadDTO.cs
@@ -21,6 +21,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc.DTO
public string TaskName { get; set; }
+ public bool IsImageFilter { get; set; }
public string CriterionModalitys { get; set; }
public Guid? SourceSubjectVisitId { get; set; }
diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs
index fda43c6ae..890a66eef 100644
--- a/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs
+++ b/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs
@@ -12,6 +12,7 @@ using Medallion.Threading;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
+using System.Data;
using System.IO.Compression;
using System.Linq;
using System.Text;
@@ -28,12 +29,13 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
{
private readonly IEasyCachingProvider _provider;
private readonly IRepository _systemAnonymizationRepository;
+ private readonly IRepository _visitTaskRepository;
private readonly IRepository _subjectVisitRepository;
private readonly IOSSService _oSSService;
private readonly IRepository _studyMonitorRepository;
private readonly IDistributedLockProvider _distributedLockProvider;
public DownloadAndUploadService(IEasyCachingProvider provider, IRepository systemAnonymizationRepository, IRepository subjectVisitRepository, IOSSService oSSService,
- IRepository studyMonitorRepository, IDistributedLockProvider distributedLockProvider)
+ IRepository studyMonitorRepository, IDistributedLockProvider distributedLockProvider, IRepository visitTaskRepository)
{
_systemAnonymizationRepository = systemAnonymizationRepository;
@@ -43,16 +45,62 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
_studyMonitorRepository = studyMonitorRepository;
_distributedLockProvider = distributedLockProvider;
_provider = provider;
+ _visitTaskRepository = visitTaskRepository;
+ }
+
+ ///
+ /// 受试者随机阅片,任务进行随机编号
+ /// 进入阅片任务前,随机挑选出该受试者的一个任务,然后给该任务一个编号,编号给的逻辑是:TimePoint Ran+ 已阅任务数量+1
+ /// 根据当前受试者该标准已阅任务数量(生效失效的任务都算,考虑重阅,最后编号不重复) 第一个就是TimePoint Ran1,后面依次随机挑选出来的阅片序号依次递增
+ ///
+ ///
+ ///
+ ///
+ public async Task SubejctRandomReadingTaskNameDeal(Guid subjectId, Guid trialReadingCriterionId)
+ {
+ //subject 随机阅片 才处理任务编号
+ if (_visitTaskRepository.Any(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.TrialReadingCriterion.IsReadingTaskViewInOrder == ReadingOrder.SubjectRandom))
+ {
+ //找到 非一致性分析,未签名,状态正常的 并且任务名称是TimePoint的 任务
+ var needDealTaskList = await _visitTaskRepository.Where(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.IsAnalysisCreate == false && t.DoctorUserId==_userInfo.Id
+ && t.ReadingTaskState != ReadingTaskState.HaveSigned && t.TaskBlindName == "Timepoint" && t.ReadingCategory == ReadingCategory.Visit
+ && (t.TaskState == TaskState.Effect || t.TaskState == TaskState.Freeze), true).ToListAsync();
+
+ if (needDealTaskList.Count>0)
+ {
+ //已完成的访视任务数量(包含重阅的)
+ var haveFinishedTaskCount = await _visitTaskRepository.CountAsync(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.IsAnalysisCreate == false
+ && t.ReadingTaskState == ReadingTaskState.HaveSigned && t.ReadingCategory == ReadingCategory.Visit);
+
+ //随机赋值编号 比如要处理5个任务,实例化一个包含1-5的数组,每次随机取出一个
+
+ List availableNumbers = Enumerable.Range(haveFinishedTaskCount + 1, needDealTaskList.Count).ToList();
+ Random rng = new Random();
+ foreach (var visitTask in needDealTaskList)
+ {
+ int randomIndex = rng.Next(availableNumbers.Count);
+
+ visitTask.TaskBlindName = $"Timepoint Ran {availableNumbers[randomIndex]}";
+
+ availableNumbers.RemoveAt(randomIndex);
+ }
+ await _visitTaskRepository.SaveChangesAsync();
+ }
+ }
+ return ResponseOutput.Ok();
}
///
/// 获取该受试者任务上传列表(展示已上传情况)
///
///
+ ///
///
- public async Task>> GetSubjectImageUploadList(Guid subjectId)
+ public async Task>> GetSubjectImageUploadList(Guid subjectId,Guid trialReadingCriterionId)
{
- var query = _repository.Where(t => t.SubjectId == subjectId && t.SourceSubjectVisitId != null && t.DoctorUserId == _userInfo.Id)
+ await SubejctRandomReadingTaskNameDeal(subjectId, trialReadingCriterionId);
+
+ var query = _repository.Where(t => t.SubjectId == subjectId &&t.TrialReadingCriterionId== trialReadingCriterionId && t.SourceSubjectVisitId != null && t.DoctorUserId == _userInfo.Id)
.Select(u => new SubjectImageUploadDTO()
{
VisitTaskId = u.Id,
@@ -63,9 +111,11 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
TrialSiteId = u.Subject.TrialSiteId,
- CriterionModalitys= u.TrialReadingCriterion.CriterionModalitys,
+ IsImageFilter = u.TrialReadingCriterion.IsImageFilter,
- SubjectCode = u.IsSelfAnalysis == true ? u.BlindSubjectCode : u.Subject.Code ,
+ CriterionModalitys = u.TrialReadingCriterion.CriterionModalitys,
+
+ SubjectCode = u.IsSelfAnalysis == true ? u.BlindSubjectCode : u.Subject.Code,
TaskBlindName = u.TaskBlindName,
TaskName = u.TaskName,
@@ -313,7 +363,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
else
{
- var studyId = IdentifierHelper.CreateGuid(incommand.Study.StudyInstanceUid, incommand.TrialId.ToString(), findOriginStudy.VisitTaskId.ToString());
+ var studyId = IdentifierHelper.CreateGuid(incommand.Study.StudyInstanceUid, incommand.TrialId.ToString(), findOriginStudy.VisitTaskId.ToString());
var study = await _repository.FirstOrDefaultAsync(t => t.Id == studyId);
@@ -324,7 +374,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
//特殊处理逻辑
study.Modalities = string.Join("、", incommand.Study.SeriesList.Select(t => t.Modality).Union(study.Modalities.Split("、", StringSplitOptions.RemoveEmptyEntries)).Distinct());
SpecialArchiveStudyDeal(study);
- modalitys = study.Modalities;
+ modalitys = study.Modalities;
// 少了整个序列
@@ -535,50 +585,59 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
if (isAnonymize)
{
+ //受试者随机阅片,需要匿名化检查时间
DicomFile dicomFile = await DicomFile.OpenAsync(destinationPath, Encoding.Default);
-
DicomDataset dataset = dicomFile.Dataset;
+ dataset.AddOrUpdate(DicomTag.StudyDate, string.Empty);
+ dataset.AddOrUpdate(DicomTag.StudyTime, string.Empty);
- foreach (var item in addOrUpdateFixedFieldList)
- {
+ #region 前端已经匿名化,不需要做相关tag匿名化
+ //DicomFile dicomFile = await DicomFile.OpenAsync(destinationPath, Encoding.Default);
- var dicomTag = new DicomTag(Convert.ToUInt16(item.Group, 16), Convert.ToUInt16(item.Element, 16));
+ //DicomDataset dataset = dicomFile.Dataset;
- dataset.AddOrUpdate(dicomTag, item.ReplaceValue);
- }
+ //foreach (var item in addOrUpdateFixedFieldList)
+ //{
- foreach (var item in ircFieldList)
- {
+ // var dicomTag = new DicomTag(Convert.ToUInt16(item.Group, 16), Convert.ToUInt16(item.Element, 16));
- var dicomTag = new DicomTag(Convert.ToUInt16(item.Group, 16), Convert.ToUInt16(item.Element, 16));
+ // dataset.AddOrUpdate(dicomTag, item.ReplaceValue);
+ //}
- if (dicomTag == DicomTag.ClinicalTrialProtocolID)
- {
- dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.TrialCode);
+ //foreach (var item in ircFieldList)
+ //{
- }
- if (dicomTag == DicomTag.ClinicalTrialSiteID)
- {
- //dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.TrialSiteCode);
+ // var dicomTag = new DicomTag(Convert.ToUInt16(item.Group, 16), Convert.ToUInt16(item.Element, 16));
- }
- if (dicomTag == DicomTag.ClinicalTrialSubjectID)
- {
- dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.SubjectCode);
+ // if (dicomTag == DicomTag.ClinicalTrialProtocolID)
+ // {
+ // dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.TrialCode);
- }
- if (dicomTag == DicomTag.ClinicalTrialTimePointID)
- {
- dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.VisitNum.ToString());
+ // }
+ // if (dicomTag == DicomTag.ClinicalTrialSiteID)
+ // {
+ // //dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.TrialSiteCode);
- }
- if (dicomTag == DicomTag.PatientID)
- {
- dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.TrialCode + "_" + subjectAndVisitInfo.SubjectCode);
+ // }
+ // if (dicomTag == DicomTag.ClinicalTrialSubjectID)
+ // {
+ // dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.SubjectCode);
- }
+ // }
+ // if (dicomTag == DicomTag.ClinicalTrialTimePointID)
+ // {
+ // dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.VisitNum.ToString());
+
+ // }
+ // if (dicomTag == DicomTag.PatientID)
+ // {
+ // dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.TrialCode + "_" + subjectAndVisitInfo.SubjectCode);
+
+ // }
+
+ //}
+ #endregion
- }
}
#endregion
}
diff --git a/IRaCIS.Core.Application/Service/Management/DTO/UserModel.cs b/IRaCIS.Core.Application/Service/Management/DTO/UserModel.cs
index 24fb5e16f..a54ec9ad4 100644
--- a/IRaCIS.Core.Application/Service/Management/DTO/UserModel.cs
+++ b/IRaCIS.Core.Application/Service/Management/DTO/UserModel.cs
@@ -21,6 +21,8 @@ namespace IRaCIS.Application.Contracts
{
public string UserName { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
+
+ public Guid? UserId { get; set; }
}
public class LoginReturnDTO
@@ -28,6 +30,8 @@ namespace IRaCIS.Application.Contracts
public UserBasicInfo BasicInfo { get; set; } = new UserBasicInfo();
public string JWTStr { get; set; }=string.Empty;
+ public bool IsMFA { get; set; } = false;
+
}
public class UserBasicInfo
@@ -59,7 +63,7 @@ namespace IRaCIS.Application.Contracts
public string PermissionStr { get; set; } = String.Empty;
-
+ public string EMail { get; set; } = string.Empty;
public bool IsFirstAdd { get; set; }
public bool IsReviewer { get; set; } = false;
diff --git a/IRaCIS.Core.Application/Service/Management/Interface/IUserService.cs b/IRaCIS.Core.Application/Service/Management/Interface/IUserService.cs
index cc44a25ed..873fced43 100644
--- a/IRaCIS.Core.Application/Service/Management/Interface/IUserService.cs
+++ b/IRaCIS.Core.Application/Service/Management/Interface/IUserService.cs
@@ -10,12 +10,16 @@ namespace IRaCIS.Application.Services
Task GetUser(Guid id);
Task> GetUserList(UserListQueryDTO param);
Task> Login(string userName, string password);
+ Task VerifyMFACodeAsync(Guid userId, string Code);
+
+ Task SendMFAEmail(Guid userId);
+ Task GetUserBasicInfo(Guid userId,string pwd);
Task ModifyPassword(EditPasswordCommand editPwModel);
Task ResetPassword(Guid userId);
Task UpdateUser(UserCommand model);
Task UpdateUserState(Guid userId, UserStateEnum state);
-
+
//Task SendVerificationCode(string emailOrPhone, VerifyType verificationType, bool isReviewer = false);
//Task SetNewPassword(ResetPasswordCommand resetPwdModel);
}
diff --git a/IRaCIS.Core.Application/Service/Management/UserService.cs b/IRaCIS.Core.Application/Service/Management/UserService.cs
index 6490c9bfb..ab4a221c2 100644
--- a/IRaCIS.Core.Application/Service/Management/UserService.cs
+++ b/IRaCIS.Core.Application/Service/Management/UserService.cs
@@ -15,6 +15,9 @@ using Medallion.Threading;
using EasyCaching.Core;
using IRaCIS.Core.Application.Contracts;
using LoginReturnDTO = IRaCIS.Application.Contracts.LoginReturnDTO;
+using IRaCIS.Core.Application.Auth;
+using BeetleX.Redis.Commands;
+using IRaCIS.Core.Domain.Models;
namespace IRaCIS.Application.Services
{
@@ -22,17 +25,17 @@ namespace IRaCIS.Application.Services
public class UserService : BaseService, IUserService
{
private readonly IRepository _userRepository;
-
- private readonly IMailVerificationService _mailVerificationService;
+
+ private readonly IMailVerificationService _mailVerificationService;
private readonly IRepository _verificationCodeRepository;
private readonly IRepository _doctorRepository;
private readonly IRepository _userTrialRepository;
private readonly IRepository _userLogRepository;
- private readonly IRepository _userPassWordLogRepository;
- private readonly IDistributedLockProvider _distributedLockProvider;
+ private readonly IRepository _userPassWordLogRepository;
+ private readonly IDistributedLockProvider _distributedLockProvider;
private readonly IEasyCachingProvider _cache;
- private readonly IReadingImageTaskService _readingImageTaskService;
- private readonly IOptionsMonitor _verifyConfig;
+ private readonly IReadingImageTaskService _readingImageTaskService;
+ private readonly IOptionsMonitor _verifyConfig;
public UserService(IRepository userRepository,
@@ -41,20 +44,20 @@ namespace IRaCIS.Application.Services
IRepository verificationCodeRepository,
IRepository doctorRepository,
IEasyCachingProvider cache,
- IReadingImageTaskService readingImageTaskService,
- IRepository userTrialRepository,
+ IReadingImageTaskService readingImageTaskService,
+ IRepository userTrialRepository,
IOptionsMonitor verifyConfig,
IRepository userLogRepository,
- IRepository userPassWordLogRepository
+ IRepository userPassWordLogRepository
,
IDistributedLockProvider distributedLockProvider)
{
_userLogRepository = userLogRepository;
- this._userPassWordLogRepository = userPassWordLogRepository;
- _verifyConfig = verifyConfig;
+ this._userPassWordLogRepository = userPassWordLogRepository;
+ _verifyConfig = verifyConfig;
_cache = cache;
- this._readingImageTaskService = readingImageTaskService;
- _userRepository = userRepository;
+ this._readingImageTaskService = readingImageTaskService;
+ _userRepository = userRepository;
_mailVerificationService = mailVerificationService;
_verificationCodeRepository = verificationCodeRepository;
_doctorRepository = doctorRepository;
@@ -95,45 +98,45 @@ namespace IRaCIS.Application.Services
private async Task VerifyUserPwdAsync(Guid userId, string newPwd, string? oldPwd = null)
{
- //var dbUser = (await _userRepository.FirstOrDefaultAsync(t => t.Id == userId)).IfNullThrowException();
+ //var dbUser = (await _userRepository.FirstOrDefaultAsync(t => t.Id == userId)).IfNullThrowException();
- if (oldPwd != null && oldPwd == newPwd)
- {
- //---新密码与旧密码相同。
- throw new BusinessValidationFailedException(_localizer["User_NewOldPwdSame"]);
- }
+ if (oldPwd != null && oldPwd == newPwd)
+ {
+ //---新密码与旧密码相同。
+ throw new BusinessValidationFailedException(_localizer["User_NewOldPwdSame"]);
+ }
- var dbUser = (await _userRepository.Where(t => t.Id == userId).FirstOrDefaultAsync()).IfNullThrowException();
+ var dbUser = (await _userRepository.Where(t => t.Id == userId).FirstOrDefaultAsync()).IfNullThrowException();
- if (oldPwd != null && dbUser.Password != oldPwd)
- {
- //---旧密码验证失败。
- throw new BusinessValidationFailedException(_localizer["User_OldPwdInvalid"]);
- }
+ if (oldPwd != null && dbUser.Password != oldPwd)
+ {
+ //---旧密码验证失败。
+ throw new BusinessValidationFailedException(_localizer["User_OldPwdInvalid"]);
+ }
- if (dbUser.Password == newPwd)
- {
- //---新密码与旧密码相同。
- throw new BusinessValidationFailedException(_localizer["User_NewOldPwdSame"]);
- }
+ if (dbUser.Password == newPwd)
+ {
+ //---新密码与旧密码相同。
+ throw new BusinessValidationFailedException(_localizer["User_NewOldPwdSame"]);
+ }
var passWordList = await _userPassWordLogRepository.Where(x => x.UserId == userId).OrderByDescending(x => x.CreateTime).Take(2).ToListAsync();
if (passWordList.Any(x => x.PassWord == newPwd))
{
- throw new BusinessValidationFailedException(_localizer["User_PassWordRepeat"]);
- }
+ throw new BusinessValidationFailedException(_localizer["User_PassWordRepeat"]);
+ }
if (oldPwd != null)
{
- await _userPassWordLogRepository.AddAsync(new UserPassWordLog()
- {
+ await _userPassWordLogRepository.AddAsync(new UserPassWordLog()
+ {
+
+ CreateTime = DateTime.Now,
+ PassWord = oldPwd,
+ UserId = userId,
+ });
+ }
- CreateTime = DateTime.Now,
- PassWord = oldPwd,
- UserId = userId,
- });
- }
-
await _userRepository.BatchUpdateNoTrackingAsync(x => x.Id == userId, x => new User()
{
@@ -142,7 +145,7 @@ namespace IRaCIS.Application.Services
await _userPassWordLogRepository.SaveChangesAsync();
- await Task.CompletedTask;
+ await Task.CompletedTask;
}
@@ -306,7 +309,7 @@ namespace IRaCIS.Application.Services
{
await _mailVerificationService.AdminResetPwdSendEmailAsync(userId, pwd);
}
- catch (Exception )
+ catch (Exception)
{
//---请检查邮箱地址或者联系维护人员, 邮件发送失败, 未能创建账户成功
throw new BusinessValidationFailedException(_localizer["User_CreateFailed"]);
@@ -319,7 +322,7 @@ namespace IRaCIS.Application.Services
IsFirstAdd = true
});
- await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = _userInfo.Id, OptUserId=userId, OptType = UserOptType.ResetPassword }, true);
+ await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = _userInfo.Id, OptUserId = userId, OptType = UserOptType.ResetPassword }, true);
return ResponseOutput.Ok();
}
@@ -403,7 +406,7 @@ namespace IRaCIS.Application.Services
}
}
- var list = await _userRepository.Where(t => t.EMail == email && t.Status== UserStateEnum.Enable).Select(t => new UserAccountDto() { UserId = t.Id, UserName = t.UserName, UserRealName = t.FullName, UserType = t.UserTypeRole.UserTypeShortName }).ToListAsync();
+ var list = await _userRepository.Where(t => t.EMail == email && t.Status == UserStateEnum.Enable).Select(t => new UserAccountDto() { UserId = t.Id, UserName = t.UserName, UserRealName = t.FullName, UserType = t.UserTypeRole.UserTypeShortName }).ToListAsync();
@@ -431,7 +434,7 @@ namespace IRaCIS.Application.Services
IsFirstAdd = false
});
- await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = userId, OptUserId = userId,LoginPassword=newPwd, OptType = UserOptType.UnloginModifyPasswoed }, true);
+ await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = userId, OptUserId = userId, LoginPassword = newPwd, OptType = UserOptType.UnloginModifyPasswoed }, true);
return ResponseOutput.Result(success);
@@ -467,7 +470,7 @@ namespace IRaCIS.Application.Services
IsFirstAdd = false
});
- await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = _userInfo.Id, OptUserId= _userInfo.Id, OptType = UserOptType.LoginModifyPassword }, true);
+ await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = _userInfo.Id, OptUserId = _userInfo.Id, OptType = UserOptType.LoginModifyPassword }, true);
return ResponseOutput.Result(success);
@@ -555,11 +558,11 @@ namespace IRaCIS.Application.Services
var success = await _userRepository.SaveChangesAsync();
}
-
+
await _mailVerificationService.AddUserSendEmailAsync(saveItem.Id, userAddModel.BaseUrl, userAddModel.RouteUrl);
- return ResponseOutput.Ok( new UserAddedReturnDTO { Id = saveItem.Id, UserCode = saveItem.UserCode });
+ return ResponseOutput.Ok(new UserAddedReturnDTO { Id = saveItem.Id, UserCode = saveItem.UserCode });
}
@@ -589,7 +592,7 @@ namespace IRaCIS.Application.Services
user.OrganizationName = AppSettings.DefaultInternalOrganizationName;
}
- await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = _userInfo.Id, OptUserId= model.Id , OptType = UserOptType.UpdateUser }, true);
+ await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = _userInfo.Id, OptUserId = model.Id, OptType = UserOptType.UpdateUser }, true);
var success = await _userRepository.SaveChangesAsync();
@@ -611,7 +614,7 @@ namespace IRaCIS.Application.Services
return ResponseOutput.NotOk(_localizer["User_InProject"]);
}
- await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = _userInfo.Id, OptUserId= userId, OptType = UserOptType.DeleteUser }, true);
+ await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = _userInfo.Id, OptUserId = userId, OptType = UserOptType.DeleteUser }, true);
var success = await _userRepository.BatchDeleteNoTrackingAsync(t => t.Id == userId);
@@ -629,7 +632,7 @@ namespace IRaCIS.Application.Services
public async Task UpdateUserState(Guid userId, UserStateEnum state)
{
- await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = _userInfo.Id, OptUserId = userId, OptType = state==UserStateEnum.Enable? UserOptType.AccountEnable: UserOptType.AccountLocked }, true);
+ await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = _userInfo.Id, OptUserId = userId, OptType = state == UserStateEnum.Enable ? UserOptType.AccountEnable : UserOptType.AccountLocked }, true);
var success = await _userRepository.BatchUpdateNoTrackingAsync(u => u.Id == userId, t => new User
{
@@ -639,7 +642,70 @@ namespace IRaCIS.Application.Services
}
+ public async Task GetUserBasicInfo(Guid userId, string pwd)
+ {
+ var info = await _userRepository.Where(u => u.Id == userId && u.Password==pwd).ProjectTo(_mapper.ConfigurationProvider).FirstNotNullAsync();
+ return info;
+ }
+
+ ///
+ /// 发送MFA 验证邮件
+ ///
+ ///
+ ///
+ [AllowAnonymous]
+ public async Task SendMFAEmail(Guid userId)
+ {
+ var userInfo = await _userRepository.Where(u => u.Id == userId).Select(t => new { t.FullName, t.EMail }).FirstOrDefaultAsync();
+
+ int verificationCode = new Random().Next(100000, 1000000);
+
+ await _mailVerificationService.SenMFAVerifyEmail(userId, userInfo.FullName, userInfo.EMail, verificationCode);
+
+ return ResponseOutput.Ok();
+ }
+
+ ///
+ /// 验证MFA 邮件
+ ///
+ ///
+ ///
+ ///
+ ///
+ [AllowAnonymous]
+ public async Task VerifyMFACodeAsync(Guid userId, string Code)
+ {
+ var verificationRecord = await _repository.GetQueryable().OrderByDescending(x => x.ExpirationTime).Where(t => t.UserId == userId && t.Code == Code && t.CodeType == VerifyType.Email).FirstOrDefaultAsync();
+ VerifyEmialGetDoctorInfoOutDto result = new VerifyEmialGetDoctorInfoOutDto();
+
+ //检查数据库是否存在该验证码
+ if (verificationRecord == null)
+ {
+ await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = userId, OptUserId = userId, OptType = UserOptType.MFALoginFail }, true);
+ //---验证码错误。
+ throw new BusinessValidationFailedException(_localizer["TrialSiteSurvey_WrongVerificationCode"]);
+ }
+ else
+ {
+ //检查验证码是否失效
+ if (verificationRecord.ExpirationTime < DateTime.Now)
+ {
+ await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = userId, OptUserId = userId, OptType = UserOptType.MFALoginFail }, true);
+ //---验证码已经过期。
+ throw new BusinessValidationFailedException(_localizer["TrialSiteSurvey_ExpiredVerificationCode"]);
+
+
+ }
+ else //验证码正确 并且 没有超时
+ {
+ await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = userId, OptUserId = userId, OptType = UserOptType.MFALogin }, true);
+
+ }
+ }
+
+ return ResponseOutput.Ok();
+ }
///
/// 用户登陆
@@ -690,14 +756,12 @@ namespace IRaCIS.Application.Services
failCount++;
_cache.Set(cacheKey, failCount, TimeSpan.FromMinutes(lockoutMinutes));
- var errorPwdUserId = await _userRepository.Where(u => u.UserName==userName).Select(t=>t.Id).FirstOrDefaultAsync();
+ var errorPwdUserId = await _userRepository.Where(u => u.UserName == userName).Select(t => t.Id).FirstOrDefaultAsync();
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = errorPwdUserId, OptUserId = errorPwdUserId, LoginFaildName = userName, LoginPassword = password, OptType = UserOptType.AccountOrPasswordError }, true);
return ResponseOutput.NotOk(_localizer["User_CheckNameOrPw"], new LoginReturnDTO());
-
-
}
if (loginUser.Status == 0)
@@ -712,26 +776,26 @@ namespace IRaCIS.Application.Services
if (loginUser.LastChangePassWordTime != null && DateTime.Now.AddDays(-90) > loginUser.LastChangePassWordTime.Value)
{
loginUser.LoginState = 1;
- }
+ }
//登录成功 清除缓存
_cache.Set(cacheKey, 0, TimeSpan.FromMinutes(lockoutMinutes));
-
- if (loginUser.LastLoginIP != string.Empty)
+
+ if (loginUser.LastLoginIP != string.Empty)
{
// 与上一次IP不一致
if (loginUser.LastLoginIP != _userInfo.IP)
{
- loginUser.LoginState = 2;
- }
-
+ loginUser.LoginState = 2;
+ }
- }
- await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = loginUser.Id, OptUserId = loginUser.Id, OptType = UserOptType.Login }, true);
+ }
+
+ await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = loginUser.Id, OptUserId = loginUser.Id, OptType = UserOptType.Login }, true);
userLoginReturnModel.BasicInfo = loginUser;
@@ -743,21 +807,13 @@ namespace IRaCIS.Application.Services
});
- }
+ }
- await _userRepository.BatchUpdateNoTrackingAsync(x => x.Id == loginUser.Id, x => new User()
- {
- LastLoginIP = _userInfo.IP
-
- });
-
-
- // 登录 清除缓存
- //_cache.Remove(userLoginReturnModel.BasicInfo.Id.ToString());
-
- var userId = loginUser.Id;
- await _cache.SetAsync($"{userId.ToString()}_Online", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(_verifyConfig.CurrentValue.AutoLoginOutMinutes));
+ await _userRepository.BatchUpdateNoTrackingAsync(x => x.Id == loginUser.Id, x => new User()
+ {
+ LastLoginIP = _userInfo.IP
+ });
return ResponseOutput.Ok(userLoginReturnModel);
@@ -766,12 +822,12 @@ namespace IRaCIS.Application.Services
[HttpPost]
public async Task> GetUserLogList(UserLogQuery inQuery)
{
- DateTime? trialCreateTime = inQuery.TrialId != null ?_repository.Where(t=>t.Id==inQuery.TrialId).Select(t=>t.CreateTime).FirstOrDefault() : null;
+ DateTime? trialCreateTime = inQuery.TrialId != null ? _repository.Where(t => t.Id == inQuery.TrialId).Select(t => t.CreateTime).FirstOrDefault() : null;
var userLogQueryable =
_userLogRepository
.WhereIf(inQuery.TrialId != null, t => t.LoginUser.UserTrials.Any(c => c.TrialId == inQuery.TrialId && (c.UserId == t.LoginUserId || c.UserId == t.OptUserId)))
- .WhereIf(trialCreateTime != null, t => t.CreateTime>= trialCreateTime)
+ .WhereIf(trialCreateTime != null, t => t.CreateTime >= trialCreateTime)
.WhereIf(inQuery.OptType != null, t => t.OptType == inQuery.OptType)
.WhereIf(inQuery.UserId != null, t => t.LoginUserId == inQuery.UserId)
.WhereIf(inQuery.BeginDate != null, t => t.CreateTime >= inQuery.BeginDate)
diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialConfigDTO.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialConfigDTO.cs
index 9236b19a1..8232ce32c 100644
--- a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialConfigDTO.cs
+++ b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialConfigDTO.cs
@@ -344,6 +344,8 @@ namespace IRaCIS.Core.Application.Contracts
{
public string TrialModalitys { get; set;}
+ public bool IsImageFilter { get; set; }
+
///
/// 项目ID
@@ -506,6 +508,7 @@ namespace IRaCIS.Core.Application.Contracts
public ReadingImageUpload? ImageUploadEnum { get; set; }
+ public Guid TrialReadingCriterionId { get; set; }
}
@@ -864,6 +867,7 @@ namespace IRaCIS.Core.Application.Contracts
public class SetCriterionReadingInfoInDto
{
+ public bool IsImageFilter { get; set; }
public string CriterionModalitys { get; set; }
public ReadingImageDownload? ImageDownloadEnum { get; set; }
diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs
index dabf10d1e..ef9c33a6d 100644
--- a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs
+++ b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs
@@ -317,12 +317,12 @@ namespace IRaCIS.Core.Application
#endregion
- var trialModalitys = _readingQuestionCriterionTrialRepository.Where(t => t.Id == inDto.TrialReadingCriterionId).Select(t => t.Trial.Modalitys).FirstOrDefault();
+ //var trialModalitys = _readingQuestionCriterionTrialRepository.Where(t => t.Id == inDto.TrialReadingCriterionId).Select(t => t.Trial.Modalitys).FirstOrDefault();
var systemCriterion = await _readingQuestionCriterionSystemRepository.Where(x => x.Id == trialCriterion.ReadingQuestionCriterionSystemId).FirstNotNullAsync();
await _readingQuestionCriterionTrialRepository.BatchUpdateNoTrackingAsync(x => x.Id == inDto.TrialReadingCriterionId, x => new ReadingQuestionCriterionTrial()
{
- CriterionModalitys= trialModalitys,
+ //CriterionModalitys= trialModalitys,
IsOncologyReading = systemCriterion.IsOncologyReading,
IsSystemSetOncology = systemCriterion.IsOncologyReading,
IseCRFShowInDicomReading = systemCriterion.IseCRFShowInDicomReading,
@@ -604,6 +604,7 @@ namespace IRaCIS.Core.Application
await _readingQuestionCriterionTrialRepository.UpdatePartialFromQueryAsync(inDto.TrialReadingCriterionId, x => new ReadingQuestionCriterionTrial()
{
+ IsImageFilter=inDto.IsImageFilter,
ImageDownloadEnum = inDto.ImageDownloadEnum,
ImageUploadEnum = inDto.ImageUploadEnum,
CriterionModalitys = inDto.CriterionModalitys,
@@ -953,7 +954,7 @@ namespace IRaCIS.Core.Application
trialInfo.UpdateTime = DateTime.Now;
- await _readingQuestionCriterionTrialRepository.BatchUpdateNoTrackingAsync(t => t.TrialId == trialConfig.TrialId && t.IsSigned == false, u => new ReadingQuestionCriterionTrial() { CriterionModalitys = trialConfig.Modalitys });
+ //await _readingQuestionCriterionTrialRepository.BatchUpdateNoTrackingAsync(t => t.TrialId == trialConfig.TrialId && t.IsSigned == false, u => new ReadingQuestionCriterionTrial() { CriterionModalitys = trialConfig.Modalitys });
return ResponseOutput.Ok(await _repository.SaveChangesAsync());
}
@@ -1039,7 +1040,8 @@ namespace IRaCIS.Core.Application
if (trialConfig.TrialCriterionIds.Contains(item.Id))
{
item.IsConfirm = true;
- item.CriterionModalitys = trialInfo.Modalitys;
+
+ //item.CriterionModalitys = trialInfo.Modalitys;
}
else
{
diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/_MapConfig.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/_MapConfig.cs
index e0a46a7f5..5546e2036 100644
--- a/IRaCIS.Core.Application/Service/TrialSiteUser/_MapConfig.cs
+++ b/IRaCIS.Core.Application/Service/TrialSiteUser/_MapConfig.cs
@@ -249,7 +249,8 @@ namespace IRaCIS.Core.Application.Service
CreateMap()
- .ForMember(t => t.TrialModalitys, u => u.MapFrom(c => c.Trial.Modalitys));
+ .ForMember(t => t.TrialModalitys, u => u.MapFrom(c => c.Trial.Modalitys))
+ .ForMember(t => t.TrialReadingCriterionId, u => u.MapFrom(c => c.Id));
CreateMap()
diff --git a/IRaCIS.Core.Domain/Management/UserLog.cs b/IRaCIS.Core.Domain/Management/UserLog.cs
index 631eb51d2..9ed33bfb2 100644
--- a/IRaCIS.Core.Domain/Management/UserLog.cs
+++ b/IRaCIS.Core.Domain/Management/UserLog.cs
@@ -93,7 +93,11 @@ namespace IRaCIS.Core.Domain.Models
DeleteUser=10,
- UpdateUser=11
+ UpdateUser=11,
+
+ MFALogin=12,
+
+ MFALoginFail=13,
}
}
diff --git a/IRaCIS.Core.Domain/Reading/ReadingCriterion/ReadingQuestionCriterionTrial.cs b/IRaCIS.Core.Domain/Reading/ReadingCriterion/ReadingQuestionCriterionTrial.cs
index 0f69ee9c4..c27d34b15 100644
--- a/IRaCIS.Core.Domain/Reading/ReadingCriterion/ReadingQuestionCriterionTrial.cs
+++ b/IRaCIS.Core.Domain/Reading/ReadingCriterion/ReadingQuestionCriterionTrial.cs
@@ -279,6 +279,8 @@ namespace IRaCIS.Core.Domain.Models
public ReadingImageDownload? ImageDownloadEnum { get; set; }
public ReadingImageUpload? ImageUploadEnum { get; set; }
+
+ public bool IsImageFilter { get; set; }
}
public enum ReadingImageDownload
diff --git a/IRaCIS.Core.Domain/_Config/_AppSettings.cs b/IRaCIS.Core.Domain/_Config/_AppSettings.cs
index 0b7018505..679d6d101 100644
--- a/IRaCIS.Core.Domain/_Config/_AppSettings.cs
+++ b/IRaCIS.Core.Domain/_Config/_AppSettings.cs
@@ -22,6 +22,8 @@ namespace IRaCIS.Core.Domain.Share
public int LoginFailLockMinutes { get; set; }
public int AutoLoginOutMinutes { get; set; }
+
+ public bool OpenLoginMFA { get; set; }
}
public class SystemEmailSendConfig