You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

610 lines
25 KiB

3 weeks ago
8 hours ago
3 weeks ago
8 hours ago
3 weeks ago
4 days ago
3 weeks ago
8 hours ago
3 weeks ago
8 hours ago
3 weeks ago
8 hours ago
3 weeks ago
8 hours ago
3 weeks ago
  1. using Dapper;
  2. using Microsoft.Extensions.Configuration;
  3. using Newtonsoft.Json;
  4. using Newtonsoft.Json.Converters;
  5. using Npgsql;
  6. using Shentun.Peis.ImportLisResults;
  7. using Shentun.Peis.ImportPacsResults;
  8. using Shentun.Peis.PlugIns.Extensions.ChargeRequests.YinHai;
  9. using Shentun.Peis.PlugIns.Extensions.ChargeRequests.YinHai.FeeBacks;
  10. using Shentun.Peis.PlugIns.Extensions.ImportLisResults.YinHai;
  11. using Shentun.Peis.PlugIns.Extensions.ImportLisResults.YinHai.ResultCalls;
  12. using Shentun.Peis.PlugIns.Extensions.ImportPacsResults.YinHai.ResultCalls;
  13. using Shentun.Peis.PlugIns.Extensions.LisRequests.YinHai;
  14. using Shentun.Peis.PlugIns.PatientRegisters;
  15. using Shentun.Peis.ThirdInterfaces;
  16. using Shentun.Utilities;
  17. using System;
  18. using System.Collections.Generic;
  19. using System.Data.Common;
  20. using System.IdentityModel.Tokens.Jwt;
  21. using System.Linq;
  22. using System.Net.Http.Headers;
  23. using System.Text;
  24. using System.Threading.Tasks;
  25. using System.Xml;
  26. namespace Shentun.Peis.PlugIns.Extensions.ImportPacsResults.YinHai
  27. {
  28. public class ImportPacsResultPlugInsYinHai
  29. {
  30. protected IConfiguration? AppConfig;
  31. private readonly string AppConnctionStr;
  32. private readonly IConfiguration? InterfaceConfig;
  33. private readonly ThirdInterfaceDto? _thirdInterfaceDto;
  34. private readonly PluginLogger _logger; // 添加日志实例
  35. private string? _appBaseAddress;
  36. private static string? _accesToken;
  37. protected string? AppUser;
  38. protected string? AppPassword;
  39. static ImportPacsResultPlugInsYinHai()
  40. {
  41. Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true;
  42. }
  43. public ImportPacsResultPlugInsYinHai(Guid thirdInterfaceId)
  44. {
  45. _logger = new PluginLogger();
  46. AppConfig = new ConfigurationBuilder()
  47. .SetBasePath(DirectoryHelper.GetAppDirectory()) // 设置基础路径为当前目录
  48. .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
  49. .Build();
  50. AppConnctionStr = AppConfig.GetSection("ConnectionStrings")
  51. .GetSection("Default").Value;
  52. using (DbConnection conn = new NpgsqlConnection(AppConnctionStr))
  53. {
  54. string sql;
  55. sql = @"
  56. SELECT *
  57. from third_interface
  58. where id =@ThirdInterfaceId
  59. ";
  60. _thirdInterfaceDto = (conn.Query<ThirdInterfaceDto>(sql,
  61. new { ThirdInterfaceId = thirdInterfaceId })).Single();
  62. }
  63. var configurationBuilder = new ConfigurationBuilder()
  64. .AddJsonStream(new MemoryStream(System.Text.Encoding.UTF8.GetBytes(_thirdInterfaceDto.ParmValue)));
  65. InterfaceConfig = configurationBuilder.Build();
  66. _appBaseAddress = AppConfig.GetSection("App")
  67. .GetSection("SelfUrl").Value;
  68. AppUser = AppConfig.GetSection("App")
  69. .GetSection("SelfUser").Value;
  70. AppPassword = AppConfig.GetSection("App")
  71. .GetSection("SelfPassword").Value;
  72. }
  73. public ImportPacsResultPlugInsYinHai(string parmValue)
  74. {
  75. _logger = new PluginLogger();
  76. AppConfig = new ConfigurationBuilder()
  77. .SetBasePath(DirectoryHelper.GetAppDirectory()) // 设置基础路径为当前目录
  78. .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
  79. .Build();
  80. AppConnctionStr = AppConfig.GetSection("ConnectionStrings")
  81. .GetSection("Default").Value;
  82. var configurationBuilder = new ConfigurationBuilder()
  83. .AddJsonStream(new MemoryStream(System.Text.Encoding.UTF8.GetBytes(parmValue)));
  84. InterfaceConfig = configurationBuilder.Build();
  85. _appBaseAddress = AppConfig.GetSection("App")
  86. .GetSection("SelfUrl").Value;
  87. AppUser = AppConfig.GetSection("App")
  88. .GetSection("SelfUser").Value;
  89. AppPassword = AppConfig.GetSection("App")
  90. .GetSection("SelfPassword").Value;
  91. }
  92. /// <summary>
  93. /// 接收Pacs检查结果
  94. /// </summary>
  95. /// <param name="input"></param>
  96. /// <returns></returns>
  97. /// <exception cref="Exception"></exception>
  98. public async Task<CallBussinessResponseDetailDto> SendResultRequestAsync(InferfaceXmlDataDto input)
  99. {
  100. var res = new CallBussinessResponseDetailDto
  101. {
  102. msg = "失败",
  103. status_code = "-1"
  104. };
  105. #region 解析xml
  106. var pacsResultCallRequestData = GetPacsResultCallRequestData(input.message);
  107. #endregion
  108. _logger.LogResult("银海接收pacs检查结果", $"请求数据:{input.message}");
  109. try
  110. {
  111. var execDoctorUser = InterfaceConfig.GetValue("Interface:ExecDoctorUser", "");
  112. // var commonTableTypeId = InterfaceConfig.GetValue("Interface:CommonTableTypeId", "");
  113. var execOrganizationUnitId = InterfaceConfig.GetValue("Interface:ExecOrganizationUnitId", "");
  114. var checkDoctorName = InterfaceConfig.GetValue("Interface:CheckDoctorName", "");
  115. string actionName = "result_call";
  116. string codeName = "pacs_server";
  117. var bodyData = pacsResultCallRequestData.body.data.request_details;
  118. if (bodyData.detail.Any())
  119. {
  120. foreach (var item in bodyData.detail)
  121. {
  122. var createImportPacsResultDto = new CreateImportPacsResultDto()
  123. {
  124. CheckRequestNo = item.request_no,
  125. PatientName = GetPatientNameByCheckRequsetNo(item.request_no).GetAwaiter().GetResult(),
  126. Result = item.diag_result,
  127. Summary = item.diag_result,
  128. Suggestion = item.diag_suggest,
  129. //CheckDate = checkDate,
  130. CheckDoctorName = checkDoctorName
  131. //Files = new List<CreateImportPacsResultPictureDto>()
  132. //{
  133. // new CreateImportPacsResultPictureDto()
  134. // {
  135. // IsPrint = 'Y',
  136. // FileTransMode = "1",//0-json,1-url
  137. // FileName = item.image_address,
  138. // FileFormat = "0",//0-图片,1-pdf
  139. // FileUrl = item.image_address
  140. // //FileBase64 = Shentun.Utilities.FileHelper.ToBase64(firstData.reportUrl)
  141. // }
  142. //}
  143. };
  144. if (item.image_address.StartsWith("http://") || item.image_address.StartsWith("https://"))
  145. {
  146. //有值
  147. var hzString = Path.GetExtension(item.image_address);
  148. if (hzString.ToLowerInvariant() == ".pdf")
  149. {
  150. var pList = new List<CreateImportPacsResultPictureDto>();
  151. pList.Add(new CreateImportPacsResultPictureDto()
  152. {
  153. IsPrint = 'Y',
  154. FileTransMode = "1",//0-json,1-url
  155. FileName = item.image_address,
  156. FileFormat = "1",//0-图片,1-pdf
  157. FileUrl = item.image_address
  158. //FileBase64 = Shentun.Utilities.FileHelper.ToBase64(firstData.reportUrl)
  159. });
  160. createImportPacsResultDto.Files = pList;
  161. }
  162. else if (hzString.ToLowerInvariant() == ".jpg" || hzString.ToLowerInvariant() == ".jpeg" || hzString.ToLowerInvariant() == ".png")
  163. {
  164. var pList = new List<CreateImportPacsResultPictureDto>();
  165. pList.Add(new CreateImportPacsResultPictureDto()
  166. {
  167. IsPrint = 'Y',
  168. FileTransMode = "1",//0-json,1-url
  169. FileName = item.image_address,
  170. FileFormat = "0",//0-图片,1-pdf
  171. FileUrl = item.image_address
  172. //FileBase64 = Shentun.Utilities.FileHelper.ToBase64(firstData.reportUrl)
  173. });
  174. createImportPacsResultDto.Files = pList;
  175. }
  176. }
  177. var callResult = await CallAppServiceAsync<CreateImportPacsResultDto, object>("api/app/ImportPacsResult/ImportResult", createImportPacsResultDto);
  178. _logger.LogResult("银海接收pacs检查结果", $"处理成功,pacs申请单号【{item.request_no}】");
  179. var yinHaiSendInterfaceLogDto = new YinHaiSendInterfaceLogDto
  180. {
  181. LogName = "接收pacs检查结果",
  182. ExecDoctorUser = Guid.Parse(execDoctorUser),
  183. InterfaceName = $"{codeName}_{actionName}",
  184. ParaValue = input.message,
  185. RequestNo = item.request_no,
  186. ReturnParaValue = ""
  187. };
  188. await AddSendLog(yinHaiSendInterfaceLogDto);
  189. }
  190. }
  191. else
  192. {
  193. throw new Exception("无结果数据");
  194. }
  195. res = new CallBussinessResponseDetailDto
  196. {
  197. status_code = "1",
  198. msg = "成功"
  199. };
  200. }
  201. catch (Exception ex)
  202. {
  203. _logger.LogResult("银海接收pacs检查结果", ex, $"接收pacs检查结果异常");
  204. }
  205. return res;
  206. }
  207. /// <summary>
  208. /// 根据检查单号获取病人姓名
  209. /// </summary>
  210. /// <param name="checkRequestNo"></param>
  211. /// <returns></returns>
  212. private async Task<string> GetPatientNameByCheckRequsetNo(string checkRequestNo)
  213. {
  214. string msg = "";
  215. using (DbConnection conn = new NpgsqlConnection(AppConnctionStr))
  216. {
  217. string sql;
  218. sql = $@"select a.patient_name from patient_register as a
  219. left join register_check as b on a.id=b.patient_register_id
  220. where b.check_request_no=@checkRequestNo ";
  221. msg = await conn.QueryFirstOrDefaultAsync<string>(sql, new
  222. {
  223. checkRequestNo = checkRequestNo
  224. });
  225. }
  226. return msg;
  227. }
  228. /// <summary>
  229. /// 添加日志
  230. /// </summary>
  231. /// <param name="input"></param>
  232. /// <returns></returns>
  233. private async Task AddSendLog(YinHaiSendInterfaceLogDto input)
  234. {
  235. using (DbConnection conn = new NpgsqlConnection(AppConnctionStr))
  236. {
  237. string sql;
  238. sql = $@" insert into interface_send_log (id,log_name,request_no,interface_name,para_value,return_para_value,concurrency_stamp,
  239. creation_time,creator_id,last_modification_time,last_modifier_id) values
  240. (@id,@log_name,@request_no,@interface_name,@para_value,@return_para_value,@concurrency_stamp,
  241. @creation_time,@creator_id,@last_modification_time,@last_modifier_id)
  242. ";
  243. await conn.ExecuteAsync(sql,
  244. new
  245. {
  246. id = Guid.NewGuid(),
  247. log_name = input.LogName,
  248. request_no = input.RequestNo,
  249. interface_name = input.InterfaceName,
  250. para_value = input.ParaValue,
  251. return_para_value = input.ReturnParaValue,
  252. concurrency_stamp = Guid.NewGuid().ToString("N"),
  253. creation_time = DateTime.Now,
  254. creator_id = input.ExecDoctorUser,
  255. last_modification_time = DateTime.Now,
  256. last_modifier_id = input.ExecDoctorUser
  257. });
  258. }
  259. }
  260. #region 解析xml
  261. private PacsResultCallRequestDto GetPacsResultCallRequestData(string message)
  262. {
  263. try
  264. {
  265. var doc = new XmlDocument();
  266. doc.LoadXml(message);
  267. var request = new PacsResultCallRequestDto();
  268. var root = doc.DocumentElement;
  269. if (root == null) return null;
  270. // 解析 head
  271. var headNode = root.SelectSingleNode("head");
  272. if (headNode != null)
  273. {
  274. request.head = new CallBussinessRequestHeadDto
  275. {
  276. version = GetNodeValue(headNode, "version"),
  277. timestamp = GetNodeValue(headNode, "timestamp"),
  278. sign = GetNodeValue(headNode, "sign"),
  279. request_id = GetNodeValue(headNode, "request_id"),
  280. source_system = GetNodeValue(headNode, "source_system"),
  281. object_system = GetNodeValue(headNode, "object_system"),
  282. action = GetNodeValue(headNode, "action"),
  283. code = GetNodeValue(headNode, "code")
  284. };
  285. }
  286. // 解析 body
  287. var bodyNode = root.SelectSingleNode("body");
  288. if (bodyNode != null)
  289. {
  290. request.body = new PacsResultCallRequestBodyDto();
  291. var dataNode = bodyNode.SelectSingleNode("data");
  292. if (dataNode != null)
  293. {
  294. request.body.data = new PacsResultCallRequestBodyDataDto();
  295. var requestDetailsNode = dataNode.SelectSingleNode("request_details");
  296. if (requestDetailsNode != null)
  297. {
  298. // 创建 detail 列表
  299. request.body.data.request_details = new PacsResultCallRequestBodyDataRequestDetails
  300. {
  301. detail = new List<PacsResultCallRequestBodyDataRequestDetail>()
  302. };
  303. // 获取所有 detail 节点
  304. var detailNodes = requestDetailsNode.SelectNodes("detail");
  305. if (detailNodes != null)
  306. {
  307. foreach (XmlNode detailNode in detailNodes)
  308. {
  309. var detail = new PacsResultCallRequestBodyDataRequestDetail
  310. {
  311. hos_id = GetNodeValue(detailNode, "hos_id"),
  312. request_no = GetNodeValue(detailNode, "request_no"),
  313. patient_type = GetNodeValue(detailNode, "patient_type"),
  314. report_serial_no = GetNodeValue(detailNode, "report_serial_no"),
  315. org_code = GetNodeValue(detailNode, "org_code"),
  316. system_source = GetNodeValue(detailNode, "system_source"),
  317. org_name = GetNodeValue(detailNode, "org_name"),
  318. patient_id = GetNodeValue(detailNode, "patient_id"),
  319. visit_id = GetNodeValue(detailNode, "visit_id"),
  320. order_id = GetNodeValue(detailNode, "order_id"),
  321. remark = GetNodeValue(detailNode, "remark"),
  322. check_no = GetNodeValue(detailNode, "check_no"),
  323. conform_reality = GetNodeValue(detailNode, "conform_reality"),
  324. diag_result = GetNodeValue(detailNode, "diag_result"),
  325. diag_suggest = GetNodeValue(detailNode, "diag_suggest"),
  326. image_address = GetNodeValue(detailNode, "image_address"),
  327. image_generation_time = GetNodeValue(detailNode, "image_generation_time"),
  328. image_report_index = GetNodeValue(detailNode, "image_report_index"),
  329. item_serial_no = GetNodeValue(detailNode, "item_serial_no"),
  330. positive_flag = GetNodeValue(detailNode, "positive_flag"),
  331. report_quality = GetNodeValue(detailNode, "report_quality"),
  332. study_uuid = GetNodeValue(detailNode, "study_uuid")
  333. };
  334. request.body.data.request_details.detail.Add(detail);
  335. }
  336. }
  337. }
  338. }
  339. }
  340. return request;
  341. }
  342. catch (Exception ex)
  343. {
  344. //_logger.LogError(ex, "解析 XML 失败");
  345. return null;
  346. }
  347. }
  348. private string GetNodeValue(XmlNode parent, string nodeName)
  349. {
  350. var node = parent.SelectSingleNode(nodeName);
  351. return node?.InnerText ?? "";
  352. }
  353. #endregion
  354. /// <summary>
  355. /// 发起api请求
  356. /// </summary>
  357. /// <typeparam name="TInput"></typeparam>
  358. /// <typeparam name="TOut"></typeparam>
  359. /// <param name="url"></param>
  360. /// <param name="data"></param>
  361. /// <param name="method"></param>
  362. /// <returns></returns>
  363. /// <exception cref="Exception"></exception>
  364. private async Task<TOut> CallAppServiceAsync<TInput, TOut>(string url, TInput data, string method = "post")
  365. {
  366. if (string.IsNullOrWhiteSpace(_appBaseAddress))
  367. {
  368. throw new Exception("_appBaseAddress不能为空");
  369. }
  370. string baseAddress = _appBaseAddress;
  371. await CheckLoginAsync();
  372. using (var httpClientHandler = new HttpClientHandler())
  373. {
  374. using (var httpClient = new HttpClient(httpClientHandler))
  375. {
  376. httpClient.BaseAddress = new Uri(baseAddress);
  377. httpClient.DefaultRequestHeaders.Accept.Add(
  378. new MediaTypeWithQualityHeaderValue("application/json"));//设置accept标头,告诉JSON是可接受的响应类型
  379. httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _accesToken);
  380. IsoDateTimeConverter timeFormat = new IsoDateTimeConverter();
  381. timeFormat.DateTimeFormat = "yyyy-MM-dd HH:mm:ss";
  382. var sendData = JsonConvert.SerializeObject(data, Newtonsoft.Json.Formatting.Indented, timeFormat);
  383. using (HttpContent httpContent = new StringContent(sendData))
  384. {
  385. httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
  386. HttpResponseMessage response = null;
  387. if (method == "post")
  388. {
  389. response = await httpClient.PostAsync(url, httpContent);
  390. }
  391. else
  392. {
  393. response = await httpClient.GetAsync(url);
  394. }
  395. string result;
  396. if (!response.IsSuccessStatusCode)
  397. {
  398. result = response.Content.ReadAsStringAsync().Result;
  399. throw new Exception("http通信错误:" + response.StatusCode + ",结果:" + result);
  400. }
  401. result = await response.Content.ReadAsStringAsync();
  402. var resultDto = JsonConvert.DeserializeObject<WebApiOutDto<TOut>>(result);
  403. if (resultDto.Code == -1)
  404. {
  405. throw new Exception($"调用WebApi失败,返回-1,消息:" + resultDto.Message);
  406. }
  407. return resultDto.Data;
  408. }
  409. }
  410. }
  411. }
  412. #region 获取token
  413. private async Task<WebApiOutDto<LoginOutDataDto>> LoginAsync(string userId, string password)
  414. {
  415. if (string.IsNullOrWhiteSpace(userId))
  416. {
  417. throw new Exception("用户ID不能为空");
  418. }
  419. if (string.IsNullOrWhiteSpace(password))
  420. {
  421. throw new Exception("密码不能为空");
  422. }
  423. using (var httpClientHandler = new HttpClientHandler())
  424. {
  425. using (var httpClient = new HttpClient(httpClientHandler))
  426. {
  427. httpClient.BaseAddress = new Uri(_appBaseAddress);
  428. httpClient.DefaultRequestHeaders.Accept.Add(
  429. new MediaTypeWithQualityHeaderValue("application/json"));//设置accept标头,告诉JSON是可接受的响应类型
  430. var url = "api/identity/users/login";
  431. var loginUser = new LoginInputDto()
  432. {
  433. UserName = userId,
  434. Password = password
  435. };
  436. var sendData = JsonConvert.SerializeObject(loginUser);
  437. using (HttpContent httpContent = new StringContent(sendData))
  438. {
  439. httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
  440. HttpResponseMessage response = await httpClient.PostAsync(url, httpContent);
  441. string result;
  442. if (!response.IsSuccessStatusCode)
  443. {
  444. result = response.Content.ReadAsStringAsync().Result;
  445. throw new Exception("http通信错误:" + response.StatusCode + ",结果:" + result);
  446. }
  447. result = await response.Content.ReadAsStringAsync();
  448. var restultDto = JsonConvert.DeserializeObject<WebApiOutDto<LoginOutDataDto>>(result);
  449. if (restultDto == null)
  450. {
  451. throw new Exception("返回结果是空");
  452. }
  453. if (restultDto.Code != 1)
  454. {
  455. throw new Exception($"登录失败{restultDto.Message}");
  456. }
  457. _accesToken = restultDto.Data.access_token;
  458. return restultDto;
  459. }
  460. }
  461. }
  462. }
  463. private async Task CheckLoginAsync()
  464. {
  465. if (string.IsNullOrWhiteSpace(_accesToken))
  466. {
  467. await LoginAsync();
  468. }
  469. else
  470. {
  471. var handler = new JwtSecurityTokenHandler();
  472. var payload = handler.ReadJwtToken(_accesToken).Payload;
  473. var claims = payload.Claims;
  474. var exp = claims.First(claim => claim.Type == "exp").Value;
  475. if (exp == null)
  476. {
  477. await LoginAsync();
  478. }
  479. else
  480. {
  481. if (long.TryParse(exp, out var expires))
  482. {
  483. var expireTime = DateTimeOffset.FromUnixTimeSeconds(expires).LocalDateTime;
  484. if (expireTime <= DateTime.Now)
  485. {
  486. await LoginAsync();
  487. }
  488. }
  489. else
  490. {
  491. await LoginAsync();
  492. }
  493. }
  494. }
  495. }
  496. private async Task<WebApiOutDto<LoginOutDataDto>> LoginAsync()
  497. {
  498. if (string.IsNullOrWhiteSpace(AppUser))
  499. {
  500. throw new Exception("SelfUser不能为空");
  501. }
  502. if (string.IsNullOrWhiteSpace(AppPassword))
  503. {
  504. throw new Exception("SelfPassword不能为空");
  505. }
  506. var relult = await LoginAsync(AppUser, AppPassword);
  507. return relult;
  508. }
  509. #endregion
  510. }
  511. }