LocalBusPatientService.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. package com.coffee.bus.service;
  2. import cn.hutool.core.collection.CollectionUtil;
  3. import cn.hutool.core.date.DateUtil;
  4. import cn.hutool.core.date.LocalDateTimeUtil;
  5. import cn.hutool.json.JSONObject;
  6. import cn.hutool.json.JSONUtil;
  7. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  8. import cn.hutool.core.util.StrUtil;
  9. import com.baomidou.mybatisplus.core.metadata.IPage;
  10. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  11. import com.coffee.bus.entity.BusClinicEntity;
  12. import com.coffee.bus.entity.BusPatientEntity;
  13. import com.coffee.bus.entity.PatientDeviceRepeatDomain;
  14. import com.coffee.bus.enums.DeviceAlarmEnum;
  15. import com.coffee.bus.enums.DeviceStatusEnum;
  16. import com.coffee.bus.service.dto.*;
  17. import com.coffee.bus.mapper.BusPatientMapper;
  18. import com.coffee.bus.registry.patient.PatientOperator;
  19. import com.coffee.bus.registry.patient.PatientRegistry;
  20. import com.coffee.bus.registry.patient.bean.PatientCacheInfo;
  21. import com.coffee.bus.utils.WsPublishUtils;
  22. import com.coffee.common.config.websocket.WebSocketConstant;
  23. import com.coffee.common.crud.BaseService;
  24. import com.coffee.common.enums.SexEnum;
  25. import lombok.extern.slf4j.Slf4j;
  26. import org.springframework.beans.factory.annotation.Autowired;
  27. import org.springframework.context.annotation.Lazy;
  28. import org.springframework.scheduling.annotation.Async;
  29. import org.springframework.stereotype.Service;
  30. import org.springframework.transaction.annotation.Transactional;
  31. import java.time.LocalDateTime;
  32. import java.util.*;
  33. import java.util.concurrent.CompletableFuture;
  34. import java.util.concurrent.Executors;
  35. import java.util.concurrent.ScheduledExecutorService;
  36. import java.util.concurrent.TimeUnit;
  37. /**
  38. * @author lifang
  39. * @version 1.0.0
  40. * @ClassName LocalBusHospitalService.java
  41. * @Description TODO
  42. * @createTime 2022年03月19日 09:27:00
  43. */
  44. @Service
  45. @Slf4j
  46. public class LocalBusPatientService extends BaseService<BusPatientMapper, BusPatientEntity,String> {
  47. @Autowired
  48. @Lazy
  49. private LocalBusClinicService clinicService;
  50. @Autowired
  51. @Lazy
  52. private PatientRegistry patientRegistry;
  53. @Autowired
  54. private WsPublishUtils wsPublishUtils;
  55. private ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
  56. @Autowired
  57. @Lazy
  58. private LocalBusPatientService patientService;
  59. @Override
  60. public void validateBeforeSave(BusPatientEntity entity) {
  61. if(entity.getGender()==null){
  62. entity.setGender(SexEnum.UNKNOW);
  63. }
  64. }
  65. @Override
  66. public void validateBeforeUpdate(BusPatientEntity entity) {
  67. }
  68. @Override
  69. public void validateBeforeDelete(String id) {
  70. }
  71. @Override
  72. public void postSave(BusPatientEntity entity) {
  73. super.postSave(entity);
  74. //新增病人后推送主题,延迟推送,保证处理逻辑已全部完成
  75. executorService.schedule(()->{
  76. wsPublishUtils.publish(WebSocketConstant.getPatientAdd(entity.getTenantId()).getTopic(),
  77. new JSONObject().putOpt("patientCode",entity.getCode()));
  78. }
  79. ,3, TimeUnit.SECONDS);
  80. }
  81. /**
  82. * 异步获取病人信息 todo
  83. * @param hospitalId 医院id
  84. * @param patientCode 病号
  85. */
  86. @Async
  87. public void syncGetPatientInfoFromHis(String hospitalId,String patientCode){
  88. }
  89. /**
  90. * 获取给定医院下所有的挂载多个设备的病人信息
  91. *
  92. */
  93. public List<PatientDeviceRepeatResult> repeatDevice() {
  94. List<PatientDeviceRepeatDomain> patientDeviceRepeats = this.baseMapper.selectRepeatDevice();
  95. Map<String, PatientDeviceRepeatResult> resultMap = new HashMap<>();
  96. patientDeviceRepeats.forEach(deviceRepeat->{
  97. PatientDeviceRepeatResult repeatResult = resultMap.computeIfAbsent(deviceRepeat.getCode(),k->
  98. PatientDeviceRepeatResult.of(
  99. deviceRepeat.getName(),
  100. deviceRepeat.getGender(),
  101. deviceRepeat.getCode(),
  102. deviceRepeat.getAge(),
  103. deviceRepeat.getWard(),
  104. deviceRepeat.getBedNo(),
  105. deviceRepeat.getClinicName(),
  106. new ArrayList<>())
  107. );
  108. List<PatientDeviceRepeatResult.DeviceRunningSmallInfo> deviceRunningSmallInfos = Optional.ofNullable(repeatResult.getDevices()).orElse(new ArrayList<>());
  109. deviceRunningSmallInfos.add(PatientDeviceRepeatResult.DeviceRunningSmallInfo.of(
  110. deviceRepeat.getDeviceRunningId(),
  111. deviceRepeat.getDeviceId(),
  112. deviceRepeat.getDeviceAlias(),
  113. deviceRepeat.getDeviceRunState(),
  114. deviceRepeat.getDeviceAlarm(),
  115. deviceRepeat.getInfusionStartTime(),
  116. deviceRepeat.getMaster()
  117. ));
  118. repeatResult.setDevices(deviceRunningSmallInfos);
  119. });
  120. return new ArrayList<>(resultMap.values());
  121. }
  122. /**
  123. * 获取无设备绑定的临床手术信息
  124. * @return
  125. */
  126. public List<PatientDeviceNoneResult> noneDevice() {
  127. return this.baseMapper.selectNoneDevice();
  128. }
  129. public List<PatientMonitorResult> selectAll(PatientMonitorQuery query) {
  130. Page<PatientMonitorResult> page = new Page<>(0, 500, false);
  131. IPage<PatientMonitorResult> result = this.baseMapper.selectMonitor(page,query);
  132. if(CollectionUtil.isNotEmpty(result.getRecords())){
  133. result.getRecords().forEach(PatientMonitorResult::handleWarn);
  134. }
  135. return result.getRecords();
  136. }
  137. /**
  138. * 根据医院和住院号获取一个患者
  139. * @param tenantId
  140. * @param patientCode
  141. * @return
  142. */
  143. public BusPatientEntity getOneByHospitalAndPatientCode(String tenantId, String patientCode) {
  144. BusPatientEntity patient = this.getOne(new QueryWrapper<BusPatientEntity>().lambda()
  145. .eq(BusPatientEntity::getTenantId,tenantId)
  146. .eq(BusPatientEntity::getCode,patientCode));
  147. // 如果患者不存在则新增一个患者
  148. if (Objects.isNull(patient)){
  149. patient = new BusPatientEntity();
  150. patient.setTenantId(tenantId);
  151. patient.setCode(patientCode);
  152. this.save(patient);
  153. }
  154. return patient;
  155. }
  156. /**
  157. *
  158. * 病人手动更新当前监控的临床信息 todo
  159. * @param clinic
  160. */
  161. @Transactional(rollbackFor = Exception.class)
  162. public void manualEdit(BusClinicEntity clinic) {
  163. //先更新手术信息 todo
  164. clinicService.saveOrUpdate(clinic);
  165. //后更新病人信息
  166. BusPatientEntity patient = BusPatientEntity.of(clinic);
  167. PatientOperator<PatientCacheInfo> patientOperator = patientRegistry.getOperator(patient.getTenantId(), patient.getCode());
  168. if (StrUtil.isEmpty(patientOperator.getCode())) {
  169. this.save(patient);
  170. patientOperator.setCode(patient.getCode());
  171. patientOperator.setTenantId(patient.getTenantId());
  172. }else {
  173. BusPatientEntity existPatient = this.getOne(new QueryWrapper<BusPatientEntity>().lambda().eq(BusPatientEntity::getCode, patient.getCode()).last("limit 1"));
  174. patient.setId(existPatient.getId());
  175. this.updateById(patient);
  176. }
  177. patientOperator.setClinicId(patient.getClinicId());
  178. patientOperator.setName(patient.getName());
  179. patientOperator.setBedNo(clinic.getBedNo());
  180. patientOperator.setWard(clinic.getWard());
  181. CompletableFuture.runAsync(()->{
  182. wsPublishUtils.publish(WebSocketConstant.getPatientMonitor(null,patient.getCode(), patient.getTenantId()).getTopic(),
  183. patientService.lookMonitorByPatientCode(patient.getCode(),patient.getTenantId()));
  184. });
  185. }
  186. /**
  187. * 根据病号查询临床监控记录
  188. * @author lifang
  189. * @param patientCode 病号
  190. * @param tenantId 医院id
  191. * @return
  192. */
  193. public PatientMonitorResult lookMonitorByPatientCode(String patientCode,String tenantId) {
  194. try {
  195. return this.baseMapper.findByPatientCode(tenantId, patientCode);
  196. } catch (Exception e) {
  197. log.error("根据病号查询临床失败,",e.getMessage());
  198. return null;
  199. }
  200. }
  201. /**
  202. * 描述: 设备状态数量统计
  203. * @author lifang
  204. * @date 2022/5/8 21:52
  205. * @param tenantId 医院id 用户请求时传输null
  206. * @return MonitorStatusStatsCountResult
  207. */
  208. public MonitorStatusStatsCountResult statusStats(String tenantId) {
  209. PatientMonitorQuery query = new PatientMonitorQuery();
  210. query.setTenantId(tenantId);
  211. List<PatientMonitorResult> patientMonitorResults = this.selectAll(query);
  212. MonitorStatusStatsCountResult result = new MonitorStatusStatsCountResult();
  213. if(CollectionUtil.isNotEmpty(patientMonitorResults)){
  214. patientMonitorResults.forEach(monitor->{
  215. //运行数量
  216. if(DeviceStatusEnum.Running.equals(monitor.getDeviceRunState())){
  217. result.setRunningCount(result.getRunningCount()+1);
  218. }
  219. //todo 待结束数量
  220. //报警数量
  221. if(monitor.getDeviceAlarm()!=null&&!monitor.getDeviceAlarm().equals(DeviceAlarmEnum.None)){
  222. result.setAlarmCount(result.getAlarmCount()+1);
  223. }
  224. //提醒数量
  225. if(Boolean.TRUE.equals(monitor.getWarnAnalgesicPoor())
  226. ||Boolean.TRUE.equals(monitor.getWarnLowBattery())
  227. ||Boolean.TRUE.equals(monitor.getWarnWillFinished())
  228. ||monitor.getWarnFlow()!=null){
  229. result.setWarnCount(result.getWarnCount()+1);
  230. }
  231. });
  232. }
  233. return result;
  234. }
  235. /**
  236. * 描述: 按照时间对输注监控进行统计
  237. * @author lifang
  238. * @date 2022/5/8 22:40
  239. * @param tenantId 医院id
  240. * @return MonitorTimeStatsCountResult
  241. */
  242. public MonitorTimeStatsCountResult timeStats(String tenantId) {
  243. PatientMonitorQuery query = new PatientMonitorQuery();
  244. query.setTenantId(tenantId);
  245. List<PatientMonitorResult> patientMonitorResults = this.selectAll(query);
  246. MonitorTimeStatsCountResult result = new MonitorTimeStatsCountResult();
  247. patientMonitorResults.forEach(monitor->{
  248. Date startTime = monitor.getMonitorStartTime();
  249. if(startTime==null){
  250. return;
  251. }
  252. if (includeTimes(startTime, 0)) {
  253. result.setToday(result.getToday()+1);
  254. return;
  255. }
  256. if (includeTimes(startTime, 1)) {
  257. result.setOneDay(result.getOneDay()+1);
  258. return;
  259. }
  260. if (includeTimes(startTime, 2)) {
  261. result.setTwoDay(result.getTwoDay()+1);
  262. return;
  263. }
  264. if (includeTimes(startTime, 3)) {
  265. result.setThreeDay(result.getThreeDay()+1);
  266. return;
  267. }
  268. result.setBeyondThreeDay(result.getBeyondThreeDay()+1);
  269. });
  270. return result;
  271. }
  272. /**
  273. * 描述: 判断所给时间是否在存在于某一时间段内
  274. * @author lifang
  275. * @date 2022/5/8 22:47
  276. * @param time 时间
  277. * @param offset 时间偏移量,单位:天 以当天时间为基准进行偏移
  278. * @return boolean
  279. */
  280. private boolean includeTimes(Date time,int offset){
  281. if(time==null){
  282. return false;
  283. }
  284. LocalDateTime dateTime = LocalDateTime.now().plusDays(offset);
  285. LocalDateTime beginTime = LocalDateTimeUtil.beginOfDay(dateTime);
  286. LocalDateTime endTime = LocalDateTimeUtil.endOfDay(dateTime);
  287. return beginTime.getSecond()<time.getSeconds()
  288. && time.getSeconds()<endTime.getSecond();
  289. }
  290. }