diff --git a/IRC.Core.SCP/appsettings.US_Prod_SCP.json b/IRC.Core.SCP/appsettings.US_Prod_SCP.json new file mode 100644 index 000000000..3387edb1d --- /dev/null +++ b/IRC.Core.SCP/appsettings.US_Prod_SCP.json @@ -0,0 +1,31 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "ObjectStoreService": { + "ObjectStoreUse": "AWS", + "AWS": { + "endPoint": "s3.us-east-1.amazonaws.com", + "useSSL": true, + "accessKey": "AKIAW3MEAFJX5P32P6NA", + "secretKey": "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", + "bucketName": "ei-med-s3-lili-store", + "viewEndpoint": "https://ei-med-s3-lili-store.s3.amazonaws.com/" + } + }, + "ConnectionStrings": { + "RemoteNew": "Server=us-prod-mssql-service,1433;Database=US_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true", + "Hangfire": "Server=us-prod-mssql-service,1433;Database=US_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true" + }, + "DicomSCPServiceConfig": { + "CalledAEList": [ + "STORESCP" + ], + "ServerPort": 11112 + } + +} diff --git a/IRaCIS.Core.API/appsettings.json b/IRaCIS.Core.API/appsettings.json index 8fa44ed41..75bc653af 100644 --- a/IRaCIS.Core.API/appsettings.json +++ b/IRaCIS.Core.API/appsettings.json @@ -88,6 +88,7 @@ "QCChallengeCodePrefix": "Q", "NoneDicomStudyCodePrefix": "NST", "DicomStudyCodePrefix": "ST", + "TaskStudyCodePrefix": "P-ST", "SystemSiteCodePrefix": "S", "DefaultPassword": "123456", "ImageShareExpireDays": 10 diff --git a/IRaCIS.Core.Application/Helper/OSSService.cs b/IRaCIS.Core.Application/Helper/OSSService.cs index 7a472d690..261594914 100644 --- a/IRaCIS.Core.Application/Helper/OSSService.cs +++ b/IRaCIS.Core.Application/Helper/OSSService.cs @@ -345,7 +345,7 @@ namespace IRaCIS.Core.Application.Helper public async Task DownLoadFromOSSAsync(string ossRelativePath, string localFilePath) { - + ossRelativePath = ossRelativePath.TrimStart('/'); try { @@ -406,7 +406,7 @@ namespace IRaCIS.Core.Application.Helper }; - await (await amazonS3Client.GetObjectAsync(getObjectArgs)).WriteResponseStreamToFileAsync(localFilePath, true, CancellationToken.None); + await (await amazonS3Client.GetObjectAsync(getObjectArgs)).WriteResponseStreamToFileAsync(localFilePath, true, CancellationToken.None); } @@ -478,18 +478,26 @@ namespace IRaCIS.Core.Application.Helper } else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS") { - var minIOConfig = ObjectStoreServiceOptions.AWS; + var awsConfig = ObjectStoreServiceOptions.AWS; - var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}") - .WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL) - .Build(); - var args = new PresignedGetObjectArgs() - .WithBucket(minIOConfig.BucketName) - .WithObject(ossRelativePath) - .WithExpiry(3600); + // 提供awsAccessKeyId和awsSecretAccessKey构造凭证 + var credentials = new BasicAWSCredentials(awsConfig.AccessKeyId, awsConfig.SecretAccessKey); - var presignedUrl = await minioClient.PresignedGetObjectAsync(args); + //提供awsEndPoint(域名)进行访问配置 + var clientConfig = new AmazonS3Config + { + ServiceURL = awsConfig.EndPoint + }; + + var amazonS3Client = new AmazonS3Client(credentials, clientConfig); + + var presignedUrl = await amazonS3Client.GetPreSignedURLAsync(new GetPreSignedUrlRequest() + { + BucketName = awsConfig.BucketName, + Key = ossRelativePath, + Expires = DateTime.UtcNow.AddMinutes(120) + }); Uri uri = new Uri(presignedUrl); @@ -643,7 +651,7 @@ namespace IRaCIS.Core.Application.Helper var deleteObjectsResponse = await amazonS3Client.DeleteObjectsAsync(deleteObjectsRequest); } - + } else diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs index 150d90103..78c83b748 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs @@ -244,6 +244,9 @@ namespace IRaCIS.Core.Application.Contracts public string RecordPath { get; set; } = string.Empty; public AddOrUpdateStudyDto Study { get; set; } + + [NotDefault] + public Guid VisitTaskId { get; set; } } public class NewArchiveStudyCommand @@ -397,6 +400,11 @@ namespace IRaCIS.Core.Application.Contracts public string SubjectCode { get; set; } } + public class IRTaskUploadedDicomStudyQuery + { + public Guid VisitTaskId { get; set; } + } + public class IRUploadTaskDicomStudyDto : DicomStudyBasicInfo { diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs index 2838c683a..d112ef13f 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs @@ -1,5 +1,7 @@ using FellowOakDicom; +using IRaCIS.Application.Contracts; using IRaCIS.Core.Application.Contracts; +using IRaCIS.Core.Application.Contracts.Dicom.DTO; using IRaCIS.Core.Application.Filter; using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.Service.ImageAndDoc.DTO; @@ -239,35 +241,42 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc } + + //public async Task> VerifyIRStudyAllowUpload(VerifyUploadOrReupload inCommand) + //{ + + //} + + [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] public async Task AddOrUpdateArchiveTaskStudy(TaskArchiveStudyCommand incommand) { #region 获取该subject 已生成任务的访视的检查 - var queryStudy = _visitTaskRepository.Where(t => t.SubjectId == incommand.SubjectId && t.SourceSubjectVisitId != null && t.DoctorUserId == _userInfo.Id).Select(u => new - { - VisitTaskId = u.Id, - SourceSubjectVisitId = u.SourceSubjectVisitId, - OrginalStudyList = u.SourceSubjectVisit.StudyList.Select(t => new StudyBasicInfo() - { - Id = t.Id, - StudyInstanceUid = t.StudyInstanceUid - }).ToList(), - }); + //var queryStudy = _visitTaskRepository.Where(t => t.SubjectId == incommand.SubjectId && t.SourceSubjectVisitId != null && t.DoctorUserId == _userInfo.Id).Select(u => new + //{ + // VisitTaskId = u.Id, + // SourceSubjectVisitId = u.SourceSubjectVisitId, + // OrginalStudyList = u.SourceSubjectVisit.StudyList.Select(t => new StudyBasicInfo() + // { + // Id = t.Id, + // StudyInstanceUid = t.StudyInstanceUid + // }).ToList(), + //}); - var studyList = await queryStudy.ToListAsync(); + //var studyList = await queryStudy.ToListAsync(); - var findOriginStudy = studyList.FirstOrDefault(c => c.OrginalStudyList.Any(t => t.StudyInstanceUid == incommand.Study.StudyInstanceUid)); + //var findOriginStudy = studyList.FirstOrDefault(c => c.OrginalStudyList.Any(t => t.StudyInstanceUid == incommand.Study.StudyInstanceUid)); - if (findOriginStudy == null) - { - return ResponseOutput.NotOk("该检查不属于该受试者,请核查"); - } + //if (findOriginStudy == null) + //{ + // return ResponseOutput.NotOk("该检查不属于该受试者,请核查"); + //} #endregion - + var visiTaskId = incommand.VisitTaskId; var modalitys = string.Empty; @@ -301,17 +310,17 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc int currentNextCodeInt = cacheMaxCodeInt > dbStudyCodeIntMax ? cacheMaxCodeInt + 1 : dbStudyCodeIntMax + 1; study.Code = currentNextCodeInt; - study.StudyCode = AppSettings.GetCodeStr(currentNextCodeInt, nameof(DicomStudy)); + study.StudyCode = AppSettings.GetCodeStr(currentNextCodeInt, nameof(TaskStudy)); await _fusionCache.SetAsync(CacheKeys.TrialStudyMaxCode(trialId), study.Code, TimeSpan.FromMinutes(30)); } - study.Id = IdentifierHelper.CreateGuid(incommand.Study.StudyInstanceUid, incommand.TrialId.ToString(), findOriginStudy.VisitTaskId.ToString()); + study.Id = IdentifierHelper.CreateGuid(incommand.Study.StudyInstanceUid, incommand.TrialId.ToString(), visiTaskId.ToString()); study.TrialId = incommand.TrialId; study.SubjectId = incommand.SubjectId; - study.VisitTaskId = findOriginStudy.VisitTaskId; + study.VisitTaskId = visiTaskId; //study.SubjectVisitId = incommand.SubjectVisitId; @@ -331,13 +340,13 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc { var series = _mapper.Map(seriesItem); - series.Id = IdentifierHelper.CreateGuid(seriesItem.StudyInstanceUid, seriesItem.SeriesInstanceUid, incommand.TrialId.ToString(), findOriginStudy.VisitTaskId.ToString()); + series.Id = IdentifierHelper.CreateGuid(seriesItem.StudyInstanceUid, seriesItem.SeriesInstanceUid, incommand.TrialId.ToString(), visiTaskId.ToString()); series.StudyId = study.Id; series.TrialId = incommand.TrialId; series.SubjectId = incommand.SubjectId; //series.SubjectVisitId = incommand.SubjectVisitId; - series.VisitTaskId = findOriginStudy.VisitTaskId; + series.VisitTaskId = visiTaskId; //前端传递的数量不准,上传的时候,把失败的也加进来了,以实际数组的数字为准 series.InstanceCount = seriesItem.InstanceList.Count; @@ -348,7 +357,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc { var isntance = _mapper.Map(instanceItem); - Guid instanceId = IdentifierHelper.CreateGuid(study.StudyInstanceUid, series.SeriesInstanceUid, isntance.SopInstanceUid, study.TrialId.ToString(), findOriginStudy.VisitTaskId.ToString()); + Guid instanceId = IdentifierHelper.CreateGuid(study.StudyInstanceUid, series.SeriesInstanceUid, isntance.SopInstanceUid, study.TrialId.ToString(), visiTaskId.ToString()); isntance.Id = instanceId; isntance.StudyId = study.Id; @@ -357,7 +366,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc isntance.TrialId = incommand.TrialId; isntance.SubjectId = incommand.SubjectId; //isntance.SubjectVisitId = incommand.SubjectVisitId; - isntance.VisitTaskId = findOriginStudy.VisitTaskId; + isntance.VisitTaskId = visiTaskId; await _taskInstanceRepository.AddAsync(isntance); } @@ -370,7 +379,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc else { - var studyId = IdentifierHelper.CreateGuid(incommand.Study.StudyInstanceUid, incommand.TrialId.ToString(), findOriginStudy.VisitTaskId.ToString()); + var studyId = IdentifierHelper.CreateGuid(incommand.Study.StudyInstanceUid, incommand.TrialId.ToString(), visiTaskId.ToString()); var study = await _taskStudyRepository.FirstOrDefaultAsync(t => t.Id == studyId); @@ -389,7 +398,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc //某个序列下少了instance foreach (var seriesItem in incommand.Study.SeriesList) { - var seriesId = IdentifierHelper.CreateGuid(seriesItem.StudyInstanceUid, seriesItem.SeriesInstanceUid, trialId.ToString(), findOriginStudy.VisitTaskId.ToString()); + var seriesId = IdentifierHelper.CreateGuid(seriesItem.StudyInstanceUid, seriesItem.SeriesInstanceUid, trialId.ToString(), visiTaskId.ToString()); TaskSeries dicomSeries = await _taskSeriesRepository.FirstOrDefaultAsync(t => t.Id == seriesId); @@ -403,7 +412,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc series.TrialId = incommand.TrialId; series.SubjectId = incommand.SubjectId; - series.VisitTaskId = findOriginStudy.VisitTaskId; + series.VisitTaskId = visiTaskId; //series.SubjectVisitId = incommand.SubjectVisitId; @@ -421,13 +430,13 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc foreach (var instanceItem in seriesItem.InstanceList) { var insntance = _mapper.Map(instanceItem); - insntance.Id = IdentifierHelper.CreateGuid(insntance.StudyInstanceUid, insntance.SeriesInstanceUid, insntance.SopInstanceUid, trialId.ToString(), findOriginStudy.VisitTaskId.ToString()); + insntance.Id = IdentifierHelper.CreateGuid(insntance.StudyInstanceUid, insntance.SeriesInstanceUid, insntance.SopInstanceUid, trialId.ToString(), visiTaskId.ToString()); insntance.StudyId = study.Id; insntance.SeriesId = dicomSeries.Id; insntance.TrialId = incommand.TrialId; insntance.SubjectId = incommand.SubjectId; - insntance.VisitTaskId = findOriginStudy.VisitTaskId; + insntance.VisitTaskId = visiTaskId; await _taskInstanceRepository.AddAsync(insntance); } @@ -484,6 +493,310 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc return ResponseOutput.Ok(); } + + + + /// + /// IR 上传任务 nonedicom 列表 后处理的数据UploadedFileCount不能排序 --new + /// + /// + /// + [HttpPost] + public async Task> GetIRUploadTaskNoneDicomStudyList(IRUploadStudyQuery inQuery) + { + var query = from u in _visitTaskRepository.Where(t => t.SubjectId == inQuery.SubjectId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId + && t.SourceSubjectVisitId != null && t.DoctorUserId == _userInfo.Id && t.TaskState == TaskState.Effect) + join ns in _noneDicomStudyReposiotry.Where(t => t.SubjectId == inQuery.SubjectId) on u.SourceSubjectVisitId equals ns.SubjectVisitId + + select new TaskNoneDicomStudyDTO() + { + SubjectId = u.SubjectId, + SubjectCode = u.IsSelfAnalysis == true ? u.BlindSubjectCode : u.Subject.Code, + TaskBlindName = u.TaskBlindName, + TaskName = u.TaskName, + SourceSubjectVisitId = u.SourceSubjectVisitId, + VisitTaskId = u.Id, + + Id = ns.Id, + Description = ns.Description, + ImageDate = ns.ImageDate, + BodyPart = ns.BodyPart, + FileCount = ns.FileCount, + Modality = ns.Modality, + StudyCode = ns.StudyCode, + + FileList = ns.NoneDicomFileList.Select(t => new NoneDicomFileInfo() + { + FileType = t.FileType, + FileName = t.FileName, + FileSize = t.FileSize, + Path = t.Path + }).ToList() + + }; + + var list = await query.Where(t => t.SubjectCode == inQuery.SubjectCode).SortToListAsync(inQuery); + + var noneDicomStudyTaskIdList = list.Select(t => t.VisitTaskId).ToList(); + + + var taskNoneDicomStudyList = _visitTaskRepository.Where(t => noneDicomStudyTaskIdList.Contains(t.Id)) + .SelectMany(t => t.TaskNoneDicomStudyFileList).Where(t => noneDicomStudyTaskIdList.Contains((Guid)t.VisitTaskId)) + .Select(u => new NoneDicomFileInfo + { + OriginNoneDicomStudyId = u.OriginNoneDicomStudyId, + + FileType = u.FileType, + FileName = u.FileName, + FileSize = u.FileSize, + Path = u.Path + }) + .ToList(); + + foreach (var item in list) + { + item.UploadedFileCount = taskNoneDicomStudyList.Where(t => t.OriginNoneDicomStudyId == item.Id).Count(); + item.UploadedFileList = taskNoneDicomStudyList.Where(t => t.OriginNoneDicomStudyId == item.Id).ToList(); + } + + return list; + + } + + + /// + /// IQC 获取CRC 上传到某一个访视的的检查信息 (原始影像信息 包含dicom 非dicom) + /// + /// + /// + [HttpPost] + public async Task GetCRCUploadedStudyInfo(CRCUploadedStudyQuqry inQuery) + { + var isQueryDicom = inQuery.DicomStudyIdList.Count > 0; + var isQueryNoneDicom = inQuery.NoneDicomStudyIdList.Count > 0; + + var query = from sv in _subjectVisitRepository.Where(t => t.Id == inQuery.SubjectVisitId) + + + select new + { + SubjectCode = sv.Subject.Code, + VisitName = sv.VisitName, + + StudyList = sv.StudyList.Where(t => isQueryDicom ? inQuery.DicomStudyIdList.Contains(t.Id) : false) + + .Select(u => new + { + u.PatientId, + u.StudyTime, + u.StudyCode, + + SeriesList = u.SeriesList.Select(z => new + { + z.Modality, + + InstanceList = z.DicomInstanceList.Select(k => new + { + k.Path, + k.FileSize + }) + }) + + }).ToList(), + + NoneDicomStudyList = sv.NoneDicomStudyList.Where(t => isQueryNoneDicom ? inQuery.NoneDicomStudyIdList.Contains(t.Id) : false) + + .Select(nd => new + { + nd.Modality, + nd.StudyCode, + nd.ImageDate, + + FileList = nd.NoneDicomFileList.Select(file => new + { + file.FileName, + file.Path, + file.FileType + }) + }).ToList() + }; + + var result = query.FirstOrDefault(); + + return ResponseOutput.Ok(result); + } + + + /// + /// IR 阅片页面 和IR 任务列表页面下载 勾选下载列表(后端要考虑到一致性分析 subjectCode的问题) + /// + /// + /// + [HttpPost] + public async Task> GetSubjectImageDownloadSelectList(IRReadingDownloadQuery inQuery) + { + + var query = _visitTaskRepository.Where(t => t.SubjectId == inQuery.SubjectId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId + && t.SourceSubjectVisitId != null && t.DoctorUserId == _userInfo.Id && t.TaskState == TaskState.Effect) + .ProjectTo(_mapper.ConfigurationProvider); + + + var list = await query.Where(t => t.SubjectCode == inQuery.SubjectCode).ToListAsync(); + + #region 将任务级别转为检查级别 + + var result = new List(); + + var dicomStudyList = list.Where(item => item.DicomStudyList.Count > 0) + .Select(item => new SubjectCRCImageUploadedStudyDto + { + VisitTaskId = item.VisitTaskId, + SubjectId = item.SubjectId, + SubjectCode = item.SubjectCode, + TaskBlindName = item.TaskBlindName, + TaskName = item.TaskName, + IsImageFilter = item.IsImageFilter, + CriterionModalitys = item.CriterionModalitys, + SourceSubjectVisitId = item.SourceSubjectVisitId, + //取dicom + DicomStudyList = item.DicomStudyList, + }).ToList(); + + var noneStudyList = list.Where(item => item.NoneDicomStudyList.Count > 0) + .Select(item => new SubjectCRCImageUploadedStudyDto + { + VisitTaskId = item.VisitTaskId, + SubjectId = item.SubjectId, + SubjectCode = item.SubjectCode, + TaskBlindName = item.TaskBlindName, + TaskName = item.TaskName, + IsImageFilter = item.IsImageFilter, + CriterionModalitys = item.CriterionModalitys, + SourceSubjectVisitId = item.SourceSubjectVisitId, + //非dicom + NoneDicomStudyList = item.NoneDicomStudyList, + }).ToList(); + + + result.AddRange(dicomStudyList); + result.AddRange(noneStudyList); + #endregion + + + return result; + + } + + /// + /// IR 阅片页面获取下载检查的信息 会根据标准进行过滤检查,(后端要考虑到一致性分析 subjectCode的问题) + /// 检查在访视下面,所以需要传递下载的访视Id,另外下载访视下面那些检查,就把访视下的对应的检查Id 丢到数组里就好 + /// + /// + /// + /// + [HttpPost] + public async Task GetIRReadingDownloadStudyInfo(IRDownloadQuery inQuery, [FromServices] IRepository _subjectRepository) + { + var info = await _readingQuestionCriterionTrialRepository.Where(t => t.Id == inQuery.TrialReadingCriterionId) + .Select(t => new { t.IsImageFilter, t.CriterionModalitys }).FirstNotNullAsync(); + + var isQueryDicom = inQuery.DicomStudyIdList.Count > 0; + var isQueryNoneDicom = inQuery.NoneDicomStudyIdList.Count > 0; + + var query = from sv in _subjectRepository.Where(t => t.Id == inQuery.SubjectId).SelectMany(t => t.SubjectVisitList.Where(t => inQuery.SubjectVisitIdList.Contains(t.Id))) + + select new + { + SubjectCode = sv.Subject.Code, + VisitName = sv.VisitName, + StudyList = sv.StudyList.Where(t => isQueryDicom ? inQuery.DicomStudyIdList.Contains(t.Id) : false) + .Select(u => new + { + u.PatientId, + u.StudyTime, + u.StudyCode, + + SeriesList = u.SeriesList.Select(z => new + { + z.Modality, + + InstancePathList = z.DicomInstanceList.Select(k => new + { + k.Path + }) + }) + + }), + + NoneDicomStudyList = sv.NoneDicomStudyList.Where(t => isQueryNoneDicom ? inQuery.NoneDicomStudyIdList.Contains(t.Id) : false) + .Select(nd => new + { + nd.Modality, + nd.StudyCode, + nd.ImageDate, + + FileList = nd.NoneDicomFileList.Select(file => new + { + file.FileName, + file.Path, + file.FileType + }) + }) + }; + + + + var result = await query.FirstOrDefaultAsync(); + + return ResponseOutput.Ok(result); + } + + [HttpPost] + public async Task GetTaskUploadedDicomStudyList(IRTaskUploadedDicomStudyQuery inQuery) + { + var query = _taskStudyRepository.Where(t => t.VisitTaskId == inQuery.VisitTaskId).Select(t => new + { + StudyId=t.Id, + t.Modalities, + t.InstanceCount, + t.SeriesCount, + t.StudyCode, + SeriesList= t.SeriesList.OrderBy(s => s.SeriesNumber).ThenBy(s => s.SeriesTime).Select(u=>new + { + u.SeriesTime, + u.InstanceCount, + u.ImageResizePath, + u.Modality, + u.Description, + u.SeriesInstanceUid, + u.SeriesNumber, + u.SliceThickness, + u.StudyInstanceUid, + + IsExistMutiFrames= u.InstanceList.Any(t=>t.NumberOfFrames>1), + + InstanceInfoList =u.InstanceList.OrderBy(t => t.InstanceNumber).Select(k => + new InstanceBasicInfo() + { + Id = k.Id, + NumberOfFrames = k.NumberOfFrames, + HtmlPath = k.HtmlPath, + Path = k.Path, + InstanceNumber = k.InstanceNumber, + + }).ToList() + }) + }); + var list = await query.ToListAsync(); + + return ResponseOutput.Ok(list); + + } + + + + #region 之前后端下载废弃 + /// /// 打包和匿名化影像 默认是匿名化打包,也可以不匿名化打包 /// @@ -493,6 +806,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc /// /// + [Obsolete] public async Task RequestPackageAndAnonymizImage(Guid trialId, Guid subjectVisitId, bool isDicom, bool isAnonymize = true) { @@ -547,6 +861,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc /// /// /// + [Obsolete] public async Task GetSubejectOrVisitZipInfo([FromServices] IRepository _subjectRepository, SubejctZipInfoQuery inQuery) { var isImageFilter = false; @@ -678,6 +993,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc /// /// [HttpPost] + [Obsolete] public async Task PackageAndAnonymizImage(Guid trialId, Guid subjectVisitId, bool isDicom, bool isAnonymize = true) { @@ -901,6 +1217,9 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc } + #endregion + + #region 按照任务为维度 展示上传的列表 废弃 @@ -910,6 +1229,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc /// /// [HttpPost] + [Obsolete] public async Task> GetIRUploadTaskList_Old(CRCUploadTaskQuery inQuery) { var query = _visitTaskRepository.Where(t => t.SubjectId == inQuery.SubjectId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId @@ -927,6 +1247,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc /// /// [HttpPost] + [Obsolete] public async Task> GetIRUploadTaskDicomStudyList_Old(CRCUploadTaskStudyQuery inQuery) { var list = await _visitTaskRepository.Where(t => t.Id == inQuery.VisitTaskId) @@ -965,6 +1286,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc /// /// [HttpPost] + [Obsolete] public async Task> GetIRUploadTaskNoneDicomStudyList_Old(CRCUploadTaskStudyQuery inQuery) { var list = await _visitTaskRepository.Where(t => t.Id == inQuery.VisitTaskId) @@ -989,270 +1311,6 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc } #endregion - - - #region IR 上传 列表,dicom 上以任务为维度,非dicom 以检查为维度 - - - - - - /// - /// IR 上传任务 nonedicom 列表 后处理的数据UploadedFileCount不能排序 --new - /// - /// - /// - [HttpPost] - public async Task> GetIRUploadTaskNoneDicomStudyList(IRUploadStudyQuery inQuery) - { - var query = from u in _visitTaskRepository.Where(t => t.SubjectId == inQuery.SubjectId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId - && t.SourceSubjectVisitId != null && t.DoctorUserId == _userInfo.Id && t.TaskState == TaskState.Effect) - join ns in _noneDicomStudyReposiotry.Where(t => t.SubjectId == inQuery.SubjectId) on u.SourceSubjectVisitId equals ns.SubjectVisitId - - select new TaskNoneDicomStudyDTO() - { - SubjectId = u.SubjectId, - SubjectCode = u.IsSelfAnalysis == true ? u.BlindSubjectCode : u.Subject.Code, - TaskBlindName = u.TaskBlindName, - TaskName = u.TaskName, - SourceSubjectVisitId = u.SourceSubjectVisitId, - VisitTaskId=u.Id, - - Id = ns.Id, - Description = ns.Description, - ImageDate = ns.ImageDate, - BodyPart = ns.BodyPart, - FileCount = ns.FileCount, - Modality = ns.Modality, - StudyCode = ns.StudyCode, - - FileList = ns.NoneDicomFileList.Select(t => new NoneDicomFileInfo() - { - FileType=t.FileType, - FileName = t.FileName, - FileSize = t.FileSize, - Path = t.Path - }).ToList() - - }; - - var list = await query.Where(t => t.SubjectCode == inQuery.SubjectCode).SortToListAsync(inQuery); - - var noneDicomStudyTaskIdList = list.Select(t => t.VisitTaskId).ToList(); - - - var taskNoneDicomStudyList = _visitTaskRepository.Where(t => noneDicomStudyTaskIdList.Contains(t.Id)) - .SelectMany(t => t.TaskNoneDicomStudyFileList).Where(t => noneDicomStudyTaskIdList.Contains((Guid)t.VisitTaskId)) - .Select(u => new NoneDicomFileInfo - { - OriginNoneDicomStudyId = u.OriginNoneDicomStudyId, - - FileType=u.FileType, - FileName = u.FileName, - FileSize = u.FileSize, - Path = u.Path - }) - .ToList(); - - foreach (var item in list) - { - item.UploadedFileCount = taskNoneDicomStudyList.Where(t => t.OriginNoneDicomStudyId == item.Id).Count(); - item.UploadedFileList = taskNoneDicomStudyList.Where(t => t.OriginNoneDicomStudyId == item.Id).ToList(); - } - - return list; - - } - #endregion - - - /// - /// IQC 获取CRC 上传到某一个访视的的检查信息 (原始影像信息 包含dicom 非dicom) - /// - /// - /// - [HttpPost] - public async Task GetCRCUploadedStudyInfo(CRCUploadedStudyQuqry inQuery) - { - var isQueryDicom = inQuery.DicomStudyIdList.Count > 0; - var isQueryNoneDicom = inQuery.NoneDicomStudyIdList.Count > 0; - - var query = from sv in _subjectVisitRepository.Where(t => t.Id == inQuery.SubjectVisitId) - - - select new - { - SubjectCode = sv.Subject.Code, - VisitName = sv.VisitName, - - StudyList = sv.StudyList.Where(t => isQueryDicom ? inQuery.DicomStudyIdList.Contains(t.Id) : false) - - .Select(u => new - { - u.PatientId, - u.StudyTime, - u.StudyCode, - - SeriesList = u.SeriesList.Select(z => new - { - z.Modality, - - InstanceList = z.DicomInstanceList.Select(k => new - { - k.Path, - k.FileSize - }) - }) - - }).ToList(), - - NoneDicomStudyList = sv.NoneDicomStudyList.Where(t => isQueryNoneDicom ? inQuery.NoneDicomStudyIdList.Contains(t.Id) : false) - - .Select(nd => new - { - nd.Modality, - nd.StudyCode, - nd.ImageDate, - - FileList = nd.NoneDicomFileList.Select(file => new - { - file.FileName, - file.Path, - file.FileType - }) - }).ToList() - }; - - var result = query.FirstOrDefault(); - - return ResponseOutput.Ok(result); - } - - - /// - /// IR 阅片页面 和IR 任务列表页面下载 勾选下载列表(后端要考虑到一致性分析 subjectCode的问题) - /// - /// - /// - [HttpPost] - public async Task> GetSubjectImageDownloadSelectList(IRReadingDownloadQuery inQuery) - { - - var query = _visitTaskRepository.Where(t => t.SubjectId == inQuery.SubjectId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId - && t.SourceSubjectVisitId != null && t.DoctorUserId == _userInfo.Id && t.TaskState == TaskState.Effect) - .ProjectTo(_mapper.ConfigurationProvider); - - - var list = await query.Where(t => t.SubjectCode == inQuery.SubjectCode).ToListAsync(); - - #region 将任务级别转为检查级别 - - var result = new List(); - - var dicomStudyList = list.Where(item => item.DicomStudyList.Count > 0) - .Select(item => new SubjectCRCImageUploadedStudyDto - { - VisitTaskId = item.VisitTaskId, - SubjectId = item.SubjectId, - SubjectCode = item.SubjectCode, - TaskBlindName = item.TaskBlindName, - TaskName = item.TaskName, - IsImageFilter = item.IsImageFilter, - CriterionModalitys = item.CriterionModalitys, - SourceSubjectVisitId = item.SourceSubjectVisitId, - //取dicom - DicomStudyList = item.DicomStudyList, - }).ToList(); - - var noneStudyList = list.Where(item => item.NoneDicomStudyList.Count > 0) - .Select(item => new SubjectCRCImageUploadedStudyDto - { - VisitTaskId = item.VisitTaskId, - SubjectId = item.SubjectId, - SubjectCode = item.SubjectCode, - TaskBlindName = item.TaskBlindName, - TaskName = item.TaskName, - IsImageFilter = item.IsImageFilter, - CriterionModalitys = item.CriterionModalitys, - SourceSubjectVisitId = item.SourceSubjectVisitId, - //非dicom - NoneDicomStudyList = item.NoneDicomStudyList, - }).ToList(); - - - result.AddRange(dicomStudyList); - result.AddRange(noneStudyList); - #endregion - - - return result; - - } - - /// - /// IR 阅片页面获取下载检查的信息 会根据标准进行过滤检查,(后端要考虑到一致性分析 subjectCode的问题) - /// 检查在访视下面,所以需要传递下载的访视Id,另外下载访视下面那些检查,就把访视下的对应的检查Id 丢到数组里就好 - /// - /// - /// - /// - [HttpPost] - public async Task GetIRReadingDownloadStudyInfo(IRDownloadQuery inQuery, [FromServices] IRepository _subjectRepository) - { - var info = await _readingQuestionCriterionTrialRepository.Where(t => t.Id == inQuery.TrialReadingCriterionId) - .Select(t => new { t.IsImageFilter, t.CriterionModalitys }).FirstNotNullAsync(); - - var isQueryDicom = inQuery.DicomStudyIdList.Count > 0; - var isQueryNoneDicom = inQuery.NoneDicomStudyIdList.Count > 0; - - var query = from sv in _subjectRepository.Where(t => t.Id == inQuery.SubjectId).SelectMany(t => t.SubjectVisitList.Where(t => inQuery.SubjectVisitIdList.Contains(t.Id))) - - select new - { - SubjectCode = sv.Subject.Code, - VisitName = sv.VisitName, - StudyList = sv.StudyList.Where(t => isQueryDicom ? inQuery.DicomStudyIdList.Contains(t.Id) : false) - .Select(u => new - { - u.PatientId, - u.StudyTime, - u.StudyCode, - - SeriesList = u.SeriesList.Select(z => new - { - z.Modality, - - InstancePathList = z.DicomInstanceList.Select(k => new - { - k.Path - }) - }) - - }), - - NoneDicomStudyList = sv.NoneDicomStudyList.Where(t => isQueryNoneDicom ? inQuery.NoneDicomStudyIdList.Contains(t.Id) : false) - .Select(nd => new - { - nd.Modality, - nd.StudyCode, - nd.ImageDate, - - FileList = nd.NoneDicomFileList.Select(file => new - { - file.FileName, - file.Path, - file.FileType - }) - }) - }; - - - - var result = await query.FirstOrDefaultAsync(); - - return ResponseOutput.Ok(result); - } - } diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/NoneDicomStudyService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/NoneDicomStudyService.cs index 63a74b56f..6bf86433b 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/NoneDicomStudyService.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/NoneDicomStudyService.cs @@ -137,14 +137,14 @@ namespace IRaCIS.Core.Application.Contracts public async Task> GetNoneDicomStudyFileList(Guid noneDicomStudyId) { return await _noneDicomStudyFileRepository.Where(t => t.NoneDicomStudyId == noneDicomStudyId) - .ProjectTo(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken }).ToListAsync(); + .ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); } [HttpGet("{subjectVisitId:guid}")] public async Task> GetVisitNoneDicomStudyFileList(Guid subjectVisitId) { return await _noneDicomStudyFileRepository.Where(t => t.NoneDicomStudy.SubjectVisitId == subjectVisitId) - .ProjectTo(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken }).ToListAsync(); + .ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); } diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs index 2eb2fe4e0..ef6d6c0c9 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs @@ -740,6 +740,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc var visitList = _subjectVisitRepository.Where(t => t.SubjectId == verifyInfo.SubjectId).Select(t => new { t.VisitNum, t.EarliestScanDate, t.LatestScanDate, t.Id }).ToList(); + var currentVisitNum = visitList.Where(t => t.Id == verifyInfo.SubjectVisitId).First().VisitNum; verifyInfo.StudyInstanceUidList.ForEach(waitUploadItem => { @@ -748,7 +749,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc { //小于当前访视 最近的最晚拍片 - var before = visitList.Where(u => u.VisitNum < verifyInfo.VisitNum).Max(k => k.LatestScanDate); + var before = visitList.Where(u => u.VisitNum < currentVisitNum).Max(k => k.LatestScanDate); if (before != null && waitUploadItem.StudyDate != null && before > waitUploadItem.StudyDate) { @@ -759,7 +760,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc } //大于当前访视 最近的最早拍片日期 - var after = visitList.Where(u => u.VisitNum > verifyInfo.VisitNum).Min(k => k.EarliestScanDate); + var after = visitList.Where(u => u.VisitNum > currentVisitNum).Min(k => k.EarliestScanDate); if (after != null && waitUploadItem.StudyDate != null && after < waitUploadItem.StudyDate) { diff --git a/IRaCIS.Core.Application/Service/QC/QCListService.cs b/IRaCIS.Core.Application/Service/QC/QCListService.cs index 3d838ea42..eab79edba 100644 --- a/IRaCIS.Core.Application/Service/QC/QCListService.cs +++ b/IRaCIS.Core.Application/Service/QC/QCListService.cs @@ -638,7 +638,7 @@ namespace IRaCIS.Core.Application.Image.QA public async Task> GetSubjectVisitSelectList(Guid subjectId) { - var maxNum = await _visitTaskRepository.Where(t => t.SubjectId == subjectId && t.TaskState == TaskState.Effect && t.SignTime != null && t.TrialReadingCriterion.IsReadingTaskViewInOrder == ReadingOrder.InOrder).MaxAsync(x => x.VisitTaskNum); + var maxNum = await _visitTaskRepository.Where(t => t.SubjectId == subjectId && t.TaskState == TaskState.Effect && t.SignTime != null && t.TrialReadingCriterion.IsReadingTaskViewInOrder == ReadingOrder.InOrder).MaxAsync(x => (decimal?)x.VisitTaskNum)??0; return await _subjectVisitRepository.Where(t => t.SubjectId == subjectId&&t.VisitNum>= maxNum).OrderBy(T => T.VisitNum).ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); diff --git a/IRaCIS.Core.Application/Service/QC/_MapConfig.cs b/IRaCIS.Core.Application/Service/QC/_MapConfig.cs index 3ad2ace1a..4be1b0a52 100644 --- a/IRaCIS.Core.Application/Service/QC/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/QC/_MapConfig.cs @@ -590,7 +590,7 @@ namespace IRaCIS.Core.Application.Service CreateMap() - .ForMember(d => d.FullFilePath, u => u.MapFrom(s => s.Path + "?access_token=" + token)); + .ForMember(d => d.FullFilePath, u => u.MapFrom(s => s.Path)); CreateMap() //.ForMember(d => d.FileCount, u => u.MapFrom(s => s.NoneDicomFileList.Count)) diff --git a/IRaCIS.Core.Application/Service/Visit/DTO/PatientViewModel.cs b/IRaCIS.Core.Application/Service/Visit/DTO/PatientViewModel.cs index 2409b3028..fe54d8536 100644 --- a/IRaCIS.Core.Application/Service/Visit/DTO/PatientViewModel.cs +++ b/IRaCIS.Core.Application/Service/Visit/DTO/PatientViewModel.cs @@ -382,6 +382,8 @@ namespace IRaCIS.Application.Contracts } + + public class VerifyPacsImageCommand { [NotDefault] diff --git a/IRaCIS.Core.Application/Service/Visit/DTO/VisitPointViewModel.cs b/IRaCIS.Core.Application/Service/Visit/DTO/VisitPointViewModel.cs index 382023c91..31e34b7b0 100644 --- a/IRaCIS.Core.Application/Service/Visit/DTO/VisitPointViewModel.cs +++ b/IRaCIS.Core.Application/Service/Visit/DTO/VisitPointViewModel.cs @@ -419,7 +419,6 @@ namespace IRaCIS.Core.Application.Contracts public Guid SubjectVisitId { get; set; } - public decimal VisitNum { get; set; } public List StudyInstanceUidList { get; set; } = new List(); } diff --git a/IRaCIS.Core.Domain/_Config/_AppSettings.cs b/IRaCIS.Core.Domain/_Config/_AppSettings.cs index fac748828..ef84fe0c5 100644 --- a/IRaCIS.Core.Domain/_Config/_AppSettings.cs +++ b/IRaCIS.Core.Domain/_Config/_AppSettings.cs @@ -108,9 +108,12 @@ namespace IRaCIS.Core.Domain.Share public static string DicomStudyCodePrefix { get; set; } + public static string TaskStudyCodePrefix { get; set; } + public static string NoneDicomStudyCodePrefix { get; set; } + public static int ImageShareExpireDays { get; set; } = 7; @@ -141,7 +144,7 @@ namespace IRaCIS.Core.Domain.Share DicomStudyCodePrefix = configuration.GetSection("IRaCISBasicConfig").GetValue("DicomStudyCodePrefix"); DefaultPassword = configuration.GetSection("IRaCISBasicConfig").GetValue("DefaultPassword"); SystemSiteCodePrefix = configuration.GetSection("IRaCISBasicConfig").GetValue("SystemSiteCodePrefix"); - + TaskStudyCodePrefix = configuration.GetSection("IRaCISBasicConfig").GetValue("TaskStudyCodePrefix"); ImageShareExpireDays = configuration.GetSection("IRaCISBasicConfig").GetValue("ImageShareExpireDays"); @@ -175,6 +178,10 @@ namespace IRaCIS.Core.Domain.Share return DicomStudyCodePrefix + codeInt.ToString("D5"); + case nameof(TaskStudy): + + return TaskStudyCodePrefix + codeInt.ToString("D5"); + case nameof(VisitTask): return "W" + codeInt.ToString("D5"); diff --git a/IRaCIS.Core.Test/IRaCIS.Core.Test.csproj b/IRaCIS.Core.Test/IRaCIS.Core.Test.csproj index 512ce8727..46a07fc5e 100644 --- a/IRaCIS.Core.Test/IRaCIS.Core.Test.csproj +++ b/IRaCIS.Core.Test/IRaCIS.Core.Test.csproj @@ -20,6 +20,9 @@ Always + + Always + Always @@ -69,6 +72,7 @@ + @@ -77,7 +81,7 @@ - + diff --git a/IRaCIS.Core.Test/Program.cs b/IRaCIS.Core.Test/Program.cs index c9771b296..6dd7114f1 100644 --- a/IRaCIS.Core.Test/Program.cs +++ b/IRaCIS.Core.Test/Program.cs @@ -1,12 +1,12 @@  using Fluid; using IRaCIS.Core.Infra.EFCore; -using IRaCIS.Core.Test.Template; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text; partial class Program @@ -47,29 +47,11 @@ partial class Program } #endregion - using (var context = new YourDbContext()) - { - var model = context.Model; - foreach (var entityType in model.GetEntityTypes()) - { - string tableName = entityType.GetTableName(); - Console.WriteLine($"Table: {tableName}"); - - foreach (var property in entityType.GetProperties()) - { - string columnName = property.GetColumnName(); - string dataType = property.ClrType.Name; - bool isNullable = property.IsNullable; - - Console.WriteLine($" Column: {columnName}, Data Type: {dataType}, Is Nullable: {isNullable}"); - } - } - } // 要生成的表名数组 - var tableNames = new List { "Product"/*, "Order"*/ }; + var tableNames = new List { "Subject"/*, "Order"*/ }; try { @@ -77,7 +59,7 @@ partial class Program foreach (var templateFilePath in Directory.GetFiles(templateFolderPath)) { - var fileName=Path.GetFileNameWithoutExtension(templateFilePath); + var fileName = Path.GetFileNameWithoutExtension(templateFilePath); //模板放入具体的文件夹 //var folder = fileName == "Entity" ? "Entity" : fileName.Replace("Entity", ""); @@ -88,9 +70,13 @@ partial class Program { TableName = tableName, - IsPaged = true + IsPaged = true, + + TableFieLdList = GetTableFiledList(tableName) }; + var options = new TemplateOptions(); + options.MemberAccessStrategy.Register(); var parser = new FluidParser(); @@ -98,12 +84,13 @@ partial class Program if (parser.TryParse(source, out var template, out var error)) { - var context = new TemplateContext(model); + var context = new TemplateContext(model, options, true); //Console.WriteLine(template.Render(context)); string outputFilePath = Path.Combine(outPutTemplateFolderPath, /*folder,*/ $"{fileName.Replace("Entity", tableName)}.cs"); + File.WriteAllText(outputFilePath, template.Render(context)); } else @@ -133,6 +120,23 @@ partial class Program //生成的列表是是分页 还是不分页 public bool IsPaged { get; set; } + public DateTime DateTimeNow = DateTime.Now; + + + public List TableFieLdList { get; set; } + + + + + public List AddOrUpdateFieldList => TableFieLdList.Where(t => !AddOrUpdateExcludeNameList.Contains(t.FieldName)).ToList(); + public List ViewListFieldList => TableFieLdList.Where(t => ListInCludeNameList.Contains(t.FieldName)).ToList(); + public List QueryListFieldList => TableFieLdList.Where(t => !AddOrUpdateExcludeNameList.Contains(t.FieldName) && t.IsPrimarykey==false).ToList(); + + //添加和更新模型排除的字段名 + public List AddOrUpdateExcludeNameList = new List() { "CreateUserId", "UpdateUserId", "CreateTime", "UpdateTime", "DeleteUserId", "IsDeleted", "DeletedTime" }; + + public List ListInCludeNameList = new List() { "CreateTime", "UpdateTime" }; + // 列表视图模型名称 public string TableNameView => TableName + "View"; //列表查询模型名称 @@ -142,10 +146,120 @@ partial class Program //删除主键属性名 public string LowercaseTableNameId => char.ToLower(TableName[0]) + TableName.Substring(1) + "Id"; - public string LowercaseRepositoryName => $"_{char.ToLower(TableName[0]) + TableName.Substring(1)}Repository" ; + public string LowercaseRepositoryName => $"_{char.ToLower(TableName[0]) + TableName.Substring(1)}Repository"; public string LowercaseQueryableName => $"{char.ToLower(TableName[0]) + TableName.Substring(1)}Queryable"; - public DateTime DateTimeNow = DateTime.Now; } + + public class TableProperty + { + public string ColumnName { get; set; } + public string FieldName { get; set; } + + public string CSharpType { get; set; } + + public bool IsNullable { get; set; } + + // 自动赋值 String.Empty 避免 数据库存储Null + public bool IsCSharpString => CSharpType.ToLower() == "string"; + + public int? MaxLength { get; set; } + + public bool IsPrimarykey { get; set; } + + } + + + private static List GetTableFiledList(string tableName) + { + + #region 直接通过上下文拿到实体信息 + + + var contextOptions = new DbContextOptionsBuilder().UseSqlServer(@"Server=106.14.89.110,1435;Database=Test_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true").Options; + + using var dbContext = new IRaCISDBContext(contextOptions); + + var dbModel = dbContext.Model; + + var entityType = dbModel.GetEntityTypes().Where(t => t.GetTableName() == tableName).FirstOrDefault(); + + if (entityType != null) + { + var list = entityType.GetProperties().Select(property => new TableProperty() + { + FieldName = property.Name, + ColumnName = property.GetColumnName(), + IsNullable = property.IsNullable, + IsPrimarykey = property.IsKey(), + CSharpType = GetCSharpType(property.ClrType), + }).ToList(); + + return list; + } + + return new List(); + + #endregion + } + + static string GetCSharpType(Type type) + { + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) + { + var underlyingType = Nullable.GetUnderlyingType(type); + return $"{GetCSharpType(underlyingType)}?"; + } + + return type switch + { + _ when type == typeof(int) => "int", + _ when type == typeof(long) => "long", + _ when type == typeof(short) => "short", + _ when type == typeof(byte) => "byte", + _ when type == typeof(bool) => "bool", + _ when type == typeof(decimal) => "decimal", + _ when type == typeof(double) => "double", + _ when type == typeof(float) => "float", + _ when type == typeof(Guid) => "Guid", + _ when type == typeof(DateTime) => "DateTime", + _ when type == typeof(string) => "string", + _ => type.Name // 非常见类型,返回 .NET 类型名称 + }; + } + + #region 核对code first 暂时屏蔽 + + public void CheckCodeFirst() + { + var contextOptions = new DbContextOptionsBuilder().UseSqlServer(@"Server=106.14.89.110,1435;Database=Test_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true").Options; + + using var dbContext = new IRaCISDBContext(contextOptions); + + var dbModel = dbContext.Model; + + foreach (var entityType in dbModel.GetEntityTypes()) + { + string tableName = entityType.GetTableName(); + Console.WriteLine($"Table: {tableName}"); + + foreach (var property in entityType.GetProperties()) + { + string columnName = property.GetColumnName(); + string dataType = property.ClrType.Name; + bool isNullable = property.IsNullable; + int? maxLength = property.GetMaxLength(); // 获取最大长度 + string columnType = property.GetColumnType(); // 获取数据库中的列类型 + bool isKey = property.IsKey(); // 判断是否为主键 + bool isIndex = property.IsIndex(); // 判断是否是索引 + object defaultValue = property.GetDefaultValue(); // 获取默认值 + bool isGenerated = property.ValueGenerated != Microsoft.EntityFrameworkCore.Metadata.ValueGenerated.Never; // 判断是否是自动生成的值 + + Console.WriteLine($" Column: {columnName}, Data Type: {dataType}, Is Nullable: {isNullable}, Max Length: {maxLength}, Column Type: {columnType}, Is Key: {isKey}, Is Index: {isIndex}, Default Value: {defaultValue}, Is Generated: {isGenerated}"); + } + } + } + + #endregion } diff --git a/IRaCIS.Core.Test/Template/EntityViewModel.liquid b/IRaCIS.Core.Test/Template/EntityViewModel.liquid new file mode 100644 index 000000000..1face3652 --- /dev/null +++ b/IRaCIS.Core.Test/Template/EntityViewModel.liquid @@ -0,0 +1,44 @@ + +//-------------------------------------------------------------------- +// 此代码由T4模板自动生成 byzhouhang 20210918 +// 生成时间 {{DateTimeNow}} +// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 +//-------------------------------------------------------------------- +using System; +using IRaCIS.Core.Domain.Share; +using System.Collections.Generic; +namespace IRaCIS.Core.Application.ViewModel +{ + public class {{ TableNameView }} : {{ TableNameAddOrEdit }} + { + {% for field in ViewListFieldList %} + public {{ field.CSharpType }} {{ field.FieldName }} { get; set; } + {% endfor %} + } + + + public class {{ TableNameAddOrEdit }} + { + {%- for field in AddOrUpdateFieldList -%} + {% if field.IsPrimarykey %} + public {{ field.CSharpType }}? {{ field.FieldName }} { get; set; } + {% else %} + public {{ field.CSharpType }} {{ field.FieldName }} { get; set; } + {% endif %} + {%- endfor -%} + } + + public class {{ TableNameQuery }} + { + {%- for field in QueryListFieldList -%} + {% if field.IsNullable and field.IsCSharpString == false %} + public {{ field.CSharpType }} {{ field.FieldName }} { get; set; } + {% else %} + public {{ field.CSharpType }}? {{ field.FieldName }} { get; set; } + {% endif %} + {%- endfor -%} + } +} + + + diff --git a/IRaCIS.Core.Test/Template/IEntityService.liquid b/IRaCIS.Core.Test/Template/IEntityService.liquid index 37c1016f9..7bd0beea6 100644 --- a/IRaCIS.Core.Test/Template/IEntityService.liquid +++ b/IRaCIS.Core.Test/Template/IEntityService.liquid @@ -6,17 +6,14 @@ //-------------------------------------------------------------------- using IRaCIS.Core.Application.ViewModel; namespace IRaCIS.Core.Application.Interfaces - { - +{ public interface I{{TableName}}Service { - {% if IsPaged %} - Task> Get{{TableName}}List({{TableNameQuery}} inQuery); + Task> Get{{TableName}}List({{TableNameQuery}} inQuery); {% else %} - Task> Get{{TableName}}List({{TableNameQuery}} inQuery); + Task> Get{{TableName}}List({{TableNameQuery}} inQuery); {% endif %} - Task AddOrUpdate{{TableName}}({{TableNameAddOrEdit}} addOrEdit{{TableName}}); Task Delete{{TableNameView}}(Guid {{LowercaseTableNameId}}); diff --git a/IRaCIS.Core.Test/YourDbContext.cs b/IRaCIS.Core.Test/YourDbContext.cs deleted file mode 100644 index 09593fc25..000000000 --- a/IRaCIS.Core.Test/YourDbContext.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace IRaCIS.Core.Test.Template -{ - class YourDbContext : DbContext - { - - - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - { - optionsBuilder.UseSqlServer("Server=106.14.89.110,1435;Database=Test_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true"); - } - - } -}