EmrServer.java 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. package thyyxxk.webserver.service.zhuyuanyisheng;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.JSONArray;
  4. import com.alibaba.fastjson.JSONObject;
  5. import com.alibaba.fastjson.serializer.SerializerFeature;
  6. import com.baomidou.dynamic.datasource.annotation.DS;
  7. import lombok.extern.slf4j.Slf4j;
  8. import org.springframework.stereotype.Service;
  9. import org.springframework.web.client.RestTemplate;
  10. import thyyxxk.webserver.config.exception.ExceptionEnum;
  11. import thyyxxk.webserver.constants.EmrType;
  12. import thyyxxk.webserver.dao.his.LoginDao;
  13. import thyyxxk.webserver.dao.his.zhuyuanyisheng.EmrPatientDao;
  14. import thyyxxk.webserver.entity.ResultVo;
  15. import thyyxxk.webserver.entity.dictionary.CodeName;
  16. import thyyxxk.webserver.entity.drg.AuxiliaryFillingOfDiagnosis;
  17. import thyyxxk.webserver.entity.zhuyuanyisheng.emr.EmrDataElement;
  18. import thyyxxk.webserver.entity.zhuyuanyisheng.emr.EmrDataExtract;
  19. import thyyxxk.webserver.entity.zhuyuanyisheng.emr.EmrPatientData;
  20. import thyyxxk.webserver.service.PublicServer;
  21. import thyyxxk.webserver.service.externalhttp.emr.EmrEditor;
  22. import thyyxxk.webserver.utils.*;
  23. import java.util.*;
  24. import java.util.stream.Collectors;
  25. @Service
  26. @Slf4j
  27. @DS("his")
  28. public class EmrServer {
  29. private final EmrPatientDao dao;
  30. private final EmrEditor emr;
  31. private final PublicServer publicServer;
  32. private final LoginDao loginDao;
  33. public EmrServer(EmrPatientDao dao, EmrEditor emr, PublicServer publicServer, LoginDao loginDao) {
  34. this.dao = dao;
  35. this.emr = emr;
  36. this.publicServer = publicServer;
  37. this.loginDao = loginDao;
  38. }
  39. /**
  40. * 获取这个患者这个住院次数的全部电子病历
  41. *
  42. * @param patNo 住院号
  43. * @param times 住院次数
  44. * @return 数据
  45. */
  46. public ResultVo<List<EmrPatientData>> getPatientDataTree(String patNo, Integer times) {
  47. List<EmrPatientData> data = new ArrayList<>();
  48. Map<String, List<EmrPatientData>> map = dao.getPatientData(patNo, times).stream().collect(Collectors.groupingBy(EmrPatientData::getEmrCategoryCode));
  49. for (Map.Entry<String, List<EmrPatientData>> key : map.entrySet()) {
  50. if (key.getValue().size() == 1) {
  51. data.add(key.getValue().get(0));
  52. } else {
  53. EmrPatientData item = new EmrPatientData();
  54. List<EmrPatientData> children = new ArrayList<>();
  55. for (int i = 0, len = key.getValue().size(); i < len; i++) {
  56. EmrPatientData childNode = key.getValue().get(i);
  57. children.add(childNode);
  58. }
  59. item.setName(key.getValue().get(0).getEmrName());
  60. item.setChildren(new ArrayList<>()).getChildren().addAll(children);
  61. data.add(item);
  62. }
  63. }
  64. return ResultVoUtil.success(data);
  65. }
  66. public ResultVo<List<JSONObject>> getEmrTree() {
  67. JSONArray data = emr.getEmrTree();
  68. List<JSONObject> tree = new ArrayList<>();
  69. if (data.isEmpty()) {
  70. return ResultVoUtil.success(tree);
  71. }
  72. emrArrToTree(data, tree);
  73. return ResultVoUtil.success(tree);
  74. }
  75. private static void emrArrToTree(JSONArray data, List<JSONObject> tree) {
  76. Map<String, JSONObject> map = new HashMap<>(data.size());
  77. for (int i = 0; i < data.size(); i++) {
  78. JSONObject item = data.getJSONObject(i);
  79. if (item.get("parent") == null) {
  80. tree.add(item);
  81. }
  82. map.put(item.getString("_id"), item);
  83. }
  84. for (int i = 0; i < data.size(); i++) {
  85. JSONObject item = data.getJSONObject(i);
  86. if (map.containsKey(item.getString("parent"))) {
  87. JSONObject parentList = map.get(item.getString("parent"));
  88. if (parentList.get("children") == null) {
  89. parentList.put("children", new JSONArray());
  90. }
  91. parentList.getJSONArray("children").add(item);
  92. }
  93. }
  94. }
  95. public ResultVo<List<JSONObject>> getSnippetTree() {
  96. JSONArray data = emr.getSnippetTree();
  97. List<JSONObject> tree = new ArrayList<>();
  98. emrArrToTree(data, tree);
  99. return ResultVoUtil.success(tree);
  100. }
  101. /**
  102. * 提取患者数据元
  103. *
  104. * @param param 结构化文档
  105. */
  106. public Map<String, Object> extractDataElement(EmrPatientData param) {
  107. EmrDataExtract emrDataExtract = dao.extractDataSource(param.getEmrCategoryCode());
  108. if (emrDataExtract == null) {
  109. return new HashMap<>();
  110. }
  111. // 获取 需要提取的数据元
  112. List<String> strings = JSON.parseArray(emrDataExtract.getDataExtract(), String.class);
  113. // 获取前端传入的数据元
  114. JSONObject elementData = param.getEmrDataElement();
  115. // 提取到的数据
  116. Map<String, Object> extractedData = new HashMap<>(strings.size());
  117. for (String el : strings) {
  118. if (elementData.containsKey(el)) {
  119. JSONObject item = elementData.getJSONObject(el);
  120. Object value = item.get("value");
  121. if (value != null) {
  122. extractedData.put(el, value);
  123. }
  124. }
  125. }
  126. EmrDataElement emrDataElement = dao.obtainPatientSOriginalData(param.getPatNo(), param.getTimes());
  127. if (emrDataElement == null) {
  128. dao.insertDataSource(param.getPatNo(), param.getTimes(), JSON.toJSONString(extractedData));
  129. } else {
  130. JSONObject jsonObject = JSONObject.parseObject(emrDataElement.getDataElement());
  131. log.info("患者原来的数据:{}", jsonObject);
  132. jsonObject.putAll(extractedData);
  133. dao.updatePatientDataSource(param.getPatNo(), param.getTimes(), JSON.toJSONString(jsonObject));
  134. }
  135. log.info("提取到的数据:{}", JSON.toJSONString(extractedData));
  136. return extractedData;
  137. }
  138. /**
  139. * 保存患者电子病历信息
  140. *
  141. * @param param 参数
  142. * @return 提示
  143. */
  144. public ResultVo<Map<String, Object>> insertEmrData(EmrPatientData param) {
  145. param.setCreateId(TokenUtil.getTokenUserId());
  146. boolean isUpdated = dao.whetherThereIsAMedicalRecord(param.getPatNo(), param.getTimes(), param.getEmrDocumentId()).equals(1);
  147. Map<String, Object> extractedData = extractDataElement(param);
  148. if (isUpdated) {
  149. dao.updateCreatedTemplate(param);
  150. } else {
  151. dao.emrInsertForTheFirstTime(param);
  152. }
  153. return ResultVoUtil.success(extractedData);
  154. }
  155. /**
  156. * 根据患者的电子病历 id 来删除
  157. * 这里用的是逻辑删除
  158. *
  159. * @param documentId 电子病历id
  160. * @return 删除电子病历的同时需要删除, 提取到的数据源.
  161. */
  162. public ResultVo<List<String>> deletePatientEmrByDocumentId(String documentId) {
  163. EmrPatientData patientData = dao.getCategoryCodeByDocumentId(documentId);
  164. EmrDataExtract emrDataExtract = dao.extractDataSource(patientData.getEmrCategoryCode());
  165. List<String> strings = new ArrayList<>();
  166. if (emrDataExtract != null) {
  167. // 获取 需要提取的数据元
  168. strings = JSON.parseArray(emrDataExtract.getDataExtract(), String.class);
  169. log.info("需要提取的数据:{}", strings);
  170. // 获取到已经提取的数据
  171. EmrDataElement emrDataElement = dao.obtainPatientSOriginalData(patientData.getPatNo(), patientData.getTimes());
  172. // 转 json
  173. JSONObject jsonObject = JSONObject.parseObject(emrDataElement.getDataElement());
  174. for (String string : strings) {
  175. // 删除提取到的数据
  176. jsonObject.remove(string);
  177. }
  178. // 更新患者数据元
  179. dao.updatePatientDataSource(patientData.getPatNo(), patientData.getTimes(), JSON.toJSONString(jsonObject));
  180. }
  181. // 删除病历
  182. dao.deletePatientEmrByDocumentId(documentId, TokenUtil.getTokenUserId());
  183. return ResultVoUtil.success(strings);
  184. }
  185. /**
  186. * 查询患者是否有指定的病历了
  187. *
  188. * @param param 住院号,住院次数,病历编码
  189. * @return 返回 Boolean
  190. */
  191. public ResultVo<Boolean> queryWhetherThePatientHasASpecifiedMedicalRecord(EmrPatientData param) {
  192. return ResultVoUtil.success(dao.queryWhetherThePatientHasASpecifiedMedicalRecord(param.getPatNo(), param.getTimes(), param.getEmrCategoryCode()) == 1);
  193. }
  194. /**
  195. * 医生诊断热缩
  196. *
  197. * @param userCode 医生编码
  198. * @param code 诊断 code
  199. * @param tableName 表名
  200. */
  201. public void hotSearchSorting(String userCode, String code, String tableName) {
  202. boolean insert = dao.queryWhetherThereIsHotSearch(userCode, code, tableName) == 0;
  203. if (insert) {
  204. dao.hotSearchSorting(userCode, code, tableName);
  205. } else {
  206. dao.updateHotSearch(userCode, code, tableName);
  207. }
  208. log.info("医生编码:{},搜索关键字:{},表名:{}", userCode, code, tableName);
  209. }
  210. /**
  211. * 根据文档 id 提交病历
  212. *
  213. * @param documentId 文档id
  214. * @return 返回数据
  215. */
  216. public ResultVo<String> submitMedicalRecord(String documentId) {
  217. String userCode = TokenUtil.getTokenUserId();
  218. String createdId = dao.getDocumentIdCreatedBy(documentId);
  219. log.info("提交病历==》 操作人:{},病历id:{},创建人:{}", userCode, documentId, createdId);
  220. if (userCode.equals(createdId)) {
  221. dao.updateSubmissionFlag(documentId);
  222. return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION, "提交成功");
  223. }
  224. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "创建人不一致无法修改。");
  225. }
  226. /**
  227. * 获取电子病历数据
  228. *
  229. * @param panNo 住院号
  230. * @param times 住院次数
  231. * @param etType 类型
  232. * @return 返回数据
  233. */
  234. public JSONArray getEmrData(String panNo, Integer times, EmrType etType) {
  235. // 查询这个病历的 唯一 id
  236. List<String> idList = dao.getDocumentIdByPatietn(panNo, times, etType.getName());
  237. JSONArray returnArray = new JSONArray();
  238. if (ListUtil.isBlank(idList)) {
  239. return returnArray;
  240. }
  241. Map<String, JSONObject> surgicalSequencing = new TreeMap<>();
  242. for (String s : idList) {
  243. JSONObject jsonObject = emr.getEditorJsonDataByDocumentId(s);
  244. if (etType.getCode() == EmrType.DIAGNOSIS.getCode()) {
  245. returnArray.addAll(extractDiagnosis(jsonObject));
  246. } else if (etType.getCode() == EmrType.OPERATION.getCode()) {
  247. String key = DateUtil.formatDatetime(jsonObject.getJSONObject("手术日期").getDate("value"));
  248. surgicalSequencing.put(key, jsonObject);
  249. }
  250. }
  251. if (!surgicalSequencing.isEmpty()) {
  252. for (Map.Entry<String, JSONObject> item : surgicalSequencing.entrySet()) {
  253. returnArray.add(item.getValue());
  254. }
  255. }
  256. return returnArray;
  257. }
  258. private JSONArray extractDiagnosis(JSONObject jsonObject) {
  259. JSONObject diagnosis = jsonObject.getJSONObject("入院诊断");
  260. if (diagnosis != null) {
  261. JSONArray diagnosisArr = diagnosis.getJSONArray("value");
  262. if (diagnosisArr != null) {
  263. return diagnosisArr;
  264. }
  265. }
  266. return new JSONArray();
  267. }
  268. public ResultVo<String> getDrgIntelligentGrouping(String patNo, Integer times) {
  269. // 获取诊断
  270. JSONArray diagnosis = getEmrData(patNo, times, EmrType.DIAGNOSIS);
  271. // 获取手术
  272. JSONArray operation = getEmrData(patNo, times, EmrType.OPERATION);
  273. int ledgerSn = publicServer.getLedgerSn(patNo, times);
  274. // 获取患者数据
  275. Map<String, String> mapData = dao.drgPatientInfo(patNo, times, ledgerSn);
  276. if (mapData == null) {
  277. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "没有查询到患者信息。");
  278. }
  279. mapData.put("visit_id", patNo + "_" + times + "_" + ledgerSn);
  280. mapData.put("bah", patNo + "_" + times);
  281. for (int i = 0; i < diagnosis.size(); i++) {
  282. JSONObject item = diagnosis.getJSONObject(i);
  283. if (i == 0) {
  284. mapData.put("jbdm", item.getString("code"));
  285. mapData.put("zyzd", item.getString("name"));
  286. } else {
  287. mapData.put("jbdm" + i, item.getString("code"));
  288. }
  289. }
  290. int operationIndex = 1;
  291. for (int i = 0; i < operation.size(); i++) {
  292. JSONObject item = operation.getJSONObject(i);
  293. JSONArray list = item.getJSONObject("手术名称").getJSONArray("value");
  294. for (int a = 0; a < list.size(); a++) {
  295. JSONObject valueList = list.getJSONObject(a);
  296. mapData.put("ssjczbm" + operationIndex, valueList.getString("code"));
  297. if (operationIndex == 1) {
  298. mapData.put("ssjczmc" + operationIndex, valueList.getString("name"));
  299. }
  300. operationIndex++;
  301. }
  302. }
  303. AuxiliaryFillingOfDiagnosis data = EntityCopy.Copy(mapData, AuxiliaryFillingOfDiagnosis.class);
  304. String url = "http://172.16.32.126:8080/drg_web/localHelp/drg_dagns/list.action";
  305. RestTemplate template = new RestTemplate();
  306. String toJsonStr = JSON.toJSONString(data, SerializerFeature.WriteNullStringAsEmpty);
  307. log.info("DRG数据:{}", toJsonStr);
  308. String res = template.postForObject(url, JSON.parseObject(toJsonStr), String.class);
  309. return ResultVoUtil.success("http://172.16.32.126:8080" + res);
  310. }
  311. /**
  312. * 获取患者最大的住院次数
  313. *
  314. * @param patNo 住院号
  315. * @return 返回最大次数
  316. */
  317. public ResultVo<Integer> getDischargeTimes(String patNo) {
  318. Integer times = dao.getMaxTimes(patNo);
  319. if (times == null) {
  320. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "没有查询到患者信息。");
  321. }
  322. return ResultVoUtil.success(times);
  323. }
  324. public ResultVo<JSONObject> getExtractDataElement(String patNo, Integer times) {
  325. Map<String, String> map = dao.selectEmrDataElement(patNo, times);
  326. if (map == null) {
  327. return ResultVoUtil.success();
  328. } else {
  329. return ResultVoUtil.success(JSONObject.parseObject(map.get("data_element")));
  330. }
  331. }
  332. public ResultVo<List<CodeName>> getAllWards() {
  333. return ResultVoUtil.success(loginDao.getAllWards());
  334. }
  335. }