package com.coffee.bus.controller; import cn.dev33.satoken.SaManager; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.dev33.satoken.stp.StpLogic; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.Update; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.mapper.Mapper; import com.coffee.bus.controller.vo.GetPatientInfoVo; import com.coffee.bus.controller.vo.MonitorFinishedVo; import com.coffee.bus.entity.*; import com.coffee.bus.enums.DeviceStatusEnum; import com.coffee.bus.enums.PatientAlarmEnum; import com.coffee.bus.registry.patient.PatientOperator; import com.coffee.bus.registry.patient.PatientRegistry; import com.coffee.bus.registry.patient.bean.DeviceTimeSmallInfo; import com.coffee.bus.registry.patient.bean.PatientCacheInfo; import com.coffee.bus.service.*; import com.coffee.bus.service.dto.*; import com.coffee.bus.utils.WsPublishUtils; import com.coffee.common.crud.BaseService; import com.coffee.common.crud.controller.BaseQueryController; import com.coffee.common.entity.GenericEntity; import com.coffee.common.exception.CustomException; import com.coffee.common.result.R; import io.swagger.annotations.*; import lombok.AllArgsConstructor; 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.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") @Api(tags = "医院病人管理",description = "关于病人的相关操作,查询操作权限【bus:patient:query】") public class BusPatientController implements BaseQueryController { private final LocalBusPatientService patientService; private final LocalBusDeviceRunningService deviceRunningService; private final LocalBusClinicService clinicService; private final PatientRegistry patientRegistry; private final LocalBusInfusionHistoryService infusionService; private final LocalBusDeviceManualService manualService; private final WsPublishUtils wsPublishUtils; @PostMapping("/no_page") @SaCheckPermission("bus:patient:query") @ApiOperation(value = "输注监控列表",notes = "病人监控管理列表,权限【bus:patient:query】") public R> selectPage(@RequestBody PatientMonitorQuery query){ return R.success(patientService.selectAll(query)); } @GetMapping("/repeat/device") @ApiOperation(value = "设备重复提示列表",notes = "当出现病患同一时间绑定了多个泵时,调用该接口查询出所有设备重复报警数据,权限【无】") public R> repeatDevice(){ return R.success(patientService.repeatDevice()); } @GetMapping("/none/device") @ApiOperation(value = "临床无泵列表",notes = "当出现病患同一时间没有泵时,调用该接口查询出所有没有泵信息的病患临床数据,权限【无】") public R> noneDevice(){ return R.success(patientService.noneDevice()); } @PostMapping("/judge/repeat") @ApiOperation(value = "判断所给病号中是否出现了绑定设备重复",notes = "当结束管理时,调用改接口判断所结束病号是否出现了设备重复异常,权限【无】") @ApiResponses({ @ApiResponse(code = 200,message = "0 病人中未出现重复,非0 病人中出现重复"), }) public R judgeRepeat(@RequestBody List patientCode){ return R.success(patientService.count(new QueryWrapper().lambda().in(BusPatientEntity::getCode,patientCode).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 patientCodes){ if(CollectionUtil.isEmpty(patientCodes)){ throw new CustomException("请选择一个病患"); } return R.success(CollectionUtil.isNotEmpty(deviceRunningService.list(new QueryWrapper() .lambda() .select(BusDeviceRunningEntity::getDeviceId,BusDeviceRunningEntity::getPatientCode,BusDeviceRunningEntity::getRunState,BusDeviceRunningEntity::getAlarm) .eq(BusDeviceRunningEntity::getMaster,true) .eq(BusDeviceRunningEntity::getMonitorType,true) .nested(i->i.ne(BusDeviceRunningEntity::getRunState,DeviceStatusEnum.Shutdown) .ne(BusDeviceRunningEntity::getRunState,DeviceStatusEnum.NoSignal)) .in(BusDeviceRunningEntity::getPatientCode,patientCodes)))); } @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){ if(haveDevice){ R result = monitorFinished(monitorFinishedVo, tenantId); wsPublishUtils.publishMonitorTotalCount(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 patientCodes = monitorFinishedVo.getPatientCodes(); if(CollectionUtil.isEmpty(patientCodes)){ List clinicIds = monitorFinishedVo.getClinicIds(); if (CollectionUtil.isEmpty(clinicIds)) { throw new CustomException("未选择临床信息"); } patientCodes=clinicService.list(new QueryWrapper().lambda() .in(BusClinicEntity::getId,clinicIds)) .stream().map(BusClinicEntity::getPatientCode).collect(Collectors.toList()); if (CollectionUtil.isEmpty(patientCodes)) { throw new CustomException("临床信息不存在"); } } List> patientOperators = patientCodes.stream().map(code -> patientRegistry.getOperator(tenantId, code)).collect(Collectors.toList()); //重复设备 Optional> existRepeatDevice = patientOperators.stream() .filter(patientOperator -> { Set allDevice = patientOperator.getAllDevice(); if (allDevice != null && allDevice.size() > 1) { return true; } return false; }) .findAny(); if(existRepeatDevice.isPresent()){ return R.fail(String.format("病号【%s】当前绑定了多个设备,请将多余设备结束后结束管理",existRepeatDevice.get().getCode())); } //组装撤泵信息 List undoConfigs = patientOperators.stream().map(operator -> ManualUndoConfig.of(Collections.singletonList(operator.getBindDeviceId()), operator.getCode(),operator.getClinicId(), tenantId,true, monitorFinishedVo.getUndo()) ) .collect(Collectors.toList()); //病患绑定的有设备,对设备进行撤泵操作,且结束临床 deviceRunningService.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 (CollectionUtil.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){ 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.getPatientCode(),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(0L); } return R.success(patientService.patientAlarmCount(alarmEnum)); } @PostMapping("/shift") @SaCheckPermission("device:patient:shift") @ApiOperation(value = "主泵切换的操作,只切换,不结束",notes = "当出现泵重复状态时,若用户想要进行主泵的切换,调用该接口进行操作,主泵切换完成后,会将副泵自动撤泵,权限标识为【device:patient:shift】") public R shift(@RequestBody@Validated DeviceShiftConfig shiftConfig){ deviceRunningService.shift(shiftConfig); wsPublishUtils.publishPatientMonitor(shiftConfig.getPatientCode(),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){ undoConfig.setTenantId(tenantId); //泵切换完成后,对病号报警解除 deviceRunningService.undo(undoConfig,false); //判断当前病号下是否还存在副泵 long count = deviceRunningService.count(new QueryWrapper().lambda() .eq(BusDeviceRunningEntity::getPatientCode, undoConfig.getPatientCode()) .eq(BusDeviceRunningEntity::getTenantId, undoConfig.getTenantId()) .eq(BusDeviceRunningEntity::getMaster, false) .eq(BusDeviceRunningEntity::getIsUndo, false)); //处理缓存信息 PatientOperator operator = patientRegistry.getOperator(undoConfig.getTenantId(), undoConfig.getPatientCode()); String bindDeviceId = operator.getBindDeviceId(); Set allDevice = operator.getAllDevice(); Optional first = allDevice.stream().filter(device -> device.getDeviceId().equals(bindDeviceId)).findFirst(); operator.setAllDevice(Collections.singleton(first.get())); if(count>0){ //仅撤泵,病号报警不解除 return R.success(); } patientService.update(new UpdateWrapper().lambda() .eq(BusPatientEntity::getCode,undoConfig.getPatientCode()) .eq(BusPatientEntity::getTenantId,undoConfig.getTenantId()) .set(BusPatientEntity::getAlarm, PatientAlarmEnum.NONE)); wsPublishUtils.publishPatientMonitor(undoConfig.getPatientCode(),undoConfig.getTenantId()); wsPublishUtils.publishDeviceRepeat(undoConfig.getTenantId()); return R.success(); } @GetMapping("/monitor/{monitorType}/{clinicId}") @SaCheckPermission("device:patient:query") @ApiOperation(value = "查看病人当前监控详情",notes = "查看病人当前监控详情,权限标识为【device:patient:query】") public R monitor(@PathVariable("monitorType")@ApiParam(value = "是否为有泵监控",example = "0、无泵,1、有泵") Boolean haveDevice, @PathVariable("clinicId")@ApiParam(value = "临床id")String clinicId){ PatientMonitorDetailResult result = new PatientMonitorDetailResult(); BusClinicEntity clinic = clinicService.getById(clinicId); result.setClinic(clinic); if(clinic==null){ throw new CustomException("该临床信息不存在,请刷新后重试"); } if(haveDevice){ BusInfusionHistoryEntity infusion =infusionService.currentInClinic(clinic.getId()); // BusInfusionHistoryEntity infusion = infusionService.getOne(new QueryWrapper().lambda().eq(BusInfusionHistoryEntity::getClinicId,clinic.getId()) // .orderByDesc(BusInfusionHistoryEntity::getStartTime).last("limit 1")); result.setInfusion(infusion); if(StrUtil.isNotEmpty(infusion.getClinicId())){ result.setClinic(clinicService.getById(infusion.getClinicId())); } }else { //无泵查看 result.setDeviceManual( manualService.getOne(new QueryWrapper().lambda().eq(BusDeviceManualEntity::getClinicId, clinic.getId()))); } 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, @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(CollectionUtil.size(patientService.repeatDevice())); } @SaCheckPermission("device:patient:query") @ApiOperation(value = "无泵数量",notes = "权限标识为【bus:patient:query】") @PostMapping("/_count/none") public R noneCount(){ return R.success(CollectionUtil.size(patientService.repeatDevice())); } /** * 描述: * @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, @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(""); } }