Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is running Details

Uat_IRC_Net8
he 2026-05-25 16:38:42 +08:00
commit 63e9428d6d
38 changed files with 67997 additions and 205 deletions

View File

@ -8,6 +8,7 @@ using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Infrastructure.Extention;
using IRaCIS.Core.SCP.Service;
using MassTransit;
using Medallion.Threading;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
using Microsoft.Extensions.DependencyInjection;
@ -95,7 +96,7 @@ namespace IRaCIS.Core.SCP.Service
public Task OnReceiveAssociationRequestAsync(DicomAssociation association)
{
_upload = new SCPImageUpload() { StartTime = DateTime.Now, CallingAE = association.CallingAE, CalledAE = association.CalledAE, CallingAEIP = association.RemoteHost };
_upload = new SCPImageUpload() { Id = NewId.NextSequentialGuid(), StartTime = DateTime.Now, CallingAE = association.CallingAE, CalledAE = association.CalledAE, CallingAEIP = association.RemoteHost };
Log.Logger.Warning($"接收到来自{association.CallingAE}的连接");
@ -644,7 +645,7 @@ namespace IRaCIS.Core.SCP.Service
ms.Position = 0;
//irc 从路径最后一截取Guid
storeRelativePath = await ossService.UploadToOSSAsync(ms, ossFolderPath, instanceId.ToString(), false, uploadInfo: new FileUploadRecordAddOrEdit() { TrialId = _trialId, BatchDataType = BatchDataType.PACSReceive });
storeRelativePath = await ossService.UploadToOSSAsync(ms, ossFolderPath, instanceId.ToString(), false, uploadInfo: new FileUploadRecordAddOrEdit() { TrialId = _trialId, BatchDataType = BatchDataType.PACSReceive, UploadBatchId = _upload.Id.ToString() });
fileSize = ms.Length;

View File

@ -63,6 +63,8 @@ public class FileUploadRecordAddOrEdit
public bool? IsNeedSync { get; set; }
public string UploadRegion { get; set; }
public string TargetRegion { get; set; }
public bool? IsSync { get; set; }
}
public interface IFileUploadRecordService
{
@ -113,6 +115,19 @@ public class FileUploadRecordService(IRepository<FileUploadRecord> _fileUploadRe
}
}
//SCP推送过来IP为空后端归档的设置区域
if (_userInfo.IP.IsNullOrEmpty() && _userInfo.Domain.IsNullOrEmpty())
{
var apiDefalut = ObjectStoreServiceConfig.SyncConfigList.FirstOrDefault(t => t.UploadRegion == ObjectStoreServiceConfig.ApiDeployRegion);
if (apiDefalut != null)
{
addOrEditFileUploadRecord.UploadRegion = apiDefalut.UploadRegion;
addOrEditFileUploadRecord.TargetRegion = apiDefalut.TargetRegion;
}
}
if (addOrEditFileUploadRecord.TrialId != null)
{
@ -129,9 +144,9 @@ public class FileUploadRecordService(IRepository<FileUploadRecord> _fileUploadRe
{
addOrEditFileUploadRecord.IsNeedSync = true;
addOrEditFileUploadRecord.Priority = 0;
addOrEditFileUploadRecord.Priority = addOrEditFileUploadRecord.Priority ?? 0;
addOrEditFileUploadRecord.IsSync = false;
}
else
{
@ -147,7 +162,9 @@ public class FileUploadRecordService(IRepository<FileUploadRecord> _fileUploadRe
//系统文件,默认同步
addOrEditFileUploadRecord.IsNeedSync = true;
addOrEditFileUploadRecord.Priority = 0;
addOrEditFileUploadRecord.IsSync = false;
addOrEditFileUploadRecord.Priority = addOrEditFileUploadRecord.Priority ?? 0;
}
var entity = await _fileUploadRecordRepository.InsertOrUpdateAsync(addOrEditFileUploadRecord, true);

View File

@ -194,7 +194,7 @@ public interface IOSSService
List<string> GetRootFolderNames();
public ObjectStoreDTO GetObjectStoreTempToken(string? domain = null, bool? isGetAllTempToken = null);
public ObjectStoreDTO GetObjectStoreTempToken(string? domain = null, bool? isGetAllTempToken = null, string? objectUse = null);
public Task MoveObject(string sourcePath, string destPath, bool overwrite = true);
@ -825,10 +825,12 @@ public class OSSService(IOptionsMonitor<ObjectStoreServiceOptions> options,
if (ObjectStoreServiceOptions.IsOpenStoreSync && uploadInfo != null)
{
var fileType = Path.GetExtension(returnPath).TrimStart('.');
uploadInfo.FileSize = fileStream.CanSeek ? fileStream.Length : 0;
uploadInfo.Path = returnPath;
uploadInfo.FileName = fileRealName;
uploadInfo.FileType = Path.GetExtension(returnPath);
uploadInfo.FileType = fileType.IsNullOrEmpty()?"dcm": fileType;
await _fileUploadRecordService.AddOrUpdateFileUploadRecord(uploadInfo);
@ -964,10 +966,14 @@ public class OSSService(IOptionsMonitor<ObjectStoreServiceOptions> options,
if (ObjectStoreServiceOptions.IsOpenStoreSync && uploadInfo != null)
{
var fileType = Path.GetExtension(returnPath).TrimStart('.');
uploadInfo.FileSize = fileSize;
uploadInfo.Path = returnPath;
uploadInfo.FileName = Path.GetFileName(localFilePath);
uploadInfo.FileType = Path.GetExtension(returnPath);
uploadInfo.FileType = fileType.IsNullOrEmpty() ? "dcm" : fileType;
await _fileUploadRecordService.AddOrUpdateFileUploadRecord(uploadInfo);
@ -1856,23 +1862,39 @@ public class OSSService(IOptionsMonitor<ObjectStoreServiceOptions> options,
public ObjectStoreDTO GetObjectStoreTempToken(string? domain = null, bool? isGetAllTempToken = null)
public ObjectStoreDTO GetObjectStoreTempToken(string? domain = null, bool? isGetAllTempToken = null, string? objectUse = null)
{
//如果传递了域名,并且打开了存储同步,根据域名使用的具体存储覆盖之前的配置,否则就用固定的配置
if (ObjectStoreServiceOptions.IsOpenStoreSync && domain.IsNotNullOrEmpty())
string objectStoreUse = string.Empty;
//使用指定配置
if (objectUse != null)
{
var userDomain = domain?.Trim();
var find = ObjectStoreServiceOptions.SyncConfigList.FirstOrDefault(t => t.Domain == userDomain);
if (find != null)
objectStoreUse = objectUse?.Trim() ?? string.Empty;
}
//根据域名动态判断
else
{
//如果传递了域名,并且打开了存储同步,根据域名使用的具体存储覆盖之前的配置,否则就用固定的配置
if (ObjectStoreServiceOptions.IsOpenStoreSync && domain.IsNotNullOrEmpty() && ObjectStoreServiceOptions.SyncConfigList.Any(t => t.Domain == domain))
{
ObjectStoreServiceOptions.ObjectStoreUse = find.Primary;
var find = ObjectStoreServiceOptions.SyncConfigList.FirstOrDefault(t => t.Domain == domain);
if (find != null)
{
objectStoreUse = find.Primary;
}
}
else
{
//兜底,如果是本地测试环境,那就使用部署默认配置
objectStoreUse = ObjectStoreServiceOptions.ObjectStoreUse;
}
}
var objectStoreDTO = new ObjectStoreDTO() { ObjectStoreUse = ObjectStoreServiceOptions.ObjectStoreUse, IsOpenStoreSync = ObjectStoreServiceOptions.IsOpenStoreSync, SyncConfigList = ObjectStoreServiceOptions.SyncConfigList };
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS" || isGetAllTempToken == true)
var objectStoreDTO = new ObjectStoreDTO() { ObjectStoreUse = objectStoreUse, IsOpenStoreSync = ObjectStoreServiceOptions.IsOpenStoreSync, SyncConfigList = ObjectStoreServiceOptions.SyncConfigList };
if (objectStoreUse == "AliyunOSS" || isGetAllTempToken == true)
{
var ossOptions = ObjectStoreServiceOptions.AliyunOSS;
@ -1920,11 +1942,11 @@ public class OSSService(IOptionsMonitor<ObjectStoreServiceOptions> options,
objectStoreDTO.AliyunOSS = tempToken;
}
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
if (objectStoreUse == "MinIO")
{
objectStoreDTO.MinIO = ObjectStoreServiceOptions.MinIO;
}
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS" || isGetAllTempToken == true)
if (objectStoreUse == "AWS" || isGetAllTempToken == true)
{
var awsOptions = ObjectStoreServiceOptions.AWS;
@ -1969,7 +1991,8 @@ public class OSSService(IOptionsMonitor<ObjectStoreServiceOptions> options,
objectStoreDTO.AWS = tempToken;
}
else
if (objectStoreUse.IsNullOrEmpty())
{
throw new BusinessValidationFailedException("未定义的存储介质类型");
}
@ -1980,7 +2003,7 @@ public class OSSService(IOptionsMonitor<ObjectStoreServiceOptions> options,
public async Task SyncFileAsync(string objectKey, ObjectStoreUse source, ObjectStoreUse destination, CancellationToken ct = default)
{
GetObjectStoreTempToken(isGetAllTempToken: true);
var tempConfig = GetObjectStoreTempToken(isGetAllTempToken: true);
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
@ -1999,36 +2022,76 @@ public class OSSService(IOptionsMonitor<ObjectStoreServiceOptions> options,
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
// ⭐ 关键变量
IDisposable? owner = null;
Stream sourceStream;
long contentLength;
// 根据源选择流式下载
Stream sourceStream = source switch
// ========= 获取流 + 长度 =========
switch (source)
{
ObjectStoreUse.AliyunOSS => _ossClient.GetObject(aliConfig.BucketName, objectKey).Content,
ObjectStoreUse.AWS => (await amazonS3Client.GetObjectAsync(awsConfig.BucketName, objectKey, ct)).ResponseStream,
_ => throw new BusinessValidationFailedException("未定义的同步类型")
};
case ObjectStoreUse.AliyunOSS:
{
if (source == ObjectStoreUse.AliyunOSS)
var obj = _ossClient.GetObject(
aliConfig.BucketName,
objectKey);
owner = obj;
sourceStream = obj.Content;
contentLength = obj.ContentLength;
break;
}
case ObjectStoreUse.AWS:
{
var response = await amazonS3Client.GetObjectAsync(
awsConfig.BucketName,
objectKey,
ct);
owner = response;
sourceStream = response.ResponseStream;
contentLength = response.Headers.ContentLength;
break;
}
default:
throw new BusinessValidationFailedException("未定义的同步类型");
}
try
{
var putRequest = new Amazon.S3.Model.PutObjectRequest
// ========= 上传 =========
if (destination == ObjectStoreUse.AWS)
{
BucketName = awsConfig.BucketName,
Key = objectKey,
InputStream = sourceStream
};
var putRequest = new Amazon.S3.Model.PutObjectRequest
{
BucketName = awsConfig.BucketName,
Key = objectKey,
InputStream = sourceStream,
Headers = { ContentLength = contentLength }
};
await amazonS3Client.PutObjectAsync(putRequest, ct);
await amazonS3Client.PutObjectAsync(putRequest, ct);
}
else if (destination == ObjectStoreUse.AliyunOSS)
{
_ossClient.PutObject(
aliConfig.BucketName,
objectKey,
sourceStream);
}
else
{
throw new BusinessValidationFailedException("未定义的同步类型");
}
}
else if (source == ObjectStoreUse.AWS)
finally
{
_ossClient.PutObject(aliConfig.BucketName, objectKey, sourceStream);
// ⭐⭐⭐ 真正释放 HTTP 连接
owner?.Dispose();
}
else
{
throw new BusinessValidationFailedException("未定义的同步类型");
}
await sourceStream.DisposeAsync(); // 释放流
}
}

View File

@ -0,0 +1,16 @@
using AutoMapper;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.SCP.Service;
namespace IRaCIS.Core.Application.Service
{
public class CommonConfig : Profile
{
public CommonConfig()
{
CreateMap<FileUploadRecordAddOrEdit, FileUploadRecord>().ReverseMap();
}
}
}

View File

@ -7,7 +7,28 @@
}
},
"ObjectStoreService": {
// 使
"ObjectStoreUse": "AliyunOSS",
"IsOpenStoreSync": true,
"ApiDeployRegion": "CN",
"SyncConfigList": [
{
"Domain": "irc.test.extimaging.com",
"Primary": "AliyunOSS",
"Target": "AWS",
"UploadRegion": "CN",
"TargetRegion": "US",
"IsOpenSync": true
},
{
"Domain": "lili.test.extimaging.com",
"Primary": "AWS",
"Target": "AliyunOSS",
"UploadRegion": "US",
"TargetRegion": "CN",
"IsOpenSync": true
}
],
"AliyunOSS": {
"RegionId": "cn-shanghai",
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
@ -29,6 +50,27 @@
"secretKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
"bucketName": "hir-test",
"viewEndpoint": "http://106.14.89.110:9001/hir-test/"
},
// AWS S3
"AWS": {
// AWS S3 Region
"Region": "us-east-1",
// AWS S3 访
"EndPoint": "s3.us-east-1.amazonaws.com",
// 使 SSL
"UseSSL": true,
// AWS S3 ARN
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
// AWS S3 访 ID
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
// AWS S3 访 Secret
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
// AWS S3 Bucket
"BucketName": "ei-med-s3-lili-uat-store",
// AWS S3 访
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com",
// AWS S3
"DurationSeconds": 7200
}
},

View File

@ -46,19 +46,19 @@ namespace IRaCIS.Core.API
var emailConfig = new SystemEmailSendConfig();
configuration.GetSection("SystemEmailSendConfig").Bind(emailConfig);
if (emailConfig.IsOpenErrorNoticeEmail)
{
config.WriteTo.Email(options: new Serilog.Sinks.Email.EmailSinkOptions()
{
From = emailConfig.FromEmail,
To = emailConfig.ErrorNoticeEmailList,
Host = emailConfig.Host,
Port = emailConfig.Port,
Subject = new MessageTemplateTextFormatter("Log Alert - 系统发生了异常,请核查"),
Credentials = new NetworkCredential(emailConfig.FromEmail, emailConfig.AuthorizationCode)
//if (emailConfig.IsOpenErrorNoticeEmail)
//{
// config.WriteTo.Email(options: new Serilog.Sinks.Email.EmailSinkOptions()
// {
// From = emailConfig.FromEmail,
// To = emailConfig.ErrorNoticeEmailList,
// Host = emailConfig.Host,
// Port = emailConfig.Port,
// Subject = new MessageTemplateTextFormatter("Log Alert - 系统发生了异常,请核查"),
// Credentials = new NetworkCredential(emailConfig.FromEmail, emailConfig.AuthorizationCode)
}, restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Error);
}
// }, restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Error);
//}
#endregion
Log.Logger = config.CreateLogger();

View File

@ -85,10 +85,8 @@
"CompanyShortName": "Extensive Imaging",
"CompanyShortNameCN": "展影医疗",
"IsEnv_US": false,
"IsOpenErrorNoticeEmail": false,
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
"CronEmailDefaultCulture": "zh-CN",
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
"CronEmailDefaultCulture": "zh-CN"
},
"SystemPacsConfig": {
"Port": "11113",

View File

@ -149,14 +149,15 @@
},
//
"SystemEmailSendConfig": {
// SMTP
"Port": 465,
// SMTP
"Host": "smtp.qiye.aliyun.com",
// SMTP
"Port": 465,
"Imap": "imap.qiye.aliyun.com",
"ImapPort": 993,
//
"FromEmail": "test@extimaging.com",
//
@ -166,14 +167,16 @@
// 访
"SiteUrl": "http://irc.test.extimaging.com/login",
"PlatformName": "EICS",
"PlatformNameCN": "展影云平台",
// 使
// - 使
"SystemShortName": "IRC",
//
// -
"OrganizationName": "ExtImaging",
//
"OrganizationNameCN": "ExtImaging",
"PlatformName": "EICS",
"PlatformNameCN": "展影云平台",
//
"CompanyName": "Extensive Imaging",
//
@ -182,15 +185,14 @@
"CompanyShortName": "Extensive Imaging",
//
"CompanyShortNameCN": "展影医疗",
//
// 便lili irc
"IsEnv_US": false,
//
"IsOpenErrorNoticeEmail": false,
//
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
"CronEmailDefaultCulture": "zh-CN",
//
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
//
"CronEmailDefaultCulture": "zh-CN"
},
// PACS
"SystemPacsConfig": {

View File

@ -90,10 +90,8 @@
"CompanyShortNameCN": "展影医疗",
"SiteUrl": "https://lili.elevateimaging.ai/login",
"IsEnv_US": true,
"IsOpenErrorNoticeEmail": false,
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
"CronEmailDefaultCulture": "en-US",
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
"CronEmailDefaultCulture": "en-US"
},
"SystemPacsConfig": {

View File

@ -93,9 +93,7 @@
"CompanyShortName": "Elevate Imaging",
"CompanyShortNameCN": "展影医疗",
"SiteUrl": "https://lili.test.elevateimaging.ai/login",
"IsEnv_US": true,
"IsOpenErrorNoticeEmail": false,
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
"IsEnv_US": true
},
"SystemPacsConfig": {

View File

@ -97,10 +97,8 @@
"CompanyShortNameCN": "展影医疗",
"SiteUrl": "https://lili.uat.elevateimaging.ai/login",
"IsEnv_US": true,
"IsOpenErrorNoticeEmail": false,
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
"CronEmailDefaultCulture": "en-US",
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
"CronEmailDefaultCulture": "en-US"
},
"SystemPacsConfig": {

View File

@ -19,6 +19,26 @@
"ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS",
"IsOpenStoreSync": true,
"ApiDeployRegion": "CN",
"SyncConfigList": [
{
"Domain": "irc.uat.extimaging.com",
"Primary": "AliyunOSS",
"Target": "AWS",
"UploadRegion": "CN",
"TargetRegion": "US",
"IsOpenSync": true
},
{
"Domain": "lili.uat.extimaging.com",
"Primary": "AWS",
"Target": "AliyunOSS",
"UploadRegion": "US",
"TargetRegion": "CN",
"IsOpenSync": true
}
],
"AliyunOSS": {
"RegionId": "cn-shanghai",
@ -104,10 +124,8 @@
"CompanyShortName": "Extensive Imaging",
"CompanyShortNameCN": "展影医疗",
"IsEnv_US": false,
"IsOpenErrorNoticeEmail": false,
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
"CronEmailDefaultCulture": "zh-CN",
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
"CronEmailDefaultCulture": "zh-CN"
},
"SystemPacsConfig": {

View File

@ -79,11 +79,12 @@ public class SystemEmailSendConfig
public bool IsEnv_US { get; set; }
public bool IsOpenErrorNoticeEmail { get; set; }
public string EmailRegexStr { get; set; }
public List<string> ErrorNoticeEmailList { get; set; } = new List<string>();
//public bool IsOpenErrorNoticeEmail { get; set; }
//public List<string> ErrorNoticeEmailList { get; set; } = new List<string>();
}
public class SystemEmailSendConfigView

View File

@ -566,6 +566,27 @@
<param name="options"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.Common.DeployConfigService.UpdateSystemBasicConfig(IRaCIS.Core.Domain.Share.ServiceVerifyConfigOption)">
<summary>
更新系统基础配置
</summary>
<param name="basicSystemConfigOption"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.Common.DeployConfigService.GetEmailConfigInfo(Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<summary>
获取系统邮件配置信息
</summary>
<param name="options"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.Common.DeployConfigService.UpdateSystemEmailConfig(IRaCIS.Core.Domain.Share.SystemEmailSendConfig)">
<summary>
更新系统邮件配置
</summary>
<param name="emailConfig"></param>
<returns></returns>
</member>
<member name="P:IRaCIS.Core.Application.Service.Common.TU_TR_RSBaseModel.ResearchProgramNo">
<summary>
方案编号 STUDYID
@ -15963,7 +15984,7 @@
<param name="inQuery"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.PatientService.SubmitVisitStudyBinding(IRaCIS.Application.Contracts.SubmitVisitStudyBindingCommand,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomSeries},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomInstance})">
<member name="M:IRaCIS.Core.Application.Service.PatientService.SubmitVisitStudyBinding(IRaCIS.Application.Contracts.SubmitVisitStudyBindingCommand,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomSeries},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomInstance},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.FileUploadRecord})">
<summary>
提交 患者检查和访视的绑定
</summary>
@ -16121,6 +16142,13 @@
<param name="outEnrollTime"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.TestService.SiteSuveryEquipment">
<summary>
维护中心调研设备默认配置
</summary>
<param name="modelVerify"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.TestService.MaskImage">
<summary>
遮挡影像
@ -18905,6 +18933,11 @@
受试者ID
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Contracts.DTO.TrialVisitQADTO.IsSupportQCDownloadImage">
<summary>
QC质控下载
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Contracts.DTO.QAStudyInfoDTO.PatientSex">
<summary>
性别
@ -19365,6 +19398,16 @@
检查名称列表
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Contracts.BasicTrialConfig.IsSupportQCDownloadImage">
<summary>
QC质控下载
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Contracts.BasicTrialConfig.IsOpenLostVistRead">
<summary>
打开失访可读
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Contracts.TrialProcessConfig.IsImageQualityControl">
<summary>
影像质控风险控制

View File

@ -54,8 +54,8 @@ namespace IRaCIS.Core.Application.Service
.WhereIf(inQuery.DoctorUserIdeaEnum != null, t => t.DoctorUserIdeaEnum == inQuery.DoctorUserIdeaEnum)
.WhereIf(inQuery.TrialReadingCriterionId != null, t => t.VisitTask.TrialReadingCriterionId == inQuery.TrialReadingCriterionId)
.WhereIf(inQuery.IsInvalid != null, t => t.IsInvalid == inQuery.IsInvalid)
.WhereIf(inQuery.IsHaveQuestion != null, t => t.IsHaveQuestion == inQuery.IsHaveQuestion)
.WhereIf(inQuery.IsInvalid != null, t => t.IsInvalid == inQuery.IsInvalid)
.WhereIf(inQuery.IsHaveQuestion != null, t => t.IsHaveQuestion == inQuery.IsHaveQuestion)
.WhereIf(inQuery.BeginAllocateDate != null, t => t.AllocateTime >= inQuery.BeginAllocateDate)
.WhereIf(inQuery.EndAllocateDate != null, t => t.AllocateTime <= inQuery.EndAllocateDate)
@ -211,23 +211,23 @@ namespace IRaCIS.Core.Application.Service
.WhereIf(inQuery.SubjectId != null, t => t.VisitTask.SubjectId == inQuery.SubjectId)
.WhereIf(inQuery.TrialSiteId != null, t => t.VisitTask.Subject.TrialSiteId == inQuery.TrialSiteId)
.WhereIf(inQuery.IsUrgent != null, t => t.VisitTask.IsUrgent == inQuery.IsUrgent)
.WhereIf(inQuery.AuditState != null, t => t.AuditState == inQuery.AuditState)
.WhereIf(inQuery.DoctorUserIdeaEnum != null, t => t.DoctorUserIdeaEnum == inQuery.DoctorUserIdeaEnum)
.WhereIf(inQuery.TaskState != null, t => t.VisitTask.TaskState == inQuery.TaskState)
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => t.VisitTask.Subject.Code.Contains(inQuery.SubjectCode) || t.VisitTask.Subject.MedicalNo.Contains(inQuery.SubjectCode))
.WhereIf(!string.IsNullOrEmpty(inQuery.TaskName), t => t.VisitTask.TaskName.Contains(inQuery.TaskName) || t.VisitTask.TaskBlindName.Contains(inQuery.TaskName))
.WhereIf(inQuery.AuditState != null, t => t.AuditState == inQuery.AuditState)
.WhereIf(inQuery.DoctorUserIdeaEnum != null, t => t.DoctorUserIdeaEnum == inQuery.DoctorUserIdeaEnum)
.WhereIf(inQuery.TaskState != null, t => t.VisitTask.TaskState == inQuery.TaskState)
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => t.VisitTask.Subject.Code.Contains(inQuery.SubjectCode) || t.VisitTask.Subject.MedicalNo.Contains(inQuery.SubjectCode))
.WhereIf(!string.IsNullOrEmpty(inQuery.TaskName), t => t.VisitTask.TaskName.Contains(inQuery.TaskName) || t.VisitTask.TaskBlindName.Contains(inQuery.TaskName))
.WhereIf(inQuery.DoctorUserId != null, t => t.VisitTask.DoctorUserId == inQuery.DoctorUserId)
.WhereIf(inQuery.ReadingCategory != null, t => t.VisitTask.ReadingCategory == inQuery.ReadingCategory)
.WhereIf(inQuery.ReadingTaskState != null, t => t.VisitTask.ReadingTaskState == inQuery.ReadingTaskState)
.WhereIf(inQuery.IsInvalid != null, t => t.IsInvalid == inQuery.IsInvalid)
.WhereIf(inQuery.IsInvalid != null, t => t.IsInvalid == inQuery.IsInvalid)
.WhereIf(inQuery.IsGetBeRead, x => !x.IsInvalid && x.AuditState != MedicalReviewAuditState.HaveSigned)
.WhereIf(inQuery.TrialReadingCriterionId != null, t => t.VisitTask.TrialReadingCriterionId == inQuery.TrialReadingCriterionId)
.WhereIf(inQuery.BeginAuditSignTime != null, t => t.AuditSignTime >= inQuery.BeginAuditSignTime)
.WhereIf(inQuery.EndAuditSignTime != null, t => t.AuditSignTime <= inQuery.EndAuditSignTime)
.WhereIf(inQuery.BeginAllocateDate != null, t => t.AllocateTime >= inQuery.BeginAllocateDate)
.WhereIf(inQuery.TrialReadingCriterionId != null, t => t.VisitTask.TrialReadingCriterionId == inQuery.TrialReadingCriterionId)
.WhereIf(inQuery.BeginAuditSignTime != null, t => t.AuditSignTime >= inQuery.BeginAuditSignTime)
.WhereIf(inQuery.EndAuditSignTime != null, t => t.AuditSignTime <= inQuery.EndAuditSignTime)
.WhereIf(inQuery.BeginAllocateDate != null, t => t.AllocateTime >= inQuery.BeginAllocateDate)
.WhereIf(inQuery.EndAllocateDate != null, t => t.AllocateTime <= inQuery.EndAllocateDate)
.WhereIf(inQuery.ArmEnum != null, t => t.VisitTask.ArmEnum == inQuery.ArmEnum)
.WhereIf(inQuery.ArmEnum != null, t => t.VisitTask.ArmEnum == inQuery.ArmEnum)
.WhereIf(inQuery.MedicalManagerUserId != null, t => t.MedicalManagerUserId == inQuery.MedicalManagerUserId)
.WhereIf(inQuery.BeginSignTime != null, t => t.VisitTask.SignTime > inQuery.BeginSignTime)
.WhereIf(inQuery.EndSignTime != null, t => t.VisitTask.SignTime < inQuery.EndSignTime)

View File

@ -1016,9 +1016,9 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
if (critrion.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
{
var extralObj = _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.TrialExtraConfigJsonStr }).FirstOrDefault();
var extralObj = _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.IsOpenLostVistRead }).FirstOrDefault();
var extralConfig = JsonConvert.DeserializeObject<TrialExtraConfig>(extralObj?.TrialExtraConfigJsonStr) ?? new TrialExtraConfig();
//var extralConfig = JsonConvert.DeserializeObject<TrialExtraConfig>(extralObj?.TrialExtraConfigJsonStr) ?? new TrialExtraConfig();
var visitQuery = _visitTaskRepository.Where(x => x.TrialId == inQuery.TrialId && x.DoctorUserId == _userInfo.UserRoleId && x.TaskState == TaskState.Effect && x.Subject.IsSubjectQuit == false)
@ -1027,7 +1027,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
.WhereIf(critrion.IsAutoCreate == false, t => !t.Subject.SubjectCriteriaEvaluationVisitFilterList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId).Any(f => f.IsGeneratedTask == false && t.VisitTaskNum > f.SubjectVisit.VisitNum))
// 前序 不存在 未一致性核查未通过的
.Where(t => !t.Subject.SubjectVisitList.Where(t => extralConfig.IsOpenLostVistRead ? t.IsLostVisit == false : true).Any(sv => sv.CheckState != CheckStateEnum.CVPassed && t.VisitTaskNum >= sv.VisitNum))
.Where(t => !t.Subject.SubjectVisitList.Where(t => extralObj.IsOpenLostVistRead ? t.IsLostVisit == false : true).Any(sv => sv.CheckState != CheckStateEnum.CVPassed && t.VisitTaskNum >= sv.VisitNum))
//.WhereIf(critrion.IsAutoCreate == false, t => t.Subject.SubjectCriteriaEvaluationVisitFilterList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId).Any(t => t.IsGeneratedTask == false) ?
//t.VisitTaskNum <= t.Subject.SubjectCriteriaEvaluationVisitFilterList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId && t.IsGeneratedTask == false).Min(t => t.SubjectVisit.VisitNum) : true)
//.Where(t => t.Subject.SubjectVisitList.Any(t => t.CheckState != CheckStateEnum.CVPassed) ? t.VisitTaskNum <= t.Subject.SubjectVisitList.Where(t => t.CheckState != CheckStateEnum.CVPassed).Min(t => t.VisitNum) : true)
@ -1050,14 +1050,14 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
UnReadTaskCount = x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned).Count(),
//未读 里可读任务量
UnReadCanReadTaskCount = x.Where(t => extralConfig.IsOpenLostVistRead ? true : t.IsFrontTaskNeedSignButNotSign == false).Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned && (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true)
UnReadCanReadTaskCount = x.Where(t => extralObj.IsOpenLostVistRead ? true : t.IsFrontTaskNeedSignButNotSign == false).Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned && (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true)
//不能对包含聚合或子查询的表达式执行聚合函数
//&& !x.Any(t => t.ReadingTaskState != ReadingTaskState.HaveSigned && t.IsNeedClinicalDataSign == true && t.IsClinicalDataSign == false && t.VisitTaskNum<y.VisitTaskNum )
).Count(),
UnReadCanReadTaskList = x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned)
.Where(t => extralConfig.IsOpenLostVistRead ? true : t.IsFrontTaskNeedSignButNotSign == false)
.Where(t => extralObj.IsOpenLostVistRead ? true : t.IsFrontTaskNeedSignButNotSign == false)
.Where(y => /*y.IsFrontTaskNeedSignButNotSign == false &&*/ (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true))
.OrderBy(x => x.VisitTaskNum)
.Select(u => new IRUnreadTaskView()

View File

@ -13,64 +13,118 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.Service.Common
namespace IRaCIS.Core.Application.Service.Common;
[ApiExplorerSettings(GroupName = "Common")]
public class DeployConfigService(IMapper _mapper, IUserInfo _userInfo, IWebHostEnvironment _hostEnvironment, IStringLocalizer _localizer, IFusionCache _fusionCache) : BaseService
{
public class DeployConfigService(IMapper _mapper, IUserInfo _userInfo, IWebHostEnvironment _hostEnvironment, IStringLocalizer _localizer, IFusionCache _fusionCache) : BaseService
/// <summary>
/// 获取系统基础配置信息
/// </summary>
/// <param name="options"></param>
/// <returns></returns>
public async Task<ServiceVerifyConfigOption> GetSystemBasicConfigInfo([FromServices] IOptionsMonitor<ServiceVerifyConfigOption> options)
{
/// <summary>
/// 获取系统基础配置信息
/// </summary>
/// <param name="options"></param>
/// <returns></returns>
public async Task<ServiceVerifyConfigOption> GetSystemBasicConfigInfo([FromServices] IOptionsMonitor<ServiceVerifyConfigOption> options)
{
return options.CurrentValue;
}
[HttpPost]
public async Task<IResponseOutput> UpdateSystemBasicConfig(ServiceVerifyConfigOption basicSystemConfigOption)
{
var path = $"appsettings.{_hostEnvironment.EnvironmentName}.json";
string text = System.IO.File.ReadAllText(path);
// 修改
JObject obj = JObject.Parse(text);
// QCRiskControl 相关配置
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.QCRiskControl)] = basicSystemConfigOption.QCRiskControl;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.OpenUserComplexPassword)] = basicSystemConfigOption.OpenUserComplexPassword;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.OpenSignDocumentBeforeWork)] = basicSystemConfigOption.OpenSignDocumentBeforeWork;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.OpenTrialRelationDelete)] = basicSystemConfigOption.OpenTrialRelationDelete;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.OpenLoginLimit)] = basicSystemConfigOption.OpenLoginLimit;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.LoginMaxFailCount)] = basicSystemConfigOption.LoginMaxFailCount;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.LoginFailLockMinutes)] = basicSystemConfigOption.LoginFailLockMinutes;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.AutoLoginOutMinutes)] = basicSystemConfigOption.AutoLoginOutMinutes;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.OpenLoginMFA)] = basicSystemConfigOption.OpenLoginMFA;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.ContinuousReadingTimeMin)] = basicSystemConfigOption.ContinuousReadingTimeMin;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.ReadingRestTimeMin)] = basicSystemConfigOption.ReadingRestTimeMin;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.IsNeedChangePassWord)] = basicSystemConfigOption.IsNeedChangePassWord;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.ChangePassWordDays)] = basicSystemConfigOption.ChangePassWordDays;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.TemplateType)] = ((int)basicSystemConfigOption.TemplateType).ToString(); // 枚举需要转换为字符串
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.ThirdPdfUrl)] = basicSystemConfigOption.ThirdPdfUrl;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.UserMFAVerifyMinutes)] = basicSystemConfigOption.UserMFAVerifyMinutes;
// 重新写入appsettings.json
string result = obj.ToString();
System.IO.File.WriteAllText(path, result);
return ResponseOutput.Ok();
}
public async Task<SystemEmailSendConfig> GetEmailConfigInfo([FromServices] IOptionsMonitor<SystemEmailSendConfig> options)
{
return options.CurrentValue;
}
return options.CurrentValue;
}
/// <summary>
/// 更新系统基础配置
/// </summary>
/// <param name="basicSystemConfigOption"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> UpdateSystemBasicConfig(ServiceVerifyConfigOption basicSystemConfigOption)
{
var path = $"appsettings.{_hostEnvironment.EnvironmentName}.json";
string text = System.IO.File.ReadAllText(path);
// 修改
JObject obj = JObject.Parse(text);
// QCRiskControl 相关配置
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.QCRiskControl)] = basicSystemConfigOption.QCRiskControl;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.OpenUserComplexPassword)] = basicSystemConfigOption.OpenUserComplexPassword;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.OpenSignDocumentBeforeWork)] = basicSystemConfigOption.OpenSignDocumentBeforeWork;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.OpenTrialRelationDelete)] = basicSystemConfigOption.OpenTrialRelationDelete;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.OpenLoginLimit)] = basicSystemConfigOption.OpenLoginLimit;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.LoginMaxFailCount)] = basicSystemConfigOption.LoginMaxFailCount;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.LoginFailLockMinutes)] = basicSystemConfigOption.LoginFailLockMinutes;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.AutoLoginOutMinutes)] = basicSystemConfigOption.AutoLoginOutMinutes;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.OpenLoginMFA)] = basicSystemConfigOption.OpenLoginMFA;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.ContinuousReadingTimeMin)] = basicSystemConfigOption.ContinuousReadingTimeMin;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.ReadingRestTimeMin)] = basicSystemConfigOption.ReadingRestTimeMin;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.IsNeedChangePassWord)] = basicSystemConfigOption.IsNeedChangePassWord;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.ChangePassWordDays)] = basicSystemConfigOption.ChangePassWordDays;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.TemplateType)] = ((int)basicSystemConfigOption.TemplateType); // 枚举需要转换为字符串
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.ThirdPdfUrl)] = basicSystemConfigOption.ThirdPdfUrl;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.UserMFAVerifyMinutes)] = basicSystemConfigOption.UserMFAVerifyMinutes;
// 重新写入appsettings.json
string result = obj.ToString();
System.IO.File.WriteAllText(path, result);
return ResponseOutput.Ok();
}
/// <summary>
/// 获取系统邮件配置信息
/// </summary>
/// <param name="options"></param>
/// <returns></returns>
public async Task<SystemEmailSendConfig> GetEmailConfigInfo([FromServices] IOptionsMonitor<SystemEmailSendConfig> options)
{
return options.CurrentValue;
}
/// <summary>
/// 更新系统邮件配置
/// </summary>
/// <param name="emailConfig"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> UpdateSystemEmailConfig(SystemEmailSendConfig emailConfig)
{
var path = $"appsettings.{_hostEnvironment.EnvironmentName}.json";
string text = System.IO.File.ReadAllText(path);
// 修改
JObject obj = JObject.Parse(text);
// SystemEmailSendConfig 相关配置
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.Port)] = emailConfig.Port;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.Host)] = emailConfig.Host;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.Imap)] = emailConfig.Imap;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.ImapPort)] = emailConfig.ImapPort;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.FromEmail)] = emailConfig.FromEmail;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.FromName)] = emailConfig.FromName;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.AuthorizationCode)] = emailConfig.AuthorizationCode;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.SiteUrl)] = emailConfig.SiteUrl;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.PlatformName)] = emailConfig.PlatformName;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.PlatformNameCN)] = emailConfig.PlatformNameCN;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.SystemShortName)] = emailConfig.SystemShortName;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.OrganizationName)] = emailConfig.OrganizationName;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.OrganizationNameCN)] = emailConfig.OrganizationNameCN;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.CompanyName)] = emailConfig.CompanyName;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.CompanyNameCN)] = emailConfig.CompanyNameCN;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.CompanyShortName)] = emailConfig.CompanyShortName;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.CompanyShortNameCN)] = emailConfig.CompanyShortNameCN;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.IsEnv_US)] = emailConfig.IsEnv_US;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.EmailRegexStr)] = emailConfig.EmailRegexStr;
// 重新写入appsettings.json
string result = obj.ToString();
System.IO.File.WriteAllText(path, result);
return ResponseOutput.Ok();
}
}

View File

@ -138,7 +138,7 @@ namespace IRaCIS.Core.Application.Service
var isNeedSend = true;
//手动发送的时候,也有可能答案是是 此时是 这里不发送,发送已经生成的文件
if (answer == "是" && isHandSend == null)
if ((answer == "是" || answer == "Yes") && isHandSend == null)
{
isNeedSend = true;
@ -1183,7 +1183,7 @@ x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.LesionNumber && x.Readi
/// <param name="userWorkLanguage"></param>
/// <returns></returns>
/// <exception cref="BusinessValidationFailedException"></exception>
private async Task<string> TranslatePdStateAsync(Guid visitTaskId, ReadingCategory readingCategory, CriterionType criterionType, UserWorkLanguage userWorkLanguage, bool? IsGlobalGenerate = null )
private async Task<string> TranslatePdStateAsync(Guid visitTaskId, ReadingCategory readingCategory, CriterionType criterionType, UserWorkLanguage userWorkLanguage, bool? IsGlobalGenerate = null)
{
var answer = string.Empty;

View File

@ -263,6 +263,12 @@ namespace IRaCIS.Core.Application.Contracts.DTO
public class TrialVisitQADTO
{
/// <summary>
/// QC质控下载
/// </summary>
public bool IsSupportQCDownloadImage { get; set; } = false;
public bool ExistsManual { get; set; }
public bool IsHaveStudyClinicalData { get; set; }
public bool QCRiskControl { get; set; }

View File

@ -421,6 +421,7 @@ namespace IRaCIS.Core.Application.Image.QA
List<SecondReviewDto> secondReviewList = new List<SecondReviewDto>();
var isSupportQCImageDownload = _trialRepository.Where(t => t.Id == sv.TrialId).Select(t => t.IsSupportQCDownloadImage).FirstOrDefault();
if (sv.SecondReviewState != SecondReviewState.None)
{
@ -459,6 +460,7 @@ namespace IRaCIS.Core.Application.Image.QA
return new TrialVisitQADTO
{
IsSupportQCDownloadImage = isSupportQCImageDownload,
QCQuestionAnswerList = qacheckList,
QCRiskControl = _verifyConfig.CurrentValue.QCRiskControl,
SecondReviewList = secondReviewList,
@ -776,7 +778,7 @@ namespace IRaCIS.Core.Application.Image.QA
var query = _inspectionFileRepository.Where(t => t.TrialId == inQuery.TrialId && (t.CheckState == EDCCheckState.Success || t.CheckState == EDCCheckState.Failed))
.ProjectTo<GetUserUploadFileDto>(_mapper.ConfigurationProvider);
return await query.ToPagedListAsync(inQuery,nameof(GetUserUploadFileDto.CreateTime));
return await query.ToPagedListAsync(inQuery, nameof(GetUserUploadFileDto.CreateTime));
}

View File

@ -1111,12 +1111,12 @@ namespace IRaCIS.Core.Application.Image.QA
var visit = await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId);
var isExistStudyClinicalData = await _clinicalDataTrialSetRepository.AnyAsync(t => t.TrialId == visit.TrialId && t.ClinicalDataLevel == ClinicalLevel.Study&&t.IsConfirm&&t.IsApply);
if(isExistStudyClinicalData)
var isExistStudyClinicalData = await _clinicalDataTrialSetRepository.AnyAsync(t => t.TrialId == visit.TrialId && t.ClinicalDataLevel == ClinicalLevel.Study && t.IsConfirm && t.IsApply);
if (isExistStudyClinicalData)
{
List<string> modalitieTypes = new List<string>() { "PT、CT", "CT、PT", "PET-CT" };
var studyList=await _dicomStudyRepository.Where(t => t.SubjectVisitId == subjectVisitId&& modalitieTypes.Contains(t.Modalities)).ProjectTo<QAStudyInfoDTO>(_mapper.ConfigurationProvider).ToListAsync();
var studyList = await _dicomStudyRepository.Where(t => t.SubjectVisitId == subjectVisitId && modalitieTypes.Contains(t.Modalities)).ProjectTo<QAStudyInfoDTO>(_mapper.ConfigurationProvider).ToListAsync();
if (studyList.Any(x => x.IsHasEmptyPatientInfo))
{
return ResponseOutput.NotOk(_localizer["QCOperation_IsHasEmptyPatientInfo"]);
@ -1189,7 +1189,7 @@ namespace IRaCIS.Core.Application.Image.QA
await _scpStudyRepository.BatchUpdateNoTrackingAsync(t => t.Id == id, u => new SCPStudy() { SubjectVisitId = null });
if (fisrtPath.IsNotNullOrEmpty())
if (fisrtPath.IsNotNullOrEmpty() && study.IsFromPACS == false)
{
var prefix = fisrtPath.Substring(1, fisrtPath.LastIndexOf('/') - 1);
@ -1230,7 +1230,7 @@ namespace IRaCIS.Core.Application.Image.QA
string cacheKey = CacheKeys.UserQCSkipTask(_userInfo.UserRoleId);
await _fusionCache.SetAsync(cacheKey, new List<Guid>(), TimeSpan.FromMinutes(60));
return ResponseOutput.Ok();
@ -1393,12 +1393,12 @@ namespace IRaCIS.Core.Application.Image.QA
// 获取当前缓存中的访视Id集合如果没有则创建空集合
var skippedVisits = await _fusionCache.GetOrDefaultAsync<List<Guid>>(CacheKeys.UserQCSkipTask(_userInfo.UserRoleId), new List<Guid>() { });
var skippedVisits = await _fusionCache.GetOrDefaultAsync<List<Guid>>(CacheKeys.UserQCSkipTask(_userInfo.UserRoleId), new List<Guid>() { });
//跳过当前访视
if (inDto.IsSkipCurrentVisit)
{
skippedVisits.Add(inDto.SubjectVisitId);
currentActionList = currentActionList.Where(t => !skippedVisits.Contains(t.SubjectVisitId)).ToList();
}
@ -1449,7 +1449,7 @@ namespace IRaCIS.Core.Application.Image.QA
//跳过当前访视
if (inDto.IsSkipCurrentVisit)
{
{
visitList = visitList.Where(t => !skippedVisits.Contains(t.SubjectVisitId)).ToList();
}

View File

@ -6,17 +6,9 @@
namespace IRaCIS.Core.Application.Contracts
{
/// <summary> TrialSiteEquipmentSurveyView 列表视图模型 </summary>
public class TrialSiteEquipmentSurveyView
public class TrialSiteEquipmentSurveyView: TrialSiteEquipmentSurveyAddOrEdit
{
public Guid Id { get; set; }
public Guid TrialSiteSurveyId { get; set; }
public string EquipmentType { get; set; } = string.Empty;
public Guid? EquipmentTypeId { get; set; }
public string Parameters { get; set; } = string.Empty;
public string ManufacturerName { get; set; } = string.Empty;
public string ScannerType { get; set; } = string.Empty;
public string Note { get; set; } = string.Empty;
public DateTime CreateTime { get; set; }
public Guid CreateUserId { get; set; }
public DateTime UpdateTime { get; set; }
@ -56,6 +48,36 @@ namespace IRaCIS.Core.Application.Contracts
public string ManufacturerName { get; set; } = string.Empty;
public string ScannerType { get; set; } = string.Empty;
public string Note { get; set; } = string.Empty;
[Comment("扫描设备-New")]
public int? EquipmentTypeEnum { get; set; }
public string OtherEquipmentType { get; set; }
[Comment("扫描设备厂商")]
public int? ManufacturerType { get; set; }
[Comment("磁场强度 (1.5T / 3.0T)")]
public int? MagneticFieldStrengthType { get; set; }
[Comment("体部线圈通道数 (≥16 或 16)")]
public int? BodyCoilChannelCount { get; set; }
[Comment("是否具备专用的PDFF脂肪定量序列CSE-MRI序列")]
public bool? HasDedicatedPdfFatQuantificationSequence { get; set; }
[Comment("专用的PDFF脂肪定量序列类型 (当 HasDedicatedPdfFatQuantificationSequence = true 时有效)")]
public int? PdfFatQuantificationSequenceType { get; set; }
[Comment("其他序列详细说明 (当 PdfFatQuantificationSequenceType = Other 时建议填写)")]
public string OtherSequenceSpecification { get; set; }
[Comment("是否包含 T2/R2 校正(用于铁沉积校正)")]
public bool? HasT2R2Correction { get; set; }
[Comment("是否可完整导出 PDFF 参数图及全部原始 DICOM 数据")]
public bool? CanFullyExportPdfParameterMapsAndRawDicom { get; set; }
}

View File

@ -678,7 +678,7 @@ namespace IRaCIS.Core.Application.Contracts
if (currentLatest.Email != userInfo.ReplaceUserEmailOrPhone)
{
//---该中心不存在该交接人的中心调研记录表,不允许选择更新。
return ResponseOutput.NotOk(_localizer["TrialSiteSurvey_NoRecordToUpdate"]);
return ResponseOutput.NotOk(_localizer["TrialSiteSurvey_NoRecordToUpdate", currentLatest.Email]);
}

View File

@ -39,8 +39,7 @@ namespace IRaCIS.Core.Application.AutoMapper
//列表
CreateMap<TrialSiteEquipmentSurvey, TrialSiteEquipmentSurveyView>()
.ForMember(t => t.EquipmentType, u => u.MapFrom(d => isEn_Us ? d.EquipmentType.Value : d.EquipmentType.ValueCN));
CreateMap<TrialSiteEquipmentSurvey, TrialSiteEquipmentSurveyView>();

View File

@ -87,6 +87,17 @@ namespace IRaCIS.Core.Application.Contracts
public List<TrialObjectNameConfig> TrialObjectNameList { get; set; }
/// <summary>
/// QC质控下载
/// </summary>
public bool IsSupportQCDownloadImage { get; set; } = false;
/// <summary>
/// 打开失访可读
/// </summary>
public bool IsOpenLostVistRead { get; set; } = true;
}
public class ConfigTrialProcessInfoVerificationInDto

View File

@ -243,11 +243,16 @@ namespace IRaCIS.Application.Contracts
}
public class TrialExtraConfig
{
#region QC 影像下载
#region QC 影像下载--下个版本删除
//QC质控
//QC质控下载
public bool IsSupportQCDownloadImage { get; set; } = false;
/// <summary>
/// 打开失访可读
/// </summary>
public bool IsOpenLostVistRead { get; set; } = true;
#endregion
@ -260,20 +265,19 @@ namespace IRaCIS.Application.Contracts
public List<SiteSurveyModifyFiled> ModifyFiledList { get; set; } = new List<SiteSurveyModifyFiled>();
public List<SiteSurveyEquipmentField> EquipmentControlFieldList { get; set; } = new List<SiteSurveyEquipmentField>();
#endregion
/// <summary>
/// 打开失访可读
/// </summary>
public bool IsOpenLostVistRead { get; set; } = true;
}
public class TrialConfigInfo: TrialExtraConfig
public class TrialConfigInfo : TrialExtraConfig
{
#region 视图模型返回 项目术语配置 ,实际数据库没有配置
public List<TrialObjectNameConfig> TrialObjectNameList { get; set; }
@ -311,6 +315,14 @@ namespace IRaCIS.Application.Contracts
}
public class SiteSurveyEquipmentField
{
public string FiledName { get; set; }
public int ShowOrder { get; set; }
public bool IsView { get; set; }
}
}

View File

@ -255,6 +255,28 @@ namespace IRaCIS.Core.Application.Service
trial.IsConfigureEmail = true;
#endregion
#region 中心调研默认值
var trialExtalConfig = new TrialExtraConfig()
{
EquipmentControlFieldList = new List<SiteSurveyEquipmentField> {
new SiteSurveyEquipmentField() { FiledName = "EquipmentTypeEnum", ShowOrder = 0, IsView = true },
new SiteSurveyEquipmentField() { FiledName = "OtherEquipmentType", ShowOrder = 1, IsView = true },
new SiteSurveyEquipmentField() { FiledName = "Parameters", ShowOrder = 2, IsView = true },
new SiteSurveyEquipmentField() { FiledName = "ManufacturerType", ShowOrder = 3, IsView = true },
new SiteSurveyEquipmentField() { FiledName = "ManufacturerName", ShowOrder = 4, IsView = true },
new SiteSurveyEquipmentField() { FiledName = "ScannerType", ShowOrder = 5, IsView = true },
new SiteSurveyEquipmentField() { FiledName = "Note", ShowOrder = 6, IsView = true },
}
};
trial.TrialExtraConfigJsonStr = trialExtalConfig.ToJsonStr();
#endregion
//如果是PM 则需要将该人员添加到 运维人员表
//添加运维人员PM
await _trialIdentityUserRepository.AddAsync(new TrialIdentityUser()
@ -341,7 +363,7 @@ namespace IRaCIS.Core.Application.Service
trial.EmailFromName = $"{_systemEmailConfig.FromName}-{trial.TrialCode}";
trial.UpdateTime = DateTime.Now;
var success = await _trialRepository.SaveChangesAsync();

View File

@ -5,6 +5,7 @@ using IRaCIS.Core.Application.Contracts.Dicom.DTO;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure;
using MassTransit;
using Microsoft.AspNetCore.Mvc;
using Pipelines.Sockets.Unofficial.Arenas;
using System.Linq.Dynamic.Core;
@ -42,7 +43,7 @@ namespace IRaCIS.Core.Application.Service
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,t.FileSize }).ToListAsync();//.GroupBy(u => u.SeriesId);
.Select(t => new { t.SeriesId, t.Id, t.Path, t.NumberOfFrames, t.InstanceNumber, t.FileSize }).ToListAsync();//.GroupBy(u => u.SeriesId);
foreach (var series in seriesList)
{
@ -55,7 +56,7 @@ namespace IRaCIS.Core.Application.Service
//HtmlPath = string.Empty,
Path = k.Path,
InstanceNumber = k.InstanceNumber,
FileSize=k.FileSize,
FileSize = k.FileSize,
}).ToList();
}
@ -378,11 +379,12 @@ namespace IRaCIS.Core.Application.Service
/// <returns></returns>
[HttpPost]
[UnitOfWork]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task<IResponseOutput> SubmitVisitStudyBinding(SubmitVisitStudyBindingCommand inCommand,
[FromServices] IRepository<DicomStudy> _dicomstudyRepository,
[FromServices] IRepository<DicomSeries> _dicomSeriesRepository,
[FromServices] IRepository<DicomInstance> _dicomInstanceRepository)
[FromServices] IRepository<DicomInstance> _dicomInstanceRepository,
[FromServices] IRepository<FileUploadRecord> _fileUploadRecordRepository)
{
//这里要做校验 + 同时验证本地系统里面的影像是否存在pacs推过来的
@ -403,11 +405,14 @@ namespace IRaCIS.Core.Application.Service
var subjectVisitId = inCommand.SubjectVisitId;
var trialId = inCommand.TrialId;
var studyCode = "";
var studyUid = "";
var @lock = _distributedLockProvider.CreateLock($"StudyCode");
using (await @lock.AcquireAsync())
{
var dbStudyCodeIntMax = _dicomStudyRepository.Where(s => s.TrialId == inCommand.TrialId).Select(t => t.Code).DefaultIfEmpty().Max();
var dbStudyCodeIntMax = _trialRepository.Where(s => s.Id == trialId, ignoreQueryFilters: true).Select(t => t.MaxDicomCode).DefaultIfEmpty().Max();
int currentNextCodeInt = dbStudyCodeIntMax + 1;
@ -430,6 +435,8 @@ namespace IRaCIS.Core.Application.Service
newStuty.SubjectId = subjectId;
newStuty.SubjectVisitId = subjectVisitId;
studyCode = newStuty.StudyCode;
await _dicomStudyRepository.AddAsync(newStuty);
@ -457,12 +464,22 @@ namespace IRaCIS.Core.Application.Service
}
await _dicomInstanceRepository.AddRangeAsync(newInstanceList);
//回更StudyCode
await _fileUploadRecordRepository.BatchUpdateNoTrackingAsync(t => t.TrialId == trialId && t.Path.Contains(newStuty.StudyInstanceUid), u => new FileUploadRecord() { StudyCode = studyCode, SubjectId = newStuty.SubjectId, SubjectVisitId = newStuty.SubjectVisitId });
await _trialRepository.BatchUpdateNoTrackingAsync(t => t.Id == trialId, u => new Trial() { MaxDicomCode = currentNextCodeInt });
await _scpPatientRepository.BatchUpdateNoTrackingAsync(t => t.Id == find.SCPStudy.PatientId, u => new SCPPatient() { SubjectId = subjectId });
await _scpStudyRepository.BatchUpdateNoTrackingAsync(t => t.Id == scpStudyId, u => new SCPStudy() { SubjectVisitId = subjectVisitId });
}
currentNextCodeInt++;
await _scpPatientRepository.BatchUpdateNoTrackingAsync(t => t.Id == find.SCPStudy.PatientId, u => new SCPPatient() { SubjectId = subjectId });
await _scpStudyRepository.BatchUpdateNoTrackingAsync(t => t.Id == scpStudyId, u => new SCPStudy() { SubjectVisitId = subjectVisitId });
}
@ -549,6 +566,10 @@ namespace IRaCIS.Core.Application.Service
}
}
//回更StudyCode
await _fileUploadRecordRepository.BatchUpdateNoTrackingAsync(t => t.TrialId == trialId && t.Path.Contains(study.StudyInstanceUid), u => new FileUploadRecord() { StudyCode = studyCode, SubjectId = study.SubjectId, SubjectVisitId = study.SubjectVisitId });
await _scpPatientRepository.BatchUpdateNoTrackingAsync(t => t.Id == scpStudy.PatientId, u => new SCPPatient() { SubjectId = subjectId });
await _scpStudyRepository.BatchUpdateNoTrackingAsync(t => t.Id == scpStudyId, u => new SCPStudy() { SubjectVisitId = subjectVisitId });
}

View File

@ -33,6 +33,7 @@ using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MiniExcelLibs;
using Minio.DataModel;
using Newtonsoft.Json;
using NPOI.SS.Formula.Functions;
using NPOI.XWPF.UserModel;
using SharpCompress.Common;
@ -107,6 +108,70 @@ namespace IRaCIS.Core.Application.Service
public DateTime? DateTimeNUllValue { get; set; }
}
/// <summary>
/// 维护中心调研设备默认配置
/// </summary>
/// <param name="modelVerify"></param>
/// <returns></returns>
[AllowAnonymous]
[HttpPost("{email}")]
public async Task<IResponseOutput> SiteSuveryEquipment()
{
//默认配置
var trialExtalConfig = new TrialExtraConfig()
{
EquipmentControlFieldList = new List<SiteSurveyEquipmentField> {
new SiteSurveyEquipmentField() { FiledName = "EquipmentTypeEnum", ShowOrder = 0, IsView = true },
new SiteSurveyEquipmentField() { FiledName = "OtherEquipmentType", ShowOrder = 1, IsView = true },
new SiteSurveyEquipmentField() { FiledName = "Parameters", ShowOrder = 2, IsView = true },
new SiteSurveyEquipmentField() { FiledName = "ManufacturerType", ShowOrder = 3, IsView = true },
new SiteSurveyEquipmentField() { FiledName = "ManufacturerName", ShowOrder = 4, IsView = true },
new SiteSurveyEquipmentField() { FiledName = "ScannerType", ShowOrder = 5, IsView = true },
new SiteSurveyEquipmentField() { FiledName = "Note", ShowOrder = 6, IsView = true },
}
};
var list = _trialRepository.Where(t => t.TrialExtraConfigJsonStr != "").Select(t => new { t.Id, t.TrialExtraConfigJsonStr }).ToList();
foreach (var item in list)
{
var extralConfig = JsonConvert.DeserializeObject<TrialExtraConfig>(item.TrialExtraConfigJsonStr);
if (extralConfig.ModifyFiledList.Count > 0)
{
extralConfig.EquipmentControlFieldList = trialExtalConfig.EquipmentControlFieldList.Where(t => t.ShowOrder != 2).ToList();
}
else
{
extralConfig.EquipmentControlFieldList = trialExtalConfig.EquipmentControlFieldList;
}
var jsonInfo = extralConfig.ToJsonStr();
await _trialRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Id, u => new Trial() { TrialExtraConfigJsonStr = jsonInfo });
}
var info = trialExtalConfig.ToJsonStr();
var idQuery = _trialRepository.Where(t => t.TrialExtraConfigJsonStr == "").Select(t => t.Id);
await _trialRepository.BatchUpdateNoTrackingAsync(t => idQuery.Contains(t.Id), u => new Trial() { TrialExtraConfigJsonStr = info });
return ResponseOutput.Ok();
}
//创建一个模型验证的方法
[AllowAnonymous]

View File

@ -14,12 +14,52 @@ public class TrialSiteEquipmentSurvey : BaseFullAuditEntity
#endregion
public Guid TrialSiteSurveyId { get; set; }
[Comment("扫描设备-废弃")]
public Guid EquipmentTypeId { get; set; }
[Comment("扫描设备参数")]
public string Parameters { get; set; } = string.Empty;
[Comment("扫描设备厂商其他补充")]
public string ManufacturerName { get; set; } = string.Empty;
[Comment("扫描设备型号")]
public string ScannerType { get; set; } = string.Empty;
public string Note { get; set; } = string.Empty;
#region 新增
[Comment("扫描设备-New")]
public int EquipmentTypeEnum { get; set; }
public string OtherEquipmentType { get; set; }
[Comment("扫描设备厂商")]
public int? ManufacturerType { get; set; }
[Comment("磁场强度 (1.5T / 3.0T)")]
public int? MagneticFieldStrengthType { get; set; }
[Comment("体部线圈通道数 (≥16 或 16)")]
public int? BodyCoilChannelCount { get; set; }
[Comment("是否具备专用的PDFF脂肪定量序列CSE-MRI序列")]
public bool? HasDedicatedPdfFatQuantificationSequence { get; set; }
[Comment("专用的PDFF脂肪定量序列类型 (当 HasDedicatedPdfFatQuantificationSequence = true 时有效)")]
public int? PdfFatQuantificationSequenceType { get; set; }
[Comment("其他序列详细说明 (当 PdfFatQuantificationSequenceType = Other 时建议填写)")]
public string OtherSequenceSpecification { get; set; }
[Comment("是否包含 T2/R2 校正(用于铁沉积校正)")]
public bool? HasT2R2Correction { get; set; }
[Comment("是否可完整导出 PDFF 参数图及全部原始 DICOM 数据")]
public bool? CanFullyExportPdfParameterMapsAndRawDicom { get; set; }
#endregion
}

View File

@ -324,6 +324,16 @@ public partial class Trial : BaseFullDeleteAuditEntity
[Comment("最大的NoneDicom检查编号 整型")]
public int MaxNoneDicomCode { get; set; }
/// <summary>
/// QC质控下载
/// </summary>
public bool IsSupportQCDownloadImage { get; set; } = false;
/// <summary>
/// 打开失访可读
/// </summary>
public bool IsOpenLostVistRead { get; set; } = true;
}
public enum TrialDataStore

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,223 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace IRaCIS.Core.Infra.EFCore.Migrations
{
/// <inheritdoc />
public partial class SiteSurveyEquipmentModify : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "ScannerType",
table: "TrialSiteEquipmentSurvey",
type: "nvarchar(400)",
maxLength: 400,
nullable: false,
comment: "扫描设备型号",
oldClrType: typeof(string),
oldType: "nvarchar(400)",
oldMaxLength: 400);
migrationBuilder.AlterColumn<string>(
name: "Parameters",
table: "TrialSiteEquipmentSurvey",
type: "nvarchar(400)",
maxLength: 400,
nullable: false,
comment: "扫描设备参数",
oldClrType: typeof(string),
oldType: "nvarchar(400)",
oldMaxLength: 400);
migrationBuilder.AlterColumn<string>(
name: "ManufacturerName",
table: "TrialSiteEquipmentSurvey",
type: "nvarchar(400)",
maxLength: 400,
nullable: false,
comment: "扫描设备厂商其他补充",
oldClrType: typeof(string),
oldType: "nvarchar(400)",
oldMaxLength: 400);
migrationBuilder.AlterColumn<Guid>(
name: "EquipmentTypeId",
table: "TrialSiteEquipmentSurvey",
type: "uniqueidentifier",
nullable: false,
comment: "扫描设备-废弃",
oldClrType: typeof(Guid),
oldType: "uniqueidentifier");
migrationBuilder.AddColumn<int>(
name: "BodyCoilChannelCount",
table: "TrialSiteEquipmentSurvey",
type: "int",
nullable: false,
defaultValue: 0,
comment: "体部线圈通道数 (≥16 或 16)");
migrationBuilder.AddColumn<bool>(
name: "CanFullyExportPdfParameterMapsAndRawDicom",
table: "TrialSiteEquipmentSurvey",
type: "bit",
nullable: false,
defaultValue: false,
comment: "是否可完整导出 PDFF 参数图及全部原始 DICOM 数据");
migrationBuilder.AddColumn<int>(
name: "EquipmentTypeEnum",
table: "TrialSiteEquipmentSurvey",
type: "int",
nullable: false,
defaultValue: 0,
comment: "扫描设备-New");
migrationBuilder.AddColumn<bool>(
name: "HasDedicatedPdfFatQuantificationSequence",
table: "TrialSiteEquipmentSurvey",
type: "bit",
nullable: false,
defaultValue: false,
comment: "是否具备专用的PDFF脂肪定量序列CSE-MRI序列");
migrationBuilder.AddColumn<bool>(
name: "HasT2R2Correction",
table: "TrialSiteEquipmentSurvey",
type: "bit",
nullable: false,
defaultValue: false,
comment: "是否包含 T2/R2 校正(用于铁沉积校正)");
migrationBuilder.AddColumn<int>(
name: "MagneticFieldStrengthType",
table: "TrialSiteEquipmentSurvey",
type: "int",
nullable: false,
defaultValue: 0,
comment: "磁场强度 (1.5T / 3.0T)");
migrationBuilder.AddColumn<int>(
name: "ManufacturerType",
table: "TrialSiteEquipmentSurvey",
type: "int",
nullable: false,
defaultValue: 0,
comment: "扫描设备厂商");
migrationBuilder.AddColumn<string>(
name: "OtherEquipmentType",
table: "TrialSiteEquipmentSurvey",
type: "nvarchar(400)",
maxLength: 400,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "OtherSequenceSpecification",
table: "TrialSiteEquipmentSurvey",
type: "nvarchar(400)",
maxLength: 400,
nullable: false,
defaultValue: "",
comment: "其他序列详细说明 (当 PdfFatQuantificationSequenceType = Other 时建议填写)");
migrationBuilder.AddColumn<int>(
name: "PdfFatQuantificationSequenceType",
table: "TrialSiteEquipmentSurvey",
type: "int",
nullable: true,
comment: "专用的PDFF脂肪定量序列类型 (当 HasDedicatedPdfFatQuantificationSequence = true 时有效)");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "BodyCoilChannelCount",
table: "TrialSiteEquipmentSurvey");
migrationBuilder.DropColumn(
name: "CanFullyExportPdfParameterMapsAndRawDicom",
table: "TrialSiteEquipmentSurvey");
migrationBuilder.DropColumn(
name: "EquipmentTypeEnum",
table: "TrialSiteEquipmentSurvey");
migrationBuilder.DropColumn(
name: "HasDedicatedPdfFatQuantificationSequence",
table: "TrialSiteEquipmentSurvey");
migrationBuilder.DropColumn(
name: "HasT2R2Correction",
table: "TrialSiteEquipmentSurvey");
migrationBuilder.DropColumn(
name: "MagneticFieldStrengthType",
table: "TrialSiteEquipmentSurvey");
migrationBuilder.DropColumn(
name: "ManufacturerType",
table: "TrialSiteEquipmentSurvey");
migrationBuilder.DropColumn(
name: "OtherEquipmentType",
table: "TrialSiteEquipmentSurvey");
migrationBuilder.DropColumn(
name: "OtherSequenceSpecification",
table: "TrialSiteEquipmentSurvey");
migrationBuilder.DropColumn(
name: "PdfFatQuantificationSequenceType",
table: "TrialSiteEquipmentSurvey");
migrationBuilder.AlterColumn<string>(
name: "ScannerType",
table: "TrialSiteEquipmentSurvey",
type: "nvarchar(400)",
maxLength: 400,
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(400)",
oldMaxLength: 400,
oldComment: "扫描设备型号");
migrationBuilder.AlterColumn<string>(
name: "Parameters",
table: "TrialSiteEquipmentSurvey",
type: "nvarchar(400)",
maxLength: 400,
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(400)",
oldMaxLength: 400,
oldComment: "扫描设备参数");
migrationBuilder.AlterColumn<string>(
name: "ManufacturerName",
table: "TrialSiteEquipmentSurvey",
type: "nvarchar(400)",
maxLength: 400,
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(400)",
oldMaxLength: 400,
oldComment: "扫描设备厂商其他补充");
migrationBuilder.AlterColumn<Guid>(
name: "EquipmentTypeId",
table: "TrialSiteEquipmentSurvey",
type: "uniqueidentifier",
nullable: false,
oldClrType: typeof(Guid),
oldType: "uniqueidentifier",
oldComment: "扫描设备-废弃");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,40 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace IRaCIS.Core.Infra.EFCore.Migrations
{
/// <inheritdoc />
public partial class modifyTrialJson : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "IsOpenLostVistRead",
table: "Trial",
type: "bit",
nullable: false,
defaultValue: true);
migrationBuilder.AddColumn<bool>(
name: "IsSupportQCDownloadImage",
table: "Trial",
type: "bit",
nullable: false,
defaultValue: false);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "IsOpenLostVistRead",
table: "Trial");
migrationBuilder.DropColumn(
name: "IsSupportQCDownloadImage",
table: "Trial");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,150 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace IRaCIS.Core.Infra.EFCore.Migrations
{
/// <inheritdoc />
public partial class modifySurvey : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<int>(
name: "ManufacturerType",
table: "TrialSiteEquipmentSurvey",
type: "int",
nullable: true,
comment: "扫描设备厂商",
oldClrType: typeof(int),
oldType: "int",
oldComment: "扫描设备厂商");
migrationBuilder.AlterColumn<int>(
name: "MagneticFieldStrengthType",
table: "TrialSiteEquipmentSurvey",
type: "int",
nullable: true,
comment: "磁场强度 (1.5T / 3.0T)",
oldClrType: typeof(int),
oldType: "int",
oldComment: "磁场强度 (1.5T / 3.0T)");
migrationBuilder.AlterColumn<bool>(
name: "HasT2R2Correction",
table: "TrialSiteEquipmentSurvey",
type: "bit",
nullable: true,
comment: "是否包含 T2/R2 校正(用于铁沉积校正)",
oldClrType: typeof(bool),
oldType: "bit",
oldComment: "是否包含 T2/R2 校正(用于铁沉积校正)");
migrationBuilder.AlterColumn<bool>(
name: "HasDedicatedPdfFatQuantificationSequence",
table: "TrialSiteEquipmentSurvey",
type: "bit",
nullable: true,
comment: "是否具备专用的PDFF脂肪定量序列CSE-MRI序列",
oldClrType: typeof(bool),
oldType: "bit",
oldComment: "是否具备专用的PDFF脂肪定量序列CSE-MRI序列");
migrationBuilder.AlterColumn<bool>(
name: "CanFullyExportPdfParameterMapsAndRawDicom",
table: "TrialSiteEquipmentSurvey",
type: "bit",
nullable: true,
comment: "是否可完整导出 PDFF 参数图及全部原始 DICOM 数据",
oldClrType: typeof(bool),
oldType: "bit",
oldComment: "是否可完整导出 PDFF 参数图及全部原始 DICOM 数据");
migrationBuilder.AlterColumn<int>(
name: "BodyCoilChannelCount",
table: "TrialSiteEquipmentSurvey",
type: "int",
nullable: true,
comment: "体部线圈通道数 (≥16 或 16)",
oldClrType: typeof(int),
oldType: "int",
oldComment: "体部线圈通道数 (≥16 或 16)");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<int>(
name: "ManufacturerType",
table: "TrialSiteEquipmentSurvey",
type: "int",
nullable: false,
defaultValue: 0,
comment: "扫描设备厂商",
oldClrType: typeof(int),
oldType: "int",
oldNullable: true,
oldComment: "扫描设备厂商");
migrationBuilder.AlterColumn<int>(
name: "MagneticFieldStrengthType",
table: "TrialSiteEquipmentSurvey",
type: "int",
nullable: false,
defaultValue: 0,
comment: "磁场强度 (1.5T / 3.0T)",
oldClrType: typeof(int),
oldType: "int",
oldNullable: true,
oldComment: "磁场强度 (1.5T / 3.0T)");
migrationBuilder.AlterColumn<bool>(
name: "HasT2R2Correction",
table: "TrialSiteEquipmentSurvey",
type: "bit",
nullable: false,
defaultValue: false,
comment: "是否包含 T2/R2 校正(用于铁沉积校正)",
oldClrType: typeof(bool),
oldType: "bit",
oldNullable: true,
oldComment: "是否包含 T2/R2 校正(用于铁沉积校正)");
migrationBuilder.AlterColumn<bool>(
name: "HasDedicatedPdfFatQuantificationSequence",
table: "TrialSiteEquipmentSurvey",
type: "bit",
nullable: false,
defaultValue: false,
comment: "是否具备专用的PDFF脂肪定量序列CSE-MRI序列",
oldClrType: typeof(bool),
oldType: "bit",
oldNullable: true,
oldComment: "是否具备专用的PDFF脂肪定量序列CSE-MRI序列");
migrationBuilder.AlterColumn<bool>(
name: "CanFullyExportPdfParameterMapsAndRawDicom",
table: "TrialSiteEquipmentSurvey",
type: "bit",
nullable: false,
defaultValue: false,
comment: "是否可完整导出 PDFF 参数图及全部原始 DICOM 数据",
oldClrType: typeof(bool),
oldType: "bit",
oldNullable: true,
oldComment: "是否可完整导出 PDFF 参数图及全部原始 DICOM 数据");
migrationBuilder.AlterColumn<int>(
name: "BodyCoilChannelCount",
table: "TrialSiteEquipmentSurvey",
type: "int",
nullable: false,
defaultValue: 0,
comment: "体部线圈通道数 (≥16 或 16)",
oldClrType: typeof(int),
oldType: "int",
oldNullable: true,
oldComment: "体部线圈通道数 (≥16 或 16)");
}
}
}

View File

@ -12642,6 +12642,9 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
.HasColumnType("bit")
.HasComment("是否 提醒受试者编号规则");
b.Property<bool>("IsOpenLostVistRead")
.HasColumnType("bit");
b.Property<bool>("IsPACSConnect")
.HasColumnType("bit");
@ -12677,6 +12680,9 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
b.Property<bool>("IsSubjectSexView")
.HasColumnType("bit");
b.Property<bool>("IsSupportQCDownloadImage")
.HasColumnType("bit");
b.Property<bool>("IsTrialBasicLogicConfirmed")
.HasColumnType("bit");
@ -15017,34 +15023,81 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<int?>("BodyCoilChannelCount")
.HasColumnType("int")
.HasComment("体部线圈通道数 (≥16 或 16)");
b.Property<bool?>("CanFullyExportPdfParameterMapsAndRawDicom")
.HasColumnType("bit")
.HasComment("是否可完整导出 PDFF 参数图及全部原始 DICOM 数据");
b.Property<DateTime>("CreateTime")
.HasColumnType("datetime2");
b.Property<Guid>("CreateUserId")
.HasColumnType("uniqueidentifier");
b.Property<int>("EquipmentTypeEnum")
.HasColumnType("int")
.HasComment("扫描设备-New");
b.Property<Guid>("EquipmentTypeId")
.HasColumnType("uniqueidentifier");
.HasColumnType("uniqueidentifier")
.HasComment("扫描设备-废弃");
b.Property<bool?>("HasDedicatedPdfFatQuantificationSequence")
.HasColumnType("bit")
.HasComment("是否具备专用的PDFF脂肪定量序列CSE-MRI序列");
b.Property<bool?>("HasT2R2Correction")
.HasColumnType("bit")
.HasComment("是否包含 T2/R2 校正(用于铁沉积校正)");
b.Property<int?>("MagneticFieldStrengthType")
.HasColumnType("int")
.HasComment("磁场强度 (1.5T / 3.0T)");
b.Property<string>("ManufacturerName")
.IsRequired()
.HasMaxLength(400)
.HasColumnType("nvarchar(400)");
.HasColumnType("nvarchar(400)")
.HasComment("扫描设备厂商其他补充");
b.Property<int?>("ManufacturerType")
.HasColumnType("int")
.HasComment("扫描设备厂商");
b.Property<string>("Note")
.IsRequired()
.HasMaxLength(400)
.HasColumnType("nvarchar(400)");
b.Property<string>("Parameters")
b.Property<string>("OtherEquipmentType")
.IsRequired()
.HasMaxLength(400)
.HasColumnType("nvarchar(400)");
b.Property<string>("OtherSequenceSpecification")
.IsRequired()
.HasMaxLength(400)
.HasColumnType("nvarchar(400)")
.HasComment("其他序列详细说明 (当 PdfFatQuantificationSequenceType = Other 时建议填写)");
b.Property<string>("Parameters")
.IsRequired()
.HasMaxLength(400)
.HasColumnType("nvarchar(400)")
.HasComment("扫描设备参数");
b.Property<int?>("PdfFatQuantificationSequenceType")
.HasColumnType("int")
.HasComment("专用的PDFF脂肪定量序列类型 (当 HasDedicatedPdfFatQuantificationSequence = true 时有效)");
b.Property<string>("ScannerType")
.IsRequired()
.HasMaxLength(400)
.HasColumnType("nvarchar(400)");
.HasColumnType("nvarchar(400)")
.HasComment("扫描设备型号");
b.Property<Guid>("TrialSiteSurveyId")
.HasColumnType("uniqueidentifier");