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.

559 lines
23 KiB

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