ReportData.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. using Newtonsoft.Json;
  2. using Newtonsoft.Json.Converters;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Threading;
  8. using Vinno.IUS.Common.Log;
  9. using Vinno.vCloud.Common.FIS.Helper;
  10. using Vinno.vCloud.FIS.CrossPlatform.Common.Helper;
  11. using Vinno.vCloud.Report.Interfaces;
  12. using Vinno.vCloud.Report.JsonConverters;
  13. using Vinno.vCloud.Report.Models;
  14. using WingInterfaceLibrary.Interface;
  15. using WingInterfaceLibrary.Request.Examine;
  16. using WingInterfaceLibrary.Request.Report;
  17. using WingInterfaceLibrary.Request.Storage;
  18. using WingInterfaceLibrary.ResearchEdition;
  19. using WingInterfaceLibrary.Result.Examine;
  20. namespace Vinno.vCloud.Common.FIS.Remedicals
  21. {
  22. public class ReportData : IDisposable
  23. {
  24. private readonly IStorageService _storageService;
  25. private readonly IReportService _reportService;
  26. private readonly IRemedicalService _remedicalService;
  27. private string _token;
  28. private UploadStatus _status;
  29. private Action<ExamPairInfo> _updateExamPairCache;
  30. private Action<ExamPairInfo, string> _updateExamPairCacheForResearch;
  31. private Func<string, ResearchProjectDTO> _getResearchProjectDTO;
  32. /// <summary>
  33. /// Id
  34. /// </summary>
  35. public string Id { get; }
  36. /// <summary>
  37. /// 云端病人Id
  38. /// </summary>
  39. public string PatientIdInServer { get; set; }
  40. /// <summary>
  41. /// 云端检查Id
  42. /// </summary>
  43. public string ExamIdInServer { get; set; }
  44. /// <summary>
  45. /// 报告信息
  46. /// </summary>
  47. public ReportInfoDTO ReportInfo { get; set; }
  48. /// <summary>
  49. /// 报告Pdf文件路径
  50. /// </summary>
  51. public string PdfFilePath { get; set; }
  52. /// <summary>
  53. /// 报告Json文件路径
  54. /// </summary>
  55. public string JsonFilePath { get; set; }
  56. public UploadStatus Status
  57. {
  58. get
  59. {
  60. return _status;
  61. }
  62. private set
  63. {
  64. if (_status != value)
  65. {
  66. _status = value;
  67. StatusChanged?.Invoke(this, Status);
  68. }
  69. }
  70. }
  71. public event EventHandler<UploadStatus> StatusChanged;
  72. public override string ToString()
  73. {
  74. return $"ReportInfoDTO Id:{Id},PatientId:{ReportInfo?.PatientId},ExamId:{ReportInfo?.ExamId},ReportId:{ReportInfo?.ReportId},PdfPath:{PdfFilePath},JsonPath:{JsonFilePath},Organ:{ReportInfo?.Organ},LanguageCode:{ReportInfo?.LanguageCode}";
  75. }
  76. public ReportData(string patientIdInServer, string examIdInServer, ReportInfoDTO reportInfo, IRemedicalService remedicalService, IStorageService storageService, IReportService reportService, string token, Action<ExamPairInfo> updateExamRecordCache, Action<ExamPairInfo, string> updateExamPairCacheForResearch, Func<string, ResearchProjectDTO> getResearchProjectDTO)
  77. {
  78. try
  79. {
  80. _remedicalService = remedicalService;
  81. _storageService = storageService;
  82. _reportService = reportService;
  83. _token = token;
  84. Id = "Report-" + Guid.NewGuid().ToString("N").ToUpper();
  85. PatientIdInServer = patientIdInServer;
  86. ExamIdInServer = examIdInServer;
  87. ReportInfo = reportInfo;
  88. _updateExamPairCache = updateExamRecordCache;
  89. _updateExamPairCacheForResearch = updateExamPairCacheForResearch;
  90. _getResearchProjectDTO = getResearchProjectDTO;
  91. if (ReportInfo == null)
  92. {
  93. throw new ArgumentNullException();
  94. }
  95. if (File.Exists(ReportInfo?.PdfFilePath))
  96. {
  97. var extension = Path.GetExtension(ReportInfo?.PdfFilePath);
  98. var filePath = Path.Combine(GetWorkingFolder(), $"{Id}{extension}");
  99. FileHelper.CopyFile(ReportInfo?.PdfFilePath, filePath, true);
  100. PdfFilePath = filePath;
  101. }
  102. else
  103. {
  104. PdfFilePath = null;
  105. }
  106. if (File.Exists(ReportInfo?.JsonFilePath))
  107. {
  108. var extension = Path.GetExtension(ReportInfo?.JsonFilePath);
  109. var filePath = Path.Combine(GetWorkingFolder(), $"{Id}{extension}");
  110. FileHelper.CopyFile(ReportInfo?.JsonFilePath, filePath, true);
  111. JsonFilePath = filePath;
  112. }
  113. else
  114. {
  115. JsonFilePath = null;
  116. }
  117. Status = UploadStatus.Idle;
  118. Logger.WriteLineInfo(ToString());
  119. }
  120. catch (Exception ex)
  121. {
  122. Logger.WriteLineError($"ReportData {ToString()} Cstor Error:{ex}");
  123. }
  124. }
  125. private string GetWorkingFolder()
  126. {
  127. var folder = Path.Combine(vCloudTerminalV2.WorkingFolder, "ReportUploadCache");
  128. DirectoryHelper.CreateDirectory(folder);
  129. return folder;
  130. }
  131. internal void UpdateStatus(UploadStatus status)
  132. {
  133. Status = status;
  134. }
  135. public void Dispose()
  136. {
  137. try
  138. {
  139. FileHelper.DeleteFile(JsonFilePath);
  140. FileHelper.DeleteFile(PdfFilePath);
  141. }
  142. catch (Exception ex)
  143. {
  144. Logger.WriteLineError($"ReportData {ToString()} Dispose Error:{ex}");
  145. }
  146. }
  147. internal void Upload(CancellationTokenSource cancellationTokenSource)
  148. {
  149. var document = RepportDeserializeHelper.DeserializeReport(JsonFilePath);
  150. if (document == null)
  151. {
  152. throw new InvalidDataException($"Report Deserialize Fail!");
  153. }
  154. if (string.IsNullOrWhiteSpace(ReportInfo.ReportId))
  155. {
  156. ReportInfo.ReportId = document.Id;
  157. }
  158. var settings = new JsonSerializerSettings
  159. {
  160. ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
  161. Converters =
  162. new List<JsonConverter>
  163. {
  164. new StringEnumConverter(),
  165. new ReadOnlyCellDictionaryJsonConverter(),
  166. #pragma warning disable 612
  167. new ElementValueDictionaryJsonConverter(),
  168. #pragma warning restore 612
  169. new ElementValueJsonConverter(),
  170. new DictionaryJsonConverter<MeasureTag, TextElementValue>(),
  171. new DictionaryJsonConverter<ElementTag, Dictionary<MeasureTag, TextElementValue>>(),
  172. }
  173. };
  174. var templatestring = JsonConvert.SerializeObject(document.Template, Formatting.None, settings);
  175. string elementValueString = SerializeElementValue(document, settings);
  176. string measureElementValueString = SerializeMeasureElementValue(document, settings);
  177. if (cancellationTokenSource.IsCancellationRequested)
  178. {
  179. throw new OperationCanceledException("Cancelled");
  180. }
  181. string pdfUrl = null;
  182. if (File.Exists(PdfFilePath))
  183. {
  184. pdfUrl = UploadPdf(cancellationTokenSource);
  185. if (string.IsNullOrWhiteSpace(pdfUrl))
  186. {
  187. throw new InvalidOperationException("Get url failed when Uploading pdf file");
  188. }
  189. }
  190. if (cancellationTokenSource.IsCancellationRequested)
  191. {
  192. throw new OperationCanceledException("Cancelled");
  193. }
  194. var saveUltrasonicReportRequest = new SaveUltrasonicReportRequest
  195. {
  196. Token = _token,
  197. DeviceExamId = ReportInfo.ExamId,
  198. DeviceReportId = ReportInfo.ReportId,
  199. ReportType = ReportInfo.ReportType,
  200. ReportTemplateJson = templatestring,
  201. ReportDatasJson = elementValueString,
  202. ReportMeasureDatasJson = measureElementValueString,
  203. ReportPDFUrl = pdfUrl,
  204. LanguageCode = ReportInfo.LanguageCode,
  205. ReportOrgan = ReportInfo.Organ,
  206. };
  207. if (cancellationTokenSource.IsCancellationRequested)
  208. {
  209. throw new OperationCanceledException("Cancelled");
  210. }
  211. var result = JsonRpcHelper.SaveUltrasonicReport(_reportService, saveUltrasonicReportRequest);
  212. if (result == null)
  213. {
  214. throw new InvalidDataException($"JsonRPCHelper SaveUltrasonicReport Result is null");
  215. }
  216. else if (result.IsSuccess)
  217. {
  218. Status = UploadStatus.Uploaded;
  219. return;
  220. }
  221. else if (!result.IsSuccess)
  222. {
  223. if (result.ErrorCode == 4016)//云端没有找到对应的检查
  224. {
  225. if (CreateExamRecord(out var examRecordId, out var patientIdInServer))
  226. {
  227. PatientIdInServer = patientIdInServer;
  228. var examPairInfo = new ExamPairInfo(ReportInfo.ExamId, ReportInfo.PatientId, examRecordId, patientIdInServer);
  229. if (string.IsNullOrEmpty(ReportInfo.ProjectCode))
  230. {
  231. _updateExamPairCache(examPairInfo);
  232. }
  233. else
  234. {
  235. _updateExamPairCacheForResearch(examPairInfo, ReportInfo.ProjectCode);
  236. }
  237. result = JsonRpcHelper.SaveUltrasonicReport(_reportService, saveUltrasonicReportRequest);
  238. if (result == null)
  239. {
  240. throw new InvalidDataException($"JsonRPCHelper SaveUltrasonicReport Result is null");
  241. }
  242. else if (result.IsSuccess)
  243. {
  244. Status = UploadStatus.Uploaded;
  245. return;
  246. }
  247. else
  248. {
  249. throw new InvalidDataException($"JsonRPCHelper SaveUltrasonicReport Fail,Error Code is {result.ErrorCode}");
  250. }
  251. }
  252. else
  253. {
  254. throw new InvalidDataException($"JsonRPCHelper SaveUltrasonicReport Fail:CreateExamRecord Result is false");
  255. }
  256. }
  257. }
  258. Status = UploadStatus.Fail;
  259. }
  260. private static string SerializeElementValue(ReportInfo document, JsonSerializerSettings settings)
  261. {
  262. var elementValuesList = new List<ReportDataItemDTO>();
  263. foreach (var elementValue in document.ElementValues)
  264. {
  265. var tagId = elementValue.Key.Id;
  266. var name = elementValue.Key.Name;
  267. var value = JsonConvert.SerializeObject(elementValue.Value, Formatting.None, settings);
  268. var key = "";
  269. foreach (var block in document.Template.Blocks)
  270. {
  271. var elment = block.Elements.FirstOrDefault(x => x.Tag?.Id == elementValue.Key.Id);
  272. if (elment != null)
  273. {
  274. key = elment.Id;
  275. break;
  276. }
  277. }
  278. elementValuesList.Add(new ReportDataItemDTO()
  279. {
  280. TagId = tagId,
  281. Value = value,
  282. Name = name,
  283. Key = key,
  284. });
  285. }
  286. var elementValueString = JsonConvert.SerializeObject(elementValuesList, Formatting.None, settings);
  287. return elementValueString;
  288. }
  289. private static string SerializeMeasureElementValue(ReportInfo document, JsonSerializerSettings settings)
  290. {
  291. var measureElementValuesList = new List<ReportDataItemDTO>();
  292. foreach (var measureElementValue in document.MeasureElementValues)
  293. {
  294. var tagId = measureElementValue.Key.Id;
  295. var name = measureElementValue.Key.Name;
  296. var key = "";
  297. var value = JsonConvert.SerializeObject(measureElementValue.Value, Formatting.None, settings);
  298. foreach (var block in document.Template.Blocks)
  299. {
  300. var elment = block.Elements.FirstOrDefault(x => x.Tag?.Id == measureElementValue.Key.Id);
  301. if (elment != null)
  302. {
  303. key = elment.Id;
  304. break;
  305. }
  306. }
  307. measureElementValuesList.Add(new ReportDataItemDTO()
  308. {
  309. TagId = tagId,
  310. Value = value,
  311. Name = name,
  312. Key = key,
  313. });
  314. }
  315. var measureElementValueString = JsonConvert.SerializeObject(measureElementValuesList, Formatting.None, settings);
  316. return measureElementValueString;
  317. }
  318. /// <inheritdoc />
  319. /// <summary>
  320. /// Create an exam record from vCloud.
  321. /// </summary>
  322. /// <param name="examId">The local excam id.</param>
  323. /// <param name="workOrderId">The workerId</param>
  324. /// <param name="patientInfo">The patient basic info for creating the exam record.</param>
  325. /// <returns><see cref="T:Vinno.vCloud.Terminal.Remedicals.IvCloudExamRecord" /></returns>
  326. private bool CreateExamRecord(out string examRecordId, out string patientIdInServer)
  327. {
  328. var patientType = vCloudServerConfig.Instance.PatientType;
  329. if (!string.IsNullOrEmpty(ReportInfo.ProjectCode))
  330. {
  331. var researchProjectDTO = _getResearchProjectDTO.Invoke(ReportInfo.ProjectCode);
  332. if (researchProjectDTO != null)
  333. {
  334. patientType = researchProjectDTO.PatientType;
  335. }
  336. else
  337. {
  338. examRecordId = string.Empty;
  339. patientIdInServer = string.Empty;
  340. Logger.WriteLineError($"GetResearchProjectDTO Fail,ProjectCode:{ReportInfo.ProjectCode}");
  341. return false;
  342. }
  343. }
  344. var createExaminfoRequest = new CreateExaminfoRequest
  345. {
  346. Token = _token,
  347. PatientType = patientType.ToString(),
  348. ExamRecordCode = null,
  349. PatientInfo = DTOConverter.RenderPatientInfo(ReportInfo.PatientInfo, ReportInfo.ExamId, patientType),
  350. PatientScanInfoList = DTOConverter.RenderPatientScanInfo(ReportInfo.PatientInfo),
  351. IsScreenshotVersion = false,
  352. PatientCode = PatientIdInServer,
  353. ExamTime = ReportInfo.PatientInfo.ExamTime,
  354. ProjectCode = ReportInfo.ProjectCode,
  355. };
  356. CreateExaminfoResult result = JsonRpcHelper.CreateExamInfo(_remedicalService, createExaminfoRequest);
  357. if (result == null || string.IsNullOrEmpty(result.ExamCode))
  358. {
  359. examRecordId = string.Empty;
  360. patientIdInServer = string.Empty;
  361. return false;
  362. }
  363. else
  364. {
  365. examRecordId = result.ExamCode;
  366. patientIdInServer = result.PatientCode;
  367. return true;
  368. }
  369. }
  370. private string UploadPdf(CancellationTokenSource cancellationTokenSource)
  371. {
  372. try
  373. {
  374. if (cancellationTokenSource.IsCancellationRequested)
  375. {
  376. throw new OperationCanceledException("Cancelled");
  377. }
  378. var fileName = Path.GetFileName(PdfFilePath);
  379. var fileServiceRequest = new FileServiceRequest
  380. {
  381. FileName = fileName,
  382. IsRechristen = true,
  383. Token = _token,
  384. };
  385. var authorizationInfo = JsonRpcHelper.GetAuthorization(_storageService, fileServiceRequest);
  386. if (authorizationInfo == null)
  387. {
  388. throw new Exception("GetAuthorization Error,AuthorizationInfo is null ");
  389. }
  390. var uploadResult = UploadFileHelper.UploadFile(authorizationInfo.StorageUrl, PdfFilePath, authorizationInfo.ContentType, authorizationInfo.Authorization, null, cancellationTokenSource);
  391. if (cancellationTokenSource.IsCancellationRequested)
  392. {
  393. throw new OperationCanceledException("Cancelled");
  394. }
  395. if (uploadResult?.Item1 == true)
  396. {
  397. return authorizationInfo.StorageUrl;
  398. }
  399. else
  400. {
  401. return string.Empty;
  402. }
  403. }
  404. catch (Exception ex)
  405. {
  406. Logger.WriteLineError($"Upload Report Pdf File Error:{ex}");
  407. return string.Empty;
  408. }
  409. }
  410. }
  411. }