Bläddra i källkod

add 病人监控列表
add 主泵切换
add 批量撤泵

18339543638 3 år sedan
förälder
incheckning
dd33c8f4d7

+ 1 - 2
coffee-common/src/main/java/com/coffee/common/config/CorsConfig.java

@@ -1,7 +1,6 @@
 package com.coffee.common.config;
 
 import org.springframework.context.annotation.Configuration;
-import org.springframework.web.cors.CorsConfiguration;
 import org.springframework.web.servlet.config.annotation.CorsRegistry;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
@@ -12,7 +11,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  * @Description TODO
  * @createTime 2022年03月23日 14:49:00
  */
-//@Configuration
+@Configuration
 public class CorsConfig implements WebMvcConfigurer {
     @Override
     public void addCorsMappings(CorsRegistry registry) {

+ 4 - 5
coffee-common/src/main/java/com/coffee/common/enums/SexEnum.java

@@ -19,18 +19,17 @@ public enum SexEnum  implements IEnum<Integer> {
     /**
      * 男
      */
-    MAN(1,"1", "男"),
+    MAN(1,"男"),
     /**
      * 女
      */
-    WOMAN(2,"2", "女"),
+    WOMAN(2, "女"),
     /**
      * 未知
      */
-    UNKNOW(3,"3", "未知");
+    UNKNOW(3, "未知");
 
     private Integer value;
-    private String code;
-    private String desc;
+    private String text;
 
 }

+ 60 - 19
coffee-system/src/main/java/com/coffee/bus/controller/BusPatientController.java

@@ -2,19 +2,20 @@ package com.coffee.bus.controller;
 
 import cn.dev33.satoken.annotation.SaCheckPermission;
 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.mapper.Mapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.coffee.bus.controller.vo.MonitorFinished;
-import com.coffee.bus.entity.BusDeviceRunningEntity;
-import com.coffee.bus.entity.BusPatientEntity;
-import com.coffee.bus.entity.PatientMonitorDomain;
+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.LocalBusClinicService;
 import com.coffee.bus.service.LocalBusDeviceRunningService;
+import com.coffee.bus.service.LocalBusInfusionHistoryService;
 import com.coffee.bus.service.LocalBusPatientService;
 import com.coffee.bus.service.dto.*;
 import com.coffee.common.crud.BaseService;
@@ -28,6 +29,7 @@ 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;
 
 /**
@@ -50,21 +52,23 @@ public class BusPatientController  {
 
     private final PatientRegistry patientRegistry;
 
+    private final LocalBusInfusionHistoryService infusionService;
+
     @PostMapping("/no_page")
     @SaCheckPermission("bus:patient:query")
-    @ApiOperation(value = "病人监控管理列表",notes = "病人监控管理列表,权限【bus:patient:query】")
+    @ApiOperation(value = "输注监控列表",notes = "病人监控管理列表,权限【bus:patient:query】")
     public R<List<PatientMonitorDomain>> selectPage(@RequestBody PatientMonitorQuery query){
         return R.success(patientService.selectAll(query));
     }
 
     @GetMapping("/repeat/device")
-    @ApiOperation(value = "获取当前医院绑定设备重复的所有病患信息",notes = "当出现病患同一时间绑定了多个泵时,调用该接口查询出所有设备重复报警数据,权限【无】")
+    @ApiOperation(value = "设备重复提示列表",notes = "当出现病患同一时间绑定了多个泵时,调用该接口查询出所有设备重复报警数据,权限【无】")
     public R<List<PatientDeviceRepeatResult>> repeatDevice(){
         return R.success(patientService.repeatDevice());
     }
 
     @GetMapping("/none/device")
-    @ApiOperation(value = "获取当前医院没有绑定泵的所有病患临床信息",notes = "当出现病患同一时间没有泵时,调用该接口查询出所有没有泵信息的病患临床数据,权限【无】")
+    @ApiOperation(value = "临床无泵列表",notes = "当出现病患同一时间没有泵时,调用该接口查询出所有没有泵信息的病患临床数据,权限【无】")
     public R<List<PatientDeviceNoneResult>> noneDevice(){
         return R.success(patientService.noneDevice());
     }
@@ -72,11 +76,10 @@ public class BusPatientController  {
     @PostMapping("/judge/repeat")
     @ApiOperation(value = "判断所给病号中是否出现了绑定设备重复",notes = "当结束管理时,调用改接口判断所结束病号是否出现了设备重复异常,权限【无】")
     @ApiResponses({
-            @ApiResponse(code = 200,message = "true 设备中未出现重复"),
-            @ApiResponse(code = 200,message = "false 设备中出现重复")
+            @ApiResponse(code = 200,message = "0 病人中未出现重复,非0 病人中出现重复"),
     })
-    public R<Boolean> judgeRepeat(@RequestBody List<String> patientCode){
-        return R.success(patientService.count(new QueryWrapper<BusPatientEntity>().lambda().in(BusPatientEntity::getCode,patientCode))==0);
+    public R<Long> judgeRepeat(@RequestBody List<String> patientCode){
+        return R.success(patientService.count(new QueryWrapper<BusPatientEntity>().lambda().in(BusPatientEntity::getCode,patientCode).eq(BusPatientEntity::getAlarm,PatientAlarmEnum.DEVICE_REPEAT)));
     }
 
     @PostMapping("/judge/finished")
@@ -102,8 +105,8 @@ public class BusPatientController  {
     @PostMapping("/do/finished")
     @SaCheckPermission("bus:patient:finished")
     @ApiResponse(code = 4001,message = "病号当前绑定了多个设备,不可结束管理")
-    @ApiOperation(value = "结束对于病号的当前监控,即结束管理",notes = "病患当前绑定主设备必须要在关机、不在服务器、待机中才能结束管理,权限【bus:patient:finished】")
-    public R finished(@RequestBody MonitorFinished monitorFinished, @RequestAttribute("tenantId")String tenantId){
+    @ApiOperation(value = "即结束管理",notes = "病患当前绑定主设备必须要在关机、不在服务器、待机中才能结束管理,权限【bus:patient:finished】")
+    public R finished(@RequestBody MonitorFinished monitorFinished, @RequestAttribute("tenantId")@ApiParam(hidden = true) String tenantId){
         List<String> patientCodes = monitorFinished.getPatientCodes();
         if(CollectionUtil.isEmpty(patientCodes)){
             throw new CustomException("请选择一个病患");
@@ -126,16 +129,25 @@ public class BusPatientController  {
         List<ManualUndoConfig> undoConfigs = patientOperators.stream().map(operator ->
                 ManualUndoConfig.of(Collections.singletonList(operator.getBindDeviceId()), operator.getCode(), tenantId,true, monitorFinished.getUndo())
         )
-                .filter(undoConfig -> undoConfig.getDeviceIds() != null && undoConfig.getDeviceIds().size() > 0)
+//                .filter(undoConfig -> undoConfig.getDeviceIds() != null && undoConfig.getDeviceIds().size() > 0)
                 .collect(Collectors.toList());
         //病患绑定的有设备,对设备进行撤泵操作,且结束临床
         deviceRunningService.batchUndo(undoConfigs,true);
         return R.success();
     }
 
+
+    @PostMapping("/monitor/reset/{patientCode}")
+    @SaCheckPermission("device:patient:edit")
+    @ApiOperation(value = "病人当前监控时间重启",notes = "当结束临床后有新的输注信息产生,那么病人监控会重新显示,此时监控时间不会重新计算,需先调用该接口,权限标识为【device:patient:edit】")
+    public R reset(@PathVariable("patientCode")String patientCode){
+        return R.success(patientService.update(new UpdateWrapper<BusPatientEntity>().lambda().eq(BusPatientEntity::getCode,patientCode).set(BusPatientEntity::getTmpFinished,false)));
+    }
+
+
     @PostMapping("/shift")
     @SaCheckPermission("device:patient:shift")
-    @ApiOperation(value = "病人进行主泵切换的操作,只切换,不结束",notes = "当出现泵重复状态时,若用户想要进行主泵的切换,调用该接口进行操作,主泵切换完成后,会将副泵自动撤泵,权限标识为【device:patient:shift】")
+    @ApiOperation(value = "主泵切换的操作,只切换,不结束",notes = "当出现泵重复状态时,若用户想要进行主泵的切换,调用该接口进行操作,主泵切换完成后,会将副泵自动撤泵,权限标识为【device:patient:shift】")
     public R shift(@RequestBody DeviceShiftConfig shiftConfig){
         deviceRunningService.shift(shiftConfig);
         return R.success();
@@ -143,9 +155,32 @@ public class BusPatientController  {
 
     @PostMapping("/undo")
     @SaCheckPermission("device:patient:undo")
-    @ApiOperation(value = "病人多余的副泵撤掉,只撤泵,不切换",notes = "当出现泵重复状态时,若用户想要取消对其他副泵的监控,则调用此接口进行撤泵操作,权限标识为【device:patient:undo】")
+    @ApiOperation(value = "批量撤泵,只撤泵,不切换",notes = "当出现泵重复状态时,若用户想要取消对其他副泵的监控,则调用此接口进行撤泵操作,权限标识为【device:patient:undo】")
     public R shift(@RequestBody ManualUndoConfig undoConfig){
+        //泵切换完成后,对病号报警解除
         deviceRunningService.undo(undoConfig,false);
+        //判断当前病号下是否还存在副泵
+        long count = deviceRunningService.count(new QueryWrapper<BusDeviceRunningEntity>().lambda().eq(BusDeviceRunningEntity::getPatientCode, undoConfig.getPatientCode())
+                .eq(BusDeviceRunningEntity::getTenantId, undoConfig.getTenantId())
+                .eq(BusDeviceRunningEntity::getMaster, false)
+                .eq(BusDeviceRunningEntity::getIsUndo, false));
+        if(count>0){
+            //仅撤泵,病号报警不解除
+            return R.success();
+        }
+
+        patientService.update(new UpdateWrapper<BusPatientEntity>().lambda()
+                .eq(BusPatientEntity::getCode,undoConfig.getPatientCode())
+                .eq(BusPatientEntity::getTenantId,undoConfig.getTenantId())
+                .set(BusPatientEntity::getAlarm, PatientAlarmEnum.NONE));
+
+        //处理缓存信息
+        PatientOperator<PatientCacheInfo> operator = patientRegistry.getOperator(undoConfig.getTenantId(), undoConfig.getPatientCode());
+        String bindDeviceId = operator.getBindDeviceId();
+        Set<DeviceTimeSmallInfo> allDevice = operator.getAllDevice();
+        Optional<DeviceTimeSmallInfo> first = allDevice.stream().filter(device -> device.getDeviceId().equals(bindDeviceId)).findFirst();
+        operator.setAllDevice(Collections.singleton(first.get()));
+
         return R.success();
     }
 
@@ -165,10 +200,16 @@ public class BusPatientController  {
     public R<PatientMonitorResult> monitor(@PathVariable("monitorType")@ApiParam(value = "是否为有泵监控",example = "0、无泵,1、有泵") Boolean haveDevice,@PathVariable("patientCode")@ApiParam(value = "病号") String patientCode){
         PatientMonitorResult result = new PatientMonitorResult();
         if(haveDevice){
-            patientService.getOne(new QueryWrapper<BusPatientEntity>().lambda()
-                    .eq(BusPatientEntity::getCode,patientCode).last("limit 1"));
+            BusPatientEntity patient = patientService.getOne(new QueryWrapper<BusPatientEntity>().lambda()
+                    .eq(BusPatientEntity::getCode, patientCode).last("limit 1"));
+            BusInfusionHistoryEntity infusion = infusionService.getById(patient.getInfusionId());
+            result.setPatient(patient);
+            result.setInfusion( infusion);
+            if(StrUtil.isNotEmpty(infusion.getClinicId())){
+                result.setClinic(clinicService.getById(infusion.getClinicId()));
+            }
         }else {
-
+            //todo 无泵查看
         }
         return R.success(result);
     }

+ 11 - 2
coffee-system/src/main/java/com/coffee/bus/entity/BusInfusionModifyEntity.java

@@ -7,14 +7,13 @@ import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.coffee.bus.enums.DeviceEnum;
 import com.coffee.common.entity.TenantGenericEntity;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.ToString;
 import lombok.experimental.Accessors;
-import org.springframework.web.context.request.async.DeferredResult;
-
 import javax.validation.constraints.DecimalMax;
 import javax.validation.constraints.DecimalMin;
 import javax.validation.constraints.Max;
@@ -153,6 +152,11 @@ public class BusInfusionModifyEntity extends TenantGenericEntity<String,String>
     @TableField(exist = false)
     private Date clinicStartTime;
 
+
+    @ApiModelProperty(value = "分包标记位",readOnly = true)
+    @JsonIgnoreProperties(allowSetters = true)
+    private String classification;
+
     public static BusInfusionModifyEntity parseRunningInfo(BusDeviceRunningEntity running){
         BusInfusionModifyEntity entity = new BusInfusionModifyEntity();
         entity.setDeviceId(running.getDeviceId());
@@ -161,6 +165,7 @@ public class BusInfusionModifyEntity extends TenantGenericEntity<String,String>
         entity.setInfusionId(running.getInfusionId());
         entity.setType(running.getType());
 
+        entity.setClassification(running.getClassification());
         entity.setTotalDose(running.getTotalDose());
         entity.setFirstDose(running.getFirstDose());
         entity.setRemainDose(running.getRemainDose());
@@ -198,6 +203,7 @@ public class BusInfusionModifyEntity extends TenantGenericEntity<String,String>
         //保证参数有序
         JSONObject param = new JSONObject(true);
 
+        //加密过程中,加入分包标识,保证新的输注的输注参数必定发生改变
         switch (this.getType()){
             case continuous:
                 param.putOpt("continueDose",this.continueDose);
@@ -205,6 +211,7 @@ public class BusInfusionModifyEntity extends TenantGenericEntity<String,String>
                 param.putOpt("appendDose",this.appendDose);
                 param.putOpt("appendLockTime",this.appendLockTime);
                 param.putOpt("maxDose",this.maxDose);
+                param.putOpt("classification",this.classification);
                 break;
             case pulse:
                 param.putOpt("firstDose",this.firstDose);
@@ -215,6 +222,7 @@ public class BusInfusionModifyEntity extends TenantGenericEntity<String,String>
                 param.putOpt("appendDose",this.appendDose);
                 param.putOpt("appendLockTime",this.appendLockTime);
                 param.putOpt("maxDose",this.maxDose);
+                param.putOpt("classification",this.classification);
                 break;
             case intelligent:
                 param.putOpt("firstDose",this.firstDose);
@@ -228,6 +236,7 @@ public class BusInfusionModifyEntity extends TenantGenericEntity<String,String>
                 param.putOpt("flowDownLimit",this.flowDownLimit);
                 param.putOpt("continueDose",this.continueDose);
                 param.putOpt("maxDose",this.maxDose);
+                param.putOpt("classification",this.classification);
                 break;
             default:break;
         }

+ 16 - 4
coffee-system/src/main/java/com/coffee/bus/entity/BusPatientEntity.java

@@ -15,6 +15,8 @@ import lombok.EqualsAndHashCode;
 import lombok.ToString;
 import org.hibernate.validator.constraints.Length;
 
+import java.util.Date;
+
 /**
  * @author lifang
  * @version 1.0.0
@@ -43,13 +45,23 @@ public class BusPatientEntity extends TenantGenericEntity<String,String> {
     @ApiModelProperty("病号最新的输注记录")
     private String infusionId;
 
+    @TableField
+    @ApiModelProperty("病人此次监护开始时间")
+    private Date monitorStartTime;
+
+    @TableField
+    @ApiModelProperty("此次监护医生是否已手动结束,以此表示来计算监护时长")
+    private Boolean tmpFinished;
+
+    @TableField
+    @ApiModelProperty("当前病人监护结束时间")
+    private Date monitorEndTime;
+
+    @TableField
     @ApiModelProperty("病人最后的手术id,若病人手术信息暂不存在,则先置为-1")
     private String clinicId;
 
-    @TableField(fill = FieldFill.INSERT)
-    @TableLogic(value = "0",delval = "1")
-    private Integer isDelete;
-
+    @TableField
     @ApiModelProperty(value = "病人报警信息",example = "泵重复,无泵")
     private PatientAlarmEnum alarm;
 

+ 10 - 1
coffee-system/src/main/java/com/coffee/bus/entity/PatientMonitorDomain.java

@@ -8,7 +8,6 @@ import com.coffee.common.enums.SexEnum;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
-import org.hibernate.validator.constraints.Length;
 
 import java.math.BigDecimal;
 import java.util.Date;
@@ -155,4 +154,14 @@ public class PatientMonitorDomain {
 
     @ApiModelProperty(value = "手术名称")
     private String surgeryName;
+
+    @ApiModelProperty(value = "当前病人是否已结束临床,根据此参数+监护开始时间计算总监护时间",
+            notes = "false:监护时长=当前时间-监护开始时间 ,true:监护时长=监护结束时间-监护开始时间")
+    private Boolean clinicFinished;
+
+    @ApiModelProperty("当前病人监护结束时间")
+    private Date monitorEndTime;
+
+    @ApiModelProperty("当前病人监护开始时间")
+    private Date monitorStartTime;
 }

+ 1 - 0
coffee-system/src/main/java/com/coffee/bus/enums/PatientAlarmEnum.java

@@ -16,6 +16,7 @@ import lombok.Getter;
 @JsonFormat(shape = JsonFormat.Shape.OBJECT)
 @Getter
 public enum PatientAlarmEnum implements IEnum<Integer> {
+    NONE(0,"无报警信息"),
     DEVICE_REPEAT(1,"病人绑定多个设备"),
     DEVICE_NONE(2,"病人未绑定设备");
 

+ 2 - 2
coffee-system/src/main/java/com/coffee/bus/handler/CheckSignHandler.java

@@ -23,8 +23,8 @@ import java.nio.charset.Charset;
  * @Description TODO
  * @createTime 2022年04月22日 10:47:00
  */
-@Configuration
-@Profile("dev")
+//@Configuration
+//@Profile("dev")
 public class CheckSignHandler implements HandlerInterceptor {
     @Override
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {

+ 9 - 1
coffee-system/src/main/java/com/coffee/bus/service/LocalBusClinicService.java

@@ -2,6 +2,7 @@ package com.coffee.bus.service;
 
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.coffee.bus.entity.BusClinicEntity;
+import com.coffee.bus.entity.BusPatientEntity;
 import com.coffee.bus.mapper.BusClinicMapper;
 import com.coffee.bus.registry.patient.PatientOperator;
 import com.coffee.bus.registry.patient.PatientRegistry;
@@ -25,7 +26,9 @@ import java.util.*;
 @Service
 @Slf4j
 public class LocalBusClinicService extends BaseService<BusClinicMapper, BusClinicEntity,String> {
-
+    @Autowired
+    @Lazy
+    private LocalBusPatientService patientService;
     @Autowired
     @Lazy
     private PatientRegistry patientRegistry;
@@ -70,6 +73,11 @@ public class LocalBusClinicService extends BaseService<BusClinicMapper, BusClini
                 .eq(BusClinicEntity::getFinished,false)
                 .set(BusClinicEntity::getFinished,true)
                 .set(BusClinicEntity::getEndTime,finishTime));
+
+        patientService.update(new UpdateWrapper<BusPatientEntity>().lambda()
+                .in(BusPatientEntity::getCode,patientCodes)
+                .set(BusPatientEntity::getTmpFinished,true)
+                .set(BusPatientEntity::getMonitorEndTime,finishTime));
         //更新病人缓存
         patientCodes.stream().map(code->patientRegistry.getOperator(tenantId,code)).forEach(operator->operator.setFinished(true));
     }

+ 28 - 27
coffee-system/src/main/java/com/coffee/bus/service/LocalBusDeviceRunningService.java

@@ -90,33 +90,34 @@ public class LocalBusDeviceRunningService extends BaseService<BusDeviceRunningMa
     @Transactional(rollbackFor = Exception.class)
     public void undo(ManualUndoConfig manualUndoConfig,boolean finishClinic) {
         List<String> deviceIds = manualUndoConfig.getDeviceIds();
-        if(CollectionUtil.isEmpty(deviceIds)){
-            return;
-        }
-        /****************将撤泵记录存入到泵的使用历史记录中***************/
-        List<BusDeviceRunningEntity> devices = this.list(new QueryWrapper<BusDeviceRunningEntity>().lambda().in(BusDeviceRunningEntity::getDeviceId,deviceIds));
-        if(CollectionUtil.isEmpty(devices)){
-            return;
-        }
-        if (devices.stream().anyMatch(BusDeviceRunningEntity::getMaster)) {
-            throw new CustomException("主泵不可撤除,请在【结束管理】处操作");
-        }
-        //对所有运行中的泵进行撤泵操作
-        this.update(new UpdateWrapper<BusDeviceRunningEntity>().lambda().in(BusDeviceRunningEntity::getDeviceId,deviceIds).set(BusDeviceRunningEntity::getIsUndo,true));
-        //无泵监护,不需要监护输注数据
-        if(!Boolean.TRUE.equals(manualUndoConfig.getMonitorType())){
-            //输注结束,更新撤泵信息
-            Set<String> infusionIds = devices.stream().map(BusDeviceRunningEntity::getInfusionId).collect(Collectors.toSet());
-            UndoDeviceConfig undo = manualUndoConfig.getUndo();
-            infusionHistoryService.update(new UpdateWrapper<BusInfusionHistoryEntity>().lambda()
-                    .in(BusInfusionHistoryEntity::getId,infusionIds)
-                    .set(BusInfusionHistoryEntity::getUndoBy,undo.getUndoBy())
-                    .set(BusInfusionHistoryEntity::getUndoTime,undo.getUndoTime())
-                    .set(BusInfusionHistoryEntity::getDestroyer,undo.getDestroyer())
-                    .set(BusInfusionHistoryEntity::getWitnesses,undo.getWitnesses()));
-            //将缓存设置为已撤泵状态
-            deviceIds.stream().map(deviceRegistry::getOperator)
-                    .forEach(operator->operator.setUndo(true));
+        if(CollectionUtil.isNotEmpty(deviceIds)){
+            /****************将撤泵记录存入到泵的使用历史记录中***************/
+            List<BusDeviceRunningEntity> devices = this.list(new QueryWrapper<BusDeviceRunningEntity>().lambda().in(BusDeviceRunningEntity::getDeviceId,deviceIds));
+            if(CollectionUtil.isEmpty(devices)){
+                return;
+            }
+//            //主泵撤除且没有结束临床
+//            if (devices.stream().anyMatch(BusDeviceRunningEntity::getMaster)&&!finishClinic) {
+//                throw new CustomException("主泵不可撤除,请在【结束管理】处操作");
+//            }
+            //对所有运行中的泵进行撤泵操作
+            this.update(new UpdateWrapper<BusDeviceRunningEntity>().lambda().in(BusDeviceRunningEntity::getDeviceId,deviceIds).set(BusDeviceRunningEntity::getIsUndo,true));
+            //无泵监护,不需要监护输注数据
+            if(Boolean.TRUE.equals(manualUndoConfig.getMonitorType())){
+                //输注结束,更新撤泵信息
+                Set<String> infusionIds = devices.stream().map(BusDeviceRunningEntity::getInfusionId).collect(Collectors.toSet());
+                UndoDeviceConfig undo = manualUndoConfig.getUndo();
+                infusionHistoryService.update(new UpdateWrapper<BusInfusionHistoryEntity>().lambda()
+                        .in(BusInfusionHistoryEntity::getId,infusionIds)
+                        .set(BusInfusionHistoryEntity::getIsUndo,true)
+                        .set(BusInfusionHistoryEntity::getUndoBy,undo.getUndoBy())
+                        .set(BusInfusionHistoryEntity::getUndoTime,undo.getUndoTime())
+                        .set(BusInfusionHistoryEntity::getDestroyer,undo.getDestroyer())
+                        .set(BusInfusionHistoryEntity::getWitnesses,undo.getWitnesses()));
+                //将缓存设置为已撤泵状态
+                deviceIds.stream().map(deviceRegistry::getOperator)
+                        .forEach(operator->operator.setUndo(true));
+            }
         }
         //结束临床
         if(finishClinic){

+ 0 - 4
coffee-system/src/main/java/com/coffee/bus/service/dto/DeviceShiftConfig.java

@@ -25,10 +25,6 @@ public class DeviceShiftConfig {
     @NotNull(message = "请选择一个泵作为此临床信息的主泵进行监控")
     private String masterDeviceId;
 
-    @ApiModelProperty("主泵的开始时间")
-    @NotNull(message = "主泵的开始时间不能为空")
-    private Date startTime;
-
     @ApiModelProperty("病号")
     @NotNull(message = "病号不能为空")
     private String patientCode;

+ 4 - 1
coffee-system/src/main/java/com/coffee/bus/service/dto/ManualUndoConfig.java

@@ -5,8 +5,10 @@ import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.AllArgsConstructor;
 import lombok.Data;
+import lombok.NoArgsConstructor;
 
 import javax.validation.constraints.NotNull;
+import java.io.Serializable;
 import java.util.*;
 /**
  * @author lifang
@@ -18,7 +20,8 @@ import java.util.*;
 @Data
 @ApiModel("手动撤泵配置")
 @AllArgsConstructor(staticName = "of")
-public class ManualUndoConfig {
+@NoArgsConstructor
+public class ManualUndoConfig implements Serializable {
     @ApiModelProperty("进行撤泵的所有运行数据id")
     private List<String> deviceIds;
 

+ 29 - 0
coffee-system/src/main/java/com/coffee/bus/websocket/handler/DeviceInfoHook.java

@@ -0,0 +1,29 @@
+package com.coffee.bus.websocket.handler;
+
+import com.coffee.bus.entity.BusDeviceRunningEntity;
+import com.coffee.bus.registry.device.DeviceOperator;
+import com.coffee.bus.registry.device.bean.DeviceCacheInfo;
+
+import java.util.List;
+import java.util.function.Supplier;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName DeviceInfoHandler.java
+ * @Description 设备信息处理钩子函数
+ * @createTime 2022年04月24日 15:45:00
+ */
+public interface DeviceInfoHook {
+
+    /**
+     * 输注参数发生变化
+     * @param device 设备数据
+     * @param deviceOperator 设备操作符
+     * @param delayOperation  延迟操作
+     * @param newInfusion 是否为新的输注
+     */
+    void infusionParamModify(BusDeviceRunningEntity device, DeviceOperator<DeviceCacheInfo> deviceOperator,  List<Supplier<?>> delayOperation,boolean newInfusion);
+
+
+}

+ 68 - 49
coffee-system/src/main/java/com/coffee/bus/websocket/listener/DeviceInfoListener.java

@@ -2,6 +2,7 @@ package com.coffee.bus.websocket.listener;
 
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.RandomUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.crypto.SignUtil;
@@ -25,6 +26,7 @@ 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.websocket.handler.DeviceInfoHook;
 import com.coffee.common.config.websocket.WebSocketConstant;
 import com.coffee.common.enums.SexEnum;
 import lombok.AllArgsConstructor;
@@ -73,9 +75,15 @@ public class DeviceInfoListener {
     private final LocalBusDeviceHistoryService historyService;
 
     private final LocalBusPatientService patientService;
+
+    private final LocalBusClinicService clinicService;
+
+    private final List<DeviceInfoHook> deviceInfoHooks;
     /**
      * 监听上传的数据信息,
      * 若设备详情发生变化,则及时通知相应的ws通道
+     * 当输注信息或新输注时,进行主副泵判断及切换
+     * 当新输注时,将关闭的临床重启
      * @param infoEvent
      */
     @EventListener
@@ -86,33 +94,45 @@ public class DeviceInfoListener {
             log.info("开始处理时间------------------------[{}]",System.currentTimeMillis());
             /****************处理泵数据 todo 后续交由上游处理****************/
             BusDeviceRunningEntity device = infoEvent.getContent();
+            device.setMonitorType(true);
+            device.setMaster(true);
             //1、判断该设备是否已和医院绑定并开启使用
             String deviceId = device.getDeviceId();
+            device.setUploadTime(device.getUploadTime()==null?new Date():device.getUploadTime());
             DeviceOperator<DeviceCacheInfo> deviceOperator = deviceRegistry.getOperator(deviceId);
             if (deviceOperator==null||!Boolean.TRUE.equals(deviceOperator.getEnable())) {
                 log.warn("设备[{}]暂不可用,数据已丢弃",deviceId);
                 return ;
             }
-            device.setUploadTime(device.getUploadTime()==null?new Date():device.getUploadTime());
+
+            //数据准确性判断
+            String classification = device.getClassification();
+            //默认为主泵,后续判断若不满足主泵条件,则替换为副泵
+            if(classification==null){
+                log.error("设备号:[{}]分包标识号为空,无法更新开始时间");
+                throw new RuntimeException("设备数据中分包标识不能为空");
+            }
+
+
             log.info("接收到设备数据:[{}]",infoEvent.getContent().toString());
             AtomicBoolean newInfusion=new AtomicBoolean(false);
             AtomicBoolean valid = new AtomicBoolean(true);
             //缓存操作
             List<Supplier<?>> cacheOperation=new ArrayList<>();
-            //处理设备运行数据
-            boolean first = handleRunningInfo(device, deviceOperator,newInfusion,valid,cacheOperation);
+            //处理设备运行数据,     判断是否为注册后第一次开机,判断是否为新的输注信息
+            boolean first = handleRunningInfo(device, deviceOperator,newInfusion,cacheOperation);
+
+            //临床已结束,且设备非主设备
             if(!valid.get()){
                 log.error("设备[{}]所绑定临床已结束且未关机,将数据[{}]丢弃",device.getDeviceId(),device.toString());
                 return;
+            }else {
+                //todo 重启临床数据
             }
-            //如果为新数据或者未撤泵
-            if(newInfusion.get()||!deviceOperator.getUndo()){
-                handlePatient(device,cacheOperation);
-            }
-            //更新/保存当前输注信息
-            handleInfusionHistory(device,deviceOperator,newInfusion,cacheOperation);
+
             //处理输注参数
-            handleInfusionParam(device,deviceOperator,newInfusion,cacheOperation);
+            handleInfusion(device,deviceOperator,newInfusion,cacheOperation);
+
             //处理历史运行数据
             BusDeviceHistoryEntity history=handleRunningHistory(device);
             //处理报警信息
@@ -126,6 +146,7 @@ public class DeviceInfoListener {
                         .eq(BusPatientEntity::getTenantId,device.getTenantId())
                         .set(BusPatientEntity::getInfusionId,device.getInfusionId()));
             }
+
             //todo 流速图处理
             if(first){
                 deviceUsingService.save(device);
@@ -151,38 +172,33 @@ public class DeviceInfoListener {
      * 设备运行数据处理,返回是否为第一次接受数据消息
      * @param device 接收到的设备信息
      * @param deviceOperator 设备缓存信息操作符
-     * @param valid 设备数据是否有效
      * @param newInfusion 是否为新的输注
      * @return 是否为第一次接收数据消息
      */
-    private boolean handleRunningInfo( BusDeviceRunningEntity device,DeviceOperator<DeviceCacheInfo> deviceOperator,AtomicBoolean newInfusion,AtomicBoolean valid,List<Supplier<?>> suppliers){
-        //判断此条数据的分包标识是否发生了改变,若改变则
+    private boolean handleRunningInfo( BusDeviceRunningEntity device,DeviceOperator<DeviceCacheInfo> deviceOperator,AtomicBoolean newInfusion,List<Supplier<?>> suppliers){
+        //判断此条数据的分包标识是否发生了改变
         String originClassify = deviceOperator.getClassification();
         String classification = device.getClassification();
-        //默认为主泵,后续判断若不满足主泵条件,则替换为副泵
-        device.setMaster(true);
-        if(classification==null){
-            log.error("设备号:[{}]分包标识号为空,无法更新开始时间");
-            newInfusion.set(true);
-            throw new RuntimeException("设备数据中分包标识不能为空");
-        }
         String usingId = deviceOperator.getUsingId();
+        device.setIsUndo(deviceOperator.getUndo());
         //todo 这部分操作交由上游处理
         device.setTenantId(deviceOperator.getTenantId());
-        device.setMonitorType(true);
+
+//        PatientOperator<PatientCacheInfo> patientOperator = patientRegistry.getOperator(device.getTenantId(), device.getPatientCode());
+//        Boolean finished = patientOperator.getFinished();
         if(!classification.equals(originClassify)){
             newInfusion.set(true);
             //启动新的输注,则撤泵标识取消
             device.setIsUndo(false);
             //分包标识发生了改变,设备开机时间重新计算
             device.setStartTime(new Date());
-        }else {
-            PatientOperator<PatientCacheInfo> patient = patientRegistry.getOperator(device.getTenantId(), device.getPatientCode());
-            Boolean finished = patient.getFinished();
-            if(Boolean.TRUE.equals(finished)){
-                //分包标识未改变且临床已结束 ,则此次数据无效
-                valid.set(false);
-            }
+            //todo 处理临床数据
+//            if(Boolean.TRUE.equals(finished)){
+//                将临床重新开启
+//                clinicService
+//                        .update(new UpdateWrapper<BusClinicEntity>().lambda().eq(BusClinicEntity::getId,patientOperator.getClinicId())
+//                                .set(BusClinicEntity::getFinished,false));
+//            }
         }
         boolean first=false;
         if(StrUtil.isNullOrUndefined(usingId)){
@@ -193,14 +209,18 @@ public class DeviceInfoListener {
             first=true;
         }else {
             device.setId(usingId);
-            device.setStartTime(deviceOperator.getStartTime());
+            if(!newInfusion.get()){
+                device.setStartTime(deviceOperator.getStartTime());
+            }
         }
         suppliers.add(()->{
             //更新设备缓存数据
             if(newInfusion.get()){
                 deviceOperator.setUndo(false);
+//                patientOperator.setFinished(false);
             }
             deviceOperator.setClassification(device.getClassification());
+
             deviceOperator.setTenantId(device.getTenantId());
             deviceOperator.setUsingId(device.getId());
             deviceOperator.setStatus(device.getRunState());
@@ -347,7 +367,8 @@ public class DeviceInfoListener {
             //检测数据库是否存在该输注信息
             infusionHistory.setId(String.valueOf(IdWorker.getId()));
             infusionHistoryService.update(new UpdateWrapper<BusInfusionHistoryEntity>().lambda()
-                    .eq(BusInfusionHistoryEntity::getId,originInfusionId)
+                    .eq(BusInfusionHistoryEntity::getDeviceId,device.getDeviceId())
+                    .eq(BusInfusionHistoryEntity::getFinished,false)
                     .set(BusInfusionHistoryEntity::getFinished,true));
             infusionHistoryService.save(infusionHistory);
         }else {
@@ -362,28 +383,27 @@ public class DeviceInfoListener {
     }
 
     /**
-     * 对输注参数进行判断处理
+     * 处理输注信息
      * @param device 设备运行数据
      * @param deviceOperator 设备操作符
      * @param  newInfusion 是否为新的输注记录
      * @param cacheOperation 缓存操作
      */
-    private void handleInfusionParam(BusDeviceRunningEntity device, DeviceOperator<DeviceCacheInfo> deviceOperator,  AtomicBoolean newInfusion,List<Supplier<?>> cacheOperation) {
+    private void handleInfusion(BusDeviceRunningEntity device, DeviceOperator<DeviceCacheInfo> deviceOperator, AtomicBoolean newInfusion, List<Supplier<?>> cacheOperation) {
+        handleInfusionHistory(device,deviceOperator,newInfusion,cacheOperation);
         BusInfusionModifyEntity busInfusionModify = BusInfusionModifyEntity.parseRunningInfo(device);
         String signHex = busInfusionModify.signParam(sign);
-        if(newInfusion.get()){
-            //新的输注记录直接生成新的输注参数
-            infusionModifyService.save(busInfusionModify);
-            cacheOperation.add(()->{
-                deviceOperator.setInfusionParam(signHex);
-                return null;
-            });
-            return;
-        }
         String infusionParam = deviceOperator.getInfusionParam();
-        if(StrUtil.isEmpty(infusionParam)||!infusionParam.equals(signHex)){
-            //输注参数发生变化, todo 则根据参数修改时间 进行主副泵的判别
+        //输注参数已发生变化
+        if(ObjectUtil.notEqual(signHex,infusionParam)){
+            //输注参数改变
             infusionModifyService.save(busInfusionModify);
+            //输注参数变化后重启临床并且主副泵判断 todo
+            if (CollectionUtil.isNotEmpty(deviceInfoHooks)) {
+                deviceInfoHooks.forEach(hook->hook.infusionParamModify(device,deviceOperator,cacheOperation,newInfusion.get()));
+            }
+            handlePatient(device,cacheOperation);
+            //todo 输注参数发生变化
             cacheOperation.add(()->{
                 deviceOperator.setInfusionParam(signHex);
                 return null;
@@ -443,7 +463,7 @@ public class DeviceInfoListener {
     }
 
     public static int count=1;
-    public static int mark=0;
+    public static long mark=System.currentTimeMillis();
     @Scheduled(cron = "0/20 * * * * ?")
     public void send() throws InterruptedException {
 //        List<BusDeviceRunningEntity> list = deviceUsingService.list();
@@ -452,10 +472,9 @@ public class DeviceInfoListener {
             return;
         }
         ++count;
-        mark=mark+1;
         BusDeviceRunningEntity pump = new BusDeviceRunningEntity();
         pump.setType(DeviceEnum.continuous);
-        pump.setClassification("1");
+        pump.setClassification(String.valueOf(mark));
         pump.setDeviceId("123");
         pump.setPatientCode("456");
         pump.setRemainDose(BigDecimal.valueOf(RandomUtil.randomInt(100)));
@@ -471,7 +490,7 @@ public class DeviceInfoListener {
         BusDeviceRunningEntity pump1 = new BusDeviceRunningEntity();
         pump1.setDeviceId("456");
         pump1.setType(DeviceEnum.continuous);
-        pump1.setClassification("1");
+        pump1.setClassification(String.valueOf(mark));
         pump1.setPatientCode("456");
         pump1.setRemainDose(BigDecimal.valueOf(RandomUtil.randomInt(100)));
         pump1.setContinueDose(BigDecimal.valueOf(RandomUtil.randomInt(100)));
@@ -486,7 +505,7 @@ public class DeviceInfoListener {
         BusDeviceRunningEntity pump2 = new BusDeviceRunningEntity();
         pump2.setType(DeviceEnum.continuous);
         pump2.setDeviceId("456");
-        pump2.setClassification("2");
+        pump2.setClassification(String.valueOf(mark));
         pump2.setPatientCode("789");
         pump2.setRemainDose(BigDecimal.valueOf(RandomUtil.randomInt(100)));
         pump2.setContinueDose(BigDecimal.valueOf(RandomUtil.randomInt(100)));
@@ -502,7 +521,7 @@ public class DeviceInfoListener {
 
         BusDeviceRunningEntity pump3 = new BusDeviceRunningEntity();
         pump3.setDeviceId("456");
-        pump3.setClassification("3");
+        pump3.setClassification(String.valueOf(mark));
         pump3.setType(DeviceEnum.continuous);
         pump3.setPatientCode("456");
         pump3.setRemainDose(BigDecimal.valueOf(RandomUtil.randomInt(100)));

+ 12 - 0
coffee-system/src/main/java/com/coffee/bus/websocket/listener/HisInfoListener.java

@@ -201,6 +201,17 @@ public class HisInfoListener {
     }
 
     private void changedRunningClinic(BusClinicEntity clinic,PatientOperator<PatientCacheInfo> patientOperator){
+        String originClinic = patientOperator.getClinicId();
+        if(!clinic.getId().equals(originClinic)){
+            //临床信息发生变化
+            if(patientOperator.getFinished()){
+                patientService.update(new UpdateWrapper<BusPatientEntity>().lambda()
+                        .eq(BusPatientEntity::getCode,clinic.getPatientCode())
+                        .eq(BusPatientEntity::getTenantId,clinic.getTenantId())
+                        .set(BusPatientEntity::getTmpFinished,false));
+                patientOperator.setFinished(false);
+            }
+        }
         patientOperator.setClinicId(clinic.getId());
         patientOperator.setWard(clinic.getWard());
         patientOperator.setBedNo(clinic.getBedNo());
@@ -211,6 +222,7 @@ public class HisInfoListener {
             List<String> deviceIds = allDevice.stream().map(DeviceTimeSmallInfo::getDeviceId).collect(Collectors.toList());
             deviceRunningService.updateClinicInfo(deviceIds,clinic);
         }
+
         log.error("临床信息发生改变:[{}],[{}]",clinic.getPatientCode(),clinic.toString());
         //todo 实时传输病人临床数据
 

+ 7 - 1
coffee-system/src/main/resources/mapper/bus/BusPatientMapper.xml

@@ -63,6 +63,9 @@
         <result column="ana_type" property="anaType"/>
         <result column="surgery_doctor" property="surgeryDoctor"/>
         <result column="surgery_name" property="surgeryName"/>
+        <result column="tmp_finished" property="clinicFinished"/>
+        <result column="monitor_end_time" property="monitorEndTime"/>
+        <result column="monitor_start_time" property="monitorStartTime"/>
     </resultMap>
 
     <select id="selectRepeatDevice" resultMap="repeatDeviceResult">
@@ -104,6 +107,9 @@ left join  (SELECT * FROM bus_clinic WHERE finished=0 ) AS c ON  c.`patient_code
         p.`code` as patient_code,
         p.gender as gender,
         p.alarm as patient_alarm,
+        p.tmp_finished as tmp_finished,
+        p.monitor_start_time as monitor_start_time,
+        p.monitor_end_time as monitor_end_time,
         i.device_id as device_id,
         i.clinic_id as clinic_id,
         i.ward as ward,
@@ -147,7 +153,7 @@ left join  (SELECT * FROM bus_clinic WHERE finished=0 ) AS c ON  c.`patient_code
         (select * from bus_patient)
         as p
         join
-        (select * from bus_infusion_history
+        (select * from bus_infusion_history  where is_undo='0'
         <where>
             <if test="query.wards != null and query.wards.size > 0">
                 and ward in