diff --git a/IRC.Core.SCP/Service/DicomArchiveService.cs b/IRC.Core.SCP/Service/DicomArchiveService.cs
index e522f6690..a79319afd 100644
--- a/IRC.Core.SCP/Service/DicomArchiveService.cs
+++ b/IRC.Core.SCP/Service/DicomArchiveService.cs
@@ -74,7 +74,7 @@ namespace IRaCIS.Core.SCP.Service
//using (@lock.Acquire())
{
- var findPatient = await _patientRepository.FirstOrDefaultAsync(t => t.PatientIdStr == patientIdStr && t.TrialSiteId==trialSiteId );
+ var findPatient = await _patientRepository.FirstOrDefaultAsync(t => t.PatientIdStr == patientIdStr /*&& t.TrialSiteId==trialSiteId*/ );
var findStudy = await _studyRepository.FirstOrDefaultAsync(t=>t.Id== studyId);
var findSerice = await _seriesRepository.FirstOrDefaultAsync(t => t.Id == seriesId);
var findInstance = await _instanceRepository.FirstOrDefaultAsync(t => t.Id == instanceId);
@@ -90,8 +90,8 @@ namespace IRaCIS.Core.SCP.Service
findPatient = new SCPPatient()
{
Id = NewId.NextSequentialGuid(),
- TrialId=trialId,
- TrialSiteId=trialSiteId,
+ //TrialId=trialId,
+ //TrialSiteId=trialSiteId,
PatientIdStr = dataset.GetSingleValueOrDefault(DicomTag.PatientID, string.Empty),
PatientName = dataset.GetSingleValueOrDefault(DicomTag.PatientName, string.Empty),
PatientAge = dataset.GetSingleValueOrDefault(DicomTag.PatientAge, string.Empty),
@@ -163,8 +163,8 @@ namespace IRaCIS.Core.SCP.Service
PatientId = findPatient.Id,
Id = studyId,
- TrialId = trialId,
- TrialSiteId = trialSiteId,
+ //TrialId = trialId,
+ //TrialSiteId = trialSiteId,
StudyInstanceUid = studyInstanceUid,
StudyTime = studyTime,
Modalities = dataset.GetSingleValueOrDefault(DicomTag.Modality, string.Empty),
diff --git a/IRaCIS.Core.Application/BusinessFilter/_Config/_AppSettings.cs b/IRaCIS.Core.Application/BusinessFilter/_Config/_AppSettings.cs
index e2c6fcddb..58f6db3f7 100644
--- a/IRaCIS.Core.Application/BusinessFilter/_Config/_AppSettings.cs
+++ b/IRaCIS.Core.Application/BusinessFilter/_Config/_AppSettings.cs
@@ -36,6 +36,8 @@ public class ServiceVerifyConfigOption
public string ThirdPdfUrl { get; set; }
+ public string AESKey { get; set; }
+
}
public class SystemEmailSendConfig
diff --git a/IRaCIS.Core.Application/Helper/Cryptography.cs b/IRaCIS.Core.Application/Helper/Cryptography.cs
new file mode 100644
index 000000000..7e8fa32a4
--- /dev/null
+++ b/IRaCIS.Core.Application/Helper/Cryptography.cs
@@ -0,0 +1,62 @@
+using System;
+using System.IO;
+using System.Security.Cryptography;
+using System.Text;
+
+public class Cryptography
+{
+ public static string EncryptString(string plainText, string key, string iv)
+ {
+ using (Aes aesAlg = Aes.Create())
+ {
+ aesAlg.Key = GetKeyBytes(key, aesAlg.KeySize / 8);
+ aesAlg.IV = GetKeyBytes(iv, 16);
+
+ ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
+
+ using (MemoryStream msEncrypt = new MemoryStream())
+ {
+ using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
+ {
+ byte[] plainBytes = Encoding.UTF8.GetBytes(plainText);
+ csEncrypt.Write(plainBytes, 0, plainBytes.Length);
+ csEncrypt.FlushFinalBlock();
+ }
+ return Convert.ToBase64String(msEncrypt.ToArray());
+ }
+ }
+ }
+
+ public static string DecryptString(string cipherText, string key, string iv)
+ {
+ byte[] cipherBytes = Convert.FromBase64String(cipherText);
+ using (Aes aesAlg = Aes.Create())
+ {
+ aesAlg.Key = GetKeyBytes(key, aesAlg.KeySize / 8);
+ aesAlg.IV = GetKeyBytes(iv, 16);
+
+ ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
+
+ using (MemoryStream msDecrypt = new MemoryStream(cipherBytes))
+ {
+ using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
+ {
+ using (StreamReader srDecrypt = new StreamReader(csDecrypt))
+ {
+ return srDecrypt.ReadToEnd();
+ }
+ }
+ }
+ }
+ }
+
+ private static byte[] GetKeyBytes(string key, int keySize)
+ {
+
+
+ using (var deriveBytes = new PasswordDeriveBytes(key, null))
+ {
+ return deriveBytes.GetBytes(keySize);
+ }
+ }
+}
diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
index ec3b62da9..3efdaaf54 100644
--- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
+++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
@@ -863,23 +863,6 @@
-
-
- 影像下载记录表
-
-
-
-
-
-
-
-
-
- 影像接收记录表
-
-
-
-
国际化导出
@@ -887,25 +870,6 @@
-
-
- 影像检查列表-患者为维度组织
-
-
-
-
-
-
-
-
-
- 邮件导出
-
-
-
-
-
-
一致性分析结果导出 7 8 分别是自身 和组件一致性
@@ -12824,42 +12788,20 @@
TrialSiteDicomAEService
-
+
- scp 影像推送记录表
-
-
-
+ DicomAEService
+
-
-
- 影像检查列表-患者为维度组织
-
-
-
-
-
+
- 影像检查列表-> 获取患者的检查列表
-
-
-
+ DicomAEService
+
-
+
- 影像访视上传 检查列表
+ 测试scp server 是否可以连接
-
-
-
-
-
- 提交 患者检查和访视的绑定
-
-
-
-
-
@@ -17655,5 +17597,304 @@
入组流程-向CRO提交医生[Submit]
+
+
+ 获取医院的配置信息
+
+
+
+
+
+
+ 配置医院信息,方便测试邮件和授权码的方式
+
+
+
+
+
+
+ 获取系统已确认的标准
+
+
+
+
+
+
+ 获取项目列表 (PM CRC 共用)
+
+
+
+
+
+
+ 添加更新项目
+
+
+
+
+
+
+
+
+
+ 获取项目授权码
+
+
+
+
+
+
+ 获取授权码明文信息
+
+
+
+
+
+
+
+ 获取项目激活码
+
+
+
+
+
+
+
+ 激活码获取明文信息
+
+
+
+
+
+
+
+
+ 设置项目授权信息
+
+
+
+
+
+
+
+ 检查管理-> 检查Tab 患者列表 (带加入的项目信息 以及检查统计) 原型标注错误,不是检查列表
+
+
+
+
+
+
+ 检查管理-> 患者加入项目 初始化勾选列表
+
+
+
+
+
+
+ 检查管理-> 患者加入项目 下拉框勾选列表
+
+
+
+
+
+
+ 检查管理-> 患者已加入的列表(原型有误,应该展示 项目 下的subject 绑定关系)
+
+
+
+
+
+
+ 检查管理-> 获取患者检查列表(同步影像数据之前的)
+
+
+
+
+
+
+ 清除该患者绑定的受试者的所有的数据、(subject subjectVisit visitTask dicom)
+
+
+
+
+
+
+ 受试者管理-> 受试者列表 (带患者信息,患者信息是数组)
+
+
+
+
+
+
+ 受试者管理-> 患者列表 (subject 列表进入,进行关系绑定初始化列表,排除已绑定的患者和已绑定给其他subject的患者)
+
+
+
+
+
+
+ 受试者管理->患者列表 Dicom AE 下拉框数据获取
+
+
+
+
+
+ 受试者管理-> 患者列表 模糊搜索下拉 选择subject 排除已绑定并提交的
+
+
+
+
+
+
+ 之前患者和subject已绑定后,新来了的检查 可能需要新建访视,或者和已有访视在同一区间,需要自动绑定
+
+
+
+
+
+
+ 建立subject与患者绑定 如果是下拉,则传递SubjectId,如果不存在,创建,那么就传递 SubjectCode
+
+ 绑定以后,后台自动创建访视 和检查预先绑定
+
+
+
+
+
+
+ 删除 受试者 和患者之间的绑定
+
+
+
+
+
+
+ 患者检查 与SubjectVisit 的绑定
+
+
+
+
+
+
+ 修改 访视 和检查的绑定关系 IsAdd 区分添加 还是移除
+
+
+
+
+
+
+ 提交 患者检查和访视的绑定
+
+
+
+
+
+
+ 绑定访视 初始化患者检查列表
+
+
+
+
+
+
+ 访视管理- 获取subject 已存在的访视列表 ,同时获取项目访视的配置 在otherData里
+
+
+
+
+
+
+
+ 添加或者更新受试者访视
+
+
+
+
+
+
+
+ 前端利用组件打成压缩包,后端返回路径和压缩包的信息
+
+
+
+
+
+
+ 访视管理-> 访视列表 (带患者信息,患者信息是数组)
+
+
+
+
+
+
+ 访视管理-> 获取当前访视 已绑定的患者检查 (从访视列表 进入修改绑定)
+
+
+
+
+
+
+ 访视管理-> 获取可选访视列表 (从访视列表 进入修改绑定)
+
+
+
+
+
+
+ 检查管理-> 检查列表 (同步影像数据之前的)
+
+
+
+
+
+
+ 检查管理-> 检查列表 (同步影像数据之后的 带患者信息 患者信息是数组)
+
+
+
+
+
+
+ 获取该项目 患者已绑定subject ,新来了的检查 可能需要新建访视 但是新增的检查未绑定访视的检查列表
+
+
+
+
+
+
+ 删除某个项目 未提交的访视检查绑定, 清理数据,方便测试自动绑定
+
+
+
+
+
+
+ 阅片管理-> 任务列表
+
+
+
+
+
+
+ 打包和匿名化影像 默认是匿名化打包,也可以不匿名化打包
+
+
+
+
+
+
+
+
+ 访视影像下载记录表
+
+
+
+
+
+ scp 影像推送记录表
+
+
+
+
diff --git a/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs b/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs
index f1559db0e..b4b48272b 100644
--- a/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs
+++ b/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs
@@ -230,7 +230,7 @@ namespace IRaCIS.Core.Application.Service.Common
ExperimentName = t.ExperimentName,
TrialCode = t.TrialCode,
CreateTime = t.CreateTime,
- Sponsor = _userInfo.IsEn_Us ? t.Sponsor.SponsorName : t.Sponsor.SponsorNameCN,
+ Sponsor = t.Sponsor,
TrialStatusStr = t.TrialStatusStr,
ExpetiedTaskCount = isPM ? t.VisitTaskList.Where(t => t.IsUrgent).Count() : 0,
@@ -1213,78 +1213,8 @@ namespace IRaCIS.Core.Application.Service.Common
}
- ///
- /// 影像下载记录表
- ///
- ///
- ///
- ///
- ///
- ///
- [HttpPost]
- public async Task GetTrialDownloadList_Export(TrialIamgeDownQuery inQuery,
- [FromServices] IRepository _trialImageDownloadRepository,
- [FromServices] IDictionaryService _dictionaryService,
- [FromServices] IRepository _trialRepository)
- {
- var query = _trialImageDownloadRepository.Where(t => t.TrialId == inQuery.TrialId)
- .WhereIf(inQuery.SubjectCode.IsNotNullOrEmpty(), t => t.SubjectCode.Contains(inQuery.SubjectCode))
- .WhereIf(inQuery.IP.IsNotNullOrEmpty(), t => t.IP.Contains(inQuery.IP))
- .WhereIf(inQuery.Name.IsNotNullOrEmpty(), t => t.CreateUser.UserName.Contains(inQuery.Name) || t.CreateUser.FullName.Contains(inQuery.Name))
- .WhereIf(inQuery.ImageType != null, t => t.ImageType == inQuery.ImageType)
- .WhereIf(inQuery.UserType != null, t => t.CreateUser.UserTypeEnum == inQuery.UserType)
- .WhereIf(inQuery.IsSuccess != null, t => t.IsSuccess == inQuery.IsSuccess)
- .WhereIf(inQuery.DownloadStartTime != null, t => t.DownloadStartTime >= inQuery.DownloadStartTime)
- .WhereIf(inQuery.DownloadEndTime != null, t => t.DownloadEndTime <= inQuery.DownloadEndTime)
-
- .ProjectTo(_mapper.ConfigurationProvider);
-
- var list = await query.SortToListAsync(inQuery);
- var exportInfo = (await _trialRepository.Where(t => t.Id == inQuery.TrialId).IgnoreQueryFilters().ProjectTo(_mapper.ConfigurationProvider).FirstOrDefaultAsync()).IfNullThrowException();
-
- exportInfo.List = ExportExcelConverterDate.ConvertToClientTimeInObject(list, _userInfo.TimeZoneId);
- exportInfo.CurrentTime = ExportExcelConverterDate.DateTimeInternationalToString(DateTime.Now, _userInfo.TimeZoneId);
-
-
- return await ExcelExportHelper.DataExportAsync(StaticData.Export.TrialImageDownloadList_Export, exportInfo, $"{exportInfo.ResearchProgramNo}", _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(TrialImageDownloadExportDto));
-
- }
-
- ///
- /// 影像接收记录表
- ///
- ///
- ///
- [HttpPost]
- public async Task GetSCPImageUploadList_Export(SCPImageUploadQuery inQuery,
- [FromServices] IRepository _scpImageUploadRepository,
- [FromServices] IDictionaryService _dictionaryService,
- [FromServices] IRepository _trialRepository)
- {
- var query = _scpImageUploadRepository.Where(t => t.TrialId == inQuery.TrialId)
- .WhereIf(!string.IsNullOrWhiteSpace(inQuery.CalledAE), t => t.CalledAE.Contains(inQuery.CalledAE))
- .WhereIf(!string.IsNullOrWhiteSpace(inQuery.CallingAEIP), t => t.CallingAEIP.Contains(inQuery.CallingAEIP))
- .WhereIf(!string.IsNullOrWhiteSpace(inQuery.CallingAE), t => t.CallingAE.Contains(inQuery.CallingAE))
- .WhereIf(inQuery.StartTime != null, t => t.StartTime >= inQuery.StartTime)
- .WhereIf(inQuery.EndTime != null, t => t.EndTime <= inQuery.EndTime)
- .WhereIf(!string.IsNullOrWhiteSpace(inQuery.TrialSiteKeyInfo), t => t.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteKeyInfo)
- || t.TrialSite.TrialSiteAliasName.Contains(inQuery.TrialSiteKeyInfo) || t.TrialSite.TrialSiteName.Contains(inQuery.TrialSiteKeyInfo))
- .ProjectTo(_mapper.ConfigurationProvider);
-
-
- var list = await query.SortToListAsync(inQuery);
-
- var exportInfo = (await _trialRepository.Where(t => t.Id == inQuery.TrialId).IgnoreQueryFilters().ProjectTo(_mapper.ConfigurationProvider).FirstOrDefaultAsync()).IfNullThrowException();
-
- exportInfo.List = ExportExcelConverterDate.ConvertToClientTimeInObject(list, _userInfo.TimeZoneId);
- exportInfo.CurrentTime = ExportExcelConverterDate.DateTimeInternationalToString(DateTime.Now, _userInfo.TimeZoneId);
-
-
- return await ExcelExportHelper.DataExportAsync(StaticData.Export.TrialSCPImageUploadList_Export, exportInfo, $"{exportInfo.ResearchProgramNo}", _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(SCPImageUploadExportDTO));
-
- }
///
/// 国际化导出
@@ -1322,110 +1252,9 @@ namespace IRaCIS.Core.Application.Service.Common
}
- ///
- ///影像检查列表-患者为维度组织
- ///
- ///
- ///
- ///
- ///
- ///
- [HttpPost]
- public async Task GetPatientList_Export(PatientTrialQuery inQuery,
- [FromServices] IRepository _patientRepository,
- [FromServices] IDictionaryService _dictionaryService,
- [FromServices] IRepository _trialRepository)
- {
+
- var query = _patientRepository.Where(t => t.TrialId == inQuery.TrialId)
- .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), t => t.PatientIdStr.Contains(inQuery.PatientIdStr))
- .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientName), t => t.PatientName.Contains(inQuery.PatientName))
- .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubejctCode), t => t.Subject.Code.Contains(inQuery.SubejctCode))
- .WhereIf(!string.IsNullOrWhiteSpace(inQuery.TrialSiteKeyInfo), t => t.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteKeyInfo)
- || t.TrialSite.TrialSiteAliasName.Contains(inQuery.TrialSiteKeyInfo) || t.TrialSite.TrialSiteName.Contains(inQuery.TrialSiteKeyInfo))
- .WhereIf(!string.IsNullOrWhiteSpace(inQuery.CallingAE), t => t.SCPStudyList.Any(t => t.CallingAE == inQuery.CallingAE))
- .WhereIf(!string.IsNullOrWhiteSpace(inQuery.CalledAE), t => t.SCPStudyList.Any(t => t.CalledAE == inQuery.CalledAE))
- .WhereIf(inQuery.BeginPushTime != null, t => t.LatestPushTime >= inQuery.BeginPushTime)
- .WhereIf(inQuery.EndPushTime != null, t => t.LatestPushTime <= inQuery.EndPushTime);
-
-
- var resultQuery = from patient in query
-
- select new SCPPatientSubjectExportDTO()
- {
- //CreateUserId = patient.CreateUserId,
- //UpdateTime = patient.UpdateTime,
- //UpdateUserId = patient.UpdateUserId,
- //TrialId = patient.TrialId,
- //SubejctId = patient.SubjectId,
- //CreateTime = patient.CreateTime,
- //PatientId = patient.Id,
-
- PatientBirthDate = patient.PatientBirthDate,
- CalledAEList = patient.SCPStudyList.Select(t => t.CalledAE).Distinct().ToList(),
- CallingAEList = patient.SCPStudyList.Select(t => t.CallingAE).Distinct().ToList(),
- EarliestStudyTime = patient.EarliestStudyTime,
- LatestStudyTime = patient.LatestStudyTime,
- LatestPushTime = patient.LatestPushTime,
- PatientAge = patient.PatientAge,
- PatientName = patient.PatientName,
- PatientIdStr = patient.PatientIdStr,
- PatientSex = patient.PatientSex,
- StudyCount = patient.SCPStudyList.Count(),
- SubjectCode = patient.Subject.Code,
- TrialSiteAliasName = patient.TrialSite.TrialSiteAliasName,
- TrialSiteCode = patient.TrialSite.TrialSiteCode,
- TrialSiteName = patient.TrialSite.TrialSiteName
-
- };
-
- var list = await resultQuery.SortToListAsync(inQuery);
-
- var exportInfo = (await _trialRepository.Where(t => t.Id == inQuery.TrialId).IgnoreQueryFilters().ProjectTo(_mapper.ConfigurationProvider).FirstOrDefaultAsync()).IfNullThrowException();
-
- exportInfo.List = ExportExcelConverterDate.ConvertToClientTimeInObject(list, _userInfo.TimeZoneId);
- exportInfo.CurrentTime = ExportExcelConverterDate.DateTimeInternationalToString(DateTime.Now, _userInfo.TimeZoneId);
-
-
- return await ExcelExportHelper.DataExportAsync(StaticData.Export.TrialSCPImageUploadPatientList_Export, exportInfo, $"{exportInfo.ResearchProgramNo}", _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(SCPPatientSubjectExportDTO));
-
- }
-
-
- ///
- /// 邮件导出
- ///
- ///
- ///
- ///
- ///
- [HttpPost]
- public async Task GetEmailNoticeConfigList_Export(EmailNoticeConfigQuery inQuery,
- [FromServices] IRepository _emailNoticeConfigrepository,
- [FromServices] IDictionaryService _dictionaryService)
- {
- var emailNoticeConfigQueryable = _emailNoticeConfigrepository
- //.WhereIf(inQuery.SystemLevel == null, t => t.SystemLevel == SysEmailLevel.not_sys)
- //.WhereIf(inQuery.SystemLevel != null, t => t.SystemLevel == inQuery.SystemLevel)
- //.WhereIf(inQuery.IsDistinguishCriteria != null, t => t.IsDistinguishCriteria == inQuery.IsDistinguishCriteria)
- .WhereIf(inQuery.CriterionTypeEnum != null, t => t.CriterionTypeEnum == inQuery.CriterionTypeEnum)
- .WhereIf(inQuery.BusinessScenarioEnum != null, t => t.BusinessScenarioEnum == inQuery.BusinessScenarioEnum)
- .WhereIf(inQuery.IsReturnRequired != null, t => t.IsReturnRequired == inQuery.IsReturnRequired)
- .WhereIf(inQuery.IsEnable != null, t => t.IsEnable == inQuery.IsEnable)
- .ProjectTo(_mapper.ConfigurationProvider);
-
- var list = await emailNoticeConfigQueryable.SortToListAsync(inQuery);
-
- var exportInfo = new ExcelExportInfo();
-
- exportInfo.List = ExportExcelConverterDate.ConvertToClientTimeInObject(list, _userInfo.TimeZoneId);
- exportInfo.CurrentTime = ExportExcelConverterDate.DateTimeInternationalToString(DateTime.Now, _userInfo.TimeZoneId);
-
-
- return await ExcelExportHelper.DataExportAsync(StaticData.Export.EmailNoticeConfig_Export, exportInfo, $"{exportInfo.ResearchProgramNo}", _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(EmailNoticeConfigExportDto));
-
- }
#region 导表公用
diff --git a/IRaCIS.Core.Application/Service/Document/EmailSendService.cs b/IRaCIS.Core.Application/Service/Document/EmailSendService.cs
index b0b9e02d9..f21040187 100644
--- a/IRaCIS.Core.Application/Service/Document/EmailSendService.cs
+++ b/IRaCIS.Core.Application/Service/Document/EmailSendService.cs
@@ -53,7 +53,7 @@ namespace IRaCIS.Core.Application.Service
t.Trial.ResearchProgramNo,
t.Subject.TrialSite.TrialSiteCode,
SubjectCode = t.Subject.Code,
- t.Trial.Sponsor.SponsorName,
+ t.Trial.Sponsor,
t.SourceSubjectVisit.VisitName,
t.TrialId,
diff --git a/IRaCIS.Core.Application/Service/Document/TrialEmailNoticeConfigService.cs b/IRaCIS.Core.Application/Service/Document/TrialEmailNoticeConfigService.cs
index 3c85f29a0..54c75c7f4 100644
--- a/IRaCIS.Core.Application/Service/Document/TrialEmailNoticeConfigService.cs
+++ b/IRaCIS.Core.Application/Service/Document/TrialEmailNoticeConfigService.cs
@@ -187,7 +187,7 @@ namespace IRaCIS.Core.Application.Service
t.Trial.ResearchProgramNo,
t.Subject.TrialSite.TrialSiteCode,
SubjectCode = t.Subject.Code,
- t.Trial.Sponsor.SponsorName,
+ t.Trial.Sponsor,
t.Trial.IsEnrollementQualificationConfirm,
t.Trial.IsPDProgressView,
@@ -617,7 +617,7 @@ namespace IRaCIS.Core.Application.Service
var value = new Dictionary()
{
- ["SponsorName"] = taskInfo.SponsorName,
+ ["SponsorName"] = taskInfo.Sponsor,
["ResearchProgramNo"] = taskInfo.ResearchProgramNo,
["TrialSiteCode"] = taskInfo.TrialSiteCode,
["SubjectCode"] = taskInfo.SubjectCode,
diff --git a/IRaCIS.Core.Application/Service/Financial/_MapConfig.cs b/IRaCIS.Core.Application/Service/Financial/_MapConfig.cs
index 17e9f3de4..79fdbe046 100644
--- a/IRaCIS.Core.Application/Service/Financial/_MapConfig.cs
+++ b/IRaCIS.Core.Application/Service/Financial/_MapConfig.cs
@@ -47,7 +47,7 @@ namespace IRaCIS.Core.Application.Service
CreateMap()
.ForMember(t => t.TrialCode, u => u.MapFrom(t => t.Trial.Code))
.ForMember(t => t.ReviewMode, u => u.MapFrom(t => t.Trial.ReviewMode.Value))
- .ForMember(t => t.Cro, u => u.MapFrom(t => t.Trial.CRO.CROName))
+ .ForMember(t => t.Cro, u => u.MapFrom(t => t.Trial.CRO))
.ForMember(t => t.Indication, u => u.MapFrom(t => t.Trial.Indication))
.ForMember(t => t.Expedited, u => u.MapFrom(t => t.Trial.Expedited))
.ForMember(t => t.DoctorsNames, u => u.MapFrom(t => string.Join(',', t.Trial.EnrollList.Select(t => t.Doctor.ChineseName))))
diff --git a/IRaCIS.Core.Application/Service/QC/QCOperationService.cs b/IRaCIS.Core.Application/Service/QC/QCOperationService.cs
index 66a613276..3ed18b0f2 100644
--- a/IRaCIS.Core.Application/Service/QC/QCOperationService.cs
+++ b/IRaCIS.Core.Application/Service/QC/QCOperationService.cs
@@ -771,7 +771,7 @@ namespace IRaCIS.Core.Application.Image.QA
var succeess2 = await _dicomInstanceRepository.BatchDeleteNoTrackingAsync(t => t.StudyId == id);
var success3 = await _dicomSeriesrepository.BatchDeleteNoTrackingAsync(t => t.StudyId == id);
- await _scpStudyRepository.BatchUpdateNoTrackingAsync(t => t.Id == id, u => new SCPStudy() { SubjectVisitId = null });
+ //await _scpStudyRepository.BatchUpdateNoTrackingAsync(t => t.Id == id, u => new SCPStudy() { SubjectVisitId = null });
@@ -797,17 +797,17 @@ namespace IRaCIS.Core.Application.Image.QA
}
- var subjectId = waitDeleteStudyList.Select(t => t.SubjectId).FirstOrDefault();
+ //var subjectId = waitDeleteStudyList.Select(t => t.SubjectId).FirstOrDefault();
- var patientList = _scpPatientRepository.Where(t => t.SubjectId == subjectId).Select(t => t.Id).ToList();
+ //var patientList = _scpPatientRepository.Where(t => t.SubjectId == subjectId).Select(t => t.Id).ToList();
- foreach (var patientId in patientList)
- {
- if (_scpPatientRepository.Where(t => t.Id == patientId).Any(t => t.SCPStudyList.Count() == t.SCPStudyList.Where(t => t.SubjectVisitId == null).Count()))
- {
- await _scpPatientRepository.BatchUpdateNoTrackingAsync(t => t.Id == patientId, u => new SCPPatient() { SubjectId = null });
- }
- }
+ //foreach (var patientId in patientList)
+ //{
+ // if (_scpPatientRepository.Where(t => t.Id == patientId).Any(t => t.SCPStudyList.Count() == t.SCPStudyList.Where(t => t.SubjectVisitId == null).Count()))
+ // {
+ // await _scpPatientRepository.BatchUpdateNoTrackingAsync(t => t.Id == patientId, u => new SCPPatient() { SubjectId = null });
+ // }
+ //}
diff --git a/IRaCIS.Core.Application/Service/SiteSurvey/_MapConfig.cs b/IRaCIS.Core.Application/Service/SiteSurvey/_MapConfig.cs
index fdf43fac5..b5d7918eb 100644
--- a/IRaCIS.Core.Application/Service/SiteSurvey/_MapConfig.cs
+++ b/IRaCIS.Core.Application/Service/SiteSurvey/_MapConfig.cs
@@ -58,7 +58,7 @@ namespace IRaCIS.Core.Application.AutoMapper
CreateMap()
- .ForMember(d => d.Sponsor, u => u.MapFrom(s => s.Sponsor.SponsorName))
+ .ForMember(d => d.Sponsor, u => u.MapFrom(s => s.Sponsor))
.ForMember(d => d.IndicationType, u => u.MapFrom(s => s.IndicationType.Value))
.ForMember(d => d.TrialSiteSelectList, u => u.MapFrom(s => s.TrialSiteList))
.ForMember(d => d.TrialId, u => u.MapFrom(s => s.Id));
diff --git a/IRaCIS.Core.Application/Service/Third-partyProject/UltrasonicDicomService.cs b/IRaCIS.Core.Application/Service/Third-partyProject/UltrasonicDicomService.cs
index 7e6c03113..2440021b7 100644
--- a/IRaCIS.Core.Application/Service/Third-partyProject/UltrasonicDicomService.cs
+++ b/IRaCIS.Core.Application/Service/Third-partyProject/UltrasonicDicomService.cs
@@ -49,7 +49,7 @@ namespace IRaCIS.Core.Application.Service.Third_partyProject
ExperimentName = t.ExperimentName,
TrialCode = t.TrialCode,
CreateTime = t.CreateTime,
- Sponsor = _userInfo.IsEn_Us ? t.Sponsor.SponsorName : t.Sponsor.SponsorNameCN,
+ Sponsor = _userInfo.IsEn_Us ? t.Sponsor : t.Sponsor,
TrialStatusStr = t.TrialStatusStr
});
diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/PersonalWorkstation.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/PersonalWorkstation.cs
index d41bdbca1..494368863 100644
--- a/IRaCIS.Core.Application/Service/TrialSiteUser/PersonalWorkstation.cs
+++ b/IRaCIS.Core.Application/Service/TrialSiteUser/PersonalWorkstation.cs
@@ -1389,7 +1389,7 @@ namespace IRaCIS.Core.Application
ExperimentName = t.ExperimentName,
TrialCode = t.TrialCode,
CreateTime = t.CreateTime,
- Sponsor = _userInfo.IsEn_Us ? t.Sponsor.SponsorName : t.Sponsor.SponsorNameCN,
+ Sponsor = t.Sponsor,
TrialStatusStr = t.TrialStatusStr,
ExpetiedTaskCount = isPM ? t.VisitTaskList.Where(t => t.IsUrgent).Count() : 0,
diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/_MapConfig.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/_MapConfig.cs
index f94b5ae18..e6b698027 100644
--- a/IRaCIS.Core.Application/Service/TrialSiteUser/_MapConfig.cs
+++ b/IRaCIS.Core.Application/Service/TrialSiteUser/_MapConfig.cs
@@ -67,11 +67,11 @@ namespace IRaCIS.Core.Application.Service
.ForMember(x => x.CriterionList, y => y.MapFrom(z => z.TrialReadingCriterionList.Where(n => n.IsConfirm).Select(m => m.CriterionName)))
.ForMember(d => d.DictionaryList, u => u.MapFrom(s => s.TrialDicList.Select(t => t.Dictionary).OrderBy(t => t.ShowOrder)))
//.ForMember(d => d.Code, u => u.MapFrom(s => s.TrialCode))
- .ForMember(d => d.Sponsor, u => u.MapFrom(s => s.Sponsor.SponsorName))
+ .ForMember(d => d.Sponsor, u => u.MapFrom(s => s.Sponsor))
.ForMember(d => d.Phase, u => u.MapFrom(s => isEn_Us ? s.Phase.Value : s.Phase.ValueCN))
//.ForMember(d => d.DeclarationType, u => u.MapFrom(s => s.DeclarationType.MappedValue))
.ForMember(d => d.IndicationType, u => u.MapFrom(s => isEn_Us ? s.IndicationType.Value : s.IndicationType.ValueCN))
- .ForMember(d => d.CRO, u => u.MapFrom(s => s.CRO.CROName))
+ .ForMember(d => d.CRO, u => u.MapFrom(s => s.CRO))
.ForMember(d => d.ReviewMode, u => u.MapFrom(s => isEn_Us ? s.ReviewMode.Value : s.ReviewMode.ValueCN))
//.ForMember(d => d.ReviewType, u => u.MapFrom(s => s.ReviewType.Value))
.ForMember(d => d.IsLocked, u => u.MapFrom(s => s.WorkloadList.Any(u => u.DataFrom == (int)WorkLoadFromStatus.FinalConfirm)))
diff --git a/IRaCIS.Core.Application/Service/Visit/DTO/PatientViewModel.cs b/IRaCIS.Core.Application/Service/Visit/DTO/PatientViewModel.cs
index 8b8fa455f..72b1ee836 100644
--- a/IRaCIS.Core.Application/Service/Visit/DTO/PatientViewModel.cs
+++ b/IRaCIS.Core.Application/Service/Visit/DTO/PatientViewModel.cs
@@ -1,7 +1,10 @@
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Share;
+using IRaCIS.Core.Infrastructure.Extention;
using Newtonsoft.Json;
using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Web;
namespace IRaCIS.Application.Contracts
{
@@ -219,83 +222,34 @@ namespace IRaCIS.Application.Contracts
public class PatientTrialQuery : PageInput
{
- [NotDefault]
- public Guid TrialId { get; set; }
-
public string? PatientIdStr { get; set; }
public string? PatientName { get; set; }
- //public List CalledAEList { get; set; } = new List();
+ public List CalledAEList { get; set; } = new List();
public string? CallingAE { get; set; }
- public string? CalledAE { get; set; }
+
+ public string? ExperimentName { get; set; } = string.Empty;
public DateTime? BeginPushTime { get; set; }
public DateTime? EndPushTime { get; set; }
- public string SubejctCode { get; set; }
-
- public string TrialSiteKeyInfo { get; set; }
-
}
- public class PatientSubjectView : PatientQueryView
+ public class PatientTrialView : PatientQueryView
{
public int? StudyCount { get; set; }
-
-
- public Guid? SubejctId { get; set; }
-
- public Guid TrialId { get; set; }
-
- public string? SubjectCode { get; set; }
-
- public string? TrialSiteCode { get; set; }
-
- public string? TrialSiteName { get; set; }
-
- public string? TrialSiteAliasName { get; set; }
-
-
-
+ public List TrialList { get; set; }
}
-
- public class SCPPatientSubjectExportDTO
+ public class PatientTrialStatInfo
{
- public int? StudyCount { get; set; }
+ public int? VisitCount { get; set; }
- public string? SubjectCode { get; set; }
-
- public string? TrialSiteCode { get; set; }
-
- public string? TrialSiteName { get; set; }
-
- public string? TrialSiteAliasName { get; set; }
-
- public string PatientIdStr { get; set; } = string.Empty;
- public string PatientName { get; set; } = string.Empty;
- public string PatientAge { get; set; } = string.Empty;
- public string PatientSex { get; set; } = string.Empty;
- public string PatientBirthDate { get; set; } = string.Empty;
-
- public DateTime? EarliestStudyTime { get; set; }
-
- public DateTime? LatestStudyTime { get; set; }
-
- public DateTime LatestPushTime { get; set; }
-
- public List CallingAEList { get; set; } = new List();
-
- public List CalledAEList { get; set; } = new List();
-
- public string CallingAEListStr => string.Join(",", CallingAEList);
-
- public string CalledAEListStr => string.Join(",", CalledAEList);
+ public string ExperimentName { get; set; }
}
-
public class PatientQuery : PageInput
{
[NotDefault]
@@ -415,9 +369,7 @@ namespace IRaCIS.Application.Contracts
}
-
-
- public class VerifyPacsImageCommand
+ public class SubmitVisitStudyBindingCommand
{
[NotDefault]
public Guid TrialId { get; set; }
@@ -425,17 +377,7 @@ namespace IRaCIS.Application.Contracts
[NotDefault]
public Guid SubjectId { get; set; }
- [NotDefault]
- public Guid SubjectVisitId { get; set; }
-
- public List SCPStudyIdList { get; set; }
- }
-
- public class SubmitVisitStudyBindingCommand : VerifyPacsImageCommand
- {
-
-
- public List ReUploadSCPStudyIdList { get; set; }
+ public List SubjectVisitIdList { get; set; }
}
public class SubjectVisitSelectQuery
@@ -996,10 +938,6 @@ namespace IRaCIS.Application.Contracts
public class SCPImageUploadQuery : PageInput
{
- [NotDefault]
- public Guid TrialId { get; set; }
- public string TrialSiteKeyInfo { get; set; }
-
public string? CallingAE { get; set; }
public string? CalledAE { get; set; }
@@ -1028,28 +966,7 @@ namespace IRaCIS.Application.Contracts
public long FileSize { get; set; }
public int StudyCount { get; set; }
-
-
- public Guid TrialId { get; set; }
- public Guid TrialSiteId { get; set; }
-
-
- public string TrialSiteCode { get; set; }
-
- public string TrialSiteName { get; set; }
-
- public string TrialSiteAliasName { get; set; }
-
- public string UploadIntervalStr
- {
- get
- {
- var uploadTimeSpan = EndTime - StartTime;
-
- return $" {uploadTimeSpan.Hours}:{uploadTimeSpan.Minutes}:{uploadTimeSpan.Seconds}.{uploadTimeSpan.Milliseconds}";
- }
- }
-
+
}
public class VisitPatientStudyView : PatientStudySelectDto
{
@@ -1073,51 +990,8 @@ namespace IRaCIS.Application.Contracts
}
- public class VisitPatientStudyFilterQuery : PageInput
- {
- [NotDefault]
- public Guid SubjectId { get; set; }
-
- [NotDefault]
- public Guid SubjectVisitId { get; set; }
-
- public DateTime? EarliestStudyTime { get; set; }
-
- public DateTime? LatestStudyTime { get; set; }
- public string? Modalities { get; set; }
-
- public string? PatientInfo { get; set; }
- }
- public class VisitPatientStudyFilterView
- {
- public Guid SCPStudyId { get; set; }
-
- public Guid PatientId { get; set; }
-
- public DateTime? StudyTime { get; set; }
- public string Modalities { get; set; } = string.Empty;
-
- public string Description { get; set; } = string.Empty;
- public int SeriesCount { get; set; } = 0;
- public int InstanceCount { get; set; } = 0;
-
- public string CalledAE { get; set; } = string.Empty;
-
- public string CallingAE { get; set; } = string.Empty;
-
- public string BodyPartExamined { get; set; } = string.Empty;
- public string AccessionNumber { get; set; } = string.Empty;
- public string PatientIdStr { get; set; } = string.Empty;
- public string PatientName { get; set; } = string.Empty;
- public string PatientAge { get; set; } = string.Empty;
- public string PatientSex { get; set; } = string.Empty;
-
- public string PatientBirthDate { get; set; } = string.Empty;
- }
-
public class PatientStudySimpleView
{
-
public Guid SCPStudyId { get; set; }
public Guid PatientId { get; set; }
@@ -1133,25 +1007,8 @@ namespace IRaCIS.Application.Contracts
public string CallingAE { get; set; } = string.Empty;
- public Guid? SubjectVisitId { get; set; }
- public string? VisitName { get; set; }
-
- public string? BlindName { get; set; } = string.Empty;
-
-
- //public SubjectVisitInfo SubejectVisit { get; set; }
-
}
- public class SubjectVisitInfo
- {
- public Guid Id { get; set; }
-
- public string VisitName { get; set; }
-
- public decimal VisitNum { get; set; }
- public string BlindName { get; set; } = string.Empty;
- }
public class PatientSeriesDTO
diff --git a/IRaCIS.Core.Application/Service/Visit/DicomAEService.cs b/IRaCIS.Core.Application/Service/Visit/DicomAEService.cs
new file mode 100644
index 000000000..ac11e0f0b
--- /dev/null
+++ b/IRaCIS.Core.Application/Service/Visit/DicomAEService.cs
@@ -0,0 +1,120 @@
+//--------------------------------------------------------------------
+// 此代码由T4模板自动生成 byzhouhang 20210918
+// 生成时间 2024-03-22 15:44:31
+// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
+//--------------------------------------------------------------------
+
+using IRaCIS.Core.Domain.Models;
+using Microsoft.AspNetCore.Mvc;
+using IRaCIS.Core.Application.Interfaces;
+using IRaCIS.Core.Application.ViewModel;
+using FellowOakDicom.Network.Client;
+using FellowOakDicom.Network;
+using IRaCIS.Application.Contracts;
+using IRaCIS.Core.Domain.Share;
+namespace IRaCIS.Core.Application.Service
+{
+ ///
+ /// DicomAEService
+ ///
+ [ApiExplorerSettings(GroupName = "Common")]
+ public class DicomAEService (IRepository _dicomAERepository, IMapper _mapper, IUserInfo _userInfo) : BaseService, IDicomAEService
+ {
+
+
+
+ [HttpPost]
+ public async Task>> GetDicomAEList(DicomAEQuery inQuery)
+ {
+
+ var dicomAEQueryable = _dicomAERepository
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.IP), t => t.IP.Contains(inQuery.IP))
+ .WhereIf(inQuery.Port != null, t => t.Port == inQuery.Port)
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.CalledAE), t => t.CalledAE.Contains(inQuery.CalledAE))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.Description), t => t.Description.Contains(inQuery.Description))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.Modality), t => t.Modality.Contains(inQuery.Modality))
+ .ProjectTo(_mapper.ConfigurationProvider);
+
+
+
+
+ var pageList = await dicomAEQueryable.ToPagedListAsync(inQuery, nameof(DicomAEView.CalledAE));
+
+
+ return ResponseOutput.Ok(pageList);
+ }
+
+
+ public async Task AddOrUpdateDicomAE(DicomAEAddOrEdit addOrEditDicomAE)
+ {
+ var verifyExp1 = new EntityVerifyExp()
+ {
+ VerifyExp = u => u.IP == addOrEditDicomAE.IP && u.Port == addOrEditDicomAE.Port,
+
+ VerifyMsg = "不允许添加相同的IP和端口的记录"
+ };
+
+ // 在此处拷贝automapper 映射
+ var entity = await _dicomAERepository.InsertOrUpdateAsync(addOrEditDicomAE, true, verifyExp1);
+
+ return ResponseOutput.Ok(entity.Id.ToString());
+
+ }
+
+
+ [HttpDelete("{dicomAEId:guid}")]
+ public async Task DeleteDicomAE(Guid dicomAEId)
+ {
+ var success = await _dicomAERepository.DeleteFromQueryAsync(t => t.Id == dicomAEId, true);
+ return ResponseOutput.Ok();
+ }
+
+
+ ///
+ /// 测试scp server 是否可以连接
+ ///
+ ///
+ [HttpGet("{dicomAEId:guid}")]
+ public async Task TestSCPServerConnect(Guid dicomAEId)
+ {
+ var find = await _dicomAERepository.FirstOrDefaultAsync(t => t.Id == dicomAEId);
+
+ if (find == null)
+ {
+
+ return false;
+ }
+ else
+ {
+ find.LatestTestTime = DateTime.Now;
+
+ try
+ {
+ var client = DicomClientFactory.Create(find.IP, find.Port, false, "test-callingAE", find.CalledAE);
+
+ client.NegotiateAsyncOps();
+
+ await client.AddRequestAsync(new DicomCEchoRequest());
+
+ await client.SendAsync();
+
+ find.IsTestOK = true;
+ await _dicomAERepository.SaveChangesAsync();
+
+ return true;
+ }
+ catch (Exception ex)
+ {
+ find.IsTestOK = false;
+ await _dicomAERepository.SaveChangesAsync();
+
+ return false;
+ }
+ }
+
+
+ }
+
+
+ }
+}
diff --git a/IRaCIS.Core.Application/Service/Visit/PatientService.cs b/IRaCIS.Core.Application/Service/Visit/PatientService.cs
index c8397ba82..ec1ef8db8 100644
--- a/IRaCIS.Core.Application/Service/Visit/PatientService.cs
+++ b/IRaCIS.Core.Application/Service/Visit/PatientService.cs
@@ -1,130 +1,558 @@
-using FellowOakDicom;
+using IRaCIS.Application.Interfaces;
using IRaCIS.Application.Contracts;
-using IRaCIS.Core.Application.Contracts;
-using IRaCIS.Core.Application.Contracts.Dicom.DTO;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Domain.Share;
-using IRaCIS.Core.Infrastructure;
using Microsoft.AspNetCore.Mvc;
-using Pipelines.Sockets.Unofficial.Arenas;
-using System.Linq.Dynamic.Core;
-using IDistributedLockProvider = Medallion.Threading.IDistributedLockProvider;
+using Microsoft.AspNetCore.Authorization;
+using IRaCIS.Core.Application.Auth;
+using MassTransit;
+using Panda.DynamicWebApi.Attributes;
+using DocumentFormat.OpenXml.Spreadsheet;
+using AutoMapper.EntityFrameworkCore;
+using IRaCIS.Core.Domain.Models;
+using IRaCIS.Core.Application.Service.Reading.Dto;
+using Microsoft.Extensions.Options;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Configuration.Json;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using SharpCompress.Common;
+using System.Reactive.Subjects;
using Subject = IRaCIS.Core.Domain.Models.Subject;
+using IRaCIS.Core.Application.ViewModel;
+using Medallion.Threading;
+using IRaCIS.Core.Infrastructure;
+using Pipelines.Sockets.Unofficial.Arenas;
+using IRaCIS.Core.Application.Contracts;
+using MailKit.Search;
+using DocumentFormat.OpenXml.Office2010.Excel;
+using IRaCIS.Core.Application.Contracts.Dicom.DTO;
+using IRaCIS.Core.Application.Helper;
+using NPOI.SS.Formula.Functions;
+using System.Linq;
+using System.Linq.Dynamic.Core;
+using System.Text;
+using DocumentFormat.OpenXml.EMMA;
+using Azure;
+using System.IO.Compression;
+using static IRaCIS.Core.Domain.Share.StaticData;
+using FellowOakDicom;
+using DocumentFormat.OpenXml.Office2010.Drawing;
+using IDistributedLockProvider = Medallion.Threading.IDistributedLockProvider;
+using DocumentFormat.OpenXml.InkML;
+using Microsoft.AspNetCore.Hosting;
-namespace IRaCIS.Core.Application.Service
+namespace IRaCIS.Application.Services
{
[ApiExplorerSettings(GroupName = "Trial")]
- public class PatientService(IRepository _trialRepository,
- IRepository _patientRepository,
- IRepository _scpStudyRepository,
- IRepository _subjectRepository,
- IRepository _subjectVisitRepository,
- IRepository _dictionaryRepository,
- IRepository _dicomStudyRepository,
- IRepository _scpPatientRepository,
- IRepository _scpImageUploadRepository,
- IDistributedLockProvider _distributedLockProvider, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService
+ public class PatientService(IRepository _studySubjectVisitRepository,
+ IRepository _subjectPatientRepository,
+ IRepository _trialRepository,
+ IRepository _patientRepository,
+ IRepository _studyRepository,
+ IRepository _subjectRepository,
+ IRepository _subjectVisitRepository,
+ IRepository _subejctVisitDownloadRepository,
+ IRepository _SCPImageUploadRepository,
+ IRepository _userRepository,
+ IDistributedLockProvider _distributedLockProvider, IMapper _mapper, IUserInfo _userInfo, IWebHostEnvironment _hostEnvironment, IStringLocalizer _localizer
+
+
+ ) : BaseService
{
+ #region 医院信息管理
- [HttpGet]
- public async Task>> GetPatientSeriesList(Guid scpStudyId,
- [FromServices] IRepository _seriesRepository,
- [FromServices] IRepository _instanceRepository
- )
+ ///
+ /// 获取医院的配置信息
+ ///
+ ///
+ ///
+ [AllowAnonymous]
+ public async Task GetHospitalInfo([FromServices] IOptionsMonitor options)
{
+ return options.CurrentValue;
+ }
- var seriesList = await _seriesRepository.Where(s => s.StudyId == scpStudyId).OrderBy(s => s.SeriesNumber).
- ThenBy(s => s.SeriesTime).ThenBy(s => s.CreateTime)
- .ProjectTo(_mapper.ConfigurationProvider).ToListAsync();
+ ///
+ /// 配置医院信息,方便测试邮件和授权码的方式
+ ///
+ ///
+ ///
+ [HttpPost]
+ public async Task UpdateHospitalInfo(SystemHospitalOption systemHospitalOption)
+ {
+ var path = $"appsettings.{_hostEnvironment.EnvironmentName}.json";
- var instanceList = await _instanceRepository.Where(s => s.StudyId == scpStudyId).OrderBy(t => t.SeriesId).ThenBy(t => t.InstanceNumber)
- .ThenBy(s => s.InstanceTime).ThenBy(s => s.CreateTime)
- .Select(t => new { t.SeriesId, t.Id, t.Path, t.NumberOfFrames, t.InstanceNumber }).ToListAsync();//.GroupBy(u => u.SeriesId);
+ string text = System.IO.File.ReadAllText(path);
- foreach (var series in seriesList)
- {
+ // 修改
+ JObject obj = JObject.Parse(text);
+ obj["SystemHospitalConfig"][nameof(SystemHospitalOption.HospitalName)] = systemHospitalOption.HospitalName;
+ obj["SystemHospitalConfig"][nameof(SystemHospitalOption.HospitalAliasName)] = systemHospitalOption.HospitalAliasName;
+ obj["SystemHospitalConfig"][nameof(SystemHospitalOption.Country)] = systemHospitalOption.Country;
+ obj["SystemHospitalConfig"][nameof(SystemHospitalOption.City)] = systemHospitalOption.City;
+ obj["SystemHospitalConfig"][nameof(SystemHospitalOption.Phone)] = systemHospitalOption.Phone;
+ obj["SystemHospitalConfig"][nameof(SystemHospitalOption.Province)] = systemHospitalOption.Province;
+ obj["SystemHospitalConfig"][nameof(SystemHospitalOption.Address)] = systemHospitalOption.Address;
+ obj["SystemHospitalConfig"][nameof(SystemHospitalOption.IsCanConnectInternet)] = systemHospitalOption.IsCanConnectInternet;
- series.InstanceInfoList = instanceList.Where(t => t.SeriesId == series.Id).OrderBy(t => t.InstanceNumber).Select(k =>
- new InstanceBasicInfo()
- {
- Id = k.Id,
- NumberOfFrames = k.NumberOfFrames,
- //HtmlPath = string.Empty,
- Path = k.Path,
- InstanceNumber = k.InstanceNumber,
+ obj["SystemHospitalConfig"][nameof(SystemHospitalOption.HospitalCode)] = systemHospitalOption.HospitalCode;
+ obj["SystemHospitalConfig"][nameof(SystemHospitalOption.HospitalLogoPath)] = systemHospitalOption.HospitalLogoPath;
+ obj["SystemHospitalConfig"][nameof(SystemHospitalOption.TrialKeepCount)] = systemHospitalOption.TrialKeepCount;
- }).ToList();
- }
+ // 重新写入appsettings.json
+ string result = obj.ToString();
+ System.IO.File.WriteAllText(path, result);
- var study = await _scpStudyRepository.FindAsync(scpStudyId);
+ await _userRepository.BatchUpdateNoTrackingAsync(t => t.IsZhiZhun, t => new User() { OrganizationName = systemHospitalOption.HospitalName });
+
+ return ResponseOutput.Ok();
+ }
+
+ #endregion
+
+ #region 项目管理
+
+ ///
+ /// 获取系统已确认的标准
+ ///
+ ///
+ ///
+ public async Task GetSystemConfirmedCreiterionList([FromServices] IRepository _readingQuestionCriterionSystemRepository)
+ {
+ var list = await _readingQuestionCriterionSystemRepository.Where(x => x.IsEnable && x.IsCompleteConfig).OrderBy(t => t.ShowOrder).Select(t => new { t.CriterionType, t.CriterionName, t.Id, t.Description }).ToListAsync();
+
+ return ResponseOutput.Ok(list);
- return ResponseOutput.Ok(seriesList, study);
}
+
///
- /// scp 影像推送记录表
+ /// 获取项目列表 (PM CRC 共用)
///
///
///
[HttpPost]
- public async Task>> GetSCPImageUploadList(SCPImageUploadQuery inQuery)
+ public async Task>> GetTrialList(NewTrialQuery inQuery)
{
- var query = _scpImageUploadRepository.Where(t => t.TrialId == inQuery.TrialId)
- .WhereIf(!string.IsNullOrWhiteSpace(inQuery.CalledAE), t => t.CalledAE.Contains(inQuery.CalledAE))
- .WhereIf(!string.IsNullOrWhiteSpace(inQuery.CallingAEIP), t => t.CallingAEIP.Contains(inQuery.CallingAEIP))
- .WhereIf(!string.IsNullOrWhiteSpace(inQuery.CallingAE), t => t.CallingAE.Contains(inQuery.CallingAE))
- .WhereIf(inQuery.StartTime != null, t => t.StartTime >= inQuery.StartTime)
- .WhereIf(inQuery.EndTime != null, t => t.EndTime <= inQuery.EndTime)
- .WhereIf(!string.IsNullOrWhiteSpace(inQuery.TrialSiteKeyInfo), t => t.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteKeyInfo)
- || t.TrialSite.TrialSiteAliasName.Contains(inQuery.TrialSiteKeyInfo) || t.TrialSite.TrialSiteName.Contains(inQuery.TrialSiteKeyInfo))
- .ProjectTo(_mapper.ConfigurationProvider);
+ var trialQuery = _trialRepository
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.ResearchProgramNo), t => t.ResearchProgramNo.Contains(inQuery.ResearchProgramNo))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.ExperimentName), t => t.ExperimentName.Contains(inQuery.ExperimentName))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SponsorName), t => t.Sponsor.Contains(inQuery.SponsorName))
+ .WhereIf(inQuery.TrialType != null, t => t.TrialType == inQuery.TrialType)
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.TrialCode), t => t.TrialCode.Contains(inQuery.TrialCode))
+ .WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin && _userInfo.UserTypeEnumInt != (int)UserTypeEnum.Admin && _userInfo.UserTypeEnumInt != (int)UserTypeEnum.OA
+ , t => t.TrialUserList.Any(t => t.UserId == _userInfo.Id && t.IsDeleted == false) && t.IsDeleted == false)
+ .ProjectTo(_mapper.ConfigurationProvider);
- var pageList = await query.ToPagedListAsync(inQuery);
+ var pageList = await trialQuery.ToPagedListAsync(inQuery, nameof(NewTrialQuery.ResearchProgramNo));
return ResponseOutput.Ok(pageList);
}
+ [HttpGet("{trialId:guid}")]
+ public async Task GetTrialInfo(Guid trialId, [FromServices] IOptionsMonitor _basicSystemConfigConfig)
+ {
+ var trial = (await _trialRepository.Where(o => o.Id == trialId).IgnoreQueryFilters().ProjectTo(_mapper.ConfigurationProvider, new { isEn_Us = _userInfo.IsEn_Us }).FirstOrDefaultAsync()).IfNullThrowException();
+
+ if (!string.IsNullOrEmpty(trial.AuthorizationEncrypt))
+ {
+ try
+ {
+ //解析加密信息
+ var decodedText = Cryptography.DecryptString(trial.AuthorizationEncrypt, _basicSystemConfigConfig.CurrentValue.AESKey, "Trial_AuthorizationEncrypt");
+
+ var authInfo = JsonConvert.DeserializeObject(decodedText);
+
+ return ResponseOutput.Ok(trial, authInfo);
+ }
+ catch (Exception)
+ {
+
+ return ResponseOutput.NotOk("授权信息无法解密,请勿人为修改授权信息,如果有误,请联系开发解决");
+ }
+ }
+ return ResponseOutput.Ok(trial);
+ }
+
+ ///
+ /// 添加更新项目
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpPost]
+ [UnitOfWork]
+ public async Task AddOrUpdateTrial(AddOrUpdateTrialCommand inCommand,
+ [FromServices] IOptionsMonitor _systemEmailSendConfig,
+ [FromServices] IOptionsMonitor _basicSystemConfigConfig,
+ [FromServices] IOptionsMonitor _systemHospitalOption,
+ IRepository _trialDictionaryRepository,
+ IRepository _trialUserRepository,
+ [FromServices] IFusionCache _provider)
+ {
+ var code = _systemHospitalOption.CurrentValue.HospitalCode;
+
+ //if (await _trialRepository.CountAsync(u => u.TrialStatusStr == StaticData.TrialState.TrialOngoing) > _systemHospitalOption.CurrentValue.TrialKeepCount)
+ //{
+ // throw new BusinessValidationFailedException($"已超过当前系统配置的未启动项目数量的限制,您的操作被限制,请获取授权再进行操作!");
+ //}
+
+ inCommand.ResearchProgramNo = inCommand.ResearchProgramNo.Trim();
+
+ if (inCommand.Id == Guid.Empty || inCommand.Id == null)
+ {
+ if (await _trialRepository.AnyAsync(u => u.TrialCode == inCommand.TrialCode))
+ {
+ //---已经存在相同的项目编号。
+ throw new BusinessValidationFailedException(_localizer["Trial_DuplicateProjectNumber"]);
+ }
+
+ foreach (var criterionType in inCommand.CriterionTypeList)
+ {
+ if (await _trialRepository.AnyAsync(u => u.ResearchProgramNo == inCommand.ResearchProgramNo && u.CriterionTypes.Contains($"|{(int)criterionType}|")))
+ {
+ throw new BusinessValidationFailedException($"已存在研究方案号为{inCommand.ResearchProgramNo},该标准的项目");
+ }
+
+ }
+
+
+ var dbMaxCode = await _trialRepository.Where(t => t.CreateTime.Year == DateTime.Now.Year && t.TrialType == inCommand.TrialType).Select(t => t.Code).DefaultIfEmpty().MaxAsync();
+
+ var currentYearMaxCodeNext = dbMaxCode + 1;
+
+
+ var trial = _mapper.Map(inCommand);
+ //trial.Id = NewId.NextGuid();
+ var yearStr = DateTime.Now.Year.ToString();
+
+ trial.Code = currentYearMaxCodeNext;
+ trial.TrialCode = (trial.TrialType == TrialType.ScientificResearch ? $"Z{code}RT" : $"Z{code}CT") + yearStr.Substring(yearStr.Length - 2) + currentYearMaxCodeNext.ToString("D3");
+ trial.CriterionTypes = $"|{string.Join('|', inCommand.CriterionTypeList.Select(x => ((int)x).ToString()).ToList())}|";
+
+
+ //多选信息
+ inCommand.ModalityIds.ForEach(modalityId => trial.TrialDicList.Add(new TrialDictionary() { DictionaryId = modalityId, KeyName = StaticData.Modality, TrialId = trial.Id }));
+
+
+ //添加项目后 项目状态变更为申请下载简历
+ trial.TrialEnrollStatus = (int)TrialEnrollStatus.ChooseDoctor;
+
+
+ trial = await _trialRepository.AddAsync(trial);
+
+ //如果是PM, 则需要将该人员添加到 运维人员表
+ //添加运维人员PM
+ await _trialUserRepository.AddAsync(new TrialUser() { TrialId = trial.Id, UserId = _userInfo.Id, JoinTime = DateTime.Now });
+
+
+ //默认采用系统邮件
+
+ trial.EmailAuthorizationCode = _systemEmailSendConfig.CurrentValue.AuthorizationCode;
+ trial.EmailFromEmail = _systemEmailSendConfig.CurrentValue.FromEmail;
+ trial.EmailFromName = _systemEmailSendConfig.CurrentValue.FromName;
+ trial.EmailSMTPServerAddress = _systemEmailSendConfig.CurrentValue.Host;
+ trial.EmailSMTPServerPort = _systemEmailSendConfig.CurrentValue.Port;
+ trial.IsConfigureEmail = true;
+ trial.CreateTime = DateTime.Now;
+
+ var success = await _trialRepository.SaveChangesAsync();
+
+
+ var caheInfo = new TrialCacheInfo() { TrialId = trial.Id, TrialStatusStr = trial.TrialStatusStr, CriterionTypes = trial.CriterionTypes, AuthorizationEncrypt = trial.AuthorizationEncrypt, AuthorizationDate = trial.AuthorizationDate, CreateUserId = trial.CreateUserId, TrialCode = trial.TrialCode };
+
+ await _provider.SetAsync(trial.Id.ToString(), JsonConvert.SerializeObject(caheInfo), TimeSpan.FromDays(7));
+
+ return ResponseOutput.Ok(trial);
+ }
+ else
+ {
+ var updateModel = inCommand;
+
+ foreach (var criterionType in inCommand.CriterionTypeList)
+ {
+ if (await _trialRepository.AnyAsync(u => u.ResearchProgramNo == inCommand.ResearchProgramNo && u.CriterionTypes.Contains($"|{(int)criterionType}|") && u.Id != updateModel.Id))
+ {
+ throw new BusinessValidationFailedException($"已存在研究方案号为{inCommand.ResearchProgramNo},该标准的项目");
+ }
+
+ }
+
+ if (!await _trialRepository.AnyAsync(u => u.Id == inCommand.Id && (u.TrialStatusStr == StaticData.TrialState.TrialInitializing || u.TrialStatusStr == StaticData.TrialState.TrialOngoing)))
+ {
+ //---项目状态只有处于:初始化或者进行中时,才允许操作。
+ throw new BusinessValidationFailedException(_localizer["Trial_InvalidProjectStatus"]);
+
+ }
+ // 判断项目Id 是否已经存在
+ if (await _trialRepository.AnyAsync(u => u.TrialCode == updateModel.TrialCode && u.Id != updateModel.Id))
+ {
+ //---已经存在相同的项目编号。
+ throw new BusinessValidationFailedException(_localizer["Trial_DuplicateProjectNumber"]);
+ }
+
+ var trial = await _trialRepository.FirstOrDefaultAsync(t => t.Id == updateModel.Id);
+
+
+ //删除中间表 Title对应的记录
+ await _trialDictionaryRepository.BatchDeleteNoTrackingAsync(t => t.TrialId == updateModel.Id);
+
+ //重新插入新的 Title记录
+
+ updateModel.ModalityIds.ForEach(modalityId => trial.TrialDicList.Add(new TrialDictionary() { DictionaryId = modalityId, KeyName = StaticData.Modality, TrialId = trial.Id }));
+
+
+ _mapper.Map(updateModel, trial);
+
+ trial.CriterionTypes = $"|{string.Join('|', inCommand.CriterionTypeList.Select(x => ((int)x).ToString()).ToList())}|";
+
+
+ var caheInfo = new TrialCacheInfo() { TrialId = trial.Id, TrialStatusStr = trial.TrialStatusStr, CriterionTypes = trial.CriterionTypes, AuthorizationEncrypt = trial.AuthorizationEncrypt, AuthorizationDate = trial.AuthorizationDate, CreateUserId = trial.CreateUserId, TrialCode = trial.TrialCode };
+
+ await _provider.SetAsync(trial.Id.ToString(), JsonConvert.SerializeObject(caheInfo), TimeSpan.FromDays(7));
+
+ var success = await _trialRepository.SaveChangesAsync();
+
+ return ResponseOutput.Ok(trial);
+
+ }
+ }
+
+ #endregion
+
+ #region 授权和激活
+
+
+
+ public async Task> GetTrialAuthorizationInfo(Guid trialId, [FromServices] IOptionsMonitor _hospitalOption)
+ {
+ var trialInfo = _trialRepository.Where(t => t.Id == trialId, ignoreQueryFilters: true).FirstOrDefault();
+
+ var authInfo = new TrialAuthorizationInfo()
+ {
+ TrialId = trialInfo.Id,
+ TrialCode = trialInfo.TrialCode,
+ CreateUserId = trialInfo.CreateUserId,
+ PurchaseDuration = 1,
+ CriterionTypeList = trialInfo.CriterionTypeList,
+ //CriterionTypes = trialInfo.CriterionTypes,
+ HospitalName = _hospitalOption.CurrentValue.HospitalName,
+ HospitalCode = _hospitalOption.CurrentValue.HospitalCode,
+ };
+
+ return ResponseOutput.Ok(authInfo);
+ }
+
+ ///
+ /// 获取项目授权码
+ ///
+ ///
+ ///
+ [HttpPost]
+ public async Task GetTrialAuthorizationCode(TrialAuthorizationInfo authInfo, [FromServices] IOptionsMonitor _hospitalOption)
+ {
+
+ // 将明文信息转换成 Base64 编码
+ string base64EncodedText = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(authInfo)));
+
+ return ResponseOutput.Ok(base64EncodedText);
+
+ }
+
+ ///
+ /// 获取授权码明文信息
+ ///
+ ///
+ ///
+ ///
+ [AllowAnonymous]
+ public async Task GetAuthorizationCodeInfo(string authorizationCode, [FromServices] IOptionsMonitor _hospitalOption)
+ {
+ // 解密 Base64 编码后的数据
+ byte[] base64DecodedBytes = Convert.FromBase64String(authorizationCode);
+ string decodedText = System.Text.Encoding.UTF8.GetString(base64DecodedBytes);
+
+
+ var authInfo = JsonConvert.DeserializeObject(decodedText);
+
+ if (authInfo == null)
+ {
+ return ResponseOutput.NotOk("不能解析该项目授权码");
+ }
+
+ return ResponseOutput.Ok(authInfo);
+ }
+
+ ///
+ /// 获取项目激活码
+ ///
+ ///
+ ///
+ ///
+ [AllowAnonymous]
+ [HttpPost]
+ public async Task GetTrialActivationCode(TrialAuthorizationInfo authorizationInfo, [FromServices] IOptionsMonitor _basicSystemConfigConfig)
+ {
+ authorizationInfo.ActiveDeadLineDate = DateTime.Now.Date.AddDays(8).AddSeconds(-1);
+ var info = Cryptography.EncryptString($"{JsonConvert.SerializeObject(authorizationInfo)}", _basicSystemConfigConfig.CurrentValue.AESKey, "Trial_AuthorizationEncrypt");
+
+ return ResponseOutput.Ok(info);
+
+ }
+
+ ///
+ /// 激活码获取明文信息
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task GetActivationCodeInfo(string activationCode,
+ [FromServices] IOptionsMonitor _hospitalOption,
+ [FromServices] IOptionsMonitor _basicSystemConfigConfig)
+ {
+
+ var decodedText = string.Empty;
+
+ try
+ {
+ decodedText = Cryptography.DecryptString(activationCode, _basicSystemConfigConfig.CurrentValue.AESKey, "Trial_AuthorizationEncrypt");
+
+
+ }
+ catch (Exception)
+ {
+
+ return ResponseOutput.NotOk("激活码有误,请核对,无法激活");
+ }
+
+ var authInfo = JsonConvert.DeserializeObject(decodedText);
+
+ if (authInfo != null)
+ {
+ return ResponseOutput.Ok(authInfo);
+ }
+ else
+ {
+ return ResponseOutput.NotOk("激活码信息有误!");
+ }
+
+ }
+
+
+ ///
+ /// 设置项目授权信息
+ ///
+ ///
+ ///
+ ///
+ [HttpPut]
+ public async Task ActivateTrial(Guid trialId, string activationCode,
+ [FromServices] IOptionsMonitor _basicSystemConfigConfig,
+ [FromServices] IFusionCache _provider,
+ [FromServices] IOptionsMonitor _hospitalOption)
+ {
+ var hospitalCode = _hospitalOption.CurrentValue.HospitalCode;
+ var trialInfo = _trialRepository.Where(t => t.Id == trialId, ignoreQueryFilters: true).FirstOrDefault();
+
+ var decodedText = string.Empty;
+ try
+ {
+ decodedText = Cryptography.DecryptString(activationCode, _basicSystemConfigConfig.CurrentValue.AESKey, "Trial_AuthorizationEncrypt");
+
+
+ }
+ catch (Exception)
+ {
+
+ return ResponseOutput.NotOk("激活码有误,请核对,无法激活");
+ }
+
+ var authInfo = JsonConvert.DeserializeObject(decodedText);
+
+ if (authInfo != null)
+ {
+ if (authInfo.TrialCode != trialInfo.TrialCode || authInfo.CreateUserId != trialInfo.CreateUserId || authInfo.HospitalCode != hospitalCode ||
+ authInfo.TrialId != trialInfo.Id || trialInfo.CriterionTypeList.Except(authInfo.CriterionTypeList).Count() != 0)
+ {
+ return ResponseOutput.NotOk("该授权码与该项目不匹配");
+ }
+
+ if (DateTime.Now > authInfo.ActiveDeadLineDate)
+ {
+ return ResponseOutput.NotOk($"当前时间{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}超过激活时间{authInfo.ActiveDeadLineDate.Value.ToString("yyyy-MM-dd HH:mm:ss")},请联系授权方重新获取激活码");
+ }
+
+ //截止日期
+ var deadLineDate = DateTime.Now.Date.AddMonths(authInfo.PurchaseDuration).AddDays(1).AddSeconds(-1);
+
+ authInfo.AuthorizationDeadLineDate = deadLineDate;
+ authInfo.ActiveTime = DateTime.Now;
+
+ var newActivationCode = Cryptography.EncryptString($"{JsonConvert.SerializeObject(authInfo)}", _basicSystemConfigConfig.CurrentValue.AESKey, "Trial_AuthorizationEncrypt");
+
+
+ await _trialRepository.BatchUpdateNoTrackingAsync(t => t.Id == trialId, u => new Trial() { AuthorizationEncrypt = newActivationCode, AuthorizationDate = deadLineDate });
+
+ var caheInfo = new TrialCacheInfo() { TrialId = trialInfo.Id, TrialStatusStr = trialInfo.TrialStatusStr, AuthorizationEncrypt = newActivationCode, CriterionTypes = trialInfo.CriterionTypes, AuthorizationDate = trialInfo.AuthorizationDate, CreateUserId = trialInfo.CreateUserId, TrialCode = trialInfo.TrialCode };
+
+ await _provider.SetAsync(trialInfo.Id.ToString(), JsonConvert.SerializeObject(caheInfo), TimeSpan.FromDays(7));
+ }
+ else
+ {
+ return ResponseOutput.NotOk("该授权码与该项目不匹配");
+
+ }
+
+ return ResponseOutput.Ok();
+
+ }
+
+
+
+ #endregion
#region 患者检查管理
///
- ///影像检查列表-患者为维度组织
+ ///检查管理-> 检查Tab 患者列表 (带加入的项目信息 以及检查统计) 原型标注错误,不是检查列表
///
///
///
[HttpPost]
- public async Task>> GetPatientList(PatientTrialQuery inQuery)
+ public async Task>> GetPatientList(PatientTrialQuery inQuery)
{
+ var isAdminOrOA = _userInfo.UserTypeEnumInt == (int)UserTypeEnum.Admin || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.OA || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.SuperAdmin;
#region new ok
- var query = _patientRepository.Where(t => t.TrialId == inQuery.TrialId)
+ var query = _patientRepository
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), t => t.PatientIdStr.Contains(inQuery.PatientIdStr))
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientName), t => t.PatientName.Contains(inQuery.PatientName))
- .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubejctCode), t => t.Subject.Code.Contains(inQuery.SubejctCode))
- .WhereIf(!string.IsNullOrWhiteSpace(inQuery.TrialSiteKeyInfo), t => t.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteKeyInfo)
- || t.TrialSite.TrialSiteAliasName.Contains(inQuery.TrialSiteKeyInfo) || t.TrialSite.TrialSiteName.Contains(inQuery.TrialSiteKeyInfo))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.ExperimentName), t => t.SubjectPatientList.Any(t => t.Subject.Trial.ExperimentName.Contains(inQuery.ExperimentName)))
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.CallingAE), t => t.SCPStudyList.Any(t => t.CallingAE == inQuery.CallingAE))
- .WhereIf(!string.IsNullOrWhiteSpace(inQuery.CalledAE), t => t.SCPStudyList.Any(t => t.CalledAE == inQuery.CalledAE))
.WhereIf(inQuery.BeginPushTime != null, t => t.LatestPushTime >= inQuery.BeginPushTime)
.WhereIf(inQuery.EndPushTime != null, t => t.LatestPushTime <= inQuery.EndPushTime);
- //foreach (var calledAE in inQuery.CalledAEList)
- //{
- // query = query.Where(t => t.SCPStudyList.Select(c => c.CalledAE).Contains(calledAE));
- //}
+ foreach (var calledAE in inQuery.CalledAEList)
+ {
+ query = query.Where(t => t.SCPStudyList.Select(c => c.CalledAE).Contains(calledAE));
+ }
var resultQuery = from patient in query
- select new PatientSubjectView()
+ select new PatientTrialView()
{
PatientId = patient.Id,
PatientBirthDate = patient.PatientBirthDate,
@@ -145,19 +573,18 @@ namespace IRaCIS.Core.Application.Service
StudyCount = patient.SCPStudyList.Count(),
- TrialId = patient.TrialId,
- SubejctId = patient.SubjectId,
- SubjectCode = patient.Subject.Code,
- TrialSiteAliasName = patient.TrialSite.TrialSiteAliasName,
- TrialSiteCode = patient.TrialSite.TrialSiteCode,
- TrialSiteName = patient.TrialSite.TrialSiteName
+ TrialList = patient.SubjectPatientList.Where(t => isAdminOrOA ? true : t.Subject.Trial.TrialUserList.Any(t => t.UserId == _userInfo.Id)).Select(c => new PatientTrialStatInfo()
+ {
+ ExperimentName = c.Subject.Trial.ExperimentName,
+ VisitCount = c.Subject.SubjectVisitList.Count()
+ }).ToList(),
};
- var pageList = await resultQuery.ToPagedListAsync(inQuery);
+ var pageList = await resultQuery.ToPagedListAsync(inQuery, nameof(PatientQueryView.PatientIdStr));
#endregion
@@ -165,18 +592,80 @@ namespace IRaCIS.Core.Application.Service
}
-
-
-
///
- /// 影像检查列表-> 获取患者的检查列表
+ /// 检查管理-> 患者加入项目 初始化勾选列表
///
///
///
[HttpPost]
- public async Task> GetPatientStudyList(PatientStudyInfoQuery inQuery)
+ public async Task>> GetPatientJoinTrialInitList(PatientJoinTrialInitQuery inQuery)
{
- var query = from scpStudy in _scpStudyRepository.Where(t => t.PatientId == inQuery.PatientId)
+
+ //排除已参与的项目列表
+ var exceptQuery = _subjectPatientRepository.Where(t => t.PatientId == inQuery.PatientId).Select(t => t.Subject.TrialId);
+
+ var trialQuery = _trialRepository.Where(t => t.TrialStatusStr == StaticData.TrialState.TrialOngoing)
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.Filter), t => t.ResearchProgramNo.Contains(inQuery.Filter) || t.ExperimentName.Contains(inQuery.Filter))
+ .Where(t => !exceptQuery.Any(c => c == t.Id)).ProjectTo(_mapper.ConfigurationProvider);
+
+
+ var pageList = await trialQuery.ToPagedListAsync(inQuery, nameof(PatientJoinTrialInitView.ResearchProgramNo));
+
+
+ return ResponseOutput.Ok(pageList);
+ }
+ ///
+ /// 检查管理-> 患者加入项目 下拉框勾选列表
+ ///
+ ///
+ ///
+ [HttpPost]
+ public async Task>> GetPatientJoinTrialInitSelectList(PatientJoinTrialInitQuery inQuery)
+ {
+ //排除已参与的项目列表
+ var exceptQuery = _subjectPatientRepository.Where(t => t.PatientId == inQuery.PatientId).Select(t => t.Subject.TrialId);
+
+ var trialQuery = _trialRepository.Where(t => t.TrialStatusStr == StaticData.TrialState.TrialOngoing)
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.Filter), t => t.ResearchProgramNo.Contains(inQuery.Filter) || t.ExperimentName.Contains(inQuery.Filter))
+ .Where(t => t.TrialUserList.Any(c => c.UserId == _userInfo.Id))
+ .Where(t => !exceptQuery.Any(c => c == t.Id)).ProjectTo(_mapper.ConfigurationProvider);
+
+ var list = trialQuery.ToList();
+ return ResponseOutput.Ok(list);
+ }
+
+
+
+
+ ///
+ /// 检查管理-> 患者已加入的列表(原型有误,应该展示 项目 下的subject 绑定关系)
+ ///
+ ///
+ ///
+ [HttpPost]
+ public async Task>> GetPatientJoinedTrialList(PatientJoinedTrialQuery inQuery)
+ {
+ var isAdminOrOA = _userInfo.UserTypeEnumInt == (int)UserTypeEnum.Admin || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.OA || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.SuperAdmin;
+
+ var trialQuery = _subjectPatientRepository.Where(t => t.PatientId == inQuery.PatientId)
+ .Where(t => isAdminOrOA ? true : t.Subject.Trial.TrialUserList.Any(t => t.UserId == _userInfo.Id))
+ .ProjectTo(_mapper.ConfigurationProvider);
+
+ var pageList = await trialQuery.ToListAsync();
+
+ return ResponseOutput.Ok(pageList);
+ }
+
+
+ ///
+ /// 检查管理-> 获取患者检查列表(同步影像数据之前的)
+ ///
+ ///
+ ///
+ [HttpPost]
+ public async Task> GetPatientStudyList(PatientStudyInfoQuery inQuery)
+ {
+ var query = from scpStudy in _studyRepository.Where(t => t.PatientId == inQuery.PatientId)
.WhereIf(inQuery.EarliestStudyTime != null, t => t.StudyTime >= inQuery.EarliestStudyTime)
.WhereIf(inQuery.LatestStudyTime != null, t => t.StudyTime <= inQuery.LatestStudyTime)
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.Modalities), t => t.Modalities.Contains(inQuery.Modalities))
@@ -191,70 +680,1599 @@ namespace IRaCIS.Core.Application.Service
SCPStudyId = scpStudy.Id,
SeriesCount = scpStudy.SeriesCount,
StudyTime = scpStudy.StudyTime,
-
-
-
-
- SubjectVisitId = scpStudy.SubjectVisitId,
- VisitName = scpStudy.SubjectVisit.VisitName,
- BlindName = scpStudy.SubjectVisit.BlindName
};
- //var sortField = string.IsNullOrWhiteSpace(inQuery.SortField) ? nameof(PatientStudySimpleView.StudyTime) : inQuery.SortField;
- //var orderQuery = inQuery.Asc ? query.OrderBy(sortField) : query.OrderBy(sortField + " desc");
+ var sortField = string.IsNullOrWhiteSpace(inQuery.SortField) ? nameof(PatientStudySimpleView.StudyTime) : inQuery.SortField;
+ var orderQuery = inQuery.Asc ? query.OrderBy(sortField) : query.OrderBy(sortField + " desc");
- //var list = await orderQuery.ToListAsync();
-
- var pageList = await query.ToPagedListAsync(inQuery, nameof(PatientStudySimpleView.StudyTime));
-
- return pageList;
- }
-
-
- public async Task> GetDicomCalledAEList(Guid trialId)
- {
- var list = await _scpStudyRepository.Where(t => t.TrialId == trialId).Select(t => t.CalledAE).Distinct().ToListAsync();
+ var list = await orderQuery.ToListAsync();
return list;
}
- public async Task> GetDicomCallingAEList(Guid trialId)
+
+
+ public async Task>> GetPatientSeriesList(Guid scpStudyId,
+ [FromServices] IRepository _seriesRepository,
+ [FromServices] IRepository _instanceRepository
+ )
{
- var list = await _scpStudyRepository.Where(t => t.TrialId == trialId).Select(t => t.CallingAE).Distinct().ToListAsync();
+
+ var seriesList = await _seriesRepository.Where(s => s.StudyId == scpStudyId).OrderBy(s => s.SeriesNumber).
+ ThenBy(s => s.SeriesTime).ThenBy(s => s.CreateTime)
+ .ProjectTo(_mapper.ConfigurationProvider).ToListAsync();
+
+ var idList = await _instanceRepository.Where(s => s.StudyId == scpStudyId).OrderBy(t => t.SeriesId).ThenBy(t => t.InstanceNumber)
+ .ThenBy(s => s.InstanceTime).ThenBy(s => s.CreateTime)
+ .Select(t => new { t.SeriesId, t.Id, t.Path, t.NumberOfFrames, t.InstanceNumber }).ToListAsync();//.GroupBy(u => u.SeriesId);
+
+ foreach (var item in seriesList)
+ {
+ item.InstanceList = idList.Where(s => s.SeriesId == item.Id).Select(u => u.Id).ToList();
+
+ //处理多帧
+ item.InstancePathList = idList.Where(s => s.SeriesId == item.Id).OrderBy(t => t.InstanceNumber)
+ .SelectMany(u =>
+ {
+
+ if (u.NumberOfFrames > 1)
+ {
+ var pathList = new List();
+
+ for (int i = 1; i <= u.NumberOfFrames; i++)
+ {
+ pathList.Add(u.Path + "?frame=" + (i - 1));
+ }
+ return pathList;
+ }
+ else
+ {
+ return new List { u.Path };
+
+ }
+ })
+ .ToList();
+ }
+
+
+ var study = await _studyRepository.FindAsync(scpStudyId);
+
+ return ResponseOutput.Ok(seriesList, study);
+ }
+
+ [UnitOfWork]
+ [HttpDelete]
+ public async Task DeletePatientStudy(Guid patiendId, Guid scpStudyId,
+ [FromServices] IRepository _SeriesRepository,
+ [FromServices] IRepository _instanceRepository)
+ {
+
+
+ if (_studySubjectVisitRepository.Any(t => t.SCPStudyId == scpStudyId && t.StudyId != null))
+ {
+ return ResponseOutput.NotOk("该检查已绑定某项目下受试者访视(不一定是你所创建的项目)并已提交生成任务,不允许删除该检查");
+ }
+ else
+ {
+ await _subjectPatientRepository.DeleteFromQueryAsync(t => t.PatientId == patiendId);
+ await _studySubjectVisitRepository.DeleteFromQueryAsync(t => t.SCPStudyId == scpStudyId);
+ }
+
+
+ await _studyRepository.BatchDeleteNoTrackingAsync(t => t.Id == scpStudyId);
+ await _SeriesRepository.BatchDeleteNoTrackingAsync(t => t.StudyId == scpStudyId);
+ await _instanceRepository.BatchDeleteNoTrackingAsync(t => t.StudyId == scpStudyId);
+
+ return ResponseOutput.Ok();
+
+ }
+
+
+
+ ///
+ /// 清除该患者绑定的受试者的所有的数据、(subject subjectVisit visitTask dicom)
+ ///
+ ///
+ ///
+ [UnitOfWork]
+ public async Task DeletePatientStudyAllData(Guid patientId,
+ [FromServices] IRepository _visitTaskRepository,
+ [FromServices] IRepository _SeriesRepository,
+ [FromServices] IRepository _instanceRepository,
+ [FromServices] IRepository _dicomStudyRepository,
+ [FromServices] IRepository _dicomSeriesRepository,
+ [FromServices] IRepository _dicomInstanceRepository,
+ [FromServices] IOSSService oSSService)
+ {
+ //清理自己管理的项目的数据
+ var subjectPatientList = await _subjectPatientRepository.Where(t => t.PatientId == patientId && t.Subject.Trial.TrialUserList.Any(t => t.UserId == _userInfo.Id))
+ .Select(t => new { t.SubjectId, StudyInstanceUidList = t.Patient.SCPStudyList.Select(t => t.StudyInstanceUid).ToList() }).ToListAsync();
+
+ if (_studyRepository.Any(t => t.IsUploadFinished == false && t.PatientId == patientId))
+ {
+ return ResponseOutput.NotOk("当前患者有检查正在上传,不允许清理数据");
+ }
+
+ foreach (var item in subjectPatientList)
+ {
+ var subjectId = item.SubjectId;
+
+ await _subjectRepository.BatchDeleteNoTrackingAsync(t => t.Id == subjectId);
+ await _studySubjectVisitRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId);
+ await _subjectVisitRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId);
+ await _visitTaskRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId);
+ await _dicomStudyRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId);
+ await _dicomSeriesRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId);
+ await _dicomInstanceRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId);
+ }
+
+ var instanceUidList = subjectPatientList.SelectMany(t => t.StudyInstanceUidList).Distinct().ToList();
+ foreach (var studyInstanceUid in instanceUidList)
+ {
+ {
+ var ossFolderPath = $"Dicom/{studyInstanceUid}";
+
+ await oSSService.DeleteFromPrefix(ossFolderPath);
+
+ }
+ }
+
+
+ var sCPStudyIdList = _studyRepository.Where(t => t.PatientId == patientId).Select(t => t.Id).ToList();
+
+ await _patientRepository.BatchDeleteNoTrackingAsync(t => t.Id == patientId);
+
+ foreach (var item in sCPStudyIdList)
+ {
+ await _studyRepository.BatchDeleteNoTrackingAsync(t => t.Id == item);
+ await _SeriesRepository.BatchDeleteNoTrackingAsync(t => t.StudyId == item);
+ await _instanceRepository.BatchDeleteNoTrackingAsync(t => t.StudyId == item);
+ }
+
+
+
+ return ResponseOutput.Ok();
+ }
+ #endregion
+
+
+ #region 受试者管理
+
+
+ [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
+ [HttpPost]
+ public async Task> AddOrUpdateSubject([FromBody] AddOrUpdateSubjectCommand subjectCommand)
+ {
+ var svlist = new List();
+
+ var verifyExp1 = new EntityVerifyExp()
+ {
+ VerifyExp = u => u.Code == subjectCommand.Code && u.TrialId == subjectCommand.TrialId,
+ //---已存在具有相关受试者编号的受试者。
+ VerifyMsg = _localizer["Subject_DuplicateSubjectNum"]
+ };
+
+
+ Subject? mapedSubject = null;
+
+ if (subjectCommand.Id == null) //insert
+ {
+
+
+ mapedSubject = await _subjectRepository.InsertFromDTOAsync(subjectCommand, false, verifyExp1);
+
+
+ }
+ else //update
+ {
+
+ mapedSubject = await _subjectRepository.UpdateFromDTOAsync(subjectCommand, false, false, verifyExp1/*, verifyExp2*/);
+
+ }
+
+
+
+ await _subjectRepository.SaveChangesAsync();
+
+ return ResponseOutput.Ok(mapedSubject.Id.ToString());
+
+ }
+
+ ///
+ /// 受试者管理-> 受试者列表 (带患者信息,患者信息是数组)
+ ///
+ ///
+ ///
+ [HttpPost]
+ public async Task>> GetPatientSubejctList(PatientSubjectQuery inQuery)
+ {
+ var subjectQuery = _subjectRepository.Where(u => u.TrialId == inQuery.TrialId)
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.Code), t => t.Code.Contains(inQuery.Code))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.ShortName), t => t.ShortName.Contains(inQuery.ShortName))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.Sex), t => t.Sex.Contains(inQuery.Sex))
+
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), t => t.SubjectPatientList.Any(t => t.Patient.PatientIdStr.Contains(inQuery.PatientIdStr)))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientName), t => t.SubjectPatientList.Any(t => t.Patient.PatientName.Contains(inQuery.PatientName)))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientSex), t => t.SubjectPatientList.Any(t => t.Patient.PatientSex.Contains(inQuery.PatientSex)))
+
+ .WhereIf(inQuery.Status != null, t => t.Status == inQuery.Status)
+ .ProjectTo(_mapper.ConfigurationProvider);
+
+ var pageList = await subjectQuery.ToPagedListAsync(inQuery, nameof(PatienSubejctView.Code) );
+
+
+ return ResponseOutput.Ok(pageList);
+ }
+
+ ///
+ /// 受试者管理-> 患者列表 (subject 列表进入,进行关系绑定初始化列表,排除已绑定的患者和已绑定给其他subject的患者)
+ ///
+ ///
+ ///
+ [HttpPost]
+ public async Task>> GetPatientInitList(PatientQuery inQuery)
+ {
+ var query = _patientRepository
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), t => t.PatientIdStr.Contains(inQuery.PatientIdStr))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientName), t => t.PatientName.Contains(inQuery.PatientName))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.CallingAE), t => t.SCPStudyList.Any(t => t.CallingAE == inQuery.CallingAE))
+ .WhereIf(inQuery.EarliestStudyTime != null, t => t.EarliestStudyTime >= inQuery.EarliestStudyTime)
+ .WhereIf(inQuery.LatestStudyTime != null, t => t.LatestStudyTime <= inQuery.LatestStudyTime)
+
+ //排除该受试者已绑定的患者
+ .WhereIf(inQuery.SubjectId != null, t => !t.SubjectPatientList.Any(u => u.SubjectId == inQuery.SubjectId))
+
+ //排除该项目已绑定的其他患者
+ .Where(t => !t.SubjectPatientList.Any(c => c.Subject.TrialId == inQuery.TrialId));
+
+ foreach (var calledAE in inQuery.CalledAEList)
+ {
+ query = query.Where(t => t.SCPStudyList.Select(c => c.CalledAE).Contains(calledAE));
+ }
+
+
+ var patientQuery = query.ProjectTo(_mapper.ConfigurationProvider);
+
+
+ var pageList = await patientQuery.ToPagedListAsync(inQuery, nameof(PatientQueryView.PatientIdStr));
+
+
+ return ResponseOutput.Ok(pageList);
+ }
+
+ ///
+ /// 受试者管理->患者列表 Dicom AE 下拉框数据获取
+ ///
+ ///
+ public async Task> GetDicomCalledAEList()
+ {
+ var list = await _studyRepository.Select(t => t.CalledAE).Distinct().ToListAsync();
return list;
}
- public async Task> GetDicomModalityList(Guid trialId)
+ public async Task> GetDicomCallingAEList()
{
- var list = await _scpStudyRepository.Where(t => t.TrialId == trialId).SelectMany(t => t.SeriesList).Select(t => t.Modality).Distinct().ToListAsync();
+ var list = await _studyRepository.Select(t => t.CallingAE).Distinct().ToListAsync();
return list;
}
///
- /// 影像访视上传 检查列表
+ ///受试者管理-> 患者列表 模糊搜索下拉 选择subject 排除已绑定并提交的
///
///
///
[HttpPost]
- public async Task> GetVisitPatientStudyFilterList(VisitPatientStudyFilterQuery inQuery)
+ public async Task> GetTrialSubejctSelectList(SubjectSelectQuery inQuery)
+ {
+ var list = await _subjectRepository.Where(t => t.TrialId == inQuery.TrialId && t.Status == SubjectStatus.OnVisit)
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectCode), u => u.Code.Contains(inQuery.SubjectCode))
+ .WhereIf(inQuery.SubjectId != null, t => t.Id == inQuery.SubjectId)
+ //.Where(t => !t.SubjectVisitList.SelectMany(t => t.SCPStudySubjectVisitList).Any(c => c.StudyId != null))
+ .Select(t => new SubjectSelectDto()
+ {
+ SubejctId = t.Id,
+ SubjectCode = t.Code,
+ Status = t.Status,
+ Sex = t.Sex,
+ ShortName = t.ShortName,
+ Age = t.Age,
+ BirthDate = t.BirthDate,
+ PatientList = t.SubjectPatientList.Select(c => new PatienBasicInfo() { PatientId = c.PatientId, PatientIdStr = c.Patient.PatientIdStr }).ToList()
+ })
+ .ToListAsync();
+
+ return list;
+ }
+
+ #endregion
+
+
+
+ #region 患者和受试者绑定,生成访视,预先绑定检查和访视
+
+ [HttpPost]
+ public async Task GetVisitStudyVerifyTime(VisitStudyVerifyTimeQuery inQuery)
+ {
+ var scpStudyList = await _studySubjectVisitRepository.Where(t => t.TrialId == inQuery.TrialId && t.SubjectId == inQuery.SubjectId && t.SCPStudyId != inQuery.SCPStudyId)
+ .Select(t => new { SubjectVisitId = t.SubjectVisitId, StudyTime = t.SCPStudy.StudyTime, t.SubjectVisit.SubmitState, t.SubjectVisit.VisitName, VisitNum = t.SubjectVisit.VisitNum, SCPStudyId = t.SCPStudyId })
+ .ToListAsync();
+
+ var result = scpStudyList.GroupBy(t => new { t.VisitName, t.VisitNum, t.SubjectVisitId, t.SubmitState })
+ .Select(g => new
+ {
+ g.Key.SubmitState,
+ g.Key.VisitNum,
+ g.Key.VisitName,
+ g.Key.SubjectVisitId,
+ VisitMaxStudyTime = g.Max(c => c.StudyTime),
+ VisitMinStudyTime = g.Min(c => c.StudyTime)
+ });
+
+ return ResponseOutput.Ok(result);
+ }
+
+ public class AuToBindingStudyInfo
+ {
+ public Guid SCPStudyId { get; set; }
+ public DateTime? StudyTime { get; set; }
+ }
+
+ private async Task DealAutoBindingStudyAsync(Guid trialId, Guid subjectId, List studyList, decimal? startBindVisitNum = null)
+ {
+ studyList = studyList.OrderBy(t => t.StudyTime).ToList();
+
+
+ //自动创建访视 和检查绑定
+
+ //1. 查询已存在的访视
+ var subjectAllVisitList = await _subjectVisitRepository.Where(t => t.SubjectId == subjectId)
+ .Select(t => new
+ {
+ t.SubjectId,
+ SubjectVisitId = t.Id,
+ t.SubmitState,
+ VisitNum = t.VisitNum,
+ MaxStudyTime = t.SCPStudySubjectVisitList.Max(t => t.SCPStudy.StudyTime),
+ MinStudyTime = t.SCPStudySubjectVisitList.Min(t => t.SCPStudy.StudyTime)
+ })
+ .ToListAsync();
+
+
+ //2、获取项目配置
+ var trialconfig = _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.BlindBaseLineName, t.BlindFollowUpPrefix }).FirstOrDefault();
+
+ //3、 未提交的最小的访视号 从这个访视开始绑定 因为重新开始绑定,所以将访视未提交的状态重置
+
+ var subjectMaxVisitNum = startBindVisitNum == null ? subjectAllVisitList.Where(t => t.SubmitState != SubmitStateEnum.Submitted).MinOrDefault(t => t.VisitNum) : startBindVisitNum.Value;
+
+ await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.SubjectId == subjectId && t.SubmitState != SubmitStateEnum.Submitted && t.VisitNum > subjectMaxVisitNum, c => new SubjectVisit() { SubmitState = SubmitStateEnum.None });
+
+ List<(int VisitCount, Guid SCPStudyId)> visits = new List<(int, Guid)>();
+
+ int visitCount = 0;
+
+ DateTime? lastVisitTime = null;
+
+ foreach (var study in studyList)
+ {
+ if (lastVisitTime == null || (study.StudyTime - lastVisitTime.Value).Value.TotalDays >= 15)
+ {
+ // 当前时间点与上一个访视时间点间隔大于等于 15 天,需要建立一个新的访视
+ visitCount++;
+
+ visits.Add((visitCount, study.SCPStudyId));
+ }
+ else
+ {
+ visits.Add((visitCount, study.SCPStudyId));
+ }
+
+ lastVisitTime = study.StudyTime;
+ }
+
+ //4、生成访视 并且绑定
+
+ for (int i = 0; i < visitCount; i++)
+ {
+
+ var bindSubjectVisitId = Guid.Empty;
+
+ var bindVisitNum = i + subjectMaxVisitNum;
+
+ var existSubjectVisit = subjectAllVisitList.FirstOrDefault(t => t.SubjectId == subjectId && t.VisitNum == bindVisitNum);
+
+ if (existSubjectVisit == null)
+ {
+ bindSubjectVisitId = NewId.NextGuid();
+
+ //基线
+ if (bindVisitNum == 0)
+ {
+
+ await _subjectVisitRepository.AddAsync(new SubjectVisit() { TrialId = trialId, SubjectId = subjectId, VisitName = trialconfig.BlindBaseLineName, VisitNum = bindVisitNum, Id = bindSubjectVisitId, SubmitState = SubmitStateEnum.ToSubmit, IsBaseLine = true });
+
+ }
+ else
+ {
+ await _subjectVisitRepository.AddAsync(new SubjectVisit() { TrialId = trialId, SubjectId = subjectId, VisitName = trialconfig.BlindFollowUpPrefix + $" {(int)bindVisitNum}", VisitNum = bindVisitNum, Id = bindSubjectVisitId, SubmitState = SubmitStateEnum.ToSubmit });
+ }
+ }
+
+ else
+ {
+ bindSubjectVisitId = existSubjectVisit.SubjectVisitId;
+ }
+
+
+
+ var currentVisitStudyList = visits.Where(t => t.VisitCount == (i + 1)).ToList();
+
+ foreach (var item in currentVisitStudyList)
+ {
+ //访视状态为未提交才绑定
+ if (!subjectAllVisitList.Any(t => t.SubjectId == subjectId && t.SubjectVisitId == bindSubjectVisitId && t.SubmitState == SubmitStateEnum.Submitted))
+ {
+ var find = await _subjectVisitRepository.FindAsync(bindSubjectVisitId);
+ find.SubmitState = SubmitStateEnum.ToSubmit;
+ await _studySubjectVisitRepository.AddAsync(new SCPStudySubjectVisit() { TrialId = trialId, SubjectVisitId = bindSubjectVisitId, SCPStudyId = item.SCPStudyId, SubjectId = subjectId });
+
+ }
+
+ }
+
+
+ }
+
+
+ await _subjectPatientRepository.SaveChangesAsync();
+ }
+
+ ///
+ /// 之前患者和subject已绑定后,新来了的检查 可能需要新建访视,或者和已有访视在同一区间,需要自动绑定
+ ///
+ ///
+ ///
+ [HttpPost]
+ [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
+ public async Task AutoBindingPatientStudyVisit(AutoBindingPatientStudyVisitCommand inCommand)
+ {
+ //找到已绑定患者,但是没绑定检查的 新来的检查->现在换成未提交的
+ //var query = from scpStudy in _studyRepository.Where(t => !t.SCPStudySubjectVisitList.Any(t => t.TrialId == inCommand.TrialId))
+ var query = from scpStudy in _studyRepository.Where(t => !t.SCPStudySubjectVisitList.Any(t => t.TrialId == inCommand.TrialId && t.SubjectVisit.SubmitState == SubmitStateEnum.Submitted))
+ join subjectPatient in _subjectPatientRepository.Where(t => t.Subject.TrialId == inCommand.TrialId)
+ on scpStudy.PatientId equals subjectPatient.PatientId
+ select new
+ {
+ subjectPatient.SubjectId,
+ subjectPatient.PatientId,
+ SCPStudyId = scpStudy.Id,
+ StudyTime = scpStudy.StudyTime
+ };
+
+ var list = query.ToList();
+
+ if (list.Count > 0)
+ {
+ //2、获取项目配置
+ var trialconfig = _trialRepository.Where(t => t.Id == inCommand.TrialId).Select(t => new { t.BlindBaseLineName, t.BlindFollowUpPrefix }).FirstOrDefault();
+
+ var subjectIdList = list.Select(t => t.SubjectId).ToList();
+
+ var allSubjectVisitList = await _subjectVisitRepository.Where(t => subjectIdList.Contains(t.SubjectId)).Select(t => new { t.SubjectId, SubjectVisitId = t.Id, t.SubmitState, VisitNum = t.VisitNum, MaxStudyTime = t.SCPStudySubjectVisitList.Max(t => t.SCPStudy.StudyTime), MinStudyTime = t.SCPStudySubjectVisitList.Min(t => t.SCPStudy.StudyTime) }).ToListAsync();
+
+ foreach (var g in list.GroupBy(t => t.SubjectId))
+ {
+
+ var subjectId = g.Key;
+ var subjectStudyList = g.ToList();
+
+ var subjectVisitList = allSubjectVisitList.Where(t => t.SubjectId == subjectId).ToList();
+
+ // 预先处理1: 删除未提交的所有绑定的检查记录,所有检查一起考虑绑定
+
+ await _studySubjectVisitRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId && t.SubjectVisit.SubmitState != SubmitStateEnum.Submitted);
+
+ //预处理2 找到该subjecct 已提交的访视的最大检查时间,绑定的检查时间要比这个时间要大
+
+ var maxStudyTime = subjectVisitList.Where(t => t.SubmitState == SubmitStateEnum.Submitted).MaxOrDefault(t => t.MaxStudyTime);
+
+ var needDealStudyList = subjectStudyList.WhereIf(maxStudyTime != null, t => t.StudyTime > maxStudyTime).Select(t => new AuToBindingStudyInfo() { SCPStudyId = t.SCPStudyId, StudyTime = t.StudyTime }).ToList();
+
+ await DealAutoBindingStudyAsync(inCommand.TrialId, subjectId, needDealStudyList);
+
+ }
+
+ await _subjectVisitRepository.SaveChangesAsync();
+ }
+
+
+
+ return ResponseOutput.Ok();
+
+ }
+
+
+
+ public async Task VerifyTrialSubject(VerifyTrialSubjectCommand inCommand, [FromServices] IRepository _subjectVisitReposiotry)
+ {
+ var find = await _subjectRepository.FirstOrDefaultAsync(t => t.TrialId == inCommand.TrialId && t.Code == inCommand.SubjectCode);
+ if (find != null)
+ {
+ return ResponseOutput.NotOk($"项目中已存在编号为“{find.Code}”的受试者,状态为:{(find.Status == SubjectStatus.OnVisit ? "访视中" : "访视结束")},不允许添加。", ApiResponseCodeEnum.NeedTips);
+
+ }
+ return ResponseOutput.Ok();
+
+ }
+
+ ///
+ /// 建立subject与患者绑定 如果是下拉,则传递SubjectId,如果不存在,创建,那么就传递 SubjectCode
+ ///
+ /// 绑定以后,后台自动创建访视 和检查预先绑定
+ ///
+ ///
+ ///
+ [HttpPost]
+ [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
+ [UnitOfWork]
+ public async Task AddSubjectPatientBinding(AddSubjectPatientCommand inCommand, [FromServices] IRepository _subjectVisitReposiotry)
+ {
+ var patientInfo = _patientRepository.Where(t => inCommand.PatientIdList.Contains(t.Id)).Select(t => new { t.PatientBirthDate, t.PatientName, t.PatientSex }).FirstOrDefault();
+
+ var subjectId = Guid.Empty;
+
+ if (inCommand.SubjectId == null)
+ {
+ var find = await _subjectRepository.FirstOrDefaultAsync(t => t.TrialId == inCommand.TrialId && t.Code == inCommand.SubjectCode);
+
+ if (find == null)
+ {
+ subjectId = NewId.NextSequentialGuid();
+
+ var subjectName = patientInfo?.PatientName ?? string.Empty;
+
+ DateTime date;
+
+ DateTime? birthDate = DateTime.TryParse(patientInfo.PatientBirthDate, out date) ? date : null;
+
+ var sex = patientInfo.PatientSex?.ToUpper();
+
+ // 计算年龄
+ int? age = null;
+
+ if (birthDate != null)
+ {
+ var patientAge = DateTime.Now.Year - birthDate.Value.Year;
+ // 如果生日还未到,年龄减去一岁
+ if (DateTime.Now < birthDate.Value.AddYears(patientAge))
+ {
+ patientAge--;
+ }
+ age = patientAge;
+ }
+
+
+
+
+ await _subjectRepository.AddAsync(new Subject() { Id = subjectId, Code = inCommand.SubjectCode, TrialId = inCommand.TrialId, ShortName = subjectName, BirthDate = birthDate, Sex = sex, Age = age });
+ }
+ else
+ {
+
+ return ResponseOutput.NotOk($"项目中已存在编号为“{find.Code}”的受试者,状态为:{(find.Status == SubjectStatus.OnVisit ? "访视中" : "访视结束")},不允许添加。");
+ //subjectId = find.Id;
+ }
+
+ }
+ else
+ {
+ subjectId = (Guid)inCommand.SubjectId;
+ }
+
+ foreach (var item in inCommand.PatientIdList)
+ {
+ if (!_subjectPatientRepository.Any(t => t.PatientId == item && t.SubjectId == subjectId))
+ {
+ await _subjectPatientRepository.AddAsync(new SubjectPatient() { PatientId = item, SubjectId = subjectId });
+ }
+
+ }
+
+
+ // 预先处理1: 数据库可能有已存在的subject 患者绑定,在这里要一起考虑绑定
+
+ var dbPatientIdList = _subjectPatientRepository.Where(t => t.SubjectId == subjectId).Select(t => t.PatientId).ToList();
+ inCommand.PatientIdList = dbPatientIdList.Union(inCommand.PatientIdList).Distinct().ToList();
+
+ // 预先处理2: 删除未提交的所有绑定的检查记录,所有检查一起考虑绑定
+ await _studySubjectVisitRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId && t.SubjectVisit.SubmitState != SubmitStateEnum.Submitted);
+
+ //预处理3 找到该subjecct 已提交的访视的最大检查时间,绑定的检查时间要比这个时间要大
+
+ var maxStudyTime = _studySubjectVisitRepository.Where(t => t.SubjectId == subjectId && t.SubjectVisit.SubmitState == SubmitStateEnum.Submitted)
+ .MaxOrDefault(t => t.SCPStudy.StudyTime);
+
+
+ // 预处理4: 处理需要绑定的检查
+ //获取 该受试者绑定患者已存在的检查,考虑要生成多少个访视,去除已提交的检查
+
+ var studyList = await _studyRepository.Where(t => inCommand.PatientIdList.Contains(t.PatientId)
+ && !t.SCPStudySubjectVisitList.Any(t => t.SubjectId == subjectId && t.SubjectVisit.SubmitState == SubmitStateEnum.Submitted))
+ .WhereIf(maxStudyTime != null, t => t.StudyTime > maxStudyTime)
+ .Select(t => new AuToBindingStudyInfo { SCPStudyId = t.Id, StudyTime = t.StudyTime }).OrderBy(t => t.StudyTime).Distinct().ToListAsync();
+
+
+ await DealAutoBindingStudyAsync(inCommand.TrialId, subjectId, studyList);
+
+ return ResponseOutput.Ok(subjectId);
+ }
+
+ ///
+ /// 删除 受试者 和患者之间的绑定
+ ///
+ ///
+ ///
+ [HttpDelete]
+ [UnitOfWork]
+ [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
+ public async Task DeleteSubjectPatientBinding(DeleteSubejctPatientCommand inCommand,
+
+
+ [FromServices] IRepository _visitTaskRepository,
+ [FromServices] IRepository _dicomStudyRepository,
+ [FromServices] IRepository _dicomSeriesRepository,
+ [FromServices] IRepository _dicomInstanceRepository)
+ {
+ var subjectId = inCommand.SubjectId;
+ var patientId = inCommand.PatientId;
+
+ var find = await _subjectPatientRepository.FirstOrDefaultAsync(t => t.PatientId == patientId && t.SubjectId == subjectId);
+
+ if (find != null)
+ {
+ //该患者检查 没有绑定提交的
+ if (!_studySubjectVisitRepository.Any(t => t.SubjectId == find.SubjectId && t.SCPStudy.PatientId == patientId && t.StudyId != null))
+ {
+ await _subjectPatientRepository.DeleteAsync(find);
+
+ await _studySubjectVisitRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == find.SubjectId && t.SCPStudy.PatientId == patientId);
+
+ await _subjectPatientRepository.SaveChangesAsync();
+
+
+
+ //触发其余访视检查自动绑定
+
+ // 预先处理1: 数据库可能有已存在的subject 患者绑定,在这里要一起考虑绑定
+
+ var dbPatientIdList = _subjectPatientRepository.Where(t => t.SubjectId == subjectId).Select(t => t.PatientId).ToList();
+
+ // 预先处理2: 删除未提交的所有绑定的检查记录,所有检查一起考虑绑定
+ await _studySubjectVisitRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId && t.SubjectVisit.SubmitState != SubmitStateEnum.Submitted);
+
+ //预处理3 找到该subjecct 已提交的访视的最大检查时间,绑定的检查时间要比这个时间要大
+
+ var maxStudyTime = _studySubjectVisitRepository.Where(t => t.SubjectId == subjectId && t.SubjectVisit.SubmitState == SubmitStateEnum.Submitted)
+ .MaxOrDefault(t => t.SCPStudy.StudyTime);
+
+
+ // 预处理4: 处理需要绑定的检查
+ //获取 该受试者绑定患者已存在的检查,考虑要生成多少个访视,去除已提交的检查
+
+ var studyList = await _studyRepository.Where(t => dbPatientIdList.Contains(t.PatientId)
+ && !t.SCPStudySubjectVisitList.Any(t => t.SubjectId == subjectId && t.SubjectVisit.SubmitState == SubmitStateEnum.Submitted))
+ .WhereIf(maxStudyTime != null, t => t.StudyTime > maxStudyTime)
+ .Select(t => new AuToBindingStudyInfo { SCPStudyId = t.Id, StudyTime = t.StudyTime }).OrderBy(t => t.StudyTime).Distinct().ToListAsync();
+
+ await DealAutoBindingStudyAsync(inCommand.TrialId, subjectId, studyList);
+
+
+
+ }
+ else if (_studySubjectVisitRepository.Any(t => t.SubjectId == subjectId && t.SubjectVisit.SubmitState == SubmitStateEnum.Submitted))
+ {
+ return ResponseOutput.NotOk(_localizer["该受试者有访视已提交,不允许解除受试者和该患者的绑定关系"]);
+ }
+
+
+
+ //当前是最后移除的患者
+ if (!_subjectPatientRepository.Any(t => t.SubjectId == subjectId && t.PatientId != patientId))
+ {
+ #region 设置了末次访视,然后一起删除会报 级联错误
+
+ ////q1:单独查询删除
+ //await _subjectRepository.DeleteFromQueryAsync(t => t.Id == subjectId);
+ //await _subjectVisitRepository.DeleteFromQueryAsync(t => t.SubjectId == subjectId);
+
+ //q2 一起查询删除 没区别,一样报错
+ //var subject = await _subjectRepository.Where(t => t.Id == subjectId, true).Include(t => t.SubjectVisitList).FirstOrDefaultAsync();
+ //await _subjectRepository.DeleteAsync(subject);
+ #endregion
+
+ //q3 设置导航属性为null 依旧不行
+ //var subject = await _subjectRepository.Where(t => t.Id == subjectId, true).Include(t => t.SubjectVisitList).FirstOrDefaultAsync();
+ //subject.FinalSubjectVisit = null;
+ //subject.FinalSubjectVisitId = null;
+
+ //foreach (var item in subject.SubjectVisitList)
+ //{
+ // item.SubjectId = Guid.Empty;
+ // item.Subject = null;
+ //}
+ //await _subjectRepository.DeleteAsync(subject);
+
+ await _subjectVisitRepository.DeleteFromQueryAsync(t => t.SubjectId == subjectId, true);
+
+ await _subjectRepository.DeleteFromQueryAsync(t => t.Id == subjectId);
+ }
+
+
+
+ await _subjectPatientRepository.SaveChangesAsync();
+
+
+ ////暂时删除访视 上线删除
+ //await _subjectVisitRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId);
+ //await _visitTaskRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId);
+ //await _dicomStudyRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId);
+ //await _dicomSeriesRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId);
+ //await _dicomInstanceRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId);
+ }
+
+ return ResponseOutput.Ok();
+ }
+
+ ///
+ /// 患者检查 与SubjectVisit 的绑定
+ ///
+ ///
+ ///
+ [HttpPost]
+ [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
+ [UnitOfWork]
+ [Obsolete]
+ public async Task AddSubjectPatientStudyBinding(List inCommandList)
{
- var trialSiteId = _subjectRepository.Where(t => t.Id == inQuery.SubjectId).Select(t => t.TrialSiteId).FirstOrDefault();
- var query = from scpStudy in _scpStudyRepository
- //未绑定的患者,或者自己已绑定但是未绑定访视的
- .Where(t => t.Patient.SubjectId == null || (t.Patient.SubjectId == inQuery.SubjectId && t.SubjectVisitId == null))
- //中心
- .Where(t => t.TrialSiteId == trialSiteId)
+ var subjectId = inCommandList.First().SubjectId;
+
+ //查询数据库所有的绑定,然后将修改的绑定更改过去,验证是否符合要求
+
+ var allSubjectVisitList = _subjectVisitRepository.Where(t => t.SubjectId == subjectId).Select(t => new { SubjectVisitId = t.Id, t.VisitNum }).ToList();
+
+ var allStudyList = await _studySubjectVisitRepository.Where(t => t.SubjectId == subjectId).Select(t => new VerifyVisitStudyDTO() { SubjectVisitId = t.SubjectVisitId, StudyTime = t.SCPStudy.StudyTime, VisitNum = t.SubjectVisit.VisitNum, SCPStudyId = t.SCPStudyId }).ToListAsync();
+
+
+ foreach (var item in inCommandList)
+ {
+ var find = allStudyList.Where(t => t.SCPStudyId == item.SCPStudyId).FirstOrDefault();
+
+ if (find != null)
+ {
+ find.SubjectVisitId = item.SubjectVisitId;
+ find.VisitNum = allSubjectVisitList.Where(t => t.SubjectVisitId == item.SubjectVisitId).FirstOrDefault().VisitNum;
+ }
+ }
+
+ foreach (var item in inCommandList)
+ {
+ var currentVisitStudyList = allStudyList.Where(t => t.SubjectVisitId == item.SubjectVisitId).OrderBy(t => t.StudyTime).ToList();
+ var currentVisitMaxTimeStudy = currentVisitStudyList.LastOrDefault();
+
+ if (currentVisitMaxTimeStudy != null)
+ {
+ var currentVisitMaxStudyTime = currentVisitMaxTimeStudy.StudyTime;
+
+ if (allStudyList.Where(t => t.VisitNum < currentVisitMaxTimeStudy.VisitNum).Any(t => t.StudyTime > currentVisitMaxStudyTime))
+ {
+ return ResponseOutput.NotOk(_localizer["当前提交的访视中,前序访视的检查时间比当前绑定访视的检查时间要大,请核查!"]);
+ }
+ if (allStudyList.Where(t => t.VisitNum > currentVisitMaxTimeStudy.VisitNum).Any(t => t.StudyTime < currentVisitMaxStudyTime))
+ {
+ return ResponseOutput.NotOk(_localizer["当前提交的访视中,后序访视的检查时间比当前绑定访视的检查时间要小,请核查!"]);
+ }
+ }
+
+ }
+
+
+
+ var studyIdList = inCommandList.Select(t => t.SCPStudyId).ToList();
+
+ await _studySubjectVisitRepository.BatchDeleteNoTrackingAsync(t => studyIdList.Contains(t.SCPStudyId));
+
+ foreach (var item in inCommandList)
+ {
+ var sv = await _subjectVisitRepository.FindAsync(item.SubjectVisitId);
+ sv.SubmitState = SubmitStateEnum.ToSubmit;
+
+ await _studySubjectVisitRepository.AddAsync(new SCPStudySubjectVisit() { TrialId = item.TrialId, SCPStudyId = item.SCPStudyId, SubjectVisitId = item.SubjectVisitId, SubjectId = item.SubjectId });
+
+ }
+ await _studySubjectVisitRepository.SaveChangesAsync();
+
+ return ResponseOutput.Ok();
+ }
+
+
+
+ ///
+ /// 修改 访视 和检查的绑定关系 IsAdd 区分添加 还是移除
+ ///
+ ///
+ ///
+ [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
+ [UnitOfWork]
+ public async Task UpdateSubjectVisitStudyBinding(UpdateSubjectVisitStudyBindingCommand inCommand)
+ {
+ var subjectId = inCommand.SubjectId;
+ var subjectVisitId = inCommand.SubjectVisitId;
+
+ if (_subjectRepository.Any(t => t.Id == subjectId && t.Status == SubjectStatus.EndOfVisit))
+ {
+ return ResponseOutput.NotOk(_localizer["受试者状态为访视结束,不允许绑定访视和检查"]);
+ }
+
+ var subjectVisit = await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId);
+
+
+
+
+ if (inCommand.IsAdd)
+ {
+ //找到所有访视的检查
+ var allStudyList = await _studySubjectVisitRepository.Where(t => t.SubjectId == subjectId).Select(t => new VerifyVisitStudyDTO() { SubjectVisitId = t.SubjectVisitId, StudyTime = t.SCPStudy.StudyTime, VisitNum = t.SubjectVisit.VisitNum, SCPStudyId = t.SCPStudyId }).ToListAsync();
+
+ var bindVisit = _subjectVisitRepository.Where(t => t.Id == subjectVisitId).Select(t => new { SubjectVisitId = t.Id, t.VisitNum, SubjectCode = t.Subject.Code }).FirstOrDefault();
+
+ var bindStudy = _studyRepository.Where(t => t.Id == inCommand.SCPStudyId).Select(t => new { SCPStudyId = t.Id, t.StudyTime }).FirstOrDefault();
+
+ //是否之前和其他访视绑定
+ var findStudy = allStudyList.FirstOrDefault(t => t.SCPStudyId == inCommand.SCPStudyId);
+ if (findStudy != null)
+ {
+
+ findStudy.SubjectVisitId = bindVisit.SubjectVisitId;
+ findStudy.VisitNum = bindVisit.VisitNum;
+ }
+ else
+ {
+ //新的检查
+ allStudyList.Add(new VerifyVisitStudyDTO() { SCPStudyId = inCommand.SCPStudyId, SubjectVisitId = bindVisit.SubjectVisitId, VisitNum = bindVisit.VisitNum, StudyTime = bindStudy.StudyTime });
+
+ }
+
+ var visitOrderStudyList = allStudyList.OrderBy(t => t.VisitNum).ThenBy(t => t.StudyTime).ToList();
+
+ var studyTimeOrderList = visitOrderStudyList.OrderBy(t => t.StudyTime).ToList();
+
+ bool arraysEqual = visitOrderStudyList.SequenceEqual(studyTimeOrderList);
+
+ if (!arraysEqual)
+ {
+ return ResponseOutput.NotOk(_localizer[$"{bindVisit.SubjectCode}所提交的访视中的检查时间,不符合后续访视的检查时间比前序检查的时间大的要求"]);
+ }
+
+
+ //如果该检查之前和其他访视绑定,那么更新绑定的访视就可以
+ var otherFind = await _studySubjectVisitRepository.FirstOrDefaultAsync(t => t.SCPStudyId == inCommand.SCPStudyId && t.SubjectId == inCommand.SubjectId);
+
+
+ if (otherFind == null)
+ {
+ await _studySubjectVisitRepository.AddAsync(new SCPStudySubjectVisit() { TrialId = inCommand.TrialId, SCPStudyId = inCommand.SCPStudyId, SubjectVisitId = subjectVisitId, SubjectId = inCommand.SubjectId });
+
+ }
+ else
+ {
+ //为了稽查 先删除 再添加
+
+ await _studySubjectVisitRepository.DeleteAsync(otherFind);
+
+ if (!_studySubjectVisitRepository.Any(t => t.SubjectVisitId == otherFind.SubjectVisitId && t.SCPStudyId != inCommand.SCPStudyId))
+ {
+ var updateVisit = await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == otherFind.SubjectVisitId);
+ updateVisit.SubmitState = SubmitStateEnum.None;
+ }
+
+ //otherFind.SubjectVisitId = inCommand.SubjectVisitId;
+ await _studySubjectVisitRepository.AddAsync(new SCPStudySubjectVisit() { TrialId = inCommand.TrialId, SCPStudyId = inCommand.SCPStudyId, SubjectVisitId = subjectVisitId, SubjectId = inCommand.SubjectId });
+
+
+ }
+
+
+ subjectVisit.SubmitState = SubmitStateEnum.ToSubmit;
+
+
+ await _studySubjectVisitRepository.SaveChangesAsync();
+
+ #region 处理自动绑定
+
+ //触发自动绑定后续检查和访视的绑定关系
+
+ //预先处理1:找到所有未提交的检查访视绑定
+ var studyList = await _studySubjectVisitRepository.Where(t => t.SubjectId == subjectId && t.SubjectVisit.SubmitState != SubmitStateEnum.Submitted)
+ .Select(t => new VerifyVisitStudyDTO() { SubjectVisitId = t.SubjectVisitId, StudyTime = t.SCPStudy.StudyTime, VisitNum = t.SubjectVisit.VisitNum, SCPStudyId = t.SCPStudyId }).ToListAsync();
+
+
+ var needDealStudyList = studyList.Where(t => t.VisitNum > subjectVisit.VisitNum).Select(t => new AuToBindingStudyInfo() { SCPStudyId = t.SCPStudyId, StudyTime = t.StudyTime }).ToList();
+
+ if (needDealStudyList.Count > 0)
+ {
+ //没有该访视的检查
+ var findVisitStudy = studyList.Where(t => t.SubjectVisitId == subjectVisitId).FirstOrDefault();
+
+ //就从当前访视开始绑定,否则就从下一个访视开始绑定
+ var startBindingVisitNum = findVisitStudy == null ? subjectVisit.VisitNum : subjectVisit.VisitNum + 1;
+
+ // 预先处理2: 删除未提交的所有绑定的检查记录,所有检查一起考虑绑定
+ await _studySubjectVisitRepository.DeleteFromQueryAsync(t => t.SubjectId == subjectId && t.SubjectVisit.VisitNum >= startBindingVisitNum);
+
+ await DealAutoBindingStudyAsync(inCommand.TrialId, subjectId, needDealStudyList, startBindingVisitNum);
+ }
+
+ #endregion
+ }
+ else
+ {
+ var find = await _studySubjectVisitRepository.FirstOrDefaultAsync(t => t.SCPStudyId == inCommand.SCPStudyId && t.SubjectVisitId == subjectVisitId);
+ await _studySubjectVisitRepository.DeleteAsync(find);
+
+ if (!_studySubjectVisitRepository.Any(t => t.SubjectVisitId == subjectVisitId && t.SCPStudyId != find.SCPStudyId))
+ {
+ subjectVisit.SubmitState = SubmitStateEnum.None;
+ }
+
+ await _studySubjectVisitRepository.SaveChangesAsync();
+
+
+ //预处理1 找到该subjecct 已提交的访视的最大检查时间,绑定的检查时间要比这个时间要大
+
+ var maxStudyTime = _subjectVisitRepository.Where(t => t.SubjectId == subjectId && t.SubmitState == SubmitStateEnum.Submitted).SelectMany(t => t.SCPStudySubjectVisitList).MaxOrDefault(t => t.SCPStudy.StudyTime);
+
+
+ //预先处理2:找到所有未提交的检查访视绑定 大于当前访视
+ var studyList = await _studySubjectVisitRepository.Where(t => t.SubjectId == subjectId && t.SubjectVisit.SubmitState != SubmitStateEnum.Submitted && t.SubjectVisit.VisitNum > subjectVisit.VisitNum)
+ .WhereIf(maxStudyTime != null, t => t.SCPStudy.StudyTime > maxStudyTime)
+ .Select(t => new AuToBindingStudyInfo() { StudyTime = t.SCPStudy.StudyTime, SCPStudyId = t.SCPStudyId }).Distinct().ToListAsync();
+
+
+ if (studyList.Count > 0)
+ {
+ //预处理3 删除所有未提交的绑定关系 所有检查一起考虑绑定 排除当前访视
+
+ await _studySubjectVisitRepository.DeleteFromQueryAsync(t => t.SubjectId == subjectId && t.SubjectVisit.SubmitState != SubmitStateEnum.Submitted && t.SubjectVisit.VisitNum > subjectVisit.VisitNum);
+
+ //没有从当前访视开始绑定,否则就从下一个访视开始绑定
+ var startBindingVisitNum = !_studySubjectVisitRepository.Any(t => t.SubjectVisitId == subjectVisitId) ? subjectVisit.VisitNum : subjectVisit.VisitNum + 1;
+
+ await DealAutoBindingStudyAsync(inCommand.TrialId, subjectId, studyList, startBindingVisitNum);
+ }
+
+ }
+
+
+
+
+
+
+
+ return ResponseOutput.Ok();
+ }
+
+
+ ///
+ /// 提交 患者检查和访视的绑定
+ ///
+ ///
+ ///
+ [HttpPost]
+ [UnitOfWork]
+ [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
+ public async Task SubmitVisitStudyBinding(SubmitVisitStudyBindingCommand inCommand,
+ [FromServices] IOptionsMonitor _basicSystemConfigConfig,
+ [FromServices] IRepository _repository
+ )
+ {
+
+ //防止访视重复
+ inCommand.SubjectVisitIdList = inCommand.SubjectVisitIdList.Distinct().ToList();
+
+ //确认当前提交的最大的访视之前所有的访视都已提交,并且没有漏的
+
+ var curentMaxNum = await _subjectVisitRepository.Where(t => inCommand.SubjectVisitIdList.Contains(t.Id)).Select(t => t.VisitNum).MaxAsync();
+
+ var allVisitList = _subjectVisitRepository.Where(t => t.TrialId == inCommand.TrialId && t.SubjectId == inCommand.SubjectId && t.VisitNum <= curentMaxNum).Select(t => new { SubjectVisitId = t.Id, t.Subject.Status, t.VisitNum, t.SubmitState }).OrderBy(t => t.VisitNum).ToList();
+
+ //批量提交
+ if (inCommand.SubjectVisitIdList.Count > 1)
+ {
+ if (allVisitList.Where(t => t.SubmitState != SubmitStateEnum.Submitted).Count() != inCommand.SubjectVisitIdList.Count())
+ {
+ return ResponseOutput.NotOk(_localizer["当前批量提交的访视中间有遗漏的访视或者前序有访视未提交"]);
+ }
+ }
+
+ else
+ {
+ if (allVisitList.Any(t => t.VisitNum < curentMaxNum && t.SubmitState != SubmitStateEnum.Submitted))
+ {
+ return ResponseOutput.NotOk(_localizer["前序有访视未提交,请先提交前序访视"]);
+ }
+ }
+
+ if (allVisitList.Any(t => t.Status == SubjectStatus.EndOfVisit))
+ {
+ return ResponseOutput.NotOk(_localizer["受试者状态为访视结束,不允许提交访视生成任务"]);
+ }
+
+ var list = await _studySubjectVisitRepository.Where(t => inCommand.SubjectVisitIdList.Contains(t.SubjectVisitId)).Select(t => new { t.SCPStudyId, t.SCPStudy.PatientId, t.SubjectVisitId, t.SubjectVisit.VisitNum, t.SubjectVisit.SubjectId, SubjectCode = t.SubjectVisit.Subject.Code, t.SubjectVisit.TrialId, t.SCPStudy.StudyTime, t.StudyId, t.SCPStudy.IsUploadFinished }).OrderBy(t => t.StudyTime).ToListAsync();
+
+ if (list.Any(t => t.StudyId != null))
+ {
+ return ResponseOutput.NotOk(_localizer["有访视和检查处于已绑定关系,不允许再次提交绑定"]);
+ }
+
+ if (list.Any(t => t.IsUploadFinished == false))
+ {
+ return ResponseOutput.NotOk(_localizer["有访视检查正在传输中,不允许提交"]);
+ }
+
+
+ //判断每个subject 批量提交的是否符合时间要求
+ foreach (var g in list.GroupBy(t => new { t.SubjectId, t.SubjectCode }))
+ {
+ var visitOrderStudyList = g.OrderBy(t => t.VisitNum).ThenBy(t => t.StudyTime).ToList();
+
+ var studyTimeOrderList = visitOrderStudyList.OrderBy(t => t.StudyTime).ToList();
+
+ bool arraysEqual = visitOrderStudyList.SequenceEqual(studyTimeOrderList);
+
+ if (!arraysEqual)
+ {
+ return ResponseOutput.NotOk(_localizer[$"{g.Key.SubjectCode}所提交的访视中的检查时间,不符合后续访视的检查时间比前序检查的时间大的要求"]);
+ }
+
+ if (DateTime.Now < studyTimeOrderList.Max(t => t.StudyTime))
+ {
+ return ResponseOutput.NotOk(_localizer[$"您当前修改了服务器时间,试图绕过软件授权,请恢复服务器时间,并联系授权方授权才可进行操作"]);
+ }
+ }
+
+ var trialConfig = await _trialRepository.Where(t => t.Id == inCommand.TrialId).Select(t => new { t.IsEnrollementQualificationConfirm, t.IsPDProgressView, t.AuthorizationEncrypt }).FirstOrDefaultAsync();
+
+
+
+ //var decodedText = Cryptography.DecryptString(trialConfig.AuthorizationEncrypt, _basicSystemConfigConfig.CurrentValue.AESKey, "Trial_AuthorizationEncrypt");
+
+ //var authInfo = JsonConvert.DeserializeObject(decodedText);
+
+
+
+
+ var @lock = _distributedLockProvider.CreateLock($"StudyCode");
+
+ using (await @lock.AcquireAsync())
+ {
+ var dbStudyCodeIntMax = _repository.Where(s => s.TrialId == inCommand.TrialId).Select(t => t.Code).DefaultIfEmpty().Max();
+
+ int currentNextCodeInt = dbStudyCodeIntMax + 1;
+
+ foreach (var item in list)
+ {
+ //提交的访视下没有检查
+ if (!_studySubjectVisitRepository.Any(t => t.SubjectVisitId == item.SubjectVisitId))
+ {
+ return ResponseOutput.NotOk(_localizer["提交的访视下必须有影像检查!"]);
+ }
+
+ var dbSubjectVisit = await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == item.SubjectVisitId);
+
+ //处理脏数据,可能之前的绑定的数据状态是待上传,但是已经绑定了检查
+ if (dbSubjectVisit.SubmitState == SubmitStateEnum.ToSubmit || dbSubjectVisit.SubmitState == SubmitStateEnum.None)
+ {
+ dbSubjectVisit.SubmitState = SubmitStateEnum.Submitted;
+ dbSubjectVisit.SubmitTime = DateTime.Now;
+ dbSubjectVisit.SubmitUserId = _userInfo.Id;
+
+ //维护统一状态
+ //dbSubjectVisit.ReadingStatus = ReadingStatusEnum.TaskAllocate;
+
+ dbSubjectVisit.AuditState = AuditStateEnum.QCPassed;
+ dbSubjectVisit.CheckState = CheckStateEnum.CVPassed;
+
+ dbSubjectVisit.IsEnrollmentConfirm = dbSubjectVisit.IsBaseLine ? trialConfig.IsEnrollementQualificationConfirm : false;
+
+ dbSubjectVisit.PDState = trialConfig.IsPDProgressView ? PDStateEnum.PDProgress : PDStateEnum.None;
+ }
+
+
+
+
+ var find = _studyRepository.Where(t => t.Id == item.SCPStudyId).Include(t => t.SeriesList).Include(t => t.InstanceList).FirstOrDefault();
+
+ if (find != null)
+ {
+ //重新算Id
+ Guid studyId = IdentifierHelper.CreateGuid(item.TrialId.ToString(), find.StudyInstanceUid);
+ find.Id = studyId;
+ var newStuty = _mapper.Map(find);
+
+ await _repository.AddAsync(newStuty);
+ //newStuty.Id = NewId.NextSequentialGuid();
+
+ newStuty.SeqId = Guid.Empty;
+ newStuty.Code = currentNextCodeInt;
+ newStuty.StudyCode = AppSettings.GetCodeStr(currentNextCodeInt, nameof(DicomStudy));
+ newStuty.TrialId = item.TrialId;
+ newStuty.SubjectId = item.SubjectId;
+ newStuty.SubjectVisitId = item.SubjectVisitId;
+
+ var newSeriesList = _mapper.Map>(find.SeriesList);
+
+ foreach (var series in newSeriesList)
+ {
+ Guid seriesId = IdentifierHelper.CreateGuid(item.TrialId.ToString(), find.StudyInstanceUid, series.SeriesInstanceUid);
+
+ //重新算Id
+ series.Id = seriesId;
+ series.StudyId = newStuty.Id;
+
+ series.SeqId = Guid.Empty;
+ series.TrialId = item.TrialId;
+ series.SubjectId = item.SubjectId;
+ series.SubjectVisitId = item.SubjectVisitId;
+ }
+
+ await _repository.AddRangeAsync(newSeriesList);
+
+ var newInstanceList = _mapper.Map>(find.InstanceList);
+
+ foreach (var instance in newInstanceList)
+ {
+ Guid seriesId = IdentifierHelper.CreateGuid(item.TrialId.ToString(), find.StudyInstanceUid, instance.SeriesInstanceUid);
+ Guid instanceId = IdentifierHelper.CreateGuid(item.TrialId.ToString(), find.StudyInstanceUid, instance.SeriesInstanceUid, instance.SopInstanceUid);
+ //重新算Id
+ instance.Id = instanceId;
+ instance.SeriesId = seriesId;
+ instance.StudyId = newStuty.Id;
+
+ instance.SeqId = Guid.Empty;
+ instance.TrialId = item.TrialId;
+ instance.SubjectId = item.SubjectId;
+ instance.SubjectVisitId = item.SubjectVisitId;
+ }
+ await _repository.AddRangeAsync(newInstanceList);
+ }
+
+ currentNextCodeInt++;
+
+ await _studySubjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.SubjectVisitId == item.SubjectVisitId && t.SCPStudyId == item.SCPStudyId, u => new SCPStudySubjectVisit() { StudyId = find.Id });
+
+ await _subjectPatientRepository.BatchUpdateNoTrackingAsync(t => t.SubjectId == item.SubjectId && t.PatientId == item.PatientId, u => new SubjectPatient() { IsBinded = true });
+
+ }
+
+
+ }
+
+
+
+ await _studySubjectVisitRepository.SaveChangesAsync();
+
+ return ResponseOutput.Ok();
+ }
+
+ #endregion
+
+ #region 访视基本管理
+
+
+ ///
+ /// 绑定访视 初始化患者检查列表
+ ///
+ ///
+ ///
+ [HttpPost]
+ public async Task> GetVisitPatientStudyList(PatientStudyQuery inQuery)
+ {
+ var patientQuery = from scpStudy in _studyRepository
+ .Where(t => inQuery.PatientIdList.Contains(t.PatientId))
+ .WhereIf(inQuery.EarliestStudyTime != null, t => t.StudyTime >= inQuery.EarliestStudyTime)
+ .WhereIf(inQuery.LatestStudyTime != null, t => t.StudyTime <= inQuery.LatestStudyTime)
+
+ join scpStudySubjectVisit in _studySubjectVisitRepository.Where(t => t.SubjectVisit.TrialId == inQuery.TrialId) on scpStudy.Id equals scpStudySubjectVisit.SCPStudyId into cc
+ from scpStudySubjectVisit in cc.DefaultIfEmpty()
+ select new PatientStudySelectDto()
+ {
+ Description = scpStudy.Description,
+ CalledAE = scpStudy.CalledAE,
+ InstanceCount = scpStudy.InstanceCount,
+ Modalities = scpStudy.Modalities,
+ PatientId = scpStudy.Patient.Id,
+
+ PatientIdStr = scpStudy.PatientIdStr,
+ PatientAge = scpStudy.PatientAge,
+ PatientBirthDate = scpStudy.PatientBirthDate,
+ PatientSex = scpStudy.PatientSex,
+ PatientName = scpStudy.PatientName,
+
+ SCPStudyId = scpStudy.Id,
+ SeriesCount = scpStudy.SeriesCount,
+ StudyTime = scpStudy.StudyTime,
+
+ CallingAE = scpStudy.CallingAE,
+
+ SubmitState = scpStudySubjectVisit.SubjectVisit.SubmitState,
+ SubjectVisitId = scpStudySubjectVisit.SubjectVisitId
+ }
+ ;
+
+ var sortField = string.IsNullOrWhiteSpace(inQuery.SortField) ? nameof(VisitPatientStudyView.StudyTime) : inQuery.SortField;
+ var orderQuery = inQuery.Asc ? patientQuery.OrderBy(sortField) : patientQuery.OrderBy(sortField + " desc");
+
+ var list = await orderQuery.ToListAsync();
+
+
+ return list;
+ }
+
+
+
+ ///
+ /// 访视管理- 获取subject 已存在的访视列表 ,同时获取项目访视的配置 在otherData里
+ ///
+ ///
+ ///
+ ///
+ [HttpPost]
+ public async Task GetSubjectVisitSelectList(SubjectVisitSelectQuery inQuery, [FromServices] IRepository _subjectVisitReposiotry)
+ {
+
+ var scpStudyList = await _studySubjectVisitRepository.Where(t => t.TrialId == inQuery.TrialId && t.SubjectId == inQuery.SubjectId && t.SCPStudyId != inQuery.SCPStudyId)
+ .Select(t => new { t.SubjectVisitId, StudyTime = t.SCPStudy.StudyTime })
+ .ToListAsync();
+
+ var result = scpStudyList.GroupBy(t => t.SubjectVisitId)
+ .Select(g => new
+ {
+
+ SubejctVisitId = g.Key,
+ VisitMaxStudyTime = g.Max(c => c.StudyTime),
+ VisitMinStudyTime = g.Min(c => c.StudyTime)
+ }).ToList();
+
+ var list = _subjectVisitReposiotry.Where(t => t.SubjectId == inQuery.SubjectId).ProjectTo(_mapper.ConfigurationProvider).ToList();
+
+ foreach (var item in list)
+ {
+ item.VisitMaxStudyTime = result.Where(t => t.SubejctVisitId == item.Id).FirstOrDefault()?.VisitMaxStudyTime;
+ item.VisitMinStudyTime = result.Where(t => t.SubejctVisitId == item.Id).FirstOrDefault()?.VisitMinStudyTime;
+ }
+
+ var trialconfig = _trialRepository.Where(t => t.Id == inQuery.TrialId).Select(t => new { t.BlindBaseLineName, t.BlindFollowUpPrefix }).FirstOrDefault();
+
+ return ResponseOutput.Ok(list, trialconfig);
+ }
+ ///
+ /// 添加或者更新受试者访视
+ ///
+ ///
+ ///
+ ///
+ [HttpPost]
+ [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
+ public async Task AddOrUpdateSubjectVisit(AddOrUpdateSubjectVisitCommand incommand, [FromServices] IRepository _subjectVisitReposiotry)
+ {
+ //var verifyExp1 = new EntityVerifyExp()
+ //{
+ // VerifyExp = t => t.VisitNum == incommand.VisitNum && t.SubjectId == incommand.SubjectId,
+ // //---该受试者的访视计划中已经包含一个具有相同访视号的访视。
+ // VerifyMsg = _localizer["Visit_DuplicateVisitNo"]
+ //};
+
+
+
+ //var verifyExp3 = new EntityVerifyExp()
+ //{
+ // VerifyExp = t => t.SubjectId == incommand.SubjectId && t.VisitName == incommand.VisitName,
+ // //---该受试者的访视计划中已经包含一个具有相同访视名称的访视。
+ // VerifyMsg = _localizer["Visit_DuplicateVisitName"]
+ //};
+
+
+ var find = _subjectVisitRepository.Where(t => t.TrialId == incommand.TrialId && t.SubjectId == incommand.SubjectId && t.VisitNum == incommand.VisitNum && t.VisitName == incommand.VisitName).FirstOrDefault();
+
+ if (find != null)
+ {
+ return ResponseOutput.Ok(find.Id);
+ }
+ else
+ {
+ var entity = await _subjectVisitReposiotry.InsertOrUpdateAsync(incommand, true);
+
+ return ResponseOutput.Ok(entity.Id);
+ }
+
+ }
+
+
+
+ ///
+ /// 前端利用组件打成压缩包,后端返回路径和压缩包的信息
+ ///
+ ///
+ ///
+ [HttpGet("{subjectId:guid}/{subjectVisitId:guid}")]
+ public async Task GetSubjectImageZipInfo(Guid subjectId, Guid subjectVisitId)
+ {
+
+ //var patientQuery = from subject in _subjectRepository.Where(t => t.Id == subjectId)
+ // select new
+ // {
+ // SubjectCode = subject.Code,
+
+ // PatientList = subject.SubjectPatientList.Select(c => new
+ // {
+ // c.Patient.PatientIdStr,
+ // c.Patient.PatientName,
+
+ // StudyList = c.Patient.SCPStudyList.Select(u => new
+ // {
+ // u.StudyTime,
+
+
+ // SeriesList = u.SeriesList.Select(z => new
+ // {
+ // z.Modality,
+
+ // InstancePathList = z.SCPInstanceList.Select(k => new
+ // {
+ // k.Path
+ // })
+ // })
+ // })
+ // })
+ // };
+
+
+ var subject_visit_studyQuery = from subject in _subjectRepository.Where(t => t.Id == subjectId)
+
+ select new
+ {
+ SubjectCode = subject.Code,
+
+ PatientList = subject.SubjectPatientList.Select(c => new
+ {
+ c.Patient.PatientIdStr,
+ c.Patient.PatientName
+ }).ToList(),
+
+ VisitList = subject.SubjectVisitList.Where(t => t.Id == subjectVisitId)
+ .Select(z => new
+ {
+ z.VisitName,
+
+ StudyList = z.StudyList.Select(u => new
+ {
+ u.PatientIdStr,
+ u.StudyTime,
+ u.StudyCode,
+
+ SeriesList = u.SeriesList.Select(z => new
+ {
+ z.Modality,
+
+ InstancePathList = z.DicomInstanceList.Select(k => new
+ {
+ k.Path
+ })
+ })
+
+ })
+
+ }),
+
+
+ };
+
+
+
+
+
+ #region subject_patient_visit
+ //var testquery = from subject in _subjectRepository.Where(t => t.Id == subjectId)
+ // select new
+ // {
+ // SubjectCode = subject.Code,
+
+ // PatientList = subject.SubjectPatientList.Select(c => new
+ // {
+ // c.Patient.PatientIdStr,
+ // c.Patient.PatientName,
+
+ // VisitList = c.Subject.SubjectVisitList.Select(z => new
+ // {
+ // z.VisitName,
+
+ // StudyList = z.SCPStudySubjectVisitList.Where(t => t.SCPStudy.PatientId == c.PatientId).Select(u => new
+ // {
+ // //u.SCPStudy.PatientId,
+ // u.SCPStudy.PatientIdStr,
+ // u.SCPStudy.StudyTime,
+
+ // SeriesList = u.SCPStudy.SeriesList.Select(z => new
+ // {
+ // z.Modality,
+
+ // InstancePathList = z.SCPInstanceList.Select(k => new
+ // {
+ // k.Path
+ // })
+ // })
+
+ // })
+
+ // }),
+
+
+
+ // })
+ // };
+
+ #endregion
+
+
+
+
+ //var subjectVisitQuery = from subject in _subjectRepository.Where(t => t.Id == subjectId)
+ // select new
+ // {
+ // SubjectCode = subject.Code,
+
+ // VisitList = subject.SubjectVisitList.Select(z => new
+ // {
+ // z.VisitName,
+
+ // StudyList = z.SCPStudySubjectVisitList.Select(u => new
+ // {
+ // u.SCPStudy.PatientId,
+ // u.SCPStudy.PatientIdStr,
+ // u.SCPStudy.StudyTime,
+
+ // SeriesList = u.SCPStudy.SeriesList.Select(z => new
+ // {
+ // z.Modality,
+
+ // InstancePathList = z.SCPInstanceList.Select(k => new
+ // {
+ // k.Path
+ // })
+ // })
+
+ // })
+
+
+ // })
+
+ // };
+
+ var result = subject_visit_studyQuery.FirstOrDefault(); ;
+
+ return ResponseOutput.Ok(result);
+ }
+
+
+
+
+ ///
+ ///访视管理-> 访视列表 (带患者信息,患者信息是数组)
+ ///
+ ///
+ ///
+ [HttpPost]
+ public async Task>> GetPatientSubejctVisitList(PatientSubejctVisitQuery inQuery)
+ {
+ var query = _subjectVisitRepository.Where(t => t.TrialId == inQuery.TrialId)
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectCode), u => u.Subject.Code.Contains(inQuery.SubjectCode))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectSex), u => u.Subject.Sex.Contains(inQuery.SubjectSex))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectShortName), u => u.Subject.ShortName.Contains(inQuery.SubjectShortName))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.VisitName), u => u.VisitName.Contains(inQuery.VisitName))
+ .WhereIf(inQuery.SubmitState != null, u => u.SubmitState == inQuery.SubmitState)
+ .WhereIf(inQuery.BeginStudyTime != null, t => t.SCPStudySubjectVisitList.Min(t => t.SCPStudy.StudyTime) >= inQuery.BeginStudyTime)
+ .WhereIf(inQuery.EndStudyTime != null, t => t.SCPStudySubjectVisitList.Max(t => t.SCPStudy.StudyTime) <= inQuery.EndStudyTime)
+
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), t => t.Subject.SubjectPatientList.Any(t => t.Patient.PatientIdStr.Contains(inQuery.PatientIdStr)))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientName), t => t.Subject.SubjectPatientList.Any(t => t.Patient.PatientName.Contains(inQuery.PatientName)))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientSex), t => t.Subject.SubjectPatientList.Any(t => t.Patient.PatientSex.Contains(inQuery.PatientSex)))
+ .Select(t => new PatientSubjectVisitView()
+ {
+ PatientList = t.Subject.SubjectPatientList.Select(c => new PatientBasicInfo()
+ {
+ PatientId = c.PatientId,
+ PatientAge = c.Patient.PatientAge,
+ PatientBirthDate = c.Patient.PatientBirthDate,
+ PatientIdStr = c.Patient.PatientIdStr,
+ PatientSex = c.Patient.PatientSex,
+ PatientName = c.Patient.PatientName,
+ }).ToList(),
+
+ TrialId = t.TrialId,
+ SubjectId = t.SubjectId,
+ SubjectVisitId = t.Id,
+ SubjectAge = t.Subject.Age,
+ SubjectSex = t.Subject.Sex,
+ SubjectShortName = t.Subject.ShortName,
+ SubjectCode = t.Subject.Code,
+ SubmitState = t.SubmitState,
+ SubmitTime = t.SubmitTime,
+ VisitNum = t.VisitNum,
+ VisitName = t.VisitName,
+ VisitEarliestStudyTime = t.SCPStudySubjectVisitList.Min(t => t.SCPStudy.StudyTime),
+ VisitLatestStudyTime = t.SCPStudySubjectVisitList.Max(t => t.SCPStudy.StudyTime),
+ VisitImageZipPath = t.VisitImageZipPath,
+ PackState = t.PackState,
+ });
+
+ var defalutSortArray = new string[] { nameof(PatientSubjectVisitView.SubjectId), nameof(PatientSubjectVisitView.VisitNum) };
+ var pageList = await query.ToPagedListAsync(inQuery, defalutSortArray);
+
+
+
+ return ResponseOutput.Ok(pageList);
+ }
+
+
+ ///
+ ///访视管理-> 获取当前访视 已绑定的患者检查 (从访视列表 进入修改绑定)
+ ///
+ ///
+ ///
+ [HttpPost]
+ public async Task> GetCurrentVisitPatientStudyList(SubjectVisitStudyQuery inQuery)
+ {
+ var patientQuery = _studySubjectVisitRepository.Where(t => t.SubjectVisitId == inQuery.SujectVisitId && t.SubjectVisit.SubmitState != SubmitStateEnum.Submitted)
+ //.WhereIf(inQuery.SubmitState != null, u => u.SubjectVisit.SubmitState == inQuery.SubmitState)
+ .ProjectTo(_mapper.ConfigurationProvider);
+
+ var sortField = string.IsNullOrWhiteSpace(inQuery.SortField) ? nameof(VisitPatientStudyView.StudyTime) : inQuery.SortField;
+ var orderQuery = inQuery.Asc ? patientQuery.OrderBy(sortField) : patientQuery.OrderBy(sortField + " desc");
+
+ var list = await orderQuery.ToListAsync();
+
+ return list;
+ }
+
+
+ ///
+ /// 访视管理-> 获取可选访视列表 (从访视列表 进入修改绑定)
+ ///
+ ///
+ ///
+ [HttpPost]
+ public async Task> GetPatientOtherStudyList(PatientStudyOtherQuery inQuery)
+ {
+ var query = from scpStudy in _studyRepository.Where(t => inQuery.PatientIdList.Contains(t.PatientId) && !t.SCPStudySubjectVisitList.Any(t => (t.SubjectVisitId == inQuery.SujectVisitId || t.SubjectVisit.SubmitState == SubmitStateEnum.Submitted) && t.TrialId == inQuery.TrialId))
.WhereIf(inQuery.EarliestStudyTime != null, t => t.StudyTime >= inQuery.EarliestStudyTime)
.WhereIf(inQuery.LatestStudyTime != null, t => t.StudyTime <= inQuery.LatestStudyTime)
- .WhereIf(!string.IsNullOrWhiteSpace(inQuery.Modalities), t => t.Modalities.Contains(inQuery.Modalities))
- .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientInfo), t => t.PatientIdStr.Contains(inQuery.PatientInfo) || t.PatientName.Contains(inQuery.PatientInfo) || t.PatientSex.Contains(inQuery.PatientInfo))
- select new VisitPatientStudyFilterView()
+ .WhereIf(!string.IsNullOrEmpty(inQuery.PatientIdStr), t => t.PatientIdStr.Contains(inQuery.PatientIdStr))
+ //不属于该访视的检查 或者未绑定的检查
+ join scpStudySubjectVisit in _studySubjectVisitRepository.Where(c => c.TrialId == inQuery.TrialId) on scpStudy.Id equals scpStudySubjectVisit.SCPStudyId
+ into dd
+ from scpStudySV in dd.DefaultIfEmpty()
+ select new VisitPatientStudyView()
{
+ PatientIdStr = scpStudy.PatientIdStr,
+ PatientBirthDate = scpStudy.PatientBirthDate,
+ PatientAge = scpStudy.PatientAge,
+ PatientName = scpStudy.PatientName,
+ PatientSex = scpStudy.PatientSex,
Description = scpStudy.Description,
CalledAE = scpStudy.CalledAE,
CallingAE = scpStudy.CallingAE,
@@ -264,352 +2282,515 @@ namespace IRaCIS.Core.Application.Service
SCPStudyId = scpStudy.Id,
SeriesCount = scpStudy.SeriesCount,
StudyTime = scpStudy.StudyTime,
- BodyPartExamined = scpStudy.BodyPartExamined,
- AccessionNumber = scpStudy.AccessionNumber,
- PatientBirthDate = scpStudy.PatientBirthDate,
- PatientAge = scpStudy.PatientAge,
- PatientIdStr = scpStudy.PatientIdStr,
- PatientName = scpStudy.PatientName,
- PatientSex = scpStudy.PatientSex,
+ SubmitState = scpStudySV.SubjectVisit.SubmitState,
+ SubjectVisitId = scpStudySV.SubjectVisitId,
+ VisitName = scpStudySV.SubjectVisit.VisitName,
};
+ #region 废弃
+ //var notCurrentVisitQuey = _studySubjectVisitRepository.Where(t => t.SubjectVisitId != inQuery.SujectVisitId && t.SCPStudy.Patient.Id == inQuery.PatientId)
+ // .Select(t => new VisitPatientStudyView()
+ // {
+ // Description = t.SCPStudy.Description,
+ // CalledAE = t.SCPStudy.CalledAE,
+ // InstanceCount = t.SCPStudy.InstanceCount,
+ // Modalities = t.SCPStudy.Modalities,
+ // PatientId = t.SCPStudy.PatientId,
+ // SCPStudyId = t.SCPStudy.PatientId,
+ // SeriesCount = t.SCPStudy.SeriesCount,
+ // StudyTime = t.SCPStudy.StudyTime,
+ // SubjectVisitId = t.SubjectVisitId,
+ // VisitName = t.SubjectVisit.VisitName,
+ // });
- var pageList = await query.ToPagedListAsync(inQuery, nameof(PatientStudySimpleView.StudyTime));
+ //var notBindQuery= _studyRepository.Where(t => t.PatientId == inQuery.PatientId && t.pa)
- return pageList;
+ //var patientQuery = query
+
+ // .ProjectTo(_mapper.ConfigurationProvider);
+ #endregion
+ var sortField = string.IsNullOrWhiteSpace(inQuery.SortField) ? nameof(VisitPatientStudyView.StudyTime) : inQuery.SortField;
+ var orderQuery = inQuery.Asc ? query.OrderBy(sortField) : query.OrderBy(sortField + " desc");
+
+ var list = await orderQuery.ToListAsync();
+
+ return list;
+ }
+
+ #endregion
+
+ #region 检查管理
+
+
+
+ ///
+ ///检查管理-> 检查列表 (同步影像数据之前的)
+ ///
+ ///
+ ///
+ [HttpPost]
+ public async Task>> GetPatientStudyBeforeConfirmList(TrialPatientStudyQuery inQuery)
+ {
+ #region 只查询已绑定的
+ //var query = _studySubjectVisitRepository.Where(t => t.SubjectVisit.TrialId == inQuery.TrialId)
+ // .WhereIf(inQuery.PatientId != null, t => t.SCPStudy.PatientId == inQuery.PatientId)
+ // .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectCode), u => u.SubjectVisit.Subject.Code.Contains(inQuery.SubjectCode))
+ // .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), u => u.SCPStudy.Patient.PatientIdStr.Contains(inQuery.PatientIdStr))
+ // .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientSex), t => t.SCPStudy.Patient.PatientSex.Contains(inQuery.PatientSex))
+ // .WhereIf(inQuery.SubjectAge != null, t => t.SubjectVisit.Subject.Age == inQuery.SubjectAge)
+ // .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectCode), u => u.SubjectVisit.Subject.Code.Contains(inQuery.SubjectCode))
+ // .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectSex), u => u.SubjectVisit.Subject.Sex.Contains(inQuery.SubjectSex))
+ // .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectShortName), t => t.SubjectVisit.Subject.ShortName.Contains(inQuery.SubjectShortName))
+ // .WhereIf(inQuery.BeginStudyTime != null, t => t.SCPStudy.StudyTime >= inQuery.BeginStudyTime)
+ // .WhereIf(inQuery.EndStudyTime != null, t => t.SCPStudy.StudyTime <= inQuery.EndStudyTime)
+ // .Select(t => new PatientStudyBeforeConfirmView()
+ // {
+ // SubjectId = t.SubjectVisit.SubjectId,
+ // SubjectAge = t.SubjectVisit.Subject.Age,
+ // SubjectSex = t.SubjectVisit.Subject.Sex,
+ // SubjectShortName = t.SubjectVisit.Subject.ShortName,
+
+
+ // PatientId = t.SCPStudy.PatientId,
+ // PatientAge = t.SCPStudy.PatientAge,
+ // PatientBirthDate = t.SCPStudy.PatientBirthDate,
+ // PatientIdStr = t.SCPStudy.PatientIdStr,
+ // PatientSex = t.SCPStudy.PatientSex,
+
+ // //PatientList = t.SubjectVisit.Subject.SubjectPatientList.Select(t => new PatientBasicInfo()
+ // //{
+ // // PatientId = t.PatientId,
+ // // PatientAge = t.Patient.PatientAge,
+ // // PatientBirthDate = t.Patient.PatientBirthDate,
+ // // PatientIdStr = t.Patient.PatientIdStr,
+ // // PatientSex = t.Patient.PatientSex,
+ // //}).ToList(),
+
+ // SubjectCode = t.SubjectVisit.Subject.Code,
+ // SubmitState = t.SubjectVisit.SubmitState,
+ // SubmitTime = t.SubjectVisit.SubmitTime,
+ // VisitName = t.SubjectVisit.VisitName,
+ // SubjectVisitId = t.SubjectVisitId,
+ // VisitEarliestStudyTime = t.SubjectVisit.SCPStudySubjectVisitList.Min(t => t.SCPStudy.StudyTime),
+ // VisitLatestStudyTime = t.SubjectVisit.SCPStudySubjectVisitList.Max(t => t.SCPStudy.StudyTime),
+
+ // StudyId = t.SCPStudyId,
+ // StudyTime = t.SCPStudy.StudyTime,
+ // CallingAE = t.SCPStudy.CallingAE,
+ // CalledAE = t.SCPStudy.CalledAE
+
+ // });
+ #endregion
+
+ var query = from scpStudy in _studyRepository.Where(t => !t.SCPStudySubjectVisitList.Any(t => t.SubjectVisit.SubmitState == SubmitStateEnum.Submitted && t.TrialId == inQuery.TrialId))
+ .WhereIf(inQuery.IsBindedVisit == false, t => !t.SCPStudySubjectVisitList.Any(t => t.TrialId == inQuery.TrialId))
+ .WhereIf(inQuery.IsBindedVisit == true, t => t.SCPStudySubjectVisitList.Any(t => t.TrialId == inQuery.TrialId))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.VisitName), t => t.SCPStudySubjectVisitList.Any(t => t.TrialId == inQuery.TrialId && t.SubjectVisit.VisitName.Contains(inQuery.VisitName)))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientSex), t => t.Patient.PatientSex.Contains(inQuery.PatientSex))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), u => u.Patient.PatientIdStr.Contains(inQuery.PatientIdStr))
+ .WhereIf(inQuery.BeginStudyTime != null, t => t.StudyTime >= inQuery.BeginStudyTime)
+ .WhereIf(inQuery.EndStudyTime != null, t => t.StudyTime <= inQuery.EndStudyTime)
+ join subjectPatient in _subjectPatientRepository.Where(t => t.Subject.TrialId == inQuery.TrialId)
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectCode), u => u.Subject.Code.Contains(inQuery.SubjectCode))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectSex), u => u.Subject.Sex.Contains(inQuery.SubjectSex))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectShortName), t => t.Subject.ShortName.Contains(inQuery.SubjectShortName))
+ on scpStudy.PatientId equals subjectPatient.PatientId
+ join scpStudySubjectVisit in _studySubjectVisitRepository.Where(t => t.TrialId == inQuery.TrialId)
+ on scpStudy.Id equals scpStudySubjectVisit.SCPStudyId into dd
+ from scpStudySV in dd.DefaultIfEmpty()
+ select new PatientStudyBeforeConfirmView()
+ {
+ SubjectId = subjectPatient.Subject.Id,
+ SubjectAge = subjectPatient.Subject.Age,
+ SubjectSex = subjectPatient.Subject.Sex,
+ SubjectShortName = subjectPatient.Subject.ShortName,
+ SubjectCode = subjectPatient.Subject.Code,
+
+ PatientId = scpStudy.PatientId,
+ PatientName = scpStudy.PatientName,
+ PatientAge = scpStudy.PatientAge,
+ PatientBirthDate = scpStudy.PatientBirthDate,
+ PatientIdStr = scpStudy.PatientIdStr,
+ PatientSex = scpStudy.PatientSex,
+
+ //PatientList = t.SubjectVisit.Subject.SubjectPatientList.Select(t => new PatientBasicInfo()
+ //{
+ // PatientId = t.PatientId,
+ // PatientAge = t.Patient.PatientAge,
+ // PatientBirthDate = t.Patient.PatientBirthDate,
+ // PatientIdStr = t.Patient.PatientIdStr,
+ // PatientSex = t.Patient.PatientSex,
+ //}).ToList(),
+
+
+ SubmitState = scpStudySV.SubjectVisit.SubmitState,
+ SubmitTime = scpStudySV.SubjectVisit.SubmitTime,
+ VisitName = scpStudySV.SubjectVisit.VisitName,
+ VisitNum = scpStudySV.SubjectVisit.VisitNum,
+ SubjectVisitId = scpStudySV.SubjectVisit.Id,
+ VisitEarliestStudyTime = scpStudySV.SubjectVisit.SCPStudySubjectVisitList.Min(t => t.SCPStudy.StudyTime),
+ VisitLatestStudyTime = scpStudySV.SubjectVisit.SCPStudySubjectVisitList.Max(t => t.SCPStudy.StudyTime),
+
+ StudyId = scpStudy.Id,
+ StudyTime = scpStudy.StudyTime,
+ CallingAE = scpStudy.CallingAE,
+ CalledAE = scpStudy.CalledAE,
+ Description = scpStudy.Description,
+ InstanceCount = scpStudy.InstanceCount,
+ Modalities = scpStudy.Modalities,
+ ModalityForEdit = scpStudy.ModalityForEdit,
+ SeriesCount = scpStudy.SeriesCount
+
+ };
+
+ var defalutSortArray = new string[] { nameof(PatientStudyBeforeConfirmView.SubjectCode), nameof(PatientStudyBeforeConfirmView.VisitNum), nameof(PatientStudyBeforeConfirmView.StudyTime) };
+ var pageList = await query.ToPagedListAsync(inQuery, defalutSortArray);
+
+
+
+ return ResponseOutput.Ok(pageList);
}
-
- public async Task> VerifyPacsImage(VerifyPacsImageCommand inCommand)
+ ///
+ ///检查管理-> 检查列表 (同步影像数据之后的 带患者信息 患者信息是数组)
+ ///
+ ///
+ ///
+ [HttpPost]
+ public async Task>> GetTrialPatientStudyList(TrialPatientStudyQuery inQuery, [FromServices] IRepository _repository)
{
- var trialId = inCommand.TrialId;
-
- var subjectId = inCommand.SubjectId;
-
- var isVerifyVisitImageDate = await _trialRepository.Where(t => t.Id == inCommand.TrialId).Select(t => t.IsVerifyVisitImageDate).FirstNotNullAsync();
-
- var result = new List();
-
- var visitList = _subjectVisitRepository.Where(t => t.SubjectId == inCommand.SubjectId).Select(t => new { t.VisitNum, t.EarliestScanDate, t.LatestScanDate, t.Id }).ToList();
-
- var currentVisitNum = visitList.First(t => t.Id == inCommand.SubjectVisitId).VisitNum;
-
- var scpStudyList = _scpStudyRepository.Where(t => inCommand.SCPStudyIdList.Contains(t.Id)).Select(t => new { StudyDate = t.StudyTime, t.Id }).ToList();
-
- foreach (var waitUploadItem in scpStudyList)
- {
-
- if (isVerifyVisitImageDate)
- {
- //小于当前访视 最近的最晚拍片
- var before = visitList.Where(u => u.VisitNum < currentVisitNum).Max(k => k.LatestScanDate);
-
- if (before != null && waitUploadItem.StudyDate != null && before > waitUploadItem.StudyDate)
- {
-
- // $"当前访视检查时间{waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")}不能早于前序访视检查时间{before?.ToString("yyyy-MM-dd")},请核对检查数据是否有误",
- result.Add(new VerifySCPStudyUploadResult() { SCPStudyId = waitUploadItem.Id, ErrorMesseage = _localizer["Study_VisitBeforePrevError", waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")!, before?.ToString("yyyy-MM-dd")!] });
- continue; // 跳过当前迭代
- }
-
- //大于当前访视 最近的最早拍片日期
- var after = visitList.Where(u => u.VisitNum > currentVisitNum).Min(k => k.EarliestScanDate);
-
- if (after != null && waitUploadItem.StudyDate != null && after < waitUploadItem.StudyDate)
- {
- // $"当前访视检查时间{waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")}不能晚于该访视之后的检查时间{after?.ToString("yyyy-MM-dd")},请核对检查数据是否有误"
- result.Add(new VerifySCPStudyUploadResult() { SCPStudyId = waitUploadItem.Id, ErrorMesseage = _localizer["Study_VisitAfterSubseqError", waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")!, after?.ToString("yyyy-MM-dd")!] });
- continue; // 跳过当前迭代
- }
- }
-
- var verifyStudyInfo = _dicomStudyRepository.Where(t => t.TrialId == trialId && t.Id == waitUploadItem.Id).ProjectTo(_mapper.ConfigurationProvider).FirstOrDefault();
-
- var currentStudyResult = new VerifySCPStudyUploadResult() { SCPStudyId = waitUploadItem.Id };
+ var query = _repository.Where(t => t.SubjectVisit.TrialId == inQuery.TrialId)
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectCode), u => u.SubjectVisit.Subject.Code.Contains(inQuery.SubjectCode))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), u => u.PatientIdStr.Contains(inQuery.PatientIdStr))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientSex), t => t.PatientSex.Contains(inQuery.PatientSex))
+ .WhereIf(inQuery.SubjectAge != null, t => t.SubjectVisit.Subject.Age == inQuery.SubjectAge)
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectCode), u => u.SubjectVisit.Subject.Code.Contains(inQuery.SubjectCode))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectSex), u => u.SubjectVisit.Subject.Sex.Contains(inQuery.SubjectSex))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectShortName), t => t.SubjectVisit.Subject.ShortName.Contains(inQuery.SubjectShortName))
+ .WhereIf(inQuery.BeginStudyTime != null, t => t.StudyTime >= inQuery.BeginStudyTime)
+ .WhereIf(inQuery.EndStudyTime != null, t => t.StudyTime <= inQuery.EndStudyTime)
+ .Select(t => new PatientStudyView()
+ {
+ SubjectId = t.SubjectVisit.SubjectId,
+ SubjectAge = t.Subject.Age,
+ SubjectSex = t.Subject.Sex,
+ SubjectShortName = t.Subject.ShortName,
- //数据库不存在该检查 允许上传
- if (verifyStudyInfo == null)
- {
- currentStudyResult.AllowUpload = true;
- }
- //数据库该项目有该检查 看是否支持重传
- else
- {
- //是同一个受试者 支持重传
- if (verifyStudyInfo.SubjectId == subjectId && verifyStudyInfo.SubjectVisitId == inCommand.SubjectVisitId)
- {
- currentStudyResult.AllowReUpload = true;
- }
- //不是同一个受试者
- else
- {
- //有默认值,其实不用写,这里为了好理解
- currentStudyResult.AllowUpload = false;
+ //PatientId = Guid.Empty,
+ PatientAge = t.PatientAge,
+ PatientName = t.PatientName,
+ PatientBirthDate = t.PatientBirthDate,
+ PatientIdStr = t.PatientIdStr,
+ PatientSex = t.PatientSex,
- currentStudyResult.AllowReUpload = false;
+ //PatientList = t.Subject.SubjectPatientList.Select(t => new PatientBasicInfo()
+ //{
+ // PatientId = t.PatientId,
+ // PatientAge = t.Patient.PatientAge,
+ // PatientBirthDate = t.Patient.PatientBirthDate,
+ // PatientIdStr = t.Patient.PatientIdStr,
+ // PatientSex = t.Patient.PatientSex,
+ //}).ToList(),
- //$"此处不可以上传。当前影像检查已经上传给受试者{verifyStudyInfo.SubjectCode}的{verifyStudyInfo.VisitName}"
- currentStudyResult.ErrorMesseage = _localizer["Study_ImgAlreadyUploaded", verifyStudyInfo.SubjectCode, verifyStudyInfo.VisitName];
- }
- }
+ Modalities = t.Modalities,
+ ModalityForEdit = t.ModalityForEdit,
+ SubjectCode = t.SubjectVisit.Subject.Code,
+ SubmitState = t.SubjectVisit.SubmitState,
+ SubmitTime = t.SubjectVisit.SubmitTime,
+ VisitName = t.SubjectVisit.VisitName,
+ VisitNum = t.SubjectVisit.VisitNum,
+ SubjectVisitId = t.SubjectVisitId,
+ VisitEarliestStudyTime = t.SubjectVisit.StudyList.Min(t => t.StudyTime),
+ VisitLatestStudyTime = t.SubjectVisit.StudyList.Max(t => t.StudyTime),
- result.Add(currentStudyResult);
- }
-
-
- return result;
+ StudyId = t.Id,
+ StudyTime = t.StudyTime,
+ Description = t.Description,
+ SeriesCount = t.SeriesCount,
+ InstanceCount = t.InstanceCount,
+ });
+
+ var defalutSortArray = new string[] { nameof(PatientStudyView.SubjectCode), nameof(PatientStudyView.VisitNum), nameof(PatientStudyView.StudyTime) };
+
+ var pageList = await query.ToPagedListAsync(inQuery, defalutSortArray);
+ return ResponseOutput.Ok(pageList);
}
///
- /// 提交 患者检查和访视的绑定
+ /// 获取该项目 患者已绑定subject ,新来了的检查 可能需要新建访视 但是新增的检查未绑定访视的检查列表
///
- ///
- ///
- ///
- ///
+ ///
///
[HttpPost]
- [UnitOfWork]
- [TrialGlobalLimit( "AfterStopCannNotOpt" )]
- public async Task SubmitVisitStudyBinding(SubmitVisitStudyBindingCommand inCommand,
- [FromServices] IRepository _dicomstudyRepository,
+ public async Task>> GetTrialUnbindSubjectVisitStudyList(TrialPatientStudyQuery inQuery)
+ {
+ //属于该项目的已绑定患者的检查,同时没有绑定任何访视
+ var query = from scpStudy in _studyRepository.Where(t => !t.SCPStudySubjectVisitList.Any(t => t.TrialId == inQuery.TrialId))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientSex), t => t.Patient.PatientSex.Contains(inQuery.PatientSex))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), u => u.Patient.PatientIdStr.Contains(inQuery.PatientIdStr))
+ .WhereIf(inQuery.BeginStudyTime != null, t => t.StudyTime >= inQuery.BeginStudyTime)
+ .WhereIf(inQuery.EndStudyTime != null, t => t.StudyTime <= inQuery.EndStudyTime)
+ join subjectPatient in _subjectPatientRepository.Where(t => t.Subject.TrialId == inQuery.TrialId)
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectCode), u => u.Subject.Code.Contains(inQuery.SubjectCode))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectSex), u => u.Subject.Sex.Contains(inQuery.SubjectSex))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectShortName), t => t.Subject.ShortName.Contains(inQuery.SubjectShortName))
+ on scpStudy.PatientId equals subjectPatient.PatientId
+ join scpStudySubjectVisit in _studySubjectVisitRepository.AsQueryable() on scpStudy.Id equals scpStudySubjectVisit.SCPStudyId
+ into dd
+ from scpStudySV in dd.DefaultIfEmpty()
+ select new UnbindStudyView()
+ {
+ PatientIdStr = scpStudy.PatientIdStr,
+ PatientBirthDate = scpStudy.PatientBirthDate,
+ PatientAge = scpStudy.PatientAge,
+ PatientName = scpStudy.PatientName,
+ PatientSex = scpStudy.PatientSex,
+ Description = scpStudy.Description,
+ CalledAE = scpStudy.CalledAE,
+ InstanceCount = scpStudy.InstanceCount,
+ Modalities = scpStudy.Modalities,
+ PatientId = scpStudy.PatientId,
+ SCPStudyId = scpStudy.Id,
+ SeriesCount = scpStudy.SeriesCount,
+ StudyTime = scpStudy.StudyTime,
+
+ SubjectVisitId = scpStudySV.SubjectVisitId,
+ VisitName = scpStudySV.SubjectVisit.VisitName,
+
+ SubjectId = subjectPatient.SubjectId,
+ SubjectCode = subjectPatient.Subject.Code,
+ TrialId = subjectPatient.Subject.TrialId,
+ SubjectAge = subjectPatient.Subject.Age,
+ SubjectSex = subjectPatient.Subject.Sex,
+ SubjectShortName = subjectPatient.Subject.ShortName,
+ SubjectBirthDate = subjectPatient.Subject.BirthDate
+ };
+
+ #region 废弃
+ //var query = from subject in _subjectRepository.Where(t => t.TrialId == inQuery.TrialId)
+ // .WhereIf(inQuery.SubjectAge != null, t => t.Age == inQuery.SubjectAge)
+ // .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectCode), u => u.Code.Contains(inQuery.SubjectCode))
+ // .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectSex), u => u.Sex.Contains(inQuery.SubjectSex))
+ // .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectShortName), t => t.ShortName.Contains(inQuery.SubjectShortName))
+ // join subjectPatient in _subjectPatientRepository.AsQueryable() on subject.Id equals subjectPatient.PatientId
+ // //没有绑定任何访视
+ // join scpStudy in _studyRepository.AsQueryable()
+ // .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientSex), t => t.Patient.PatientSex.Contains(inQuery.PatientSex))
+ // .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), u => u.Patient.PatientIdStr.Contains(inQuery.PatientIdStr))
+ // .WhereIf(inQuery.BeginStudyTime != null, t => t.StudyTime >= inQuery.BeginStudyTime)
+ // .WhereIf(inQuery.EndStudyTime != null, t => t.StudyTime <= inQuery.EndStudyTime)
+ // on subjectPatient.PatientId equals scpStudy.PatientId
+ // select new SubjectPatientStudyView()
+ // {
+ // SubjectId = subject.Id,
+ // SubjectAge = subject.Age,
+ // SubjectSex = subject.Sex,
+ // SubjectShortName = subject.ShortName,
+
+ // PatientList = subject.SubjectPatientList.Select(t => new PatientBasicInfo()
+ // {
+ // PatientId = t.PatientId,
+ // PatientAge = t.Patient.PatientAge,
+ // PatientBirthDate = t.Patient.PatientBirthDate,
+ // PatientIdStr = t.Patient.PatientIdStr,
+ // PatientSex = t.Patient.PatientSex,
+ // }).ToList(),
+
+ // SubjectCode = subject.Code,
+
+ // SeriesCount = scpStudy.SeriesCount,
+ // CalledAE = scpStudy.CalledAE,
+ // InstanceCount = scpStudy.InstanceCount,
+ // Description = scpStudy.Description,
+ // Modalities = scpStudy.Modalities,
+ // PatientId = scpStudy.PatientId,
+
+ // SCPStudyId = scpStudy.Id,
+ // StudyTime = scpStudy.StudyTime
+
+ // };
+ #endregion
+
+
+
+
+
+
+ var pageList = await query.ToPagedListAsync(inQuery, nameof(UnbindStudyView.StudyTime));
+
+
+ return ResponseOutput.Ok(pageList);
+ }
+
+ ///
+ /// 删除某个项目 未提交的访视检查绑定, 清理数据,方便测试自动绑定
+ ///
+ ///
+ ///
+ [HttpDelete]
+ public async Task DeleteUnSubmittedStudyBind(Guid trialId, Guid? subjectId,
+ [FromServices] IRepository _visitTaskRepository,
+ [FromServices] IRepository _dicomStudyRepository,
[FromServices] IRepository _dicomSeriesRepository,
[FromServices] IRepository _dicomInstanceRepository)
{
-
- //这里要做校验 + 同时验证本地系统里面的影像是否存在pacs推过来的
-
- var copyCommand = inCommand.Clone();
- copyCommand.SCPStudyIdList = inCommand.SCPStudyIdList.Union(inCommand.ReUploadSCPStudyIdList).ToList();
- var verifyResult = await VerifyPacsImage(copyCommand);
-
- var allowUploadList = verifyResult.Where(u => u.AllowUpload == true).Select(t => t.SCPStudyId).ToList();
- var allowReUploadList = verifyResult.Where(u => u.AllowReUpload == true).Select(t => t.SCPStudyId).ToList();
-
- if (!(inCommand.SCPStudyIdList.All(t => allowUploadList.Contains(t)) && inCommand.ReUploadSCPStudyIdList.All(t => allowReUploadList.Contains(t))))
+ if (subjectId != null)
{
- throw new BusinessValidationFailedException("对接提示: 前端提交的检查有不能上传的,请刷新页面调用验证接口重试!");
- }
+ await _studySubjectVisitRepository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId && t.SubjectId == subjectId);
- var subjectId = inCommand.SubjectId;
- var subjectVisitId = inCommand.SubjectVisitId;
- var trialId = inCommand.TrialId;
+ await _subjectVisitRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId);
- var @lock = _distributedLockProvider.CreateLock($"StudyCode");
-
- using (await @lock.AcquireAsync())
- {
- var dbStudyCodeIntMax = _dicomStudyRepository.Where(s => s.TrialId == inCommand.TrialId).Select(t => t.Code).DefaultIfEmpty().Max();
-
- int currentNextCodeInt = dbStudyCodeIntMax + 1;
-
- //新增的,上传的
- foreach (var scpStudyId in inCommand.SCPStudyIdList)
- {
-
- var find = _scpStudyRepository.Where(t => t.Id == scpStudyId).Select(t => new { SCPStudy = t, t.SeriesList, t.InstanceList }).FirstOrDefault();
-
- if (find != null)
- {
- var newStuty = _mapper.Map(find.SCPStudy);
-
- await _dicomStudyRepository.AddAsync(newStuty);
-
- newStuty.SeqId = Guid.Empty;
- newStuty.Code = currentNextCodeInt;
- newStuty.StudyCode = AppSettings.GetCodeStr(currentNextCodeInt, nameof(DicomStudy));
- newStuty.IsFromPACS = true;
- newStuty.TrialId = trialId;
- newStuty.SubjectId = subjectId;
- newStuty.SubjectVisitId = subjectVisitId;
-
- var newSeriesList = _mapper.Map>(find.SeriesList);
-
- foreach (var series in newSeriesList)
- {
-
- series.SeqId = Guid.Empty;
- series.TrialId = trialId;
- series.SubjectId = subjectId;
- series.SubjectVisitId = subjectVisitId;
- }
-
- await _dicomSeriesRepository.AddRangeAsync(newSeriesList);
-
- var newInstanceList = _mapper.Map>(find.InstanceList);
-
- foreach (var instance in newInstanceList)
- {
- instance.SeqId = Guid.Empty;
- instance.TrialId = trialId;
- instance.SubjectId = subjectId;
- instance.SubjectVisitId = subjectVisitId;
-
- }
- await _dicomInstanceRepository.AddRangeAsync(newInstanceList);
- }
-
- currentNextCodeInt++;
-
- await _scpPatientRepository.BatchUpdateNoTrackingAsync(t => t.Id == find.SCPStudy.PatientId, u => new SCPPatient() { SubjectId = subjectId });
- await _scpStudyRepository.BatchUpdateNoTrackingAsync(t => t.Id == scpStudyId, u => new SCPStudy() { SubjectVisitId = subjectVisitId });
-
-
- }
-
- foreach (var scpStudyId in inCommand.ReUploadSCPStudyIdList)
- {
-
- var study = await _dicomstudyRepository.FirstOrDefaultAsync(t => t.Id == scpStudyId);
-
- var instanceIdList = _dicomInstanceRepository.Where(t => t.Id == scpStudyId).Select(t => t.Id).ToList();
-
- var scpStudy = _scpStudyRepository.Where(t => t.Id == scpStudyId).Include(t => t.SeriesList).ThenInclude(t => t.SCPInstanceList).FirstOrDefault();
-
- //以最后一次为准
- study.IsFromPACS = true;
- //特殊处理逻辑
- study.Modalities = string.Join("、", scpStudy.SeriesList.Select(t => t.Modality).Union(study.Modalities.Split("、", StringSplitOptions.RemoveEmptyEntries)).Distinct());
-
- SpecialArchiveStudyDeal(study);
-
-
- // 少了整个序列
-
- //某个序列下少了instance
- foreach (var seriesItem in scpStudy.SeriesList)
- {
- var seriesId = IdentifierHelper.CreateGuid(seriesItem.StudyInstanceUid, seriesItem.SeriesInstanceUid, trialId.ToString());
-
- DicomSeries dicomSeries = await _dicomSeriesRepository.FirstOrDefaultAsync(t => t.Id == seriesId);
-
- //判断重复
- if (dicomSeries == null)
- {
- var series = _mapper.Map(seriesItem);
-
- series.SeqId = Guid.Empty;
- series.TrialId = trialId;
- series.SubjectId = subjectId;
- series.SubjectVisitId = subjectVisitId;
-
-
- dicomSeries = await _dicomSeriesRepository.AddAsync(series);
-
-
-
- foreach (var instanceItem in seriesItem.SCPInstanceList)
- {
- var instance = _mapper.Map(instanceItem);
-
- instance.SeqId = Guid.Empty;
- instance.TrialId = trialId;
- instance.SubjectId = subjectId;
- instance.SubjectVisitId = subjectVisitId;
-
- await _dicomInstanceRepository.AddAsync(instance);
- }
-
- //新的序列 那么 检查的序列数量+1
- study.SeriesCount += 1;
-
- study.InstanceCount += seriesItem.SCPInstanceList.Count;
- }
- else
- {
- //该序列掉了instance
- dicomSeries.InstanceCount += seriesItem.SCPInstanceList.Count;
-
- var newInstanceList = seriesItem.SCPInstanceList.Where(t => !instanceIdList.Contains(t.Id));
-
- foreach (var instanceItem in newInstanceList)
- {
- var instance = _mapper.Map(instanceItem);
-
- instance.SeqId = Guid.Empty;
- instance.TrialId = trialId;
- instance.SubjectId = subjectId;
- instance.SubjectVisitId = subjectVisitId;
-
- await _dicomInstanceRepository.AddAsync(instance);
- }
-
- study.InstanceCount += newInstanceList.Count();
-
- }
- }
-
- await _scpPatientRepository.BatchUpdateNoTrackingAsync(t => t.Id == scpStudy.PatientId, u => new SCPPatient() { SubjectId = subjectId });
- await _scpStudyRepository.BatchUpdateNoTrackingAsync(t => t.Id == scpStudyId, u => new SCPStudy() { SubjectVisitId = subjectVisitId });
- }
+ await _visitTaskRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId);
+ await _dicomStudyRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId);
+ await _dicomSeriesRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId);
+ await _dicomInstanceRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId);
}
+ else
+ {
+ await _studySubjectVisitRepository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId && t.SubjectVisit.SubmitState != SubmitStateEnum.Submitted);
-
-
- await _scpStudyRepository.SaveChangesAsync();
+ }
return ResponseOutput.Ok();
}
- private void SpecialArchiveStudyDeal(DicomStudy study)
+ ///
+ /// 阅片管理-> 任务列表
+ ///
+ ///
+ ///
+ [HttpPost]
+ public async Task>> GetPatientVisitTaskList([FromServices] IRepository _visitTaskRepository, PatientVisitTaskQuery inQuery)
{
- #region 特殊逻辑
+ var visitTaskQueryable = _visitTaskRepository.Where(t => t.TrialId == inQuery.TrialId && t.IsAnalysisCreate == false)
+ .WhereIf(inQuery.ReadingCategory != null, t => t.ReadingCategory == inQuery.ReadingCategory)
+ .WhereIf(inQuery.ReadingCategory == null, t => t.ReadingCategory != ReadingCategory.Judge)
+ .WhereIf(inQuery.ReadingTaskState != null, t => t.ReadingTaskState == inQuery.ReadingTaskState)
+ .WhereIf(inQuery.TaskState != null, t => t.TaskState == inQuery.TaskState)
+ .WhereIf(inQuery.SubjectId != null, t => t.SubjectId == inQuery.SubjectId)
+ .WhereIf(inQuery.DoctorUserId != null, t => t.DoctorUserId == inQuery.DoctorUserId)
+ .WhereIf(inQuery.TrialReadingCriterionId != null, t => t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId)
- if (study.PatientBirthDate.Length == 8)
- {
- study.PatientBirthDate = $"{study.PatientBirthDate[0]}{study.PatientBirthDate[1]}{study.PatientBirthDate[2]}{study.PatientBirthDate[3]}-{study.PatientBirthDate[4]}{study.PatientBirthDate[5]}-{study.PatientBirthDate[6]}{study.PatientBirthDate[7]}";
- }
+ .WhereIf(!string.IsNullOrEmpty(inQuery.TaskName), t => t.TaskName.Contains(inQuery.TaskName) || t.TaskBlindName.Contains(inQuery.TaskName))
+ .WhereIf(inQuery.BeginSignTime != null, t => t.SignTime >= inQuery.BeginSignTime)
+ .WhereIf(inQuery.EndSignTime != null, t => t.SignTime <= inQuery.EndSignTime)
- var dicModalityList = _dictionaryRepository.Where(t => t.Code == "Modality").SelectMany(t => t.ChildList.Select(c => c.Value)).ToList();
+ .WhereIf(inQuery.BeginTaskCreateTime != null, t => t.CreateTime >= inQuery.BeginTaskCreateTime)
+ .WhereIf(inQuery.EndTaskCreateTime != null, t => t.CreateTime <= inQuery.EndTaskCreateTime)
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), t => t.Subject.SubjectPatientList.Any(t => t.Patient.PatientIdStr.Contains(inQuery.PatientIdStr)))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientName), t => t.Subject.SubjectPatientList.Any(t => t.Patient.PatientName.Contains(inQuery.PatientName)))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientSex), t => t.Subject.SubjectPatientList.Any(t => t.Patient.PatientSex.Contains(inQuery.PatientSex)))
+ .WhereIf(!string.IsNullOrEmpty(inQuery.SubjectShortName), t => t.Subject.ShortName.Contains(inQuery.SubjectShortName))
+ .WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => (t.Subject.Code.Contains(inQuery.SubjectCode) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(inQuery.SubjectCode) && t.IsAnalysisCreate))
+ .ProjectTo(_mapper.ConfigurationProvider);
- var modality = study.Modalities;
+ var defalutSortArray = new string[] { nameof(PatientVisitTaskDTO.SubjectId), nameof(PatientVisitTaskDTO.VisitTaskNum) };
- var modalityForEdit = dicModalityList.Contains(modality) ? modality : String.Empty;
+ var pageList = await visitTaskQueryable.ToPagedListAsync(inQuery, defalutSortArray);
- if (modality == "MR")
- {
- modalityForEdit = "MRI";
- }
-
- if (modality == "PT")
- {
- modalityForEdit = "PET";
- }
- if (modality == "PT、CT")
- {
- modalityForEdit = "PET-CT";
- }
-
- study.ModalityForEdit = modalityForEdit;
- #endregion
+ return ResponseOutput.Ok(pageList);
}
#endregion
+ ///
+ /// 打包和匿名化影像 默认是匿名化打包,也可以不匿名化打包
+ ///
+ ///
+ ///
+ ///
+ ///
+
+ public async Task RequestPackageAndAnonymizImage(Guid trialId, Guid subjectVisitId, [FromServices] IOSSService _oSSService, bool isAnonymize = true)
+ {
+ var subjectVisit = await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId);
+
+ if (subjectVisit.PackState == PackState.WaitPack)
+ {
+ HangfireJobHelper.NotImmediatelyOnceOnlyJob(t => t.RequestPackageAndAnonymizImage(trialId, subjectVisitId, isAnonymize), TimeSpan.FromSeconds(1));
+
+ subjectVisit.PackState = PackState.Packing;
+
+ await _subjectVisitRepository.SaveChangesAsync();
+
+ }
+
+ var zipPath = subjectVisit.VisitImageZipPath;
+
+ if (!string.IsNullOrEmpty(zipPath))
+ {
+ //记录下载的记录
+
+ await _subejctVisitDownloadRepository.AddAsync(new SubejctVisitDownload() { IP = _userInfo.IP, SubjectVisitId = subjectVisitId }, true);
+ }
+
+ return ResponseOutput.Ok(zipPath);
+
+ }
+
+ ///
+ /// 访视影像下载记录表
+ ///
+ ///
+ [HttpPost]
+ public async Task>> GetTrialSubjectVisitDownloadList(VisitImageDownloadQuery inQuery)
+ {
+ var query = _subejctVisitDownloadRepository.Where(t => t.SubjectVisit.TrialId == inQuery.TrialId)
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.IP), t => t.IP.Contains(inQuery.IP))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectCode), t => t.SubjectVisit.Subject.Code.Contains(inQuery.SubjectCode))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.VisitName), t => t.SubjectVisit.VisitName.Contains(inQuery.VisitName))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.Name), t => t.CreateUser.UserName.Contains(inQuery.Name) || t.CreateUser.FullName.Contains(inQuery.Name))
+ .WhereIf(inQuery.UserTypeEnum != null, t => t.CreateUser.UserTypeRole.UserTypeEnum == inQuery.UserTypeEnum)
+ .WhereIf(inQuery.BeginDownloadTime != null, t => t.CreateTime >= inQuery.BeginDownloadTime)
+ .WhereIf(inQuery.EndDownloadTime != null, t => t.CreateTime <= inQuery.EndDownloadTime)
+
+ .ProjectTo(_mapper.ConfigurationProvider);
+ var pageList = await query.ToPagedListAsync(inQuery, nameof(VisitImageDownloadQuery.SubjectCode));
+ return ResponseOutput.Ok(pageList);
+ }
+ ///
+ /// scp 影像推送记录表
+ ///
+ ///
+ ///
+ [HttpPost]
+ public async Task>> GetSCPImageUploadList(SCPImageUploadQuery inQuery)
+ {
+ var query = _SCPImageUploadRepository.Where()
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.CalledAE), t => t.CalledAE.Contains(inQuery.CalledAE))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.CallingAEIP), t => t.CallingAEIP.Contains(inQuery.CallingAEIP))
+ .WhereIf(!string.IsNullOrWhiteSpace(inQuery.CallingAE), t => t.CallingAE.Contains(inQuery.CallingAE))
+ .WhereIf(inQuery.StartTime != null, t => t.StartTime >= inQuery.StartTime)
+ .WhereIf(inQuery.EndTime != null, t => t.EndTime <= inQuery.EndTime)
+
+ .ProjectTo(_mapper.ConfigurationProvider);
+ var pageList = await query.ToPagedListAsync(inQuery, nameof(SCPImageUploadView.CallingAE));
+ return ResponseOutput.Ok(pageList);
+ }
@@ -617,5 +2798,191 @@ namespace IRaCIS.Core.Application.Service
}
+ public interface IDownloadAndUploadService
+ {
+ Task RequestPackageAndAnonymizImage(Guid trialId, Guid subjectVisitId, bool isAnonymize = true);
+ }
+ [ApiExplorerSettings(GroupName = "Trial")]
+ public class DownloadAndUploadService : BaseService, IDownloadAndUploadService
+ {
+ private readonly IRepository _systemAnonymizationRepository;
+ private readonly IRepository _subjectVisitRepository;
+ private readonly IOSSService _oSSService;
+ public DownloadAndUploadService(IRepository systemAnonymizationRepository, IRepository subjectVisitRepository, IOSSService oSSService)
+ {
+ _systemAnonymizationRepository = systemAnonymizationRepository;
+
+ _subjectVisitRepository = subjectVisitRepository;
+
+ _oSSService = oSSService;
+ }
+
+
+ public async Task RequestPackageAndAnonymizImage(Guid trialId, Guid subjectVisitId, bool isAnonymize = true)
+ {
+
+ var subjectVisit = await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId);
+
+ try
+ {
+ var addOrUpdateFixedFieldList = new List();
+
+ var ircFieldList = new List();
+
+ if (isAnonymize)
+ {
+ var systemAnonymizationList = _systemAnonymizationRepository.Where(t => t.IsEnable).ToList();
+
+ addOrUpdateFixedFieldList = systemAnonymizationList.Where(t => t.IsFixed).ToList();
+
+ ircFieldList = systemAnonymizationList.Where(t => t.IsFixed == false).ToList();
+ }
+
+ var subjectAndVisitInfo = _subjectVisitRepository.Where(t => t.Id == subjectVisitId).Select(t => new { SubjectCode = t.Subject.Code, t.Trial.TrialCode, t.VisitNum }).FirstOrDefault();
+
+ var query = from sv in _subjectVisitRepository.Where(t => t.Id == subjectVisitId)
+
+ select new
+ {
+ SubjectCode = sv.Subject.Code,
+ VisitName = sv.VisitName,
+ StudyList = sv.StudyList.Select(u => new
+ {
+ u.PatientIdStr,
+ u.StudyTime,
+ u.StudyCode,
+
+ SeriesList = u.SeriesList.Select(z => new
+ {
+ z.Modality,
+
+ InstancePathList = z.DicomInstanceList.Select(k => new
+ {
+ k.Path
+ })
+ })
+
+ })
+ };
+
+ var info = query.FirstOrDefault();
+
+ if (info != null)
+ {
+ // 创建一个临时文件夹来存放文件
+ string tempFolderPath = Path.Combine(Directory.GetCurrentDirectory(), $"DownloadTemp_{NewId.NextGuid()}");
+ Directory.CreateDirectory(tempFolderPath);
+
+ // 遍历查询结果
+ foreach (var studyInfo in info.StudyList)
+ {
+ // 遍历 Series
+ foreach (var seriesInfo in studyInfo.SeriesList)
+ {
+ string studyFolderPath = Path.Combine(tempFolderPath, $"{info.SubjectCode}_{info.VisitName}", $"{studyInfo.StudyCode}_{studyInfo.StudyTime?.ToString("yyyy-MM-dd")}_{seriesInfo.Modality}");
+
+ // 创建 影像 文件夹
+ Directory.CreateDirectory(studyFolderPath);
+
+ // 遍历 InstancePathList
+ foreach (var instanceInfo in seriesInfo.InstancePathList)
+ {
+ // 复制文件到相应的文件夹
+ string destinationPath = Path.Combine(studyFolderPath, Path.GetFileName(instanceInfo.Path));
+
+ //下载到当前目录
+ await _oSSService.DownLoadFromOSSAsync(instanceInfo.Path, destinationPath);
+
+ #region 匿名化逻辑
+
+
+ if (isAnonymize)
+ {
+ DicomFile dicomFile = await DicomFile.OpenAsync(destinationPath, Encoding.Default);
+
+ DicomDataset dataset = dicomFile.Dataset;
+
+ foreach (var item in addOrUpdateFixedFieldList)
+ {
+
+ var dicomTag = new DicomTag(Convert.ToUInt16(item.Group, 16), Convert.ToUInt16(item.Element, 16));
+
+ dataset.AddOrUpdate(dicomTag, item.ReplaceValue);
+ }
+
+ foreach (var item in ircFieldList)
+ {
+
+ var dicomTag = new DicomTag(Convert.ToUInt16(item.Group, 16), Convert.ToUInt16(item.Element, 16));
+
+ if (dicomTag == DicomTag.ClinicalTrialProtocolID)
+ {
+ dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.TrialCode);
+
+ }
+ if (dicomTag == DicomTag.ClinicalTrialSiteID)
+ {
+ //dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.TrialSiteCode);
+
+ }
+ 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
+ }
+ }
+ }
+
+ var zipPath = Path.Combine(Directory.GetCurrentDirectory(), $"{info.SubjectCode}_{info.VisitName}_ImageStudy.zip");
+
+ ZipFile.CreateFromDirectory(tempFolderPath, zipPath);
+
+ //上传到Oss
+ var relativePath = await _oSSService.UploadToOSSAsync(zipPath, $"download_zip/{subjectVisitId}", false);
+
+
+ //subjectVisit.PackState = PackState.Packed;
+ //subjectVisit.VisitImageZipPath = relativePath;
+ //await _subjectVisitRepository.SaveChangesAsync();
+
+ var zipSize = File.OpenRead(zipPath).Length;
+ var fileCount = info.StudyList.SelectMany(t => t.SeriesList).SelectMany(t => t.InstancePathList).Count();
+ await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.Id == subjectVisitId, u => new SubjectVisit() { PackState = PackState.Packed, VisitImageZipPath = relativePath, VisitImageFileCount = fileCount, VisitImageZipSize = zipSize });
+
+
+ //清理文件夹
+ Directory.Delete(tempFolderPath, true);
+ File.Delete(zipPath);
+
+ }
+ }
+ catch (Exception ex)
+ {
+ await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.Id == subjectVisitId, u => new SubjectVisit() { PackState = PackState.WaitPack });
+
+ }
+
+
+
+
+
+ }
+
+ }
}
diff --git a/IRaCIS.Core.Application/Service/Visit/_MapConfig.cs b/IRaCIS.Core.Application/Service/Visit/_MapConfig.cs
index cf927ee17..05a50ef5d 100644
--- a/IRaCIS.Core.Application/Service/Visit/_MapConfig.cs
+++ b/IRaCIS.Core.Application/Service/Visit/_MapConfig.cs
@@ -1,7 +1,7 @@
using AutoMapper;
using IRaCIS.Application.Contracts;
using IRaCIS.Core.Application.Contracts;
-using IRaCIS.Core.Application.Contracts.Dicom.DTO;
+using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Share;
namespace IRaCIS.Core.Application.Service
@@ -22,8 +22,20 @@ namespace IRaCIS.Core.Application.Service
.ForMember(d => d.VisitStageId, t => t.MapFrom(u => u.Id));
+ CreateMap()
+ .ForMember(d => d.SubjectCode, u => u.MapFrom(s => s.SubjectVisit.Subject.Code))
+ .ForMember(d => d.VisitName, u => u.MapFrom(s => s.SubjectVisit.VisitName))
+ .ForMember(d => d.VisitImageFileCount, u => u.MapFrom(s => s.SubjectVisit.VisitImageFileCount))
+ .ForMember(d => d.VisitImageZipPath, u => u.MapFrom(s => s.SubjectVisit.VisitImageZipPath))
+ .ForMember(d => d.VisitImageZipSize, u => u.MapFrom(s => s.SubjectVisit.VisitImageZipSize))
+ .ForMember(d => d.DownloadTime, u => u.MapFrom(s => s.CreateTime))
+ .ForMember(d => d.DownloadUserName, u => u.MapFrom(s => s.CreateUser.UserName))
+ .ForMember(d => d.StudyCount, u => u.MapFrom(s => s.SubjectVisit.StudyList.Count()))
+ .ForMember(d => d.DownLoadUserFullName, u => u.MapFrom(s => s.CreateUser.FullName))
+ .ForMember(d => d.UserTypeEnum, u => u.MapFrom(s => s.CreateUser.UserTypeEnum));
-
+ CreateMap();
+
CreateMap()
.ForMember(d => d.CreateUser, u => u.MapFrom(g => g.CreateUser.LastName + " / " + g.CreateUser.FirstName));
@@ -66,7 +78,6 @@ namespace IRaCIS.Core.Application.Service
.ForMember(d => d.MissingSubmmitCount, u => u.MapFrom(s => s.SubjectVisitList.Count(t => t.VisitNum < s.LatestSubjectVisit.VisitNum && t.SubmitState != SubmitStateEnum.Submitted && t.IsLostVisit == false)))
- .ForMember(d => d.IsMissingImages, u => u.MapFrom(s => s.SubjectVisitList.Any(t => t.VisitNum < s.LatestSubjectVisit.VisitNum && t.SubmitState != SubmitStateEnum.Submitted && t.IsLostVisit == false)))
.ForMember(d => d.InPlanVisitSubmmitCount, u => u.MapFrom(s => s.SubjectVisitList.Count(t => t.SubmitState == SubmitStateEnum.Submitted && t.InPlan == true)))
.ForMember(d => d.LostVisitCount, u => u.MapFrom(s => s.SubjectVisitList.Count(t => t.IsLostVisit)))
.ForMember(d => d.InPlanVisitSubmmitCount, u => u.MapFrom(s => s.SubjectVisitList.Count(t => t.SubmitState == SubmitStateEnum.Submitted && t.InPlan == true)))
@@ -77,8 +88,6 @@ namespace IRaCIS.Core.Application.Service
//.ForMember(d => d.OutPlanVisitUploadCount, u => u.MapFrom(s => s.SubjectVisitList.Count(t => t.VisitExecuted == VisitExecutedEnum.Executed && t.InPlan == false)));
- //审计信息 这里不用IncludeMembers 也可以识别 是以导航属性名称开头
- // 还有 外键? COALESCE([t0].[SubjectId], '00000000-0000-0000-0000-000000000000') 因为destination 是Guid
CreateMap().ForAllMembers(opt => opt.Condition((src, dest, srcMember) => srcMember != null));
@@ -90,7 +99,7 @@ namespace IRaCIS.Core.Application.Service
.ForMember(d => d.SubjectVisitId, u => u.MapFrom(s => s.Id))
.ForMember(d => d.TrialSiteCode, u => u.MapFrom(s => s.TrialSite.TrialSiteCode))
.ForMember(d => d.TrialCode, u => u.MapFrom(s => s.Trial.TrialCode))
- .ForMember(d => d.Sponsor, u => u.MapFrom(s => s.Trial.Sponsor.SponsorName));
+ .ForMember(d => d.Sponsor, u => u.MapFrom(s => s.Trial.Sponsor));
CreateMap();
CreateMap()
@@ -100,31 +109,99 @@ namespace IRaCIS.Core.Application.Service
.ForMember(d => d.TrialSiteCode, u => u.MapFrom(s => s.SubjectVisit.TrialSite.TrialSiteCode));
- CreateMap()
- .ForMember(d => d.StudyId, u => u.MapFrom(s => s.Id))
- .ForMember(d => d.SeriesList, u => u.MapFrom(s => s.SeriesList));
+ CreateMap()
+ .ForMember(d => d.SCPStudyId, u => u.MapFrom(s => s.Id));
- CreateMap()
- .ForMember(d => d.InstanceInfoList, u => u.MapFrom(s => s.InstanceList));
+ CreateMap()
+ .ForMember(d => d.CalledAEList, u => u.MapFrom(s => s.SCPStudyList.Select(t => t.CalledAE).Distinct()))
+ .ForMember(d => d.CallingAEList, u => u.MapFrom(s => s.SCPStudyList.Select(t => t.CallingAE).Distinct()))
+ .ForMember(d => d.PatientId, u => u.MapFrom(s => s.Id));
- CreateMap();
+ CreateMap().IncludeMembers(t=>t.SCPStudy)
+ .ForMember(d => d.VisitName, u => u.MapFrom(s => s.SubjectVisit.VisitName));
+
+ CreateMap()
+ .ForMember(d => d.PatientList, u => u.MapFrom(s => s.SubjectPatientList))
+ .ForMember(d => d.VisitCount, u => u.MapFrom(s => s.SubjectVisitList.Count()))
+ .ForMember(d => d.LatestVisitName, u => u.MapFrom(s => s.SubjectVisitList.OrderByDescending(t => t.VisitNum).First().VisitName))
+ ;
+
+ CreateMap()
+ .ForMember(d => d.PatientId, u => u.MapFrom(s => s.Patient.Id))
+ .ForMember(d => d.PatientSex, u => u.MapFrom(s => s.Patient.PatientSex))
+ .ForMember(d => d.PatientIdStr, u => u.MapFrom(s => s.Patient.PatientIdStr))
+ .ForMember(d => d.PatientAge, u => u.MapFrom(s => s.Patient.PatientAge))
+ .ForMember(d => d.PatientName, u => u.MapFrom(s => s.Patient.PatientName))
+ .ForMember(d => d.PatientBirthDate, u => u.MapFrom(s => s.Patient.PatientBirthDate));
+
+ CreateMap()
+ .ForMember(d => d.TrialId, u => u.MapFrom(s => s.Id));
+
+ CreateMap()
+ .ForMember(d => d.TrialId, u => u.MapFrom(s => s.Id))
+ .ForMember(d => d.UnSubmitCount, u => u.MapFrom(s => s.SubjectVisitList.Count(t=>t.SubmitState==SubmitStateEnum.ToSubmit)))
+ .ForMember(d => d.UnReadCount, u => u.MapFrom(s => s.VisitTaskList.Count(t=>t.TaskState==TaskState.Effect && t.SignTime==null)))
+ ;
+
+ CreateMap()
+ .ForMember(d => d.DictionaryList, u => u.MapFrom(s => s.TrialDicList.Select(t => t.Dictionary).OrderBy(t => t.ShowOrder)));
+
+
+ CreateMap()
+ .ForMember(d => d.SCPStudyId, u => u.MapFrom(s => s.Id));
+
+ CreateMap();
+ CreateMap().ReverseMap();
+
+ CreateMap().IncludeMembers(t => t.Subject)
+ .ForMember(d => d.TrialId, u => u.MapFrom(s => s.Subject.TrialId))
+ .ForMember(d => d.ResearchProgramNo, u => u.MapFrom(s => s.Subject.Trial.ResearchProgramNo))
+ .ForMember(d => d.TrialStatusStr, u => u.MapFrom(s => s.Subject.Trial.TrialStatusStr))
+ .ForMember(d => d.TrialType, u => u.MapFrom(s => s.Subject.Trial.TrialType))
+ .ForMember(d => d.Sponsor, u => u.MapFrom(s => s.Subject.Trial.Sponsor))
+ .ForMember(d => d.CreateTime, u => u.MapFrom(s => s.CreateTime))
+ .ForMember(d => d.TrialCode, u => u.MapFrom(s => s.Subject.Trial.TrialCode))
+ .ForMember(d => d.ExperimentName, u => u.MapFrom(s => s.Subject.Trial.ExperimentName));
+
+ CreateMap();
+
+
+ CreateMap();
+
+ CreateMap()
+ .ForMember(d => d.SubjectCode, u => u.MapFrom(s => s.Subject.Code))
+ .ForMember(d => d.SubjectShortName, u => u.MapFrom(s => s.Subject.ShortName))
+ .ForMember(d => d.TrialReadingCriterionName, u => u.MapFrom(s => s.TrialReadingCriterion.CriterionName))
+ .ForMember(d => d.CriterionType, u => u.MapFrom(s => s.TrialReadingCriterion.CriterionType))
+ .ForMember(d => d.PatientList, u => u.MapFrom(s => s.Subject.SubjectPatientList))
+ .ForMember(d => d.VisitImageZipPath, u => u.MapFrom(s => s.SourceSubjectVisit.VisitImageZipPath))
+ .ForMember(d => d.PackState, u => u.MapFrom(s => s.SourceSubjectVisit.PackState));
+
+ CreateMap().ReverseMap();
+
+ CreateMap();
- CreateMap()
- .ForMember(d => d.TrialSiteCode, u => u.MapFrom(s => s.TrialSite.TrialSiteCode))
- .ForMember(d => d.TrialSiteAliasName, u => u.MapFrom(s => s.TrialSite.TrialSiteAliasName))
- .ForMember(d => d.TrialSiteName, u => u.MapFrom(s => s.TrialSite.TrialSiteName));
+ CreateMap()
+ .ForMember(d => d.SeriesList, u => u.Ignore())
+ /* .ForMember(d => d.SeriesList, u => u.Ignore())*/;
- CreateMap()
- .ForMember(d => d.TrialSiteCode, u => u.MapFrom(s => s.TrialSite.TrialSiteCode))
- .ForMember(d => d.TrialSiteAliasName, u => u.MapFrom(s => s.TrialSite.TrialSiteAliasName))
- .ForMember(d => d.TrialSiteName, u => u.MapFrom(s => s.TrialSite.TrialSiteName));
-
-
- CreateMap();
CreateMap();
CreateMap();
+ CreateMap()
+ .ForMember(d => d.TrialId, u => u.MapFrom(s => s.Id));
+
+ CreateMap().ReverseMap();
+
+ CreateMap();
+
+ CreateMap().ReverseMap();
+
+
+ CreateMap();
+
+
}
}
diff --git a/IRaCIS.Core.Domain.Share/Trial/TrialExpedited.cs b/IRaCIS.Core.Domain.Share/Trial/TrialExpedited.cs
index 1c7d99f54..e023561b2 100644
--- a/IRaCIS.Core.Domain.Share/Trial/TrialExpedited.cs
+++ b/IRaCIS.Core.Domain.Share/Trial/TrialExpedited.cs
@@ -22,7 +22,12 @@ namespace IRaCIS.Core.Domain.Share
NoneOfficial = 0,
- Training = 2
+ Training = 2,
+
+ //临床研究
+ ClinicalResearch = 3,
+
+ ScientificResearch = 4
}
diff --git a/IRaCIS.Core.Domain.Share/User/UserType.cs b/IRaCIS.Core.Domain.Share/User/UserType.cs
index b38f45d76..2dc5e933c 100644
--- a/IRaCIS.Core.Domain.Share/User/UserType.cs
+++ b/IRaCIS.Core.Domain.Share/User/UserType.cs
@@ -4,43 +4,65 @@
public enum UserTypeEnum
{
-
+ SuperAdmin = 1,
+
+ Admin = 2,
+
+
+ TA = 3,
+
+
+
//PM
- ProjectManager=1,
+ ProjectManager = 4,
+
+
//CRC
- ClinicalResearchCoordinator=2,
+ ClinicalResearchCoordinator = 5,
+
+ CRA = 6,
//IQC
- IQC = 3,
+ IQC = 7,
- ReviewerCoordinator = 4,
- // 大屏展示
- Dashboard = 6,
-
- // 超级管理员用户类型,用于取代 SuperAdmin字段 数据库不内置这个用户类型和角色的配置,因为只允许有一个
- SuperAdmin=7,
-
- Admin = 8,
+ PI = 8,
- CRA =9,
+ SR = 9,
- SPM=10,
-
- APM=11,
-
- CPM=12,
-
- IndependentReviewer=13,
-
- // 医学影像经理
- MIM = 14,
+ MIM = 10,
+
+
+ IM = 11,
+
+
+ QA = 12,
+
+ OP = 13,
+
+ OA = 14,
+
+ SPM = 20,
+ APM = 21,
+ CPM = 22,
+
+ IndependentReviewer = 18,
+
+ AIR = 21,
+
+ //医生用户类型暂不处理
+
+ ShareImage = 125,
+
+
+ Undefined = 0,
+
+
- QA=15,
EA=16,
@@ -52,7 +74,6 @@
CMM=19,
- AIR=21,
ZYSS=26,
@@ -60,16 +81,6 @@
MC=30,
- OP=31,
-
- //医生用户类型暂不处理
-
- ShareImage = 125,
-
-
-
-
- Undefined=0
}
diff --git a/IRaCIS.Core.Domain/Allocation/VisitTask.cs b/IRaCIS.Core.Domain/Allocation/VisitTask.cs
index 4efb9a1dd..78e86e852 100644
--- a/IRaCIS.Core.Domain/Allocation/VisitTask.cs
+++ b/IRaCIS.Core.Domain/Allocation/VisitTask.cs
@@ -281,4 +281,67 @@ public class VisitTask : BaseFullAuditEntity
[Comment("通知IR加急阅片时间")]
public DateTime? ExpetidEmailNoticeTime { get; set; }
+
+ #region HIR 新增字段
+
+ [JsonIgnore]
+ public User FirstAuditUser { get; set; }
+
+ [JsonIgnore]
+ public User LatestReplyUser { get; set; }
+
+ [JsonIgnore]
+ public User SubjectCriterionClaimUser { get; set; }
+
+
+ [NotMapped]
+ public List PIAuditImagePathList
+ {
+ get
+ {
+
+ try
+ {
+ return this.PIAuditImagePath?.Trim().Split('|', StringSplitOptions.RemoveEmptyEntries).ToList();
+ }
+ catch (Exception)
+ {
+
+ return new List();
+ }
+
+ }
+ }
+
+ public string PIAuditNote { get; set; } = string.Empty;
+
+ public string PIAuditImagePath { get; set; } = string.Empty;
+
+ public string NotAgreeReason { get; set; } = string.Empty;
+
+ public PIAuditState PIAuditState { get; set; }
+
+ public bool? IsEnrollment { get; set; }
+
+ public bool? IsPDConfirm { get; set; }
+
+ public Guid? FirstAuditUserId { get; set; }
+ public DateTime? FirstAuditTime { get; set; }
+
+ public Guid? LatestReplyUserId { get; set; }
+ public DateTime? LatestReplyTime { get; set; }
+
+ public Guid? SubjectCriterionClaimUserId { get; set; }
+
+ public DateTime? ReportExportDate { get; set; }
+
+ public int? ReportExportNum { get; set; }
+
+ public string ReportExportUrl { get; set; } = string.Empty;
+
+ ///