阅片报告功能

Test_HIR_Net8
he 2024-11-14 10:53:23 +08:00
parent 75bf9b394b
commit 44f33fb7f0
25 changed files with 2076 additions and 6 deletions

View File

@ -112,6 +112,18 @@
<Content Update="Resources\zh-CN.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\ReadReoprtTemplate\downLoad\file.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\ReadReoprtTemplate\ReportTemplate_IRECIST_CN_V1.docx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\ReadReoprtTemplate\ReportTemplate_PCWG3_CN_V1.docx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\ReadReoprtTemplate\ReportTemplate_RECIST1.1_CN_V1.docx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ProjectExtensions>

View File

@ -38,6 +38,8 @@ public class AWSOptions
public string ViewEndpoint { get; set; }
public int DurationSeconds { get; set; }
public string Region { get; set; }
public string viewEndpoint { get; set; }
}
public class AliyunOSSOptions

View File

@ -2521,6 +2521,88 @@
<param name="visitTaskId"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.GeneralCalculateService.StringEmptyTurnedLine(System.Collections.Generic.Dictionary{System.String,System.Object})">
<summary>
空转为横线
</summary>
<param name="myDictionary"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.GeneralCalculateService.GetWordPicture(System.String,System.String,System.Int32)">
<summary>
获取word图片
</summary>
<param name="url"></param>
<param name="savePath"></param>
<param name="width"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.GeneralCalculateService.GetWordPicture(System.String,System.String,System.Int32,System.Int32)">
<summary>
获取word图片
</summary>
<param name="url"></param>
<param name="savePath"></param>
<param name="width"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.GeneralCalculateService.GetWordPictureMaxWL(System.String,System.String,System.Int32,System.Int32)">
<summary>
最大宽高
</summary>
<param name="url"></param>
<param name="savePath"></param>
<param name="width"></param>
<param name="height"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.GeneralCalculateService.GetTaskanswer(System.Collections.Generic.List{IRaCIS.Core.Domain.Models.ReadingTaskQuestionAnswer},System.Collections.Generic.List{IRaCIS.Core.Domain.Models.Dictionary},System.Collections.Generic.List{IRaCIS.Core.Domain.Models.Dictionary},System.Guid,IRaCIS.Core.Domain.Share.QuestionType)">
<summary>
获取任务问题答案
</summary>
<param name="answerList">问题答案</param>
<param name="dictionList">字典数据</param>
<param name="unitDictionary">单位字典</param>
<param name="taskId">任务Id</param>
<param name="questionType">任务类型</param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.GeneralCalculateService.GetReportExportNo(IRaCIS.Core.Domain.Models.VisitTask)">
<summary>
获取报告No
</summary>
<param name="visitTaskInfo"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.GeneralCalculateService.ReadAndReturnStream(System.String)">
<summary>
获取并复制文件流
</summary>
<param name="outputFilePath"></param>
<returns></returns>
</member>
<!-- Badly formed XML comment ignored for member "M:IRaCIS.Core.Application.Service.ReadingCalculate.GeneralCalculateService.FileDownSave(System.String,System.String)" -->
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.GeneralCalculateService.GetTaskTableAnswer(System.Collections.Generic.List{IRaCIS.Core.Domain.Models.ReadingTableQuestionAnswer},System.Collections.Generic.List{IRaCIS.Core.Domain.Models.Dictionary},System.Collections.Generic.List{IRaCIS.Core.Domain.Models.Dictionary},System.Guid,IRaCIS.Core.Domain.Share.LesionType,IRaCIS.Core.Domain.Share.QuestionMark,System.Decimal)">
<summary>
获取任务表格问题答案
</summary>
<param name="tableAnswerList">表格答案</param>
<param name="dictionList">字典</param>
<param name="unitDictionary">单位字典</param>
<param name="taskId">任务Id</param>
<param name="lesionType">病灶类型</param>
<param name="questionMark">问题标识</param>
<param name="rowIndex">索引</param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.GeneralCalculateService.GetLesionPic(System.Collections.Generic.List{IRaCIS.Core.Domain.Models.ReadingTableAnswerRowInfo},IRaCIS.Core.Domain.Share.LesionType,System.Guid)">
<summary>
获取病灶的图片 rowinfoList要带question的信息
</summary>
<param name="rowinfoList"></param>
<param name="lesionType"></param>
<returns></returns>
</member>
<member name="F:IRaCIS.Core.Application.Service.ReadingCalculate.ReadingCalculateService.CalculateServiceDic">
<summary>
标准和服务对应
@ -2533,6 +2615,34 @@
<param name="visitTaskId"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.ReadingCalculateService.DownLoadReadReport(IRaCIS.Core.Application.Service.Reading.Dto.DownLoadReadReportInDto)">
<summary>
下载阅片报告
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.ReadingCalculateService.DeleteFile(IRaCIS.Core.Application.Service.Reading.Dto.DownLoadReadReportInDto)">
<summary>
删除文件
</summary>
<param name="inDto"></param>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.ReadingCalculateService.DownLoadReadReportStream(IRaCIS.Core.Application.Service.Reading.Dto.DownLoadReadReportInDto)">
<summary>
下载阅片报告流
</summary>
<param name="inDto"></param>
<returns></returns>
<exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.ReadingCalculateService.GetVisitReadReportUrl(IRaCIS.Core.Application.Service.Reading.Dto.CaGetVisitReadReportUrl)">
<summary>
获取并生成报告URL
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.ReadingCalculateService.CalculateTask(IRaCIS.Core.Application.Service.Reading.Dto.CalculateTaskInDto)">
<summary>
自动计算 并修改值
@ -2601,6 +2711,13 @@
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.IRECIST1Point1CalculateService.DownLoadReadReportStream(IRaCIS.Core.Application.Service.Reading.Dto.DownLoadReadReportInDto)">
<summary>
下载阅片报告
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="F:IRaCIS.Core.Application.Service.ReadingCalculate.IRECIST1Point1CalculateService.sODData">
<summary>
获取Sod的值
@ -2981,6 +3098,13 @@
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.IVUSCalculateService.DownLoadReadReportStream(IRaCIS.Core.Application.Service.Reading.Dto.DownLoadReadReportInDto)">
<summary>
下载阅片报告
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="F:IRaCIS.Core.Application.Service.ReadingCalculate.IVUSCalculateService.sODData">
<summary>
获取Sod的值
@ -3110,6 +3234,13 @@
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.LuganoCalculateService.DownLoadReadReportStream(IRaCIS.Core.Application.Service.Reading.Dto.DownLoadReadReportInDto)">
<summary>
下载阅片报告
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="F:IRaCIS.Core.Application.Service.ReadingCalculate.LuganoCalculateService.sODData">
<summary>
获取Sod的值
@ -3631,6 +3762,13 @@
<param name="digitPlaces"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.LuganoWithoutPETCalculateService.DownLoadReadReportStream(IRaCIS.Core.Application.Service.Reading.Dto.DownLoadReadReportInDto)">
<summary>
下载阅片报告
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.LuganoWithoutPETCalculateService.GetReadingCalculationData(IRaCIS.Core.Application.Service.Reading.Dto.GetReadingCalculationDataInDto)">
<summary>
获取阅片的计算数据
@ -4159,6 +4297,13 @@
<param name="digitPlaces"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.OCTCalculateService.DownLoadReadReportStream(IRaCIS.Core.Application.Service.Reading.Dto.DownLoadReadReportInDto)">
<summary>
下载阅片报告
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.OCTCalculateService.GetReadingCalculationData(IRaCIS.Core.Application.Service.Reading.Dto.GetReadingCalculationDataInDto)">
<summary>
获取阅片的计算数据
@ -4337,6 +4482,13 @@
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.PCWG3CalculateService.DownLoadReadReportStream(IRaCIS.Core.Application.Service.Reading.Dto.DownLoadReadReportInDto)">
<summary>
下载阅片报告
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.PCWG3CalculateService.GetDeleteLesionStatrIndex(IRaCIS.Core.Application.Service.Reading.Dto.DeleteReadingRowAnswerInDto)">
<summary>
删除病灶获取起始病灶序号
@ -4443,6 +4595,13 @@
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.RECIST1Point1CalculateService.DownLoadReadReportStream(IRaCIS.Core.Application.Service.Reading.Dto.DownLoadReadReportInDto)">
<summary>
下载阅片报告
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="F:IRaCIS.Core.Application.Service.ReadingCalculate.RECIST1Point1CalculateService.sODData">
<summary>
获取Sod的值
@ -4694,6 +4853,13 @@
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.RECIST1Point1_BMCalculateService.DownLoadReadReportStream(IRaCIS.Core.Application.Service.Reading.Dto.DownLoadReadReportInDto)">
<summary>
下载阅片报告
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="F:IRaCIS.Core.Application.Service.ReadingCalculate.RECIST1Point1_BMCalculateService.sODData">
<summary>
获取Sod的值
@ -4998,6 +5164,13 @@
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.SelfDefineCalculateService.DownLoadReadReportStream(IRaCIS.Core.Application.Service.Reading.Dto.DownLoadReadReportInDto)">
<summary>
下载阅片报告
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.SelfDefineCalculateService.GetReadingCalculationData(IRaCIS.Core.Application.Service.Reading.Dto.GetReadingCalculationDataInDto)">
<summary>
获取阅片的计算数据
@ -5096,6 +5269,13 @@
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ICriterionCalculateService.DownLoadReadReportStream(IRaCIS.Core.Application.Service.Reading.Dto.DownLoadReadReportInDto)">
<summary>
下载阅片报告
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.IGeneralCalculateService.GetReadingCalculateDto(System.Guid)">
<summary>
获取ReadingCalculateDto
@ -5134,6 +5314,96 @@
<param name="file"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.IGeneralCalculateService.GetWordPicture(System.String,System.String,System.Int32)">
<summary>
获取图片
</summary>
<param name="url"></param>
<param name="savePath"></param>
<param name="width"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.IGeneralCalculateService.GetWordPicture(System.String,System.String,System.Int32,System.Int32)">
<summary>
获取图片
</summary>
<param name="url"></param>
<param name="savePath"></param>
<param name="width"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.IGeneralCalculateService.FileDownSave(System.String,System.String)">
<summary>
下载文件
</summary>
<param name="url"></param>
<param name="savePath"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.IGeneralCalculateService.ReadAndReturnStream(System.String)">
<summary>
获取并复制文件流
</summary>
<param name="outputFilePath"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.IGeneralCalculateService.GetWordPictureMaxWL(System.String,System.String,System.Int32,System.Int32)">
<summary>
最大宽高 保持比例
</summary>
<param name="url"></param>
<param name="savePath"></param>
<param name="width"></param>
<param name="height"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.IGeneralCalculateService.StringEmptyTurnedLine(System.Collections.Generic.Dictionary{System.String,System.Object})">
<summary>
空转为横线
</summary>
<param name="myDictionary"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.IGeneralCalculateService.GetLesionPic(System.Collections.Generic.List{IRaCIS.Core.Domain.Models.ReadingTableAnswerRowInfo},IRaCIS.Core.Domain.Share.LesionType,System.Guid)">
<summary>
获取病灶的图片 rowinfoList要带question的信息
</summary>
<param name="rowinfoList"></param>
<param name="lesionType"></param>
<param name="downLoadGuid"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.IGeneralCalculateService.GetTaskanswer(System.Collections.Generic.List{IRaCIS.Core.Domain.Models.ReadingTaskQuestionAnswer},System.Collections.Generic.List{IRaCIS.Core.Domain.Models.Dictionary},System.Collections.Generic.List{IRaCIS.Core.Domain.Models.Dictionary},System.Guid,IRaCIS.Core.Domain.Share.QuestionType)">
<summary>
获取任务问题答案
</summary>
<param name="answerList">问题答案</param>
<param name="dictionList">字典数据</param>
<param name="unitDictionary">单位字典</param>
<param name="taskId">任务Id</param>
<param name="questionType">任务类型</param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.IGeneralCalculateService.GetTaskTableAnswer(System.Collections.Generic.List{IRaCIS.Core.Domain.Models.ReadingTableQuestionAnswer},System.Collections.Generic.List{IRaCIS.Core.Domain.Models.Dictionary},System.Collections.Generic.List{IRaCIS.Core.Domain.Models.Dictionary},System.Guid,IRaCIS.Core.Domain.Share.LesionType,IRaCIS.Core.Domain.Share.QuestionMark,System.Decimal)">
<summary>
获取任务表格问题答案
</summary>
<param name="tableAnswerList">表格答案</param>
<param name="dictionList">字典</param>
<param name="unitDictionary">单位字典</param>
<param name="taskId">任务Id</param>
<param name="lesionType">病灶类型</param>
<param name="questionMark">问题标识</param>
<param name="rowIndex">索引</param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.IGeneralCalculateService.GetReportExportNo(IRaCIS.Core.Domain.Models.VisitTask)">
<summary>
获取阅片报告
</summary>
<param name="visitTaskInfo"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.IReadingCalculateService.CalculateTask(IRaCIS.Core.Application.Service.Reading.Dto.CalculateTaskInDto)">
<summary>
自动计算 并修改值
@ -5182,6 +5452,27 @@
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.IReadingCalculateService.DownLoadReadReport(IRaCIS.Core.Application.Service.Reading.Dto.DownLoadReadReportInDto)">
<summary>
下载阅片报告
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.IReadingCalculateService.DownLoadReadReportStream(IRaCIS.Core.Application.Service.Reading.Dto.DownLoadReadReportInDto)">
<summary>
获取阅片报告流
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.IReadingCalculateService.GetVisitReadReportUrl(IRaCIS.Core.Application.Service.Reading.Dto.CaGetVisitReadReportUrl)">
<summary>
获取并生成报告URl
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="T:IRaCIS.Core.Application.Service.SubjectCriteriaEvaluationService">
<summary>
SubjectCriteriaEvaluationService
@ -6846,6 +7137,11 @@
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.DownLoadReadReportInDto.VisitTaskId">
<summary>
任务Id
</summary>
</member>
<member name="T:IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto">
<summary>
阅片计算Dto
@ -7486,6 +7782,16 @@
任务Id
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.CaGetVisitReadReportUrl.VisitTaskId">
<summary>
任务Id
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.GenerateReadingReportInDto.VisitTaskId">
<summary>
任务Id
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.GetPreviousOtherPicturePathInDto.QuestionType">
<summary>
问题类型
@ -11896,6 +12202,20 @@
IR影像阅片
</summary>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.DownLoadReadReport(IRaCIS.Core.Application.Service.Reading.Dto.DownLoadReadReportInDto)">
<summary>
下载阅片报告
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.GetVisitReadReportUrl(IRaCIS.Core.Application.Service.Reading.Dto.GenerateReadingReportInDto)">
<summary>
获取阅片报告
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.GetReadingCalculationData(IRaCIS.Core.Application.Service.Reading.Dto.GetReadingCalculationDataInDto)">
<summary>
获取阅片的计算数据

View File

@ -291,6 +291,29 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
public List<string> SheetNames { get; set; }
}
public class ExportReportQuestion
{
public string QuestionName { get; set; }
public QuestionType QuestionType { get; set; }
}
public class DownLoadReadReportInDto
{
/// <summary>
/// 任务Id
/// </summary>
public Guid VisitTaskId { get; set; }
public Guid DownLoadGuid { get; set; }
}
/// <summary>
/// 阅片计算Dto
/// </summary>

View File

@ -446,6 +446,24 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
}
public class CaGetVisitReadReportUrl
{
/// <summary>
/// 任务Id
/// </summary>
public Guid VisitTaskId { get; set; }
}
public class GenerateReadingReportInDto
{
/// <summary>
/// 任务Id
/// </summary>
public Guid VisitTaskId { get; set; }
}
public class GetPreviousOtherPicturePathInDto
{

View File

@ -41,5 +41,7 @@ namespace IRaCIS.Core.Application.Contracts
Task<List<GetReadingPastResultListOutDto>> GetReadingPastResultList(GetReadingPastResultListInDto inDto);
Task<(List<GetRelatedVisitTaskOutDto>, object)> GetRelatedVisitTask(GetRelatedVisitTaskInDto inDto);
}
}

View File

@ -68,6 +68,31 @@ namespace IRaCIS.Core.Application.Service
/// <summary>
/// 下载阅片报告
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<FileResult> DownLoadReadReport(DownLoadReadReportInDto inDto)
{
return await _readingCalculateService.DownLoadReadReport(inDto);
}
/// <summary>
/// 获取阅片报告
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<string> GetVisitReadReportUrl(GenerateReadingReportInDto inDto)
{
return await _readingCalculateService.GetVisitReadReportUrl(new CaGetVisitReadReportUrl()
{
VisitTaskId = inDto.VisitTaskId,
});
}
#region 计算
/// <summary>

View File

@ -3,10 +3,15 @@ using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore.Common;
using IRaCIS.Core.Infrastructure;
using MassTransit;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MiniExcelLibs;
using MiniSoftware;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using System.Data;
using System.IO;
using System.Text;
@ -21,6 +26,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
IRepository<ReadingTableAnswerRowInfo> _readingTableAnswerRowInfoRepository,
IRepository<ReadingQuestionTrial> _readingQuestionTrialRepository,
IRepository<SubjectVisit> _subjectVisitRepository,
IOptionsMonitor<ObjectStoreServiceOptions> _options,
IRepository<TumorAssessment_RECIST1Point1> _tumorAssessmentRepository,
IRepository<ReadingTaskQuestionAnswer> _readingTaskQuestionAnswerRepository,
IRepository<InspectionFile> _inspectionFileRepository,
@ -482,5 +488,381 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
});
return taskInfoList;
}
/// <summary>
/// 空转为横线
/// </summary>
/// <param name="myDictionary"></param>
/// <returns></returns>
public Dictionary<string, object> StringEmptyTurnedLine(Dictionary<string, object> myDictionary)
{
foreach (var item in myDictionary)
{
if (item.Value == null)
{
myDictionary[item.Key] = "-";
}
else if (item.Value.GetType() == typeof(string))
{
if (item.Value.ToString() == string.Empty || item.Value == null)
{
myDictionary[item.Key] = "-";
};
}
else if (item.Value.GetType() == typeof(List<Dictionary<string, object>>))
{
var value = item.Value;
foreach (var column in value as List<Dictionary<string, object>>)
{
foreach (var item2 in column)
{
if (item2.Value.ToString() == string.Empty || item.Value == null)
{
column[item2.Key] = "-";
};
}
}
myDictionary[item.Key] = value;
}
}
return myDictionary;
}
/// <summary>
/// 获取word图片
/// </summary>
/// <param name="url"></param>
/// <param name="savePath"></param>
/// <param name="width"></param>
/// <returns></returns>
public async Task<MiniWordPicture> GetWordPicture(string url, string savePath, int width)
{
var resultUrl = await this.FileDownSave(url, savePath);
int picWidth = 0;
int picHeight = 0;
using (var bitmap = Image<Rgba32>.Load(resultUrl))
{
// 获取图片的宽度和高度
picWidth = bitmap.Width;
picHeight = bitmap.Height;
}
var height = width * picHeight / picWidth;
return new MiniWordPicture()
{
Path = resultUrl,
Height = height,
Width = width
};
}
/// <summary>
/// 获取word图片
/// </summary>
/// <param name="url"></param>
/// <param name="savePath"></param>
/// <param name="width"></param>
/// <returns></returns>
public async Task<MiniWordPicture> GetWordPicture(string url, string savePath, int width, int height)
{
var resultUrl = await this.FileDownSave(url, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"wwwroot/ReadReoprtTemplate/downLoad"));
return new MiniWordPicture()
{
Path = resultUrl,
Height = height,
Width = width
};
}
/// <summary>
/// 最大宽高
/// </summary>
/// <param name="url"></param>
/// <param name="savePath"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <returns></returns>
public async Task<MiniWordPicture> GetWordPictureMaxWL(string url, string savePath, int width, int height)
{
var resultUrl = await this.FileDownSave(url, savePath);
int picWidth = 0;
int picHeight = 0;
using (var bitmap = Image<Rgba32>.Load(resultUrl))
{
// 获取图片的宽度和高度
picWidth = bitmap.Width;
picHeight = bitmap.Height;
}
if (picWidth / picHeight > width / height)
{
height = width * picHeight / picWidth;
}
else
{
width = height * picWidth / picHeight;
}
return new MiniWordPicture()
{
Path = resultUrl,
Height = height,
Width = width
};
}
/// <summary>
/// 获取任务问题答案
/// </summary>
/// <param name="answerList">问题答案</param>
/// <param name="dictionList">字典数据</param>
/// <param name="unitDictionary">单位字典</param>
/// <param name="taskId">任务Id</param>
/// <param name="questionType">任务类型</param>
/// <returns></returns>
public string GetTaskanswer(List<ReadingTaskQuestionAnswer>? answerList, List<Dictionary>? dictionList, List<Dictionary>? unitDictionary, Guid taskId, QuestionType questionType)
{
var answerData = answerList.FirstOrDefault(x => x.VisitTaskId == taskId && x.ReadingQuestionTrial.QuestionType == questionType);
if (answerData == null || answerData.Answer == string.Empty)
{
return string.Empty;
}
var answer = string.Empty;
if (answerData.ReadingQuestionTrial.QuestionGenre == TableQuestionType.Dictionary)
{
answer = dictionList.Where(x => x.Code == answerData.ReadingQuestionTrial.DictionaryCode).SelectMany(x => x.ChildList).Where(x => x.Code == answerData.Answer).Select(x => x.ValueCN).FirstIsNullReturnEmpty();
}
else
{
answer = answerData.Answer;
}
if (answer != "NA" && answerData.ReadingQuestionTrial.Unit != null && answerData.ReadingQuestionTrial.Unit != ValueUnit.none)
{
answer += " " + unitDictionary.SelectMany(x => x.ChildList).Where(x => x.Code == ((int)answerData.ReadingQuestionTrial.Unit).ToString()).Select(x => x.ValueCN).FirstIsNullReturnEmpty();
}
if (answer != "NA" && answerData.ReadingQuestionTrial.ValueType == ValueOfType.Percentage)
{
answer += " %";
}
return answer;
}
/// <summary>
/// 获取报告No
/// </summary>
/// <param name="visitTaskInfo"></param>
/// <returns></returns>
public async Task<string> GetReportExportNo(VisitTask visitTaskInfo)
{
if (visitTaskInfo.ReportExportDate != null && visitTaskInfo.ReportExportNum != null)
{
return visitTaskInfo.ReportExportDate.Value.ToString("yyyyMMdd") + visitTaskInfo.ReportExportNum.ToString().PadLeft(4, '0');
}
else
{
DateTime today = DateTime.Today;
var reportExportNum = await _visitTaskRepository.Where(x => x.TrialId == visitTaskInfo.TrialId && x.ReportExportDate != null && x.ReportExportDate.Value.Date == today).MaxAsync(x => x.ReportExportNum);
reportExportNum = reportExportNum == null ? 0 : reportExportNum;
await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => x.Id == visitTaskInfo.Id, x => new VisitTask()
{
ReportExportDate = today,
ReportExportNum = reportExportNum + 1
});
return today.ToString("yyyyMMdd") + (reportExportNum + 1).ToString().PadLeft(4, '0');
}
}
/// <summary>
/// 获取并复制文件流
/// </summary>
/// <param name="outputFilePath"></param>
/// <returns></returns>
public Stream ReadAndReturnStream(string outputFilePath)
{
byte[] data;
using (Stream stream = new FileStream(outputFilePath, FileMode.Open, FileAccess.Read))
{
// 从流中读取数据保存到内存中
using (MemoryStream memoryStream = new MemoryStream())
{
stream.CopyTo(memoryStream);
data = memoryStream.ToArray();
}
}
// 返回内存中的数据作为新的流
return new MemoryStream(data);
}
/// <summary>
/// 下载并保存
/// </summary>
/// <param name="url">网络路径</param>
/// <param name="savePath">保存本地的文件夹</param>
/// <returns><placeholder>A <see cref="Task"/>
public async Task<string> FileDownSave(string url, string savePath)
{
try
{
HttpClient httpClient = new HttpClient();
if (!string.IsNullOrWhiteSpace(url))
{
string[] strArry = url.Split('/');
savePath = savePath + "/" + strArry[strArry.Length - 1];
}
var t = httpClient.GetByteArrayAsync(url);
t.Wait();
Stream responseStream = new MemoryStream(t.Result);
Stream stream = new FileStream(savePath, FileMode.Create);
byte[] bArr = new byte[1024];
int size = responseStream.Read(bArr, 0, bArr.Length);
while (size > 0)
{
stream.Write(bArr, 0, size);
size = responseStream.Read(bArr, 0, bArr.Length);
}
stream.Close();
responseStream.Close();
return savePath;
}
catch (Exception)
{
throw new BusinessValidationFailedException(_localizer["ReadingCalculate_ImageNotExist"]);
}
}
/// <summary>
/// 获取任务表格问题答案
/// </summary>
/// <param name="tableAnswerList">表格答案</param>
/// <param name="dictionList">字典</param>
/// <param name="unitDictionary">单位字典</param>
/// <param name="taskId">任务Id</param>
/// <param name="lesionType">病灶类型</param>
/// <param name="questionMark">问题标识</param>
/// <param name="rowIndex">索引</param>
/// <returns></returns>
public string GetTaskTableAnswer(List<ReadingTableQuestionAnswer>? tableAnswerList, List<Dictionary>? dictionList, List<Dictionary>? unitDictionary, Guid taskId, LesionType lesionType, QuestionMark questionMark, decimal rowIndex)
{
var answerData = tableAnswerList.FirstOrDefault(x => x.VisitTaskId == taskId && x.ReadingQuestionTrial.LesionType == lesionType && x.ReadingTableQuestionTrial.QuestionMark == questionMark && x.RowIndex == rowIndex);
if (answerData == null || answerData.Answer == string.Empty)
{
return string.Empty;
}
var answer = string.Empty;
if (answerData.ReadingTableQuestionTrial.TableQuestionType == TableQuestionType.Dictionary)
{
answer = dictionList.Where(x => x.Code == answerData.ReadingTableQuestionTrial.DictionaryCode).SelectMany(x => x.ChildList).Where(x => x.Code == answerData.Answer).Select(x => x.ValueCN).FirstIsNullReturnEmpty();
}
else
{
answer = answerData.Answer;
}
if (answer != "NA" && answerData.ReadingTableQuestionTrial.Unit != null && answerData.ReadingTableQuestionTrial.Unit != ValueUnit.none)
{
answer += " " + unitDictionary.SelectMany(x => x.ChildList).Where(x => x.Code == ((int)answerData.ReadingTableQuestionTrial.Unit).ToString()).Select(x => x.ValueCN).FirstIsNullReturnEmpty();
}
if (answer != "NA" && answerData.ReadingTableQuestionTrial.ValueType == ValueOfType.Percentage)
{
answer += " %";
}
return answer;
}
/// <summary>
/// 获取病灶的图片 rowinfoList要带question的信息
/// </summary>
/// <param name="rowinfoList"></param>
/// <param name="lesionType"></param>
/// <returns></returns>
public async Task<List<Dictionary<string, object>>> GetLesionPic(List<ReadingTableAnswerRowInfo> rowinfoList, LesionType lesionType, Guid DownLoadGuid)
{
var lesionRowinfo = rowinfoList.Where(x => x.PicturePath != string.Empty && x.ReadingQuestionTrial.LesionType == lesionType).OrderBy(x => x.VisitTask.VisitTaskNum).OrderBy(x => x.RowIndex).ToList();
List<Dictionary<string, object>> lesionImage = new List<Dictionary<string, object>>();
var lesionCount = lesionRowinfo.Select(x => x.VisitTask.VisitTaskNum).Distinct().OrderBy(x => x).ToList();
int picNum = 0;
foreach (var num in lesionCount)
{
var picRowinfo = lesionRowinfo.Where(x => x.VisitTask.VisitTaskNum == num).OrderBy(x => x.RowIndex).ToList();
var picCount = picRowinfo.Count();
for (int i = 0; i < Math.Ceiling((double)picCount / 2); i++)
{
lesionImage.Add(new Dictionary<string, object>()
{
{ "ImageOneMark",getPicNum(true)+ picRowinfo[2*i].VisitTask.TaskName+" "+picRowinfo[2*i].RowMark},
{ "ImageOneUrl" ,await GetWordPictureMaxWL(_options.CurrentValue.MinIO.viewEndpoint+picRowinfo[2*i].PicturePath ,System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $@"wwwroot/ReadReoprtTemplate/downLoad/{DownLoadGuid}"),290,390) },
{ "ImageTwoMark",getPicNum(picCount>2*i+1) + (picCount<=2*i+1?string.Empty:picRowinfo[2*i+1].VisitTask.TaskName+" "+picRowinfo[2*i+1].RowMark) },
{ "ImageTwoUrl", picCount<=2*i+1?string.Empty:await GetWordPictureMaxWL(_options.CurrentValue.MinIO.viewEndpoint+picRowinfo[2*i+1].PicturePath ,System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $@"wwwroot/ReadReoprtTemplate/downLoad/{DownLoadGuid}"),290, 390) },
});
}
}
string getPicNum(bool isHavePic)
{
if (isHavePic)
{
picNum += 1;
return $"图{picNum} ";
}
else
{
return string.Empty;
}
}
return lesionImage;
}
}
}

View File

@ -1,4 +1,5 @@
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure;
@ -7,12 +8,14 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using MiniExcelLibs;
using System.Data;
using System.Runtime.InteropServices;
namespace IRaCIS.Core.Application.Service.ReadingCalculate
{
[ApiExplorerSettings(GroupName = "Image")]
public class ReadingCalculateService(IEnumerable<ICriterionCalculateService> _criterionServices,
IRepository<VisitTask> _visitTaskRepository,
IOSSService _oSSService,
IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository,
IStringLocalizer _localizer, IUserInfo _userInfo
@ -81,6 +84,131 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
}
}
/// <summary>
/// 下载阅片报告
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<FileResult> DownLoadReadReport(DownLoadReadReportInDto inDto)
{
var service = await this.GetService(inDto.VisitTaskId);
if (service != null)
{
inDto.DownLoadGuid = Guid.NewGuid();
Stream stream = await service.DownLoadReadReportStream(inDto);
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
FileStreamResult actionResult = new FileStreamResult(stream, new Microsoft.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream"));
actionResult.FileDownloadName = "ReadReoprtTemplate.docx";
this.DeleteFile(inDto);
return actionResult;
}
else
{
FileStreamResult actionResult = new FileStreamResult(stream, new Microsoft.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream"));
actionResult.FileDownloadName = "ReadReoprtTemplate.pdf";
this.DeleteFile(inDto);
return actionResult;
}
}
else
{
throw new BusinessValidationFailedException("error");
}
}
/// <summary>
/// 删除文件
/// </summary>
/// <param name="inDto"></param>
public void DeleteFile(DownLoadReadReportInDto inDto)
{
try
{
File.Delete(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $@"wwwroot/ReadReoprtTemplate/downLoad/{inDto.DownLoadGuid}.docx"));
}
catch (Exception)
{
}
try
{
File.Delete(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $@"wwwroot/ReadReoprtTemplate/downLoad/{inDto.DownLoadGuid}.pdf"));
}
catch (Exception)
{
}
}
/// <summary>
/// 下载阅片报告流
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
/// <exception cref="BusinessValidationFailedException"></exception>
public async Task<Stream> DownLoadReadReportStream(DownLoadReadReportInDto inDto)
{
var service = await this.GetService(inDto.VisitTaskId);
if (service != null)
{
inDto.DownLoadGuid = Guid.NewGuid();
var result = await service.DownLoadReadReportStream(inDto);
this.DeleteFile(inDto);
return result;
}
else
{
throw new BusinessValidationFailedException(_localizer["ReadingCalculate_DownLoadReadReport"]);
}
}
/// <summary>
/// 获取并生成报告URL
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<string> GetVisitReadReportUrl(CaGetVisitReadReportUrl inDto)
{
var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Include(x => x.Subject).Include(x => x.SourceSubjectVisit).FirstNotNullAsync();
if (taskinfo.ReportExportUrl != string.Empty)
{
return taskinfo.ReportExportUrl;
}
else
{
var stream = await DownLoadReadReportStream(new DownLoadReadReportInDto()
{
VisitTaskId = inDto.VisitTaskId,
});
var url = await _oSSService.UploadToOSSAsync(stream, $"ReadingReport/{taskinfo.TrialId.ToString()}/{taskinfo.Id.ToString()}", $"{taskinfo.Subject.Code}_{taskinfo.SourceSubjectVisit.VisitName}.pdf", false);
await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => x.Id == inDto.VisitTaskId, x => new VisitTask()
{
ReportExportUrl = url
});
return url;
}
}
/// <summary>
/// 自动计算 并修改值
/// </summary>

View File

@ -1,11 +1,19 @@
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Application.Contracts;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore.Common;
using IRaCIS.Core.Infrastructure;
using MassTransit;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MiniSoftware;
using System.Runtime.InteropServices;
using System.Text;
namespace IRaCIS.Core.Application.Service.ReadingCalculate
@ -24,9 +32,18 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
IRepository<TumorAssessment_IRECIST1Point1> _tumorAssessmentRepository,
IGeneralCalculateService _generalCalculateService,
IRepository<ReadingTaskQuestionAnswer> _readingTaskQuestionAnswerRepository,
IRepository<Subject> _subjectRepository,
IRepository<User> _userRepository,
IServiceProvider ServiceProvider,
IOptionsMonitor<SystemHospitalOption> _hospital,
IRepository<Dictionary> _dictionaryRepository,
IRepository<DicomStudy> _dicomStudyRepository,
IRepository<SubjectPatient> _subjectPatientRepository,
ILogger<IRECIST1Point1CalculateService> _logger, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, ICriterionCalculateService
{
/// <summary>
/// 获取阅片的计算数据
/// </summary>
@ -39,6 +56,277 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
};
}
/// <summary>
/// 下载阅片报告
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<Stream> DownLoadReadReportStream(DownLoadReadReportInDto inDto)
{
var downFile = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $@"wwwroot/ReadReoprtTemplate/downLoad/{inDto.DownLoadGuid}");
Directory.CreateDirectory(downFile);
var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId && x.ReadingCategory == ReadingCategory.Visit)
.Include(x => x.TrialReadingCriterion).FirstNotNullAsync();
var visitInfo = await _subjectVisitRepository.Where(x => x.Id == taskinfo.SourceSubjectVisitId).Include(x => x.StudyList).FirstNotNullAsync();
var subjectInfo = await _subjectRepository.Where(x => x.Id == taskinfo.SubjectId).Include(x => x.SubjectPatientList).FirstNotNullAsync();
var doctor = await _userRepository.Where(x => x.Id == taskinfo.DoctorUserId).FirstOrDefaultAsync();
var trialQuestion = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == taskinfo.TrialReadingCriterionId).ToListAsync();
var tableQuestion = await _readingTableQuestionTrialRepository.Where(x => x.ReadingQuestionTrial.ReadingQuestionCriterionTrialId == taskinfo.TrialReadingCriterionId).ToListAsync();
var dicotionCode = trialQuestion.Where(x => x.DictionaryCode != string.Empty).Select(x => x.DictionaryCode).Distinct().ToList();
dicotionCode.AddRange(tableQuestion.Where(x => x.DictionaryCode != string.Empty).Select(x => x.DictionaryCode).Distinct());
var dictionList = await _dictionaryRepository.Where(x => dicotionCode.Contains(x.Code)).Include(x => x.ChildList).ToListAsync();
List<Guid> taskIds = new List<Guid>() { };
var relatedVisitTask = await ServiceProvider.GetService<IReadingImageTaskService>().GetRelatedVisitTask(new GetRelatedVisitTaskInDto()
{
VisitTaskId = inDto.VisitTaskId
});
var relatedCount = relatedVisitTask.Item1.Count();
if (relatedCount <= 3)
{
taskIds = relatedVisitTask.Item1.Select(x => x.VisitTaskId).ToList();
}
else
{
var count = relatedVisitTask.Item1.Count();
taskIds.Add(relatedVisitTask.Item1[0].VisitTaskId);
taskIds.Add(relatedVisitTask.Item1[count - 2].VisitTaskId);
taskIds.Add(relatedVisitTask.Item1[count - 1].VisitTaskId);
}
relatedVisitTask.Item1 = relatedVisitTask.Item1.Where(x => taskIds.Contains(x.VisitTaskId)).ToList();
// 所有访视问题的答案
var answerList = await _readingTaskQuestionAnswerRepository.Where(x => taskIds.Contains(x.VisitTaskId)).Include(x => x.ReadingQuestionTrial).ToListAsync();
// 单位字典
var unitDictionary = await _dictionaryRepository.Where(x => x.Code == "ValueUnit").Include(x => x.ChildList).ToListAsync();
var imageProblem = _generalCalculateService.GetTaskanswer(answerList, dictionList, unitDictionary, inDto.VisitTaskId, QuestionType.ImageQualityAssessment);
var rowinfoList = await _readingTableAnswerRowInfoRepository.Where(x => taskIds.Contains(x.VisitTaskId)).Include(x => x.VisitTask).Include(x => x.ReadingQuestionTrial).ToListAsync();
var tableAnswerList = await _readingTableQuestionAnswerRepository.Where(x => taskIds.Contains(x.VisitTaskId)).Include(x => x.ReadingQuestionTrial).Include(x => x.ReadingTableQuestionTrial).ToListAsync();
#region 获取各个病灶
List<Dictionary<string, object>> getLesionInfo(LesionType lesionType)
{
List<decimal> targetFocusNum = rowinfoList.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.ReadingQuestionTrial.LesionType == lesionType).Select(x => x.RowIndex).OrderBy(x => x).ToList();
List<Dictionary<string, object>> targetInfo = new List<Dictionary<string, object>>();
foreach (var item in targetFocusNum)
{
var bodyPartDescription = _generalCalculateService.GetTaskTableAnswer(tableAnswerList, dictionList, unitDictionary, inDto.VisitTaskId, lesionType, QuestionMark.BodyPartDescription, item);
var rowMark = rowinfoList.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.RowIndex == item && x.ReadingQuestionTrial.LesionType == lesionType).Select(x => x.RowMark).FirstIsNullReturnEmpty();
var reportMark = rowinfoList.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.RowIndex == item && x.ReadingQuestionTrial.LesionType == lesionType).Select(x => x.ReportMark).FirstIsNullReturnEmpty();
if (reportMark != string.Empty)
{
rowMark = $"{rowMark}{reportMark}";
}
Dictionary<string, object> target = new Dictionary<string, object>()
{
{ "RowMark",rowMark},
{ "Organ",_generalCalculateService.GetTaskTableAnswer(tableAnswerList,dictionList,unitDictionary,inDto.VisitTaskId,lesionType,QuestionMark.Organ,item)+""+_generalCalculateService.GetTaskTableAnswer(tableAnswerList,dictionList,unitDictionary,inDto.VisitTaskId,lesionType,QuestionMark.Part,item)+ (bodyPartDescription==string.Empty?string.Empty:""+bodyPartDescription) },
{ "FirstVisit",getStateInfo(0,item, lesionType) },
{ "SecondVisit", relatedCount>=2?getStateInfo(1,item,lesionType):string.Empty },
{ "ThirdlyVisit", relatedCount>=3?getStateInfo(2,item,lesionType):string.Empty },
};
targetInfo.Add(target);
}
return targetInfo;
}
string getStateInfo(int index, decimal item, LesionType lesionType)
{
// 非淋巴结取长径 淋巴结取长短径
var state = _generalCalculateService.GetTaskTableAnswer(tableAnswerList, dictionList, unitDictionary, taskIds[index], lesionType, QuestionMark.State, item);
var majorAxis = _generalCalculateService.GetTaskTableAnswer(tableAnswerList, dictionList, unitDictionary, taskIds[index], lesionType, QuestionMark.MajorAxis, item);
var isLymph = _generalCalculateService.GetTaskTableAnswer(tableAnswerList, dictionList, unitDictionary, taskIds[index], lesionType, QuestionMark.IsLymph, item);
var shortAxis = _generalCalculateService.GetTaskTableAnswer(tableAnswerList, dictionList, unitDictionary, taskIds[index], lesionType, QuestionMark.ShortAxis, item);
var result = string.Empty;
if (!state.IsNullOrEmpty())
{
result = state;
}
if (!majorAxis.IsNullOrEmpty())
{
result += result == string.Empty ? $"L{majorAxis}" : $"L{majorAxis}";
}
if (isLymph.EqEnum(YesOrNoOrNa.Yes) && !shortAxis.IsNullOrEmpty())
{
result += result == string.Empty ? $"S{shortAxis}" : $"S{shortAxis}";
}
return result;
}
#endregion
#region 外层问题处理
// 获取外层问题
List<Dictionary<string, object>> getQuestionAnswerList(List<ExportReportQuestion> exports)
{
List<Dictionary<string, object>> questionAnswerList = new List<Dictionary<string, object>>();
foreach (var item in exports)
{
Dictionary<string, object> questionAnswer = new Dictionary<string, object>()
{
{"Name",item.QuestionName },
{"FirstVisit", _generalCalculateService.GetTaskanswer(answerList,dictionList,unitDictionary,taskIds[0],item.QuestionType)},
{"SecondVisit", relatedCount>=2? _generalCalculateService.GetTaskanswer(answerList,dictionList,unitDictionary,taskIds[1],item.QuestionType):string.Empty },
{"ThirdlyVisit", relatedCount>=3? _generalCalculateService.GetTaskanswer(answerList,dictionList,unitDictionary,taskIds[2],item.QuestionType):string.Empty },
};
questionAnswerList.Add(questionAnswer);
}
return questionAnswerList;
}
#endregion
var studyInfo = (await _dicomStudyRepository.Where(x => x.SubjectVisitId == taskinfo.SourceSubjectVisitId).Select(x => new
{
x.Modalities,
x.StudyTime,
x.BodyPartExamined,
x.Description
}).OrderBy(x => x.StudyTime).ToListAsync()).Select(x => new Dictionary<string, object>() {
{ "Modalities",x.Modalities},
{ "StudyTime",x.StudyTime?.ToString("yyyy-MM-dd")},
{ "Description",x.Description},
{ "ImageProblem",imageProblem},
}).ToList();
var subjectPatientList = await _subjectPatientRepository.Where(x => x.SubjectId == subjectInfo.Id).Include(x => x.Patient).ToListAsync();
var resultList = new List<ExportReportQuestion>()
{ new ExportReportQuestion (){ QuestionName="靶病灶径线之和SOD",QuestionType=QuestionType.SOD},
new ExportReportQuestion (){ QuestionName="非淋巴结靶病灶长径之和",QuestionType=QuestionType.SumOfDiameter},
new ExportReportQuestion (){ QuestionName="与基线相比SOD变化量",QuestionType=QuestionType.SODChange},
new ExportReportQuestion (){ QuestionName="与基线相比SOD变化百分比",QuestionType=QuestionType.SODPercent},
new ExportReportQuestion (){ QuestionName="与最低点相比SOD变化量",QuestionType=QuestionType.LowestIncrease},
new ExportReportQuestion (){ QuestionName="与最低点相比SOD变化百分比",QuestionType=QuestionType.LowPercent},
new ExportReportQuestion (){ QuestionName="最低点访视",QuestionType=QuestionType.LowVisit},
};
var isConvertedTask = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Select(x => x.IsConvertedTask).FirstOrDefaultAsync();
if (isConvertedTask)
{
resultList.AddRange(new List<ExportReportQuestion>()
{ new ExportReportQuestion (){ QuestionName="与触发iRECIST访视相比SOD变化量",QuestionType=QuestionType.ComparedTriggeringSODChange},
new ExportReportQuestion (){ QuestionName="新靶病灶直径之和iSOD",QuestionType=QuestionType.ISOD},
new ExportReportQuestion (){ QuestionName="与触发iRECIST访视相比iSOD变化量",QuestionType=QuestionType.ComparedTriggeringiSODChange},
});
}
var assessmentResult = string.Empty;
if (visitInfo.IsBaseLine)
{
var existDisease = answerList.Where(x => x.ReadingQuestionTrial.QuestionType == QuestionType.ExistDisease).Select(x => x.Answer).FirstIsNullReturnEmpty().EqEnum(ExistDisease.No) ? "不" : string.Empty;
assessmentResult = $"{existDisease}存在疾病";
}
else
{
assessmentResult = $"整体肿瘤评估结果为{_generalCalculateService.GetTaskanswer(answerList, dictionList, unitDictionary, inDto.VisitTaskId, QuestionType.Tumor)}";
}
var value = new Dictionary<string, object>()
{
// { "Logo" ,await _generalCalculateService.GetWordPictureMaxWL(_options.CurrentValue.MinIO.viewEndpoint+_hospital.CurrentValue.HospitalLogoPath ,System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $@"wwwroot/ReadReoprtTemplate/downLoad/{inDto.DownLoadGuid}"),110,100) },
{ "HospitalName",_hospital.CurrentValue.HospitalName } ,// 医院名称
{ "SubjectName",subjectInfo.ShortName }, //患者姓名
{ "SubjectSex", subjectInfo.Sex==string.Empty?string.Empty: subjectInfo.Sex=="M"?"男":"女" }, //患者性别
{ "SubjectAge",subjectInfo.Age==null?string.Empty: subjectInfo.Age +"岁" }, //患者年龄
{ "SubjectCode",subjectPatientList.Select(x=>x.Patient).OrderByDescending(x=>x.CreateTime).Select(x=>x.PatientIdStr).FirstIsNullReturnEmpty() }, //患者编号
{ "VisitName",visitInfo.VisitName }, //访视名称
{ "LatestScanDate",visitInfo.StudyList.Min(x=>x.StudyTime)?.ToString("yyyy-MM-dd") }, //随访日期
{ "CriterionName",taskinfo.TrialReadingCriterion.CriterionName }, //评估标准
{ "AssessmentResult", assessmentResult }, //评估结果
{ "DoctorName",doctor.LastName + doctor.FirstName}, //医生姓名
{ "SignTime",taskinfo.SignTime?.ToString("yyyy-MM-dd HH:mm:ss") }, //签名时间
{ "StudyInfo",studyInfo }, // 检查信息
{ "FirstVisit", relatedVisitTask.Item1[0].TaskName},
{ "SecondVisit",relatedCount>=2?relatedVisitTask.Item1[1].TaskName:string.Empty},
{ "ThirdlyVisit", relatedCount>=3?relatedVisitTask.Item1[2].TaskName:string.Empty},
{ "TargetInfo", getLesionInfo(LesionType.TargetLesion)}, // 靶病灶
{ "NoTargetInfo", getLesionInfo(LesionType.NonTargetLesions)}, // 非把病灶
{ "NewTargetInfo", getLesionInfo(LesionType.NewLesions)},// 新病灶
{ "NewITargetInfo", getLesionInfo(LesionType.NewTargetLesion)}, // 新靶病灶
{ "NewNoTargetInfo", getLesionInfo(LesionType.NewNonTargetLesion)}, // 新非靶病灶
{ "OtherPreviousNewInfo", getLesionInfo(LesionType.OtherPreviousNewLesion)}, // 其它既往新病灶
{ "TriggeringIRECSITInfo", getLesionInfo(LesionType.TriggeringIRECSIT)}, // 触发iRECSIT后的新病灶
{ "TargetImage", await _generalCalculateService.GetLesionPic(rowinfoList, LesionType.TargetLesion,inDto.DownLoadGuid)}, // 靶病灶图片
{ "NoTargetImage",await _generalCalculateService.GetLesionPic(rowinfoList, LesionType.NonTargetLesions,inDto.DownLoadGuid)}, // 非靶病灶图片
{ "NewImage", await _generalCalculateService.GetLesionPic(rowinfoList, LesionType.NewLesions,inDto.DownLoadGuid)}, // 新病灶图片
{ "NewITargetImage",await _generalCalculateService.GetLesionPic(rowinfoList, LesionType.NewTargetLesion,inDto.DownLoadGuid)}, // 新靶病灶
{ "NewNoTargetImage",await _generalCalculateService.GetLesionPic(rowinfoList, LesionType.NewNonTargetLesion,inDto.DownLoadGuid)}, // 新非靶病灶
{ "OtherPreviousNewImage", await _generalCalculateService.GetLesionPic(rowinfoList, LesionType.OtherPreviousNewLesion,inDto.DownLoadGuid)}, // 其它既往新病灶
{ "TriggeringIRECSITImage",await _generalCalculateService.GetLesionPic(rowinfoList, LesionType.TriggeringIRECSIT,inDto.DownLoadGuid)}, // 触发iRECSIT后的新病灶
{ "Result",getQuestionAnswerList(resultList)}, // 评估结果
{ "Curative",getQuestionAnswerList(new List<ExportReportQuestion>()
{ new ExportReportQuestion (){ QuestionName="靶病灶评估",QuestionType=QuestionType.TargetLesion},
new ExportReportQuestion (){ QuestionName="非靶病灶评估",QuestionType=QuestionType.NoTargetLesion},
new ExportReportQuestion (){ QuestionName="存在新病灶",QuestionType=QuestionType.NewLesions},
new ExportReportQuestion (){ QuestionName="存在疾病",QuestionType=QuestionType.ExistDisease},
new ExportReportQuestion (){ QuestionName="整体肿瘤评估",QuestionType=QuestionType.Tumor},
})}, // 疗效结果
{ "ReportNo",await _generalCalculateService.GetReportExportNo(taskinfo) } ,
};
value = _generalCalculateService.StringEmptyTurnedLine(value);
var templatePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"wwwroot/ReadReoprtTemplate/ReportTemplate_RECIST1.1_CN_V1.docx");
if (isConvertedTask)
{
templatePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"wwwroot/ReadReoprtTemplate/ReportTemplate_IRECIST_CN_V1.docx");
}
var outputFilePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $@"wwwroot/ReadReoprtTemplate/downLoad/{inDto.DownLoadGuid}.docx");
MiniWord.SaveAsByTemplate(outputFilePath, templatePath, value);
Directory.Delete(downFile, true);
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
Stream stream = _generalCalculateService.ReadAndReturnStream(outputFilePath);
return stream;
}
else
{
var pdfurl = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"wwwroot/ReadReoprtTemplate/downLoad");
FileConvertHelper.ConvertWordToPdf(outputFilePath, pdfurl);
Stream stream = _generalCalculateService.ReadAndReturnStream(pdfurl + $"/{inDto.DownLoadGuid}.pdf");
return stream;
}
}
#region 临时对象 单个请求的生命周期 避免重复查询数据库
private List<VisitTaskAnswerInfo> visitTaskAnswerList;

View File

@ -45,6 +45,16 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
};
}
/// <summary>
/// 下载阅片报告
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<Stream> DownLoadReadReportStream(DownLoadReadReportInDto inDto)
{
throw new BusinessValidationFailedException(_localizer["ReadingCalculate_DownLoadReadReport"]);
}
#region 临时对象 单个请求的生命周期 避免重复查询数据库
private List<VisitTaskAnswerInfo> visitTaskAnswerList;

View File

@ -55,6 +55,13 @@ namespace IRaCIS.Core.Application.Service
Task<object> GetReadingCalculationData(GetReadingCalculationDataInDto inDto);
/// <summary>
/// 下载阅片报告
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
Task<Stream> DownLoadReadReportStream(DownLoadReadReportInDto inDto);
}

View File

@ -1,6 +1,7 @@
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Http;
using MiniSoftware;
using System.Data;
namespace IRaCIS.Core.Application.Service
@ -45,5 +46,95 @@ namespace IRaCIS.Core.Application.Service
/// <param name="file"></param>
/// <returns></returns>
Task<FileToDataTableDto> GetDataTableFromUpload(IFormFile file, string pathCode, Guid trialId);
/// <summary>
/// 获取图片
/// </summary>
/// <param name="url"></param>
/// <param name="savePath"></param>
/// <param name="width"></param>
/// <returns></returns>
Task<MiniWordPicture> GetWordPicture(string url, string savePath, int width);
/// <summary>
/// 获取图片
/// </summary>
/// <param name="url"></param>
/// <param name="savePath"></param>
/// <param name="width"></param>
/// <returns></returns>
Task<MiniWordPicture> GetWordPicture(string url, string savePath, int width, int height);
/// <summary>
/// 下载文件
/// </summary>
/// <param name="url"></param>
/// <param name="savePath"></param>
/// <returns></returns>
Task<string> FileDownSave(string url, string savePath);
/// <summary>
/// 获取并复制文件流
/// </summary>
/// <param name="outputFilePath"></param>
/// <returns></returns>
Stream ReadAndReturnStream(string outputFilePath);
/// <summary>
/// 最大宽高 保持比例
/// </summary>
/// <param name="url"></param>
/// <param name="savePath"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <returns></returns>
Task<MiniWordPicture> GetWordPictureMaxWL(string url, string savePath, int width, int height);
/// <summary>
/// 空转为横线
/// </summary>
/// <param name="myDictionary"></param>
/// <returns></returns>
Dictionary<string, object> StringEmptyTurnedLine(Dictionary<string, object> myDictionary);
/// <summary>
/// 获取病灶的图片 rowinfoList要带question的信息
/// </summary>
/// <param name="rowinfoList"></param>
/// <param name="lesionType"></param>
/// <param name="downLoadGuid"></param>
/// <returns></returns>
Task<List<Dictionary<string, object>>> GetLesionPic(List<ReadingTableAnswerRowInfo> rowinfoList, LesionType lesionType, Guid downLoadGuid);
/// <summary>
/// 获取任务问题答案
/// </summary>
/// <param name="answerList">问题答案</param>
/// <param name="dictionList">字典数据</param>
/// <param name="unitDictionary">单位字典</param>
/// <param name="taskId">任务Id</param>
/// <param name="questionType">任务类型</param>
/// <returns></returns>
string GetTaskanswer(List<ReadingTaskQuestionAnswer>? answerList, List<Dictionary>? dictionList, List<Dictionary>? unitDictionary, Guid taskId, QuestionType questionType);
/// <summary>
/// 获取任务表格问题答案
/// </summary>
/// <param name="tableAnswerList">表格答案</param>
/// <param name="dictionList">字典</param>
/// <param name="unitDictionary">单位字典</param>
/// <param name="taskId">任务Id</param>
/// <param name="lesionType">病灶类型</param>
/// <param name="questionMark">问题标识</param>
/// <param name="rowIndex">索引</param>
/// <returns></returns>
string GetTaskTableAnswer(List<ReadingTableQuestionAnswer>? tableAnswerList, List<Dictionary>? dictionList, List<Dictionary>? unitDictionary, Guid taskId, LesionType lesionType, QuestionMark questionMark, decimal rowIndex);
/// <summary>
/// 获取阅片报告
/// </summary>
/// <param name="visitTaskInfo"></param>
/// <returns></returns>
Task<string> GetReportExportNo(VisitTask visitTaskInfo);
}
}

View File

@ -1,6 +1,7 @@
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Application.ViewModel;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Data;
namespace IRaCIS.Core.Application.Service
@ -56,7 +57,28 @@ namespace IRaCIS.Core.Application.Service
/// <returns></returns>
Task<object> GetReadingCalculationData(GetReadingCalculationDataInDto inDto);
/// <summary>
/// 下载阅片报告
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
Task<FileResult> DownLoadReadReport(DownLoadReadReportInDto inDto);
/// <summary>
/// 获取阅片报告流
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
Task<Stream> DownLoadReadReportStream(DownLoadReadReportInDto inDto);
/// <summary>
/// 获取并生成报告URl
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
Task<string> GetVisitReadReportUrl(CaGetVisitReadReportUrl inDto);
}
}

View File

@ -55,6 +55,16 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
};
}
/// <summary>
/// 下载阅片报告
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<Stream> DownLoadReadReportStream(DownLoadReadReportInDto inDto)
{
throw new BusinessValidationFailedException(_localizer["ReadingCalculate_DownLoadReadReport"]);
}
#region 临时对象 单个请求的生命周期 避免重复查询数据库
private List<VisitTaskAnswerInfo> visitTaskAnswerList;

View File

@ -29,6 +29,16 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
IRepository<ReadingTaskQuestionAnswer> _readingTaskQuestionAnswerRepository, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, ICriterionCalculateService, ILuganoCalculateService
{
/// <summary>
/// 下载阅片报告
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<Stream> DownLoadReadReportStream(DownLoadReadReportInDto inDto)
{
throw new BusinessValidationFailedException(_localizer["ReadingCalculate_DownLoadReadReport"]);
}
/// <summary>
/// 获取阅片的计算数据
/// </summary>

View File

@ -28,6 +28,15 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
IRepository<ReadingTaskQuestionAnswer> _readingTaskQuestionAnswerRepository,
ILogger<IRECIST1Point1CalculateService> _logger, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, ICriterionCalculateService
{
/// <summary>
/// 下载阅片报告
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<Stream> DownLoadReadReportStream(DownLoadReadReportInDto inDto)
{
throw new BusinessValidationFailedException(_localizer["ReadingCalculate_DownLoadReadReport"]);
}
/// <summary>
/// 获取阅片的计算数据

View File

@ -1,10 +1,17 @@
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Application.Contracts;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore.Common;
using IRaCIS.Core.Infrastructure;
using MassTransit;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using MiniSoftware;
using System.Runtime.InteropServices;
namespace IRaCIS.Core.Application.Service.ReadingCalculate
{
@ -21,6 +28,12 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
IRepository<NoneDicomStudy> _noneDicomStudyRepository,
IRepository<TumorAssessment_RECIST1Point1> _tumorAssessmentRepository,
IGeneralCalculateService _generalCalculateService,
IRepository<Subject> _subjectRepository,
IRepository<User> _userRepository,
IServiceProvider ServiceProvider,
IOptionsMonitor<SystemHospitalOption> _hospital,
IRepository<Dictionary> _dictionaryRepository,
IRepository<SubjectPatient> _subjectPatientRepository,
IRepository<ReadingTaskQuestionAnswer> _readingTaskQuestionAnswerRepository, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, ICriterionCalculateService
{
@ -39,6 +52,202 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
};
}
/// <summary>
/// 下载阅片报告
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<Stream> DownLoadReadReportStream(DownLoadReadReportInDto inDto)
{
var downFile = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $@"wwwroot/ReadReoprtTemplate/downLoad/{inDto.DownLoadGuid}");
Directory.CreateDirectory(downFile);
var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId && x.ReadingCategory == ReadingCategory.Visit).Include(x => x.TrialReadingCriterion).FirstNotNullAsync();
var visitInfo = await _subjectVisitRepository.Where(x => x.Id == taskinfo.SourceSubjectVisitId).Include(x => x.StudyList).FirstNotNullAsync();
var subjectInfo = await _subjectRepository.Where(x => x.Id == taskinfo.SubjectId).Include(x => x.SubjectPatientList).FirstNotNullAsync();
var doctor = await _userRepository.Where(x => x.Id == taskinfo.DoctorUserId).FirstOrDefaultAsync();
var trialQuestion = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == taskinfo.TrialReadingCriterionId).ToListAsync();
var tableQuestion = await _readingTableQuestionTrialRepository.Where(x => x.ReadingQuestionTrial.ReadingQuestionCriterionTrialId == taskinfo.TrialReadingCriterionId).ToListAsync();
var dicotionCode = trialQuestion.Where(x => x.DictionaryCode != string.Empty).Select(x => x.DictionaryCode).Distinct().ToList();
dicotionCode.AddRange(tableQuestion.Where(x => x.DictionaryCode != string.Empty).Select(x => x.DictionaryCode).Distinct());
var dictionList = await _dictionaryRepository.Where(x => dicotionCode.Contains(x.Code)).Include(x => x.ChildList).ToListAsync();
List<Guid> taskIds = new List<Guid>() { };
var relatedVisitTask = await ServiceProvider.GetService<IReadingImageTaskService>().GetRelatedVisitTask(new GetRelatedVisitTaskInDto()
{
VisitTaskId = inDto.VisitTaskId
});
var relatedCount = relatedVisitTask.Item1.Count();
if (relatedCount <= 3)
{
taskIds = relatedVisitTask.Item1.Select(x => x.VisitTaskId).ToList();
}
else
{
var count = relatedVisitTask.Item1.Count();
taskIds.Add(relatedVisitTask.Item1[0].VisitTaskId);
taskIds.Add(relatedVisitTask.Item1[count - 2].VisitTaskId);
taskIds.Add(relatedVisitTask.Item1[count - 1].VisitTaskId);
}
relatedVisitTask.Item1 = relatedVisitTask.Item1.Where(x => taskIds.Contains(x.VisitTaskId)).ToList();
// 所有访视问题的答案
var answerList = await _readingTaskQuestionAnswerRepository.Where(x => taskIds.Contains(x.VisitTaskId)).Include(x => x.ReadingQuestionTrial).ToListAsync();
// 单位字典
var unitDictionary = await _dictionaryRepository.Where(x => x.Code == "ValueUnit").Include(x => x.ChildList).ToListAsync();
var imageProblem = _generalCalculateService.GetTaskanswer(answerList, dictionList, unitDictionary, inDto.VisitTaskId, QuestionType.ImageQualityAssessment);
var rowinfoList = await _readingTableAnswerRowInfoRepository.Where(x => taskIds.Contains(x.VisitTaskId)).Include(x => x.VisitTask).Include(x => x.ReadingQuestionTrial).ToListAsync();
var tableAnswerList = await _readingTableQuestionAnswerRepository.Where(x => taskIds.Contains(x.VisitTaskId)).Include(x => x.ReadingQuestionTrial).Include(x => x.ReadingTableQuestionTrial).ToListAsync();
#region 获取各个病灶
List<Dictionary<string, object>> getLesionInfo(LesionType lesionType)
{
List<decimal> targetFocusNum = rowinfoList.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.ReadingQuestionTrial.LesionType == lesionType).Select(x => x.RowIndex).OrderBy(x => x).ToList();
List<Dictionary<string, object>> targetInfo = new List<Dictionary<string, object>>();
foreach (var item in targetFocusNum)
{
var bodyPartDescription = _generalCalculateService.GetTaskTableAnswer(tableAnswerList, dictionList, unitDictionary, inDto.VisitTaskId, lesionType, QuestionMark.BodyPartDescription, item);
Dictionary<string, object> target = new Dictionary<string, object>()
{
{ "RowMark",rowinfoList.Where(x=>x.VisitTaskId == inDto.VisitTaskId &&x.RowIndex==item && x.ReadingQuestionTrial.LesionType == lesionType).Select(x=>x.RowMark).FirstIsNullReturnEmpty() },
{ "Organ",_generalCalculateService.GetTaskTableAnswer(tableAnswerList,dictionList,unitDictionary,inDto.VisitTaskId,lesionType,QuestionMark.Organ,item)+""+_generalCalculateService.GetTaskTableAnswer(tableAnswerList,dictionList,unitDictionary,inDto.VisitTaskId,lesionType,QuestionMark.Part,item)+ (bodyPartDescription==string.Empty?string.Empty:""+bodyPartDescription) },
{ "FirstVisit",getStateInfo(0,item, lesionType) },
{ "SecondVisit", relatedCount>=2?getStateInfo(1,item,lesionType):string.Empty },
{ "ThirdlyVisit", relatedCount>=3?getStateInfo(2,item,lesionType):string.Empty },
};
targetInfo.Add(target);
}
return targetInfo;
}
string getStateInfo(int index, decimal item, LesionType lesionType)
{
var state = _generalCalculateService.GetTaskTableAnswer(tableAnswerList, dictionList, unitDictionary, taskIds[index], lesionType, QuestionMark.State, item);
var LesionNumber = _generalCalculateService.GetTaskTableAnswer(tableAnswerList, dictionList, unitDictionary, taskIds[index], lesionType, QuestionMark.LesionNumber, item);
var result = string.Empty;
if (lesionType == LesionType.BaselineLesions)
{
return LesionNumber;
}
else
{
return state;
}
}
#endregion
#region 外层问题处理
// 获取外层问题
List<Dictionary<string, object>> getQuestionAnswerList(List<ExportReportQuestion> exports)
{
List<Dictionary<string, object>> questionAnswerList = new List<Dictionary<string, object>>();
foreach (var item in exports)
{
Dictionary<string, object> questionAnswer = new Dictionary<string, object>()
{
{"Name",item.QuestionName },
{"FirstVisit", _generalCalculateService.GetTaskanswer(answerList,dictionList,unitDictionary,taskIds[0],item.QuestionType)},
{"SecondVisit", relatedCount>=2? _generalCalculateService.GetTaskanswer(answerList,dictionList,unitDictionary,taskIds[1],item.QuestionType):string.Empty },
{"ThirdlyVisit", relatedCount>=3? _generalCalculateService.GetTaskanswer(answerList,dictionList,unitDictionary,taskIds[2],item.QuestionType):string.Empty },
};
questionAnswerList.Add(questionAnswer);
}
return questionAnswerList;
}
#endregion
var studyInfo = (await _dicomStudyRepository.Where(x => x.SubjectVisitId == taskinfo.SourceSubjectVisitId).Select(x => new
{
x.Modalities,
x.StudyTime,
x.BodyPartExamined,
x.Description
}).OrderBy(x => x.StudyTime).ToListAsync()).Select(x => new Dictionary<string, object>() {
{ "Modalities",x.Modalities},
{ "StudyTime",x.StudyTime?.ToString("yyyy-MM-dd")},
{ "Description",x.Description},
{ "ImageProblem",imageProblem},
}).ToList();
var subjectPatientList = await _subjectPatientRepository.Where(x => x.SubjectId == subjectInfo.Id).Include(x => x.Patient).ToListAsync();
var value = new Dictionary<string, object>()
{
// { "Logo" ,await _generalCalculateService.GetWordPictureMaxWL(_options.CurrentValue.MinIO.viewEndpoint+_hospital.CurrentValue.HospitalLogoPath ,System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $@"wwwroot/ReadReoprtTemplate/downLoad/{inDto.DownLoadGuid}"),110,100) },
{ "HospitalName",_hospital.CurrentValue.HospitalName } ,// 医院名称
{ "SubjectName",subjectInfo.ShortName }, //患者姓名
{ "SubjectSex", subjectInfo.Sex==string.Empty?string.Empty: subjectInfo.Sex=="M"?"男":"女" }, //患者性别
{ "SubjectAge",subjectInfo.Age==null?string.Empty: subjectInfo.Age +"岁" }, //患者年龄
{ "SubjectCode",subjectPatientList.Select(x=>x.Patient).OrderByDescending(x=>x.CreateTime).Select(x=>x.PatientIdStr).FirstIsNullReturnEmpty() }, //患者编号
{ "VisitName",visitInfo.VisitName }, //访视名称
{ "LatestScanDate",visitInfo.StudyList.Min(x=>x.StudyTime)?.ToString("yyyy-MM-dd") }, //随访日期
{ "CriterionName",taskinfo.TrialReadingCriterion.CriterionName }, //评估标准
{ "AssessmentResult", _generalCalculateService.GetTaskanswer(answerList,dictionList,unitDictionary,inDto.VisitTaskId,QuestionType.SiteVisitForTumorEvaluation) }, //评估结果
{ "DoctorName",doctor.LastName + doctor.FirstName}, //医生姓名
{ "SignTime",taskinfo.SignTime?.ToString("yyyy-MM-dd HH:mm:ss") }, //签名时间
{ "StudyInfo",studyInfo }, // 检查信息
{ "FirstVisit", relatedVisitTask.Item1[0].TaskName},
{ "SecondVisit",relatedCount>=2?relatedVisitTask.Item1[1].TaskName:string.Empty},
{ "ThirdlyVisit", relatedCount>=3?relatedVisitTask.Item1[2].TaskName:string.Empty},
{ "BaselineLesionsInfo", getLesionInfo(LesionType.BaselineLesions)}, // 基线病灶
{ "AlwaysNewLesionsInfo", getLesionInfo(LesionType.AlwaysNewLesions)}, // 既往新病灶
{ "NewTargetInfo", getLesionInfo(LesionType.NewLesions)},// 新病灶
{ "BaselineLesionsImage", await _generalCalculateService.GetLesionPic(rowinfoList, LesionType.BaselineLesions, inDto.DownLoadGuid)}, // 基线病灶
{ "AlwaysNewLesionsImage",await _generalCalculateService.GetLesionPic(rowinfoList, LesionType.AlwaysNewLesions, inDto.DownLoadGuid)}, // 既往新病灶
{ "NewImage", await _generalCalculateService.GetLesionPic(rowinfoList, LesionType.NewLesions, inDto.DownLoadGuid)}, // 新病灶图片
{ "Result",getQuestionAnswerList(new List<ExportReportQuestion>()
{ new ExportReportQuestion (){ QuestionName="基线病灶计数",QuestionType=QuestionType.BaseLineLesionsCount},
new ExportReportQuestion (){ QuestionName="新病灶计数",QuestionType=QuestionType.NewLesionsCount},
new ExportReportQuestion (){ QuestionName="既往新病灶计数",QuestionType=QuestionType.AlwaysNewLesionsCount},
new ExportReportQuestion (){ QuestionName="自治疗后第二个访视点以来持续的新骨病变数量",QuestionType=QuestionType.NewBoneLesionsCount},
new ExportReportQuestion (){ QuestionName="与前一个访视间隔天数",QuestionType=QuestionType.DaysBetween},
})}, // 评估结果
{ "Curative",getQuestionAnswerList(new List<ExportReportQuestion>()
{ new ExportReportQuestion (){ QuestionName="访视点肿瘤评估",QuestionType=QuestionType.SiteVisitForTumorEvaluation},
new ExportReportQuestion (){ QuestionName="访视阅片备注",QuestionType=QuestionType.AdjustReason},
})}, // 疗效结果
{ "ReportNo",await _generalCalculateService.GetReportExportNo(taskinfo) } ,
};
value = _generalCalculateService.StringEmptyTurnedLine(value);
var templatePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"wwwroot/ReadReoprtTemplate/ReportTemplate_PCWG3_CN_V1.docx");
var outputFilePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $@"wwwroot/ReadReoprtTemplate/downLoad/{inDto.DownLoadGuid}.docx");
MiniWord.SaveAsByTemplate(outputFilePath, templatePath, value);
Directory.Delete(downFile, true);
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
Stream stream = _generalCalculateService.ReadAndReturnStream(outputFilePath);
return stream;
}
else
{
var pdfurl = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"wwwroot/ReadReoprtTemplate/downLoad");
FileConvertHelper.ConvertWordToPdf(outputFilePath, pdfurl);
Stream stream = _generalCalculateService.ReadAndReturnStream(pdfurl + $"/{inDto.DownLoadGuid}.pdf");
return stream;
}
}
#region 删除病灶获取起始病灶序号
/// <summary>
/// 删除病灶获取起始病灶序号

View File

@ -1,10 +1,17 @@
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Application.Contracts;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore.Common;
using IRaCIS.Core.Infrastructure;
using MassTransit;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using MiniSoftware;
using System.Runtime.InteropServices;
namespace IRaCIS.Core.Application.Service.ReadingCalculate
{
@ -21,6 +28,13 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
IRepository<SubjectVisit> _subjectVisitRepository,
IRepository<TumorAssessment_RECIST1Point1> _tumorAssessmentRepository,
IGeneralCalculateService _generalCalculateService,
IRepository<Subject> _subjectRepository,
IRepository<User> _userRepository,
IServiceProvider ServiceProvider,
IOptionsMonitor<SystemHospitalOption> _hospital,
IRepository<Dictionary> _dictionaryRepository,
IRepository<DicomStudy> _dicomStudyRepository,
IRepository<SubjectPatient> _subjectPatientRepository,
IRepository<ReadingTaskQuestionAnswer> _readingTaskQuestionAnswerRepository, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, ICriterionCalculateService
{
@ -36,6 +50,238 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
};
}
/// <summary>
/// 下载阅片报告
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<Stream> DownLoadReadReportStream(DownLoadReadReportInDto inDto)
{
var downFile = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $@"wwwroot/ReadReoprtTemplate/downLoad/{inDto.DownLoadGuid}");
Directory.CreateDirectory(downFile);
var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId && x.ReadingCategory == ReadingCategory.Visit)
.Include(x => x.TrialReadingCriterion).FirstNotNullAsync();
var visitInfo = await _subjectVisitRepository.Where(x => x.Id == taskinfo.SourceSubjectVisitId).Include(x => x.StudyList).FirstNotNullAsync();
var subjectInfo = await _subjectRepository.Where(x => x.Id == taskinfo.SubjectId).Include(x => x.SubjectPatientList).FirstNotNullAsync();
var doctor = await _userRepository.Where(x => x.Id == taskinfo.DoctorUserId).FirstOrDefaultAsync();
var trialQuestion = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == taskinfo.TrialReadingCriterionId).ToListAsync();
var tableQuestion = await _readingTableQuestionTrialRepository.Where(x => x.ReadingQuestionTrial.ReadingQuestionCriterionTrialId == taskinfo.TrialReadingCriterionId).ToListAsync();
var dicotionCode = trialQuestion.Where(x => x.DictionaryCode != string.Empty).Select(x => x.DictionaryCode).Distinct().ToList();
dicotionCode.AddRange(tableQuestion.Where(x => x.DictionaryCode != string.Empty).Select(x => x.DictionaryCode).Distinct());
var dictionList = await _dictionaryRepository.Where(x => dicotionCode.Contains(x.Code)).Include(x => x.ChildList).ToListAsync();
List<Guid> taskIds = new List<Guid>() { };
var relatedVisitTask = await ServiceProvider.GetService<IReadingImageTaskService>().GetRelatedVisitTask(new GetRelatedVisitTaskInDto()
{
VisitTaskId = inDto.VisitTaskId
});
var relatedCount = relatedVisitTask.Item1.Count();
if (relatedCount <= 3)
{
taskIds = relatedVisitTask.Item1.Select(x => x.VisitTaskId).ToList();
}
else
{
var count = relatedVisitTask.Item1.Count();
taskIds.Add(relatedVisitTask.Item1[0].VisitTaskId);
taskIds.Add(relatedVisitTask.Item1[count - 2].VisitTaskId);
taskIds.Add(relatedVisitTask.Item1[count - 1].VisitTaskId);
}
relatedVisitTask.Item1 = relatedVisitTask.Item1.Where(x => taskIds.Contains(x.VisitTaskId)).ToList();
// 所有访视问题的答案
var answerList = await _readingTaskQuestionAnswerRepository.Where(x => taskIds.Contains(x.VisitTaskId)).Include(x => x.ReadingQuestionTrial).ToListAsync();
// 单位字典
var unitDictionary = await _dictionaryRepository.Where(x => x.Code == "ValueUnit").Include(x => x.ChildList).ToListAsync();
var imageProblem = _generalCalculateService.GetTaskanswer(answerList, dictionList, unitDictionary, inDto.VisitTaskId, QuestionType.ImageQualityAssessment);
var rowinfoList = await _readingTableAnswerRowInfoRepository.Where(x => taskIds.Contains(x.VisitTaskId)).Include(x => x.VisitTask).Include(x => x.ReadingQuestionTrial).ToListAsync();
var tableAnswerList = await _readingTableQuestionAnswerRepository.Where(x => taskIds.Contains(x.VisitTaskId)).Include(x => x.ReadingQuestionTrial).Include(x => x.ReadingTableQuestionTrial).ToListAsync();
#region 获取各个病灶
List<Dictionary<string, object>> getLesionInfo(LesionType lesionType)
{
List<decimal> targetFocusNum = rowinfoList.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.ReadingQuestionTrial.LesionType == lesionType).Select(x => x.RowIndex).OrderBy(x => x).ToList();
List<Dictionary<string, object>> targetInfo = new List<Dictionary<string, object>>();
foreach (var item in targetFocusNum)
{
var bodyPartDescription = _generalCalculateService.GetTaskTableAnswer(tableAnswerList, dictionList, unitDictionary, inDto.VisitTaskId, lesionType, QuestionMark.BodyPartDescription, item);
Dictionary<string, object> target = new Dictionary<string, object>()
{
{ "RowMark",rowinfoList.Where(x=>x.VisitTaskId == inDto.VisitTaskId &&x.RowIndex==item && x.ReadingQuestionTrial.LesionType == lesionType).Select(x=>x.RowMark).FirstIsNullReturnEmpty() },
{ "Organ",_generalCalculateService.GetTaskTableAnswer(tableAnswerList,dictionList,unitDictionary,inDto.VisitTaskId,lesionType,QuestionMark.Organ,item)+""+_generalCalculateService.GetTaskTableAnswer(tableAnswerList,dictionList,unitDictionary,inDto.VisitTaskId,lesionType,QuestionMark.Part,item)+ (bodyPartDescription==string.Empty?string.Empty:""+bodyPartDescription) },
{ "FirstVisit",getStateInfo(0,item, lesionType) },
{ "SecondVisit", relatedCount>=2?getStateInfo(1,item,lesionType):string.Empty },
{ "ThirdlyVisit", relatedCount>=3?getStateInfo(2,item,lesionType):string.Empty },
};
targetInfo.Add(target);
}
return targetInfo;
}
string getStateInfo(int index, decimal item, LesionType lesionType)
{
// 非淋巴结取长径 淋巴结取长短径
var state = _generalCalculateService.GetTaskTableAnswer(tableAnswerList, dictionList, unitDictionary, taskIds[index], lesionType, QuestionMark.State, item);
var majorAxis = _generalCalculateService.GetTaskTableAnswer(tableAnswerList, dictionList, unitDictionary, taskIds[index], lesionType, QuestionMark.MajorAxis, item);
var isLymph = _generalCalculateService.GetTaskTableAnswer(tableAnswerList, dictionList, unitDictionary, taskIds[index], lesionType, QuestionMark.IsLymph, item);
var shortAxis = _generalCalculateService.GetTaskTableAnswer(tableAnswerList, dictionList, unitDictionary, taskIds[index], lesionType, QuestionMark.ShortAxis, item);
var result = string.Empty;
if (!state.IsNullOrEmpty())
{
result = state;
}
if (!majorAxis.IsNullOrEmpty())
{
result += result == string.Empty ? $"L{majorAxis}" : $"L{majorAxis}";
}
if (isLymph.EqEnum(YesOrNoOrNa.Yes) && !shortAxis.IsNullOrEmpty())
{
result += result == string.Empty ? $"S{shortAxis}" : $"S{shortAxis}";
}
return result;
}
#endregion
#region 外层问题处理
// 获取外层问题
List<Dictionary<string, object>> getQuestionAnswerList(List<ExportReportQuestion> exports)
{
List<Dictionary<string, object>> questionAnswerList = new List<Dictionary<string, object>>();
foreach (var item in exports)
{
Dictionary<string, object> questionAnswer = new Dictionary<string, object>()
{
{"Name",item.QuestionName },
{"FirstVisit", _generalCalculateService.GetTaskanswer(answerList,dictionList,unitDictionary,taskIds[0],item.QuestionType)},
{"SecondVisit", relatedCount>=2? _generalCalculateService.GetTaskanswer(answerList,dictionList,unitDictionary,taskIds[1],item.QuestionType):string.Empty },
{"ThirdlyVisit", relatedCount>=3? _generalCalculateService.GetTaskanswer(answerList,dictionList,unitDictionary,taskIds[2],item.QuestionType):string.Empty },
};
questionAnswerList.Add(questionAnswer);
}
return questionAnswerList;
}
#endregion
var studyInfo = (await _dicomStudyRepository.Where(x => x.SubjectVisitId == taskinfo.SourceSubjectVisitId).Select(x => new
{
x.Modalities,
x.StudyTime,
x.BodyPartExamined,
x.Description
}).OrderBy(x => x.StudyTime).ToListAsync()).Select(x => new Dictionary<string, object>() {
{ "Modalities",x.Modalities},
{ "StudyTime",x.StudyTime?.ToString("yyyy-MM-dd")},
{ "Description",x.Description},
{ "ImageProblem",imageProblem},
}).ToList();
var subjectPatientList = await _subjectPatientRepository.Where(x => x.SubjectId == subjectInfo.Id).Include(x => x.Patient).ToListAsync();
var assessmentResult = string.Empty;
if (visitInfo.IsBaseLine)
{
var existDisease = answerList.Where(x => x.ReadingQuestionTrial.QuestionType == QuestionType.ExistDisease).Select(x => x.Answer).FirstIsNullReturnEmpty().EqEnum(ExistDisease.No) ? "不" : string.Empty;
assessmentResult = $"{existDisease}存在疾病";
}
else
{
assessmentResult = $"整体肿瘤评估结果为{_generalCalculateService.GetTaskanswer(answerList, dictionList, unitDictionary, inDto.VisitTaskId, QuestionType.Tumor)}";
}
var value = new Dictionary<string, object>()
{
// { "Logo" ,await _generalCalculateService.GetWordPictureMaxWL(_options.CurrentValue.MinIO.viewEndpoint+_hospital.CurrentValue.HospitalLogoPath ,System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $@"wwwroot/ReadReoprtTemplate/downLoad/{inDto.DownLoadGuid}"),110,100) },
{ "HospitalName",_hospital.CurrentValue.HospitalName } ,// 医院名称
{ "SubjectName",subjectInfo.ShortName }, //患者姓名
{ "SubjectSex", subjectInfo.Sex==string.Empty?string.Empty: subjectInfo.Sex=="M"?"男":"女" }, //患者性别
{ "SubjectAge",subjectInfo.Age==null?string.Empty: subjectInfo.Age +"岁" }, //患者年龄
{ "SubjectCode",subjectPatientList.Select(x=>x.Patient).OrderByDescending(x=>x.CreateTime).Select(x=>x.PatientIdStr).FirstIsNullReturnEmpty() }, //患者编号
{ "VisitName",visitInfo.VisitName }, //访视名称
{ "LatestScanDate",visitInfo.StudyList.Min(x=>x.StudyTime)?.ToString("yyyy-MM-dd") }, //随访日期
{ "CriterionName",taskinfo.TrialReadingCriterion.CriterionName }, //评估标准
{ "AssessmentResult", assessmentResult }, //评估结果
{ "DoctorName",doctor.LastName + doctor.FirstName}, //医生姓名
{ "SignTime",taskinfo.SignTime?.ToString("yyyy-MM-dd HH:mm:ss") }, //签名时间
{ "StudyInfo",studyInfo }, // 检查信息
{ "FirstVisit", relatedVisitTask.Item1[0].TaskName},
{ "SecondVisit",relatedCount>=2?relatedVisitTask.Item1[1].TaskName:string.Empty},
{ "ThirdlyVisit", relatedCount>=3?relatedVisitTask.Item1[2].TaskName:string.Empty},
{ "TargetInfo", getLesionInfo(LesionType.TargetLesion)}, // 靶病灶
{ "NoTargetInfo", getLesionInfo(LesionType.NonTargetLesions)}, // 非把病灶
{ "NewTargetInfo", getLesionInfo(LesionType.NewLesions)},// 新病灶
{ "TargetImage", await _generalCalculateService.GetLesionPic(rowinfoList, LesionType.TargetLesion,inDto.DownLoadGuid)}, // 靶病灶图片
{ "NoTargetImage",await _generalCalculateService.GetLesionPic(rowinfoList, LesionType.NonTargetLesions,inDto.DownLoadGuid)}, // 非靶病灶图片
{ "NewImage", await _generalCalculateService.GetLesionPic(rowinfoList, LesionType.NewLesions,inDto.DownLoadGuid)}, // 新病灶图片
{ "Result",getQuestionAnswerList(new List<ExportReportQuestion>()
{ new ExportReportQuestion (){ QuestionName="靶病灶径线之和SOD",QuestionType=QuestionType.SOD},
new ExportReportQuestion (){ QuestionName="非淋巴结靶病灶长径之和",QuestionType=QuestionType.SumOfDiameter},
new ExportReportQuestion (){ QuestionName="与基线相比SOD变化量",QuestionType=QuestionType.SODChange},
new ExportReportQuestion (){ QuestionName="与基线相比SOD变化百分比",QuestionType=QuestionType.SODPercent},
new ExportReportQuestion (){ QuestionName="与最低点相比SOD变化量",QuestionType=QuestionType.LowestIncrease},
new ExportReportQuestion (){ QuestionName="与最低点相比SOD变化百分比",QuestionType=QuestionType.LowPercent},
new ExportReportQuestion (){ QuestionName="最低点访视",QuestionType=QuestionType.LowVisit},
})}, // 评估结果
{ "Curative",getQuestionAnswerList(new List<ExportReportQuestion>()
{ new ExportReportQuestion (){ QuestionName="靶病灶评估",QuestionType=QuestionType.TargetLesion},
new ExportReportQuestion (){ QuestionName="非靶病灶评估",QuestionType=QuestionType.NoTargetLesion},
new ExportReportQuestion (){ QuestionName="存在新病灶",QuestionType=QuestionType.NewLesions},
new ExportReportQuestion (){ QuestionName="存在疾病",QuestionType=QuestionType.ExistDisease},
new ExportReportQuestion (){ QuestionName="整体肿瘤评估",QuestionType=QuestionType.Tumor},
})}, // 疗效结果
{ "ReportNo",await _generalCalculateService.GetReportExportNo(taskinfo) } ,
};
value = _generalCalculateService.StringEmptyTurnedLine(value);
var templatePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"wwwroot/ReadReoprtTemplate/ReportTemplate_RECIST1.1_CN_V1.docx");
var outputFilePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $@"wwwroot/ReadReoprtTemplate/downLoad/{inDto.DownLoadGuid}.docx");
MiniWord.SaveAsByTemplate(outputFilePath, templatePath, value);
//// 获取文件夹中的所有文件路径
Directory.Delete(downFile, true);
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
Stream stream = _generalCalculateService.ReadAndReturnStream(outputFilePath);
return stream;
}
else
{
var pdfurl = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"wwwroot/ReadReoprtTemplate/downLoad");
FileConvertHelper.ConvertWordToPdf(outputFilePath, pdfurl);
Stream stream = _generalCalculateService.ReadAndReturnStream(pdfurl + $"/{inDto.DownLoadGuid}.pdf");
return stream;
}
}
#region 临时对象 单个请求的生命周期 避免重复查询数据库
private List<VisitTaskAnswerInfo> visitTaskAnswerList;

View File

@ -1,10 +1,18 @@
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Application.Contracts;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore.Common;
using IRaCIS.Core.Infrastructure;
using MassTransit;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using MiniSoftware;
using System.Runtime.InteropServices;
namespace IRaCIS.Core.Application.Service.ReadingCalculate
{
@ -21,6 +29,13 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
IRepository<SubjectVisit> _subjectVisitRepository,
IRepository<TumorAssessment_RECIST1Point1BM> _tumorAssessment_RECIST1Point1BM,
IGeneralCalculateService _generalCalculateService,
IRepository<Subject> _subjectRepository,
IRepository<User> _userRepository,
IServiceProvider ServiceProvider,
IOptionsMonitor<SystemHospitalOption> _hospital,
IRepository<Dictionary> _dictionaryRepository,
IRepository<DicomStudy> _dicomStudyRepository,
IRepository<SubjectPatient> _subjectPatientRepository,
IRepository<ReadingTaskQuestionAnswer> _readingTaskQuestionAnswerRepository, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, ICriterionCalculateService
{
@ -36,6 +51,236 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
};
}
/// <summary>
/// 下载阅片报告
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<Stream> DownLoadReadReportStream(DownLoadReadReportInDto inDto)
{
var downFile = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $@"wwwroot/ReadReoprtTemplate/downLoad/{inDto.DownLoadGuid}");
Directory.CreateDirectory(downFile);
var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId && x.ReadingCategory == ReadingCategory.Visit).Include(x => x.TrialReadingCriterion).FirstNotNullAsync();
var visitInfo = await _subjectVisitRepository.Where(x => x.Id == taskinfo.SourceSubjectVisitId).Include(x => x.StudyList).FirstNotNullAsync();
var subjectInfo = await _subjectRepository.Where(x => x.Id == taskinfo.SubjectId).Include(x => x.SubjectPatientList).FirstNotNullAsync();
var doctor = await _userRepository.Where(x => x.Id == taskinfo.DoctorUserId).FirstOrDefaultAsync();
var trialQuestion = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == taskinfo.TrialReadingCriterionId).ToListAsync();
var tableQuestion = await _readingTableQuestionTrialRepository.Where(x => x.ReadingQuestionTrial.ReadingQuestionCriterionTrialId == taskinfo.TrialReadingCriterionId).ToListAsync();
var dicotionCode = trialQuestion.Where(x => x.DictionaryCode != string.Empty).Select(x => x.DictionaryCode).Distinct().ToList();
dicotionCode.AddRange(tableQuestion.Where(x => x.DictionaryCode != string.Empty).Select(x => x.DictionaryCode).Distinct());
var dictionList = await _dictionaryRepository.Where(x => dicotionCode.Contains(x.Code)).Include(x => x.ChildList).ToListAsync();
List<Guid> taskIds = new List<Guid>() { };
var relatedVisitTask = await ServiceProvider.GetService<IReadingImageTaskService>().GetRelatedVisitTask(new GetRelatedVisitTaskInDto()
{
VisitTaskId = inDto.VisitTaskId
});
var relatedCount = relatedVisitTask.Item1.Count();
if (relatedCount <= 3)
{
taskIds = relatedVisitTask.Item1.Select(x => x.VisitTaskId).ToList();
}
else
{
var count = relatedVisitTask.Item1.Count();
taskIds.Add(relatedVisitTask.Item1[0].VisitTaskId);
taskIds.Add(relatedVisitTask.Item1[count - 2].VisitTaskId);
taskIds.Add(relatedVisitTask.Item1[count - 1].VisitTaskId);
}
relatedVisitTask.Item1 = relatedVisitTask.Item1.Where(x => taskIds.Contains(x.VisitTaskId)).ToList();
// 所有访视问题的答案
var answerList = await _readingTaskQuestionAnswerRepository.Where(x => taskIds.Contains(x.VisitTaskId)).Include(x => x.ReadingQuestionTrial).ToListAsync();
// 单位字典
var unitDictionary = await _dictionaryRepository.Where(x => x.Code == "ValueUnit").Include(x => x.ChildList).ToListAsync();
var imageProblem = _generalCalculateService.GetTaskanswer(answerList, dictionList, unitDictionary, inDto.VisitTaskId, QuestionType.ImageQualityAssessment);
var rowinfoList = await _readingTableAnswerRowInfoRepository.Where(x => taskIds.Contains(x.VisitTaskId)).Include(x => x.VisitTask).Include(x => x.ReadingQuestionTrial).ToListAsync();
var tableAnswerList = await _readingTableQuestionAnswerRepository.Where(x => taskIds.Contains(x.VisitTaskId)).Include(x => x.ReadingQuestionTrial).Include(x => x.ReadingTableQuestionTrial).ToListAsync();
#region 获取各个病灶
List<Dictionary<string, object>> getLesionInfo(LesionType lesionType)
{
List<decimal> targetFocusNum = rowinfoList.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.ReadingQuestionTrial.LesionType == lesionType).Select(x => x.RowIndex).OrderBy(x => x).ToList();
List<Dictionary<string, object>> targetInfo = new List<Dictionary<string, object>>();
foreach (var item in targetFocusNum)
{
var bodyPartDescription = _generalCalculateService.GetTaskTableAnswer(tableAnswerList, dictionList, unitDictionary, inDto.VisitTaskId, lesionType, QuestionMark.BodyPartDescription, item);
Dictionary<string, object> target = new Dictionary<string, object>()
{
{ "RowMark",rowinfoList.Where(x=>x.VisitTaskId == inDto.VisitTaskId &&x.RowIndex==item && x.ReadingQuestionTrial.LesionType == lesionType).Select(x=>x.RowMark).FirstIsNullReturnEmpty() },
{ "Organ",_generalCalculateService.GetTaskTableAnswer(tableAnswerList,dictionList,unitDictionary,inDto.VisitTaskId,lesionType,QuestionMark.Organ,item)+""+_generalCalculateService.GetTaskTableAnswer(tableAnswerList,dictionList,unitDictionary,inDto.VisitTaskId,lesionType,QuestionMark.Part,item)+ (bodyPartDescription==string.Empty?string.Empty:""+bodyPartDescription) },
{ "FirstVisit",getStateInfo(0,item, lesionType) },
{ "SecondVisit", relatedCount>=2?getStateInfo(1,item,lesionType):string.Empty },
{ "ThirdlyVisit", relatedCount>=3?getStateInfo(2,item,lesionType):string.Empty },
};
targetInfo.Add(target);
}
return targetInfo;
}
string getStateInfo(int index, decimal item, LesionType lesionType)
{
// 非淋巴结取长径 淋巴结取长短径
var state = _generalCalculateService.GetTaskTableAnswer(tableAnswerList, dictionList, unitDictionary, taskIds[index], lesionType, QuestionMark.State, item);
var majorAxis = _generalCalculateService.GetTaskTableAnswer(tableAnswerList, dictionList, unitDictionary, taskIds[index], lesionType, QuestionMark.MajorAxis, item);
var isLymph = _generalCalculateService.GetTaskTableAnswer(tableAnswerList, dictionList, unitDictionary, taskIds[index], lesionType, QuestionMark.IsLymph, item);
var shortAxis = _generalCalculateService.GetTaskTableAnswer(tableAnswerList, dictionList, unitDictionary, taskIds[index], lesionType, QuestionMark.ShortAxis, item);
var result = string.Empty;
if (!state.IsNullOrEmpty())
{
result = state;
}
if (!majorAxis.IsNullOrEmpty())
{
result += result == string.Empty ? $"L{majorAxis}" : $"L{majorAxis}";
}
if (isLymph.EqEnum(YesOrNoOrNa.Yes) && !shortAxis.IsNullOrEmpty())
{
result += result == string.Empty ? $"S{shortAxis}" : $"S{shortAxis}";
}
return result;
}
#endregion
#region 外层问题处理
// 获取外层问题
List<Dictionary<string, object>> getQuestionAnswerList(List<ExportReportQuestion> exports)
{
List<Dictionary<string, object>> questionAnswerList = new List<Dictionary<string, object>>();
foreach (var item in exports)
{
Dictionary<string, object> questionAnswer = new Dictionary<string, object>()
{
{"Name",item.QuestionName },
{"FirstVisit", _generalCalculateService.GetTaskanswer(answerList,dictionList,unitDictionary,taskIds[0],item.QuestionType)},
{"SecondVisit", relatedCount>=2? _generalCalculateService.GetTaskanswer(answerList,dictionList,unitDictionary,taskIds[1],item.QuestionType):string.Empty },
{"ThirdlyVisit", relatedCount>=3? _generalCalculateService.GetTaskanswer(answerList,dictionList,unitDictionary,taskIds[2],item.QuestionType):string.Empty },
};
questionAnswerList.Add(questionAnswer);
}
return questionAnswerList;
}
#endregion
var studyInfo = (await _dicomStudyRepository.Where(x => x.SubjectVisitId == taskinfo.SourceSubjectVisitId).Select(x => new
{
x.Modalities,
x.StudyTime,
x.BodyPartExamined,
x.Description
}).OrderBy(x => x.StudyTime).ToListAsync()).Select(x => new Dictionary<string, object>() {
{ "Modalities",x.Modalities},
{ "StudyTime",x.StudyTime?.ToString("yyyy-MM-dd")},
{ "Description",x.Description},
{ "ImageProblem",imageProblem},
}).ToList();
var subjectPatientList = await _subjectPatientRepository.Where(x => x.SubjectId == subjectInfo.Id).Include(x => x.Patient).ToListAsync();
var assessmentResult = string.Empty;
if (visitInfo.IsBaseLine)
{
var existDisease = answerList.Where(x => x.ReadingQuestionTrial.QuestionType == QuestionType.ExistDisease).Select(x => x.Answer).FirstIsNullReturnEmpty().EqEnum(ExistDisease.No) ? "不" : string.Empty;
assessmentResult = $"{existDisease}存在疾病";
}
else
{
assessmentResult = $"整体肿瘤评估结果为{_generalCalculateService.GetTaskanswer(answerList, dictionList, unitDictionary, inDto.VisitTaskId, QuestionType.Tumor)}";
}
var value = new Dictionary<string, object>()
{
// { "Logo" ,await _generalCalculateService.GetWordPictureMaxWL(_options.CurrentValue.MinIO.viewEndpoint+_hospital.CurrentValue.HospitalLogoPath ,System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $@"wwwroot/ReadReoprtTemplate/downLoad/{inDto.DownLoadGuid}"),110,100) },
{ "HospitalName",_hospital.CurrentValue.HospitalName } ,// 医院名称
{ "SubjectName",subjectInfo.ShortName }, //患者姓名
{ "SubjectSex", subjectInfo.Sex==string.Empty?string.Empty: subjectInfo.Sex=="M"?"男":"女" }, //患者性别
{ "SubjectAge",subjectInfo.Age==null?string.Empty: subjectInfo.Age +"岁" }, //患者年龄
{ "SubjectCode",subjectPatientList.Select(x=>x.Patient).OrderByDescending(x=>x.CreateTime).Select(x=>x.PatientIdStr).FirstIsNullReturnEmpty() }, //患者编号
{ "VisitName",visitInfo.VisitName }, //访视名称
{ "LatestScanDate",visitInfo.StudyList.Min(x=>x.StudyTime)?.ToString("yyyy-MM-dd") }, //随访日期
{ "CriterionName",taskinfo.TrialReadingCriterion.CriterionName }, //评估标准
{ "AssessmentResult", assessmentResult }, //评估结果
{ "DoctorName",doctor.LastName + doctor.FirstName}, //医生姓名
{ "SignTime",taskinfo.SignTime?.ToString("yyyy-MM-dd HH:mm:ss") }, //签名时间
{ "StudyInfo",studyInfo }, // 检查信息
{ "FirstVisit", relatedVisitTask.Item1[0].TaskName},
{ "SecondVisit",relatedCount>=2?relatedVisitTask.Item1[1].TaskName:string.Empty},
{ "ThirdlyVisit", relatedCount>=3?relatedVisitTask.Item1[2].TaskName:string.Empty},
{ "TargetInfo", getLesionInfo(LesionType.TargetLesion)}, // 靶病灶
{ "NoTargetInfo", getLesionInfo(LesionType.NonTargetLesions)}, // 非把病灶
{ "NewTargetInfo", getLesionInfo(LesionType.NewLesions)},// 新病灶
{ "TargetImage", await _generalCalculateService.GetLesionPic(rowinfoList, LesionType.TargetLesion,inDto.DownLoadGuid)}, // 靶病灶图片
{ "NoTargetImage",await _generalCalculateService.GetLesionPic(rowinfoList, LesionType.NonTargetLesions,inDto.DownLoadGuid)}, // 非靶病灶图片
{ "NewImage", await _generalCalculateService.GetLesionPic(rowinfoList, LesionType.NewLesions,inDto.DownLoadGuid)}, // 新病灶图片
{ "Result",getQuestionAnswerList(new List<ExportReportQuestion>()
{ new ExportReportQuestion (){ QuestionName="靶病灶径线之和SOD",QuestionType=QuestionType.SOD},
new ExportReportQuestion (){ QuestionName="非淋巴结靶病灶长径之和",QuestionType=QuestionType.SumOfDiameter},
new ExportReportQuestion (){ QuestionName="与基线相比SOD变化量",QuestionType=QuestionType.SODChange},
new ExportReportQuestion (){ QuestionName="与基线相比SOD变化百分比",QuestionType=QuestionType.SODPercent},
new ExportReportQuestion (){ QuestionName="与最低点相比SOD变化量",QuestionType=QuestionType.LowestIncrease},
new ExportReportQuestion (){ QuestionName="与最低点相比SOD变化百分比",QuestionType=QuestionType.LowPercent},
new ExportReportQuestion (){ QuestionName="最低点访视",QuestionType=QuestionType.LowVisit},
})}, // 评估结果
{ "Curative",getQuestionAnswerList(new List<ExportReportQuestion>()
{ new ExportReportQuestion (){ QuestionName="靶病灶评估",QuestionType=QuestionType.TargetLesion},
new ExportReportQuestion (){ QuestionName="非靶病灶评估",QuestionType=QuestionType.NoTargetLesion},
new ExportReportQuestion (){ QuestionName="存在新病灶",QuestionType=QuestionType.NewLesions},
new ExportReportQuestion (){ QuestionName="存在疾病",QuestionType=QuestionType.ExistDisease},
new ExportReportQuestion (){ QuestionName="整体肿瘤评估",QuestionType=QuestionType.Tumor},
})}, // 疗效结果
{ "ReportNo",await _generalCalculateService.GetReportExportNo(taskinfo) } ,
};
value = _generalCalculateService.StringEmptyTurnedLine(value);
var templatePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"wwwroot/ReadReoprtTemplate/ReportTemplate_RECIST1.1_CN_V1.docx");
var outputFilePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $@"wwwroot/ReadReoprtTemplate/downLoad/{inDto.DownLoadGuid}.docx");
MiniWord.SaveAsByTemplate(outputFilePath, templatePath, value);
//// 获取文件夹中的所有文件路径
Directory.Delete(downFile, true);
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
Stream stream = _generalCalculateService.ReadAndReturnStream(outputFilePath);
return stream;
}
else
{
var pdfurl = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"wwwroot/ReadReoprtTemplate/downLoad");
FileConvertHelper.ConvertWordToPdf(outputFilePath, pdfurl);
Stream stream = _generalCalculateService.ReadAndReturnStream(pdfurl + $"/{inDto.DownLoadGuid}.pdf");
return stream;
}
}
#region 临时对象 单个请求的生命周期 避免重复查询数据库
private List<VisitTaskAnswerInfo> visitTaskAnswerList;

View File

@ -2,6 +2,7 @@
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore.Common;
using IRaCIS.Core.Infrastructure;
using MassTransit;
using Microsoft.AspNetCore.Mvc;
@ -25,6 +26,16 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
{
/// <summary>
/// 下载阅片报告
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<Stream> DownLoadReadReportStream(DownLoadReadReportInDto inDto)
{
throw new BusinessValidationFailedException(_localizer["ReadingCalculate_DownLoadReadReport"]);
}
private List<SiteVisitForTumor> siteVisitForTumorList = new List<SiteVisitForTumor>();
/// <summary>