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 passing Details

Test_IRC_Net8
he 2025-06-09 10:19:03 +08:00
commit 1c7f4eac90
10 changed files with 438 additions and 40 deletions

View File

@ -549,20 +549,6 @@
</summary>
<returns></returns>
</member>
<member name="T:IRaCIS.Core.Application.Service.BackDownloadService">
<summary>
项目影像后台下载,不打包
</summary>
<param name="_trialRepository"></param>
<param name="_oSSService"></param>
</member>
<member name="M:IRaCIS.Core.Application.Service.BackDownloadService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Application.Helper.IOSSService,Microsoft.AspNetCore.Hosting.IWebHostEnvironment)">
<summary>
项目影像后台下载,不打包
</summary>
<param name="_trialRepository"></param>
<param name="_oSSService"></param>
</member>
<member name="T:IRaCIS.Core.Application.Service.CommonDocumentService">
<summary>
系统模板文档配置表
@ -1067,6 +1053,27 @@
PublishLogService
</summary>
</member>
<member name="T:IRaCIS.Core.Application.Service.TrialImageDownloadService">
<summary>
项目影像后台下载,不打包
</summary>
<param name="_trialRepository"></param>
<param name="_oSSService"></param>
</member>
<member name="M:IRaCIS.Core.Application.Service.TrialImageDownloadService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Application.Helper.IOSSService,Microsoft.AspNetCore.Hosting.IWebHostEnvironment)">
<summary>
项目影像后台下载,不打包
</summary>
<param name="_trialRepository"></param>
<param name="_oSSService"></param>
</member>
<member name="M:IRaCIS.Core.Application.Service.TrialImageDownloadService.DownloadTrialImage(System.Guid)">
<summary>
后端api swagger 下载项目影像
</summary>
<param name="trialId"></param>
<returns></returns>
</member>
<member name="T:IRaCIS.Core.Application.Service.AttachmentService">
<summary>
医生文档关联关系维护
@ -2047,6 +2054,14 @@
<param name="inQuery"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ImageAndDoc.DownloadAndUploadService.UpdateTaskStudyModality(System.Guid,System.String)">
<summary>
更新后处理上传的检查modality
</summary>
<param name="taskStudyId"></param>
<param name="modality"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ImageAndDoc.DownloadAndUploadService.DownloadImageSuccess(System.Guid)">
<summary>
影像下载成功回调
@ -2061,12 +2076,18 @@
<param name="inQuery"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ImageAndDoc.DownloadAndUploadService.UpdateTaskStudyModality(System.Guid,System.String)">
<member name="M:IRaCIS.Core.Application.Service.ImageAndDoc.DownloadAndUploadService.GetTrialVisitImageStatInfo(System.Guid)">
<summary>
更新后处理上传的检查modality
获取项目影像统计有影像的subject 数量 访视数量
</summary>
<param name="taskStudyId"></param>
<param name="modality"></param>
<param name="trialId"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ImageAndDoc.DownloadAndUploadService.GetExportSubjectVisitImageList(IRaCIS.Core.Application.Contracts.TrialExportImageCommand)">
<summary>
批量勾选访视 进行下载
</summary>
<param name="inCommand"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ImageAndDoc.DownloadAndUploadService.GetSubejectOrVisitZipInfo(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Subject},IRaCIS.Core.Application.Contracts.SubejctZipInfoQuery)">
@ -16080,6 +16101,13 @@
系统邮件配置表
</summary>
</member>
<member name="M:IRaCIS.Core.Application.Contracts.EmailNoticeConfigService.BatchUpdateEmail(System.Collections.Generic.List{IRaCIS.Core.Application.Contracts.BatchUpdateEmailTopicCommand})">
<summary>
批量更新邮件主题中英文
</summary>
<param name="inCommandList"></param>
<returns></returns>
</member>
<member name="T:IRaCIS.Core.Application.Contracts.ISystemBasicDataService">
<summary>
ISystemBasicDataService

View File

@ -143,6 +143,17 @@ namespace IRaCIS.Core.Application.Contracts
}
public class BatchUpdateEmailTopicCommand
{
[NotDefault]
public Guid Id { get; set; }
public string EmailTopic { get; set; } = string.Empty;
public string EmailTopicCN { get; set; } = string.Empty;
}
public class EmailNoticeConfigExportDto
{
public Guid? Id { get; set; }

View File

@ -41,6 +41,44 @@ namespace IRaCIS.Core.Application.Contracts
return await emailNoticeConfigQueryable.ToPagedListAsync(inQuery);
}
/// <summary>
/// 批量更新邮件主题中英文
/// </summary>
/// <param name="inCommandList"></param>
/// <returns></returns>
public async Task<IResponseOutput> BatchUpdateEmail(List<BatchUpdateEmailTopicCommand> inCommandList)
{
var findIdList = inCommandList.Select(x => x.Id).ToList();
var regex = new Regex(@"\{\s*\d+\s*\}");
foreach (var inCommand in inCommandList)
{
if (regex.Matches($"{inCommand.EmailTopic}{inCommand.EmailTopicCN}")
.Any(t => t.Value.Contains(" ")))
{
//邮件模板占位符不允许有空格,请核查占位符的地方
return ResponseOutput.NotOk(I18n.T("EmailNoticeConfig_ContainEmpty"));
}
}
var list = _emailNoticeConfigrepository.Where(t => findIdList.Contains(t.Id), true).ToList();
foreach (var item in list)
{
var exist = inCommandList.FirstOrDefault(t => t.Id == item.Id);
if (exist != null)
{
item.EmailTopic = exist.EmailTopic;
item.EmailTopicCN = exist.EmailTopicCN;
}
}
await _emailNoticeConfigrepository.SaveChangesAsync();
return ResponseOutput.Ok();
}
public async Task<IResponseOutput> AddOrUpdateEmailNoticeConfig(EmailNoticeConfigAddOrEdit addOrEditEmailNoticeConfig)
{

View File

@ -22,20 +22,31 @@ namespace IRaCIS.Core.Application.Service
/// </summary>
/// <param name="_trialRepository"></param>
/// <param name="_oSSService"></param>
[AllowAnonymous]
[ApiExplorerSettings(GroupName = "Common")]
public class BackDownloadService(IRepository<Trial> _trialRepository, IOSSService _oSSService, IWebHostEnvironment _hostEnvironment) : BaseService
public class TrialImageDownloadService(IRepository<Trial> _trialRepository, IOSSService _oSSService, IWebHostEnvironment _hostEnvironment) : BaseService
{
/// <summary>
/// 后端api swagger 下载项目影像
/// </summary>
/// <param name="trialId"></param>
/// <returns></returns>
[HttpPost]
[AllowAnonymous]
public async Task<IResponseOutput> DownloadTrialImage(Guid trialId)
{
var subjectCodeList = new List<string>() { "S040001", "S140001", "S190002" };
var downloadInfo = _trialRepository.Where(t => t.Id == trialId).Select(t => new
{
t.ResearchProgramNo,
VisitList = t.SubjectVisitList.Select(sv => new
VisitList = t.SubjectVisitList.Where(t=>subjectCodeList.Contains(t.Subject.Code)).Select(sv => new
{
TrialSiteCode = sv.TrialSite.TrialSiteCode,
SubjectCode = sv.Subject.Code,

View File

@ -546,6 +546,110 @@ namespace IRaCIS.Core.Application.Contracts
}
public class TrialExportImageCommand
{
[NotDefault]
public Guid TrialId { get; set; }
public List<Guid> SubjectVisitIdList { get; set; }
public bool IsKeyImage { get; set; }
}
public class TrialVisitImageQuery : PageInput
{
[NotDefault]
public Guid TrialId { get; set; }
public Guid? TrialSiteId { get; set; }
public string? SubjectCode { get; set; }
public DateTime? BeginScanDate { get; set; }
public DateTime? EndScanDate { get; set; }
}
public class TrialVisitImageStatView
{
public Guid TrialId { get; set; }
public Guid SubjectVisitId { get; set; }
public Guid TrialSiteId { get; set; }
public string TrialSiteCode { get; set; }
public string SubjectCode { get; set; }
public string VisitName { get; set; }
public decimal VisitNum { get; set; }
public DateTime? EarliestScanDate { get; set; }
public DateTime? LatestScanDate { get; set; }
public int TotalStudyCount { get; set; }
public int TotalImageCount { get; set; }
public long? TotalImageSize { get; set; }
public string TotalImageSizeStr => TotalImageSize.HasValue
? $"{TotalImageSize.Value / 1024d / 1024d:F3} MB"
: "0.000 MB";
#region 废弃,为了字段排序
//public int TotalStudyCount => DicomStudyCount + NoneDicomStudyCount;
//public int TotalImageCount => DicomImageCount + NoneDicomImageCount;
//public long? TotalImageSize => DicomImageSize + NoneDicomImageSize;
//public int DicomStudyCount { get; set; }
//public int DicomImageCount { get; set; }
//public long? DicomImageSize { get; set; }
//public int NoneDicomStudyCount { get; set; }
//public int NoneDicomImageCount { get; set; }
//public long? NoneDicomImageSize { get; set; }
#endregion
}
public class TrialImageStatInfo
{
public int SubjectCount { get; set; }
public int SubjectVisitCount { get; set; }
public long? TotalImageSize { get; set; }
public string TotalImageSizeStr => TotalImageSize.HasValue
? $"{TotalImageSize.Value / 1024d / 1024d:F3} MB"
: "0.000 MB";
public string SubjectImageAVGSizeStr => TotalImageSize.HasValue
? $"{TotalImageSize.Value / SubjectCount / 1024d / 1024d:F3} MB"
: "0.000 MB";
public string SubjectVisitImageAVGSizeStr => TotalImageSize.HasValue
? $"{TotalImageSize.Value / SubjectVisitCount / 1024d / 1024d:F3} MB"
: "0.000 MB";
}
public class TrialImageDownloadView
{
public Guid TrialId { get; set; }

View File

@ -1117,7 +1117,18 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
}
/// <summary>
/// 更新后处理上传的检查modality
/// </summary>
/// <param name="taskStudyId"></param>
/// <param name="modality"></param>
/// <returns></returns>
[HttpPut]
public async Task<IResponseOutput> UpdateTaskStudyModality(Guid taskStudyId, string modality)
{
await _taskStudyRepository.UpdatePartialFromQueryAsync(t => t.Id == taskStudyId, u => new TaskStudy() { ModalityForEdit = modality }, true);
return ResponseOutput.Ok();
}
/// <summary>
/// 影像下载成功回调
@ -1154,19 +1165,174 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
return await query.ToPagedListAsync(inQuery);
}
/// <summary>
/// 更新后处理上传的检查modality
/// </summary>
/// <param name="taskStudyId"></param>
/// <param name="modality"></param>
/// <returns></returns>
[HttpPut]
public async Task<IResponseOutput> UpdateTaskStudyModality(Guid taskStudyId, string modality)
#region 影像汇总页面
public async Task<IResponseOutput<PageOutput<TrialVisitImageStatView>>> GetTrialVisitImageStatList(TrialVisitImageQuery inQuery)
{
await _taskStudyRepository.UpdatePartialFromQueryAsync(t => t.Id == taskStudyId, u => new TaskStudy() { ModalityForEdit = modality }, true);
return ResponseOutput.Ok();
var query = _subjectVisitRepository.Where(t => t.TrialId == inQuery.TrialId)
.WhereIf(inQuery.TrialSiteId != null, t => t.TrialSiteId == inQuery.TrialSiteId)
.WhereIf(inQuery.SubjectCode.IsNotNullOrEmpty(), t => t.Subject.Code.Contains(inQuery.SubjectCode))
.WhereIf(inQuery.BeginScanDate != null, t => t.LatestScanDate >= inQuery.BeginScanDate)
.WhereIf(inQuery.EndScanDate != null, t => t.LatestScanDate == inQuery.EndScanDate)
.Select(t => new TrialVisitImageStatView()
{
TrialId = t.TrialId,
SubjectCode = t.Subject.Code,
TrialSiteCode = t.TrialSite.TrialSiteCode,
TrialSiteId = t.TrialSiteId,
VisitName = t.VisitName,
VisitNum = t.VisitNum,
EarliestScanDate = t.EarliestScanDate,
LatestScanDate = t.LatestScanDate,
TotalStudyCount = t.StudyList.Count() + t.NoneDicomStudyList.Count(),
TotalImageCount = t.StudyList.Sum(t => t.InstanceCount) + t.NoneDicomStudyList.Sum(t => t.FileCount),
TotalImageSize = t.StudyList.SelectMany(t => t.InstanceList).Sum(t => t.FileSize) + t.NoneDicomStudyList.SelectMany(t => t.NoneDicomFileList).Sum(t => t.FileSize),
//DicomStudyCount = t.StudyList.Count(),
//NoneDicomStudyCount = t.NoneDicomStudyList.Count(),
//DicomImageCount = t.StudyList.Sum(t => t.InstanceCount),
//NoneDicomImageCount = t.NoneDicomStudyList.Sum(t => t.FileCount),
//DicomImageSize = t.StudyList.SelectMany(t => t.InstanceList).Sum(t => t.FileSize),
//NoneDicomImageSize = t.NoneDicomStudyList.SelectMany(t => t.NoneDicomFileList).Sum(t => t.FileSize)
});
var pagelist = await query.ToPagedListAsync(inQuery);
return ResponseOutput.Ok(pagelist);
}
/// <summary>
/// 获取项目影像统计有影像的subject 数量 访视数量
/// </summary>
/// <param name="trialId"></param>
/// <returns></returns>
public async Task<IResponseOutput> GetTrialVisitImageStatInfo(Guid trialId)
{
var subjectImageList = _subjectVisitRepository.Where(t => t.TrialId == trialId)
.Where(t => t.StudyList.Sum(t => t.InstanceCount) > 0 || t.NoneDicomStudyList.Sum(t => t.FileCount) > 0)
.GroupBy(t => t.SubjectId)
.Select(g => new
{
SubjectId = g.Key,
VisitCount = g.Count(),
ImageSize = g.Sum(t => t.NoneDicomStudyList.SelectMany(t => t.NoneDicomFileList).Sum(t => t.FileSize)
+ g.Sum(t => t.StudyList.SelectMany(t => t.InstanceList).Sum(t => t.FileSize)))
})
.ToList();
var subjectCount = subjectImageList.Count;
var subjectVisitCount = subjectImageList.Sum(t => t.VisitCount);
var totalImageSize = subjectImageList.Sum(t => t.ImageSize);
return ResponseOutput.Ok(new TrialImageStatInfo { SubjectCount = subjectCount, SubjectVisitCount = subjectVisitCount, TotalImageSize = totalImageSize });
}
/// <summary>
/// 批量勾选访视 进行下载
/// </summary>
/// <param name="inCommand"></param>
/// <returns></returns>
public async Task<IResponseOutput> GetExportSubjectVisitImageList(TrialExportImageCommand inCommand)
{
if (inCommand.IsKeyImage)
{
var downloadInfo = _visitTaskRepository.Where(t => t.TrialId == inCommand.TrialId && t.ReadingCategory == ReadingCategory.Visit && t.IsAnalysisCreate == false)
.Where(t => inCommand.SubjectVisitIdList.Contains((Guid)t.SourceSubjectVisitId))
.Select(t => new
{
t.Trial.ResearchProgramNo,
CriterionName = t.TrialReadingCriterion.CriterionName,
TrialSiteCode = t.Subject.TrialSite.TrialSiteCode,
SubjectCode = t.Subject.Code,
VisitName = (string?)t.SourceSubjectVisit.VisitName,
QuestionMarkPictureList = t.ReadingTaskQuestionMarkList.SelectMany(c => new List<string>() { c.PicturePath, c.OtherPicturePath }).ToList(),
TableQuestionRowPictureList = t.LesionList.SelectMany(c => new List<string>() { c.PicturePath, c.OtherPicturePath }).ToList(),
IsJudgeSelect = t.JudgeResultTaskId == t.Id
}).FirstOrDefault();
return ResponseOutput.Ok(downloadInfo);
}
else
{
var downloadInfo = _trialRepository.Where(t => t.Id == inCommand.TrialId).Select(t => new
{
t.ResearchProgramNo,
VisitList = t.SubjectVisitList.Where(t => inCommand.SubjectVisitIdList.Contains(t.Id)).Select(sv => new
{
TrialSiteCode = sv.TrialSite.TrialSiteCode,
SubjectCode = sv.Subject.Code,
VisitName = sv.VisitName,
StudyList = sv.StudyList.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.Select(nd => new
{
nd.Modality,
nd.StudyCode,
nd.ImageDate,
FileList = nd.NoneDicomFileList.Select(file => new
{
file.FileName,
file.Path,
file.FileType
})
})
}).ToList()
}).FirstOrDefault();
return ResponseOutput.Ok(downloadInfo);
}
}
#endregion
#region 之前后端下载废弃

View File

@ -79,7 +79,7 @@ namespace IRaCIS.Core.Application.Contracts
/// </summary>
public List<StudyName> StudyNameList { get; set; }
public List<TrialObjectNameConfig> TrialObjectNameList { get; set; }
@ -1040,7 +1040,7 @@ namespace IRaCIS.Core.Application.Contracts
public class TrialSPMConfigCommand
{
public Guid Id { get; set; }
public Guid Id { get; set; }
[Comment("SPM 参与中心调研")]
public bool IsSPMJoinSiteSurvey { get; set; }
@ -1184,6 +1184,9 @@ namespace IRaCIS.Core.Application.Contracts
public class TrialBodyPartView
{
public bool IsStudyUse { get; set; }
public string Code { get; set; }

View File

@ -503,8 +503,9 @@ namespace IRaCIS.Core.Application
&& x.ReadingCriterionPageId == null)
.ProjectTo<TrialReadQuestion>(_mapper.ConfigurationProvider).OrderBy(x => x.ShowOrder).ToListAsync();
return (result, new {
ReadingVersionEnum= trialCriterion.ReadingVersionEnum
return (result, new
{
ReadingVersionEnum = trialCriterion.ReadingVersionEnum
});
}
@ -585,7 +586,7 @@ namespace IRaCIS.Core.Application
await _readingQuestionCriterionTrialRepository.UpdatePartialFromQueryAsync(inDto.TrialReadingCriterionId, x => new ReadingQuestionCriterionTrial()
{
ReadingToolList=inDto.ReadingToolList,
ReadingToolList = inDto.ReadingToolList,
IsImageFilter = inDto.IsImageFilter,
ImageDownloadEnum = inDto.ImageDownloadEnum,
ImageUploadEnum = inDto.ImageUploadEnum,
@ -1334,7 +1335,35 @@ namespace IRaCIS.Core.Application
/// <returns></returns>
public async Task<IResponseOutput<List<TrialBodyPartView>>> GetTrialBodyPartList(Guid trialId)
{
var list = await _trialRepository.Where(t => t.Id == trialId).SelectMany(t => t.TrialBodyPartList).Select(t => new TrialBodyPartView() { Code = t.Code, Name = _userInfo.IsEn_Us ? t.Name : t.NameCN, Id = t.Id, IsHandAdd = t.IsHandAdd }).OrderBy(t=>t.Name).ToListAsync();
var list = await _trialRepository.Where(t => t.Id == trialId)
.SelectMany(t => t.TrialBodyPartList)
.Select(t => new TrialBodyPartView() { Code = t.Code, Name = _userInfo.IsEn_Us ? t.Name : t.NameCN, Id = t.Id, IsHandAdd = t.IsHandAdd })
.OrderBy(t => t.Name).ToListAsync();
var useBodyPart = _trialRepository.Where(t => t.Id == trialId).Select(t => new
{
DicomBodyPartList = t.StudyList.Where(t => t.BodyPartForEdit != "")
.Select(c => c.BodyPartForEdit)
.Distinct(),
NoneDicomBodyPartList = t.NoneDicomStudyList.Where(t => t.BodyPart != "")
.Select(c => c.BodyPart)
.Distinct(),
}).FirstOrDefault();
foreach (var item in list)
{
var useBodyPartList = new List<string>();
if (useBodyPart != null)
{
useBodyPartList = useBodyPart.DicomBodyPartList.Union(useBodyPart.NoneDicomBodyPartList).Distinct().ToList();
}
item.IsStudyUse = useBodyPartList.Any(t => t == item.Name);
}
return ResponseOutput.Ok(list);
}
@ -1417,7 +1446,7 @@ namespace IRaCIS.Core.Application
[HttpPost]
public async Task<IResponseOutput> UpdateTrialStudyNameList(UpdateTrialStudyNameListInDto inDto)
{
var trial = await _trialRepository.FirstOrDefaultAsync(x => x.Id == inDto.TrialId);

View File

@ -9,6 +9,11 @@ namespace IRaCIS.Core.Domain.Models;
public class VisitTask : BaseFullAuditEntity
{
#region 导航属性
[JsonIgnore]
public List<ReadingTaskQuestionMark> ReadingTaskQuestionMarkList { get; set; }
[JsonIgnore]
public List<TaskStudy> TaskStudyList { get; set; }

View File

@ -48,6 +48,9 @@ public partial class Trial : BaseFullDeleteAuditEntity
public List<Subject> SubjectList { get; set; } = new List<Subject>();
[JsonIgnore]
public List<SubjectVisit> SubjectVisitList { get; set; } = new List<SubjectVisit>();
[JsonIgnore]
public List<NoneDicomStudy> NoneDicomStudyList { get; set; }
[JsonIgnore]
public List<DicomStudy> StudyList { get; set; } = new List<DicomStudy>();
[JsonIgnore]