EmrServer.java 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065
  1. package thyyxxk.webserver.service.zhuyuanyisheng.emr;
  2. import cn.hutool.core.codec.Base64;
  3. import cn.hutool.core.convert.Convert;
  4. import cn.hutool.core.util.IdUtil;
  5. import cn.hutool.http.HttpRequest;
  6. import com.alibaba.fastjson.JSON;
  7. import com.alibaba.fastjson.JSONArray;
  8. import com.alibaba.fastjson.JSONObject;
  9. import com.alibaba.fastjson.serializer.SerializerFeature;
  10. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  11. import com.dtflys.forest.Forest;
  12. import com.dtflys.forest.http.ForestRequest;
  13. import com.dtflys.forest.interceptor.Interceptor;
  14. import com.dtflys.forest.reflection.ForestMethod;
  15. import com.dtflys.forest.utils.ForestDataType;
  16. import lombok.extern.slf4j.Slf4j;
  17. import org.apache.commons.collections4.ListUtils;
  18. import org.jetbrains.annotations.NotNull;
  19. import org.springframework.beans.factory.annotation.Value;
  20. import org.springframework.scheduling.annotation.Scheduled;
  21. import org.springframework.stereotype.Service;
  22. import org.springframework.transaction.annotation.Transactional;
  23. import org.springframework.web.client.RestTemplate;
  24. import thyyxxk.webserver.config.exception.ExceptionEnum;
  25. import thyyxxk.webserver.constants.Capacity;
  26. import thyyxxk.webserver.constants.EmrType;
  27. import thyyxxk.webserver.dao.his.LoginDao;
  28. import thyyxxk.webserver.dao.his.zhuyuanyisheng.emr.EmrFolderDao;
  29. import thyyxxk.webserver.dao.his.zhuyuanyisheng.emr.EmrPatientDao;
  30. import thyyxxk.webserver.entity.ResultVo;
  31. import thyyxxk.webserver.entity.datamodify.YzTemperature;
  32. import thyyxxk.webserver.entity.dictionary.CodeName;
  33. import thyyxxk.webserver.entity.drg.AuxiliaryFillingOfDiagnosis;
  34. import thyyxxk.webserver.entity.fluorescenceTest.FluorescenceSpecimenResult;
  35. import thyyxxk.webserver.entity.login.UserInfo;
  36. import thyyxxk.webserver.entity.medicalinsurance.inpatient.ZyPatientInfo;
  37. import thyyxxk.webserver.entity.outpatient.thmz.MzEmrPatientData;
  38. import thyyxxk.webserver.entity.socketmessage.ApiMessageBody;
  39. import thyyxxk.webserver.entity.zhuyuanyisheng.ZyZkList;
  40. import thyyxxk.webserver.entity.zhuyuanyisheng.emr.*;
  41. import thyyxxk.webserver.entity.zhuyuanyisheng.jianyanjiancha.YshYjReq;
  42. import thyyxxk.webserver.entity.zhuyuanyisheng.shoushu.OpRecord;
  43. import thyyxxk.webserver.service.PublicServer;
  44. import thyyxxk.webserver.service.RedisServer;
  45. import thyyxxk.webserver.service.externalhttp.WebSocketService;
  46. import thyyxxk.webserver.service.externalhttp.emr.EmrEditor;
  47. import thyyxxk.webserver.service.redislike.RedisLikeService;
  48. import thyyxxk.webserver.utils.*;
  49. import javax.annotation.PostConstruct;
  50. import java.util.*;
  51. import java.util.stream.Collectors;
  52. @Service
  53. @Slf4j
  54. public class EmrServer {
  55. private final EmrPatientDao dao;
  56. private final EmrEditor emr;
  57. private final EmrFolderDao folderDao;
  58. private final RedisServer redisServer;
  59. private final PublicServer publicServer;
  60. private final LoginDao loginDao;
  61. private final RedisLikeService redisLikeService;
  62. private final WebSocketService socketService;
  63. private static String emrToken = null;
  64. private static String EMR_URL;
  65. public static final String THIS_IS_DIR = "This is Dir";
  66. @Value("${forest.variables.emrUrl}")
  67. public void setUrl(String key) {
  68. EMR_URL = key;
  69. }
  70. public static class EmrInterceptor implements Interceptor<String> {
  71. @Override
  72. public void onInvokeMethod(ForestRequest request, ForestMethod method, Object[] args) {
  73. request.addHeader("emr-token", emrToken);
  74. }
  75. }
  76. @PostConstruct
  77. @Scheduled(cron = "* * */12 * * ?")
  78. public void token() {
  79. String URL = EMR_URL.replace("/emr/runtime/api/v1", "");
  80. String result = HttpRequest.post(URL + "/emr/runtime/api/v1/oauth/token")
  81. .header("Authorization", "Basic " + Base64.encode("user:dc71ccfec05b799ad52360c48d504019"))
  82. .form("grant_type", "client_credentials").execute().body();
  83. JSONObject data = JSONObject.parseObject(result);
  84. emrToken = data.getString("access_token");
  85. }
  86. public EmrServer(EmrPatientDao dao,
  87. EmrEditor emr,
  88. EmrFolderDao folderDao,
  89. RedisServer redisServer,
  90. PublicServer publicServer,
  91. LoginDao loginDao,
  92. RedisLikeService redisLikeService,
  93. WebSocketService socketService) {
  94. this.dao = dao;
  95. this.emr = emr;
  96. this.folderDao = folderDao;
  97. this.redisServer = redisServer;
  98. this.publicServer = publicServer;
  99. this.loginDao = loginDao;
  100. this.redisLikeService = redisLikeService;
  101. this.socketService = socketService;
  102. }
  103. /**
  104. * 获取这个患者这个住院次数的全部电子病历
  105. *
  106. * @param patNo 住院号
  107. * @param times 住院次数
  108. * @return 数据
  109. */
  110. public ResultVo<List<EmrPatientData>> getPatientDataTree(String patNo, Integer times) {
  111. List<EmrPatientData> list = dao.getPatientData(patNo, times);
  112. List<EmrPatientData> folder = redisServer.getData("emrFolder", () -> folderDao.getFolderByName("HOSPITAL"));
  113. if (ListUtil.isBlank(list)) {
  114. return ResultVoUtil.success(folder);
  115. }
  116. folder.addAll(list);
  117. Map<String, EmrPatientData> folderMap = new HashMap<>();
  118. List<EmrPatientData> result = new ArrayList<>();
  119. folder.add(EmrPatientData.builder()
  120. .id(null)
  121. .emrDocumentId("noFolder")
  122. .name("可拖动病历调整到合适文件夹,右键确认排序")
  123. .emrCategoryCode(THIS_IS_DIR)
  124. .sort(0)
  125. .children(new ArrayList<>())
  126. .parent(null)
  127. .build());
  128. for (EmrPatientData item : folder) {
  129. folderMap.put(item.getEmrDocumentId(), item);
  130. if (item.getParent() == null) {
  131. if ("group-category".equals(item.getType()))
  132. result.add(item);
  133. }
  134. }
  135. for (EmrPatientData item : folder) {
  136. String key = item.getParent();
  137. EmrPatientData parent = folderMap.get(key);
  138. if (parent != null) {
  139. if (parent.getChildren() == null) {
  140. parent.setChildren(new ArrayList<>());
  141. }
  142. parent.getChildren().add(item);
  143. } else {
  144. if (THIS_IS_DIR.equals(item.getEmrCategoryCode())) {
  145. continue;
  146. }
  147. EmrPatientData no = folderMap.get("noFolder");
  148. no.getChildren().add(item);
  149. }
  150. }
  151. result.sort(Comparator.comparing((o) -> o.getSort() == null ? 0 : o.getSort()));
  152. return ResultVoUtil.success(result);
  153. }
  154. public ResultVo<Map<String, List<JSONObject>>> getEmrTree(String type) {
  155. Map<String, List<JSONObject>> map = new HashMap<>(Capacity.TWO);
  156. if ("all".equals(type)) {
  157. map.put("all", wholeHospitalTemplate());
  158. map.put("dept", getDeptTemplate());
  159. } else if ("dept".equals(type)) {
  160. map.put("dept", getDeptTemplate());
  161. } else if ("hosp".equals(type)) {
  162. map.put("all", wholeHospitalTemplate());
  163. }
  164. return ResultVoUtil.success(map);
  165. }
  166. private List<JSONObject> getDeptTemplate() {
  167. UserInfo user = redisLikeService.getUserInfoByToken();
  168. JSONArray data = new JSONArray();
  169. if (ListUtil.notBlank(user.getPartTimeDept())) {
  170. user.getPartTimeDept().forEach(item -> {
  171. data.addAll(emr.getDeptList(item));
  172. });
  173. }
  174. data.addAll(emr.getDeptList(user.getDeptCode()));
  175. return emrToTree(data);
  176. }
  177. /**
  178. * 获取 整个医院模板
  179. */
  180. private List<JSONObject> wholeHospitalTemplate() {
  181. JSONArray data = emr.getEmrTree();
  182. return emrToTree(data);
  183. }
  184. /**
  185. * 电子病历转成树状图 二次封装
  186. *
  187. * @param data 模板数据
  188. * @return 返回
  189. */
  190. public List<JSONObject> emrToTree(JSONArray data) {
  191. List<JSONObject> tree = new ArrayList<>();
  192. if (data.isEmpty()) {
  193. return tree;
  194. }
  195. emrArrToTree(data, tree);
  196. return tree;
  197. }
  198. /**
  199. * 电子病历转成树状图
  200. *
  201. * @param data 电子病历
  202. * @param tree 树
  203. */
  204. private static void emrArrToTree(JSONArray data, List<JSONObject> tree) {
  205. Map<String, JSONObject> map = new HashMap<>(data.size());
  206. for (int i = 0; i < data.size(); i++) {
  207. JSONObject item = data.getJSONObject(i);
  208. if (item.get("parent") == null) {
  209. tree.add(item);
  210. }
  211. map.put(item.getString("_id"), item);
  212. }
  213. for (int i = 0; i < data.size(); i++) {
  214. JSONObject item = data.getJSONObject(i);
  215. if (map.containsKey(item.getString("parent"))) {
  216. JSONObject parentList = map.get(item.getString("parent"));
  217. parentList.computeIfAbsent("children", k -> new JSONArray());
  218. parentList.getJSONArray("children").add(item);
  219. }
  220. }
  221. }
  222. /**
  223. * 获取电子病历的片段
  224. *
  225. * @return 树
  226. */
  227. public ResultVo<List<JSONObject>> getSnippetTree() {
  228. JSONArray data = emr.getSnippetTree();
  229. List<JSONObject> tree = new ArrayList<>();
  230. emrArrToTree(data, tree);
  231. return ResultVoUtil.success(tree);
  232. }
  233. /**
  234. * 提取患者数据元
  235. *
  236. * @param param 结构化文档
  237. */
  238. public Map<String, Object> extractDataElement(EmrPatientData param) {
  239. EmrDataExtract emrDataExtract = dao.extractDataSource(param.getEmrCategoryCode());
  240. if (emrDataExtract == null) {
  241. return new HashMap<>();
  242. }
  243. // 获取 需要提取的数据元
  244. List<String> strings = JSON.parseArray(emrDataExtract.getDataExtract(), String.class);
  245. // 获取前端传入的数据元
  246. Map<String, Object> extractedData = getStringObjectMap(param, strings);
  247. EmrDataElement emrDataElement = dao.obtainPatientSOriginalData(param.getPatNo(), param.getTimes());
  248. if (emrDataElement == null) {
  249. // 创建的病历可以解锁了
  250. dao.insertDataSource(param.getPatNo(), param.getTimes(), JSON.toJSONString(extractedData));
  251. } else {
  252. JSONObject jsonObject = JSONObject.parseObject(emrDataElement.getDataElement());
  253. jsonObject.putAll(extractedData);
  254. dao.updatePatientDataSource(param.getPatNo(), param.getTimes(), JSON.toJSONString(jsonObject));
  255. }
  256. return extractedData;
  257. }
  258. @NotNull
  259. private static Map<String, Object> getStringObjectMap(EmrPatientData param, List<String> strings) {
  260. JSONObject elementData = param.getEmrDataElement();
  261. // 提取到的数据
  262. Map<String, Object> extractedData = new HashMap<>(strings.size());
  263. for (String el : strings) {
  264. if (elementData.containsKey(el)) {
  265. JSONObject item;
  266. try {
  267. item = elementData.getJSONObject(el);
  268. } catch (Exception ignore) {
  269. throw new RuntimeException("数据元提取失败,但病历保存成功。数据元名称:【" + el + "】,粘贴时请使用(文本粘贴)。");
  270. }
  271. Object value = item.get("value");
  272. if (value != null) {
  273. extractedData.put(el, value);
  274. }
  275. }
  276. }
  277. return extractedData;
  278. }
  279. /**
  280. * 保存电子病历
  281. *
  282. * @param param 参数
  283. * @return 提示
  284. */
  285. @Transactional(rollbackFor = Exception.class)
  286. public ResultVo<Map<String, Object>> insertEmrData(EmrPatientData param) {
  287. EmrPatientData patientData = dao.getCategoryCodeByDocumentId(param.getEmrDocumentId());
  288. if (patientData != null && patientData.getSignComplete()) {
  289. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "患者完成电子签名无法修改。");
  290. }
  291. JSONObject saveJson = new JSONObject();
  292. saveJson.put("document", param.getDocumentData());
  293. try {
  294. emr.saveDocument(saveJson);
  295. } catch (Exception e) {
  296. return ResultVoUtil.fail(ExceptionEnum.EMR_SAVE, "病历保存错误,请重试!" + e.getMessage());
  297. }
  298. param.setCreateId(TokenUtil.getInstance().getTokenUserId());
  299. Integer isUpdated = dao.whetherThereIsAMedicalRecord(param.getEmrDocumentId());
  300. if (isUpdated != null) {
  301. dao.updateCreatedTemplate(param);
  302. insertAFragmentOfTheCourseOfTheDisease(isUpdated, param.getFragment());
  303. } else {
  304. // 新增的时候插入数据
  305. ZyPatientInfo patInfo = publicServer.getPatInfo(param.getPatNo(), param.getTimes());
  306. param.setReferPhysician(patInfo.getReferPhysician());
  307. param.setConsultPhysician(patInfo.getConsultPhysician());
  308. param.setDeptDirector(patInfo.getDeptDirector());
  309. dao.emrInsertForTheFirstTime(param);
  310. insertAFragmentOfTheCourseOfTheDisease(param.getId(), param.getFragment());
  311. }
  312. Map<String, Object> extractedData;
  313. try {
  314. extractedData = extractDataElement(param);
  315. } catch (Exception e) {
  316. return ResultVoUtil.fail(ExceptionEnum.EMR_EXTRACT_OBJECTS, e.getMessage());
  317. }
  318. return ResultVoUtil.success(extractedData);
  319. }
  320. /**
  321. * 插入病程记录的片段
  322. *
  323. * @param id 病程记录
  324. * @param fragment 片段
  325. */
  326. private void insertAFragmentOfTheCourseOfTheDisease(Integer id, List<EmrProgressNote> fragment) {
  327. if (ListUtil.isBlank(fragment)) {
  328. return;
  329. }
  330. dao.delOldFragment(id);
  331. List<List<EmrProgressNote>> lists = ListUtils.partition(fragment, 50);
  332. for (List<EmrProgressNote> list : lists) {
  333. dao.insertFragment(list, id);
  334. }
  335. }
  336. /**
  337. * 根据患者的电子病历 id 来删除
  338. * 这里用的是逻辑删除
  339. *
  340. * @param documentId 电子病历id
  341. * @return 删除电子病历的同时需要删除, 提取到的数据源.
  342. */
  343. public ResultVo<List<String>> deletePatientEmrByDocumentId(String documentId) {
  344. EmrPatientData patientData = dao.getCategoryCodeByDocumentId(documentId);
  345. if (patientData.getSignComplete()) {
  346. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "患者完成电子签名无法删除。");
  347. }
  348. // 如果没有医务部的权限的话就不能删除
  349. if (!publicServer.needRule(38)) {
  350. if (!patientData.getCreateId().equals(TokenUtil.getInstance().getTokenUserId())) {
  351. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "创建人不是你无法删除。");
  352. }
  353. }
  354. EmrDataExtract emrDataExtract = dao.extractDataSource(patientData.getEmrCategoryCode());
  355. List<String> strings = new ArrayList<>();
  356. if (emrDataExtract != null) {
  357. // 获取 需要提取的数据元
  358. strings = JSON.parseArray(emrDataExtract.getDataExtract(), String.class);
  359. // 获取到已经提取的数据
  360. EmrDataElement emrDataElement = dao.obtainPatientSOriginalData(patientData.getPatNo(), patientData.getTimes());
  361. // 转 json
  362. JSONObject jsonObject = JSONObject.parseObject(emrDataElement.getDataElement());
  363. for (String string : strings) {
  364. // 删除提取到的数据
  365. jsonObject.remove(string);
  366. }
  367. // 更新患者数据元
  368. dao.updatePatientDataSource(patientData.getPatNo(), patientData.getTimes(), JSON.toJSONString(jsonObject));
  369. }
  370. // 删除病历
  371. dao.deletePatientEmrByDocumentId(documentId, TokenUtil.getInstance().getTokenUserId());
  372. try {
  373. emr.deleteEmr(documentId);
  374. } catch (Exception e) {
  375. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "删除电子病历失败,请重试!" + e.getMessage());
  376. }
  377. return ResultVoUtil.success(strings);
  378. }
  379. /**
  380. * 查询患者是否有指定的病历了
  381. *
  382. * @param param 住院号,住院次数,病历编码
  383. * @return 返回 Boolean
  384. */
  385. public ResultVo<Boolean> queryWhetherThePatientHasASpecifiedMedicalRecord(EmrPatientData param) {
  386. return ResultVoUtil.success(dao.queryWhetherThePatientHasASpecifiedMedicalRecord(param.getPatNo(), param.getTimes(), param.getEmrCategoryCode()) == 1);
  387. }
  388. /**
  389. * 医生诊断热缩
  390. *
  391. * @param userCode 医生编码
  392. * @param code 诊断 code
  393. * @param tableName 表名
  394. */
  395. public void hotSearchSorting(String userCode, String code, String tableName) {
  396. boolean insert = dao.queryWhetherThereIsHotSearch(userCode, code, tableName) == 0;
  397. if (insert) {
  398. dao.hotSearchSorting(userCode, code, tableName);
  399. } else {
  400. dao.updateHotSearch(userCode, code, tableName);
  401. }
  402. }
  403. /**
  404. * 根据文档 id 提交病历
  405. *
  406. * @param documentId 文档id
  407. * @return 返回数据
  408. */
  409. public ResultVo<String> submitMedicalRecord(String documentId) {
  410. String userCode = TokenUtil.getInstance().getTokenUserId();
  411. String createdId = dao.getDocumentIdCreatedBy(documentId);
  412. if (userCode.equals(createdId)) {
  413. dao.updateSubmissionFlag(documentId, userCode);
  414. return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "提交成功");
  415. }
  416. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "创建人不一致无法修改。");
  417. }
  418. public ResultVo<String> audit(String documentId) {
  419. String userCode = TokenUtil.getInstance().getTokenUserId();
  420. int count = dao.updateAuditByDocumentId(documentId, userCode);
  421. if (count > 0) {
  422. return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "审核成功");
  423. }
  424. return ResultVoUtil.success(ExceptionEnum.NO_DATA_EXIST, "操作失败,可能原因,已经审核完成或还未保存。");
  425. }
  426. /**
  427. * 获取电子病历数据
  428. *
  429. * @param panNo 住院号
  430. * @param times 住院次数
  431. * @param etType 类型
  432. * @return 返回数据
  433. */
  434. public JSONArray getEmrData(String panNo, Integer times, EmrType etType) {
  435. // 查询这个病历的 唯一 id
  436. List<String> idList = dao.getDocumentIdByPatietn(panNo, times, etType.getName());
  437. JSONArray returnArray = new JSONArray();
  438. if (ListUtil.isBlank(idList)) {
  439. return returnArray;
  440. }
  441. Map<String, JSONObject> surgicalSequencing = new TreeMap<>();
  442. for (String s : idList) {
  443. JSONObject jsonObject = emr.getEditorJsonDataByDocumentId(s);
  444. if (etType.getCode() == EmrType.DIAGNOSIS.getCode()) {
  445. returnArray.addAll(extractDiagnosis(jsonObject));
  446. } else if (etType.getCode() == EmrType.OPERATION.getCode()) {
  447. String key = DateUtil.formatDatetime(jsonObject.getJSONObject("手术日期").getDate("value"));
  448. surgicalSequencing.put(key, jsonObject);
  449. }
  450. }
  451. if (!surgicalSequencing.isEmpty()) {
  452. for (Map.Entry<String, JSONObject> item : surgicalSequencing.entrySet()) {
  453. returnArray.add(item.getValue());
  454. }
  455. }
  456. return returnArray;
  457. }
  458. /**
  459. * 获取患者提取到的数据
  460. *
  461. * @param patNo 住院号
  462. * @param times 次数
  463. * @return 返回 json
  464. */
  465. public JSONObject getEmrPatientData(String patNo, Integer times) {
  466. String js = dao.getEmrPatientData(patNo, times);
  467. if (StringUtil.isBlank(js)) {
  468. return new JSONObject();
  469. }
  470. return JSON.parseObject(js);
  471. }
  472. /**
  473. * 获取患者的手术
  474. *
  475. * @param patNo 获取住院号
  476. * @param times 获取住院次数
  477. * @return 返回数据
  478. */
  479. public JSONArray getPatientSurgery(String patNo, Integer times) {
  480. List<String> idList = dao.getDocumentIdByPatietn(patNo, times, "shoushujilu");
  481. JSONArray returnArray = new JSONArray();
  482. if (ListUtil.isBlank(idList)) {
  483. return returnArray;
  484. }
  485. Map<String, JSONObject> surgicalSequencing = new TreeMap<>();
  486. for (String s : idList) {
  487. JSONObject jsonObject = emr.getEditorJsonDataByDocumentId(s);
  488. JSONObject surgeryDate = jsonObject.getJSONObject("手术日期");
  489. if (null == surgeryDate) {
  490. continue;
  491. }
  492. String key = DateUtil.formatDatetime(surgeryDate.getDate("value"));
  493. if (StringUtil.isBlank(key)) {
  494. continue;
  495. }
  496. surgicalSequencing.put(key, jsonObject);
  497. }
  498. if (!surgicalSequencing.isEmpty()) {
  499. for (Map.Entry<String, JSONObject> item : surgicalSequencing.entrySet()) {
  500. returnArray.add(item.getValue());
  501. }
  502. }
  503. return returnArray;
  504. }
  505. private JSONArray extractDiagnosis(JSONObject jsonObject) {
  506. JSONObject diagnosis = jsonObject.getJSONObject("入院诊断");
  507. if (diagnosis != null) {
  508. JSONArray diagnosisArr = diagnosis.getJSONArray("value");
  509. if (diagnosisArr != null) {
  510. return diagnosisArr;
  511. }
  512. }
  513. return new JSONArray();
  514. }
  515. public ResultVo<String> getDrgIntelligentGrouping(String patNo, Integer times) {
  516. // 获取诊断
  517. JSONArray diagnosis = getEmrData(patNo, times, EmrType.DIAGNOSIS);
  518. // 获取手术
  519. JSONArray operation = getEmrData(patNo, times, EmrType.OPERATION);
  520. int ledgerSn = publicServer.getLedgerSn(patNo, times);
  521. // 获取患者数据
  522. Map<String, String> mapData = dao.drgPatientInfo(patNo, times, ledgerSn);
  523. if (mapData == null) {
  524. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "没有查询到患者信息。");
  525. }
  526. mapData.put("visit_id", patNo + "_" + times + "_" + ledgerSn);
  527. mapData.put("bah", patNo + "_" + times);
  528. for (int i = 0; i < diagnosis.size(); i++) {
  529. JSONObject item = diagnosis.getJSONObject(i);
  530. if (i == 0) {
  531. mapData.put("jbdm", item.getString("code"));
  532. mapData.put("zyzd", item.getString("name"));
  533. } else {
  534. mapData.put("jbdm" + i, item.getString("code"));
  535. }
  536. }
  537. int operationIndex = 1;
  538. for (int i = 0; i < operation.size(); i++) {
  539. JSONObject item = operation.getJSONObject(i);
  540. JSONArray list = null;
  541. try {
  542. list = item.getJSONObject("手术名称").getJSONArray("value");
  543. } catch (Exception e) {
  544. continue;
  545. }
  546. if (list == null) {
  547. continue;
  548. }
  549. for (int a = 0; a < list.size(); a++) {
  550. JSONObject valueList = list.getJSONObject(a);
  551. mapData.put("ssjczbm" + operationIndex, valueList.getString("code"));
  552. if (operationIndex == 1) {
  553. mapData.put("ssjczmc" + operationIndex, valueList.getString("name"));
  554. }
  555. operationIndex++;
  556. }
  557. }
  558. AuxiliaryFillingOfDiagnosis data = EntityCopy.Copy(mapData, AuxiliaryFillingOfDiagnosis.class);
  559. String url = "http://172.16.32.126:8080/drg_web/localHelp/drg_dagns/list.action";
  560. RestTemplate template = new RestTemplate();
  561. String toJsonStr = JSON.toJSONString(data, SerializerFeature.WriteNullStringAsEmpty);
  562. String res = template.postForObject(url, JSON.parseObject(toJsonStr), String.class);
  563. return ResultVoUtil.success("http://172.16.32.126:8080" + res);
  564. }
  565. /**
  566. * 获取患者最大的住院次数
  567. *
  568. * @param patNo 住院号
  569. * @return 返回最大次数
  570. */
  571. public ResultVo<Integer> getDischargeTimes(String patNo) {
  572. Integer times = dao.getMaxTimes(patNo);
  573. if (times == null) {
  574. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "没有查询到患者信息。");
  575. }
  576. return ResultVoUtil.success(times);
  577. }
  578. public ResultVo<JSONObject> getExtractDataElement(String patNo, Integer times) {
  579. Map<String, String> map = dao.selectEmrDataElement(patNo, times);
  580. if (map == null) {
  581. return ResultVoUtil.success();
  582. } else {
  583. return ResultVoUtil.success(JSONObject.parseObject(map.get("data_element")));
  584. }
  585. }
  586. public ResultVo<List<CodeName>> getAllWards() {
  587. return ResultVoUtil.success(loginDao.getAllWards());
  588. }
  589. /**
  590. * 获取患者已经被删除的病历,管理员不需要限制
  591. *
  592. * @param patNo 住院号
  593. * @return 返回
  594. */
  595. public ResultVo<List<EmrPatientData>> getDeleteMedicalRecord(String patNo) {
  596. Integer times = dao.getAdmissTimes(patNo);
  597. if (times == null) {
  598. return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "出院患者无法恢复病历,如果要恢复请先召回在院。");
  599. }
  600. String userCode = TokenUtil.getInstance().getTokenUserId();
  601. if (publicServer.needRule()) {
  602. userCode = "";
  603. }
  604. return ResultVoUtil.success(dao.selectEmrDeteles(patNo, times, userCode));
  605. }
  606. public ResultVo<JSONObject> getInvalidByDocumentId(String id) {
  607. return ResultVoUtil.success(emr.getInvalidByDocumentIdApi(id));
  608. }
  609. /**
  610. * 恢复电子病历
  611. *
  612. * @param documentId 电子病历文档
  613. * @return 返回提示
  614. */
  615. public ResultVo<String> resumeMedicalRecords(String documentId) {
  616. EmrPatientData data = dao.selectemPatientDataOne(documentId);
  617. if (data.getDelFlag() == 0) {
  618. return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "病历已经被恢复了请勿重复点击");
  619. }
  620. Integer times = dao.getAdmissTimes(data.getPatNo());
  621. if (times == null) {
  622. return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "出院患者无法恢复病历,如果要恢复请先召回在院。");
  623. }
  624. JSONObject param = new JSONObject();
  625. param.put("_id", documentId);
  626. param.put("valid", 1);
  627. JSONObject json = emr.resumeMedicalRecords(documentId, param);
  628. if (json.getInteger("ok") == 1) {
  629. dao.updateDeleteFlag(data.getId());
  630. return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "病历恢复成功。");
  631. } else {
  632. return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "病历恢复失败,请重试!");
  633. }
  634. }
  635. /**
  636. * 查询出院患者的申请
  637. *
  638. * @param flag 1 只查询自己的 2 查询审核的
  639. * @return 提示
  640. */
  641. public ResultVo<List<DischargedEmrModifyApply>> getDisReqEmr(Integer flag) {
  642. QueryWrapper<?> qw = new QueryWrapper<>();
  643. if (flag == 1) {
  644. qw.eq("req_id", TokenUtil.getInstance().getTokenUserId());
  645. } else if (flag == 2) {
  646. qw.eq("req_status", 0);
  647. }
  648. qw.ge("edit_date", DateUtil.formatDatetime(new Date(), DateUtil.DATE));
  649. return ResultVoUtil.success(dao.getDisReqEmr(qw));
  650. }
  651. public ResultVo<List<DischargedEmrModifyApply>> downloadTheDischargeEdit(String start, String end) {
  652. return ResultVoUtil.success(dao.selectDisReqEmyDownload(start, end));
  653. }
  654. /**
  655. * 申请出院患者修改
  656. *
  657. * @param param 参数
  658. * @return 提示
  659. */
  660. @Transactional(rollbackFor = Exception.class)
  661. public ResultVo<String> saveDisEmrReq(DischargedEmrModifyApply param) {
  662. param.setReqId(TokenUtil.getInstance().getTokenUserId());
  663. int num = dao.deleteRequest(param.getPatNo());
  664. dao.insertApplicationEmrDis(param);
  665. if (num > 0) {
  666. return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "修改原申请成功。");
  667. } else {
  668. return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "申请成功。");
  669. }
  670. }
  671. /**
  672. * 删除申请
  673. *
  674. * @param patNo 住院号
  675. * @return 提示
  676. */
  677. public ResultVo<String> deleteDisEmrDis(String patNo) {
  678. dao.deleteRequest(patNo);
  679. return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "操作成功。");
  680. }
  681. /**
  682. * 通过申请
  683. *
  684. * @param patNo 住院号
  685. * @return 提示
  686. */
  687. public ResultVo<String> adoptEmrDisReq(String patNo) {
  688. int num = dao.adoptEmrDisReq(patNo, null, 1);
  689. if (num > 0) {
  690. return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
  691. }
  692. return ResultVoUtil.fail(ExceptionEnum.INTERNAL_SERVER_ERROR, "操作失败,原申请可能已经被删除了。");
  693. }
  694. /**
  695. * 拒绝出院患者申请
  696. *
  697. * @param patNo 住院号
  698. * @param reviewNotes 审核信息
  699. * @return 提示
  700. */
  701. public ResultVo<String> refuseEmrDisReq(String patNo, String reviewNotes) {
  702. int num = dao.adoptEmrDisReq(patNo, reviewNotes, 2);
  703. if (num > 0) {
  704. return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
  705. }
  706. return ResultVoUtil.fail(ExceptionEnum.INTERNAL_SERVER_ERROR, "操作失败,原申请可能已经被删除了。");
  707. }
  708. /**
  709. * 查询出院患者是否已经通过了编辑
  710. *
  711. * @param patNo 住院号
  712. * @return Boolean
  713. */
  714. public ResultVo<Boolean> isDisReqEdit(String patNo) {
  715. QueryWrapper<?> qw = new QueryWrapper<>();
  716. qw.eq("pat_no", patNo);
  717. qw.eq("req_status", 1);
  718. qw.ge("edit_date", DateUtil.formatDatetime(new Date(), DateUtil.DATE));
  719. List<DischargedEmrModifyApply> list = dao.getDisReqEmr(qw);
  720. if (ListUtil.isBlank(list)) {
  721. return ResultVoUtil.success(false);
  722. } else {
  723. return ResultVoUtil.success(true);
  724. }
  725. }
  726. public ResultVo<Object> getHistory(String documentId) {
  727. return ResultVoUtil.success(emr.getHistory(documentId));
  728. }
  729. public ResultVo<List<MedicalHistoryPrompts>> getEmrTips() {
  730. return ResultVoUtil.success(dao.selectEmrTips(TokenUtil.getInstance().getTokenUserId()));
  731. }
  732. public ResultVo<String> addEmrTips(MedicalHistoryPrompts param) {
  733. UserInfo userInfo = redisLikeService.getUserInfoByToken();
  734. param.setDept(userInfo.getDeptCode());
  735. param.setCreatorId(userInfo.getCode());
  736. dao.insertEmrTips(param);
  737. return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
  738. }
  739. public ResultVo<String> updateEmrTips(MedicalHistoryPrompts param) {
  740. if (param.getId() == null) {
  741. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "id 为空无法更新。");
  742. }
  743. dao.updateEmrTips(param);
  744. return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
  745. }
  746. public ResultVo<String> deleteEmrTips(Integer id) {
  747. dao.delEmrTips(id);
  748. return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
  749. }
  750. /**
  751. * 在病程记录中获取文本数据
  752. *
  753. * @param name 名称
  754. * @return 返回数据
  755. */
  756. public ResultVo<List<MedicalHistoryPrompts>> getEmrTipsData(String name, int typeCode) {
  757. QueryWrapper<?> qw = new QueryWrapper<>();
  758. UserInfo us = redisLikeService.getUserInfoByToken();
  759. if (typeCode == 1) {
  760. qw.eq("creator_id", us.getCode());
  761. } else if (typeCode == 2) {
  762. qw.eq("dept", us.getDeptCode());
  763. }
  764. qw.like("query_key", name)
  765. .eq("type_code", typeCode)
  766. .orderByDesc("count");
  767. return ResultVoUtil.success(dao.getEmrTipsData(qw));
  768. }
  769. public ResultVo<List<ZyPatientInfo>> getListOfDischargedPatients(String patNo) {
  770. List<ZyPatientInfo> list = dao.getListOfDischargedPatients(patNo);
  771. if (ListUtil.isBlank(list)) {
  772. return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "没有" + patNo + "的出院记录。");
  773. }
  774. return ResultVoUtil.success(list);
  775. }
  776. public ResultVo<JSONObject> getYzTemperature(YzTemperatureParam param) {
  777. JSONObject js = new JSONObject();
  778. QueryWrapper<?> qw = new QueryWrapper<>();
  779. qw.eq("inpatient_no", param.getPatNo())
  780. .eq("admiss_times", param.getTimes())
  781. .ge("CONVERT(varchar(10), rec_date, 23)", param.getStartTime())
  782. .le("CONVERT(varchar(10), rec_date, 23)", param.getEndTime());
  783. List<YzTemperature> list = dao.getYzTemperature(qw);
  784. if (ListUtil.isBlank(list)) {
  785. return ResultVoUtil.success(js);
  786. }
  787. Map<Date, YzTemperature> map = new LinkedHashMap<>(list.size());
  788. for (YzTemperature item : list) {
  789. Date key = item.getTempDate();
  790. if (map.containsKey(key)) {
  791. YzTemperature yz = map.get(key);
  792. yz.setOtherInfo(nullToEmpty(yz.getOtherInfo()) + nullToEmpty(item.getOtherInfo()));
  793. } else {
  794. map.put(key, item);
  795. }
  796. }
  797. js.put("list", list);
  798. js.put("map", map);
  799. return ResultVoUtil.success(js);
  800. }
  801. public ResultVo<List<YshYjReq>> getExamine(String patNo, Integer times) {
  802. return ResultVoUtil.success(dao.getExamine(patNo, times));
  803. }
  804. private String nullToEmpty(String str) {
  805. if (StringUtil.isBlank(str)) {
  806. return "";
  807. }
  808. return str;
  809. }
  810. public ResultVo<ZyZkList> whetherItExistsInTheDepartment(String patNo, Integer times) {
  811. ZyZkList zk = dao.getMaxTransferDateByPatNo(patNo, times);
  812. if (zk != null) {
  813. zk.setTimeout(DateUtil.moreThanHours(zk.getOpTime(), 48));
  814. }
  815. return ResultVoUtil.success(zk);
  816. }
  817. public ResultVo<String> emrSocketUnlock(String sid, String documentId) {
  818. ApiMessageBody messageBody = new ApiMessageBody();
  819. messageBody.setSid(sid);
  820. messageBody.setDocumentId(documentId);
  821. messageBody.setUserCode(TokenUtil.getInstance().getTokenUserId());
  822. return socketService.emrSocketUnlock(messageBody);
  823. }
  824. public ResultVo<String> electronicMedicalRecordSequencing(List<EmrPatientData> data) {
  825. if (ListUtil.isBlank(data)) {
  826. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "请选择有效的分类数据。");
  827. }
  828. ListUtil.batchList(data, EmrPatientDao.class, (m, item) -> {
  829. m.updateTheNode(item.getParent(), item.getId());
  830. });
  831. return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "操作成功。");
  832. }
  833. public ResultVo<Map<String, List<EmrPatientData>>> getPastHistory(String patNo, Integer times) {
  834. List<EmrPatientData> list = dao.getHisPatInfo(patNo, times);
  835. if (ListUtil.isBlank(list)) {
  836. return ResultVoUtil.success(new HashMap<>());
  837. }
  838. Map<String, List<EmrPatientData>> grouping = list.stream().collect(
  839. Collectors.groupingBy(item -> item.getTimes().toString())
  840. );
  841. return ResultVoUtil.success(grouping);
  842. }
  843. public ResultVo<Map<Integer, List<MzEmrPatientData>>> getMzPatientDataByPatNo(String patNo) {
  844. String mzNo = dao.getMzNoByPatNo(patNo);
  845. Map<Integer, List<MzEmrPatientData>> map1 = new HashMap<>();
  846. if (StringUtil.isBlank(mzNo)) {
  847. return ResultVoUtil.success(map1);
  848. }
  849. List<MzEmrPatientData> mzList = dao.getEmrPatientMz(mzNo);
  850. if (ListUtil.isBlank(mzList)) {
  851. return ResultVoUtil.success(map1);
  852. }
  853. Map<Integer, List<MzEmrPatientData>> map = mzList.stream().collect(
  854. Collectors.groupingBy(MzEmrPatientData::getTimes)
  855. );
  856. return ResultVoUtil.success(map);
  857. }
  858. public ResultVo<List<FluorescenceSpecimenResult>> getFluorescenceSpecimenResult(String patNo, Integer times) {
  859. return ResultVoUtil.success(dao.selectFluorescenceSpecimenResult(patNo, times));
  860. }
  861. public ResultVo<List<OpRecord>> getOpRecordList(String patNo, Integer times) {
  862. return ResultVoUtil.success(dao.getOpRecordList(patNo, times));
  863. }
  864. public String getEmrToken() {
  865. return emrToken;
  866. }
  867. private static String createEmr(JSONObject param) {
  868. String url = "http://webhis.thyy.cn:8080/thyyemrpdfserver/emr/archive/pdf";
  869. String text = Forest.post(url)
  870. .contentTypeJson()
  871. .addBody(param)
  872. .bodyType(ForestDataType.JSON)
  873. .addHeader("emr-token", emrToken)
  874. .execute(String.class);
  875. int index = text.lastIndexOf("<br/>buffer:,");
  876. if (index != -1) {
  877. String[] split = text.substring(text.lastIndexOf("<br/>buffer:,") + 13).split(",");
  878. return Base64.encode(Convert.toPrimitiveByteArray(split));
  879. }
  880. throw new RuntimeException(text);
  881. }
  882. public static String getPdfBase(String documentId) {
  883. JSONObject param = new JSONObject();
  884. param.put("emrToken", true);
  885. param.put("stream", true);
  886. param.put("arcive", false);
  887. param.put("patientId", false);
  888. param.put("params", new JSONObject() {{
  889. put("documentId", documentId);
  890. }});
  891. param.put("fileName", "病历pdf");
  892. param.put("type", "document");
  893. return createEmr(param);
  894. }
  895. public static String getPdfBase64ByTemplate(cn.hutool.json.JSONObject template, Object data) {
  896. JSONObject param = new JSONObject();
  897. param.put("emrToken", true);
  898. param.put("stream", true);
  899. param.put("arcive", false);
  900. param.put("patientId", false);
  901. param.put("params", new JSONObject() {{
  902. put("document", template);
  903. put("appContext", data);
  904. }});
  905. param.put("fileName", "病历pdf");
  906. param.put("type", "template");
  907. return createEmr(param);
  908. }
  909. public static String getPdfBase64ByCategoryId(String id, String categoryCode, Object data) {
  910. JSONObject param = new JSONObject();
  911. param.put("emrToken", true);
  912. param.put("stream", true);
  913. param.put("arcive", false);
  914. param.put("patientId", false);
  915. param.put("params", new JSONObject() {{
  916. put("categoryId", id);
  917. put("categoryCode", categoryCode);
  918. put("appContext", new JSONObject() {{
  919. put("data", data);
  920. }});
  921. }});
  922. param.put("fileName", "病历pdf");
  923. param.put("type", "template");
  924. return createEmr(param);
  925. }
  926. public ResultVo<String> newDir(EmrPatientData data) {
  927. data.setEmrDocumentId(SnowFlakeId.instance().nextId());
  928. data.setCreateDate(new Date());
  929. data.setCreateId(TokenUtil.getInstance().getTokenUserId());
  930. data.setEmrCategoryCode(THIS_IS_DIR);
  931. if (data.getParent() == null) {
  932. return ResultVoUtil.success(ExceptionEnum.LOGICAL_ERROR, "父节点为空请重新创建!");
  933. }
  934. dao.insert(data);
  935. return ResultVoUtil.success();
  936. }
  937. public ResultVo<String> delDir(String dirId) {
  938. boolean dirHasFile = dao.dirHasFile(dirId);
  939. if (dirHasFile) {
  940. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "文件夹下面还存在文件无法删除。");
  941. }
  942. int i = dao.delDir(dirId, TokenUtil.getInstance().getTokenUserId());
  943. if (i > 0) {
  944. return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
  945. }
  946. return ResultVoUtil.success(ExceptionEnum.LOGICAL_ERROR, "无法删除,创建人不是你,或者这个是文件。");
  947. }
  948. public ResultVo<String> rename(String name, String documentId) {
  949. int i = dao.rename(name, documentId);
  950. if (i > 0) {
  951. return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
  952. }
  953. return ResultVoUtil.success(ExceptionEnum.LOGICAL_ERROR, "重命名失败。");
  954. }
  955. public static void main(String[] args) {
  956. System.out.println(IdUtil.fastSimpleUUID());
  957. System.out.println(IdUtil.fastSimpleUUID());
  958. }
  959. }