BusPatientController.java 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. package com.nb.bus.controller;
  2. import cn.dev33.satoken.SaManager;
  3. import cn.dev33.satoken.annotation.SaCheckPermission;
  4. import cn.dev33.satoken.stp.StpLogic;
  5. import cn.hutool.core.collection.CollUtil;
  6. import cn.hutool.core.text.CharSequenceUtil;
  7. import cn.hutool.core.util.StrUtil;
  8. import cn.hutool.json.JSONUtil;
  9. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  10. import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
  11. import com.baomidou.mybatisplus.core.mapper.Mapper;
  12. import com.nb.bus.controller.vo.GetPatientInfoVo;
  13. import com.nb.bus.controller.vo.MonitorDetailVo;
  14. import com.nb.bus.controller.vo.MonitorFinishedVo;
  15. import com.nb.bus.entity.*;
  16. import com.nb.bus.enums.DeviceStatusEnum;
  17. import com.nb.bus.enums.PatientAlarmEnum;
  18. import com.nb.bus.registry.patient.PatientOperator;
  19. import com.nb.bus.registry.patient.PatientRegistry;
  20. import com.nb.bus.service.*;
  21. import com.nb.bus.service.dto.*;
  22. import com.nb.bus.utils.WsPublishUtils;
  23. import com.nb.common.annotation.Log;
  24. import com.nb.common.crud.BaseService;
  25. import com.nb.common.crud.controller.BaseQueryController;
  26. import com.nb.common.exception.CustomException;
  27. import com.nb.common.result.R;
  28. import io.swagger.annotations.*;
  29. import lombok.AllArgsConstructor;
  30. import lombok.extern.slf4j.Slf4j;
  31. import org.springframework.validation.annotation.Validated;
  32. import org.springframework.web.bind.annotation.*;
  33. import org.springframework.web.context.request.async.DeferredResult;
  34. import java.util.*;
  35. import java.util.concurrent.CompletableFuture;
  36. import java.util.stream.Collectors;
  37. /**
  38. * @author lifang
  39. * @version 1.0.0
  40. * @ClassName BusHospitalController.java
  41. * @Description TODO
  42. * @createTime 2022年03月19日 09:28:00
  43. */
  44. @RestController
  45. @AllArgsConstructor
  46. @RequestMapping("/bus/patient")
  47. @Slf4j
  48. @Api(tags = "医院病人管理",description = "关于病人的相关操作,查询操作权限【bus:patient:query】")
  49. public class BusPatientController implements BaseQueryController<BusPatientEntity,String> {
  50. private final LocalBusPatientService patientService;
  51. private final LocalBusClinicService clinicService;
  52. private final PatientRegistry patientRegistry;
  53. private final LocalBusInfusionHistoryService infusionService;
  54. private final LocalBusDeviceManualService manualService;
  55. private final WsPublishUtils wsPublishUtils;
  56. @PostMapping("/no_page")
  57. @SaCheckPermission("device:patient:query")
  58. @ApiOperation(value = "输注监控列表",notes = "病人监控管理列表,权限【device:patient:query】")
  59. public R<List<PatientMonitorResult>> selectPage(@RequestBody PatientMonitorQuery query){
  60. log.info("输注监控列表,【{}】",JSONUtil.toJsonStr(query));
  61. return R.success(patientService.selectAll(query));
  62. }
  63. @Log(title = "查询该次临床过程中所用的所有输注信息")
  64. @PostMapping("/look/{clinicId}/infusion")
  65. @SaCheckPermission("bus:patient:query")
  66. @ApiOperation(value = "查询该次临床过程中所用的所有输注信息",notes = "查询该次临床过程中所用的所有输注信息,权限【bus:patient:query】")
  67. public R lookUpAllInfusion(@PathVariable("clinicId") String clinicId){
  68. List<BusInfusionHistoryEntity> infusionHistories = infusionService.list(new QueryWrapper<BusInfusionHistoryEntity>().lambda().eq(BusInfusionHistoryEntity::getClinicId, clinicId));
  69. return R.success(infusionHistories.stream()
  70. .map(InfusionHistorySmallResult::of)
  71. .sorted(Comparator.comparing(InfusionHistorySmallResult::getStartTime))
  72. .collect(Collectors.toList()));
  73. }
  74. @GetMapping("/repeat/device")
  75. @ApiOperation(value = "设备重复提示列表",notes = "当出现病患同一时间绑定了多个泵时,调用该接口查询出所有设备重复报警数据,权限【无】")
  76. public R<List<PatientDeviceRepeatResult>> repeatDevice(){
  77. log.info("设备重复提示列表");
  78. return R.success(patientService.repeatDevice());
  79. }
  80. @GetMapping("/none/device")
  81. @ApiOperation(value = "临床无泵列表",notes = "当出现病患同一时间没有泵时,调用该接口查询出所有没有泵信息的病患临床数据,权限【无】")
  82. public R<List<PatientDeviceNoneResult>> noneDevice(){
  83. log.info("设备重复提示列表");
  84. return R.success(patientService.noneDevice());
  85. }
  86. @PostMapping("/judge/repeat")
  87. @ApiOperation(value = "判断所给病号中是否出现了绑定设备重复",notes = "当结束管理时,调用改接口判断所结束病号是否出现了设备重复异常,权限【无】")
  88. @ApiResponses({
  89. @ApiResponse(code = 200,message = "0 病人中未出现重复,非0 病人中出现重复"),
  90. })
  91. public R<Long> judgeRepeat(@RequestBody List<String> patientIds){
  92. log.info("判断所给病号中是否出现了绑定设备重复,【{}】",patientIds);
  93. return R.success(patientService.count(new QueryWrapper<BusPatientEntity>().lambda().in(BusPatientEntity::getId,patientIds).eq(BusPatientEntity::getAlarm,PatientAlarmEnum.DEVICE_REPEAT)));
  94. }
  95. @PostMapping("/judge/finished")
  96. @ApiOperation(value = "判断给定病号中是否可以结束临床管理",notes = "病患当前绑定主设备必须要在关机、不在服务器、待机中才能结束管理,权限【无】")
  97. @ApiResponses({
  98. @ApiResponse(code = 500,message = "没有选择病号"),
  99. @ApiResponse(code =200 ,message = "若存在不可以结束的临床信息,返回1",response = BusDeviceRunningEntity.class)
  100. })
  101. public R<Boolean> judgeFinished(@RequestBody List<String> patientIds){
  102. log.info("判断给定病号中是否可以结束临床管理,【{}】",patientIds);
  103. if(CollUtil.isEmpty(patientIds)){
  104. throw new CustomException("请选择一个病患");
  105. }
  106. List<BusPatientEntity> patients = patientService.list(new QueryWrapper<BusPatientEntity>()
  107. .lambda().in(BusPatientEntity::getId, patientIds));
  108. if(CollUtil.isEmpty(patients)){
  109. throw new CustomException("病号不存在,请刷新后重试");
  110. }
  111. return R.success(infusionService.count(new QueryWrapper<BusInfusionHistoryEntity>()
  112. .lambda()
  113. .nested(i->i.ne(BusInfusionHistoryEntity::getRunState,DeviceStatusEnum.Shutdown)
  114. .ne(BusInfusionHistoryEntity::getRunState,DeviceStatusEnum.NoSignal))
  115. .in(BusInfusionHistoryEntity::getPatientId,patients.stream().map(BusPatientEntity::getId).collect(Collectors.toList()))
  116. .eq(BusInfusionHistoryEntity::getFinished,false))!=0);
  117. }
  118. @PostMapping("/do/{monitorType}/finished")
  119. @SaCheckPermission("bus:patient:finished")
  120. @ApiResponse(code = 4001,message = "病号当前绑定了多个设备,不可结束管理")
  121. @ApiOperation(value = "结束管理",notes = "病患当前绑定主设备必须要在关机、不在服务器、待机中才能结束管理,权限【bus:patient:finished】")
  122. public R<Boolean> finished(@PathVariable("monitorType")@ApiParam(value = "是否为无泵管理 false、无泵 true、有泵",defaultValue = "false" ) boolean haveDevice,
  123. @RequestBody MonitorFinishedVo monitorFinishedVo,
  124. @RequestAttribute("tenantId")@ApiParam(hidden = true) String tenantId){
  125. log.info("结束管理,【{}】",JSONUtil.toJsonStr(monitorFinishedVo));
  126. if(haveDevice){
  127. R<Boolean> result = monitorFinished(monitorFinishedVo, tenantId);
  128. CompletableFuture.runAsync(()->wsPublishUtils.publishMonitorTotalCount(tenantId))
  129. .thenRunAsync(()->wsPublishUtils.publishDeviceNone(tenantId))
  130. .thenRunAsync(()->wsPublishUtils.publishMonitorStateCount(tenantId));
  131. return result;
  132. }else {
  133. return manualFinished(monitorFinishedVo);
  134. }
  135. }
  136. /**
  137. * 描述: 输注监控结束管理(即使用驼人网络泵产品)
  138. * @author lifang
  139. * @date 2022/5/10 11:48
  140. * @param monitorFinishedVo
  141. * @param tenantId
  142. * @return R
  143. */
  144. private R<Boolean> monitorFinished(MonitorFinishedVo monitorFinishedVo, String tenantId){
  145. List<String> patientIds = monitorFinishedVo.getPatientIds();
  146. if(CollUtil.isEmpty(patientIds)){
  147. List<String> clinicIds = monitorFinishedVo.getClinicIds();
  148. if (CollUtil.isEmpty(clinicIds)) {
  149. throw new CustomException("未选择临床信息");
  150. }
  151. }
  152. List<BusPatientEntity> patients = patientService.list(new QueryWrapper<BusPatientEntity>().lambda().in(BusPatientEntity::getId, patientIds));
  153. List<ManualUndoConfig> undoConfigs=new ArrayList<>();
  154. for (BusPatientEntity patient : patients) {
  155. undoConfigs.add(
  156. ManualUndoConfig.of(
  157. Collections.singletonList(patient.getInfusionId()),
  158. patient.getId(),
  159. patient.getClinicId(),
  160. tenantId,
  161. true,
  162. monitorFinishedVo.getUndo())
  163. );
  164. }
  165. //病患绑定的有设备,对设备进行撤泵操作,且结束临床
  166. infusionService.batchUndo(undoConfigs,true);
  167. return R.success(true);
  168. }
  169. /**
  170. * 描述: 其他监控手动结束管理(即未采用驼人网络泵产品)
  171. * @author lifang
  172. * @date 2022/5/10 11:49
  173. * @param monitorFinishedVo
  174. * @return R
  175. */
  176. private R<Boolean> manualFinished(MonitorFinishedVo monitorFinishedVo){
  177. List<String> clinicIds = monitorFinishedVo.getClinicIds();
  178. if (CollUtil.isEmpty(clinicIds)) {
  179. throw new CustomException("未选择临床信息");
  180. }
  181. manualService.finishedMonitor(monitorFinishedVo);
  182. return R.success(true);
  183. }
  184. @PostMapping("/monitor/reset/{clinicId}")
  185. @SaCheckPermission("device:patient:edit")
  186. @ApiOperation(value = "病人当前监控时间重启",notes = "当结束临床后有新的输注信息产生,那么病人监控会重新显示,此时监控时间不会重新计算,需先调用该接口,权限标识为【device:patient:edit】")
  187. public R<Boolean> reset(@ApiParam("临床id")@PathVariable("clinicId")String clinicId){
  188. log.info("病人当前监控时间重启,【{}】",clinicId);
  189. R<Boolean> result = R.success(clinicService.update(new UpdateWrapper<BusClinicEntity>().lambda().eq(BusClinicEntity::getId, clinicId)
  190. .set(BusClinicEntity::getEndTime, null)));
  191. BusClinicEntity clinic = clinicService.getById(clinicId);
  192. wsPublishUtils.publishPatientMonitor(clinic.getPatientId(),clinic.getTenantId());
  193. return result;
  194. }
  195. @PostMapping("/{alarm}/_count")
  196. @SaCheckPermission("device:patient:query")
  197. @ApiOperation(value = "病人报警数量统计",notes = "病人报警数量统计 0、未报警 1、泵重复 2、无泵,权限标识为【device:patient:query】")
  198. public R<Integer> alarmCount(@PathVariable("alarm") int alarm){
  199. PatientAlarmEnum alarmEnum = PatientAlarmEnum.of(alarm);
  200. if(alarmEnum==null){
  201. return R.success(0);
  202. }
  203. log.info("病人报警数量统计,【{}】",alarmEnum);
  204. switch (alarmEnum){
  205. case DEVICE_REPEAT:
  206. return this.noneCount();
  207. case NONE:
  208. return this.repeatCount();
  209. default:return R.success(0);
  210. }
  211. }
  212. @PostMapping("/shift")
  213. @SaCheckPermission("device:patient:shift")
  214. @ApiOperation(value = "主泵切换的操作,只切换,不结束",notes = "当出现泵重复状态时,若用户想要进行主泵的切换,调用该接口进行操作,主泵切换完成后,会将副泵自动撤泵,权限标识为【device:patient:shift】")
  215. public R shift(@RequestBody@Validated DeviceShiftConfig shiftConfig){
  216. log.info("主泵切换的操作,【{}】",JSONUtil.toJsonStr(shiftConfig));
  217. patientService.shift(shiftConfig);
  218. wsPublishUtils.publishPatientMonitor(shiftConfig.getPatientId(),shiftConfig.getTenantId());
  219. return R.success();
  220. }
  221. @PostMapping("/undo")
  222. @SaCheckPermission("device:patient:undo")
  223. @ApiOperation(value = "批量撤泵,只撤泵,不切换",notes = "当出现泵重复状态时,若用户想要取消对其他副泵的监控,则调用此接口进行撤泵操作,权限标识为【device:patient:undo】")
  224. public R shift(@RequestBody@Validated ManualUndoConfig undoConfig, @RequestAttribute("tenantId")@ApiParam(hidden = true) String tenantId){
  225. log.info("批量撤泵,【{}】",JSONUtil.toJsonStr(undoConfig));
  226. undoConfig.setTenantId(tenantId);
  227. BusPatientEntity patient = patientService.getById( undoConfig.getPatientId());
  228. if(patient==null){
  229. return R.success();
  230. }
  231. //泵切换完成后,对病号报警解除
  232. infusionService.undo(undoConfig,false);
  233. PatientOperator operator = patientRegistry.getOperator(undoConfig.getTenantId(), patient.getOriginCode());
  234. //判断当前病号下是否还存在副泵
  235. long count = infusionService.count(new QueryWrapper<BusInfusionHistoryEntity>().lambda()
  236. .eq(BusInfusionHistoryEntity::getClinicId, operator.getClinicId())
  237. .eq(BusInfusionHistoryEntity::getFinished,false)
  238. .eq(BusInfusionHistoryEntity::getIsUndo,false));
  239. //处理缓存信息
  240. if(count==1){
  241. patientService.update(new UpdateWrapper<BusPatientEntity>().lambda()
  242. .eq(BusPatientEntity::getId,patient.getId())
  243. .set(BusPatientEntity::getAlarm, PatientAlarmEnum.NONE));
  244. wsPublishUtils.publishDeviceRepeat(undoConfig.getTenantId());
  245. }
  246. wsPublishUtils.publishPatientMonitor(patient.getId(),undoConfig.getTenantId());
  247. return R.success();
  248. }
  249. @PostMapping("/monitor")
  250. @SaCheckPermission("device:patient:query")
  251. @ApiOperation(value = "查看病人当前监控详情",notes = "查看病人当前监控详情,权限标识为【device:patient:query】")
  252. public R<PatientMonitorDetailResult> monitor(@RequestBody@Validated MonitorDetailVo vo){
  253. log.info("查看病人监控详情,【{}】", JSONUtil.toJsonStr(vo));
  254. PatientMonitorDetailResult result = new PatientMonitorDetailResult();
  255. BusClinicEntity clinic =null;
  256. Boolean monitorType = vo.getMonitorType();
  257. if(Boolean.TRUE.equals(monitorType)){
  258. if (StrUtil.isEmpty(vo.getPatientId())) {
  259. throw new CustomException("病号id不能为空");
  260. }
  261. String infusionId=vo.getInfusionId();
  262. if(CharSequenceUtil.isAllBlank(infusionId)){
  263. BusPatientEntity patient = patientService.getById(vo.getPatientId());
  264. if(patient==null){
  265. throw new CustomException("该病号信息不存在,请刷新后重试");
  266. }
  267. clinic = clinicService.getById(patient.getClinicId());
  268. infusionId=patient.getInfusionId();
  269. }else {
  270. clinic= clinicService.getById(vo.getClinicId());
  271. }
  272. BusInfusionHistoryEntity infusion =infusionService.getById(infusionId);
  273. result.setInfusion(infusion);
  274. }else {
  275. String clinicId = vo.getClinicId();
  276. clinic = clinicService.getById(clinicId);
  277. result.setClinic(clinic);
  278. if(clinic!=null){
  279. //无泵查看
  280. result.setDeviceManual( manualService.getOne(new QueryWrapper<BusDeviceManualEntity>().lambda().eq(BusDeviceManualEntity::getClinicId, clinic.getId())));
  281. }
  282. }
  283. if(clinic==null){
  284. throw new CustomException("该临床信息不存在,请刷新后重试");
  285. }
  286. result.setClinic(clinic);
  287. return R.success(result);
  288. }
  289. @PostMapping("/stats/status")
  290. @SaCheckPermission("device:patient:query")
  291. @ApiOperation(value = "按照状态统计病人监控状态数量",notes = "权限【device:patient:query】")
  292. public R<MonitorStatusStatsCountResult> statsStatus(){
  293. return R.success(patientService.statusStats(null));
  294. }
  295. @PostMapping("/stats/time")
  296. @SaCheckPermission("device:patient:query")
  297. @ApiOperation(value = "按照时间统计病人监控数量",notes = "权限【device:patient:query】")
  298. public R<MonitorTimeStatsCountResult> statsTime(){
  299. return R.success(patientService.timeStats(null));
  300. }
  301. @PostMapping("/pull/async")
  302. @SaCheckPermission("device:patient:pull")
  303. @ApiOperation(value = "异步更新患者信息,超时时间默认为10s,超时后数据返回继续处理,输注监控",notes = "权限标识为【bus:patient:pull】")
  304. public DeferredResult<R<BusClinicEntity>> syn(@RequestAttribute("tenantId")@ApiParam(hidden = true) String tenantId, @Validated@RequestBody GetPatientInfoVo vo){
  305. return patientService.getPatientInfoFromHis(tenantId,vo.getPatientCode(),vo.getTimeout(),false);
  306. }
  307. @SaCheckPermission("device:patient:query")
  308. @ApiOperation(value = "泵重复绑定数量",notes = "权限标识为【bus:patient:query】")
  309. @PostMapping("/_count/repeat")
  310. public R<Integer> repeatCount(){
  311. return R.success(CollUtil.size(patientService.repeatDevice()));
  312. }
  313. @SaCheckPermission("device:patient:query")
  314. @ApiOperation(value = "无泵数量",notes = "权限标识为【bus:patient:query】")
  315. @PostMapping("/_count/none")
  316. public R<Integer> noneCount(){
  317. return R.success(CollUtil.size(patientService.noneDevice()));
  318. }
  319. /**
  320. * 描述:
  321. * @author lifang
  322. * @date 2022/5/15 21:56
  323. * @param tenantId
  324. * @param vo
  325. * @return R
  326. */
  327. @PostMapping("/pull/sync")
  328. @SaCheckPermission("device:patient:pull")
  329. @ApiOperation(value = "同步更新患者信息,超时时间默认为10s,超时后数据返回则不进行处理,无泵更新",notes = "权限标识为【bus:patient:pull】")
  330. public DeferredResult<R<BusClinicEntity>> async(@RequestAttribute("tenantId")@ApiParam(hidden = true) String tenantId,@Validated @RequestBody GetPatientInfoVo vo){
  331. return patientService.getPatientInfoFromHis(tenantId,vo.getPatientCode(),vo.getTimeout(),true);
  332. }
  333. @Override
  334. public BaseService<? extends Mapper<BusPatientEntity>, BusPatientEntity, String> getService() {
  335. return patientService;
  336. }
  337. @Override
  338. public String getPermissionPrefix() {
  339. return "bus:patient:";
  340. }
  341. @Override
  342. public StpLogic getStpLogin() {
  343. return SaManager.getStpLogic("");
  344. }
  345. }