diff --git a/IRaCIS.Core.API/Controllers/ExtraController.cs b/IRaCIS.Core.API/Controllers/ExtraController.cs index 0aaba76b6..68d71badf 100644 --- a/IRaCIS.Core.API/Controllers/ExtraController.cs +++ b/IRaCIS.Core.API/Controllers/ExtraController.cs @@ -106,195 +106,6 @@ namespace IRaCIS.Api.Controllers - /// 系统用户登录接口[New] - [HttpPost, Route("user/login")] - [AllowAnonymous] - public async Task Login(UserLoginDTO loginUser, - [FromServices] IFusionCache _fusionCache, - [FromServices] IUserService _userService, - [FromServices] ITokenService _tokenService, - [FromServices] IReadingImageTaskService readingImageTaskService, - [FromServices] IOptionsMonitor _verifyConfig, - [FromServices] IOptionsMonitor _emailConfig, - [FromServices] IMapper _mapper, - [FromServices] IMailVerificationService _mailVerificationService) - { - var emailConfig = _emailConfig.CurrentValue; - var companyInfo = new SystemEmailSendConfigView() { CompanyName = emailConfig.CompanyName, CompanyNameCN = emailConfig.CompanyNameCN, CompanyShortName = emailConfig.CompanyShortName, CompanyShortNameCN = emailConfig.CompanyShortNameCN }; - - //MFA 邮箱验证 前端传递用户Id 和MFACode - if (loginUser.UserId != null && _verifyConfig.CurrentValue.OpenLoginMFA) - { - Guid userId = (Guid)loginUser.UserId; - - //验证MFA 编码是否有问题 ,前端要拆开,自己调用验证的逻辑 - //await _userService.VerifyMFACodeAsync(userId, loginUser.MFACode); - - //var loginUser = await _userRoleRepository.Where(u => u.UserName.Equals(userName) && u.Password == password).ProjectTo(_mapper.ConfigurationProvider).FirstOrDefaultAsync(); - - var basicInfo = await _userService.GetUserBasicInfo(userId, loginUser.Password); - - var loginReturn = new LoginReturnDTO() { BasicInfo = basicInfo }; - - loginReturn.JWTStr = _tokenService.GetToken(new UserTokenInfo() { IdentityUserId = basicInfo.IdentityUserId }); - - - // 创建一个 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", loginReturn.JWTStr, option); - - // 验证阅片休息时间 - await readingImageTaskService.ResetReadingRestTime(userId); - - - await _fusionCache.SetAsync(CacheKeys.UserAutoLoginOut(userId), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(_verifyConfig.CurrentValue.AutoLoginOutMinutes)); - - loginReturn.CompanyInfo = companyInfo; - 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.IdentityUserId; - - if (_verifyConfig.CurrentValue.OpenLoginMFA) - { - - - - - //MFA 发送邮件 - - returnModel.Data.IsMFA = true; - - var email = returnModel.Data.BasicInfo.EMail; - - var hiddenEmail = IRCEmailPasswordHelper.MaskEmail(email); - - returnModel.Data.BasicInfo.EMail = hiddenEmail; - - //修改密码 - if (returnModel.Data.BasicInfo.IsFirstAdd || returnModel.Data.BasicInfo.LoginState == 1) - { - returnModel.Data.JWTStr = _tokenService.GetToken(_mapper.Map(returnModel.Data.BasicInfo)); - } - else - { - //正常登录才发送邮件 - await _userService.SendMFAEmail(new Core.Application.ViewModel.SendMfaCommand() { IdentityUserId= userId }); - - } - - } - else - { - returnModel.Data.JWTStr = _tokenService.GetToken(_mapper.Map(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.IdentityUserId); - - - - await _fusionCache.SetAsync(CacheKeys.UserAutoLoginOut(userId), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(_verifyConfig.CurrentValue.AutoLoginOutMinutes)); - } - - } - - returnModel.Data.CompanyInfo = companyInfo; - return returnModel; - - } - - - - - } - [AllowAnonymous] [HttpGet, Route("user/getPublicKey")] public IResponseOutput GetPublicKey([FromServices] IOptionsMonitor _IRCEncreptOption) diff --git a/IRaCIS.Core.API/IRaCIS.Core.API.xml b/IRaCIS.Core.API/IRaCIS.Core.API.xml index 556371672..df2392c13 100644 --- a/IRaCIS.Core.API/IRaCIS.Core.API.xml +++ b/IRaCIS.Core.API/IRaCIS.Core.API.xml @@ -34,9 +34,6 @@ - - 系统用户登录接口[New] - 回调到前端,前端调用后端的接口 diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml index d412a314d..d72802c4c 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -2288,14 +2288,14 @@ - + 账号验证,获取账号角色信息 获取临时token - + 验证密码成功后,选定角色,然后获取当前角色的Token @@ -12047,7 +12047,7 @@ - + IR影像阅片 diff --git a/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs b/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs index de447237f..b03622dab 100644 --- a/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs +++ b/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs @@ -2224,12 +2224,6 @@ namespace IRaCIS.Core.Application.Service.Common if (inQuery.ReadingExportType == ExportResult.DetailedTableOfAdjudicationResults) { - //R1 R2 两个人的访视都阅片完成了才可以,去除只有一个人阅片完成的访视 - - //找到只有一个人阅片的受试者 和访视 - var exceptVisit = list.GroupBy(t => new { t.SubjectCode, t.TaskName }).Where(g => g.Count() == 1).Select(g => new { g.Key.SubjectCode, g.Key.TaskName }).ToList(); - list = list.Where(t => !exceptVisit.Any(ev => ev.SubjectCode == t.SubjectCode && ev.TaskName == t.TaskName)).ToList(); - //裁判明表 export_Template = StaticData.Export.CommonJudgeReadingDetail_Export; } @@ -2704,12 +2698,23 @@ namespace IRaCIS.Core.Application.Service.Common #region 最终导出参数处理 + if (inQuery.ReadingExportType == ExportResult.DetailedTableOfAdjudicationResults) + { + //R1 R2 两个人的访视都阅片完成了才可以,去除只有一个人阅片完成的访视 + //找到只有一个人阅片的受试者 和访视 + var exceptVisit = list.Where(t => t.ReadingCategory == ReadingCategory.Visit) + .GroupBy(t => new { t.SubjectCode, t.TaskName}).Where(g => g.Count() == 1).Select(g => new { g.Key.SubjectCode, g.Key.TaskName }).ToList(); + + list = list.Where(t => !exceptVisit.Any(ev => ev.SubjectCode == t.SubjectCode && ev.TaskName == t.TaskName)).ToList(); + + } + list = list.OrderBy(t => t.SubjectCode).ThenBy(t => t.ArmEnum).ThenBy(t => t.VisitTaskNum).ToList(); //处理裁判标记 list = DealJudgeMark(criterion.ArbitrationRule, criterion.IsGlobalReading, list); - + //裁判阅片明细表 if (export_Template == StaticData.Export.CommonJudgeReadingDetail_Export) { //裁判产生标记为空的数据过滤掉 diff --git a/IRaCIS.Core.Application/Service/Management/UserService.cs b/IRaCIS.Core.Application/Service/Management/UserService.cs index dba110cb8..5e76c3dcb 100644 --- a/IRaCIS.Core.Application/Service/Management/UserService.cs +++ b/IRaCIS.Core.Application/Service/Management/UserService.cs @@ -888,7 +888,7 @@ namespace IRaCIS.Core.Application.Service if (_verifyConfig.CurrentValue.IsNeedChangePassWord && loginUser.LastChangePassWordTime != null && DateTime.Now.AddDays(-_verifyConfig.CurrentValue.ChangePassWordDays) > loginUser.LastChangePassWordTime.Value) { loginUser.NeedChangePassWord = true; - + } //await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = loginUser.IdentityUserId, OptUserId = loginUser.IdentityUserId, OptType = UserOptType.Login }, true); @@ -968,8 +968,8 @@ namespace IRaCIS.Core.Application.Service [HttpPost] public async Task> GetUserLoginRoleList(IRCLoginDto loginDto, [FromServices] ITokenService _tokenService, - [FromServices] IOptionsMonitor _emailConfig, - [FromServices] IReadingImageTaskService readingImageTaskService) + [FromServices] IOptionsMonitor _emailConfig + ) { var userName = loginDto.UserName; @@ -1012,55 +1012,83 @@ namespace IRaCIS.Core.Application.Service var loginUser = await _identityUserRepository.Where(u => u.UserName.Equals(userName) && u.Password == password).ProjectTo(_mapper.ConfigurationProvider).FirstOrDefaultAsync(); + var existUserLoginInfo = await _identityUserRepository.Where(u => u.UserName == userName).Select(t => new { t.LastLoginIP, t.LastChangePassWordTime, t.Id }).FirstOrDefaultAsync(); + + var isExistAccount = existUserLoginInfo != null; + + var isLoginUncommonly = false; + + #region //登录用户是系统用户的时候,就要要记录异地登录 + + //账号在系统存在 + if (isExistAccount || loginUser != null) + { + var ipinfo = _searcher.Search(_userInfo.IP); + + var iPRegion = string.Join('|', ipinfo.Split('|').TakeLast(3)); + + string SplitAndConcatenate(string input) + { + string[] parts = input.Split('|'); + return parts.Length >= 3 ? parts[0] + parts[1] : string.Join("", parts); + } + + if (existUserLoginInfo.LastLoginIP != string.Empty) + { + // 与上一次区域不一致 + if (SplitAndConcatenate(existUserLoginInfo.LastLoginIP) != SplitAndConcatenate(iPRegion)) + { + + isLoginUncommonly = true; + + //设置上次登录的IP + await _identityUserRepository.BatchUpdateNoTrackingAsync(x => x.Id == existUserLoginInfo.Id, x => new IdentityUser() + { + LastLoginIP = iPRegion, + LastLoginTime = DateTime.Now + + }); + + if (loginUser != null) + { + //异地登录 + loginUser.LoginState = 2; + + //超过90天没修改密码 + if (_verifyConfig.CurrentValue.IsNeedChangePassWord && loginUser.LastChangePassWordTime != null && DateTime.Now.AddDays(-_verifyConfig.CurrentValue.ChangePassWordDays) > loginUser.LastChangePassWordTime.Value) + { + loginUser.NeedChangePassWord = true; + } + } + } + } + + } + + #endregion + + if (loginUser == null) { //错误次数累加 failCount++; + await _fusionCache.SetAsync(cacheKey, failCount, TimeSpan.FromMinutes(lockoutMinutes)); - var errorPwdUserId = await _identityUserRepository.Where(u => u.UserName == userName).Select(t => t.Id).FirstOrDefaultAsync(); - - await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionUserName = userName, LoginPassword = password, OptType = UserOptType.AccountOrPasswordError }, true); + await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionUserName = userName, LoginPassword = password, OptType = UserOptType.AccountOrPasswordError, IsLoginUncommonly = isLoginUncommonly }, true); return ResponseOutput.NotOk(_localizer["User_CheckNameOrPw"], new IRCLoginReturnDTO()); } - //登录用户是系统用户的时候,就要要记录异地登录 - - #region 处理用户状态 - var ipinfo = _searcher.Search(_userInfo.IP); - var iPRegion = string.Join('|', ipinfo.Split('|').TakeLast(3)); - - string SplitAndConcatenate(string input) - { - string[] parts = input.Split('|'); - return parts.Length >= 3 ? parts[0] + parts[1] : string.Join("", parts); - } - - if (loginUser.LastLoginIP != string.Empty) - { - // 与上一次区域不一致 - if (SplitAndConcatenate(loginUser.LastLoginIP) != SplitAndConcatenate(iPRegion)) - { - loginUser.LoginState = 2; - } - } - //超过90天没修改密码 - if (_verifyConfig.CurrentValue.IsNeedChangePassWord && loginUser.LastChangePassWordTime != null && DateTime.Now.AddDays(-_verifyConfig.CurrentValue.ChangePassWordDays) > loginUser.LastChangePassWordTime.Value) - { - loginUser.NeedChangePassWord = true; - } - - #endregion if (loginUser.Status == 0) { - await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionIdentityUserId = loginUser.IdentityUserId, ActionUserName = userName, OptType = UserOptType.LoginLockedAccount, IsLoginUncommonly = (loginUser.LoginState == 2) }, true); + await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionIdentityUserId = loginUser.IdentityUserId, ActionUserName = userName, OptType = UserOptType.LoginLockedAccount, IsLoginUncommonly = isLoginUncommonly }, true); //---该用户已经被禁用。 return ResponseOutput.NotOk(_localizer["User_Disabled"], new IRCLoginReturnDTO()); @@ -1070,7 +1098,7 @@ namespace IRaCIS.Core.Application.Service await _fusionCache.SetAsync(cacheKey, 0, TimeSpan.FromMinutes(lockoutMinutes)); - await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionIdentityUserId = loginUser.IdentityUserId, OptType = UserOptType.Login, IsLoginUncommonly = (loginUser.LoginState == 2) }, true); + await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionIdentityUserId = loginUser.IdentityUserId, OptType = UserOptType.Login, IsLoginUncommonly = isLoginUncommonly }, true); userLoginReturnModel.BasicInfo = loginUser; @@ -1084,12 +1112,7 @@ namespace IRaCIS.Core.Application.Service } - await _identityUserRepository.BatchUpdateNoTrackingAsync(x => x.Id == loginUser.IdentityUserId, x => new IdentityUser() - { - LastLoginIP = iPRegion, - LastLoginTime = DateTime.Now - }); //返回临时token userLoginReturnModel.JWTStr = _tokenService.GetToken(new UserTokenInfo() { IdentityUserId = loginUser.IdentityUserId, UserName = userName }); @@ -1112,7 +1135,7 @@ namespace IRaCIS.Core.Application.Service userLoginReturnModel.BasicInfo.EMail = hiddenEmail; //修改密码 || 90天修改密码再mfa 之前 - if (userLoginReturnModel.BasicInfo.IsFirstAdd || userLoginReturnModel.BasicInfo.LoginState == 1) + if (userLoginReturnModel.BasicInfo.IsFirstAdd || userLoginReturnModel.BasicInfo.NeedChangePassWord) { //userLoginReturnModel.JWTStr = _tokenService.GetToken(userLoginReturnModel.BasicInfo); } @@ -1126,8 +1149,6 @@ namespace IRaCIS.Core.Application.Service } else { - // 验证阅片休息时间 - await readingImageTaskService.ResetReadingRestTime(userLoginReturnModel.BasicInfo.IdentityUserId); await _fusionCache.SetAsync(CacheKeys.UserToken(identityUserId), userLoginReturnModel.JWTStr, TimeSpan.FromDays(7)); @@ -1149,7 +1170,7 @@ namespace IRaCIS.Core.Application.Service /// /// [HttpGet] - public async Task LoginSelectUserRole(Guid userRoleId, [FromServices] ITokenService _tokenService) + public async Task LoginSelectUserRole(Guid userRoleId, [FromServices] ITokenService _tokenService, [FromServices] IReadingImageTaskService readingImageTaskService) { var identityUserId = _userInfo.IdentityUserId; @@ -1173,6 +1194,8 @@ namespace IRaCIS.Core.Application.Service { var jwt = _tokenService.GetToken(userTokenInfo); + // 验证阅片休息时间 + await readingImageTaskService.ResetReadingRestTime(userTokenInfo.UserRoleId); await _fusionCache.SetAsync(CacheKeys.UserToken(userTokenInfo.IdentityUserId), jwt, TimeSpan.FromDays(7)); diff --git a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs index f35a4e975..e83bcef85 100644 --- a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs @@ -4,6 +4,7 @@ using IRaCIS.Core.Application.Filter; using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.Interfaces; using IRaCIS.Core.Application.Service.ImageAndDoc; +using IRaCIS.Core.Application.Service.OAuth; using IRaCIS.Core.Application.Service.Reading.Dto; using IRaCIS.Core.Application.Service.ReadingCalculate.Interface; using IRaCIS.Core.Application.ViewModel; @@ -31,6 +32,7 @@ namespace IRaCIS.Core.Application.Service IRepository _noneDicomStudyRepository, IRepository _visitTaskRepository, IRepository _trialRepository, + IRepository _userLogRepository, IRepository _readingTableQuestionAnswerRepository, IRepository _readingOncologyTaskInfoRepository, IVisitTaskHelpeService _visitTaskHelpeService, @@ -101,7 +103,7 @@ namespace IRaCIS.Core.Application.Service await _readingTableQuestionAnswerRepository.DeleteFromQueryAsync(x => x.RowId == mark.RowId && x.TableQuestionId == mark.TableQuestionId); await _readingTaskQuestionMarkRepository.UpdatePartialFromQueryAsync(x => x.Id == inDto.Id, x => new ReadingTaskQuestionMark() { - InstanceId=null, + InstanceId = null, SeriesId = null, StudyId = null, MarkTool = string.Empty, @@ -117,7 +119,7 @@ namespace IRaCIS.Core.Application.Service OtherNumberOfFrames = null, OtherMeasureData = string.Empty, }); - var result= await _readingTaskQuestionMarkRepository.SaveChangesAsync(); + var result = await _readingTaskQuestionMarkRepository.SaveChangesAsync(); await _readingCalculateService.CalculateTask(new CalculateTaskInDto() { @@ -145,7 +147,7 @@ namespace IRaCIS.Core.Application.Service SeriesId = null, StudyId = null, MarkTool = string.Empty, - // PicturePath = string.Empty, 稽查需要显示截图 + // PicturePath = string.Empty, 稽查需要显示截图 NumberOfFrames = null, MeasureData = string.Empty, OrderMarkName = string.Empty, @@ -451,7 +453,7 @@ namespace IRaCIS.Core.Application.Service /// /// [HttpPost] - [TrialGlobalLimit( "AfterStopCannNotOpt" )] + [TrialGlobalLimit("AfterStopCannNotOpt")] public async Task ChangeCalculationAnswer(ChangeCalculationAnswerInDto inDto) { var visitTask = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync(); @@ -527,7 +529,7 @@ namespace IRaCIS.Core.Application.Service /// /// [HttpPost] - [TrialGlobalLimit( "AfterStopCannNotOpt" )] + [TrialGlobalLimit("AfterStopCannNotOpt")] public async Task ReadClinicalData(ReadClinicalDataInDto inDto) { await _visitTaskRepository.UpdatePartialFromQueryAsync(inDto.VisitTaskId, x => new VisitTask @@ -904,7 +906,7 @@ namespace IRaCIS.Core.Application.Service var criterionIdInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == trialReadingCriterionId).FirstNotNullAsync(); - var groupIds = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == trialReadingCriterionId &&( x.Type == ReadingQestionType.Table || x.Type == ReadingQestionType.BasicTable)).Select(x => x.GroupId).Distinct().ToListAsync(); + var groupIds = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == trialReadingCriterionId && (x.Type == ReadingQestionType.Table || x.Type == ReadingQestionType.BasicTable)).Select(x => x.GroupId).Distinct().ToListAsync(); var questionIds = await _readingQuestionTrialRepository .Where(x => x.IsShowInDicom) @@ -1088,7 +1090,7 @@ namespace IRaCIS.Core.Application.Service x.IsFirstChangeTask = x.VisitTaskId == inDto.VisitTaskId; }); result.AddRange(questionMark); - result= result.OrderBy(x=>x.ShowOrder).ThenBy(x=>x.RowIndex).ThenBy(x => x.OrderMarkName).ToList(); + result = result.OrderBy(x => x.ShowOrder).ThenBy(x => x.RowIndex).ThenBy(x => x.OrderMarkName).ToList(); return result; } @@ -1439,7 +1441,7 @@ namespace IRaCIS.Core.Application.Service item.TableQuestions.Questions = tableQuestionLists.Where(x => x.ReadingQuestionId == item.Id).OrderBy(x => x.ShowOrder).ToList(); item.TableQuestions.Questions.ForEach(x => { - x.RelationQuestions= _mapper.Map>(tableQuestionLists.Where(z => (z.DependParentId ?? default(Guid)) == x.Id)); + x.RelationQuestions = _mapper.Map>(tableQuestionLists.Where(z => (z.DependParentId ?? default(Guid)) == x.Id)); x.RelationQuestions.ForEach(y => { y.Childrens = new List(); @@ -1449,7 +1451,7 @@ namespace IRaCIS.Core.Application.Service y.LesionType = item.LesionType; y.RelationQuestions = new List(); }); - + }); var thisAnswer = tableAnswers.Where(x => x.QuestionId == item.Id).ToList(); @@ -1560,7 +1562,7 @@ namespace IRaCIS.Core.Application.Service { FloatParseHandling = FloatParseHandling.Double, }; - answers.Add("TableQuestionMarkList", rowInfo == null ? "[]" : JsonConvert.SerializeObject(TableQuestionMarkList.Where(x=>x.RowId== rowInfo.Id).ToList(), settings)); + answers.Add("TableQuestionMarkList", rowInfo == null ? "[]" : JsonConvert.SerializeObject(TableQuestionMarkList.Where(x => x.RowId == rowInfo.Id).ToList(), settings)); answers.Add("RowId", rowInfo == null ? string.Empty : rowInfo.Id.ToString()); answers.Add("MarkTool", rowInfo.MarkTool); answers.Add("StudyId", rowInfo.StudyId.ToString()); @@ -1609,7 +1611,7 @@ namespace IRaCIS.Core.Application.Service /// /// [HttpPost] - [TrialGlobalLimit( "AfterStopCannNotOpt" )] + [TrialGlobalLimit("AfterStopCannNotOpt")] public async Task SplitLesion(SplitLesionInDto inDto) { await VerifyTaskIsSign(inDto.VisitTaskId); @@ -1847,7 +1849,7 @@ namespace IRaCIS.Core.Application.Service /// [HttpPost] - [TrialGlobalLimit( "AfterStopCannNotOpt" )] + [TrialGlobalLimit("AfterStopCannNotOpt")] public async Task SaveImageQuality(ChangeDicomReadingQuestionAnswerInDto inDto) { inDto.UpdateMark = true; @@ -1906,7 +1908,7 @@ namespace IRaCIS.Core.Application.Service /// /// [HttpPost] - [TrialGlobalLimit( "AfterStopCannNotOpt" )] + [TrialGlobalLimit("AfterStopCannNotOpt")] public async Task ChangeDicomReadingQuestionAnswer(ChangeDicomReadingQuestionAnswerInDto inDto) { await VerifyTaskIsSign(inDto.VisitTaskId); @@ -2023,7 +2025,7 @@ namespace IRaCIS.Core.Application.Service /// /// [HttpPost] - [TrialGlobalLimit( "AfterStopCannNotOpt" )] + [TrialGlobalLimit("AfterStopCannNotOpt")] public async Task DeleteReadingRowAnswer(DeleteReadingRowAnswerInDto inDto) { await VerifyTaskIsSign(inDto.VisitTaskId); @@ -2212,7 +2214,7 @@ namespace IRaCIS.Core.Application.Service /// [HttpPost] [Route("/SubmitTaskRowInfo/{param}")] - public async Task SubmitTaskRowInfo(SubmitTableQuestionInDto inDto,string param) + public async Task SubmitTaskRowInfo(SubmitTableQuestionInDto inDto, string param) { inDto.ComputationTrigger = (ComputationTrigger)int.Parse(param); @@ -2226,7 +2228,7 @@ namespace IRaCIS.Core.Application.Service /// /// [HttpPost] - [TrialGlobalLimit( "AfterStopCannNotOpt" )] + [TrialGlobalLimit("AfterStopCannNotOpt")] public async Task SubmitTableQuestion(SubmitTableQuestionInDto inDto) { SubmitTableQuestionOutDto result = new SubmitTableQuestionOutDto(); @@ -2413,7 +2415,7 @@ namespace IRaCIS.Core.Application.Service && x.QuestionId == inDto.QuestionId ).CountAsync()) + 1)) { - throw new BusinessValidationFailedException(_localizer["ReadingImage_MaxQuestion", _userInfo.IsEn_Us? questionInfo.QuestionEnName:questionInfo.QuestionName, questionInfo.MaxQuestionCount]); + throw new BusinessValidationFailedException(_localizer["ReadingImage_MaxQuestion", _userInfo.IsEn_Us ? questionInfo.QuestionEnName : questionInfo.QuestionName, questionInfo.MaxQuestionCount]); } } @@ -2625,7 +2627,7 @@ namespace IRaCIS.Core.Application.Service /// /// /// - [TrialGlobalLimit( "AfterStopCannNotOpt" )] + [TrialGlobalLimit("AfterStopCannNotOpt")] public async Task SubmitDicomVisitTask(SubmitDicomVisitTaskInDto inDto) { @@ -2710,7 +2712,7 @@ namespace IRaCIS.Core.Application.Service var criterion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == taskInfo.TrialReadingCriterionId).FirstNotNullAsync(); - var readingQuestionList = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == taskInfo.TrialReadingCriterionId&&x.Type != "group") + var readingQuestionList = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == taskInfo.TrialReadingCriterionId && x.Type != "group") .WhereIf(taskInfo.SourceSubjectVisit.IsBaseLine, x => ((x.IsRequired == IsRequired.Required && x.ShowQuestion == ShowQuestion.Show) && (x.LimitEdit == LimitEdit.None || x.LimitEdit == LimitEdit.OnlyBaseLine))) .WhereIf(!taskInfo.SourceSubjectVisit.IsBaseLine, x => ((x.IsRequired == IsRequired.Required && x.ShowQuestion == ShowQuestion.Show) && (x.LimitEdit == LimitEdit.None || x.LimitEdit == LimitEdit.OnlyVisit))) .WhereIf(taskInfo.TrialReadingCriterion.CriterionType == CriterionType.PCWG3, x => x.QuestionType != QuestionType.SiteVisitForTumorEvaluation) @@ -2988,7 +2990,7 @@ namespace IRaCIS.Core.Application.Service List remainingItems = taskList.Select(x => x.Id).Except(cacheSkipIds).ToList(); //受试者随机固定排序 - taskList = taskList.Where(x => remainingItems.Contains(x.Id)).OrderBy(t=>t.TaskBlindName).ToList(); + taskList = taskList.Where(x => remainingItems.Contains(x.Id)).OrderBy(t => t.TaskBlindName).ToList(); // 当前受试者没有就找其他受试者 if (taskList.Count() == 0) @@ -3048,7 +3050,7 @@ namespace IRaCIS.Core.Application.Service var query = _visitTaskRepository.Where(x => x.TrialId == inDto.TrialId && x.TrialReadingCriterionId == trialReadingCriterionId && x.ReadingTaskState != ReadingTaskState.HaveSigned && x.DoctorUserId == _userInfo.UserRoleId && x.TrialReadingCriterionId == trialReadingCriterionId && x.TaskState == TaskState.Effect) - .Where(x=> !cacheSkipIds.Contains(x.Id)); + .Where(x => !cacheSkipIds.Contains(x.Id)); var count = await query.CountAsync(); if (count == 0) { @@ -3273,31 +3275,36 @@ namespace IRaCIS.Core.Application.Service /// /// [HttpPost] - public async Task ResetReadingRestTime(Guid? userID) + public async Task ResetReadingRestTime(Guid? userRoleId) { - if (userID == null) - { - userID = _userInfo.UserRoleId; - } + var roleId = (userRoleId != null && userRoleId != Guid.Empty) ? (Guid) userRoleId : _userInfo.UserRoleId; //int readingMinute = 120; // 为60整数 int restMinute = 10; // - var startReadingTime = await _fusionCache.GetOrDefaultAsync(CacheKeys.StartReadingTimeKey(_userInfo.UserRoleId)); - var startRestTime = await _fusionCache.GetOrDefaultAsync(CacheKeys.StartRestTime(_userInfo.UserRoleId)); + var startReadingTime = await _fusionCache.GetOrDefaultAsync(CacheKeys.StartReadingTimeKey(roleId)); + var startRestTime = await _fusionCache.GetOrDefaultAsync(CacheKeys.StartRestTime(roleId)); if (startRestTime != null) { var cacheStartRestTime = DateTime.Parse(startRestTime!.ToString()); int timespanMin = (DateTime.Now - cacheStartRestTime).Minutes; if (timespanMin > restMinute) { - await _fusionCache.RemoveAsync(CacheKeys.StartRestTime(_userInfo.UserRoleId)); + await _fusionCache.RemoveAsync(CacheKeys.StartRestTime(roleId)); } } else if (startReadingTime != null) { - await _fusionCache.SetAsync(CacheKeys.StartReadingTimeKey(_userInfo.UserRoleId), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromHours(48)); + await _fusionCache.SetAsync(CacheKeys.StartReadingTimeKey(roleId), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromHours(48)); } + + //前端屏幕解锁才调用 + if (userRoleId == null) + { + await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionIdentityUserId = _userInfo.IdentityUserId, OptType = UserOptType.WebUnlock }, true); + + } + return true; } @@ -3525,7 +3532,7 @@ namespace IRaCIS.Core.Application.Service /// /// [HttpPost] - [TrialGlobalLimit( "AfterStopCannNotOpt" )] + [TrialGlobalLimit("AfterStopCannNotOpt")] public async Task AddReadingTask(Guid visitTaskId, Guid? trialId = null) { // ****** 先生成阅片期 阅片期任务阅片完成之后生成肿瘤学的 如果没有阅片期 直接生成肿瘤学 *********//// diff --git a/IRaCIS.Core.Domain.Share/Reading/ImageFilterState.cs b/IRaCIS.Core.Domain.Share/Reading/ImageFilterState.cs index 8fdd57ae8..60bef07e3 100644 --- a/IRaCIS.Core.Domain.Share/Reading/ImageFilterState.cs +++ b/IRaCIS.Core.Domain.Share/Reading/ImageFilterState.cs @@ -50,7 +50,9 @@ public enum UserOptType TempLockLogin = 13, - AddUser = 14 + AddUser = 14, + + WebUnlock=16 } [Description("影像下载打包状态")]