package com.nb.bus.controller; import cn.dev33.satoken.SaManager; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.dev33.satoken.stp.StpLogic; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.mapper.Mapper; import com.nb.bus.controller.vo.GetPatientInfoVo; import com.nb.bus.controller.vo.MonitorDetailVo; import com.nb.bus.controller.vo.MonitorFinishedVo; import com.nb.bus.entity.*; import com.nb.bus.enums.DeviceStatusEnum; import com.nb.bus.enums.PatientAlarmEnum; import com.nb.bus.registry.patient.PatientOperator; import com.nb.bus.registry.patient.PatientRegistry; import com.nb.bus.service.*; import com.nb.bus.service.dto.*; import com.nb.bus.utils.WsPublishUtils; import com.nb.common.annotation.Log; import com.nb.common.crud.BaseService; import com.nb.common.crud.controller.BaseQueryController; import com.nb.common.exception.CustomException; import com.nb.common.result.R; import io.swagger.annotations.*; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.context.request.async.DeferredResult; import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; /** * @author lifang * @version 1.0.0 * @ClassName BusHospitalController.java * @Description TODO * @createTime 2022年03月19日 09:28:00 */ @RestController @AllArgsConstructor @RequestMapping("/bus/patient") @Slf4j @Api(tags = "医院病人管理",description = "关于病人的相关操作,查询操作权限【bus:patient:query】") public class BusPatientController implements BaseQueryController { private final LocalBusPatientService patientService; private final LocalBusClinicService clinicService; private final PatientRegistry patientRegistry; private final LocalBusInfusionHistoryService infusionService; private final LocalBusDeviceManualService manualService; private final WsPublishUtils wsPublishUtils; @PostMapping("/no_page") @SaCheckPermission("device:patient:query") @ApiOperation(value = "输注监控列表",notes = "病人监控管理列表,权限【device:patient:query】") public R> selectPage(@RequestBody PatientMonitorQuery query){ log.info("输注监控列表,【{}】",JSONUtil.toJsonStr(query)); return R.success(patientService.selectAll(query)); } @Log(title = "查询该次临床过程中所用的所有输注信息") @PostMapping("/look/{clinicId}/infusion") @SaCheckPermission("bus:patient:query") @ApiOperation(value = "查询该次临床过程中所用的所有输注信息",notes = "查询该次临床过程中所用的所有输注信息,权限【bus:patient:query】") public R lookUpAllInfusion(@PathVariable("clinicId") String clinicId){ List infusionHistories = infusionService.list(new QueryWrapper().lambda().eq(BusInfusionHistoryEntity::getClinicId, clinicId)); return R.success(infusionHistories.stream() .map(InfusionHistorySmallResult::of) .sorted(Comparator.comparing(InfusionHistorySmallResult::getStartTime)) .collect(Collectors.toList())); } @GetMapping("/repeat/device") @ApiOperation(value = "设备重复提示列表",notes = "当出现病患同一时间绑定了多个泵时,调用该接口查询出所有设备重复报警数据,权限【无】") public R> repeatDevice(){ log.info("设备重复提示列表"); return R.success(patientService.repeatDevice()); } @GetMapping("/none/device") @ApiOperation(value = "临床无泵列表",notes = "当出现病患同一时间没有泵时,调用该接口查询出所有没有泵信息的病患临床数据,权限【无】") public R> noneDevice(){ log.info("设备重复提示列表"); return R.success(patientService.noneDevice()); } @PostMapping("/judge/repeat") @ApiOperation(value = "判断所给病号中是否出现了绑定设备重复",notes = "当结束管理时,调用改接口判断所结束病号是否出现了设备重复异常,权限【无】") @ApiResponses({ @ApiResponse(code = 200,message = "0 病人中未出现重复,非0 病人中出现重复"), }) public R judgeRepeat(@RequestBody List patientIds){ log.info("判断所给病号中是否出现了绑定设备重复,【{}】",patientIds); return R.success(patientService.count(new QueryWrapper().lambda().in(BusPatientEntity::getId,patientIds).eq(BusPatientEntity::getAlarm,PatientAlarmEnum.DEVICE_REPEAT))); } @PostMapping("/judge/finished") @ApiOperation(value = "判断给定病号中是否可以结束临床管理",notes = "病患当前绑定主设备必须要在关机、不在服务器、待机中才能结束管理,权限【无】") @ApiResponses({ @ApiResponse(code = 500,message = "没有选择病号"), @ApiResponse(code =200 ,message = "若存在不可以结束的临床信息,返回1",response = BusDeviceRunningEntity.class) }) public R judgeFinished(@RequestBody List patientIds){ log.info("判断给定病号中是否可以结束临床管理,【{}】",patientIds); if(CollUtil.isEmpty(patientIds)){ throw new CustomException("请选择一个病患"); } List patients = patientService.list(new QueryWrapper() .lambda().in(BusPatientEntity::getId, patientIds)); if(CollUtil.isEmpty(patients)){ throw new CustomException("病号不存在,请刷新后重试"); } return R.success(infusionService.count(new QueryWrapper() .lambda() .nested(i->i.ne(BusInfusionHistoryEntity::getRunState,DeviceStatusEnum.Shutdown) .ne(BusInfusionHistoryEntity::getRunState,DeviceStatusEnum.NoSignal)) .in(BusInfusionHistoryEntity::getPatientId,patients.stream().map(BusPatientEntity::getId).collect(Collectors.toList())) .eq(BusInfusionHistoryEntity::getFinished,false))!=0); } @PostMapping("/do/{monitorType}/finished") @SaCheckPermission("bus:patient:finished") @ApiResponse(code = 4001,message = "病号当前绑定了多个设备,不可结束管理") @ApiOperation(value = "结束管理",notes = "病患当前绑定主设备必须要在关机、不在服务器、待机中才能结束管理,权限【bus:patient:finished】") public R finished(@PathVariable("monitorType")@ApiParam(value = "是否为无泵管理 false、无泵 true、有泵",defaultValue = "false" ) boolean haveDevice, @RequestBody MonitorFinishedVo monitorFinishedVo, @RequestAttribute("tenantId")@ApiParam(hidden = true) String tenantId){ log.info("结束管理,【{}】",JSONUtil.toJsonStr(monitorFinishedVo)); if(haveDevice){ R result = monitorFinished(monitorFinishedVo, tenantId); CompletableFuture.runAsync(()->wsPublishUtils.publishMonitorTotalCount(tenantId)) .thenRunAsync(()->wsPublishUtils.publishDeviceNone(tenantId)) .thenRunAsync(()->wsPublishUtils.publishMonitorStateCount(tenantId)); return result; }else { return manualFinished(monitorFinishedVo); } } /** * 描述: 输注监控结束管理(即使用驼人网络泵产品) * @author lifang * @date 2022/5/10 11:48 * @param monitorFinishedVo * @param tenantId * @return R */ private R monitorFinished(MonitorFinishedVo monitorFinishedVo, String tenantId){ List patientIds = monitorFinishedVo.getPatientIds(); if(CollUtil.isEmpty(patientIds)){ List clinicIds = monitorFinishedVo.getClinicIds(); if (CollUtil.isEmpty(clinicIds)) { throw new CustomException("未选择临床信息"); } } List patients = patientService.list(new QueryWrapper().lambda().in(BusPatientEntity::getId, patientIds)); List undoConfigs=new ArrayList<>(); for (BusPatientEntity patient : patients) { undoConfigs.add( ManualUndoConfig.of( Collections.singletonList(patient.getInfusionId()), patient.getId(), patient.getClinicId(), tenantId, true, monitorFinishedVo.getUndo()) ); } //病患绑定的有设备,对设备进行撤泵操作,且结束临床 infusionService.batchUndo(undoConfigs,true); return R.success(true); } /** * 描述: 其他监控手动结束管理(即未采用驼人网络泵产品) * @author lifang * @date 2022/5/10 11:49 * @param monitorFinishedVo * @return R */ private R manualFinished(MonitorFinishedVo monitorFinishedVo){ List clinicIds = monitorFinishedVo.getClinicIds(); if (CollUtil.isEmpty(clinicIds)) { throw new CustomException("未选择临床信息"); } manualService.finishedMonitor(monitorFinishedVo); return R.success(true); } @PostMapping("/monitor/reset/{clinicId}") @SaCheckPermission("device:patient:edit") @ApiOperation(value = "病人当前监控时间重启",notes = "当结束临床后有新的输注信息产生,那么病人监控会重新显示,此时监控时间不会重新计算,需先调用该接口,权限标识为【device:patient:edit】") public R reset(@ApiParam("临床id")@PathVariable("clinicId")String clinicId){ log.info("病人当前监控时间重启,【{}】",clinicId); R result = R.success(clinicService.update(new UpdateWrapper().lambda().eq(BusClinicEntity::getId, clinicId) .set(BusClinicEntity::getEndTime, null))); BusClinicEntity clinic = clinicService.getById(clinicId); wsPublishUtils.publishPatientMonitor(clinic.getPatientId(),clinic.getTenantId()); return result; } @PostMapping("/{alarm}/_count") @SaCheckPermission("device:patient:query") @ApiOperation(value = "病人报警数量统计",notes = "病人报警数量统计 0、未报警 1、泵重复 2、无泵,权限标识为【device:patient:query】") public R alarmCount(@PathVariable("alarm") int alarm){ PatientAlarmEnum alarmEnum = PatientAlarmEnum.of(alarm); if(alarmEnum==null){ return R.success(0); } log.info("病人报警数量统计,【{}】",alarmEnum); switch (alarmEnum){ case DEVICE_REPEAT: return this.noneCount(); case NONE: return this.repeatCount(); default:return R.success(0); } } @PostMapping("/shift") @SaCheckPermission("device:patient:shift") @ApiOperation(value = "主泵切换的操作,只切换,不结束",notes = "当出现泵重复状态时,若用户想要进行主泵的切换,调用该接口进行操作,主泵切换完成后,会将副泵自动撤泵,权限标识为【device:patient:shift】") public R shift(@RequestBody@Validated DeviceShiftConfig shiftConfig){ log.info("主泵切换的操作,【{}】",JSONUtil.toJsonStr(shiftConfig)); patientService.shift(shiftConfig); wsPublishUtils.publishPatientMonitor(shiftConfig.getPatientId(),shiftConfig.getTenantId()); return R.success(); } @PostMapping("/undo") @SaCheckPermission("device:patient:undo") @ApiOperation(value = "批量撤泵,只撤泵,不切换",notes = "当出现泵重复状态时,若用户想要取消对其他副泵的监控,则调用此接口进行撤泵操作,权限标识为【device:patient:undo】") public R shift(@RequestBody@Validated ManualUndoConfig undoConfig, @RequestAttribute("tenantId")@ApiParam(hidden = true) String tenantId){ log.info("批量撤泵,【{}】",JSONUtil.toJsonStr(undoConfig)); undoConfig.setTenantId(tenantId); BusPatientEntity patient = patientService.getById( undoConfig.getPatientId()); if(patient==null){ return R.success(); } //泵切换完成后,对病号报警解除 infusionService.undo(undoConfig,false); PatientOperator operator = patientRegistry.getOperator(undoConfig.getTenantId(), patient.getOriginCode()); //判断当前病号下是否还存在副泵 long count = infusionService.count(new QueryWrapper().lambda() .eq(BusInfusionHistoryEntity::getClinicId, operator.getClinicId()) .eq(BusInfusionHistoryEntity::getFinished,false) .eq(BusInfusionHistoryEntity::getIsUndo,false)); //处理缓存信息 if(count==1){ patientService.update(new UpdateWrapper().lambda() .eq(BusPatientEntity::getId,patient.getId()) .set(BusPatientEntity::getAlarm, PatientAlarmEnum.NONE)); wsPublishUtils.publishDeviceRepeat(undoConfig.getTenantId()); } wsPublishUtils.publishPatientMonitor(patient.getId(),undoConfig.getTenantId()); return R.success(); } @PostMapping("/monitor") @SaCheckPermission("device:patient:query") @ApiOperation(value = "查看病人当前监控详情",notes = "查看病人当前监控详情,权限标识为【device:patient:query】") public R monitor(@RequestBody@Validated MonitorDetailVo vo){ log.info("查看病人监控详情,【{}】", JSONUtil.toJsonStr(vo)); PatientMonitorDetailResult result = new PatientMonitorDetailResult(); BusClinicEntity clinic =null; Boolean monitorType = vo.getMonitorType(); if(Boolean.TRUE.equals(monitorType)){ if (StrUtil.isEmpty(vo.getPatientId())) { throw new CustomException("病号id不能为空"); } String infusionId=vo.getInfusionId(); if(CharSequenceUtil.isAllBlank(infusionId)){ BusPatientEntity patient = patientService.getById(vo.getPatientId()); if(patient==null){ throw new CustomException("该病号信息不存在,请刷新后重试"); } clinic = clinicService.getById(patient.getClinicId()); infusionId=patient.getInfusionId(); }else { clinic= clinicService.getById(vo.getClinicId()); } BusInfusionHistoryEntity infusion =infusionService.getById(infusionId); result.setInfusion(infusion); }else { String clinicId = vo.getClinicId(); clinic = clinicService.getById(clinicId); result.setClinic(clinic); if(clinic!=null){ //无泵查看 result.setDeviceManual( manualService.getOne(new QueryWrapper().lambda().eq(BusDeviceManualEntity::getClinicId, clinic.getId()))); } } if(clinic==null){ throw new CustomException("该临床信息不存在,请刷新后重试"); } result.setClinic(clinic); return R.success(result); } @PostMapping("/stats/status") @SaCheckPermission("device:patient:query") @ApiOperation(value = "按照状态统计病人监控状态数量",notes = "权限【device:patient:query】") public R statsStatus(){ return R.success(patientService.statusStats(null)); } @PostMapping("/stats/time") @SaCheckPermission("device:patient:query") @ApiOperation(value = "按照时间统计病人监控数量",notes = "权限【device:patient:query】") public R statsTime(){ return R.success(patientService.timeStats(null)); } @PostMapping("/pull/async") @SaCheckPermission("device:patient:pull") @ApiOperation(value = "异步更新患者信息,超时时间默认为10s,超时后数据返回继续处理,输注监控",notes = "权限标识为【bus:patient:pull】") public DeferredResult> syn(@RequestAttribute("tenantId")@ApiParam(hidden = true) String tenantId, @Validated@RequestBody GetPatientInfoVo vo){ return patientService.getPatientInfoFromHis(tenantId,vo.getPatientCode(),vo.getTimeout(),false); } @SaCheckPermission("device:patient:query") @ApiOperation(value = "泵重复绑定数量",notes = "权限标识为【bus:patient:query】") @PostMapping("/_count/repeat") public R repeatCount(){ return R.success(CollUtil.size(patientService.repeatDevice())); } @SaCheckPermission("device:patient:query") @ApiOperation(value = "无泵数量",notes = "权限标识为【bus:patient:query】") @PostMapping("/_count/none") public R noneCount(){ return R.success(CollUtil.size(patientService.noneDevice())); } /** * 描述: * @author lifang * @date 2022/5/15 21:56 * @param tenantId * @param vo * @return R */ @PostMapping("/pull/sync") @SaCheckPermission("device:patient:pull") @ApiOperation(value = "同步更新患者信息,超时时间默认为10s,超时后数据返回则不进行处理,无泵更新",notes = "权限标识为【bus:patient:pull】") public DeferredResult> async(@RequestAttribute("tenantId")@ApiParam(hidden = true) String tenantId,@Validated @RequestBody GetPatientInfoVo vo){ return patientService.getPatientInfoFromHis(tenantId,vo.getPatientCode(),vo.getTimeout(),true); } @Override public BaseService, BusPatientEntity, String> getService() { return patientService; } @Override public String getPermissionPrefix() { return "bus:patient:"; } @Override public StpLogic getStpLogin() { return SaManager.getStpLogic(""); } }