Browse Source

fix 实时推送
add 医院会话管理

A17404李放 3 years ago
parent
commit
db322f9f6c

+ 4 - 0
coffee-common/src/main/java/com/coffee/common/config/websocket/WebSocketConstant.java

@@ -25,6 +25,10 @@ public class WebSocketConstant {
      */
     public static final String PATIENT_MONITOR="patient-monitor";
 
+    /**
+     * his脚本连接通道
+     */
+    public static final String HIS_CONNECTION ="his-connection";
     /**
      * 主题格式为 device-info-detail:default:45789215623:医院id
      *             alarm-count:default:电量不足:医院id

+ 4 - 0
coffee-common/src/main/java/com/coffee/common/config/websocket/handler/Subscribe.java

@@ -1,6 +1,7 @@
 package com.coffee.common.config.websocket.handler;
 
 import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.StrUtil;
 import com.coffee.common.Constants;
 import com.coffee.common.bo.LoginUser;
 import com.coffee.common.config.websocket.DefaultMessageListener;
@@ -136,6 +137,9 @@ public abstract class Subscribe implements WsHandler {
      * @param topic
      */
     public void unsubscribe(ChannelContext channelContext, String topic){
+        if(StrUtil.isEmpty(topic)){
+            return;
+        }
         Object result = Optional.ofNullable(channelContext.get(SUBSCRIBE_TOPIC)).orElse(new HashSet<>());
         Set<String> subscribeTopicSet= (Set<String>) result;
         subscribeTopicSet.remove(topic);

+ 36 - 1
coffee-framework/src/main/java/com/coffee/framework/config/WebAppMvcConfig.java

@@ -1,14 +1,24 @@
 package com.coffee.framework.config;
 
 import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.StrUtil;
 import com.coffee.common.config.BooleanToIntegerSerializer;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationContext;
 import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
+import com.fasterxml.jackson.databind.deser.std.StringDeserializer;
 import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.ser.std.StringSerializer;
 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import org.python.antlr.ast.Str;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Profile;
+import org.springframework.format.Formatter;
+import org.springframework.format.FormatterRegistry;
 import org.springframework.http.converter.HttpMessageConverter;
 import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
 import org.springframework.web.servlet.HandlerInterceptor;
@@ -16,6 +26,8 @@ import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
 import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
+import java.io.IOException;
+import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.*;
  
@@ -41,6 +53,17 @@ public class WebAppMvcConfig implements WebMvcConfigurer {
         SimpleModule booleanSimpleModule = new SimpleModule();
         booleanSimpleModule.addSerializer(Boolean.class, new BooleanToIntegerSerializer());
         booleanSimpleModule.addSerializer(Boolean.TYPE, new BooleanToIntegerSerializer());
+
+        SimpleModule stringModule = new SimpleModule();
+        stringModule.addSerializer(String.class,new StringSerializer());
+        stringModule.addDeserializer(String.class, new StdScalarDeserializer<String>(String.class) {
+            @Override
+            public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
+                String text = p.getText();
+                return StrUtil.isBlankIfStr(text)?null:text;
+            }
+        });
+        objectMapper.registerModule(stringModule);
         objectMapper.registerModule(booleanSimpleModule);
         // 设置格式化内容
         converter.setObjectMapper(objectMapper);
@@ -74,6 +97,18 @@ public class WebAppMvcConfig implements WebMvcConfigurer {
     }
 
 
+    @Override
+    public void addFormatters(FormatterRegistry registry) {
+        registry.addFormatterForFieldType(String.class, new Formatter<String>() {
+            @Override
+            public String parse(String text, Locale locale) throws ParseException {
+                return StrUtil.isBlankIfStr(text)?null:text;
+            }
 
-
+            @Override
+            public String print(String object, Locale locale) {
+                return object;
+            }
+        });
+    }
 }

+ 5 - 0
coffee-system/src/main/java/com/coffee/bus/controller/BusPatientController.java

@@ -18,6 +18,7 @@ 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.exception.CustomException;
@@ -54,6 +55,8 @@ public class BusPatientController  implements BaseQueryController<BusPatientEnti
     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】")
@@ -130,6 +133,7 @@ public class BusPatientController  implements BaseQueryController<BusPatientEnti
             throw new CustomException("请选择一个病患");
         }
         List<PatientOperator<PatientCacheInfo>> patientOperators = patientCodes.stream().map(code -> patientRegistry.getOperator(tenantId, code)).collect(Collectors.toList());
+
         //重复设备
         Optional<PatientOperator<PatientCacheInfo>> existRepeatDevice = patientOperators.stream()
                 .filter(patientOperator -> {
@@ -184,6 +188,7 @@ public class BusPatientController  implements BaseQueryController<BusPatientEnti
     @ApiOperation(value = "主泵切换的操作,只切换,不结束",notes = "当出现泵重复状态时,若用户想要进行主泵的切换,调用该接口进行操作,主泵切换完成后,会将副泵自动撤泵,权限标识为【device:patient:shift】")
     public R shift(@RequestBody DeviceShiftConfig shiftConfig){
         deviceRunningService.shift(shiftConfig);
+        wsPublishUtils.publishPatientMonitor(shiftConfig.getPatientCode(),shiftConfig.getTenantId());
         return R.success();
     }
 

+ 3 - 0
coffee-system/src/main/java/com/coffee/bus/entity/BusHospitalEntity.java

@@ -73,6 +73,9 @@ public class BusHospitalEntity implements RecordModifierEntity, RecordCreationEn
     @TableField(typeHandler = FastjsonTypeHandler.class)
     private Script script;
 
+    @ApiModelProperty("医院脚本是否在线")
+    private Boolean scriptOnline;
+
     @ApiModelProperty("设备数量")
     private Integer deviceCount;
 

+ 20 - 0
coffee-system/src/main/java/com/coffee/bus/his/HisScriptSession.java

@@ -0,0 +1,20 @@
+package com.coffee.bus.his;
+
+import org.tio.core.ChannelContext;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName HisSession.java
+ * @Description his脚本会话
+ * @createTime 2022年05月13日 17:30:00
+ */
+public class HisScriptSession {
+    private ChannelContext channelContext;
+
+    //同步拉取病人信息
+
+    //异步拉取病人信息
+
+    //处理临床数据
+}

+ 28 - 0
coffee-system/src/main/java/com/coffee/bus/his/HisScriptSessionManager.java

@@ -0,0 +1,28 @@
+package com.coffee.bus.his;
+
+import org.springframework.stereotype.Component;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName HisScriptConnectionManager.java
+ * @Description his脚本管理
+ * @createTime 2022年05月13日 16:10:00
+ */
+@Component
+public class HisScriptSessionManager {
+    //获取会话
+    public HisScriptSession get(String hospital){
+        return null;
+    };
+
+    //注册会话
+    public HisScriptSession register(String hospital){
+        return null;
+    }
+
+    //注销会话
+    public HisScriptSession unregister(String hospitalId){
+        return null;
+    }
+}

+ 11 - 4
coffee-system/src/main/java/com/coffee/bus/registry/patient/ClusterPatientRegistry.java

@@ -16,15 +16,14 @@ import com.coffee.bus.service.LocalBusDeviceRunningService;
 import com.coffee.bus.service.LocalBusInfusionHistoryService;
 import com.coffee.bus.service.LocalBusPatientService;
 import com.coffee.common.cache.manager.ClusterConfigStorageManager;
+import com.coffee.common.cache.value.Value;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.dao.DuplicateKeyException;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
+import java.util.*;
 import java.util.stream.Collectors;
 
 
@@ -44,9 +43,16 @@ public class ClusterPatientRegistry implements PatientRegistry {
     private final LocalBusClinicService clinicService;
     private final LocalBusInfusionHistoryService infusionService;
     private final LocalBusDeviceRunningService deviceRunningService;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public PatientOperator<PatientCacheInfo> getOperator(String hospitalId, String patientCode){
+        return this.getOperator(hospitalId,patientCode,new HashMap<>());
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public PatientOperator<PatientCacheInfo> getOperator(String hospitalId, String patientCode) {
+    public PatientOperator<PatientCacheInfo> getOperator(String hospitalId, String patientCode, Map<String, Object> params) {
         if(StrUtil.isEmpty(hospitalId)||StrUtil.isEmpty(patientCode)){
             return null;
         }
@@ -66,6 +72,7 @@ public class ClusterPatientRegistry implements PatientRegistry {
                 clinic.setPatientCode(patientCode);
                 clinic.setTenantId(hospitalId);
                 clinic.setMonitorType(true);
+                clinic.setMonitorStartTime(Value.simple(params.get("startTime")).asDate());
                 //当用户不存在时,创建用户,并给与用户一个空的临床信息
                 insert=true;
                 patient=new BusPatientEntity();

+ 6 - 0
coffee-system/src/main/java/com/coffee/bus/registry/patient/PatientRegistry.java

@@ -2,6 +2,9 @@ package com.coffee.bus.registry.patient;
 
 import com.coffee.bus.registry.Registry;
 import com.coffee.bus.registry.patient.bean.PatientCacheInfo;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Map;
 
 /**
  * @author lifang
@@ -19,6 +22,9 @@ public interface PatientRegistry extends Registry {
      */
     PatientOperator<PatientCacheInfo> getOperator(String hospitalId, String patientCode);
 
+
+    PatientOperator<PatientCacheInfo> getOperator(String hospitalId, String patientCode, Map<String, Object> params);
+
     /**
      * 删除病人信息
      * @param hospitalId

+ 5 - 0
coffee-system/src/main/java/com/coffee/bus/service/LocalBusClinicService.java

@@ -19,6 +19,7 @@ import com.coffee.bus.service.dto.ClinicQuery;
 import com.coffee.bus.service.dto.ClinicResult;
 import com.coffee.bus.service.dto.ClinicStatsQueryResult;
 import com.coffee.bus.service.dto.ClinicStatsReturnResult;
+import com.coffee.bus.utils.WsPublishUtils;
 import com.coffee.common.crud.BaseService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -53,6 +54,9 @@ public class LocalBusClinicService extends BaseService<BusClinicMapper, BusClini
     @Autowired
     @Lazy
     private LocalBusPatientService patientService;
+    @Autowired
+    @Lazy
+    private WsPublishUtils wsPublishUtils;
     @Override
     public void validateBeforeSave(BusClinicEntity entity) {
 
@@ -206,6 +210,7 @@ public class LocalBusClinicService extends BaseService<BusClinicMapper, BusClini
 
         PatientOperator<PatientCacheInfo> operator = patientRegistry.getOperator(source.getTenantId(), source.getPatientCode());
         operator.setClinicId(source.getId());
+        wsPublishUtils.publishPatientMonitor(source.getPatientCode(),source.getTenantId());
     }
     /**
      * 从his同步病人数据-异步

+ 4 - 11
coffee-system/src/main/java/com/coffee/bus/service/LocalBusDeviceRunningService.java

@@ -17,6 +17,7 @@ import com.coffee.bus.entity.BusClinicEntity;
 import com.coffee.bus.entity.BusDeviceRunningEntity;
 import com.coffee.bus.entity.BusInfusionHistoryEntity;
 import com.coffee.bus.mapper.BusDeviceRunningMapper;
+import com.coffee.bus.utils.WsPublishUtils;
 import com.coffee.common.crud.BaseService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Lazy;
@@ -51,6 +52,9 @@ public class LocalBusDeviceRunningService extends BaseService<BusDeviceRunningMa
     @Lazy
     private DeviceRegistry deviceRegistry;
 
+    @Autowired
+    @Lazy
+    private WsPublishUtils wsPublishUtils;
     @Override
     public void validateBeforeSave(BusDeviceRunningEntity entity) {
 
@@ -126,17 +130,6 @@ public class LocalBusDeviceRunningService extends BaseService<BusDeviceRunningMa
 
     }
 
-    @Transactional(rollbackFor = Exception.class)
-    public void updateClinicInfo(List<String> deviceIds, BusClinicEntity clinic) {
-        this.update(new UpdateWrapper<BusDeviceRunningEntity>().lambda()
-                .in(BusDeviceRunningEntity::getDeviceId,deviceIds)
-                .set(BusDeviceRunningEntity::getClinicId,clinic.getId())
-                .set(BusDeviceRunningEntity::getPatientName,clinic.getPatientName())
-                .set(BusDeviceRunningEntity::getWard,clinic.getWard())
-                .set(BusDeviceRunningEntity::getPatientSex,clinic.getPatientGender())
-                .set(BusDeviceRunningEntity::getBedNo,clinic.getBedNo()));
-    }
-
     /**
      * 切换主泵
      * @param shiftConfig 切换配置

+ 1 - 0
coffee-system/src/main/java/com/coffee/bus/service/dto/DeviceResult.java

@@ -21,6 +21,7 @@ import java.util.Date;
 @Data
 @ApiModel("设备查询结果")
 public class DeviceResult {
+    private String id;
     @ApiModelProperty(value = "设备唯一id")
     private String deviceId;
 

+ 45 - 0
coffee-system/src/main/java/com/coffee/bus/websocket/HisConnectionHandler.java

@@ -0,0 +1,45 @@
+package com.coffee.bus.websocket;
+
+import com.coffee.bus.service.LocalBusHospitalService;
+import com.coffee.common.config.websocket.MessagingRequest;
+import com.coffee.common.config.websocket.WebSocketConstant;
+import com.coffee.common.config.websocket.handler.Subscribe;
+import lombok.AllArgsConstructor;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+import org.tio.core.ChannelContext;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName DeviceRepeatHandler.java
+ * @Description his脚本连接通道
+ * @createTime 2022年03月25日 14:21:00
+ */
+@Component
+@AllArgsConstructor
+public class HisConnectionHandler extends Subscribe {
+    private final RedisTemplate redisTemplate;
+    private final LocalBusHospitalService hospitalService;
+    @Override
+    public String getId() {
+        return WebSocketConstant.HIS_CONNECTION;
+    }
+
+    @Override
+    public void onMessage(MessagingRequest message, ChannelContext channelContext) {
+        //医院his脚本逻辑单独处理
+        String tenantId = message.getTenantId();
+
+    }
+
+    @Override
+    public void close(ChannelContext channelContext) {
+
+    }
+
+    @Override
+    public boolean needParam() {
+        return false;
+    }
+}

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

@@ -1,6 +1,7 @@
 package com.coffee.bus.websocket.listener;
 
 import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.map.MapUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.crypto.SignUtil;
@@ -268,7 +269,6 @@ public class DeviceInfoListener {
                 log.warn("病号:【{}】临床发生无泵报警",patientCode);
                 patientService.update(new UpdateWrapper<BusPatientEntity>().lambda().eq(BusPatientEntity::getCode,patientCode)
                                 .eq(BusPatientEntity::getTenantId,hospitalId)
-//                        .set(BusPatientEntity::getInfusionId,null)
                                 .set(BusPatientEntity::getAlarm, PatientAlarmEnum.DEVICE_NONE)
                 );
                 suppliers.add(()->{
@@ -332,12 +332,12 @@ public class DeviceInfoListener {
         PatientOperator<PatientCacheInfo> patientOperator = patientRegistry.getOperator(device.getTenantId(), device.getPatientCode());
         String bindDeviceId = patientOperator.getBindDeviceId();
         if(!StrUtil.isNullOrUndefined(bindDeviceId)&&!deviceId.equals(bindDeviceId)){
-            //泵号发生改变,获取病号绑定的泵信息,判断绑定的泵开始时间,将开始时间稍后的泵设置为主泵 todo 发生病人绑定多个泵冲突
+            //泵号发生改变,获取病号绑定的泵信息,判断绑定的泵开始时间,将开始时间稍后的泵设置为主泵
             DeviceOperator<DeviceCacheInfo> patientCurrentBindDevice = deviceRegistry.getOperator(bindDeviceId);
             Date startTime = patientCurrentBindDevice.getStartTime();
             if (startTime==null||startTime.before(device.getStartTime())) {
                 log.warn("病号:[{}],之前主泵为:[{}],现在主泵为:[{}]",device.getPatientCode(),bindDeviceId,deviceId);
-                //设置当前上传信息的泵为主泵,将旧泵设置为副泵,并更新病人绑定泵的消息 todo 更新缓存信息
+                //设置当前上传信息的泵为主泵,将旧泵设置为副泵,并更新病人绑定泵的消息
                 device.setMaster(true);
                 deviceRunningService.update(new UpdateWrapper<BusDeviceRunningEntity>().lambda().eq(BusDeviceRunningEntity::getDeviceId,bindDeviceId).set(BusDeviceRunningEntity::getMaster,false));
             }else {
@@ -350,7 +350,7 @@ public class DeviceInfoListener {
                     .set(Boolean.TRUE.equals(device.getMaster()),BusPatientEntity::getInfusionId,device.getInfusionId())
                     .set(BusPatientEntity::getAlarm,PatientAlarmEnum.DEVICE_REPEAT));
             suppliers.add(()->{
-                wsPublishUtils.publishDeviceRepeat(device.getPatientCode());
+                wsPublishUtils.publishDeviceRepeat(device.getTenantId());
                 return null;
             });
         }
@@ -394,7 +394,7 @@ public class DeviceInfoListener {
      * @param cacheOperation 缓存操作
      */
     private BusInfusionHistoryEntity handleInfusion(BusDeviceRunningEntity device, DeviceOperator<DeviceCacheInfo> deviceOperator, AtomicBoolean newInfusion, List<Supplier<?>> cacheOperation) {
-        PatientOperator<PatientCacheInfo> operator = patientRegistry.getOperator(device.getTenantId(), device.getPatientCode());
+        PatientOperator<PatientCacheInfo> operator = patientRegistry.getOperator(device.getTenantId(), device.getPatientCode(),MapUtil.of("startTime", device.getStartTime()));
         device.setClinicId(operator.getClinicId());
 
         BusInfusionHistoryEntity infusionHistory = handleInfusionHistory(device, deviceOperator, newInfusion, cacheOperation);

+ 2 - 0
coffee-system/src/main/resources/mapper/bus/BusDeviceMapper.xml

@@ -3,6 +3,7 @@
 <mapper namespace="com.coffee.bus.mapper.BusDeviceMapper">
 
     <resultMap id="pageQueryResult" type="com.coffee.bus.service.dto.DeviceResult">
+        <result column="id" property="id"/>
         <result column="device_id" property="deviceId"/>
         <result column="alias" property="alias"/>
         <result column="type" property="type"/>
@@ -34,6 +35,7 @@
 
     <select id="pageQuery" resultMap="pageQueryResult" parameterType="com.coffee.bus.service.dto.DeviceQuery">
         select
+        d.id as id,
         d.device_id as device_id,
         d.alias as alias,
         d.type as type,