3230 lines
156 KiB
C#
3230 lines
156 KiB
C#
using IRaCIS.Application.Interfaces;
|
||
using IRaCIS.Application.Contracts;
|
||
using IRaCIS.Core.Application.Filter;
|
||
using IRaCIS.Core.Domain.Share;
|
||
using Microsoft.AspNetCore.Mvc;
|
||
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 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;
|
||
using IRaCIS.Core.Infrastructure.Encryption;
|
||
using FellowOakDicom.Network.Client;
|
||
using FellowOakDicom.Network;
|
||
using Microsoft.Extensions.Logging;
|
||
using DocumentFormat.OpenXml.Wordprocessing;
|
||
using System;
|
||
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
|
||
using DocumentFormat.OpenXml.Vml.Office;
|
||
using IRaCIS.Core.Infra.EFCore.Migrations;
|
||
using System.Dynamic;
|
||
using System.Threading.Channels;
|
||
|
||
|
||
namespace IRaCIS.Application.Services
|
||
{
|
||
[ApiExplorerSettings(GroupName = "Trial")]
|
||
public class PatientService(IRepository<SCPStudySubjectVisit> _studySubjectVisitRepository,
|
||
IRepository<SubjectPatient> _subjectPatientRepository,
|
||
IRepository<Trial> _trialRepository,
|
||
IRepository<SCPPatient> _patientRepository,
|
||
IRepository<SCPStudy> _studyRepository,
|
||
IRepository<Subject> _subjectRepository,
|
||
IRepository<SubjectVisit> _subjectVisitRepository,
|
||
IRepository<SubejctVisitDownload> _subejctVisitDownloadRepository,
|
||
IRepository<SCPImageUpload> _SCPImageUploadRepository,
|
||
IRepository<User> _userRepository,
|
||
ILogger<PatientService> _logger,
|
||
IDistributedLockProvider _distributedLockProvider, IMapper _mapper, IUserInfo _userInfo, IWebHostEnvironment _hostEnvironment, IStringLocalizer _localizer, IFusionCache _fusionCache
|
||
|
||
|
||
) : BaseService
|
||
{
|
||
|
||
|
||
#region 医院信息管理
|
||
|
||
|
||
/// <summary>
|
||
/// 获取医院的配置信息
|
||
/// </summary>
|
||
/// <param name="options"></param>
|
||
/// <returns></returns>
|
||
[AllowAnonymous]
|
||
public async Task<SystemHospitalOption> GetHospitalInfo([FromServices] IOptionsMonitor<SystemHospitalOption> options)
|
||
{
|
||
return options.CurrentValue;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 配置医院信息,方便测试邮件和授权码的方式
|
||
/// </summary>
|
||
/// <param name="systemHospitalOption"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput> UpdateHospitalInfo(SystemHospitalOption systemHospitalOption)
|
||
{
|
||
var path = $"appsettings.{_hostEnvironment.EnvironmentName}.json";
|
||
|
||
string text = System.IO.File.ReadAllText(path);
|
||
|
||
// 修改
|
||
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;
|
||
|
||
obj["SystemHospitalConfig"][nameof(SystemHospitalOption.HospitalCode)] = systemHospitalOption.HospitalCode;
|
||
obj["SystemHospitalConfig"][nameof(SystemHospitalOption.HospitalLogoPath)] = systemHospitalOption.HospitalLogoPath;
|
||
obj["SystemHospitalConfig"][nameof(SystemHospitalOption.TrialKeepCount)] = systemHospitalOption.TrialKeepCount;
|
||
|
||
// 重新写入appsettings.json
|
||
string result = obj.ToString();
|
||
System.IO.File.WriteAllText(path, result);
|
||
|
||
await _userRepository.BatchUpdateNoTrackingAsync(t => t.IsZhiZhun, t => new User() { OrganizationName = systemHospitalOption.HospitalName });
|
||
|
||
return ResponseOutput.Ok();
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 项目管理
|
||
|
||
/// <summary>
|
||
/// 获取系统已确认的标准
|
||
/// </summary>
|
||
/// <param name="_readingQuestionCriterionSystemRepository"></param>
|
||
/// <returns></returns>
|
||
public async Task<IResponseOutput> GetSystemConfirmedCreiterionList([FromServices] IRepository<ReadingQuestionCriterionSystem> _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);
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 获取项目列表 (PM CRC 共用)
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput<PageOutput<NewTrialView>>> GetTrialList(NewTrialQuery inQuery)
|
||
{
|
||
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<NewTrialView>(_mapper.ConfigurationProvider);
|
||
|
||
|
||
var pageList = await trialQuery.ToPagedListAsync(inQuery, nameof(NewTrialQuery.ResearchProgramNo));
|
||
|
||
|
||
return ResponseOutput.Ok(pageList);
|
||
}
|
||
|
||
[HttpGet("{trialId:guid}")]
|
||
public async Task<IResponseOutput> GetTrialInfo(Guid trialId, [FromServices] IOptionsMonitor<ServiceVerifyConfigOption> _basicSystemConfigConfig)
|
||
{
|
||
var trial = (await _trialRepository.Where(o => o.Id == trialId).IgnoreQueryFilters().ProjectTo<TrialInfoDTO>(_mapper.ConfigurationProvider, new { isEn_Us = _userInfo.IsEn_Us }).FirstOrDefaultAsync()).IfNullThrowException();
|
||
|
||
if (!string.IsNullOrEmpty(trial.AuthorizationEncrypt))
|
||
{
|
||
try
|
||
{
|
||
//解析加密信息
|
||
var decodedText = AesEncryption.Decrypt(trial.AuthorizationEncrypt, _basicSystemConfigConfig.CurrentValue.AESKey, "Trial_AuthorizationEncrypt");
|
||
|
||
var authInfo = JsonConvert.DeserializeObject<TrialAuthorizationInfo>(decodedText);
|
||
|
||
return ResponseOutput.Ok(trial, authInfo);
|
||
}
|
||
catch (Exception)
|
||
{
|
||
|
||
return ResponseOutput.Ok(trial, msg: "项目未授权,请确认。", code: ApiResponseCodeEnum.NeedTips);
|
||
}
|
||
}
|
||
return ResponseOutput.Ok(trial);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加更新项目
|
||
/// </summary>
|
||
/// <param name="inCommand"></param>
|
||
/// <param name="_systemEmailSendConfig"></param>
|
||
/// <param name="_provider"></param>
|
||
/// <returns></returns>
|
||
/// <exception cref="BusinessValidationFailedException"></exception>
|
||
[HttpPost]
|
||
[UnitOfWork]
|
||
public async Task<IResponseOutput> AddOrUpdateTrial(AddOrUpdateTrialCommand inCommand,
|
||
[FromServices] IOptionsMonitor<SystemEmailSendConfig> _systemEmailSendConfig,
|
||
[FromServices] IOptionsMonitor<ServiceVerifyConfigOption> _basicSystemConfigConfig,
|
||
[FromServices] IOptionsMonitor<SystemHospitalOption> _systemHospitalOption,
|
||
[FromServices] IRepository<TrialDictionary> _trialDictionaryRepository,
|
||
[FromServices] IRepository<TrialUser> _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<Trial>(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(), 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(), caheInfo, TimeSpan.FromDays(7));
|
||
|
||
var success = await _trialRepository.SaveChangesAsync();
|
||
|
||
return ResponseOutput.Ok(trial);
|
||
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 授权和激活
|
||
|
||
|
||
|
||
public async Task<IResponseOutput<TrialAuthorizationInfo>> GetTrialAuthorizationInfo(Guid trialId, [FromServices] IOptionsMonitor<SystemHospitalOption> _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);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取项目授权码
|
||
/// </summary>
|
||
/// <param name="authInfo"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput> GetTrialAuthorizationCode(TrialAuthorizationInfo authInfo, [FromServices] IOptionsMonitor<SystemHospitalOption> _hospitalOption)
|
||
{
|
||
|
||
// 将明文信息转换成 Base64 编码
|
||
string base64EncodedText = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(authInfo)));
|
||
|
||
return ResponseOutput.Ok(base64EncodedText);
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取授权码明文信息
|
||
/// </summary>
|
||
/// <param name="authorizationCode"></param>
|
||
/// <param name="_hospitalOption"></param>
|
||
/// <returns></returns>
|
||
[AllowAnonymous]
|
||
public async Task<IResponseOutput> GetAuthorizationCodeInfo(string authorizationCode, [FromServices] IOptionsMonitor<SystemHospitalOption> _hospitalOption)
|
||
{
|
||
// 解密 Base64 编码后的数据
|
||
byte[] base64DecodedBytes = Convert.FromBase64String(authorizationCode);
|
||
string decodedText = System.Text.Encoding.UTF8.GetString(base64DecodedBytes);
|
||
|
||
|
||
var authInfo = JsonConvert.DeserializeObject<TrialAuthorizationInfo>(decodedText);
|
||
|
||
if (authInfo == null)
|
||
{
|
||
return ResponseOutput.NotOk("不能解析该项目授权码");
|
||
}
|
||
|
||
return ResponseOutput.Ok(authInfo);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取项目激活码
|
||
/// </summary>
|
||
/// <param name="authorizationInfo"></param>
|
||
/// <param name="_basicSystemConfigConfig"></param>
|
||
/// <returns></returns>
|
||
[AllowAnonymous]
|
||
[HttpPost]
|
||
public async Task<IResponseOutput> GetTrialActivationCode(TrialAuthorizationInfo authorizationInfo, [FromServices] IOptionsMonitor<ServiceVerifyConfigOption> _basicSystemConfigConfig)
|
||
{
|
||
authorizationInfo.ActiveDeadLineDate = DateTime.Now.Date.AddDays(8).AddSeconds(-1);
|
||
var info = AesEncryption.Encrypt($"{JsonConvert.SerializeObject(authorizationInfo)}", _basicSystemConfigConfig.CurrentValue.AESKey, "Trial_AuthorizationEncrypt");
|
||
|
||
return ResponseOutput.Ok(info);
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 激活码获取明文信息
|
||
/// </summary>
|
||
/// <param name="activationCode"></param>
|
||
/// <param name="_hospitalOption"></param>
|
||
/// <param name="_basicSystemConfigConfig"></param>
|
||
/// <returns></returns>
|
||
public async Task<IResponseOutput> GetActivationCodeInfo(string activationCode,
|
||
[FromServices] IOptionsMonitor<SystemHospitalOption> _hospitalOption,
|
||
[FromServices] IOptionsMonitor<ServiceVerifyConfigOption> _basicSystemConfigConfig)
|
||
{
|
||
|
||
var decodedText = string.Empty;
|
||
|
||
try
|
||
{
|
||
decodedText = AesEncryption.Decrypt(activationCode, _basicSystemConfigConfig.CurrentValue.AESKey, "Trial_AuthorizationEncrypt");
|
||
|
||
|
||
}
|
||
catch (Exception)
|
||
{
|
||
|
||
return ResponseOutput.NotOk("激活码有误,请核对,无法激活");
|
||
}
|
||
|
||
var authInfo = JsonConvert.DeserializeObject<TrialAuthorizationInfo>(decodedText);
|
||
|
||
if (authInfo != null)
|
||
{
|
||
return ResponseOutput.Ok(authInfo);
|
||
}
|
||
else
|
||
{
|
||
return ResponseOutput.NotOk("激活码信息有误!");
|
||
}
|
||
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 设置项目授权信息
|
||
/// </summary>
|
||
/// <param name="trialId"></param>
|
||
/// <param name="activationCode"></param>
|
||
/// <returns></returns>
|
||
[HttpPut]
|
||
public async Task<IResponseOutput> ActivateTrial(Guid trialId, string activationCode,
|
||
[FromServices] IOptionsMonitor<ServiceVerifyConfigOption> _basicSystemConfigConfig,
|
||
[FromServices] IFusionCache _provider,
|
||
[FromServices] IOptionsMonitor<SystemHospitalOption> _hospitalOption)
|
||
{
|
||
var hospitalCode = _hospitalOption.CurrentValue.HospitalCode;
|
||
var trialInfo = _trialRepository.Where(t => t.Id == trialId, ignoreQueryFilters: true).FirstOrDefault();
|
||
|
||
var decodedText = string.Empty;
|
||
try
|
||
{
|
||
decodedText = AesEncryption.Decrypt(activationCode, _basicSystemConfigConfig.CurrentValue.AESKey, "Trial_AuthorizationEncrypt");
|
||
|
||
|
||
}
|
||
catch (Exception)
|
||
{
|
||
|
||
return ResponseOutput.NotOk("激活码有误,请核对,无法激活");
|
||
}
|
||
|
||
var authInfo = JsonConvert.DeserializeObject<TrialAuthorizationInfo>(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 = AesEncryption.Encrypt($"{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 患者检查管理
|
||
|
||
/// <summary>
|
||
///检查管理-> 检查Tab 患者列表 (带加入的项目信息 以及检查统计) 原型标注错误,不是检查列表
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput<PageOutput<PatientTrialView>>> 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
|
||
.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.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(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));
|
||
}
|
||
|
||
|
||
var resultQuery = from patient in query
|
||
|
||
select new PatientTrialView()
|
||
{
|
||
PatientId = patient.Id,
|
||
PatientBirthDate = patient.PatientBirthDate,
|
||
CreateTime = patient.CreateTime,
|
||
CalledAEList = patient.SCPStudyList.Select(t => t.CalledAE).Distinct().ToList(),
|
||
CallingAEList = patient.SCPStudyList.Select(t => t.CallingAE).Distinct().ToList(),
|
||
CreateUserId = patient.CreateUserId,
|
||
UpdateTime = patient.UpdateTime,
|
||
UpdateUserId = patient.UpdateUserId,
|
||
|
||
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(),
|
||
|
||
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, nameof(PatientQueryView.PatientIdStr));
|
||
#endregion
|
||
|
||
|
||
return ResponseOutput.Ok(pageList);
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 检查管理-> 患者加入项目 初始化勾选列表
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput<PageOutput<PatientJoinTrialInitView>>> GetPatientJoinTrialInitList(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 => !exceptQuery.Any(c => c == t.Id)).ProjectTo<PatientJoinTrialInitView>(_mapper.ConfigurationProvider);
|
||
|
||
|
||
var pageList = await trialQuery.ToPagedListAsync(inQuery, nameof(PatientJoinTrialInitView.ResearchProgramNo));
|
||
|
||
|
||
return ResponseOutput.Ok(pageList);
|
||
}
|
||
/// <summary>
|
||
/// 检查管理-> 患者加入项目 下拉框勾选列表
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput<List<PatientJoinTrialSelectView>>> 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<PatientJoinTrialSelectView>(_mapper.ConfigurationProvider);
|
||
|
||
var list = trialQuery.ToList();
|
||
return ResponseOutput.Ok(list);
|
||
}
|
||
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 检查管理-> 患者已加入的列表(原型有误,应该展示 项目 下的subject 绑定关系)
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput<PageOutput<PatientJoinedTrialView>>> 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<PatientJoinedTrialView>(_mapper.ConfigurationProvider);
|
||
|
||
var pageList = await trialQuery.ToPagedListAsync(inQuery);
|
||
|
||
return ResponseOutput.Ok(pageList);
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 检查管理-> 获取患者检查列表(同步影像数据之前的)
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<PageOutput<PatientStudySimpleView>> 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))
|
||
select new PatientStudySimpleView()
|
||
{
|
||
Description = scpStudy.Description,
|
||
CalledAE = scpStudy.CalledAE,
|
||
CallingAE = scpStudy.CallingAE,
|
||
InstanceCount = scpStudy.InstanceCount,
|
||
Modalities = scpStudy.Modalities,
|
||
PatientId = scpStudy.PatientId,
|
||
AccessionNumber = scpStudy.AccessionNumber,
|
||
SCPStudyId = scpStudy.Id,
|
||
SeriesCount = scpStudy.SeriesCount,
|
||
StudyTime = scpStudy.StudyTime,
|
||
};
|
||
|
||
var pageList = await query.ToPagedListAsync(inQuery, nameof(PatientStudySimpleView.StudyTime));
|
||
|
||
return pageList;
|
||
}
|
||
|
||
|
||
|
||
public async Task<IResponseOutput<List<PatientSeriesDTO>>> GetPatientSeriesList(Guid scpStudyId,
|
||
[FromServices] IRepository<SCPSeries> _seriesRepository,
|
||
[FromServices] IRepository<SCPInstance> _instanceRepository
|
||
)
|
||
{
|
||
|
||
var seriesList = await _seriesRepository.Where(s => s.StudyId == scpStudyId).OrderBy(s => s.SeriesNumber).
|
||
ThenBy(s => s.SeriesTime).ThenBy(s => s.CreateTime)
|
||
.ProjectTo<PatientSeriesDTO>(_mapper.ConfigurationProvider).ToListAsync();
|
||
|
||
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);
|
||
|
||
foreach (var series in seriesList)
|
||
{
|
||
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,
|
||
|
||
}).ToList();
|
||
}
|
||
|
||
|
||
var study = await _studyRepository.FirstOrDefaultAsync(t => t.Id == scpStudyId);
|
||
|
||
return ResponseOutput.Ok(seriesList, study);
|
||
}
|
||
|
||
[UnitOfWork]
|
||
[HttpDelete]
|
||
public async Task<IResponseOutput> DeletePatientStudy(Guid patiendId, Guid scpStudyId,
|
||
[FromServices] IRepository<SCPSeries> _SeriesRepository,
|
||
[FromServices] IRepository<SCPInstance> _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();
|
||
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 清除该患者绑定的受试者的所有的数据、(subject subjectVisit visitTask dicom)
|
||
/// </summary>
|
||
/// <param name="patientId"></param>
|
||
/// <returns></returns>
|
||
[UnitOfWork]
|
||
public async Task<IResponseOutput> DeletePatientStudyAllData(Guid patientId,
|
||
[FromServices] IRepository<VisitTask> _visitTaskRepository,
|
||
[FromServices] IRepository<SCPSeries> _SeriesRepository,
|
||
[FromServices] IRepository<SCPInstance> _instanceRepository,
|
||
[FromServices] IRepository<DicomStudy> _dicomStudyRepository,
|
||
[FromServices] IRepository<DicomSeries> _dicomSeriesRepository,
|
||
[FromServices] IRepository<DicomInstance> _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 受试者管理
|
||
|
||
|
||
[TrialGlobalLimit("AfterStopCannNotOpt")]
|
||
[HttpPost]
|
||
public async Task<IResponseOutput<string>> AddOrUpdateSubject([FromBody] AddOrUpdateSubjectCommand subjectCommand)
|
||
{
|
||
var svlist = new List<SubjectVisit>();
|
||
|
||
var verifyExp1 = new EntityVerifyExp<Subject>()
|
||
{
|
||
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());
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 受试者管理-> 受试者列表 (带患者信息,患者信息是数组)
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput<PageOutput<PatienSubejctView>>> 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<PatienSubejctView>(_mapper.ConfigurationProvider);
|
||
|
||
var pageList = await subjectQuery.ToPagedListAsync(inQuery, nameof(PatienSubejctView.Code));
|
||
|
||
|
||
return ResponseOutput.Ok(pageList);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 受试者管理-> 患者列表 (subject 列表进入,进行关系绑定初始化列表,排除已绑定的患者和已绑定给其他subject的患者)
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput<PageOutput<PatientQueryView>>> 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<PatientQueryView>(_mapper.ConfigurationProvider);
|
||
|
||
|
||
var pageList = await patientQuery.ToPagedListAsync(inQuery, nameof(PatientQueryView.PatientIdStr));
|
||
|
||
|
||
return ResponseOutput.Ok(pageList);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 受试者管理->患者列表 Dicom AE 下拉框数据获取
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public async Task<List<string>> GetDicomCalledAEList()
|
||
{
|
||
var list = await _studyRepository.Select(t => t.CalledAE).Distinct().ToListAsync();
|
||
|
||
return list;
|
||
}
|
||
|
||
public async Task<List<string>> GetDicomCallingAEList()
|
||
{
|
||
var list = await _studyRepository.Select(t => t.CallingAE).Distinct().ToListAsync();
|
||
|
||
return list;
|
||
}
|
||
|
||
/// <summary>
|
||
///受试者管理-> 患者列表 模糊搜索下拉 选择subject 排除已绑定并提交的
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<List<SubjectSelectDto>> 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<IResponseOutput> 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<AuToBindingStudyInfo> 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();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 之前患者和subject已绑定后,新来了的检查 可能需要新建访视,或者和已有访视在同一区间,需要自动绑定
|
||
/// </summary>
|
||
/// <param name="inCommand"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
[TrialGlobalLimit("AfterStopCannNotOpt")]
|
||
public async Task<IResponseOutput> 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<IResponseOutput> VerifyTrialSubject(VerifyTrialSubjectCommand inCommand, [FromServices] IRepository<SubjectVisit> _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();
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 建立subject与患者绑定 如果是下拉,则传递SubjectId,如果不存在,创建,那么就传递 SubjectCode
|
||
///
|
||
/// 绑定以后,后台自动创建访视 和检查预先绑定
|
||
/// </summary>
|
||
/// <param name="inCommand"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
[TrialGlobalLimit("AfterStopCannNotOpt")]
|
||
[UnitOfWork]
|
||
public async Task<IResponseOutput> AddSubjectPatientBinding(AddSubjectPatientCommand inCommand, [FromServices] IRepository<SubjectVisit> _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);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 删除 受试者 和患者之间的绑定
|
||
/// </summary>
|
||
/// <param name="inCommand"></param>
|
||
/// <returns></returns>
|
||
[HttpDelete]
|
||
[UnitOfWork]
|
||
[TrialGlobalLimit("AfterStopCannNotOpt")]
|
||
public async Task<IResponseOutput> DeleteSubjectPatientBinding(DeleteSubejctPatientCommand inCommand,
|
||
|
||
|
||
[FromServices] IRepository<VisitTask> _visitTaskRepository,
|
||
[FromServices] IRepository<DicomStudy> _dicomStudyRepository,
|
||
[FromServices] IRepository<DicomSeries> _dicomSeriesRepository,
|
||
[FromServices] IRepository<DicomInstance> _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();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 患者检查 与SubjectVisit 的绑定
|
||
/// </summary>
|
||
/// <param name="inCommandList"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
[TrialGlobalLimit("AfterStopCannNotOpt")]
|
||
[UnitOfWork]
|
||
[Obsolete]
|
||
public async Task<IResponseOutput> AddSubjectPatientStudyBinding(List<AddSubjectPatientStudyVisitCommand> inCommandList)
|
||
{
|
||
|
||
|
||
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();
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 修改 访视 和检查的绑定关系 IsAdd 区分添加 还是移除
|
||
/// </summary>
|
||
/// <param name="inCommand"></param>
|
||
/// <returns></returns>
|
||
[TrialGlobalLimit("AfterStopCannNotOpt")]
|
||
[UnitOfWork]
|
||
public async Task<IResponseOutput> 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();
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 提交 患者检查和访视的绑定
|
||
/// </summary>
|
||
/// <param name="inCommand"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
[UnitOfWork]
|
||
[TrialGlobalLimit("AfterStopCannNotOpt")]
|
||
public async Task<IResponseOutput> SubmitVisitStudyBinding(SubmitVisitStudyBindingCommand inCommand,
|
||
[FromServices] IOptionsMonitor<ServiceVerifyConfigOption> _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<TrialAuthorizationInfo>(decodedText);
|
||
|
||
|
||
|
||
|
||
var @lock = _distributedLockProvider.CreateLock($"StudyCode");
|
||
|
||
using (await @lock.AcquireAsync())
|
||
{
|
||
var dbStudyCodeIntMax = _repository.Where<DicomStudy>(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<DicomStudy>(find);
|
||
|
||
await _repository.AddAsync(newStuty);
|
||
//newStuty.Id = NewId.NextSequentialGuid();
|
||
|
||
newStuty.SeqId = NewId.NextSequentialGuid();
|
||
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<List<DicomSeries>>(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 = NewId.NextSequentialGuid();
|
||
series.TrialId = item.TrialId;
|
||
series.SubjectId = item.SubjectId;
|
||
series.SubjectVisitId = item.SubjectVisitId;
|
||
}
|
||
|
||
await _repository.AddRangeAsync(newSeriesList);
|
||
|
||
var newInstanceList = _mapper.Map<List<DicomInstance>>(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 = NewId.NextSequentialGuid();
|
||
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 访视基本管理
|
||
|
||
|
||
/// <summary>
|
||
/// 绑定访视 初始化患者检查列表
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<List<PatientStudySelectDto>> 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;
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 访视管理- 获取subject 已存在的访视列表 ,同时获取项目访视的配置 在otherData里
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <param name="_subjectVisitReposiotry"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput> GetSubjectVisitSelectList(SubjectVisitSelectQuery inQuery, [FromServices] IRepository<SubjectVisit> _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<SubjectVisitSelectDto>(_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);
|
||
}
|
||
/// <summary>
|
||
/// 添加或者更新受试者访视
|
||
/// </summary>
|
||
/// <param name="incommand"></param>
|
||
/// <param name="_subjectVisitReposiotry"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
[TrialGlobalLimit("AfterStopCannNotOpt")]
|
||
public async Task<IResponseOutput> AddOrUpdateSubjectVisit(AddOrUpdateSubjectVisitCommand incommand, [FromServices] IRepository<SubjectVisit> _subjectVisitReposiotry)
|
||
{
|
||
//var verifyExp1 = new EntityVerifyExp<SubjectVisit>()
|
||
//{
|
||
// VerifyExp = t => t.VisitNum == incommand.VisitNum && t.SubjectId == incommand.SubjectId,
|
||
// //---该受试者的访视计划中已经包含一个具有相同访视号的访视。
|
||
// VerifyMsg = _localizer["Visit_DuplicateVisitNo"]
|
||
//};
|
||
|
||
|
||
|
||
//var verifyExp3 = new EntityVerifyExp<SubjectVisit>()
|
||
//{
|
||
// 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);
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 前端利用组件打成压缩包,后端返回路径和压缩包的信息
|
||
/// </summary>
|
||
/// <param name="subjectId"></param>
|
||
/// <returns></returns>
|
||
[HttpGet("{subjectId:guid}/{subjectVisitId:guid}")]
|
||
public async Task<IResponseOutput> 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);
|
||
}
|
||
|
||
|
||
|
||
|
||
/// <summary>
|
||
///访视管理-> 访视列表 (带患者信息,患者信息是数组)
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput<PageOutput<PatientSubjectVisitView>>> 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)
|
||
});
|
||
|
||
var defalutSortArray = new string[] { nameof(PatientSubjectVisitView.SubjectId), nameof(PatientSubjectVisitView.VisitNum) };
|
||
var pageList = await query.ToPagedListAsync(inQuery, defalutSortArray);
|
||
|
||
|
||
|
||
return ResponseOutput.Ok(pageList);
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
///访视管理-> 获取当前访视 已绑定的患者检查 (从访视列表 进入修改绑定)
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<List<VisitPatientStudyView>> 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<VisitPatientStudyView>(_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;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 访视管理-> 获取可选访视列表 (从访视列表 进入修改绑定)
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<List<VisitPatientStudyView>> 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.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,
|
||
InstanceCount = scpStudy.InstanceCount,
|
||
Modalities = scpStudy.Modalities,
|
||
PatientId = scpStudy.PatientId,
|
||
SCPStudyId = scpStudy.Id,
|
||
SeriesCount = scpStudy.SeriesCount,
|
||
StudyTime = scpStudy.StudyTime,
|
||
|
||
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 notBindQuery= _studyRepository.Where(t => t.PatientId == inQuery.PatientId && t.pa)
|
||
|
||
//var patientQuery = query
|
||
|
||
// .ProjectTo<VisitPatientStudyView>(_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 检查管理
|
||
|
||
|
||
|
||
/// <summary>
|
||
///检查管理-> 检查列表 (同步影像数据之前的)
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput<PageOutput<PatientStudyBeforeConfirmView>>> 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);
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
///检查管理-> 检查列表 (同步影像数据之后的 带患者信息 患者信息是数组)
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput<PageOutput<PatientStudyView>>> GetTrialPatientStudyList(TrialPatientStudyQuery inQuery, [FromServices] IRepository _repository)
|
||
{
|
||
var query = _repository.Where<DicomStudy>(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,
|
||
|
||
|
||
//PatientId = Guid.Empty,
|
||
PatientAge = t.PatientAge,
|
||
PatientName = t.PatientName,
|
||
PatientBirthDate = t.PatientBirthDate,
|
||
PatientIdStr = t.PatientIdStr,
|
||
PatientSex = t.PatientSex,
|
||
|
||
//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(),
|
||
|
||
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),
|
||
|
||
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);
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 获取该项目 患者已绑定subject ,新来了的检查 可能需要新建访视 但是新增的检查未绑定访视的检查列表
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput<PageOutput<UnbindStudyView>>> 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);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 删除某个项目 未提交的访视检查绑定, 清理数据,方便测试自动绑定
|
||
/// </summary>
|
||
/// <param name="trialId"></param>
|
||
/// <returns></returns>
|
||
[HttpDelete]
|
||
public async Task<IResponseOutput> DeleteUnSubmittedStudyBind(Guid trialId, Guid? subjectId,
|
||
[FromServices] IRepository<VisitTask> _visitTaskRepository,
|
||
[FromServices] IRepository<DicomStudy> _dicomStudyRepository,
|
||
[FromServices] IRepository<DicomSeries> _dicomSeriesRepository,
|
||
[FromServices] IRepository<DicomInstance> _dicomInstanceRepository)
|
||
{
|
||
if (subjectId != null)
|
||
{
|
||
await _studySubjectVisitRepository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId && 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);
|
||
|
||
}
|
||
else
|
||
{
|
||
await _studySubjectVisitRepository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId && t.SubjectVisit.SubmitState != SubmitStateEnum.Submitted);
|
||
|
||
}
|
||
|
||
|
||
return ResponseOutput.Ok();
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 阅片管理-> 任务列表
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput<PageOutput<PatientVisitTaskDTO>>> GetPatientVisitTaskList([FromServices] IRepository<VisitTask> _visitTaskRepository, PatientVisitTaskQuery inQuery)
|
||
{
|
||
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)
|
||
|
||
.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)
|
||
|
||
.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<PatientVisitTaskDTO>(_mapper.ConfigurationProvider);
|
||
|
||
var defalutSortArray = new string[] { nameof(PatientVisitTaskDTO.SubjectId), nameof(PatientVisitTaskDTO.VisitTaskNum) };
|
||
|
||
var pageList = await visitTaskQueryable.ToPagedListAsync(inQuery, defalutSortArray);
|
||
|
||
return ResponseOutput.Ok(pageList);
|
||
}
|
||
|
||
|
||
#endregion
|
||
|
||
|
||
#region 影像下载
|
||
|
||
|
||
/// <summary>
|
||
/// 获取下载的访视检查信息
|
||
/// </summary>
|
||
/// <param name="trialId"></param>
|
||
/// <param name="subjectVisitId"></param>
|
||
/// <returns></returns>
|
||
public async Task<IResponseOutput> GetDownloadSubjectVisitStudyInfo(Guid trialId, Guid subjectVisitId)
|
||
{
|
||
var query = from sv in _subjectVisitRepository.Where(t => t.Id == subjectVisitId)
|
||
|
||
select new
|
||
{
|
||
TrialId = sv.TrialId,
|
||
SubjectId = sv.SubjectId,
|
||
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,
|
||
|
||
InstanceList = z.DicomInstanceList.Select(k => new
|
||
{
|
||
k.Path,
|
||
k.FileSize
|
||
})
|
||
})
|
||
|
||
}).ToList(),
|
||
|
||
|
||
};
|
||
|
||
var result = query.FirstOrDefault();
|
||
|
||
var preDownloadInfo = new SubejctVisitDownload()
|
||
{
|
||
Id = NewId.NextSequentialGuid(),
|
||
IP = _userInfo.IP,
|
||
SubjectVisitId = subjectVisitId,
|
||
DownloadStartTime = DateTime.Now,
|
||
ImageCount = result.StudyList.Sum(s => s.SeriesList.Sum(s => s.InstanceList.Count())),
|
||
ImageSize = result.StudyList.Sum(t => t.SeriesList.Sum(s => s.InstanceList.Sum(i => i.FileSize))) ?? 0
|
||
};
|
||
|
||
await _subejctVisitDownloadRepository.AddAsync(preDownloadInfo, true);
|
||
|
||
return ResponseOutput.Ok(result, preDownloadInfo.Id);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 影像下载成功回调
|
||
/// </summary>
|
||
/// <param name="trialImageDownloadId"></param>
|
||
/// <returns></returns>
|
||
[HttpGet]
|
||
public async Task<IResponseOutput> DownloadImageSuccess(Guid trialImageDownloadId)
|
||
{
|
||
await _subejctVisitDownloadRepository.UpdatePartialFromQueryAsync(t => t.Id == trialImageDownloadId, u => new SubejctVisitDownload()
|
||
{ DownloadEndTime = DateTime.Now, IsSuccess = true }, true);
|
||
return ResponseOutput.Ok();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 访视影像下载记录表
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput<PageOutput<VisitImageDownloadView>>> 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<VisitImageDownloadView>(_mapper.ConfigurationProvider);
|
||
|
||
|
||
var pageList = await query.ToPagedListAsync(inQuery, nameof(VisitImageDownloadQuery.SubjectCode));
|
||
|
||
|
||
return ResponseOutput.Ok(pageList);
|
||
}
|
||
|
||
#endregion
|
||
|
||
|
||
/// <summary>
|
||
/// scp 影像推送记录表
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput<PageOutput<SCPImageUploadView>>> 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<SCPImageUploadView>(_mapper.ConfigurationProvider);
|
||
|
||
|
||
var pageList = await query.ToPagedListAsync(inQuery, nameof(SCPImageUploadView.CallingAE));
|
||
|
||
|
||
return ResponseOutput.Ok(pageList);
|
||
}
|
||
|
||
|
||
#region 作为SCU C-find c-move 操作
|
||
|
||
#region 基础方法
|
||
|
||
public static DicomCFindRequest CreateStudyRequest(SCUQuery inQuery, string modality/*, List<string> modalityList*/)
|
||
{
|
||
|
||
var request = new DicomCFindRequest(DicomQueryRetrieveLevel.Study);
|
||
|
||
// always add the encoding
|
||
request.Dataset.AddOrUpdate(new DicomTag(0x8, 0x5), "ISO_IR 100");
|
||
|
||
// add the dicom tags with empty values that should be included in the result of the QR Server
|
||
|
||
////病例号
|
||
//request.Dataset.AddOrUpdate(DicomTag.PatientID, "");
|
||
|
||
//request.Dataset.AddOrUpdate(DicomTag.PatientName, "");
|
||
//request.Dataset.AddOrUpdate(DicomTag.PatientSex, "");
|
||
//request.Dataset.AddOrUpdate(DicomTag.PatientBirthDate, "");
|
||
////检查号 设备类型
|
||
//request.Dataset.AddOrUpdate(DicomTag.StudyID, "");
|
||
|
||
//request.Dataset.AddOrUpdate(DicomTag.ModalitiesInStudy, "");
|
||
|
||
//request.Dataset.AddOrUpdate(DicomTag.StudyDate, "");
|
||
//request.Dataset.AddOrUpdate(DicomTag.StudyTime, "");
|
||
|
||
//request.Dataset.AddOrUpdate(DicomTag.BodyPartExamined, "");
|
||
//request.Dataset.AddOrUpdate(DicomTag.StudyDescription, "");
|
||
|
||
//request.Dataset.AddOrUpdate(DicomTag.StudyInstanceUID, "");
|
||
|
||
|
||
|
||
// add the dicom tags that contain the filter criterias
|
||
|
||
//request.Dataset.AddOrUpdate(DicomTag.PatientID, "Test*");
|
||
|
||
//var modalityQuery = string.Join($"\\", (inQuery.ModalitiesInStudyList == null || inQuery.ModalitiesInStudyList?.Count == 0) ? modalityList : inQuery.ModalitiesInStudyList);
|
||
|
||
//病例号
|
||
request.Dataset.AddOrUpdate(DicomTag.PatientID, inQuery.PatientID.IsNullOrEmpty() ? "" : inQuery.PatientID);
|
||
|
||
request.Dataset.AddOrUpdate(DicomTag.PatientName, inQuery.PatientName.IsNullOrEmpty() ? "" : inQuery.PatientName);
|
||
request.Dataset.AddOrUpdate(DicomTag.PatientSex, inQuery.PatientSex.IsNullOrEmpty() ? "" : inQuery.PatientSex);
|
||
request.Dataset.AddOrUpdate(DicomTag.PatientBirthDate, inQuery.PatientBirthDate.IsNullOrEmpty() ? "" : inQuery.PatientBirthDate);
|
||
//检查号 设备类型
|
||
request.Dataset.AddOrUpdate(DicomTag.StudyID, inQuery.StudyID.IsNullOrEmpty() ? "" : inQuery.StudyID);
|
||
request.Dataset.AddOrUpdate(DicomTag.AccessionNumber, inQuery.StudyID.IsNullOrEmpty() ? "" : inQuery.AccessionNumber);
|
||
|
||
request.Dataset.AddOrUpdate(DicomTag.Modality, "");
|
||
request.Dataset.AddOrUpdate(DicomTag.ModalitiesInStudy, modality);
|
||
|
||
request.Dataset.AddOrUpdate(DicomTag.StudyDate, inQuery.StudyDate.IsNullOrEmpty() ? "" : inQuery.StudyDate);
|
||
request.Dataset.AddOrUpdate(DicomTag.StudyTime, inQuery.StudyTime.IsNullOrEmpty() ? "" : inQuery.StudyTime);
|
||
|
||
|
||
request.Dataset.AddOrUpdate(DicomTag.StudyDescription, inQuery.StudyDescription.IsNullOrEmpty() ? "" : inQuery.StudyDescription);
|
||
|
||
request.Dataset.AddOrUpdate(DicomTag.StudyInstanceUID, inQuery.StudyInstanceUID.IsNullOrEmpty() ? "" : inQuery.StudyInstanceUID);
|
||
|
||
//测试
|
||
//request.Dataset.AddOrUpdate(DicomTag.SeriesInstanceUID, "");
|
||
//request.Dataset.AddOrUpdate(DicomTag.SeriesDescription, "");
|
||
//request.Dataset.AddOrUpdate(DicomTag.BodyPartExamined, inQuery.BodyPartExamined.IsNullOrEmpty() ? "" : inQuery.BodyPartExamined);
|
||
|
||
return request;
|
||
}
|
||
|
||
public static void DebugStudyResponse(DicomCFindResponse response, ILogger _logger)
|
||
{
|
||
if (response.Status == DicomStatus.Pending)
|
||
{
|
||
|
||
// print the results
|
||
_logger.LogDebug($"Patient {response.Dataset.GetSingleValueOrDefault(DicomTag.PatientName, string.Empty)}, {(response.Dataset.TryGetString(DicomTag.ModalitiesInStudy, out var dummy) ? dummy : string.Empty)}-Study from {response.Dataset.GetSingleValueOrDefault(DicomTag.StudyDate, new DateTime())} with UID {response.Dataset.GetSingleValueOrDefault(DicomTag.StudyInstanceUID, string.Empty)} ");
|
||
}
|
||
if (response.Status == DicomStatus.Success)
|
||
{
|
||
Console.WriteLine(response.Status.ToString());
|
||
|
||
|
||
}
|
||
}
|
||
|
||
|
||
#endregion
|
||
|
||
|
||
private bool CEchoTest(DicomAE find, string clientAE)
|
||
{
|
||
var client = DicomClientFactory.Create(find.IP, find.Port, false, clientAE, find.CalledAE);
|
||
|
||
|
||
client.NegotiateAsyncOps();
|
||
|
||
client.ServiceOptions.RequestTimeout = TimeSpan.FromSeconds(3);
|
||
|
||
var request = new DicomCEchoRequest
|
||
{
|
||
OnResponseReceived = (req, response) =>
|
||
{
|
||
|
||
if (response.Status == DicomStatus.Success)
|
||
{
|
||
find.IsTestOK = true;
|
||
}
|
||
else
|
||
{
|
||
find.IsTestOK = false;
|
||
}
|
||
}
|
||
};
|
||
|
||
return find.IsTestOK;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取 检查列表
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <param name="_dicomAEReposiotry"></param>
|
||
/// <param name="_logger"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput<List<SCUStudyView>>> GetCFindStudyList(SCUQuery inQuery,
|
||
[FromServices] IRepository<DicomAE> _dicomAEReposiotry,
|
||
[FromServices] ILogger<PatientService> _logger)
|
||
{
|
||
|
||
var result = new List<SCUStudyView>();
|
||
|
||
var find = await _dicomAEReposiotry.FirstOrDefaultAsync(t => t.Id == inQuery.PacsDicomAEId);
|
||
|
||
var hirClient = await _dicomAEReposiotry.FirstOrDefaultAsync(t => t.PacsTypeEnum == PacsType.HIRClient);
|
||
|
||
if (hirClient == null)
|
||
{
|
||
throw new BusinessValidationFailedException(_localizer["Patient_NoPacsClientAE"]);
|
||
}
|
||
|
||
if (find != null)
|
||
{
|
||
//测试失败
|
||
if (!CEchoTest(find, hirClient.CalledAE))
|
||
{
|
||
throw new BusinessValidationFailedException(_localizer["Patient_PacsAENotOnline"]);
|
||
}
|
||
|
||
var @lock = _distributedLockProvider.CreateLock($"CFind");
|
||
|
||
|
||
var maxStudyCount = find.MaxStudyCount > 0 ? find.MaxStudyCount : 50;
|
||
|
||
var client = DicomClientFactory.Create(find.IP, find.Port, false, hirClient.CalledAE, find.CalledAE);
|
||
|
||
client.NegotiateAsyncOps();
|
||
|
||
|
||
DicomCFindRequest.ResponseDelegate responseDelegate = (req, response) =>
|
||
{
|
||
|
||
if (response.HasDataset)
|
||
{
|
||
using (@lock.Acquire())
|
||
{
|
||
if (result.Count >= maxStudyCount)
|
||
{
|
||
response.Status = DicomStatus.Cancel;
|
||
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
var studyTime = response.Dataset.GetDateTime(DicomTag.StudyDate, DicomTag.StudyTime);
|
||
|
||
DateOnly datePart = DateOnly.FromDateTime(studyTime);
|
||
TimeOnly timePart = TimeOnly.FromDateTime(studyTime);
|
||
|
||
var canParce = DateTime.TryParseExact(response.Dataset?.GetSingleValueOrDefault<string>(DicomTag.PatientBirthDate, ""), "yyyyMMdd", null, System.Globalization.DateTimeStyles.None, out DateTime birthDate);
|
||
|
||
// 格式化为你需要的日期格式,例如:yyyy-MM-dd
|
||
string formattedBirthDate = canParce ? birthDate.ToString("yyyy-MM-dd") : string.Empty;
|
||
|
||
|
||
result.Add(new SCUStudyView()
|
||
{
|
||
PatientID = response.Dataset?.GetSingleValueOrDefault<string>(DicomTag.PatientID, ""),
|
||
PatientName = response.Dataset?.GetSingleValueOrDefault<string>(DicomTag.PatientName, ""),
|
||
PatientSex = response.Dataset?.GetSingleValueOrDefault<string>(DicomTag.PatientSex, ""),
|
||
PatientBirthDate = formattedBirthDate,
|
||
StudyID = response.Dataset?.GetSingleValueOrDefault<string>(DicomTag.StudyID, ""),
|
||
AccessionNumber = response.Dataset?.GetSingleValueOrDefault<string>(DicomTag.AccessionNumber, ""),
|
||
ModalitiesInStudy = response.Dataset?.GetSingleValueOrDefault<string>(DicomTag.ModalitiesInStudy, ""),
|
||
Modality = response.Dataset?.GetSingleValueOrDefault<string>(DicomTag.Modality, ""),
|
||
StudyDate = datePart.ToString("yyyy-MM-dd"),
|
||
StudyTime = timePart.ToString("HH:mm:ss"),
|
||
BodyPartExamined = response.Dataset?.GetSingleValueOrDefault<string>(DicomTag.BodyPartExamined, ""),
|
||
StudyDescription = response.Dataset?.GetSingleValueOrDefault<string>(DicomTag.StudyDescription, ""),
|
||
StudyInstanceUID = response.Dataset?.GetSingleValueOrDefault<string>(DicomTag.StudyInstanceUID, "")
|
||
});
|
||
}
|
||
|
||
}
|
||
|
||
|
||
}
|
||
|
||
};
|
||
|
||
//判断前段有没有传递时间
|
||
|
||
if (find.PacsSearchMaxDays != 0)
|
||
{
|
||
//0 天 + 前端不传递就是不限制
|
||
inQuery.StudyDate = inQuery.StudyDate.IsNullOrEmpty() ? $"{DateTime.Now.AddDays(-(find.PacsSearchMaxDays - 1)).ToString("yyyyMMdd")}-{DateTime.Now.ToString("yyyyMMdd")}" : inQuery.StudyDate;
|
||
|
||
}
|
||
|
||
//看当前前端有没有传递modality,有的话以前端为准,没有的话以配置为准 构造同样数量的请求
|
||
var requestModalityList = (inQuery.ModalitiesInStudyList != null && inQuery.ModalitiesInStudyList.Count > 0) ? inQuery.ModalitiesInStudyList : find.ModalityList;
|
||
|
||
//if (find.IsSupportMutiModality || requestModalityList.Count > 0)
|
||
{
|
||
var modality = string.Join($"\\", requestModalityList);
|
||
|
||
var request = CreateStudyRequest(inQuery, modality);
|
||
|
||
request.OnResponseReceived += responseDelegate;
|
||
|
||
await client.AddRequestAsync(request);
|
||
}
|
||
//else
|
||
//{
|
||
|
||
// var request = CreateStudyRequest(inQuery, modality);
|
||
|
||
// request.OnResponseReceived += responseDelegate;
|
||
|
||
// await client.AddRequestAsync(request);
|
||
//}
|
||
|
||
|
||
|
||
await client.SendAsync();
|
||
|
||
|
||
var resultInstanceUidList = result.Select(t => t.StudyInstanceUID).ToList();
|
||
|
||
var existStudyIdList = _studyRepository.Where(t => resultInstanceUidList.Contains(t.StudyInstanceUid))
|
||
.Select(t => t.StudyInstanceUid).ToList();
|
||
|
||
foreach (var item in result)
|
||
{
|
||
item.IsStudyExist = existStudyIdList.Any(t => t == item.StudyInstanceUID);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
return ResponseOutput.Ok(result, find);
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 批量验证Cmove 检查在系统存在与否
|
||
/// </summary>
|
||
/// <param name="inCommand"></param>
|
||
/// <returns></returns>
|
||
public async Task<Dictionary<string, object>> CMoveVerify(SCUCmoveCommand inCommand)
|
||
{
|
||
var existStudyIdList = _studyRepository.Where(t => inCommand.StudyInstanceUIDList.Contains(t.StudyInstanceUid))
|
||
.Select(t => new { t.StudyInstanceUid, t.StudyId, PatientId = t.PatientIdStr, t.AccessionNumber, t.PatientName }).ToList();
|
||
|
||
var dic = new Dictionary<string, object>();
|
||
foreach (var item in inCommand.StudyInstanceUIDList)
|
||
{
|
||
var find = existStudyIdList.FirstOrDefault(t => t.StudyInstanceUid == item);
|
||
dic.Add(item, find == null ? string.Empty : find);
|
||
}
|
||
|
||
return dic;
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 拉取影像
|
||
/// </summary>
|
||
/// <param name="inCommand"></param>
|
||
/// <param name="_dicomAEReposiotry"></param>
|
||
/// <param name="_scpInstanceRepository"></param>
|
||
/// <param name="_basicSystemConfigConfig"></param>
|
||
/// <returns></returns>
|
||
public async Task<IResponseOutput> CmoveStudyList(SCUCmoveCommand inCommand,
|
||
[FromServices] IRepository<DicomAE> _dicomAEReposiotry,
|
||
[FromServices] IRepository<SCPInstance> _scpInstanceRepository,
|
||
[FromServices] IOptionsMonitor<ServiceVerifyConfigOption> _basicSystemConfigConfig)
|
||
{
|
||
|
||
var result = new List<SCUStudyView>();
|
||
|
||
var find = await _dicomAEReposiotry.FirstOrDefaultAsync(t => t.Id == inCommand.PacsDicomAEId);
|
||
|
||
var hirServer = await _dicomAEReposiotry.FirstOrDefaultAsync(t => t.PacsTypeEnum == PacsType.HIRServer);
|
||
|
||
var hirClient = await _dicomAEReposiotry.FirstOrDefaultAsync(t => t.PacsTypeEnum == PacsType.HIRClient);
|
||
|
||
if (hirServer == null)
|
||
{
|
||
//"未找到服务端AE配置,请核查后再拉取"
|
||
return ResponseOutput.NotOk(_localizer["Patient_NoPacsAE"]);
|
||
}
|
||
|
||
if (hirClient == null)
|
||
{
|
||
return ResponseOutput.NotOk(_localizer["Patient_NoPacsClientAE"]);
|
||
}
|
||
|
||
if (find != null)
|
||
{
|
||
DicomCMoveRequest.ResponseDelegate responseDelegate = (req, response) =>
|
||
{
|
||
if (response.Status.State == DicomState.Failure || response.Status.State == DicomState.Cancel)
|
||
{
|
||
_logger.LogError($" Cmove Pacs 返回状态: {response.Status.State} {response.SOPClassUID.ToJsonNotIgnoreNull()}");
|
||
|
||
_fusionCache.Set<string?>(CacheKeys.CmoveStudyId(req.Dataset.GetString(DicomTag.StudyInstanceUID)), null, TimeSpan.FromSeconds(1));
|
||
}
|
||
|
||
// 判断是否传输完成或中断,执行缓存清理
|
||
if (response.Status.State == DicomState.Success && response.Remaining == 0)
|
||
{
|
||
_fusionCache.Set<string?>(CacheKeys.CmoveStudyId(req.Dataset.GetString(DicomTag.StudyInstanceUID)), null, TimeSpan.FromSeconds(1));
|
||
}
|
||
};
|
||
|
||
var latestInstanceList = await _scpInstanceRepository.Where(t => inCommand.StudyInstanceUIDList.Contains(t.StudyInstanceUid))
|
||
.GroupBy(t => t.StudyInstanceUid).Select(g => g.OrderByDescending(t => t.CreateTime).FirstOrDefault()).ToListAsync();
|
||
|
||
var task = Task.Run(async () =>
|
||
{
|
||
var client = DicomClientFactory.Create(find.IP, find.Port, false, hirClient.CalledAE, find.CalledAE);
|
||
client.NegotiateAsyncOps();
|
||
|
||
var cmoveRequestList = new List<DicomCMoveRequest>();
|
||
|
||
foreach (var item in inCommand.StudyInstanceUIDList)
|
||
{
|
||
|
||
var cmoveConfig = _basicSystemConfigConfig.CurrentValue;
|
||
var exsitStudyId = await _fusionCache.GetOrDefaultAsync<string>(CacheKeys.CmoveStudyId(item), null);
|
||
|
||
var latestInstance = latestInstanceList.Where(t => t.StudyInstanceUid == item).FirstOrDefault();
|
||
|
||
//缓存不存在当前检查,或者instance表最新的记录时间与当前时间之差超过1分钟(认为完成归档,可以重复拉取)
|
||
if (exsitStudyId == null && (latestInstance == null || latestInstance?.CreateTime.AddMinutes(cmoveConfig.CmoveInstanceIntervalMinutes) < DateTime.Now))
|
||
{
|
||
await _fusionCache.SetAsync(CacheKeys.CmoveStudyId(item), item, TimeSpan.FromMinutes(cmoveConfig.CmoveIntervalMinutes));
|
||
|
||
var cmoveRequest = new DicomCMoveRequest(hirServer.CalledAE, item);
|
||
|
||
cmoveRequest.OnResponseReceived += responseDelegate;
|
||
|
||
cmoveRequestList.Add(cmoveRequest);
|
||
|
||
_logger.LogInformation($"执行 Cmove StudyInstanceUid:{item}");
|
||
|
||
}
|
||
else
|
||
{
|
||
_logger.LogInformation($"忽略 Cmove StudyInstanceUid:{item}");
|
||
|
||
}
|
||
|
||
}
|
||
|
||
await client.AddRequestsAsync(cmoveRequestList);
|
||
await client.SendAsync();
|
||
});
|
||
|
||
//await task;
|
||
|
||
}
|
||
|
||
return ResponseOutput.Ok();
|
||
}
|
||
|
||
|
||
|
||
|
||
#endregion
|
||
|
||
}
|
||
|
||
|
||
}
|