diff --git a/IRC.Core.SCP/Service/PatientStudyService.cs b/IRC.Core.SCP/Service/PatientStudyService.cs
index f41366145..a809fd90c 100644
--- a/IRC.Core.SCP/Service/PatientStudyService.cs
+++ b/IRC.Core.SCP/Service/PatientStudyService.cs
@@ -78,7 +78,26 @@ namespace IRaCIS.Core.SCP.Service
//3、 未提交的最小的访视号 从这个访视开始绑定
- var subjectMaxVisitNum = startBindVisitNum == null ? subjectAllVisitList.Where(t => t.SubmitState != SubmitStateEnum.Submitted).MinOrDefault(t => t.VisitNum) : startBindVisitNum.Value;
+ decimal subjectMaxVisitNum = 0;
+
+ if (startBindVisitNum == null)
+ {
+ if (subjectAllVisitList.Any(t => t.SubmitState != SubmitStateEnum.Submitted))
+ {
+ subjectMaxVisitNum = subjectAllVisitList.Where(t => t.SubmitState != SubmitStateEnum.Submitted).MinOrDefault(t => t.VisitNum);
+ }
+ else
+ {
+ //没有未提交的,那么开始绑定的就是已提交的加1
+ subjectMaxVisitNum = subjectAllVisitList.Last().VisitNum + 1;
+ }
+ }
+ else
+ {
+ subjectMaxVisitNum = startBindVisitNum.Value;
+ }
+
+ //var subjectMaxVisitNum = startBindVisitNum == null ? subjectAllVisitList.Where(t => t.SubmitState != SubmitStateEnum.Submitted).MinOrDefault(t => t.VisitNum) : startBindVisitNum.Value;
List<(int VisitCount, Guid SCPStudyId)> visits = new List<(int, Guid)>();
diff --git a/IRaCIS.Core.API/appsettings.Test_HIR.json b/IRaCIS.Core.API/appsettings.Test_HIR.json
index 0f52c6d19..093dc9938 100644
--- a/IRaCIS.Core.API/appsettings.Test_HIR.json
+++ b/IRaCIS.Core.API/appsettings.Test_HIR.json
@@ -21,7 +21,7 @@
//"viewEndpoint": "https://hir.test.extimaging.com/oss/hir-test"
"ViewEndpoint": "https://hir-oss.test.extimaging.com/hir-test"
}
-
+
},
"ConnectionStrings": {
"RemoteNew": "Server=106.14.89.110,1435;Database=Test_HIR_New;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
@@ -41,7 +41,8 @@
// 是否强制用户定期修改密码
"IsNeedChangePassWord": true,
// 密码有效期(天),到期后必须修改
- "ChangePassWordDays": 1000
+ "ChangePassWordDays": 1000,
+ "OpenImageShare": true,
},
"SystemEmailSendConfig": {
diff --git a/IRaCIS.Core.Application/BusinessFilter/_Config/_AppSettings.cs b/IRaCIS.Core.Application/BusinessFilter/_Config/_AppSettings.cs
index 465bf5d6e..702d3fc24 100644
--- a/IRaCIS.Core.Application/BusinessFilter/_Config/_AppSettings.cs
+++ b/IRaCIS.Core.Application/BusinessFilter/_Config/_AppSettings.cs
@@ -43,6 +43,8 @@ public class ServiceVerifyConfigOption
public int CmoveInstanceIntervalMinutes { get; set; }
+
+ public bool OpenImageShare { get; set; }
}
public class SystemEmailSendConfig
@@ -92,6 +94,8 @@ public class SystemEmailSendConfigView
public string CompanyShortNameCN { get; set; } = string.Empty;
public string EmailRegexStr { get; set; }
+
+ public bool OpenImageShare { get; set; }
}
public class SystemPacsConfig
diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
index 512b1297b..71bf4b20b 100644
--- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
+++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
@@ -2154,7 +2154,7 @@
-
+
账号验证,获取账号角色信息 获取临时token
@@ -12648,7 +12648,7 @@
-
+
IR影像阅片
@@ -12993,6 +12993,14 @@
+
+
+ 前端 仅仅释放的时候使用,领取是后端调用该方法
+
+
+
+
+
重置阅片时间 登录和解锁调用
diff --git a/IRaCIS.Core.Application/MassTransit/Consumer/SubjectCriterionClaimCancelConsumer.cs b/IRaCIS.Core.Application/MassTransit/Consumer/SubjectCriterionClaimCancelConsumer.cs
new file mode 100644
index 000000000..c284c21dc
--- /dev/null
+++ b/IRaCIS.Core.Application/MassTransit/Consumer/SubjectCriterionClaimCancelConsumer.cs
@@ -0,0 +1,38 @@
+using IRaCIS.Core.Domain;
+using IRaCIS.Core.Domain._DomainEvent;
+using IRaCIS.Core.Domain.Models;
+using MassTransit;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace IRaCIS.Core.Application.MassTransit.Consumer
+{
+ public class SubjectCriterionClaimCancelConsumer(IRepository _visitTaskRepository) : IConsumer
+ {
+ public async Task Consume(ConsumeContext context)
+ {
+
+ Log.Logger.Warning($"定时任务取消领取!{context.Message.ToJsonStr()}");
+ bool isInOrder = context.Message.IsInOrder;
+
+ if (isInOrder)
+ {
+ Guid subjectId = (Guid)context.Message.SubjectId;
+
+ Guid trialReadingCriterionId = (Guid)context.Message.TrialReadingCriterionId;
+
+ await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.ReadingTaskState != ReadingTaskState.HaveSigned, u => new VisitTask() { SubjectCriterionClaimUserId = null });
+
+ }
+ else
+ {
+ Guid id = (Guid)context.Message.VisitTaskId;
+
+ await _visitTaskRepository.UpdatePartialFromQueryAsync(t => t.Id == id && t.ReadingTaskState != ReadingTaskState.HaveSigned, u => new VisitTask() { DoctorUserId = null }, true);
+ }
+ }
+ }
+}
diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/ImageShareService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/ImageShareService.cs
index 398546f4c..1c9a46264 100644
--- a/IRaCIS.Core.Application/Service/ImageAndDoc/ImageShareService.cs
+++ b/IRaCIS.Core.Application/Service/ImageAndDoc/ImageShareService.cs
@@ -5,6 +5,7 @@ using IRaCIS.Core.Application.Contracts.Dicom.DTO;
using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
+using System.Windows.Input;
namespace IRaCIS.Core.Application.Services
{
@@ -27,6 +28,7 @@ namespace IRaCIS.Core.Application.Services
var addEntity = await _imageShareRepository.AddAsync(imageShare);
+ addEntity.ExpireTime = DateTime.Now.AddDays(7);
//验证码 4位
int verificationPassWord = new Random().Next(1000, 10000);
@@ -36,7 +38,7 @@ namespace IRaCIS.Core.Application.Services
var success = await _imageShareRepository.SaveChangesAsync();
- return ResponseOutput.Result(success, new { ResourceId = imageShare.Id, Password = verificationPassWord.ToString() });
+ return ResponseOutput.Result(success, new { ResourceId = imageShare.Id, Password = verificationPassWord.ToString(), ImageShareExpireDays = 7 });
}
diff --git a/IRaCIS.Core.Application/Service/Management/UserService.cs b/IRaCIS.Core.Application/Service/Management/UserService.cs
index cb816f4b3..3b041089c 100644
--- a/IRaCIS.Core.Application/Service/Management/UserService.cs
+++ b/IRaCIS.Core.Application/Service/Management/UserService.cs
@@ -461,6 +461,8 @@ namespace IRaCIS.Core.Application.Service
public async Task> GetUserList(UserListQueryDTO inQuery)
{
+ var isGAGroupAdmin = _userInfo.HospitalGroupAdminIdList.Any();
+
var userQueryable = _identityUserRepository.Where(x => x.UserRoleList.Any(x => x.UserTypeEnum != UserTypeEnum.SuperAdmin))
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.UserName), t => t.UserName.Contains(inQuery.UserName))
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.RealName), t => t.FullName.Contains(inQuery.RealName))
@@ -482,8 +484,8 @@ namespace IRaCIS.Core.Application.Service
.WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.OA, t => !t.UserRoleList.Any(t => t.UserTypeEnum == UserTypeEnum.Admin || t.UserTypeEnum == UserTypeEnum.SuperAdmin))
//GA 只能看有该课题组的用户,并且不是admin oa
- .WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.GA && _userInfo.HospitalGroupAdminIdList.Any(), t => !t.UserRoleList.Any(t => t.UserTypeEnum == UserTypeEnum.Admin || t.UserTypeEnum == UserTypeEnum.SuperAdmin || t.UserTypeEnum == UserTypeEnum.OA)
- && t.IdentityUserHospitalGroupList.Any(t => _userInfo.HospitalGroupAdminIdList.Contains(t.HospitalGroupId)))
+ .WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.GA, t => !t.UserRoleList.Any(t => t.UserTypeEnum == UserTypeEnum.Admin || t.UserTypeEnum == UserTypeEnum.SuperAdmin || t.UserTypeEnum == UserTypeEnum.OA)
+ && t.IdentityUserHospitalGroupList.Any(t => isGAGroupAdmin ? _userInfo.HospitalGroupAdminIdList.Contains(t.HospitalGroupId) : false))
.ProjectTo(_mapper.ConfigurationProvider);
return await userQueryable.ToPagedListAsync(inQuery);
@@ -1123,7 +1125,8 @@ namespace IRaCIS.Core.Application.Service
[HttpPost]
public async Task> GetUserLoginRoleList(IRCLoginDto loginDto,
[FromServices] ITokenService _tokenService,
- [FromServices] IOptionsMonitor _emailConfig
+ [FromServices] IOptionsMonitor _emailConfig,
+ [FromServices] IOptionsMonitor _basicSystemConfigConfig
)
{
@@ -1131,7 +1134,10 @@ namespace IRaCIS.Core.Application.Service
var password = loginDto.Password;
var emailConfig = _emailConfig.CurrentValue;
+ var basicConfig = _basicSystemConfigConfig.CurrentValue;
var companyInfo = new SystemEmailSendConfigView() { CompanyName = emailConfig.CompanyName, CompanyNameCN = emailConfig.CompanyNameCN, CompanyShortName = emailConfig.CompanyShortName, CompanyShortNameCN = emailConfig.CompanyShortNameCN, SystemShortName = emailConfig.SystemShortName, EmailRegexStr = emailConfig.EmailRegexStr };
+ companyInfo.OpenImageShare = basicConfig.OpenImageShare;
+
int maxFailures = _verifyConfig.CurrentValue.LoginMaxFailCount;
diff --git a/IRaCIS.Core.Application/Service/Reading/Dto/ReadingImageTaskViewModel.cs b/IRaCIS.Core.Application/Service/Reading/Dto/ReadingImageTaskViewModel.cs
index 586df651b..93efa7aff 100644
--- a/IRaCIS.Core.Application/Service/Reading/Dto/ReadingImageTaskViewModel.cs
+++ b/IRaCIS.Core.Application/Service/Reading/Dto/ReadingImageTaskViewModel.cs
@@ -3074,4 +3074,17 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
//{
//}
+
+ public class ClaimSubjectDto
+ {
+ public bool IsInOrder { get; set; }
+
+ public Guid? VisitTaskId { get; set; }
+
+ public Guid TrialReadingCriterionId { get; set; }
+
+ public Guid SubejctId { get; set; }
+
+ public bool IsClaim { get; set; }
+ }
}
diff --git a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs
index b538e50cd..09835644c 100644
--- a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs
+++ b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs
@@ -12,13 +12,18 @@ using IRaCIS.Core.Infra.EFCore.Common;
using IRaCIS.Core.Infrastructure;
using MassTransit;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NPOI.POIFS.Properties;
using NPOI.SS.Formula.Functions;
using Panda.DynamicWebApi.Attributes;
+using System.Reactive.Concurrency;
using ZiggyCreatures.Caching.Fusion;
+using IRaCIS.Core.Domain.BaseModel;
+using IRaCIS.Core.Domain._DomainEvent;
namespace IRaCIS.Core.Application.Service
{
@@ -30,6 +35,7 @@ namespace IRaCIS.Core.Application.Service
IRepository _noneDicomStudyRepository,
IRepository _visitTaskRepository,
IRepository _trialRepository,
+ IMessageScheduler _scheduler,
IRepository _readingTableQuestionAnswerRepository,
IRepository _readingOncologyTaskInfoRepository,
IVisitTaskHelpeService _visitTaskHelpeService,
@@ -72,9 +78,9 @@ namespace IRaCIS.Core.Application.Service
[HttpPost]
public async Task GetTNMValue(TNMValueDto inDto)
{
- var result= await _visitTaskRepository.Where(x=>x.Id==inDto.VisitTaskId).Select(x => new TNMValueDto()
+ var result = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Select(x => new TNMValueDto()
{
- VisitTaskId=inDto.VisitTaskId,
+ VisitTaskId = inDto.VisitTaskId,
TNMValue = x.TNMValue
}).FirstOrDefaultAsync();
return result;
@@ -93,7 +99,7 @@ namespace IRaCIS.Core.Application.Service
await _visitTaskRepository.UpdatePartialFromQueryAsync(x => x.Id == inDto.VisitTaskId, x => new VisitTask()
{
TNMValue = inDto.TNMValue
- },true);
+ }, true);
return inDto;
}
@@ -771,6 +777,11 @@ namespace IRaCIS.Core.Application.Service
}
+ if (await _visitTaskRepository.AnyAsync(x => x.Id == visitTaskid && x.DoctorUserId != _userInfo.UserRoleId && x.SubjectCriterionClaimUserId != _userInfo.UserRoleId))
+ {
+ throw new BusinessValidationFailedException(_localizer["其他人已领取该任务,不允许操作"]);
+ }
+
if (await _visitTaskRepository.AnyAsync(x => x.Id == visitTaskid && x.TaskState != TaskState.Effect))
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_Beinvalid"]);
@@ -2869,7 +2880,11 @@ namespace IRaCIS.Core.Application.Service
TrialReadingCriterionId = x.TrialReadingCriterionId,
}).FirstOrDefault();
-
+ if (task != null)
+ {
+ // 有序 自动领取该Subject
+ await ClaimOrCancelSubjectAsync(new ClaimSubjectDto() { IsClaim = true, SubejctId = task.SubjectId, TrialReadingCriterionId = task.TrialReadingCriterionId, VisitTaskId = task.VisitTaskId, IsInOrder = true });
+ }
}
else if (inDto.SubjectId != null && trialReadingCriterion.IsReadingTaskViewInOrder == ReadingOrder.SubjectRandom)
@@ -2996,6 +3011,12 @@ namespace IRaCIS.Core.Application.Service
TrialReadingCriterionId = x.TrialReadingCriterionId,
}).Skip(skipcount).FirstOrDefaultAsync();
+ if (task != null)
+ {
+ // 无序
+ await ClaimOrCancelSubjectAsync(new ClaimSubjectDto() { IsClaim = true, VisitTaskId = task.VisitTaskId, IsInOrder = false });
+ }
+
}
if (task == null)
@@ -3184,6 +3205,77 @@ namespace IRaCIS.Core.Application.Service
return true;
}
+
+
+ ///
+ /// 前端 仅仅释放的时候使用,领取是后端调用该方法
+ ///
+ ///
+ ///
+ ///
+ [HttpPost]
+ public async Task ClaimOrCancelSubjectAsync(ClaimSubjectDto claimSubjectDto)
+ {
+
+
+ //有序 用SubjectCriterionClaimUserId 某个标准的所有任务,该字段保持一致
+ if (claimSubjectDto.IsInOrder)
+ {
+
+ if (claimSubjectDto.IsClaim)
+ {
+ //每个subject 每个标准的领取放在 任务上 免得加表
+ if (_visitTaskRepository.Any(t => t.Id == claimSubjectDto.SubejctId && t.TrialReadingCriterionId == claimSubjectDto.TrialReadingCriterionId
+ && t.SubjectCriterionClaimUserId != _userInfo.UserRoleId && t.SubjectCriterionClaimUserId != null))
+ {
+ throw new BusinessValidationFailedException(_localizer["ReadingImageTask_TaskTaken"]);
+ }
+ else
+ {
+ await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => t.SubjectId == claimSubjectDto.SubejctId && t.TrialReadingCriterionId == claimSubjectDto.TrialReadingCriterionId, u => new VisitTask() { SubjectCriterionClaimUserId = _userInfo.UserRoleId });
+
+ //列表可以看到当前阅片人是谁
+ await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => t.Id == claimSubjectDto.VisitTaskId, u => new VisitTask() { DoctorUserId = _userInfo.UserRoleId });
+ }
+
+
+ var domainEvent = new SubjectCriterionClaimCancelEvent() { SubjectId = claimSubjectDto.SubejctId, TrialReadingCriterionId = claimSubjectDto.TrialReadingCriterionId, IsInOrder = claimSubjectDto.IsInOrder };
+ await _scheduler.SchedulePublish(DateTime.Now.AddDays(1), (object)domainEvent);
+
+
+ //BackgroundJob.Schedule(t => t.CancelQCObtaion(subjectVisitId, DateTime.Now), TimeSpan.FromHours(1));
+
+ }
+ else
+ {
+ await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => t.SubjectId == claimSubjectDto.SubejctId && t.TrialReadingCriterionId == claimSubjectDto.TrialReadingCriterionId && t.ReadingTaskState != ReadingTaskState.HaveSigned, u => new VisitTask() { SubjectCriterionClaimUserId = null });
+ }
+ }
+ //无序 直接用DoctorUserId 当做领取人
+ else
+ {
+ if (claimSubjectDto.IsClaim)
+ {
+ if (_visitTaskRepository.Any(t => t.Id == claimSubjectDto.VisitTaskId && t.DoctorUserId != _userInfo.UserRoleId && t.DoctorUserId != null))
+ {
+ throw new BusinessValidationFailedException(_localizer["ReadingImageTask_TaskTaken"]);
+ }
+ else
+ {
+ await _visitTaskRepository.UpdatePartialFromQueryAsync(t => t.Id == claimSubjectDto.VisitTaskId, u => new VisitTask() { DoctorUserId = _userInfo.UserRoleId }, true);
+
+ }
+
+ var domainEvent = new SubjectCriterionClaimCancelEvent() { VisitTaskId = claimSubjectDto.VisitTaskId, IsInOrder = claimSubjectDto.IsInOrder };
+ await _scheduler.SchedulePublish(DateTime.Now.AddDays(1), (object)domainEvent);
+
+
+ }
+ }
+
+
+ }
+
///
/// 重置阅片时间 登录和解锁调用
///
diff --git a/IRaCIS.Core.Domain/_DomainEvent/SubjectCriterionClaimCancelEvent.cs b/IRaCIS.Core.Domain/_DomainEvent/SubjectCriterionClaimCancelEvent.cs
new file mode 100644
index 000000000..3be6e7970
--- /dev/null
+++ b/IRaCIS.Core.Domain/_DomainEvent/SubjectCriterionClaimCancelEvent.cs
@@ -0,0 +1,23 @@
+using IRaCIS.Core.Domain.BaseModel;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace IRaCIS.Core.Domain._DomainEvent
+{
+ public class SubjectCriterionClaimCancelEvent : DomainEvent
+ {
+ public Guid? SubjectId { get; set; }
+
+ public Guid? TrialReadingCriterionId { get; set; }
+
+
+ public Guid? VisitTaskId { get; set; }
+
+
+ public bool IsInOrder { get; set; }
+
+ }
+}