Sfoglia il codice sorgente

Merge remote-tracking branch 'origin/dev' into zsl

15638522405 3 anni fa
parent
commit
5275e24a27
100 ha cambiato i file con 2045 aggiunte e 451 eliminazioni
  1. 4 4
      coffee-admin/src/main/resources/application-dev.yml
  2. 26 2
      coffee-admin/src/test/java/com/coffee/admin/BusClinicTest.java
  3. 36 0
      coffee-admin/src/test/java/com/coffee/admin/BusDeviceTest.java
  4. 2 2
      coffee-admin/src/test/java/com/coffee/admin/BusHospitalTest.java
  5. 1 3
      coffee-admin/src/test/java/com/coffee/admin/BusPatientTest.java
  6. 4 6
      coffee-admin/src/test/java/com/coffee/admin/HisStrategyTest.java
  7. 11 0
      coffee-common/pom.xml
  8. 16 29
      coffee-common/src/main/java/com/coffee/common/cache/ClusterConfigStorage.java
  9. 5 2
      coffee-common/src/main/java/com/coffee/common/cache/manager/ClusterConfigStorageManager.java
  10. 2 2
      coffee-common/src/main/java/com/coffee/common/config/CorsConfig.java
  11. 1 0
      coffee-common/src/main/java/com/coffee/common/config/mybatis/TenantNameHandler.java
  12. 4 1
      coffee-common/src/main/java/com/coffee/common/config/websocket/DefaultMessageListener.java
  13. 1 1
      coffee-common/src/main/java/com/coffee/common/config/websocket/MessageResponse.java
  14. 11 8
      coffee-common/src/main/java/com/coffee/common/config/websocket/handler/Subscribe.java
  15. 3 3
      coffee-common/src/main/java/com/coffee/common/entity/TenantGenericEntity.java
  16. 48 15
      coffee-common/src/main/java/com/coffee/common/util/RedissonUtil.java
  17. 16 12
      coffee-framework/src/main/java/com/coffee/framework/config/WebAppMvcConfig.java
  18. 1 1
      coffee-framework/src/main/java/com/coffee/framework/web/exception/GlobalExceptionHandler.java
  19. 2 1
      coffee-system/src/main/java/com/coffee/aliyun/AliyunConsumerGroupService.java
  20. 7 0
      coffee-system/src/main/java/com/coffee/aliyun/utils/Items.java
  21. 2 0
      coffee-system/src/main/java/com/coffee/bus/bean/Script.java
  22. 0 46
      coffee-system/src/main/java/com/coffee/bus/config/HospitalFunctionOtherConfigHandler.java
  23. 4 7
      coffee-system/src/main/java/com/coffee/bus/controller/BusAlarmController.java
  24. 8 5
      coffee-system/src/main/java/com/coffee/bus/controller/BusClinicController.java
  25. 17 0
      coffee-system/src/main/java/com/coffee/bus/controller/BusHospitalConfigController.java
  26. 55 6
      coffee-system/src/main/java/com/coffee/bus/controller/BusHospitalController.java
  27. 49 7
      coffee-system/src/main/java/com/coffee/bus/controller/BusPatientController.java
  28. 22 0
      coffee-system/src/main/java/com/coffee/bus/controller/vo/CauseVo.java
  29. 3 0
      coffee-system/src/main/java/com/coffee/bus/controller/vo/ClinicStatsVo.java
  30. 27 0
      coffee-system/src/main/java/com/coffee/bus/controller/vo/ExecScript.java
  31. 0 1
      coffee-system/src/main/java/com/coffee/bus/entity/BusDeviceAlarmEntity.java
  32. 4 8
      coffee-system/src/main/java/com/coffee/bus/entity/BusDeviceEntity.java
  33. 4 7
      coffee-system/src/main/java/com/coffee/bus/entity/BusDeviceHistoryEntity.java
  34. 12 0
      coffee-system/src/main/java/com/coffee/bus/entity/BusDeviceRunningEntity.java
  35. 1 8
      coffee-system/src/main/java/com/coffee/bus/entity/BusHospitalConfigEntity.java
  36. 9 38
      coffee-system/src/main/java/com/coffee/bus/entity/BusHospitalEntity.java
  37. 1 1
      coffee-system/src/main/java/com/coffee/bus/entity/BusInfusionHistoryEntity.java
  38. 1 0
      coffee-system/src/main/java/com/coffee/bus/entity/BusInfusionModifyEntity.java
  39. 12 0
      coffee-system/src/main/java/com/coffee/bus/enums/ConfigEnum.java
  40. 13 0
      coffee-system/src/main/java/com/coffee/bus/enums/PatientAlarmEnum.java
  41. 168 0
      coffee-system/src/main/java/com/coffee/bus/hospital/HospitalManager.java
  42. 88 0
      coffee-system/src/main/java/com/coffee/bus/hospital/HospitalManagerRegister.java
  43. 57 0
      coffee-system/src/main/java/com/coffee/bus/hospital/config/AbstractHospitalConfigHandler.java
  44. 154 0
      coffee-system/src/main/java/com/coffee/bus/hospital/config/HospitalAutoUndoConfigHandler.java
  45. 8 10
      coffee-system/src/main/java/com/coffee/bus/hospital/config/HospitalConfigHandler.java
  46. 169 0
      coffee-system/src/main/java/com/coffee/bus/hospital/config/HospitalFinishMonitorConfigHandler.java
  47. 217 0
      coffee-system/src/main/java/com/coffee/bus/hospital/config/HospitalFunctionAnalConfigHandler.java
  48. 220 0
      coffee-system/src/main/java/com/coffee/bus/hospital/config/HospitalFunctionExtraConfigHandler.java
  49. 4 2
      coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionAnalConfig.java
  50. 4 2
      coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionAutoUndoConfig.java
  51. 6 2
      coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionExtraConfig.java
  52. 28 0
      coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionFinishMonitorConfig.java
  53. 4 2
      coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionManualUndoConfig.java
  54. 5 3
      coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionOtherConfig.java
  55. 6 4
      coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionUndoConfig.java
  56. 22 0
      coffee-system/src/main/java/com/coffee/bus/hospital/enums/ConfigHandlerEnums.java
  57. 3 3
      coffee-system/src/main/java/com/coffee/bus/hospital/his/HisRequest.java
  58. 1 1
      coffee-system/src/main/java/com/coffee/bus/hospital/his/HisResponse.java
  59. 34 41
      coffee-system/src/main/java/com/coffee/bus/hospital/his/HisScriptSession.java
  60. 7 7
      coffee-system/src/main/java/com/coffee/bus/hospital/his/HisScriptSessionManager.java
  61. 15 1
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/HisStrategyEnum.java
  62. 1 1
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/HisStrategyHandler.java
  63. 1 1
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/HisStrategyManager.java
  64. 1 1
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/HisStrategyManagerRegister.java
  65. 1 4
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/all/EqualsStrategyHandler.java
  66. 2 2
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/all/HisAllStrategyHandler.java
  67. 3 3
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/all/HisAllStrategyManager.java
  68. 1 2
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/all/LessToMoreHisStrategyHandler.java
  69. 1 2
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/all/MoreToLessHisStrategyHandler.java
  70. 1 1
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/onlynew/DefaultHisNewStrategyHandler.java
  71. 2 2
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/onlynew/HisNewStrategyHandler.java
  72. 3 3
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/onlynew/HisNewStrategyManager.java
  73. 3 3
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/part/DefaultHisPartStrategyHandler.java
  74. 2 2
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/part/HisPartStrategyHandler.java
  75. 3 3
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/part/HisPartStrategyManager.java
  76. 1 3
      coffee-system/src/main/java/com/coffee/bus/hospital/script/DefaultParse.java
  77. 13 6
      coffee-system/src/main/java/com/coffee/bus/hospital/script/ExecuteResult.java
  78. 27 13
      coffee-system/src/main/java/com/coffee/bus/hospital/script/PythonParse.java
  79. 23 16
      coffee-system/src/main/java/com/coffee/bus/hospital/script/ScriptManager.java
  80. 1 3
      coffee-system/src/main/java/com/coffee/bus/hospital/script/ScriptParse.java
  81. 28 0
      coffee-system/src/main/java/com/coffee/bus/listener/event/bean/DeviceLifecycleEvent.java
  82. 4 0
      coffee-system/src/main/java/com/coffee/bus/mapper/BusPatientMapper.java
  83. 2 0
      coffee-system/src/main/java/com/coffee/bus/registry/constant/DeviceKeyConstant.java
  84. 12 2
      coffee-system/src/main/java/com/coffee/bus/registry/device/ClusterDeviceOperator.java
  85. 1 1
      coffee-system/src/main/java/com/coffee/bus/registry/device/ClusterDeviceRegistry.java
  86. 16 4
      coffee-system/src/main/java/com/coffee/bus/registry/device/DeviceOperator.java
  87. 0 3
      coffee-system/src/main/java/com/coffee/bus/registry/patient/ClusterPatientOperator.java
  88. 1 1
      coffee-system/src/main/java/com/coffee/bus/registry/patient/ClusterPatientRegistry.java
  89. 1 0
      coffee-system/src/main/java/com/coffee/bus/service/LocalBusClinicService.java
  90. 1 5
      coffee-system/src/main/java/com/coffee/bus/service/LocalBusDeviceRunningService.java
  91. 134 0
      coffee-system/src/main/java/com/coffee/bus/service/LocalBusHospitalConfigService.java
  92. 38 16
      coffee-system/src/main/java/com/coffee/bus/service/LocalBusHospitalService.java
  93. 26 14
      coffee-system/src/main/java/com/coffee/bus/service/LocalBusPatientService.java
  94. 4 4
      coffee-system/src/main/java/com/coffee/bus/service/dto/ClinicAnalRecordResult.java
  95. 3 0
      coffee-system/src/main/java/com/coffee/bus/service/dto/ClinicStatsReturnResult.java
  96. 3 1
      coffee-system/src/main/java/com/coffee/bus/service/dto/ManualUndoConfig.java
  97. 3 0
      coffee-system/src/main/java/com/coffee/bus/service/dto/PatientDeviceNoneResult.java
  98. 9 20
      coffee-system/src/main/java/com/coffee/bus/utils/WsPublishUtils.java
  99. 2 3
      coffee-system/src/main/java/com/coffee/bus/websocket/HisConnectionHandler.java
  100. 2 2
      coffee-system/src/main/java/com/coffee/bus/websocket/WebSocketCloseHandler.java

+ 4 - 4
coffee-admin/src/main/resources/application-dev.yml

@@ -88,14 +88,14 @@ spring:
     # 密码
     password: 6E6985E1F7CB40F24A\.
     # 连接超时时间
-    timeout: 10s
+    timeout: 30s
     lettuce:
       pool:
         # 连接池中的最小空闲连接
-        min-idle: 0
+        min-idle: 16
         # 连接池中的最大空闲连接
-        max-idle: 8
+        max-idle: 16
         # 连接池的最大数据库连接数
-        max-active: 8
+        max-active: 16
         # #连接池最大阻塞等待时间(使用负值表示没有限制)
         max-wait: -1ms

+ 26 - 2
coffee-admin/src/test/java/com/coffee/admin/BusClinicTest.java

@@ -1,5 +1,7 @@
 package com.coffee.admin;
 
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.json.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.coffee.bus.controller.vo.ClinicStatsVo;
 import com.coffee.bus.entity.BusDeviceRunningEntity;
@@ -8,8 +10,14 @@ import com.coffee.bus.listener.event.bean.DeviceInfoEvent;
 import com.coffee.bus.service.LocalBusClinicService;
 import com.coffee.bus.service.LocalBusInfusionHistoryService;
 import com.coffee.bus.service.dto.ClinicStatsReturnResult;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.redisson.api.RBlockingQueue;
+import org.redisson.api.RDelayedQueue;
+import org.redisson.api.RedissonClient;
+import org.redisson.codec.JsonJacksonCodec;
+import org.redisson.codec.TypedJsonJacksonCodec;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.context.ApplicationContext;
@@ -17,6 +25,7 @@ import org.springframework.test.context.junit4.SpringRunner;
 
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.TimeUnit;
 
 /**
  * @Author longsanlang
@@ -28,10 +37,12 @@ import java.util.Map;
 @SpringBootTest(classes = AdminApplication.class)
 public class BusClinicTest {
 
+    @Autowired
+    private RedissonClient redissonClient;
     @Autowired
     private LocalBusClinicService clinicService;
-
-
+    @Autowired
+    private ObjectMapper objectMapper;
     @Autowired
     private LocalBusInfusionHistoryService infusionHistoryService;
 
@@ -47,6 +58,19 @@ public class BusClinicTest {
         System.out.println(stats);
     }
 
+    @Test
+    public void redisson(){
+        RBlockingQueue<Object> blockingFairQueue = redissonClient.getBlockingQueue("delay_queue",new JsonJacksonCodec());
+        RDelayedQueue<Object> delayedQueue = redissonClient.getDelayedQueue(blockingFairQueue);
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.putOpt(DateUtil.now(),"1");
+        System.out.println(jsonObject);
+
+        delayedQueue.offerAsync(jsonObject,60, TimeUnit.SECONDS);
+        while (true){
+
+        }
+    }
 
     @Test
     public void save(){

+ 36 - 0
coffee-admin/src/test/java/com/coffee/admin/BusDeviceTest.java

@@ -1,7 +1,13 @@
 package com.coffee.admin;
 
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.coffee.bus.entity.BusDeviceEntity;
+import com.coffee.bus.entity.BusDeviceHistoryEntity;
+import com.coffee.bus.service.LocalBusDeviceHistoryService;
 import com.coffee.bus.service.LocalBusDeviceService;
+import com.coffee.bus.service.dto.ClinicAnalInfusionRecord;
+import lombok.extern.slf4j.Slf4j;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -18,12 +24,15 @@ import java.util.List;
  * @Description XXX
  */
 @RunWith(SpringRunner.class)
+@Slf4j
 @SpringBootTest(classes = AdminApplication.class)
 public class BusDeviceTest {
 
     @Autowired
     LocalBusDeviceService deviceService;
 
+    @Autowired
+    LocalBusDeviceHistoryService historyService;
     @Test
     public void test001(){
         BusDeviceEntity device = new BusDeviceEntity();
@@ -50,4 +59,31 @@ public class BusDeviceTest {
         deviceService.removeByDeviceId("nbceshi001");
     }
 
+
+    @Test
+    public void copy(){
+        Page<BusDeviceHistoryEntity> page = historyService.page(Page.of(0, 50));
+        List<BusDeviceHistoryEntity> records = page.getRecords();
+
+        for (int i = 0; i < 100; i++) {
+            long current = System.currentTimeMillis();
+            records.stream().forEach(record->{
+//            long start = System.currentTimeMillis();
+                BeanUtil.copyProperties(record, ClinicAnalInfusionRecord.class);
+//            System.out.println("BeanCopy耗时:" + (System.currentTimeMillis() - start));
+            });
+            System.out.println("BeanCopy单线程总耗时:" + (System.currentTimeMillis() - current));
+        }
+
+        for (int i = 0; i < 100; i++) {
+            long current1 = System.currentTimeMillis();
+            records.parallelStream().forEach(record->{
+//            long start = System.currentTimeMillis();
+                BeanUtil.copyProperties(record, ClinicAnalInfusionRecord.class);
+//            System.out.println("BeanCopy耗时:" + (System.currentTimeMillis() - start));
+            });
+            System.out.println("BeanCopy多线程总耗时:" + (System.currentTimeMillis() - current1));
+        }
+
+    }
 }

+ 2 - 2
coffee-admin/src/test/java/com/coffee/admin/BusHospitalTest.java

@@ -87,7 +87,7 @@ public class BusHospitalTest {
 
     @Test
     public void debug(){
-        R debug = busHospitalController.debug("1505789859765604353", "{\"ceshi\":\"测试\" , \"age\":\"20\" }");
-        System.out.println(debug);
+//        R debug = busHospitalController.debug("1505789859765604353", "{\"ceshi\":\"测试\" , \"age\":\"20\" }");
+//        System.out.println(debug);
     }
 }

+ 1 - 3
coffee-admin/src/test/java/com/coffee/admin/BusPatientTest.java

@@ -11,13 +11,11 @@ import com.coffee.bus.entity.BusClinicEntity;
 import com.coffee.bus.entity.BusDeviceManualEntity;
 import com.coffee.bus.entity.BusPatientEntity;
 import com.coffee.bus.enums.DeviceManualEnum;
-import com.coffee.bus.his.strategy.all.EqualsStrategyHandler;
-import com.coffee.bus.his.strategy.all.HisAllStrategyHandler;
+import com.coffee.bus.hospital.his.strategy.all.EqualsStrategyHandler;
 import com.coffee.bus.service.LocalBusClinicService;
 import com.coffee.bus.service.LocalBusPatientService;
 import com.coffee.bus.service.dto.PatientDeviceRepeatResult;
 import com.coffee.common.enums.SexEnum;
-import org.hibernate.validator.constraints.Length;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;

+ 4 - 6
coffee-admin/src/test/java/com/coffee/admin/HisStrategyTest.java

@@ -6,13 +6,11 @@ import cn.hutool.core.util.EnumUtil;
 import cn.hutool.core.util.RandomUtil;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.coffee.bus.entity.BusClinicEntity;
-import com.coffee.bus.entity.BusDeviceEntity;
-import com.coffee.bus.his.strategy.HisStrategyEnum;
-import com.coffee.bus.his.strategy.HisStrategyHandler;
-import com.coffee.bus.his.strategy.HisStrategyManager;
-import com.coffee.bus.his.strategy.HisStrategyManagerRegister;
+import com.coffee.bus.hospital.his.strategy.HisStrategyEnum;
+import com.coffee.bus.hospital.his.strategy.HisStrategyHandler;
+import com.coffee.bus.hospital.his.strategy.HisStrategyManager;
+import com.coffee.bus.hospital.his.strategy.HisStrategyManagerRegister;
 import com.coffee.bus.service.LocalBusClinicService;
-import com.coffee.bus.service.LocalBusDeviceService;
 import com.coffee.common.enums.SexEnum;
 import org.junit.Test;
 import org.junit.runner.RunWith;

+ 11 - 0
coffee-common/pom.xml

@@ -116,5 +116,16 @@
             <groupId>jakarta.websocket</groupId>
             <artifactId>jakarta.websocket-api</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.redisson</groupId>
+            <artifactId>redisson-spring-boot-starter</artifactId>
+            <optional>true</optional>
+            <scope>compile</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.jboss.marshalling</groupId>
+            <artifactId>jboss-marshalling</artifactId>
+        </dependency>
     </dependencies>
 </project>

+ 16 - 29
coffee-common/src/main/java/com/coffee/common/cache/ClusterConfigStorage.java

@@ -1,12 +1,9 @@
 package com.coffee.common.cache;
 
-import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.extra.spring.SpringUtil;
 import com.baomidou.mybatisplus.annotation.IEnum;
 import com.coffee.common.cache.value.Value;
-import org.redisson.api.RMap;
-import org.redisson.api.RedissonClient;
 import org.springframework.cache.Cache;
 import org.springframework.cache.CacheManager;
 import org.springframework.data.redis.core.BoundHashOperations;
@@ -20,9 +17,9 @@ import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
 public class ClusterConfigStorage implements ConfigStorage {
-    private final RMap<String, Object>  cacheMap;
-    public ClusterConfigStorage(RedissonClient redissonClient,String name){
-        cacheMap = SpringUtil.getBean(RedissonClient.class).getMap(name);
+    private  BoundHashOperations boundHashOperations;
+    public ClusterConfigStorage(RedisTemplate redisTemplate,String name){
+        boundHashOperations = redisTemplate.opsForSet().getOperations().boundHashOps(name);
     }
 
     @Override
@@ -30,8 +27,7 @@ public class ClusterConfigStorage implements ConfigStorage {
         if (StrUtil.isEmpty(key)) {
             return null;
         }
-//        return Value.simple(boundHashOperations.get(key));
-        return Value.simple(cacheMap.get(key));
+        return Value.simple(boundHashOperations.get(key));
     }
 
     @Override
@@ -47,8 +43,7 @@ public class ClusterConfigStorage implements ConfigStorage {
                 map.put(k,v);
             }
         });
-//        boundHashOperations.putAll(map);
-        cacheMap.putAll(map);
+        boundHashOperations.putAll(map);
         return true;
     }
 
@@ -58,55 +53,47 @@ public class ClusterConfigStorage implements ConfigStorage {
             return true;
         }
         if(value==null){
-            cacheMap.remove(key);
-//            boundHashOperations.delete(key);
+            boundHashOperations.delete(key);
         }else {
             if(value instanceof IEnum){
                 value=((IEnum) value).getValue();
             }
-//            boundHashOperations.put(key,value);
-            cacheMap.put(key,value);
+            boundHashOperations.put(key,value);
         }
         return true;
     }
 
     @Override
     public Value getAndRemove(String key) {
-//        Value value = Value.simple(boundHashOperations.get(key));
-//        boundHashOperations.delete(key);
-
-        return      Value.simple(cacheMap.remove(key));
+        Value value = Value.simple(boundHashOperations.get(key));
+        boundHashOperations.delete(key);
+        return value;
     }
 
     @Override
     public Boolean remove(String key) {
-//        boundHashOperations.delete(key);
-        cacheMap.remove(key);
+        boundHashOperations.delete(key);
         return true;
     }
 
     @Override
     public Boolean remove(Collection<String> key) {
-//        boundHashOperations.delete(key);
-        cacheMap.fastRemove(key.toArray(new String[CollectionUtil.size(key)]));
+        boundHashOperations.delete(key);
         return true;
     }
 
     @Override
     public Boolean clear() {
-//        boundHashOperations.delete(boundHashOperations.keys());
-        cacheMap.readAllMap();
+        boundHashOperations.delete(boundHashOperations.keys());
         return true;
     }
 
     @Override
     public Map<String, Value> getKeys(Collection<String> keys) {
         Map<String, Value> result = new HashMap<>();
-        Map<String, Object> map = cacheMap.readAllMap();
-//        keys.parallelStream().forEach(key->{
-//            result.put(key,getConfig(key));
-//        });
-        map.forEach((k,v)->result.put(k,Value.simple(v)));
+        keys.parallelStream().forEach(key->{
+            result.put(key,getConfig(key));
+        });
         return result;
     }
 }

+ 5 - 2
coffee-common/src/main/java/com/coffee/common/cache/manager/ClusterConfigStorageManager.java

@@ -23,16 +23,19 @@ public class ClusterConfigStorageManager implements ConfigStorageManager {
 
     private final RedissonClient redissonClient;
 
+    private final RedisTemplate redisTemplate;
+
 
     private Map<String,ClusterConfigStorage > storageMap=new ConcurrentHashMap<>();
 
-    public ClusterConfigStorageManager(RedissonClient redissonClient) {
+    public ClusterConfigStorageManager(RedissonClient redissonClient,RedisTemplate redisTemplate) {
         this.redissonClient = redissonClient;
+        this.redisTemplate=redisTemplate;
     }
 
     @Override
     public ConfigStorage getStorage(String id) {
-        return  storageMap.computeIfAbsent(id, __ -> new ClusterConfigStorage(redissonClient,id));
+        return  storageMap.computeIfAbsent(id, __ -> new ClusterConfigStorage(redisTemplate,id));
     }
 
 }

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

@@ -23,8 +23,8 @@ public class CorsConfig implements WebMvcConfigurer {
                 .allowedOriginPatterns("*")
                 .allowedOrigins("*")
                 //放行哪些请求方式
-//                .allowedMethods(new String[]{"GET", "POST", "PUT", "DELETE"})
-                .allowedMethods("*") //或者放行全部
+                .allowedMethods(new String[]{"GET", "POST", "PUT"})
+//                .allowedMethods("*") //或者放行全部
                 //放行哪些原始请求头部信息
                 .allowedHeaders("*")
                 //暴露哪些原始请求头部信息

+ 1 - 0
coffee-common/src/main/java/com/coffee/common/config/mybatis/TenantNameHandler.java

@@ -24,6 +24,7 @@ public class TenantNameHandler implements TypeHandler<String> {
 
     private GetNameInterface<String,String> getHospitalName;
 
+
     @Override
     public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) {
 

+ 4 - 1
coffee-common/src/main/java/com/coffee/common/config/websocket/DefaultMessageListener.java

@@ -7,6 +7,8 @@ import lombok.Data;
 import lombok.extern.slf4j.Slf4j;
 import org.redisson.api.RPatternTopic;
 import org.redisson.api.listener.PatternMessageListener;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
 import org.tio.core.ChannelContext;
 import org.tio.core.Tio;
 import org.tio.core.utils.TioUtils;
@@ -35,12 +37,13 @@ public class DefaultMessageListener implements PatternMessageListener<TopicMessa
             String json = null;
             try {
                 json = objectMapper.writeValueAsString(MessageResponse.of(id, "result", msg.getParam(),
-                        JSONUtil.parse(objectMapper.writeValueAsString(msg.getMessage()))));
+                        msg.getMessage()));
                 Tio.send(channelContext, WsResponse.fromText(json, WsPacket.CHARSET_NAME));
             } catch (JsonProcessingException e) {
                 log.error("ws消息订阅,解析失败,message:【】", JSONUtil.toJsonStr(msg));
             }
         }else {
+            channelContext.setClosed(true);
             rPatternTopic.removeListener(this);
         }
     }

+ 1 - 1
coffee-common/src/main/java/com/coffee/common/config/websocket/MessageResponse.java

@@ -19,5 +19,5 @@ public class MessageResponse implements Serializable {
     private String id;
     private String type;
     private String param;
-    private JSON payload;
+    private Object payload;
 }

+ 11 - 8
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;
@@ -96,13 +97,15 @@ public abstract class Subscribe implements WsHandler {
      * @param topic
      */
     public void unsubscribe(ChannelContext channelContext, String topic){
-//        if(StrUtil.isEmpty(topic)){
-//            return;
-//        }
-//        topicMap.computeIfPresent(topic,(k,rTopic)->{
-//            rTopic.removeListener( getTopicListener(channelContext,k));
-//            return rTopic;
-//        });
+        if(StrUtil.isEmpty(topic)){
+            return;
+        }
+        topicMap.computeIfPresent(topic,(k,rTopic)->{
+            rTopic.removeListener( getTopicListener(channelContext,k));
+            return rTopic;
+        });
+        Map<String, DefaultMessageListener> topicListeners = getTopicListeners(channelContext);
+        topicListeners.remove(topic);
     };
 
 
@@ -121,7 +124,7 @@ public abstract class Subscribe implements WsHandler {
         Map<String, DefaultMessageListener> topicByChannel = getTopicListeners(channelContext);
         DefaultMessageListener messageListener = topicByChannel.computeIfAbsent(topic, k -> {
             DefaultMessageListener defaultMessageListener = new DefaultMessageListener(getId(), objectMapper, channelContext,rTopic);
-            rTopic.addListener(TopicMessage.class, defaultMessageListener);
+            rTopic.addListenerAsync(TopicMessage.class, defaultMessageListener);
             return defaultMessageListener;
         });
         return  messageListener;

+ 3 - 3
coffee-common/src/main/java/com/coffee/common/entity/TenantGenericEntity.java

@@ -28,7 +28,7 @@ public abstract class TenantGenericEntity<PK,TN> extends GenericEntity<PK> {
     @JsonSerialize(using = ToStringSerializer.class)
     private TN tenantId;
 
-    @Getter
-    @TableField(value = "tenant_id",insertStrategy = FieldStrategy.NEVER,updateStrategy = FieldStrategy.NEVER,typeHandler = TenantNameHandler.class)
-    private String tenantName;
+//    @Getter
+//    @TableField(value = "tenant_id",insertStrategy = FieldStrategy.NEVER,updateStrategy = FieldStrategy.NEVER,typeHandler = TenantNameHandler.class)
+//    private String tenantName;
 }

+ 48 - 15
coffee-common/src/main/java/com/coffee/common/util/RedissonUtil.java

@@ -1,16 +1,17 @@
 package com.coffee.common.util;
 
-import cn.hutool.json.JSONUtil;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.redisson.api.RPatternTopic;
-import org.redisson.api.RTopic;
-import org.redisson.api.RedissonClient;
+
+import io.netty.channel.DefaultEventLoop;
+import io.netty.channel.EventLoopGroup;
+import lombok.Getter;
+import org.redisson.api.*;
 import org.redisson.client.codec.Codec;
-import org.redisson.codec.JsonJacksonCodec;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
-
-import javax.annotation.PostConstruct;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
 
 /**
  * @author lifang
@@ -21,16 +22,17 @@ import javax.annotation.PostConstruct;
  */
 @Component
 public class RedissonUtil {
+
     @Autowired
+    @Getter
     private RedissonClient redissonClient;
-    @Autowired
-    private ObjectMapper objectMapper;
-    private JsonJacksonCodec jsonObjectCodec;
 
-    @PostConstruct
-    public void init(){
-        jsonObjectCodec=new JsonJacksonCodec(objectMapper);
-    }
+    private static Map<String,RDelayedQueue<Object>> delayedQueueMap=new ConcurrentHashMap<>();
+
+    private static Map<String,RBlockingDeque<Object>> blockingDequeMap=new ConcurrentHashMap<>();
+
+    private static Map<String,RLock> lockMap=new ConcurrentHashMap<>();
+    private EventLoopGroup eventLoopGroup=new DefaultEventLoop();
 
     public RPatternTopic getPatternTopic(String pattern){
         return redissonClient.getPatternTopic(pattern);
@@ -43,4 +45,35 @@ public class RedissonUtil {
     public RTopic getTopic(String pattern, Codec codec){
         return redissonClient.getTopic(pattern,codec);
     }
+
+    public RDelayedQueue getDelayedQueue(String name, Consumer<Object> consumer){
+        name="queue:"+name;
+        synchronized (name){
+            if(!blockingDequeMap.containsKey(name)){
+                String lockName="lock:"+name;
+                RBlockingDeque<Object> value = redissonClient.getBlockingDeque(name);
+                delayedQueueMap.putIfAbsent(name,redissonClient.getDelayedQueue(value));
+                lockMap.putIfAbsent(lockName,redissonClient.getLock(lockName));
+                value.subscribeOnElements(i->{
+                    //开启新的线程消费,唯一线程消费,不可阻塞该异步线程
+                    eventLoopGroup.submit(() -> {
+                        RLock lock = lockMap.get(lockName);
+                        try {
+                            if (lock.tryLock(-1,20,TimeUnit.SECONDS)) {
+                                try {
+                                    consumer.accept(i);
+                                    value.popAsync();
+                                }finally {
+                                    lock.unlockAsync();
+                                }
+                            }
+                        } catch (InterruptedException e) {
+                            e.printStackTrace();
+                        }
+                    });
+                });
+            }
+            return delayedQueueMap.get(name);
+        }
+    }
 }

+ 16 - 12
coffee-framework/src/main/java/com/coffee/framework/config/WebAppMvcConfig.java

@@ -3,20 +3,15 @@ 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.JsonGenerator;
 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.*;
 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;
@@ -30,7 +25,7 @@ import java.io.IOException;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.*;
- 
+
 /**
  * @Description TODO
  * @Classname Knife4jWebMvcConfig
@@ -40,13 +35,22 @@ import java.util.*;
 @Configuration
 //@Profile("dev")
 public class WebAppMvcConfig implements WebMvcConfigurer {
+    @Autowired
+    private ObjectMapper objectMapper;
     @Autowired
     private List<HandlerInterceptor> interceptors;
     @Override
     public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
         MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
-        ObjectMapper objectMapper = converter.getObjectMapper();
+//        ObjectMapper objectMapper = converter.getObjectMapper();
         // 时间格式化
+        SerializerProvider serializerProvider = objectMapper.getSerializerProvider();
+        serializerProvider.setNullValueSerializer(new JsonSerializer<Object>() {
+            @Override
+            public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
+                gen.writeNull();
+            }
+        });
         objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
         objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
 
@@ -72,13 +76,13 @@ public class WebAppMvcConfig implements WebMvcConfigurer {
 
     @Override
     public void addResourceHandlers(ResourceHandlerRegistry registry) {
- 
+
         registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
- 
+
         /** 配置knife4j 显示文档 */
         registry.addResourceHandler("doc.html")
                 .addResourceLocations("classpath:/META-INF/resources/");
- 
+
         /**
          * 配置swagger-ui显示文档
          */

+ 1 - 1
coffee-framework/src/main/java/com/coffee/framework/web/exception/GlobalExceptionHandler.java

@@ -39,7 +39,7 @@ public class GlobalExceptionHandler {
     @ExceptionHandler(NotLoginException.class)
     public R handleNotLoginException(NotLoginException e) {
         log.error(e.getMessage(), e);
-        return R.result(ResultCode.UN_AUTHORIZED);
+        return R.result(ResultCode.TOKEN_ERROR);
     }
 
     @ExceptionHandler(NotRoleException.class)

+ 2 - 1
coffee-system/src/main/java/com/coffee/aliyun/AliyunConsumerGroupService.java

@@ -169,9 +169,10 @@ public class AliyunConsumerGroupService {
                     // 创建设备
                     BusDeviceEntity device = new BusDeviceEntity();
                     device.setDeviceId(deviceName);
+                    device.setCreateTime(now);
                     device.setCreateBy(Constants.DefaultCreateBy);
-                    device.setUpdateBy(Constants.DefaultUpdateBy);
                     device.setUpdateTime(now);
+                    device.setUpdateBy(Constants.DefaultUpdateBy);
                     device.setTenantId(Constants.DefaultHospital);
 
                     // 配置信息

+ 7 - 0
coffee-system/src/main/java/com/coffee/aliyun/utils/Items.java

@@ -5,6 +5,7 @@ import lombok.AllArgsConstructor;
 import lombok.Data;
 
 import java.math.BigDecimal;
+import java.util.Date;
 
 /**
  * @Author 龙三郎
@@ -15,6 +16,7 @@ import java.math.BigDecimal;
 @AllArgsConstructor
 public class Items {
     public static final String VALUE = "value";
+    public static final String TIME = "time";
 
     private JSONObject items;
 
@@ -26,6 +28,11 @@ public class Items {
         return items.getJSONObject(param.getParam()).getInteger(VALUE);
     }
 
+    public Date getDate(){
+        long time = items.getJSONObject(PumpParams.patientCode.getParam()).getLong(TIME);
+        return new Date(time);
+    }
+
     public BigDecimal getBigDecimal(PumpParams param){
         return items.getJSONObject(param.getParam()).getBigDecimal(VALUE);
     }

+ 2 - 0
coffee-system/src/main/java/com/coffee/bus/bean/Script.java

@@ -1,5 +1,6 @@
 package com.coffee.bus.bean;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import lombok.Data;
 
 import java.io.Serializable;
@@ -13,6 +14,7 @@ import java.io.Serializable;
  */
 @Data
 public class Script implements Serializable {
+    @JsonIgnore
     private String id;
     private String content;
     /**

+ 0 - 46
coffee-system/src/main/java/com/coffee/bus/config/HospitalFunctionOtherConfigHandler.java

@@ -1,46 +0,0 @@
-package com.coffee.bus.config;
-
-import cn.hutool.json.JSONUtil;
-import com.coffee.bus.entity.BusDeviceRunningEntity;
-import com.coffee.bus.enums.ConfigEnum;
-import com.coffee.bus.service.dto.function.FunctionOtherConfig;
-import com.coffee.common.cache.ClusterConfigStorage;
-
-import org.redisson.api.RedissonClient;
-import org.springframework.data.redis.core.RedisTemplate;
-
-import java.util.Map;
-
-/**
- * @author lifang
- * @version 1.0.0
- * @ClassName HospitalFunctionOtherConfigHandler.java
- * @Description 其他配置
- * @createTime 2022年05月18日 11:25:00
- */
-public class HospitalFunctionOtherConfigHandler extends ClusterConfigStorage implements HospitalConfigHandler<BusDeviceRunningEntity> {
-
-    public HospitalFunctionOtherConfigHandler(RedissonClient redissonClient, String name) {
-        super(redissonClient, name);
-    }
-
-    @Override
-    public ConfigEnum getType() {
-        return ConfigEnum.other;
-    }
-
-    @Override
-    public String getDescription() {
-        return "进行镇痛不足判定、不在服务区判定、低输注判定";
-    }
-
-    @Override
-    public void setConfig(Map<String, Object> map) {
-        JSONUtil.toBean(JSONUtil.toJsonStr(map), FunctionOtherConfig.class);
-    }
-
-    @Override
-    public void handler(BusDeviceRunningEntity source) {
-
-    }
-}

+ 4 - 7
coffee-system/src/main/java/com/coffee/bus/controller/BusAlarmController.java

@@ -3,6 +3,7 @@ package com.coffee.bus.controller;
 import cn.dev33.satoken.annotation.SaCheckPermission;
 import com.baomidou.mybatisplus.core.mapper.Mapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.coffee.bus.controller.vo.CauseVo;
 import com.coffee.bus.service.dto.AlarmQuery;
 import com.coffee.bus.entity.BusClinicEntity;
 import com.coffee.bus.entity.BusDeviceAlarmEntity;
@@ -31,15 +32,11 @@ public class BusAlarmController extends BaseCrudController<BusDeviceAlarmEntity,
     private final LocalBusDeviceAlarmService deviceAlarmService;
 
     @PostMapping("/cause/{id}")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "cause",value = "报警原因",dataTypeClass = String.class,required = true,example = "设备误报"),
-            @ApiImplicitParam(name = "id",value = "报警信息id",dataTypeClass = String.class,required = true)
-    })
     @ApiOperation(value = "添加报警原因",notes = "权限:【bus:alarm:cause】")
     @SaCheckPermission("bus:alarm:cause")
-    public R cause(@PathVariable("id") String id, @RequestBody String cause) {
-        deviceAlarmService.addCause(id,cause);
-        return R.success();
+    public R<Boolean> cause(@PathVariable("id") String id, @RequestBody@Validated CauseVo cause) {
+        deviceAlarmService.addCause(id,cause.getCause());
+        return R.success(true);
     }
 
 

+ 8 - 5
coffee-system/src/main/java/com/coffee/bus/controller/BusClinicController.java

@@ -13,6 +13,7 @@ import com.coffee.common.result.R;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 import java.util.List;
@@ -29,6 +30,7 @@ import java.util.stream.Collectors;
 @RestController
 @AllArgsConstructor
 @RequestMapping("/bus/clinic")
+@Slf4j
 @Api(tags = "病人临床手术管理",description = "统一权限前缀(bus:clinic),例如新增bus:clinic:add")
 public class BusClinicController {
     private final LocalBusClinicService clinicService;
@@ -39,7 +41,7 @@ public class BusClinicController {
     private final DeviceRegistry deviceRegistry;
     @PostMapping("/stats")
     @ApiOperation(value = "临床过程中的数据记录",notes = "权限【无】")
-    public R<ClinicStatsReturnResult> stats(@RequestBody ClinicStatsVo statsVo) {
+    public R<ClinicStatsReturnResult> stats(@RequestBody@Validated ClinicStatsVo statsVo) {
         return R.success(clinicService.stats(statsVo));
     }
 
@@ -55,7 +57,8 @@ public class BusClinicController {
     @PostMapping("/anal/record/{clinicId}")
     @SaCheckPermission("bus:clinic:query")
     @ApiOperation(value = "查询临床信息的镇痛访视记录单",notes = "权限【bus:clinic:query】")
-    public R<ClinicAnalRecordResult> analRecord(@PathVariable("clinicId") String clinicId){
+    public R<ClinicAnalRecordResult> analRecord(@PathVariable("clinicId") String clinicId,@RequestAttribute("tenantId") String tenantId){
+        log.info("查询临床访视单【{}】",clinicId);
         ClinicAnalRecordResult result = new ClinicAnalRecordResult();
         BusClinicEntity clinic = clinicService.getById(clinicId);
         if(clinic==null){
@@ -67,12 +70,13 @@ public class BusClinicController {
         //填充评价记录
         result.setEvaluations(evaluationService.list(new QueryWrapper<BusEvaluationEntity>().lambda().eq(BusEvaluationEntity::getClinicId,clinicId).orderByAsc(BusEvaluationEntity::getEvaluateTime)));
 
-
         //填充输注记录
         List<BusInfusionHistoryEntity> infusionHistories = infusionHistoryService.list(new QueryWrapper<BusInfusionHistoryEntity>().lambda()
                 .eq(BusInfusionHistoryEntity::getClinicId, clinicId)
                 .orderByAsc(BusInfusionHistoryEntity::getStartTime));
 
+        result.fillUndoInfo(infusionHistories);
+
         //添加设备别名
         Map<String, List<BusInfusionHistoryEntity>> infusionByDeviceId = infusionHistories.stream().collect(Collectors.groupingBy(BusInfusionHistoryEntity::getDeviceId));
         infusionByDeviceId.forEach((deviceId,infusions)->{
@@ -80,11 +84,10 @@ public class BusClinicController {
             infusions.forEach(infusion->infusion.setAlias(alias));
         });
 
-        result.fillUndoInfo(infusionHistories);
-
         List<String> infusionIds = infusionHistories.stream().map(BusInfusionHistoryEntity::getId).collect(Collectors.toList());
         List<BusInfusionModifyEntity> infusionModifies = infusionModifyService.list(new QueryWrapper<BusInfusionModifyEntity>().lambda()
                 .in(BusInfusionModifyEntity::getInfusionId, infusionIds));
+
         result.fillInfusionRecords(infusionHistories,infusionModifies);
 
         List<BusDeviceHistoryEntity> deviceHistories = deviceHistoryService.list(new QueryWrapper<BusDeviceHistoryEntity>()

+ 17 - 0
coffee-system/src/main/java/com/coffee/bus/controller/BusHospitalConfigController.java

@@ -1,11 +1,16 @@
 package com.coffee.bus.controller;
 
+import cn.dev33.satoken.annotation.SaCheckPermission;
 import com.baomidou.mybatisplus.core.mapper.Mapper;
 import com.coffee.bus.entity.BusHospitalConfigEntity;
+import com.coffee.bus.enums.ConfigEnum;
 import com.coffee.bus.service.LocalBusHospitalConfigService;
 import com.coffee.common.crud.BaseService;
 import com.coffee.common.crud.controller.BaseCrudController;
+import com.coffee.common.exception.CustomException;
+import com.coffee.common.result.R;
 import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
@@ -33,6 +38,18 @@ public class BusHospitalConfigController extends BaseCrudController<BusHospitalC
         return "hospital:config";
     }
 
+    @PostMapping("/reset/{type}")
+    @SaCheckPermission("hospital:config:edit")
+    @ApiOperation(value = "将某一功能项改为默认配置",notes = "权限【hospital:config:edit】")
+    public R<Boolean> reset(@RequestAttribute("tenantId")String tenantId,@PathVariable("type") int type){
+        ConfigEnum configEnum = ConfigEnum.valueOf(type);
+        if(configEnum==null){
+            throw new CustomException("无此配置项");
+        }
+        hospitalConfigService.setDefaultConfig(tenantId,configEnum);
+         return R.success(true);
+    }
+
     @Override
     public BaseService<? extends Mapper<BusHospitalConfigEntity>, BusHospitalConfigEntity, String> getService() {
         return hospitalConfigService;

+ 55 - 6
coffee-system/src/main/java/com/coffee/bus/controller/BusHospitalController.java

@@ -3,16 +3,24 @@ package com.coffee.bus.controller;
 
 import cn.dev33.satoken.annotation.SaCheckPermission;
 import cn.dev33.satoken.annotation.SaMode;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.mapper.Mapper;
 import com.coffee.bus.bean.Script;
+import com.coffee.bus.controller.vo.ExecScript;
 import com.coffee.bus.entity.BusHospitalEntity;
-import com.coffee.bus.script.ScriptManager;
+import com.coffee.bus.hospital.HospitalManagerRegister;
+import com.coffee.bus.hospital.his.strategy.HisStrategyEnum;
+import com.coffee.bus.hospital.script.ScriptManager;
 import com.coffee.bus.service.LocalBusHospitalService;
 import com.coffee.common.crud.BaseService;
 import com.coffee.common.crud.controller.BaseCrudController;
+import com.coffee.common.exception.CustomException;
 import com.coffee.common.result.R;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
 import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
@@ -29,7 +37,7 @@ import org.springframework.web.bind.annotation.*;
 @Api(tags = "医院管理",description = "统一权限前缀(bus:hospital),例如新增bus:hospital:add")
 public class BusHospitalController extends BaseCrudController<BusHospitalEntity, String> {
     private final LocalBusHospitalService hospitalService;
-
+    private final HospitalManagerRegister hospitalManagerRegister;
     private final ScriptManager scriptManager;
 
     /**
@@ -59,12 +67,53 @@ public class BusHospitalController extends BaseCrudController<BusHospitalEntity,
         return R.success();
     }
 
-    @PostMapping("/{id}/debug")
-    @ApiOperation(value = "执行医院解析脚本")
-    public R debug(@PathVariable("id") String id,@RequestBody String param){
-        return R.success( scriptManager.lookUpHospital(id).exec(param));
+    @PostMapping("/debug")
+    @SaCheckPermission("bus:hospital:script")
+    @ApiOperation(value = "执行解析脚本",notes = "医院必选,根据入参执行解析脚本,权限【bus:hospital:script】")
+    public R debug(@RequestBody ExecScript execScript){
+        return R.success( scriptManager.debug(execScript.getContent(),execScript.getInput()));
+    }
+
+    @PostMapping("/draft/script")
+    @SaCheckPermission("bus:hospital:script")
+    @ApiOperation(value = "保存脚本草稿脚本",notes = "医院必选,保存脚本草稿脚本,权限【bus:hospital:script】")
+    public R draftScript(@RequestAttribute("tenantId")@ApiParam(hidden = true) String tenantId, @RequestBody Script script){
+        scriptManager.check(script.getContent(),script.getType());
+        hospitalService.update(new UpdateWrapper<BusHospitalEntity>().lambda().eq(BusHospitalEntity::getId,tenantId)
+                .set(BusHospitalEntity::getScript,script));
+        return R.success(true);
+    }
+
+    @PostMapping("/publish/script")
+    @SaCheckPermission("bus:hospital:script")
+    @ApiOperation(value = "发布脚本",notes = "医院必选,发布脚本,发布后即用该脚本解析his数据,权限【bus:hospital:script】")
+    public R publishScript(@RequestAttribute("tenantId")@ApiParam(hidden = true) String tenantId){
+        BusHospitalEntity hospital = hospitalService.getById(tenantId);
+        if (ObjectUtil.isNull(hospital.getScript())||StrUtil.isEmpty(hospital.getScript().getContent())) {
+            throw new CustomException("草稿脚本内容为空,发布失败");
+        }
+        hospitalService.update(new UpdateWrapper<BusHospitalEntity>().lambda().eq(BusHospitalEntity::getId,tenantId)
+                .set(BusHospitalEntity::getScript,hospital.getDraftScript()));
+        hospitalManagerRegister.refresh(tenantId,false,false,true);
+        return R.success(true);
     }
 
+    @PostMapping("/strategy/{type}")
+    @SaCheckPermission("bus:hospital:strategy")
+    @ApiOperation(value = "His对接策略编辑",notes = "His对接策略编辑,权限【bus:hospital:strategy】")
+    public R editStrategy(@PathVariable("type")@ApiParam("接收his数据的策略, 0、无his 1(默认)、获取病人全部信息 2、获取病人部分信息 3、获取病人最新信息") Integer type,@RequestAttribute("tenantId")@ApiParam(hidden = true) String tenantId){
+        HisStrategyEnum strategy = HisStrategyEnum.valueOf(type);
+        if(strategy==null){
+            throw new CustomException("所选策略不存在");
+        }
+        hospitalService.update(new UpdateWrapper<BusHospitalEntity>()
+                .lambda()
+                .eq(BusHospitalEntity::getId,tenantId)
+                .set(BusHospitalEntity::getStrategy,strategy));
+        return R.success(true);
+    }
+
+
     @PostMapping("/validate")
     @SaCheckPermission(mode = SaMode.OR,value = {"bus:hospital:edit","bus:hospital:add"})
     @ApiOperation(value = "校验医院名称是否重复",notes = "权限【bus:hospital:edit 或 bus:hospital:edit】")

+ 49 - 7
coffee-system/src/main/java/com/coffee/bus/controller/BusPatientController.java

@@ -26,6 +26,7 @@ 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;
 
@@ -89,7 +90,7 @@ public class BusPatientController  implements BaseQueryController<BusPatientEnti
     @ApiOperation(value = "判断给定病号中是否可以结束临床管理",notes = "病患当前绑定主设备必须要在关机、不在服务器、待机中才能结束管理,权限【无】")
     @ApiResponses({
             @ApiResponse(code = 500,message = "没有选择病号"),
-            @ApiResponse(code =200 ,message = "若存在不可以结束的临床信息,将会把该临床的主泵信息返回",response = BusDeviceRunningEntity.class)
+            @ApiResponse(code =200 ,message = "若存在不可以结束的临床信息,返回1",response = BusDeviceRunningEntity.class)
     })
     public R<Boolean> judgeFinished(@RequestBody List<String> patientCodes){
         if(CollectionUtil.isEmpty(patientCodes)){
@@ -101,7 +102,8 @@ public class BusPatientController  implements BaseQueryController<BusPatientEnti
                 .select(BusDeviceRunningEntity::getDeviceId,BusDeviceRunningEntity::getPatientCode,BusDeviceRunningEntity::getRunState,BusDeviceRunningEntity::getAlarm)
                 .eq(BusDeviceRunningEntity::getMaster,true)
                 .eq(BusDeviceRunningEntity::getMonitorType,true)
-                .ne(BusDeviceRunningEntity::getRunState, DeviceStatusEnum.Shutdown)
+                .nested(i->i.ne(BusDeviceRunningEntity::getRunState,DeviceStatusEnum.Shutdown)
+                        .ne(BusDeviceRunningEntity::getRunState,DeviceStatusEnum.NoSignal))
                 .in(BusDeviceRunningEntity::getPatientCode,patientCodes))));
     }
 
@@ -132,7 +134,16 @@ public class BusPatientController  implements BaseQueryController<BusPatientEnti
     private R<Boolean> monitorFinished(MonitorFinishedVo monitorFinishedVo, String tenantId){
         List<String> patientCodes = monitorFinishedVo.getPatientCodes();
         if(CollectionUtil.isEmpty(patientCodes)){
-            throw new CustomException("请选择一个病患");
+            List<String> clinicIds = monitorFinishedVo.getClinicIds();
+            if (CollectionUtil.isEmpty(clinicIds)) {
+                throw new CustomException("未选择临床信息");
+            }
+            patientCodes=clinicService.list(new QueryWrapper<BusClinicEntity>().lambda()
+                    .in(BusClinicEntity::getId,clinicIds))
+                    .stream().map(BusClinicEntity::getPatientCode).collect(Collectors.toList());
+            if (CollectionUtil.isEmpty(patientCodes)) {
+                throw new CustomException("临床信息不存在");
+            }
         }
         List<PatientOperator<PatientCacheInfo>> patientOperators = patientCodes.stream().map(code -> patientRegistry.getOperator(tenantId, code)).collect(Collectors.toList());
 
@@ -180,15 +191,28 @@ public class BusPatientController  implements BaseQueryController<BusPatientEnti
     @SaCheckPermission("device:patient:edit")
     @ApiOperation(value = "病人当前监控时间重启",notes = "当结束临床后有新的输注信息产生,那么病人监控会重新显示,此时监控时间不会重新计算,需先调用该接口,权限标识为【device:patient:edit】")
     public R reset(@ApiParam("临床id")@PathVariable("clinicId")String clinicId){
-        return R.success(clinicService.update(new UpdateWrapper<BusClinicEntity>().lambda().eq(BusClinicEntity::getId,clinicId)
-                .set(BusClinicEntity::getFinished,false)));
+        R<Boolean> result = R.success(clinicService.update(new UpdateWrapper<BusClinicEntity>().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<Long> 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 DeviceShiftConfig shiftConfig){
+    public R shift(@RequestBody@Validated DeviceShiftConfig shiftConfig){
         deviceRunningService.shift(shiftConfig);
         wsPublishUtils.publishPatientMonitor(shiftConfig.getPatientCode(),shiftConfig.getTenantId());
         return R.success();
@@ -197,7 +221,8 @@ public class BusPatientController  implements BaseQueryController<BusPatientEnti
     @PostMapping("/undo")
     @SaCheckPermission("device:patient:undo")
     @ApiOperation(value = "批量撤泵,只撤泵,不切换",notes = "当出现泵重复状态时,若用户想要取消对其他副泵的监控,则调用此接口进行撤泵操作,权限标识为【device:patient:undo】")
-    public R shift(@RequestBody ManualUndoConfig undoConfig){
+    public R shift(@RequestBody@Validated ManualUndoConfig undoConfig, @RequestAttribute("tenantId")@ApiParam(hidden = true) String tenantId){
+        undoConfig.setTenantId(tenantId);
         //泵切换完成后,对病号报警解除
         deviceRunningService.undo(undoConfig,false);
         //判断当前病号下是否还存在副泵
@@ -220,6 +245,9 @@ public class BusPatientController  implements BaseQueryController<BusPatientEnti
                 .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();
     }
 
@@ -282,6 +310,20 @@ public class BusPatientController  implements BaseQueryController<BusPatientEnti
         return patientService.getPatientInfoFromHis(tenantId,vo.getPatientCode(),vo.getTimeout(),false);
     }
 
+
+    @SaCheckPermission("device:patient:query")
+    @ApiOperation(value = "泵重复绑定数量",notes = "权限标识为【bus:patient:query】")
+    @PostMapping("/_count/repeat")
+    public R<Integer> repeatCount(){
+        return R.success(CollectionUtil.size(patientService.repeatDevice()));
+    }
+
+    @SaCheckPermission("device:patient:query")
+    @ApiOperation(value = "无泵数量",notes = "权限标识为【bus:patient:query】")
+    @PostMapping("/_count/none")
+    public R<Integer> noneCount(){
+        return R.success(CollectionUtil.size(patientService.repeatDevice()));
+    }
     /**
      * 描述:
      * @author lifang

+ 22 - 0
coffee-system/src/main/java/com/coffee/bus/controller/vo/CauseVo.java

@@ -0,0 +1,22 @@
+package com.coffee.bus.controller.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName CauseVo.java
+ * @Description TODO
+ * @createTime 2022年05月21日 14:14:00
+ */
+@Data
+@ApiModel("报警原因")
+public class CauseVo {
+    @NotNull(message = "报警原因不能为空")
+    @ApiModelProperty("报警原因")
+    private String cause;
+}

+ 3 - 0
coffee-system/src/main/java/com/coffee/bus/controller/vo/ClinicStatsVo.java

@@ -3,6 +3,8 @@ package com.coffee.bus.controller.vo;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
+
+import javax.validation.constraints.NotNull;
 import java.util.*;
 /**
  * @author lifang
@@ -15,6 +17,7 @@ import java.util.*;
 @Data
 public class ClinicStatsVo {
     @ApiModelProperty("临床id")
+    @NotNull(message = "临床id不能为空")
     private String clinicId;
     @ApiModelProperty("设备id")
     private String deviceId;

+ 27 - 0
coffee-system/src/main/java/com/coffee/bus/controller/vo/ExecScript.java

@@ -0,0 +1,27 @@
+package com.coffee.bus.controller.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName ExecScript.java
+ * @Description TODO
+ * @createTime 2022年05月21日 19:14:00
+ */
+@Data
+@ApiModel("脚本执行")
+public class ExecScript {
+    @ApiModelProperty("脚本内容")
+    @NotBlank(message = "脚本内容不能为空")
+    private String content;
+    @ApiModelProperty("输入参数")
+    private String input;
+    @ApiModelProperty("脚本类型")
+    private String type;
+}

+ 0 - 1
coffee-system/src/main/java/com/coffee/bus/entity/BusDeviceAlarmEntity.java

@@ -13,7 +13,6 @@ import com.coffee.common.entity.TenantGenericEntity;
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
-import jdk.nashorn.internal.ir.EmptyNode;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.ToString;

+ 4 - 8
coffee-system/src/main/java/com/coffee/bus/entity/BusDeviceEntity.java

@@ -42,6 +42,10 @@ public class BusDeviceEntity extends TenantGenericEntity<String,String> {
     @ApiModelProperty(value = "设备唯一id")
     private String deviceId;
 
+
+    @ApiModelProperty(value = "mqtt通道信息")
+    private String mqttConnInfo;
+
     @ApiModelProperty(value = "设备别名")
     @Length(max = 255,message = "设备别名不得超过255个字符")
     private String alias;
@@ -50,14 +54,6 @@ public class BusDeviceEntity extends TenantGenericEntity<String,String> {
     @Length(max = 255,message = "设备类型不得超过255个字符")
     private DeviceTypeEnum type;
 
-    @ApiModelProperty(value = "运行状态",readOnly = true)
-    @TableField(javaType = true,updateStrategy = FieldStrategy.IGNORED)
-    private DeviceStatusEnum runState;
-
-    @ApiModelProperty(value = "报警信息",readOnly = true)
-    @TableField(javaType = true,updateStrategy = FieldStrategy.IGNORED)
-    private DeviceAlarmEnum alarm;
-
     @ApiModelProperty(value = "第三方平台返回配置")
     @TableField(typeHandler = FastjsonTypeHandler.class,updateStrategy = FieldStrategy.DEFAULT)
     private AliIotConfig config;

+ 4 - 7
coffee-system/src/main/java/com/coffee/bus/entity/BusDeviceHistoryEntity.java

@@ -36,9 +36,6 @@ import java.util.Date;
 @ApiModel(value="设备历史运行数据", description="设备历史运行数据记录")
 public class BusDeviceHistoryEntity extends CommonDeviceParam<String,String> {
 
-    @ApiModelProperty(value = "患者编号")
-    private String patientId;
-
     @ApiModelProperty(value = "输注记录id")
     @JsonIgnoreProperties
     private String infusionId;
@@ -47,10 +44,6 @@ public class BusDeviceHistoryEntity extends CommonDeviceParam<String,String> {
     @JsonIgnoreProperties
     private String infusionModifyId;
 
-    @ApiModelProperty(value = "是否已撤泵,0、未撤泵1、已撤泵")
-    @JsonIgnoreProperties
-    private Boolean isUndo;
-
     @ApiModelProperty(value = "是否为主泵数据, 0、副泵 1、主泵(即当前临床绑定的泵)")
     @JsonIgnoreProperties
     private Boolean master;
@@ -81,6 +74,7 @@ public class BusDeviceHistoryEntity extends CommonDeviceParam<String,String> {
         entity.setPcaValidCount(running.getPcaValidCount());
         entity.setPcaInvalidCount(running.getPcaInvalidCount());
         entity.setPcaTotalCount(running.getPcaTotalCount());
+        entity.setDataNumber(running.getDataNumber());
         /**
          * 脉冲泵参数
          */
@@ -104,6 +98,9 @@ public class BusDeviceHistoryEntity extends CommonDeviceParam<String,String> {
         entity.setWarnWillFinished(running.getWarnAnalgesicPoor());
         entity.setAlarm(running.getAlarm());
 
+        entity.setWard(running.getWard());
+        entity.setBedNo(running.getBedNo());
+        entity.setDataNumber(running.getDataNumber());
         entity.setMaster(running.getMaster());
         entity.setTenantId(running.getTenantId());
         return entity;

+ 12 - 0
coffee-system/src/main/java/com/coffee/bus/entity/BusDeviceRunningEntity.java

@@ -83,6 +83,15 @@ public class BusDeviceRunningEntity extends CommonDeviceParam<String,String> {
     @JsonIgnoreProperties
     private String infusionModifyId;
 
+    @TableField(exist = false)
+    @JsonIgnoreProperties
+    private Date modifyTime;
+    /**
+     * 当前运行状态是否开启了新的输注,只在设备上传解析过程中使用,其他地方无用处
+     */
+    @TableField(exist = false)
+    @JsonIgnoreProperties
+    private boolean newInfusion;
     /**
      * @author 龙三郎
      * 根据阿里云传回数据的items,设置输注的属性
@@ -90,6 +99,9 @@ public class BusDeviceRunningEntity extends CommonDeviceParam<String,String> {
      * @param items
      */
     public void setFiledsByItems(String deviceName, Items items) {
+        // 属性上传时间
+        this.setUploadTime(items.getDate());
+
         this.setDeviceId(deviceName);
         this.setClassification( items.getString(PumpParams.classification));
         this.setDataNumber(items.getInteger(PumpParams.dataNumber));

+ 1 - 8
coffee-system/src/main/java/com/coffee/bus/entity/BusHospitalConfigEntity.java

@@ -1,20 +1,13 @@
 package com.coffee.bus.entity;
 
-import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
 import com.coffee.bus.enums.ConfigEnum;
-import com.coffee.common.config.mybatis.DateToBigIntHandler;
-import com.coffee.common.entity.RecordCreationEntity;
-import com.coffee.common.entity.RecordModifierEntity;
 import com.coffee.common.entity.TenantGenericEntity;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
-import org.apache.ibatis.type.EnumTypeHandler;
-
-import java.util.Date;
 import java.util.Map;
 
 /**
@@ -30,7 +23,7 @@ import java.util.Map;
 public class BusHospitalConfigEntity extends TenantGenericEntity<String,String>  {
 
 
-    @ApiModelProperty(value = "配置类型",example = "eval:评价配置,other:其他设置,undo:撤泵配置",allowableValues = "eval:评价配置,other:其他设置,undo:撤泵配置")
+    @ApiModelProperty(value = "配置类型",example = "eval:评价配置,extra:其他设置,undo:撤泵配置",allowableValues = "eval:评价配置,extra:其他设置,undo:撤泵配置")
     private ConfigEnum type;
 
     @TableField(typeHandler = FastjsonTypeHandler.class,javaType = true)

+ 9 - 38
coffee-system/src/main/java/com/coffee/bus/entity/BusHospitalEntity.java

@@ -4,12 +4,10 @@ import com.baomidou.mybatisplus.annotation.*;
 import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
 import com.coffee.bus.bean.GeoPoint;
 import com.coffee.bus.bean.Script;
-import com.coffee.bus.his.strategy.HisStrategyEnum;
+import com.coffee.bus.hospital.his.strategy.HisStrategyEnum;
 import com.coffee.common.entity.RecordCreationEntity;
 import com.coffee.common.entity.RecordModifierEntity;
-import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonSetter;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
@@ -74,9 +72,14 @@ public class BusHospitalEntity implements RecordModifierEntity, RecordCreationEn
     @TableField(typeHandler = FastjsonTypeHandler.class )
     private GeoPoint coordinate;
 
-    @TableField(typeHandler = FastjsonTypeHandler.class)
+    @ApiModelProperty("发布的脚本内容")
+    @TableField(typeHandler = FastjsonTypeHandler.class,updateStrategy = FieldStrategy.NEVER)
     private Script script;
 
+    @ApiModelProperty("草稿(编辑中的脚本内容)")
+    @TableField(typeHandler = FastjsonTypeHandler.class,updateStrategy = FieldStrategy.NEVER)
+    private Script draftScript;
+
     @ApiModelProperty("医院唯一编码,自动生成")
     @JsonIgnoreProperties(allowGetters = true)
     private String code;
@@ -87,43 +90,11 @@ public class BusHospitalEntity implements RecordModifierEntity, RecordCreationEn
     @ApiModelProperty("设备数量")
     private Integer deviceCount;
 
-    @ApiModelProperty("气泡报警数量")
-    private Integer bubbleCount;
-
-    @ApiModelProperty("堵塞报警数量")
-    private Integer jamCount;
-
-    @ApiModelProperty("极限报警数量")
-    private Integer limitCount;
-
-    @ApiModelProperty("未装药盒报警数量")
-    private Integer noBoxCount;
-
-    @ApiModelProperty("电机失控报警数量")
-    private Integer outOfControlCount;
-
-    @ApiModelProperty("镇痛不足提醒数量")
-    private Integer warnAnalgesicPoorCount;
-
-    @ApiModelProperty(" 不在服务区数量")
-    private Integer noSignalCount;
-
-    @ApiModelProperty(" 机械报警数量")
-    private Integer machineCount;
-
-    @ApiModelProperty("电量耗尽报警数量")
-    private Integer lowBatteryCount;
-
-    @ApiModelProperty("低输注报警数量")
-    private Integer lowestCount;
-
-    @ApiModelProperty("返厂维护报警数量")
-    private Integer maintainCount;
-
     @TableField(fill = FieldFill.INSERT)
     private String createBy;
 
-    @ApiModelProperty("接受his数据的策略, 1(默认)、获取病人全部信息 2、获取病人部分信息 3、获取病人最新信息")
+    @ApiModelProperty("接收his数据的策略, 1(默认)、获取病人全部信息 2、获取病人部分信息 3、获取病人最新信息")
+    @TableField(updateStrategy = FieldStrategy.NEVER)
     private HisStrategyEnum strategy;
 
     @TableField(fill = FieldFill.INSERT_UPDATE)

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

@@ -111,7 +111,7 @@ public class BusInfusionHistoryEntity extends CommonDeviceParam<String,String> {
         entity.setPcaValidCount(running.getPcaValidCount());
         entity.setPcaInvalidCount(running.getPcaInvalidCount());
         entity.setPcaTotalCount(running.getPcaTotalCount());
-
+        entity.setDataNumber(running.getDataNumber());
         /**
          * 脉冲泵参数
          */

+ 1 - 0
coffee-system/src/main/java/com/coffee/bus/entity/BusInfusionModifyEntity.java

@@ -176,6 +176,7 @@ public class BusInfusionModifyEntity extends TenantGenericEntity<String,String>
         entity.setPcaValidCount(running.getPcaValidCount());
         entity.setPcaInvalidCount(running.getPcaInvalidCount());
         entity.setPcaTotalCount(running.getPcaTotalCount());
+        entity.setDataNumber(running.getDataNumber());
         /**
          * 脉冲泵参数
          */

+ 12 - 0
coffee-system/src/main/java/com/coffee/bus/enums/ConfigEnum.java

@@ -20,4 +20,16 @@ public enum  ConfigEnum implements IEnum<Integer> {
 
     private Integer value;
     private String text;
+
+    public static ConfigEnum valueOf(Integer value){
+        switch (value){
+            case 0:
+                return undo;
+            case 1:
+                return eval;
+            case 2:
+                return other;
+            default:return null;
+        }
+    }
 }

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

@@ -22,4 +22,17 @@ public enum PatientAlarmEnum implements IEnum<Integer> {
 
     private Integer value;
     private String text;
+
+    public static PatientAlarmEnum of(int value){
+        switch (value){
+            case 0:
+                return NONE;
+            case 1:
+                return DEVICE_REPEAT;
+            case 2:
+                return DEVICE_NONE;
+            default:break;
+        }
+        return null;
+    }
 }

+ 168 - 0
coffee-system/src/main/java/com/coffee/bus/hospital/HospitalManager.java

@@ -0,0 +1,168 @@
+package com.coffee.bus.hospital;
+
+import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.coffee.bus.bean.Script;
+import com.coffee.bus.entity.BusDeviceRunningEntity;
+import com.coffee.bus.entity.BusHospitalConfigEntity;
+import com.coffee.bus.entity.BusHospitalEntity;
+import com.coffee.bus.hospital.config.HospitalAutoUndoConfigHandler;
+import com.coffee.bus.hospital.config.HospitalFinishMonitorConfigHandler;
+import com.coffee.bus.hospital.config.HospitalFunctionAnalConfigHandler;
+import com.coffee.bus.hospital.config.HospitalFunctionExtraConfigHandler;
+import com.coffee.bus.hospital.config.bean.*;
+import com.coffee.bus.hospital.his.HisScriptSession;
+import com.coffee.bus.registry.device.DeviceRegistry;
+import com.coffee.bus.registry.patient.PatientRegistry;
+import com.coffee.bus.hospital.script.ScriptManager;
+import com.coffee.bus.hospital.script.ScriptParse;
+import com.coffee.bus.service.*;
+import com.coffee.bus.utils.WsPublishUtils;
+import com.coffee.common.cache.ConfigStorage;
+import com.coffee.common.cache.manager.ConfigStorageManager;
+import com.coffee.common.util.RedissonUtil;
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName HospitalManage.java
+ * @Description 医院管理器
+ * @createTime 2022年05月20日 08:33:00
+ */
+@Data
+public class HospitalManager {
+    private String hospitalId;
+
+    private HisScriptSession scriptSession;
+
+    private HospitalAutoUndoConfigHandler autoUndoConfigHandler;
+
+    private HospitalFinishMonitorConfigHandler finishMonitorConfigHandler;
+
+    private HospitalFunctionAnalConfigHandler analConfigHandler;
+
+    private HospitalFunctionExtraConfigHandler extraConfigHandler;
+
+    private LocalBusHospitalService hospitalService;
+
+    private LocalBusHospitalConfigService hospitalConfigService;
+
+    private LocalBusClinicService clinicService;
+
+    private ScriptManager scriptManager;
+
+    private ConfigStorage storage;
+
+    public HospitalManager(String hospitalId,
+                           LocalBusHospitalService hospitalService,
+                           LocalBusHospitalConfigService hospitalConfigService,
+                           LocalBusClinicService clinicService,
+                           LocalBusDeviceRunningService deviceRunningService,
+                           LocalBusInfusionHistoryService infusionHistoryService,
+                           PatientRegistry patientRegistry,
+                           DeviceRegistry deviceRegistry,
+                           WsPublishUtils wsPublishUtils,
+                           ScriptManager scriptManager,
+                           ConfigStorageManager configStorageManager,
+                           RedissonUtil redissonUtil) {
+        this.hospitalId = hospitalId;
+        this.hospitalService = hospitalService;
+        this.hospitalConfigService = hospitalConfigService;
+        this.clinicService = clinicService;
+        this.scriptManager = scriptManager;
+        this.hospitalId = hospitalId;
+        this.storage=configStorageManager.getStorage(hospitalId);
+        this.autoUndoConfigHandler=new HospitalAutoUndoConfigHandler(storage,hospitalId,redissonUtil,deviceRunningService,infusionHistoryService,deviceRegistry,wsPublishUtils,patientRegistry);
+        this.finishMonitorConfigHandler=new HospitalFinishMonitorConfigHandler(storage,hospitalId,redissonUtil,deviceRunningService,infusionHistoryService,deviceRegistry,wsPublishUtils,patientRegistry);
+        this.analConfigHandler=new HospitalFunctionAnalConfigHandler(storage,hospitalId,redissonUtil,deviceRunningService,infusionHistoryService,deviceRegistry,wsPublishUtils,patientRegistry);
+        this.extraConfigHandler=new HospitalFunctionExtraConfigHandler(storage,hospitalId,redissonUtil,deviceRunningService,infusionHistoryService,deviceRegistry,wsPublishUtils,patientRegistry,finishMonitorConfigHandler,autoUndoConfigHandler);
+        init(configStorageManager);
+    }
+
+    private void init(ConfigStorageManager configStorageManager){
+        this.scriptSession=new HisScriptSession(hospitalId,scriptManager,configStorageManager,clinicService,hospitalService);
+        refreshInfo();
+        refreshConfig();
+        refreshScript();
+    }
+
+    /**
+     * 描述: 刷新医院信息
+     * @author lifang
+     * @date 2022/5/20 8:47
+     * @param
+     * @return void
+     */
+    public void refreshInfo(){
+        BusHospitalEntity hospital = hospitalService.getById(hospitalId);
+        storage.setConfig("info",hospital);
+    }
+
+    public BusHospitalEntity getInfo(){
+        return storage.getConfig("info").as(BusHospitalEntity.class);
+    }
+
+    /**
+     * 描述: 刷新配置
+     * @author lifang
+     * @date 2022/5/20 8:47
+     * @param
+     * @return void
+     */
+    public void refreshConfig(){
+        List<BusHospitalConfigEntity> hospitalConfig = hospitalConfigService.list(new QueryWrapper<BusHospitalConfigEntity>().lambda().eq(BusHospitalConfigEntity::getTenantId, hospitalId));
+        //设置默认参数
+        for (BusHospitalConfigEntity config : hospitalConfig) {
+            Map<String, Object> param = config.getConfig();
+            switch (config.getType()) {
+                case undo:
+                    FunctionUndoConfig functionUndoConfig = JSONUtil.toBean(JSONUtil.toJsonStr(param), FunctionUndoConfig.class);
+                    //自动撤泵
+                    FunctionAutoUndoConfig autoUndo = functionUndoConfig.getAuto();
+                    autoUndoConfigHandler.setConfig(autoUndo);
+                    //自动结束临床管理
+                    FunctionFinishMonitorConfig finishMonitor = functionUndoConfig.getFinishMonitor();
+                    finishMonitorConfigHandler.setConfig(finishMonitor);
+                    break;
+                case other:
+                    FunctionOtherConfig otherConfig = JSONUtil.toBean(JSONUtil.toJsonStr(param), FunctionOtherConfig.class);
+                    //镇痛不足
+                    FunctionAnalConfig anal = otherConfig.getAnal();
+                    analConfigHandler.setConfig(anal);
+                    //其他
+                    FunctionExtraConfig extraConfig = otherConfig.getExtra();
+                    extraConfigHandler.setConfig(extraConfig);
+                    break;
+                default:break;
+            }
+        }
+    }
+
+
+    /**
+     * 描述: 对设备发来消息进行处理
+     * @author lifang
+     * @date 2022/5/20 8:50
+     * @param source
+     * @return void
+     */
+    public void handleDeviceMessage(BusDeviceRunningEntity source){
+        analConfigHandler.handler(source);
+        extraConfigHandler.handler(source);
+        autoUndoConfigHandler.handler(source);
+        finishMonitorConfigHandler.handler(source);
+    }
+
+
+    public void refreshScript(){
+        BusHospitalEntity hospital = hospitalService.getById(hospitalId);
+        ScriptParse scriptParse = scriptManager.getById(hospitalId);
+        scriptManager.resetScript(hospitalId,scriptParse.getId(), Optional.ofNullable(hospital.getScript()).orElse(new Script()).getContent());
+    }
+
+}

+ 88 - 0
coffee-system/src/main/java/com/coffee/bus/hospital/HospitalManagerRegister.java

@@ -0,0 +1,88 @@
+package com.coffee.bus.hospital;
+
+import com.coffee.bus.registry.device.DeviceRegistry;
+import com.coffee.bus.registry.patient.PatientRegistry;
+import com.coffee.bus.hospital.script.ScriptManager;
+import com.coffee.bus.service.*;
+import com.coffee.bus.utils.WsPublishUtils;
+import com.coffee.common.cache.manager.ConfigStorageManager;
+import com.coffee.common.util.RedissonUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName HospitalManageRegister.java
+ * @Description 医院管理注册
+ * @createTime 2022年05月20日 08:33:00
+ */
+@Component
+public class HospitalManagerRegister {
+    private Map<String,HospitalManager> managerMap=new ConcurrentHashMap<>();
+
+    private LocalBusHospitalService hospitalService;
+    private LocalBusHospitalConfigService hospitalConfigService;
+    private LocalBusClinicService clinicService;
+    private LocalBusDeviceRunningService deviceRunningService;
+    private LocalBusInfusionHistoryService infusionHistoryService;
+    private PatientRegistry patientRegistry;
+    private DeviceRegistry deviceRegistry;
+    private WsPublishUtils wsPublishUtils;
+    private ScriptManager scriptManager;
+    private ConfigStorageManager configStorageManager;
+    private RedissonUtil redissonUtil;
+
+    public HospitalManagerRegister( LocalBusHospitalService hospitalService, LocalBusHospitalConfigService hospitalConfigService, LocalBusClinicService clinicService, LocalBusDeviceRunningService deviceRunningService, LocalBusInfusionHistoryService infusionHistoryService, PatientRegistry patientRegistry, DeviceRegistry deviceRegistry, WsPublishUtils wsPublishUtils, ScriptManager scriptManager, ConfigStorageManager configStorageManager, RedissonUtil redissonUtil) {
+        this.hospitalService = hospitalService;
+        this.hospitalConfigService = hospitalConfigService;
+        this.clinicService = clinicService;
+        this.deviceRunningService = deviceRunningService;
+        this.infusionHistoryService = infusionHistoryService;
+        this.patientRegistry = patientRegistry;
+        this.deviceRegistry = deviceRegistry;
+        this.wsPublishUtils = wsPublishUtils;
+        this.scriptManager = scriptManager;
+        this.configStorageManager = configStorageManager;
+        this.redissonUtil = redissonUtil;
+    }
+
+    public void register(String hospitalId){
+        managerMap.computeIfAbsent(hospitalId,k->
+                new HospitalManager(k,hospitalService,hospitalConfigService,clinicService,deviceRunningService,infusionHistoryService,patientRegistry,deviceRegistry,wsPublishUtils,scriptManager,configStorageManager,redissonUtil)
+        );
+    };
+
+    public HospitalManager get(String hospitalId){
+        return  managerMap.computeIfAbsent(hospitalId,k->
+                new HospitalManager(k,hospitalService,hospitalConfigService,clinicService,deviceRunningService,infusionHistoryService,patientRegistry,deviceRegistry,wsPublishUtils,scriptManager,configStorageManager,redissonUtil)
+        );
+    }
+
+
+    public void refresh(String hospitalId,boolean info){
+        refresh(hospitalId,info,false,false);
+    }
+
+    public void refresh(String hospitalId,boolean info,boolean config){
+        refresh(hospitalId,info,config,false);
+    }
+
+    public void refresh(String hospitalId,boolean info,boolean config,boolean script){
+        HospitalManager hospitalManager = this.get(hospitalId);
+        if(info){
+            hospitalManager.refreshConfig();
+        }
+        if(config){
+            hospitalManager.refreshConfig();
+        }
+        if(script){
+            hospitalManager.refreshScript();
+        }
+    }
+
+
+
+}

+ 57 - 0
coffee-system/src/main/java/com/coffee/bus/hospital/config/AbstractHospitalConfigHandler.java

@@ -0,0 +1,57 @@
+package com.coffee.bus.hospital.config;
+
+import com.coffee.bus.registry.device.DeviceRegistry;
+import com.coffee.bus.registry.patient.PatientRegistry;
+import com.coffee.bus.service.LocalBusDeviceRunningService;
+import com.coffee.bus.service.LocalBusInfusionHistoryService;
+import com.coffee.bus.utils.WsPublishUtils;
+import com.coffee.common.cache.ConfigStorage;
+import com.coffee.common.cache.value.Value;
+import com.coffee.common.util.RedissonUtil;
+import lombok.Getter;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName AbstractHospitalConfigHandler.java
+ * @Description TODO
+ * @createTime 2022年05月19日 23:29:00
+ */
+public abstract class AbstractHospitalConfigHandler<E,T> implements HospitalConfigHandler<E,T> {
+    protected final RedissonUtil redissonUtil;
+
+    protected final  LocalBusDeviceRunningService deviceRunningService;
+
+    protected  final LocalBusInfusionHistoryService infusionHistoryService;
+
+    protected final  DeviceRegistry deviceRegistry;
+
+    protected final  WsPublishUtils wsPublishUtils;
+
+    protected final  PatientRegistry patientRegistry;
+
+    protected final ConfigStorage configStorage;
+    @Getter
+    protected String hospitalId;
+
+    public AbstractHospitalConfigHandler(ConfigStorage configStorage, String hospitalId, RedissonUtil redissonUtil, LocalBusDeviceRunningService deviceRunningService, LocalBusInfusionHistoryService infusionHistoryService, DeviceRegistry deviceRegistry, WsPublishUtils wsPublishUtils, PatientRegistry patientRegistry) {
+        this.hospitalId=hospitalId;
+        this.configStorage=configStorage;
+        this.redissonUtil = redissonUtil;
+        this.deviceRunningService = deviceRunningService;
+        this.infusionHistoryService = infusionHistoryService;
+        this.deviceRegistry = deviceRegistry;
+        this.wsPublishUtils = wsPublishUtils;
+        this.patientRegistry = patientRegistry;
+    }
+
+
+    @Override
+    public void setConfig(E config){
+        this.configStorage.setConfig(getId().name(),config);
+    };
+
+    public Value getConfig(){
+        return this.configStorage.getConfig(getId().name());
+    }
+}

+ 154 - 0
coffee-system/src/main/java/com/coffee/bus/hospital/config/HospitalAutoUndoConfigHandler.java

@@ -0,0 +1,154 @@
+package com.coffee.bus.hospital.config;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.coffee.bus.hospital.config.bean.FunctionAutoUndoConfig;
+import com.coffee.bus.hospital.config.bean.FunctionFinishMonitorConfig;
+import com.coffee.bus.entity.BusDeviceRunningEntity;
+import com.coffee.bus.enums.DeviceStatusEnum;
+import com.coffee.bus.hospital.enums.ConfigHandlerEnums;
+import com.coffee.bus.registry.device.DeviceRegistry;
+import com.coffee.bus.registry.patient.PatientRegistry;
+import com.coffee.bus.service.LocalBusDeviceRunningService;
+import com.coffee.bus.service.LocalBusInfusionHistoryService;
+import com.coffee.bus.service.dto.ManualUndoConfig;
+import com.coffee.bus.service.dto.UndoDeviceConfig;
+import com.coffee.bus.utils.WsPublishUtils;
+import com.coffee.common.cache.ConfigStorage;
+import com.coffee.common.util.RedissonUtil;
+import lombok.Builder;
+import lombok.Data;
+import org.redisson.api.RDelayedQueue;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName HospitalFinishMonitorConfigHandler.java
+ * @Description 自动结束管理处理
+ * @createTime 2022年05月19日 16:22:00
+ */
+public class HospitalAutoUndoConfigHandler extends  AbstractHospitalConfigHandler<FunctionAutoUndoConfig, BusDeviceRunningEntity>{
+
+
+    public HospitalAutoUndoConfigHandler(ConfigStorage configStorage, String hospitalId, RedissonUtil redissonUtil, LocalBusDeviceRunningService deviceRunningService, LocalBusInfusionHistoryService infusionHistoryService, DeviceRegistry deviceRegistry, WsPublishUtils wsPublishUtils, PatientRegistry patientRegistry) {
+        super(configStorage, hospitalId, redissonUtil, deviceRunningService, infusionHistoryService, deviceRegistry, wsPublishUtils, patientRegistry);
+    }
+
+    @Override
+    public ConfigHandlerEnums getId() {
+        return ConfigHandlerEnums.autoUndo;
+    }
+
+    @Override
+    public String getDescription() {
+        return "自动撤泵";
+    }
+
+    @Override
+    public void handler(BusDeviceRunningEntity source) {
+        FunctionAutoUndoConfig config = this.getConfig().as(FunctionAutoUndoConfig.class);
+        if(config==null||!Boolean.TRUE.equals(config.isEnable())|| Objects.isNull(config.getShutDownInterval())){
+            return;
+        }
+        judgeShutdown(source,config);
+    }
+
+    public void judgeNoSignal(String device,String patientCode,String tenantId){
+        FunctionFinishMonitorConfig config = this.getConfig().as(FunctionFinishMonitorConfig.class);
+        if(config==null||!Boolean.TRUE.equals(config.isEnable())|| Objects.isNull(config.getNoSignalInterval())){
+            return;
+        }
+        RDelayedQueue noSignalUndoDelay = redissonUtil.getDelayedQueue(getId() +"-noSignalUndo"+ "-" + tenantId + "-" +device, e -> {
+            if(e instanceof UndoEntity){
+                this.handleShutdown((UndoEntity) e);
+            }
+        });
+        UndoDeviceConfig undoDeviceConfig = new UndoDeviceConfig();
+        undoDeviceConfig.setUndoBy(config.getUndoBy());
+        HospitalFinishMonitorConfigHandler.FinishMonitorEntity finishMonitor = HospitalFinishMonitorConfigHandler.FinishMonitorEntity.builder()
+                .deviceId(device)
+                .patientCode(patientCode)
+                .config(undoDeviceConfig)
+                .timeout(config.getNoSignalInterval())
+                .unit(TimeUnit.SECONDS)
+                .tenantId(tenantId)
+                .timestamp(new Date())
+                .build();
+        noSignalUndoDelay.offer(finishMonitor,finishMonitor.getTimeout(),finishMonitor.getUnit());
+    }
+
+    /**
+     * 描述: 处理关机到撤泵时间
+     * @author lifang
+     * @date 2022/5/19 16:51
+     * @param source
+     * @param config
+     * @return void
+     */
+    private void judgeShutdown(BusDeviceRunningEntity source,   FunctionAutoUndoConfig config ){
+        RDelayedQueue shutdownUndoDelay = redissonUtil.getDelayedQueue(getId() +"-shutdownUndo"+ "-" + source.getTenantId() + "-" + source.getDeviceId(), e -> {
+            if(e instanceof UndoEntity){
+                this.handleShutdown((UndoEntity) e);
+            }
+        });
+        //清空延迟队列消息
+        shutdownUndoDelay.clear();
+        UndoDeviceConfig undoDeviceConfig = new UndoDeviceConfig();
+        undoDeviceConfig.setUndoBy(config.getUndoBy());
+        //清空延迟队列消息
+        shutdownUndoDelay.clear();
+        if(DeviceStatusEnum.Shutdown.equals(source.getType())){
+            UndoEntity finishMonitor = UndoEntity.builder()
+                    .deviceId(source.getDeviceId())
+                    .patientCode(source.getPatientCode())
+                    .config(undoDeviceConfig)
+                    .timeout(config.getShutDownInterval())
+                    .unit(TimeUnit.SECONDS)
+                    .tenantId(source.getTenantId())
+                    .timestamp(new Date())
+                    .build();
+            shutdownUndoDelay.offer(finishMonitor,config.getShutDownInterval(),finishMonitor.getUnit());
+        }
+
+
+    }
+
+    private void handleShutdown(UndoEntity source){
+        String deviceId = source.getDeviceId();
+        String patientCode = source.getPatientCode();
+        String tenantId = source.getTenantId();
+        //只有副泵会自动撤泵
+        BusDeviceRunningEntity entity = deviceRunningService.getOne(new QueryWrapper<BusDeviceRunningEntity>().lambda()
+                .eq(BusDeviceRunningEntity::getDeviceId, deviceId)
+                .eq(BusDeviceRunningEntity::getPatientCode, patientCode)
+                .eq(BusDeviceRunningEntity::getMaster, false)
+                .eq(BusDeviceRunningEntity::getTenantId, tenantId));
+        if(entity!=null){
+            ManualUndoConfig manualUndoConfig = new ManualUndoConfig();
+            manualUndoConfig.setDeviceIds(Collections.singletonList(deviceId));
+            manualUndoConfig.setPatientCode(patientCode);
+            manualUndoConfig.setClinicId(entity.getClinicId());
+            manualUndoConfig.setMonitorType(true);
+            manualUndoConfig.setUndo(source.getConfig());
+            manualUndoConfig.setTenantId(source.getTenantId());
+            deviceRunningService.undo(manualUndoConfig,false);
+        }
+    }
+
+
+    @Data
+    @Builder
+    static class UndoEntity{
+        private String deviceId;
+        private String patientCode;
+        private UndoDeviceConfig config;
+        private Integer timeout;
+        private TimeUnit unit;
+        private String tenantId;
+        private Date timestamp;
+    }
+}

+ 8 - 10
coffee-system/src/main/java/com/coffee/bus/config/HospitalConfigHandler.java → coffee-system/src/main/java/com/coffee/bus/hospital/config/HospitalConfigHandler.java

@@ -1,10 +1,6 @@
-package com.coffee.bus.config;
+package com.coffee.bus.hospital.config;
 
-import cn.hutool.core.util.ClassUtil;
-import cn.hutool.core.util.ObjectUtil;
-import com.coffee.bus.enums.ConfigEnum;
-
-import java.util.Map;
+import com.coffee.bus.hospital.enums.ConfigHandlerEnums;
 
 /**
  * @author lifang
@@ -13,9 +9,11 @@ import java.util.Map;
  * @Description 医院配置处理器
  * @createTime 2022年05月18日 10:33:00
  */
-public interface HospitalConfigHandler<T> {
+public interface HospitalConfigHandler<E,T> {
+
+    String getHospitalId();
 
-    ConfigEnum getType();
+    ConfigHandlerEnums getId();
 
     String getDescription();
 
@@ -23,10 +21,10 @@ public interface HospitalConfigHandler<T> {
      * 描述: 设置配置参数
      * @author lifang
      * @date 2022/5/18 10:34
-     * @param map
+     * @param config
      * @return void
      */
-    void setConfig(Map<String,Object> map);
+    void setConfig(E config);
 
     /**
      * 描述: 处理传入数据

+ 169 - 0
coffee-system/src/main/java/com/coffee/bus/hospital/config/HospitalFinishMonitorConfigHandler.java

@@ -0,0 +1,169 @@
+package com.coffee.bus.hospital.config;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.coffee.bus.hospital.config.bean.FunctionFinishMonitorConfig;
+import com.coffee.bus.entity.BusDeviceRunningEntity;
+import com.coffee.bus.enums.DeviceStatusEnum;
+import com.coffee.bus.hospital.enums.ConfigHandlerEnums;
+import com.coffee.bus.registry.device.DeviceRegistry;
+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.LocalBusDeviceRunningService;
+import com.coffee.bus.service.LocalBusInfusionHistoryService;
+import com.coffee.bus.service.dto.ManualUndoConfig;
+import com.coffee.bus.service.dto.UndoDeviceConfig;
+import com.coffee.bus.utils.WsPublishUtils;
+import com.coffee.common.cache.ConfigStorage;
+import com.coffee.common.util.RedissonUtil;
+import lombok.Builder;
+import lombok.Data;
+import org.redisson.api.RDelayedQueue;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName HospitalFinishMonitorConfigHandler.java
+ * @Description 自动结束管理处理
+ * @createTime 2022年05月19日 16:22:00
+ */
+public class HospitalFinishMonitorConfigHandler extends AbstractHospitalConfigHandler<FunctionFinishMonitorConfig, BusDeviceRunningEntity>{
+
+
+    public HospitalFinishMonitorConfigHandler(ConfigStorage configStorage, String hospitalId, RedissonUtil redissonUtil, LocalBusDeviceRunningService deviceRunningService, LocalBusInfusionHistoryService infusionHistoryService, DeviceRegistry deviceRegistry, WsPublishUtils wsPublishUtils, PatientRegistry patientRegistry) {
+        super(configStorage, hospitalId, redissonUtil, deviceRunningService, infusionHistoryService, deviceRegistry, wsPublishUtils, patientRegistry);
+    }
+
+    @Override
+    public ConfigHandlerEnums getId() {
+        return ConfigHandlerEnums.finishMonitor;
+    }
+
+    @Override
+    public String getDescription() {
+        return "自动结束管理";
+    }
+
+    @Override
+    public void handler(BusDeviceRunningEntity source) {
+        FunctionFinishMonitorConfig config = this.getConfig().as(FunctionFinishMonitorConfig.class);
+        if(config==null||!Boolean.TRUE.equals(config.isEnable())||Objects.isNull(config.getShutDownInterval())){
+            return;
+        }
+        judgeShutdown(source,config);
+
+    }
+
+    public void judgeNoSignal(String device,String patientCode,String tenantId){
+        FunctionFinishMonitorConfig config = this.getConfig().as(FunctionFinishMonitorConfig.class);
+        if(config==null||!Boolean.TRUE.equals(config.isEnable())|| Objects.isNull(config.getNoSignalInterval())){
+            return;
+        }
+        RDelayedQueue noSignalFinishDelay = redissonUtil.getDelayedQueue(getId() +"-noSignalFinish"+ "-" + tenantId + "-" +device, e -> {
+            if(e instanceof FinishMonitorEntity){
+                this.handleFinishMonitor((FinishMonitorEntity) e);
+            }
+        });
+        UndoDeviceConfig undoDeviceConfig = new UndoDeviceConfig();
+        undoDeviceConfig.setUndoBy(config.getUndoBy());
+        FinishMonitorEntity finishMonitor = FinishMonitorEntity.builder()
+                .deviceId(device)
+                .patientCode(patientCode)
+                .config(undoDeviceConfig)
+                .timeout(config.getNoSignalInterval())
+                .unit(TimeUnit.DAYS)
+                .tenantId(tenantId)
+                .timestamp(new Date())
+                .build();
+        noSignalFinishDelay.offer(finishMonitor,finishMonitor.getTimeout(),finishMonitor.getUnit());
+    }
+
+    /**
+     * 描述: 处理关机到结束时间
+     * @author lifang
+     * @date 2022/5/19 16:51
+     * @param source
+     * @param config
+     * @return void
+     */
+    private void judgeShutdown(BusDeviceRunningEntity source,FunctionFinishMonitorConfig config){
+        RDelayedQueue shutdownFinishDelay = redissonUtil.getDelayedQueue(getId() +"-ShutdownFinish"+ "-" + source.getTenantId() + "-" + source.getDeviceId(), e -> {
+            if(e instanceof FinishMonitorEntity){
+                this.handleFinishMonitor((FinishMonitorEntity) e);
+            }
+        });
+        UndoDeviceConfig undoDeviceConfig = new UndoDeviceConfig();
+        undoDeviceConfig.setUndoBy(config.getUndoBy());
+        //清空延迟队列消息
+        shutdownFinishDelay.clear();
+        if(DeviceStatusEnum.Shutdown.equals(source.getType())){
+            FinishMonitorEntity finishMonitor = FinishMonitorEntity.builder()
+                    .deviceId(source.getDeviceId())
+                    .patientCode(source.getPatientCode())
+                    .config(undoDeviceConfig)
+                    .timeout(config.getShutDownInterval())
+                    .unit(TimeUnit.DAYS)
+                    .tenantId(source.getTenantId())
+                    .timestamp(new Date())
+                    .build();
+            shutdownFinishDelay.offer(finishMonitor,config.getShutDownInterval(),finishMonitor.getUnit());
+        }
+
+        //不在服务区延迟队列清空
+        RDelayedQueue noSignalFinishDelay = redissonUtil.getDelayedQueue(getId() +"-noSignalFinish"+ "-" + source.getTenantId() + "-" +source.getDeviceId(), e -> {
+            if(e instanceof FinishMonitorEntity){
+                this.handleFinishMonitor((FinishMonitorEntity) e);
+            }
+        });
+        noSignalFinishDelay.clear();
+    }
+
+    /**
+     * 描述: 自动结束管理处理
+     * @author lifang
+     * @date 2022/5/19 22:35
+     * @param source
+     * @return void
+     */
+    private void handleFinishMonitor(FinishMonitorEntity source){
+        String deviceId = source.getDeviceId();
+        String patientCode = source.getPatientCode();
+        String tenantId = source.getTenantId();
+        UndoDeviceConfig config = source.getConfig();
+        BusDeviceRunningEntity entity = deviceRunningService.getOne(new QueryWrapper<BusDeviceRunningEntity>().lambda().eq(BusDeviceRunningEntity::getDeviceId, deviceId)
+                .eq(BusDeviceRunningEntity::getPatientCode, patientCode)
+                .eq(BusDeviceRunningEntity::getMaster,true)
+                .eq(BusDeviceRunningEntity::getTenantId, tenantId));
+        if(entity!=null){
+            PatientOperator<PatientCacheInfo> patientOperator = patientRegistry.getOperator(tenantId, patientCode);
+            ManualUndoConfig manualUndoConfig = new ManualUndoConfig();
+            config.setUndoTime(new Date());
+            manualUndoConfig.setTenantId(source.getTenantId());
+            manualUndoConfig.setUndo(config);
+            manualUndoConfig.setMonitorType(true);
+            manualUndoConfig.setClinicId(entity.getClinicId());
+            manualUndoConfig.setPatientCode(patientCode);
+            manualUndoConfig.setDeviceIds(patientOperator.getAllDevice().stream().map(DeviceTimeSmallInfo::getDeviceId).collect(Collectors.toList()));
+            deviceRunningService.undo(manualUndoConfig,true);
+        }
+    }
+
+    @Data
+    @Builder
+    static class FinishMonitorEntity implements Serializable {
+        private String deviceId;
+        private String patientCode;
+        private UndoDeviceConfig config;
+        private Integer timeout;
+        private TimeUnit unit;
+        private String tenantId;
+        private Date timestamp;
+    }
+}

+ 217 - 0
coffee-system/src/main/java/com/coffee/bus/hospital/config/HospitalFunctionAnalConfigHandler.java

@@ -0,0 +1,217 @@
+package com.coffee.bus.hospital.config;
+
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.coffee.bus.hospital.config.bean.FunctionAnalConfig;
+import com.coffee.bus.entity.BusDeviceRunningEntity;
+import com.coffee.bus.entity.BusInfusionHistoryEntity;
+import com.coffee.bus.hospital.enums.ConfigHandlerEnums;
+import com.coffee.bus.registry.device.DeviceRegistry;
+import com.coffee.bus.registry.patient.PatientRegistry;
+import com.coffee.bus.service.LocalBusDeviceRunningService;
+import com.coffee.bus.service.LocalBusInfusionHistoryService;
+import com.coffee.bus.utils.WsPublishUtils;
+import com.coffee.common.cache.ConfigStorage;
+import com.coffee.common.util.RedissonUtil;
+import lombok.Builder;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.redisson.api.RDelayedQueue;
+import org.redisson.api.RedissonClient;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.Optional;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName HospitalFunctionAnalConfigHandler.java
+ * @Description 镇痛不足检测
+ * @createTime 2022年05月18日 11:25:00
+ */
+@Slf4j
+public class HospitalFunctionAnalConfigHandler extends AbstractHospitalConfigHandler<FunctionAnalConfig,BusDeviceRunningEntity> {
+
+
+    public HospitalFunctionAnalConfigHandler(ConfigStorage configStorage, String hospitalId, RedissonUtil redissonUtil, LocalBusDeviceRunningService deviceRunningService, LocalBusInfusionHistoryService infusionHistoryService, DeviceRegistry deviceRegistry, WsPublishUtils wsPublishUtils, PatientRegistry patientRegistry) {
+        super(configStorage, hospitalId, redissonUtil, deviceRunningService, infusionHistoryService, deviceRegistry, wsPublishUtils, patientRegistry);
+    }
+
+    @Override
+    public ConfigHandlerEnums getId() {
+        return ConfigHandlerEnums.anal;
+    }
+
+    @Override
+    public String getDescription() {
+        return "进行镇痛不足判定、不在服务区判定、低输注判定";
+    }
+
+
+
+    @Override
+    public void handler(BusDeviceRunningEntity source) {
+        FunctionAnalConfig config = this.getConfig().as(FunctionAnalConfig.class);
+        if(config==null){
+            log.warn("id:{},配置名称:{},不存在",getId(),hospitalId);
+            return;
+        }
+        handlerAnal(source,config);
+    }
+
+    /**
+     * 描述: 镇痛不足处理
+     * 在时间窗口中判断pca是否达到一定次数
+     * @author lifang
+     * @date 2022/5/18 14:05
+     * @param source
+     * @param analConfig
+     * @return void
+     */
+    private void handlerAnal(BusDeviceRunningEntity source,FunctionAnalConfig analConfig){
+        RDelayedQueue delayedQueue = redissonUtil.getDelayedQueue(getId() + "-" + source.getTenantId() + "-" + source.getDeviceId(), e -> {
+            if(e instanceof AnalEntity){
+                this.judgeAnalPoor((AnalEntity) e);
+            }
+        });
+        //如果有新的输注产生,则清空延迟队列
+        if(source.isNewInfusion()){
+            //镇痛不足设置为false
+            source.setWarnAnalgesicPoor(false);
+            delayedQueue.clear();
+        }
+        Integer insufficientTime = analConfig.getInsufficientTime();
+        Integer insufficientCount = analConfig.getInsufficientCount();
+        Boolean valid = analConfig.getValid();
+        if(valid==null||(insufficientTime==null||insufficientTime<=0)||
+                (insufficientCount==null||insufficientCount<=0)){
+            return;
+        }
+
+        AnalEntity anal = AnalEntity.builder()
+                .deviceId(source.getDeviceId())
+                .pcaValidCount(source.getPcaValidCount())
+                .pcaInvalidCount(source.getPcaInvalidCount())
+                .timeout(analConfig.getInsufficientTime())
+                .unit(TimeUnit.MINUTES)
+                .threshold(analConfig.getInsufficientCount())
+                .judgeByValid(analConfig.getValid())
+                .tenantId(source.getTenantId())
+                .timestamp(new Date())
+                .build();
+
+        delayedQueue.offer(anal,anal.getTimeout(),anal.getUnit());
+    }
+
+
+    /**
+     * 描述: 判断延迟任务是否触发镇痛不足
+     * @author lifang
+     * @date 2022/5/19 9:14
+     * @param
+     * @return void
+     */
+    private void judgeAnalPoor(AnalEntity anal){
+        //镇痛消失延迟队列
+        RDelayedQueue noneAnalDelayedQueue = redissonUtil.getDelayedQueue("none-" + getId()+"-" + anal.getTenantId()+"-" + anal.getDeviceId(), e -> {
+            if(e instanceof NoneAnalEntity){
+                handleNoneAnal((NoneAnalEntity) e);
+            }
+        });
+        String deviceId = anal.getDeviceId();
+        BusDeviceRunningEntity runningInfo = deviceRunningService.getOne(new QueryWrapper<BusDeviceRunningEntity>().lambda().eq(BusDeviceRunningEntity::getDeviceId, deviceId).eq(BusDeviceRunningEntity::getTenantId, anal.getTenantId()));
+        if(runningInfo==null){
+            //泵已换绑医院,无需再处理
+            return;
+        }
+        //PCA差值
+        int subCount=0;
+        if(anal.isJudgeByValid()){
+            subCount=Math.subtractExact(runningInfo.getPcaValidCount(), Optional.ofNullable(anal.getPcaValidCount()).orElse(0));
+        }else {
+            subCount=Math.subtractExact(runningInfo.getPcaInvalidCount(), Optional.ofNullable(anal.getPcaInvalidCount()).orElse(0));
+        }
+        if(subCount>anal.getThreshold()){
+            log.info("设备:{}镇痛不足",deviceId);
+            //触发阈值,设置为镇痛不足
+            if(!Boolean.TRUE.equals(runningInfo.getWarnAnalgesicPoor())){
+                deviceRunningService.update(new UpdateWrapper<BusDeviceRunningEntity>().lambda().eq(BusDeviceRunningEntity::getId,runningInfo.getId())
+                        .set(BusDeviceRunningEntity::getWarnAnalgesicPoor,true));
+                infusionHistoryService.update(new UpdateWrapper<BusInfusionHistoryEntity>().lambda().eq(BusInfusionHistoryEntity::getId,runningInfo.getInfusionId())
+                        .set(BusInfusionHistoryEntity::getWarnAnalgesicPoor,true));
+                //报警/提醒缓存重置
+                deviceRegistry.getOperator(deviceId).setAlarmOrWarn(null);
+                if(Boolean.TRUE.equals(runningInfo.getMaster())){
+                    //发布推送
+                    wsPublishUtils.publishPatientMonitor(runningInfo.getPatientCode(),runningInfo.getTenantId());
+                }
+                //设置镇痛不足后,设置镇痛消失延迟时间
+            }
+            noneAnalDelayedQueue.clear();
+        }else {
+            //没有触发阈值,发入镇痛消失处理
+            FunctionAnalConfig config = this.getConfig().as(FunctionAnalConfig.class);
+            NoneAnalEntity noneAnal = NoneAnalEntity.builder()
+                    .deviceId(anal.getDeviceId())
+                    .tenantId(anal.getTenantId())
+                    .timeout(config.getDisappearTime())
+                    .unit(TimeUnit.MINUTES)
+                    .timestamp(new Date())
+                    .build();
+            noneAnalDelayedQueue.offer(noneAnal,noneAnal.getTimeout(),noneAnal.getUnit());
+        }
+    }
+
+
+    private void handleNoneAnal(NoneAnalEntity noneAnal){
+        String deviceId = noneAnal.getDeviceId();
+        BusDeviceRunningEntity runningInfo = deviceRunningService.getOne(new QueryWrapper<BusDeviceRunningEntity>().lambda().eq(BusDeviceRunningEntity::getDeviceId, deviceId).eq(BusDeviceRunningEntity::getTenantId, noneAnal.getTenantId()));
+        if(runningInfo==null){
+            //泵已换绑医院,无需再处理
+            return;
+        }
+        //将设备由镇痛不足取消成功
+        if (deviceRunningService.update(new UpdateWrapper<BusDeviceRunningEntity>().lambda().eq(BusDeviceRunningEntity::getId, runningInfo.getId())
+                .eq(BusDeviceRunningEntity::getWarnAnalgesicPoor, true)
+                .set(BusDeviceRunningEntity::getWarnAnalgesicPoor, false))) {
+            log.info("设备:{}取消镇痛不足",deviceId);
+            infusionHistoryService.update(new UpdateWrapper<BusInfusionHistoryEntity>().lambda().eq(BusInfusionHistoryEntity::getId,runningInfo.getInfusionId())
+                    .set(BusInfusionHistoryEntity::getWarnAnalgesicPoor,false));
+            deviceRegistry.getOperator(deviceId).setAlarmOrWarn(null);
+            if(Boolean.TRUE.equals(runningInfo.getMaster())){
+                //发布推送
+                wsPublishUtils.publishPatientMonitor(runningInfo.getPatientCode(),runningInfo.getTenantId());
+            }
+        }
+
+
+
+    }
+    @Data
+    @Builder
+    static class AnalEntity implements Serializable {
+        private String deviceId;
+        private Integer pcaValidCount;
+        private Integer pcaInvalidCount;
+        private Integer timeout;
+        private TimeUnit unit;
+        private Integer threshold;
+        private boolean judgeByValid;
+        private String tenantId;
+        private Date timestamp;
+    }
+
+    @Data
+    @Builder
+    static class NoneAnalEntity implements Serializable {
+        private String deviceId;
+        private Integer timeout;
+        private TimeUnit unit;
+        private String tenantId;
+        private Date timestamp;
+    }
+
+}

+ 220 - 0
coffee-system/src/main/java/com/coffee/bus/hospital/config/HospitalFunctionExtraConfigHandler.java

@@ -0,0 +1,220 @@
+package com.coffee.bus.hospital.config;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.coffee.bus.enums.ConfigEnum;
+import com.coffee.bus.hospital.config.bean.FunctionExtraConfig;
+import com.coffee.bus.entity.BusDeviceRunningEntity;
+import com.coffee.bus.entity.BusInfusionHistoryEntity;
+import com.coffee.bus.enums.DeviceStatusEnum;
+import com.coffee.bus.enums.DeviceTypeEnum;
+import com.coffee.bus.hospital.enums.ConfigHandlerEnums;
+import com.coffee.bus.registry.device.DeviceRegistry;
+import com.coffee.bus.registry.patient.PatientRegistry;
+import com.coffee.bus.service.LocalBusDeviceRunningService;
+import com.coffee.bus.service.LocalBusInfusionHistoryService;
+import com.coffee.bus.utils.WsPublishUtils;
+import com.coffee.common.cache.ConfigStorage;
+import com.coffee.common.util.RedissonUtil;
+import lombok.Builder;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.redisson.api.RDelayedQueue;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName HospitalFunctionLowInfusionConfigHandler.java
+ * @Description 低输注判断处理
+ * 不在服务区处理:当设备下线时,且最后一个包不为关机包,则开启延迟任务进行不在服务区处理判断
+ * 低输注处理:当设备持续发送输注下限时,开启低输注延迟任务,当输注>输注下限时,撤销所有延迟任务
+ * @createTime 2022年05月19日 15:13:00
+ */
+@Slf4j
+public class HospitalFunctionExtraConfigHandler  extends  AbstractHospitalConfigHandler<FunctionExtraConfig, BusDeviceRunningEntity>{
+
+    private HospitalFinishMonitorConfigHandler monitorConfigHandler;
+    private HospitalAutoUndoConfigHandler autoUndoConfigHandler;
+    public HospitalFunctionExtraConfigHandler(ConfigStorage configStorage, String hospitalId, RedissonUtil redissonUtil, LocalBusDeviceRunningService deviceRunningService, LocalBusInfusionHistoryService infusionHistoryService, DeviceRegistry deviceRegistry, WsPublishUtils wsPublishUtils, PatientRegistry patientRegistry
+    , HospitalFinishMonitorConfigHandler monitorConfigHandler,HospitalAutoUndoConfigHandler autoUndoConfigHandler) {
+        super(configStorage, hospitalId, redissonUtil, deviceRunningService, infusionHistoryService, deviceRegistry, wsPublishUtils, patientRegistry);
+        this.monitorConfigHandler=monitorConfigHandler;
+        this.autoUndoConfigHandler=autoUndoConfigHandler;
+    }
+
+    @Override
+    public ConfigHandlerEnums getId() {
+        return ConfigHandlerEnums.extra;
+    }
+
+    @Override
+    public String getDescription() {
+        return "医院其他配置处理,不在服务区设置、低输注设置";
+    }
+
+    @Override
+    public void handler(BusDeviceRunningEntity source) {
+        FunctionExtraConfig config = this.getConfig().as(FunctionExtraConfig.class);
+        if(config==null){
+            log.warn("id:{},配置名称:{},不存在",getId(),hospitalId);
+            return;
+        }
+        if (config.getNoSignal()!=null&&config.getNoSignal()>0) {
+            judgeNoSignal(source,config.getNoSignal());
+        }
+        if (config.getLowInfusion()!=null&&config.getLowInfusion()>0) {
+            judgeLowInfusion(source,config.getLowInfusion());
+        }
+    }
+
+    /**
+     * 描述: 不在服务区处理
+     * @author lifang
+     * @date 2022/5/19 15:52
+     * @param source
+     * @param interval
+     * @return void
+     */
+    private void judgeNoSignal(BusDeviceRunningEntity source,int interval){
+        RDelayedQueue delayedQueue = redissonUtil.getDelayedQueue(getId() +"-signal"+ "-" + source.getTenantId() + "-" + source.getDeviceId(), e -> {
+            if(e instanceof  NoSignalEntity){
+                this.handleNoSignal((NoSignalEntity) e);
+            }
+        });
+        //清空延迟队列消息
+        delayedQueue.clear();
+
+        NoSignalEntity noSignal = NoSignalEntity.builder()
+                .deviceId(source.getDeviceId())
+                .patientCode(source.getPatientCode())
+                .tenantId(source.getTenantId())
+                .timestamp(new Date())
+                .timeout(interval)
+                .unit(TimeUnit.MINUTES)
+                .build();
+        //将该次消息视为最后一次消息放入队列中
+        delayedQueue.offer(noSignal,noSignal.getTimeout(),noSignal.getUnit());
+    }
+
+    /**
+     * 描述: 不在服务区处理
+     * @author lifang
+     * @date 2022/5/19 16:02
+     * @param source
+     * @return void
+     */
+    private void handleNoSignal(NoSignalEntity source){
+        String deviceId = source.getDeviceId();
+        String tenantId = source.getTenantId();
+        BusDeviceRunningEntity runningInfo = deviceRunningService.getOne(new QueryWrapper<BusDeviceRunningEntity>().lambda().eq(BusDeviceRunningEntity::getDeviceId, deviceId).eq(BusDeviceRunningEntity::getTenantId, tenantId));
+        if (runningInfo == null) {
+            //泵已换绑医院,无需再处理
+            return;
+        }
+        deviceRunningService.update(new UpdateWrapper<BusDeviceRunningEntity>().lambda().eq(BusDeviceRunningEntity::getId, runningInfo.getId())
+                .set(BusDeviceRunningEntity::getRunState, DeviceStatusEnum.NoSignal));
+        infusionHistoryService.update(new UpdateWrapper<BusInfusionHistoryEntity>().lambda().eq(BusInfusionHistoryEntity::getId, runningInfo.getInfusionId())
+                .set(BusInfusionHistoryEntity::getRunState, DeviceStatusEnum.NoSignal));
+        //报警/提醒缓存重置
+        deviceRegistry.getOperator(deviceId)
+                .setStatus(DeviceStatusEnum.NoSignal);
+        if (Boolean.TRUE.equals(runningInfo.getMaster())) {
+            //发布推送
+            wsPublishUtils.publishPatientMonitor(runningInfo.getPatientCode(), runningInfo.getTenantId());
+        }
+        //不在服务区
+        monitorConfigHandler.judgeNoSignal(deviceId,source.getPatientCode(),source.getTenantId());
+        autoUndoConfigHandler.judgeNoSignal(deviceId,source.getPatientCode(),source.getTenantId());
+    }
+
+
+    /**
+     * 描述: 低输注判断
+     * @author lifang
+     * @date 2022/5/19 15:52
+     * @param source
+     * @param interval
+     * @return void
+     */
+    private void judgeLowInfusion(BusDeviceRunningEntity source,int interval){
+        RDelayedQueue delayedQueue = redissonUtil.getDelayedQueue(getId() +"-lowFusion"+ "-" + source.getTenantId() + "-" + source.getDeviceId(), e -> {
+            if(e instanceof  LowInfusionEntity){
+                handleLowInfusion((LowInfusionEntity)e);
+            }
+        });
+        //仅智能泵存在
+        if(DeviceTypeEnum.intelligent.equals(source.getType())){
+            if (source.getFlowDownLimit()!=null&&source.getFlowDownLimit().compareTo(BigDecimal.valueOf(0.1))<1) {
+                //输注量超过阈值,进行低输注判定
+                LowInfusionEntity lowInfusionEntity = LowInfusionEntity.builder()
+                        .deviceId(source.getDeviceId())
+                        .timeout(interval)
+                        .unit(TimeUnit.MINUTES)
+                        .tenantId(source.getTenantId())
+                        .timestamp(new Date())
+                        .build();
+                delayedQueue.offer(lowInfusionEntity,lowInfusionEntity.getTimeout(),lowInfusionEntity.getUnit());
+            }
+
+
+
+        }else {
+            //输注量未超过阈值,取消低输注状态
+            source.setWarnLowBattery(false);
+            delayedQueue.clear();
+        }
+    }
+
+    /**
+     * 描述: 低输注状态处理
+     * @author lifang
+     * @date 2022/5/19 16:08
+     * @param source
+     * @return void
+     */
+    private void handleLowInfusion(LowInfusionEntity source) {
+        String deviceId = source.getDeviceId();
+        String tenantId = source.getTenantId();
+        BusDeviceRunningEntity runningInfo = deviceRunningService.getOne(new QueryWrapper<BusDeviceRunningEntity>().lambda().eq(BusDeviceRunningEntity::getDeviceId, deviceId).eq(BusDeviceRunningEntity::getTenantId, tenantId));
+        if (runningInfo == null) {
+            //泵已换绑医院,无需再处理
+            return;
+        }
+        deviceRunningService.update(new UpdateWrapper<BusDeviceRunningEntity>().lambda().eq(BusDeviceRunningEntity::getId, runningInfo.getId())
+                .set(BusDeviceRunningEntity::getWarnLowBattery, true));
+        infusionHistoryService.update(new UpdateWrapper<BusInfusionHistoryEntity>().lambda().eq(BusInfusionHistoryEntity::getId, runningInfo.getInfusionId())
+                .set(BusInfusionHistoryEntity::getWarnLowBattery, true));
+        //报警/提醒缓存重置
+        deviceRegistry.getOperator(deviceId).setAlarmOrWarn(null);
+        if (Boolean.TRUE.equals(runningInfo.getMaster())) {
+            //发布推送
+            wsPublishUtils.publishPatientMonitor(runningInfo.getPatientCode(), runningInfo.getTenantId());
+        }
+    }
+
+    @Data
+    @Builder
+    static class NoSignalEntity implements Serializable {
+        private String deviceId;
+        private String patientCode;
+        private Integer timeout;
+        private TimeUnit unit;
+        private String tenantId;
+        private Date timestamp;
+    }
+
+    @Data
+    @Builder
+    static class LowInfusionEntity implements Serializable {
+        private String deviceId;
+        private Integer timeout;
+        private TimeUnit unit;
+        private String tenantId;
+        private Date timestamp;
+    }
+}

+ 4 - 2
coffee-system/src/main/java/com/coffee/bus/service/dto/function/FunctionAnalConfig.java → coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionAnalConfig.java

@@ -1,9 +1,11 @@
-package com.coffee.bus.service.dto.function;
+package com.coffee.bus.hospital.config.bean;
 
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
+import java.io.Serializable;
+
 /**
  * @author lifang
  * @version 1.0.0
@@ -13,7 +15,7 @@ import lombok.Data;
  */
 @ApiModel("镇痛不足配置")
 @Data
-public class FunctionAnalConfig {
+public class FunctionAnalConfig implements Serializable {
     @ApiModelProperty("镇痛不足提醒消失时间")
     private Integer disappearTime;
     @ApiModelProperty("镇痛不足判定次数")

+ 4 - 2
coffee-system/src/main/java/com/coffee/bus/service/dto/function/FunctionAutoUndoConfig.java → coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionAutoUndoConfig.java

@@ -1,9 +1,11 @@
-package com.coffee.bus.service.dto.function;
+package com.coffee.bus.hospital.config.bean;
 
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
+import java.io.Serializable;
+
 /**
  * @author lifang
  * @version 1.0.0
@@ -13,7 +15,7 @@ import lombok.Data;
  */
 @ApiModel("自动撤泵配置")
 @Data
-public class FunctionAutoUndoConfig {
+public class FunctionAutoUndoConfig implements Serializable {
     @ApiModelProperty("是否开启自动撤泵")
     private boolean enable;
     @ApiModelProperty("不在服务区撤泵时间间隔")

+ 6 - 2
coffee-system/src/main/java/com/coffee/bus/service/dto/function/FunctionExtraConfig.java → coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionExtraConfig.java

@@ -1,7 +1,10 @@
-package com.coffee.bus.service.dto.function;
+package com.coffee.bus.hospital.config.bean;
 
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
 
 /**
  * @author lifang
@@ -11,7 +14,8 @@ import io.swagger.annotations.ApiModelProperty;
  * @createTime 2022年05月18日 10:22:00
  */
 @ApiModel("其他配置中的其他配置")
-public class FunctionExtraConfig {
+@Data
+public class FunctionExtraConfig implements Serializable {
     @ApiModelProperty("低输注时间设置")
     private Integer lowInfusion;
     @ApiModelProperty("不在服务区时间设置")

+ 28 - 0
coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionFinishMonitorConfig.java

@@ -0,0 +1,28 @@
+package com.coffee.bus.hospital.config.bean;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName FunctionUndoConfig.java
+ * @Description TODO
+ * @createTime 2022年05月18日 08:33:00
+ */
+@ApiModel("结束管理功能配置")
+@Data
+public class FunctionFinishMonitorConfig implements Serializable {
+    @ApiModelProperty("是否开启自动结束管理")
+    private boolean enable;
+    @ApiModelProperty("关机到结束时间间隔")
+    private Integer shutDownInterval;
+    @ApiModelProperty("自动撤泵人姓名")
+    private String undoBy;
+    @ApiModelProperty("不在服务区到结束时间")
+    private Integer noSignalInterval;
+
+}

+ 4 - 2
coffee-system/src/main/java/com/coffee/bus/service/dto/function/FunctionManualUndoConfig.java → coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionManualUndoConfig.java

@@ -1,9 +1,11 @@
-package com.coffee.bus.service.dto.function;
+package com.coffee.bus.hospital.config.bean;
 
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
+import java.io.Serializable;
+
 /**
  * @author lifang
  * @version 1.0.0
@@ -13,7 +15,7 @@ import lombok.Data;
  */
 @ApiModel("手动撤泵配置")
 @Data
-public class FunctionManualUndoConfig {
+public class FunctionManualUndoConfig implements Serializable {
     @ApiModelProperty("是否开启手动撤泵配置")
     private boolean enable;
     @ApiModelProperty("撤泵人为空检测")

+ 5 - 3
coffee-system/src/main/java/com/coffee/bus/service/dto/function/FunctionOtherConfig.java → coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionOtherConfig.java

@@ -1,9 +1,11 @@
-package com.coffee.bus.service.dto.function;
+package com.coffee.bus.hospital.config.bean;
 
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
+import java.io.Serializable;
+
 /**
  * @author lifang
  * @version 1.0.0
@@ -13,9 +15,9 @@ import lombok.Data;
  */
 @Data
 @ApiModel("其他配置")
-public class FunctionOtherConfig {
+public class FunctionOtherConfig implements Serializable {
     @ApiModelProperty("其他配置")
-    private FunctionExtraConfig other;
+    private FunctionExtraConfig extra;
     @ApiModelProperty("镇痛不足配置")
     private FunctionAnalConfig anal;
 }

+ 6 - 4
coffee-system/src/main/java/com/coffee/bus/service/dto/function/FunctionUndoConfig.java → coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionUndoConfig.java

@@ -1,7 +1,8 @@
-package com.coffee.bus.service.dto.function;
+package com.coffee.bus.hospital.config.bean;
 
 import io.swagger.annotations.ApiModel;
 import lombok.Data;
+import java.io.Serializable;
 
 /**
  * @author lifang
@@ -10,11 +11,12 @@ import lombok.Data;
  * @Description TODO
  * @createTime 2022年05月18日 08:33:00
  */
-@ApiModel("撤泵功能配置")
+@ApiModel("结束管理功能配置")
 @Data
-public class FunctionUndoConfig {
+public class FunctionUndoConfig implements Serializable {
+    private FunctionFinishMonitorConfig finishMonitor;
+
     private FunctionAutoUndoConfig auto;
 
     private FunctionManualUndoConfig manual;
-
 }

+ 22 - 0
coffee-system/src/main/java/com/coffee/bus/hospital/enums/ConfigHandlerEnums.java

@@ -0,0 +1,22 @@
+package com.coffee.bus.hospital.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName ConfigHandlerEnums.java
+ * @Description 功能配置类型
+ * @createTime 2022年05月20日 08:37:00
+ */
+@AllArgsConstructor
+public enum ConfigHandlerEnums {
+    autoUndo("自动撤泵配置"),
+    finishMonitor("自动结束管理配置"),
+    anal("镇痛不足配置"),
+    extra("其他配置");
+
+    @Getter
+    private String description;
+}

+ 3 - 3
coffee-system/src/main/java/com/coffee/bus/his/HisRequest.java → coffee-system/src/main/java/com/coffee/bus/hospital/his/HisRequest.java

@@ -1,4 +1,4 @@
-package com.coffee.bus.his;
+package com.coffee.bus.hospital.his;
 
 import com.coffee.bus.entity.BusClinicEntity;
 import com.coffee.common.result.R;
@@ -8,7 +8,7 @@ import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 import org.springframework.web.context.request.async.DeferredResult;
-
+import java.util.*;
 import javax.validation.constraints.NotNull;
 import java.io.Serializable;
 import java.util.Date;
@@ -77,5 +77,5 @@ public class HisRequest implements Serializable {
      */
     @JsonIgnore
     @NotNull
-    private DeferredResult<R<BusClinicEntity>> result;
+    private List<DeferredResult<R<BusClinicEntity>>> result;
 }

+ 1 - 1
coffee-system/src/main/java/com/coffee/bus/his/HisResponse.java → coffee-system/src/main/java/com/coffee/bus/hospital/his/HisResponse.java

@@ -1,4 +1,4 @@
-package com.coffee.bus.his;
+package com.coffee.bus.hospital.his;
 
 import lombok.Data;
 

+ 34 - 41
coffee-system/src/main/java/com/coffee/bus/his/HisScriptSession.java → coffee-system/src/main/java/com/coffee/bus/hospital/his/HisScriptSession.java

@@ -1,4 +1,4 @@
-package com.coffee.bus.his;
+package com.coffee.bus.hospital.his;
 
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollectionUtil;
@@ -14,19 +14,18 @@ import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.coffee.bus.entity.BusClinicEntity;
 import com.coffee.bus.entity.BusHospitalEntity;
 import com.coffee.bus.listener.event.bean.HisEvent;
-import com.coffee.bus.script.DefaultParse;
-import com.coffee.bus.script.ExecuteResult;
-import com.coffee.bus.script.ScriptManager;
-import com.coffee.bus.script.ScriptParse;
+import com.coffee.bus.hospital.script.DefaultParse;
+import com.coffee.bus.hospital.script.ExecuteResult;
+import com.coffee.bus.hospital.script.ScriptManager;
+import com.coffee.bus.hospital.script.ScriptParse;
 import com.coffee.bus.service.LocalBusClinicService;
 import com.coffee.bus.service.LocalBusHospitalService;
-import com.coffee.common.cache.ClusterConfigStorage;
+import com.coffee.common.cache.ConfigStorage;
+import com.coffee.common.cache.manager.ConfigStorageManager;
 import com.coffee.common.cache.value.Value;
 import com.coffee.common.exception.CustomException;
 import com.coffee.common.result.R;
 import lombok.extern.slf4j.Slf4j;
-import org.redisson.api.RedissonClient;
-import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.util.Assert;
 import org.springframework.web.context.request.async.DeferredResult;
 import org.tio.core.ChannelContext;
@@ -54,35 +53,20 @@ public class HisScriptSession {
     private ChannelContext channelContext;
     private ScriptManager scriptManager;
     private LocalBusClinicService clinicService;
-    private ClusterConfigStorage clusterConfigStorage;
+    private ConfigStorage clusterConfigStorage;
     private LocalBusHospitalService hospitalService;
     private Map<String,HisRequest> hisRequestMap=new ConcurrentHashMap<>();
 
-    public HisScriptSession(String hospitalId, ChannelContext channelContext, ScriptManager scriptManager,
-                            RedissonClient redissonClient, LocalBusClinicService clinicService, LocalBusHospitalService hospitalService) {
+    public HisScriptSession(String hospitalId, ScriptManager scriptManager, ConfigStorageManager configStorageManager, LocalBusClinicService clinicService, LocalBusHospitalService hospitalService) {
         this.hospitalId = hospitalId;
-        this.channelContext = channelContext;
         this.scriptManager = scriptManager;
         this.clinicService = clinicService;
         this.hospitalService=hospitalService;
-        init(redissonClient,hospitalId,hospitalService);
+        init(configStorageManager,hospitalId);
     }
 
-    public HisScriptSession(String hospitalId, ScriptManager scriptManager, RedissonClient redissonClient, LocalBusClinicService clinicService,LocalBusHospitalService hospitalService) {
-        this.hospitalId = hospitalId;
-        this.scriptManager = scriptManager;
-        this.clinicService = clinicService;
-        this.hospitalService=hospitalService;
-        init(redissonClient,hospitalId,hospitalService);
-    }
-
-    private void init(RedissonClient redissonClient, String hospitalId, LocalBusHospitalService hospitalService){
-        BusHospitalEntity hospital = hospitalService.getById(hospitalId);
-        if(hospital==null){
-            throw new RuntimeException(String.format("医院{%s}不存在,获取医院脚本会话失败",hospitalId));
-        }
-        clusterConfigStorage=new ClusterConfigStorage(redissonClient,hospitalId);
-        clusterConfigStorage.setConfig("info",hospital);
+    private void init(ConfigStorageManager configStorageManager, String hospitalId){
+        clusterConfigStorage = configStorageManager.getStorage(hospitalId);
     }
 
     /**
@@ -127,7 +111,7 @@ public class HisScriptSession {
                 .sync(true)
                 .timeout(timeout)
                 .timeUnit(unit)
-                .result(result)
+                .result(Arrays.asList(result))
                 .timestamp(new Date())
                 .build();
         sendRequest(channelContext,request);
@@ -164,7 +148,7 @@ public class HisScriptSession {
                 .sync(true)
                 .timeout(timeout)
                 .timeUnit(unit)
-                .result(result)
+                .result(Arrays.asList(result))
                 .timestamp(new Date())
                 .build();
         result.onTimeout(()->{
@@ -256,6 +240,7 @@ public class HisScriptSession {
      * @return void
      */
     private ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
+
     private void sendRequest(ChannelContext channelContext,HisRequest request){
         hisRequestMap.put(request.getMessageId(),request);
         Tio.send(channelContext, WsResponse.fromText(JSONUtil.toJsonStr(request),"utf-8"));
@@ -301,22 +286,30 @@ public class HisScriptSession {
                 Date requestTimestamp = hisRequest.getTimestamp();
                 long timeout = hisRequest.getTimeout();
                 TimeUnit timeUnit = hisRequest.getTimeUnit();
-                DeferredResult<R<BusClinicEntity>> result = hisRequest.getResult();
-                if (requestTimestamp.getTime()+timeUnit.toMillis(timeout)>responseTimestamp.getTime()) {
-                    log.warn("请求[{}]已超时,请求时间[{}],响应时间[{}],是否为同步请求[{}]",messageId,requestTimestamp,responseTimestamp,sync);
-                    if(sync){
-                        result.setErrorResult("响应超时");
-                        return;
-                    }
+                List<DeferredResult<R<BusClinicEntity>>> results = hisRequest.getResult();
+                if(CollectionUtil.isNotEmpty(results)){
+                    results.parallelStream().forEach(result->{
+                        if (requestTimestamp.getTime()+timeUnit.toMillis(timeout)>responseTimestamp.getTime()) {
+                            log.warn("请求[{}]已超时,请求时间[{}],响应时间[{}],是否为同步请求[{}]",messageId,requestTimestamp,responseTimestamp,sync);
+                            if(sync){
+                                result.setErrorResult("响应超时");
+                                return;
+                            }
+                        }
+                        //正常响应
+                        BusClinicEntity clinic = handle(Value.simple(hisResponse.getContext()).asString(), hisResponse.getPatientCode());
+                        result.setResult(R.success(clinic));
+                    });
                 }
-                //正常响应
-                BusClinicEntity clinic = handle(Value.simple(hisResponse.getContext()).asString(), hisResponse.getPatientCode());
-                result.setResult(R.success(clinic));
+
             }
         }else {
             if (hisRequest != null) {
                 log.warn("医院[{}]拉取信息失败,失败原因[{}]",hospitalId,hisResponse.getErrorMsg());
-                hisRequest.getResult().setResult(R.fail("更新失败,失败原因["+ hisResponse.getErrorMsg()+"]"));
+                 List<DeferredResult<R<BusClinicEntity>>> results = hisRequest.getResult();
+                if(CollectionUtil.isNotEmpty(results)){
+                    results.parallelStream().forEach(result-> result.setResult(R.fail("更新失败,失败原因["+ hisResponse.getErrorMsg()+"]")));
+                }
             }
         }
     }

+ 7 - 7
coffee-system/src/main/java/com/coffee/bus/his/HisScriptSessionManager.java → coffee-system/src/main/java/com/coffee/bus/hospital/his/HisScriptSessionManager.java

@@ -1,11 +1,11 @@
-package com.coffee.bus.his;
+package com.coffee.bus.hospital.his;
 
-import com.coffee.bus.script.ScriptManager;
+import com.coffee.bus.hospital.script.ScriptManager;
 import com.coffee.bus.service.LocalBusClinicService;
 import com.coffee.bus.service.LocalBusHospitalService;
+import com.coffee.common.cache.manager.ClusterConfigStorageManager;
 import org.redisson.api.RedissonClient;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Component;
 
 import java.util.Map;
@@ -23,15 +23,15 @@ public class HisScriptSessionManager {
     private Map<String,HisScriptSession> sessionMap=new ConcurrentHashMap<>();
     private LocalBusClinicService clinicService;
     private ScriptManager scriptManager;
-    private RedissonClient redissonClient;
     private LocalBusHospitalService hospitalService;
+    private ClusterConfigStorageManager configStorageManager;
 
     @Autowired
-    public HisScriptSessionManager(LocalBusClinicService clinicService, ScriptManager scriptManager, RedissonClient redissonClient, LocalBusHospitalService hospitalService) {
+    public HisScriptSessionManager( LocalBusClinicService clinicService, ScriptManager scriptManager, LocalBusHospitalService hospitalService, ClusterConfigStorageManager configStorageManager) {
         this.clinicService = clinicService;
         this.scriptManager = scriptManager;
-        this.redissonClient = redissonClient;
         this.hospitalService = hospitalService;
+        this.configStorageManager = configStorageManager;
     }
 
     /**
@@ -53,7 +53,7 @@ public class HisScriptSessionManager {
      * @return HisScriptSession
      */
     public HisScriptSession register(String hospitalId){
-        return new HisScriptSession(hospitalId, scriptManager,redissonClient, clinicService,hospitalService);
+        return new HisScriptSession(hospitalId, scriptManager,configStorageManager, clinicService,hospitalService);
     }
 
     /**

+ 15 - 1
coffee-system/src/main/java/com/coffee/bus/his/strategy/HisStrategyEnum.java → coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/HisStrategyEnum.java

@@ -1,4 +1,4 @@
-package com.coffee.bus.his.strategy;
+package com.coffee.bus.hospital.his.strategy;
 
 import com.baomidou.mybatisplus.annotation.IEnum;
 import lombok.AllArgsConstructor;
@@ -14,6 +14,7 @@ import lombok.Getter;
 @AllArgsConstructor
 @Getter
 public enum  HisStrategyEnum  implements IEnum<Integer> {
+    NONE(0,"无his对接"),
     ALL(1,"拉取所有的病人数据"),
     PART(2,"拉取部分病人数据(例、最新三个月)"),
     NEW(3,"只拉取最新的病人数据"),
@@ -22,4 +23,17 @@ public enum  HisStrategyEnum  implements IEnum<Integer> {
     private Integer value;
     private String text;
 
+    public static HisStrategyEnum valueOf(Integer value){
+        switch (value){
+            case 0:
+                return NONE;
+            case 1:
+                return ALL;
+            case 2:
+                return PART;
+            case 3:
+                return NEW;
+            default:return null;
+        }
+    }
 }

+ 1 - 1
coffee-system/src/main/java/com/coffee/bus/his/strategy/HisStrategyHandler.java → coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/HisStrategyHandler.java

@@ -1,4 +1,4 @@
-package com.coffee.bus.his.strategy;
+package com.coffee.bus.hospital.his.strategy;
 
 import com.coffee.bus.entity.BusClinicEntity;
 import java.util.*;

+ 1 - 1
coffee-system/src/main/java/com/coffee/bus/his/strategy/HisStrategyManager.java → coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/HisStrategyManager.java

@@ -1,4 +1,4 @@
-package com.coffee.bus.his.strategy;
+package com.coffee.bus.hospital.his.strategy;
 
 import java.util.*;
 /**

+ 1 - 1
coffee-system/src/main/java/com/coffee/bus/his/strategy/HisStrategyManagerRegister.java → coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/HisStrategyManagerRegister.java

@@ -1,4 +1,4 @@
-package com.coffee.bus.his.strategy;
+package com.coffee.bus.hospital.his.strategy;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;

+ 1 - 4
coffee-system/src/main/java/com/coffee/bus/his/strategy/all/EqualsStrategyHandler.java → coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/all/EqualsStrategyHandler.java

@@ -1,11 +1,9 @@
-package com.coffee.bus.his.strategy.all;
+package com.coffee.bus.hospital.his.strategy.all;
 
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.json.JSONUtil;
-import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.coffee.bus.entity.BusClinicEntity;
 import com.coffee.bus.service.LocalBusClinicService;
-import com.coffee.bus.his.strategy.HisStrategyHandler;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
@@ -13,7 +11,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 import java.util.Comparator;
 import java.util.List;
-import java.util.stream.Collectors;
 
 /**
  * @author lifang

+ 2 - 2
coffee-system/src/main/java/com/coffee/bus/his/strategy/all/HisAllStrategyHandler.java → coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/all/HisAllStrategyHandler.java

@@ -1,6 +1,6 @@
-package com.coffee.bus.his.strategy.all;
+package com.coffee.bus.hospital.his.strategy.all;
 
-import com.coffee.bus.his.strategy.HisStrategyHandler;
+import com.coffee.bus.hospital.his.strategy.HisStrategyHandler;
 
 /**
  * @author lifang

+ 3 - 3
coffee-system/src/main/java/com/coffee/bus/his/strategy/all/HisAllStrategyManager.java → coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/all/HisAllStrategyManager.java

@@ -1,7 +1,7 @@
-package com.coffee.bus.his.strategy.all;
+package com.coffee.bus.hospital.his.strategy.all;
 
-import com.coffee.bus.his.strategy.HisStrategyEnum;
-import com.coffee.bus.his.strategy.HisStrategyManager;
+import com.coffee.bus.hospital.his.strategy.HisStrategyEnum;
+import com.coffee.bus.hospital.his.strategy.HisStrategyManager;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 

+ 1 - 2
coffee-system/src/main/java/com/coffee/bus/his/strategy/all/LessToMoreHisStrategyHandler.java → coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/all/LessToMoreHisStrategyHandler.java

@@ -1,10 +1,9 @@
-package com.coffee.bus.his.strategy.all;
+package com.coffee.bus.hospital.his.strategy.all;
 
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.json.JSONUtil;
 import com.coffee.bus.entity.BusClinicEntity;
 import com.coffee.bus.service.LocalBusClinicService;
-import com.coffee.bus.his.strategy.HisStrategyHandler;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;

+ 1 - 2
coffee-system/src/main/java/com/coffee/bus/his/strategy/all/MoreToLessHisStrategyHandler.java → coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/all/MoreToLessHisStrategyHandler.java

@@ -1,10 +1,9 @@
-package com.coffee.bus.his.strategy.all;
+package com.coffee.bus.hospital.his.strategy.all;
 
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.json.JSONUtil;
 import com.coffee.bus.entity.BusClinicEntity;
 import com.coffee.bus.service.LocalBusClinicService;
-import com.coffee.bus.his.strategy.HisStrategyHandler;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;

+ 1 - 1
coffee-system/src/main/java/com/coffee/bus/his/strategy/onlynew/DefaultHisNewStrategyHandler.java → coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/onlynew/DefaultHisNewStrategyHandler.java

@@ -1,4 +1,4 @@
-package com.coffee.bus.his.strategy.onlynew;
+package com.coffee.bus.hospital.his.strategy.onlynew;
 
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.json.JSONUtil;

+ 2 - 2
coffee-system/src/main/java/com/coffee/bus/his/strategy/onlynew/HisNewStrategyHandler.java → coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/onlynew/HisNewStrategyHandler.java

@@ -1,6 +1,6 @@
-package com.coffee.bus.his.strategy.onlynew;
+package com.coffee.bus.hospital.his.strategy.onlynew;
 
-import com.coffee.bus.his.strategy.HisStrategyHandler;
+import com.coffee.bus.hospital.his.strategy.HisStrategyHandler;
 
 /**
  * @author lifang

+ 3 - 3
coffee-system/src/main/java/com/coffee/bus/his/strategy/onlynew/HisNewStrategyManager.java → coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/onlynew/HisNewStrategyManager.java

@@ -1,7 +1,7 @@
-package com.coffee.bus.his.strategy.onlynew;
+package com.coffee.bus.hospital.his.strategy.onlynew;
 
-import com.coffee.bus.his.strategy.HisStrategyEnum;
-import com.coffee.bus.his.strategy.HisStrategyManager;
+import com.coffee.bus.hospital.his.strategy.HisStrategyEnum;
+import com.coffee.bus.hospital.his.strategy.HisStrategyManager;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;

+ 3 - 3
coffee-system/src/main/java/com/coffee/bus/his/strategy/part/DefaultHisPartStrategyHandler.java → coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/part/DefaultHisPartStrategyHandler.java

@@ -1,10 +1,10 @@
-package com.coffee.bus.his.strategy.part;
+package com.coffee.bus.hospital.his.strategy.part;
 
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.json.JSONUtil;
 import com.coffee.bus.entity.BusClinicEntity;
-import com.coffee.bus.his.strategy.all.HisAllStrategyHandler;
-import com.coffee.bus.his.strategy.onlynew.HisNewStrategyHandler;
+import com.coffee.bus.hospital.his.strategy.all.HisAllStrategyHandler;
+import com.coffee.bus.hospital.his.strategy.onlynew.HisNewStrategyHandler;
 import com.coffee.bus.service.LocalBusClinicService;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;

+ 2 - 2
coffee-system/src/main/java/com/coffee/bus/his/strategy/part/HisPartStrategyHandler.java → coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/part/HisPartStrategyHandler.java

@@ -1,6 +1,6 @@
-package com.coffee.bus.his.strategy.part;
+package com.coffee.bus.hospital.his.strategy.part;
 
-import com.coffee.bus.his.strategy.HisStrategyHandler;
+import com.coffee.bus.hospital.his.strategy.HisStrategyHandler;
 
 /**
  * @author lifang

+ 3 - 3
coffee-system/src/main/java/com/coffee/bus/his/strategy/part/HisPartStrategyManager.java → coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/part/HisPartStrategyManager.java

@@ -1,7 +1,7 @@
-package com.coffee.bus.his.strategy.part;
+package com.coffee.bus.hospital.his.strategy.part;
 
-import com.coffee.bus.his.strategy.HisStrategyEnum;
-import com.coffee.bus.his.strategy.HisStrategyManager;
+import com.coffee.bus.hospital.his.strategy.HisStrategyEnum;
+import com.coffee.bus.hospital.his.strategy.HisStrategyManager;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;

+ 1 - 3
coffee-system/src/main/java/com/coffee/bus/script/DefaultParse.java → coffee-system/src/main/java/com/coffee/bus/hospital/script/DefaultParse.java

@@ -1,7 +1,5 @@
-package com.coffee.bus.script;
+package com.coffee.bus.hospital.script;
 
-import cn.hutool.json.JSON;
-import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
 
 /**

+ 13 - 6
coffee-system/src/main/java/com/coffee/bus/script/ExecuteResult.java → coffee-system/src/main/java/com/coffee/bus/hospital/script/ExecuteResult.java

@@ -1,22 +1,29 @@
-package com.coffee.bus.script;
+package com.coffee.bus.hospital.script;
 
 import cn.hutool.json.JSON;
 import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import javax.script.ScriptException;
 import java.util.function.Supplier;
 @Data
+@ApiModel("脚本执行结果")
 public class ExecuteResult {
+    @ApiModelProperty("脚本是否执行成功")
     private boolean success;
-
+    @ApiModelProperty("脚本输入参数成功")
+    private String input;
+    @ApiModelProperty("脚本输出")
     private JSON result;
-
+    @ApiModelProperty("错误消息")
     private String message;
-
+    @ApiModelProperty("错误类型")
+    @JsonIgnore
     private transient Exception exception;
-
+    @ApiModelProperty("脚本运行时间")
     private long useTime;
 
     public boolean isSuccess() {

+ 27 - 13
coffee-system/src/main/java/com/coffee/bus/script/PythonParse.java → coffee-system/src/main/java/com/coffee/bus/hospital/script/PythonParse.java

@@ -1,8 +1,9 @@
-package com.coffee.bus.script;
+package com.coffee.bus.hospital.script;
 
-import cn.hutool.http.webservice.SoapUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSON;
 import cn.hutool.json.JSONUtil;
+import com.coffee.common.exception.CustomException;
 import lombok.extern.slf4j.Slf4j;
 import org.python.core.*;
 import org.python.util.PythonInterpreter;
@@ -24,13 +25,16 @@ public class PythonParse implements ScriptParse {
     private PyFunction pyFunction;
 
     public PythonParse() {
-//        Properties p = new Properties();
-//        p.setProperty("python.console.encoding", "UTF-8");
-//        PySystemState systemState = Py.getSystemState();
-//        PyString xml = new PyString(Thread.currentThread().getContextClassLoader().getResource("python").getPath());
-//        systemState.path.append(xml);
-//        PythonInterpreter.initialize(System.getProperties(), p, new String[] {});
-//        interpreter = new PythonInterpreter();
+        Properties p = new Properties();
+        p.setProperty("python.console.encoding", "UTF-8");
+        PySystemState systemState = Py.getSystemState();
+//        PyString xml = new PyString("\\python-modules");
+        PyString xml = new PyString("E:\\software\\coffee-boot\\coffee-admin\\src\\main\\resources\\python");
+        systemState.path.append(xml);
+        PythonInterpreter.initialize(System.getProperties(), p, new String[] {});
+
+        interpreter = new PythonInterpreter();
+
     }
 
     @Override
@@ -46,14 +50,25 @@ public class PythonParse implements ScriptParse {
 
     @Override
     public void reset(String script){
-        interpreter.exec(Py.newStringUTF8(script));
+        if(StrUtil.isEmpty(script)){
+            return;
+        }
+        try {
+            interpreter.exec(Py.newStringUTF8(script));
+        }catch (Exception e){
+            throw new CustomException("脚本错误,请检查后重试,"+e.toString());
+        }
         pyFunction = interpreter.get(functionName(), PyFunction.class);
+        if(pyFunction==null){
+            throw new CustomException("脚本不包含方法【{"+functionName()+"}】");
+        }
     }
 
     @Override
     public ExecuteResult exec(String param) {
         ExecuteResult executeResult = new ExecuteResult();
         try {
+            executeResult.setInput(param);
             long start = System.currentTimeMillis();
             PyObject result = pyFunction.__call__(Py.newStringUTF8(param));
             long end = System.currentTimeMillis();
@@ -72,9 +87,8 @@ public class PythonParse implements ScriptParse {
         Properties p = new Properties();
         p.setProperty("python.console.encoding", "UTF-8");
         PySystemState systemState = Py.getSystemState();
-        PyString xml = new PyString("E:\\software\\coffee-boot\\coffee-admin\\src\\main\\resources\\python");
-//        PyString xml = new PyString("_classpath_:python");
-        systemState.path.append(xml);
+        PyString xml = new PyString("\\python-modules");
+        systemState.modules.__add__(xml);
         PythonInterpreter.initialize(System.getProperties(), p, new String[] {});
         PythonInterpreter pythonInterpreter = new PythonInterpreter();
         String str = "# -*- coding: utf-8 -*-\n" +

+ 23 - 16
coffee-system/src/main/java/com/coffee/bus/script/ScriptManager.java → coffee-system/src/main/java/com/coffee/bus/hospital/script/ScriptManager.java

@@ -1,7 +1,8 @@
-package com.coffee.bus.script;
+package com.coffee.bus.hospital.script;
 
 import cn.hutool.core.collection.CollectionUtil;
 import com.coffee.bus.service.LocalBusHospitalService;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.CommandLineRunner;
 import org.springframework.stereotype.Component;
 
@@ -18,7 +19,7 @@ import java.util.stream.Collectors;
  * @createTime 2022年03月27日 17:23:00
  */
 @Component
-public class ScriptManager implements CommandLineRunner {
+public class ScriptManager {
 
     @Resource
     private List<ScriptParse> scriptParseList;
@@ -27,8 +28,9 @@ public class ScriptManager implements CommandLineRunner {
 
     private Map<String,ScriptParse> hospital=new HashMap<>();
 
-    @Resource
-    private LocalBusHospitalService hospitalService;
+    @Autowired
+    private PythonParse pythonParse;
+
     @PostConstruct
     public void init(){
         if(CollectionUtil.isNotEmpty(scriptParseList)){
@@ -58,20 +60,25 @@ public class ScriptManager implements CommandLineRunner {
         hospital.put(hospitalId,scriptParse);
     }
 
+    public ExecuteResult debug(String script,String input){
+        pythonParse.reset(script);
+        return pythonParse.exec(input);
+    }
+
+    /**
+     * 描述: 检查脚本是否编写正确
+     * @author lifang
+     * @date 2022/5/21 19:39
+     * @param script
+     * @param type
+     * @return void
+     */
+    public void check(String script,String type){
+        pythonParse.reset(script);
+    }
+
     public ScriptParse createScript(String scriptId ){
         return new PythonParse();
     }
 
-    @Override
-    public void run(String... args) {
-//        List<BusHospitalEntity> hospitals = hospitalService.list(new QueryWrapper<BusHospitalEntity>().lambda().isNotNull(BusHospitalEntity::getScript));
-//        //将脚本初始化
-//        if(CollectionUtil.isNotEmpty(hospitals)){
-//            hospitals.stream().filter(hospitalEntity -> ObjectUtil.isNotNull(hospitalEntity.getScript())).forEach(hospital -> {
-//
-//                Script script = hospital.getScript();
-//                resetScript(hospital.getId(),script.getId(),script.getContent());
-//            });
-//        }
-    }
 }

+ 1 - 3
coffee-system/src/main/java/com/coffee/bus/script/ScriptParse.java → coffee-system/src/main/java/com/coffee/bus/hospital/script/ScriptParse.java

@@ -1,6 +1,4 @@
-package com.coffee.bus.script;
-
-import cn.hutool.json.JSON;
+package com.coffee.bus.hospital.script;
 
 /**
  * @author lifang

+ 28 - 0
coffee-system/src/main/java/com/coffee/bus/listener/event/bean/DeviceLifecycleEvent.java

@@ -0,0 +1,28 @@
+package com.coffee.bus.listener.event.bean;
+
+import lombok.Getter;
+import org.springframework.context.ApplicationEvent;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName DeviceLifecycleEvent.java
+ * @Description 设备上/下线事件
+ * @createTime 2022年05月19日 15:27:00
+ */
+
+public class DeviceLifecycleEvent extends ApplicationEvent {
+    @Getter
+    private final String deviceId;
+
+    /*
+     * 设备是否上线
+     */
+    @Getter
+    private final boolean online;
+    public DeviceLifecycleEvent(Object source,String deviceId,boolean online) {
+        super(source);
+        this.deviceId=deviceId;
+        this.online=online;
+    }
+}

+ 4 - 0
coffee-system/src/main/java/com/coffee/bus/mapper/BusPatientMapper.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.coffee.bus.entity.BusPatientEntity;
 import com.coffee.bus.entity.PatientDeviceRepeatDomain;
+import com.coffee.bus.enums.PatientAlarmEnum;
 import com.coffee.bus.service.dto.PatientMonitorResult;
 import com.coffee.bus.service.dto.PatientDeviceNoneResult;
 import com.coffee.bus.service.dto.PatientMonitorQuery;
@@ -42,4 +43,7 @@ public interface BusPatientMapper extends BaseMapper<BusPatientEntity> {
     IPage<PatientMonitorResult> selectMonitor(IPage<PatientMonitorResult> page, @Param("query") PatientMonitorQuery query);
 
     PatientMonitorResult findByPatientCode(@Param("tenantId") String tenantId,@Param("patientCode")String patientCode);
+
+
+    long selectAlarmCount(@Param("tenantId") String tenantId,@Param("alarmValue") int alarmValue);
 }

+ 2 - 0
coffee-system/src/main/java/com/coffee/bus/registry/constant/DeviceKeyConstant.java

@@ -20,6 +20,8 @@ public class DeviceKeyConstant {
 
     public static final String START_TIME="startTime";
 
+    public static final String MODIFY_TIME="modifyTime";
+
     public static final String PATIENT_CODE="patientCode";
 
     public static final String STATUS="status";

+ 12 - 2
coffee-system/src/main/java/com/coffee/bus/registry/device/ClusterDeviceOperator.java

@@ -89,6 +89,16 @@ public class ClusterDeviceOperator implements DeviceOperator<DeviceCacheInfo> {
         return getValue(DeviceKeyConstant.START_TIME).asDate();
     }
 
+    @Override
+    public void setModifyTime(Date startTime) {
+        configStorage.setConfig(DeviceKeyConstant.MODIFY_TIME,startTime);
+    }
+
+    @Override
+    public Date getModifyTime() {
+        return getValue(DeviceKeyConstant.MODIFY_TIME).asDate();
+    }
+
     @Override
     public void setPatientCode(String patientCode) {
         configStorage.setConfig(DeviceKeyConstant.PATIENT_CODE,patientCode);
@@ -125,12 +135,12 @@ public class ClusterDeviceOperator implements DeviceOperator<DeviceCacheInfo> {
     }
 
     @Override
-    public void setAlarm(String alarm) {
+    public void setAlarmOrWarn(String alarm) {
         configStorage.setConfig(DeviceKeyConstant.ALARM,alarm);
     }
 
     @Override
-    public String getAlarm() {
+    public String getAlarmOrWarn() {
         return getValue(DeviceKeyConstant.ALARM).asString();
     }
 

+ 1 - 1
coffee-system/src/main/java/com/coffee/bus/registry/device/ClusterDeviceRegistry.java

@@ -67,7 +67,7 @@ public class ClusterDeviceRegistry implements DeviceRegistry {
                     }
                 }
                 if (BusDeviceAlarmEntity.alarmOrWarn(runningInfo)) {
-                    deviceOperator.setAlarm(BusDeviceAlarmEntity.parseRunning(runningInfo).signParm(DeviceInfoListener.sign));
+                    deviceOperator.setAlarmOrWarn(BusDeviceAlarmEntity.parseRunning(runningInfo).signParm(DeviceInfoListener.sign));
                 }
                 deviceOperator.setMaster(runningInfo.getMaster());
                 deviceOperator.setStartTime(runningInfo.getStartTime());

+ 16 - 4
coffee-system/src/main/java/com/coffee/bus/registry/device/DeviceOperator.java

@@ -90,6 +90,18 @@ public interface DeviceOperator<T> extends Operator<T> {
      */
     Date getStartTime();
 
+    /**
+     * 设置设备开机时间
+     * @param startTime
+     */
+    void setModifyTime(Date startTime);
+
+    /**
+     * 获取设备开机时间
+     * @return
+     */
+    Date getModifyTime();
+
     /**
      * 设置设备当前绑定泵号
      * @param patientCode
@@ -139,16 +151,16 @@ public interface DeviceOperator<T> extends Operator<T> {
     String getInfusionId();
 
     /**
-     * 设置当前设备报警信息
+     * 设置当前设备报警(提醒)信息
      * @param alarm
      */
-    void setAlarm(String alarm);
+    void setAlarmOrWarn(String alarm);
 
     /**
-     * 获取当前设备报警信息
+     * 获取当前设备报警(提醒)信息
      * @return
      */
-    String getAlarm();
+    String getAlarmOrWarn();
 
     /**
      * 设置当前设备输注参数

+ 0 - 3
coffee-system/src/main/java/com/coffee/bus/registry/patient/ClusterPatientOperator.java

@@ -1,7 +1,5 @@
 package com.coffee.bus.registry.patient;
 
-import cn.hutool.core.collection.CollectionUtil;
-import cn.hutool.json.JSONUtil;
 import com.coffee.bus.registry.constant.PatientKeyConstant;
 import com.coffee.bus.registry.patient.bean.DeviceTimeSmallInfo;
 import com.coffee.bus.registry.patient.bean.PatientCacheInfo;
@@ -9,7 +7,6 @@ import com.coffee.common.cache.ConfigStorage;
 import com.coffee.common.enums.SexEnum;
 
 import java.util.*;
-import java.util.stream.Collectors;
 
 /**
  * @author lifang

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

@@ -96,7 +96,6 @@ public class ClusterPatientRegistry implements PatientRegistry {
             patientOperator.setWard(clinic.getWard());
             patientOperator.setBedNo(clinic.getBedNo());
             patientOperator.setClinicId(clinic.getId());
-            patientOperator.setFinished(clinic.getFinished());
             //填充输注信息
             BusInfusionHistoryEntity recentInfusion = infusionService.recentInfusionByPatientCode(hospitalId, patientCode);
             if(recentInfusion!=null){
@@ -108,6 +107,7 @@ public class ClusterPatientRegistry implements PatientRegistry {
                     clinic.setFinished(true);
                 }
             }
+            patientOperator.setFinished(clinic.getFinished());
             //填充主副泵信息
             List<BusDeviceRunningEntity> runningList = deviceRunningService.list(new QueryWrapper<BusDeviceRunningEntity>().lambda().eq(BusDeviceRunningEntity::getPatientCode, patientCode).eq(BusDeviceRunningEntity::getTenantId, hospitalId));
             if (CollectionUtil.isNotEmpty(runningList)) {

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

@@ -102,6 +102,7 @@ public class LocalBusClinicService extends BaseService<BusClinicMapper, BusClini
                 .map(BusClinicEntity::getPatientCode)
                 .map(code->patientRegistry.getOperator(tenantId,code))
                 .forEach(operator->operator.setFinished(true));
+        wsPublishUtils.publishMonitorTotalCount(tenantId);
     }
 
     /**

+ 1 - 5
coffee-system/src/main/java/com/coffee/bus/service/LocalBusDeviceRunningService.java

@@ -96,7 +96,7 @@ public class LocalBusDeviceRunningService extends BaseService<BusDeviceRunningMa
         if(finishClinic){
             Map<String, List<ManualUndoConfig>> configsMap = undoConfigs.stream().collect(Collectors.groupingBy(ManualUndoConfig::getTenantId));
             configsMap.forEach((k,v)-> {
-                clinicService.finish(v.stream().map(ManualUndoConfig::getPatientCode).collect(Collectors.toList()),v.get(0).getUndo().getUndoTime() ,k);
+                clinicService.finish(v.stream().map(ManualUndoConfig::getClinicId).collect(Collectors.toList()),v.get(0).getUndo().getUndoTime() ,k);
             });
         }
     }
@@ -114,10 +114,6 @@ public class LocalBusDeviceRunningService extends BaseService<BusDeviceRunningMa
             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));
             //无泵监护,不需要监护输注数据

+ 134 - 0
coffee-system/src/main/java/com/coffee/bus/service/LocalBusHospitalConfigService.java

@@ -1,9 +1,19 @@
 package com.coffee.bus.service;
 
+import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.coffee.bus.entity.BusHospitalConfigEntity;
+import com.coffee.bus.enums.ConfigEnum;
+import com.coffee.bus.hospital.HospitalManagerRegister;
+import com.coffee.bus.hospital.config.bean.*;
 import com.coffee.bus.mapper.BusHospitalConfigMapper;
 import com.coffee.common.crud.BaseService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Map;
 
 /**
  * @author lifang
@@ -14,6 +24,11 @@ import org.springframework.stereotype.Service;
  */
 @Service
 public class LocalBusHospitalConfigService extends BaseService<BusHospitalConfigMapper, BusHospitalConfigEntity,String> {
+    @Autowired
+    @Lazy
+    private HospitalManagerRegister managerRegister;
+
+
     @Override
     public void validateBeforeSave(BusHospitalConfigEntity entity) {
 
@@ -28,4 +43,123 @@ public class LocalBusHospitalConfigService extends BaseService<BusHospitalConfig
     public void validateBeforeDelete(String id) {
 
     }
+
+    @Override
+    public void postSave(BusHospitalConfigEntity entity) {
+        BusHospitalConfigEntity configEntity = this.getById(entity.getId());
+        managerRegister.refresh(configEntity.getTenantId(),false,true);
+    }
+
+    @Override
+    public void postUpdate(BusHospitalConfigEntity entity) {
+        BusHospitalConfigEntity configEntity = this.getById(entity.getId());
+        managerRegister.refresh(configEntity.getTenantId(),false,true);
+    }
+
+    /**
+     * 描述: 默认配置
+     * @author lifang
+     * @date 2022/5/20 11:23
+     * @param hospitalId
+     * @return void
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public void setDefaultConfig(String hospitalId, ConfigEnum type){
+        //找到默认医院的配置
+        BusHospitalConfigEntity defaultConfig = getDefaultConfig(type);
+        BusHospitalConfigEntity hospitalConfig = this.getOne(new QueryWrapper<BusHospitalConfigEntity>()
+                .lambda()
+                .eq(BusHospitalConfigEntity::getType, type)
+                .eq(BusHospitalConfigEntity::getTenantId, hospitalId));
+        BusHospitalConfigEntity saveOrUpdate = new BusHospitalConfigEntity();
+        if(hospitalConfig!=null){
+            saveOrUpdate.setId(hospitalConfig.getId());
+        };
+        saveOrUpdate.setConfig(defaultConfig.getConfig());
+        saveOrUpdate.setType(type);
+        saveOrUpdate.setTenantId(hospitalId);
+        this.saveOrUpdate(saveOrUpdate);
+    }
+
+
+    public void saveDefaultConfig(){
+        BusHospitalConfigEntity otherConfig = new BusHospitalConfigEntity();
+        otherConfig.setTenantId("1");
+        otherConfig.setType(ConfigEnum.other);
+        otherConfig.setConfig(getOtherDefault());
+
+        try {
+            this.save(otherConfig);
+        } catch (Exception e){
+        }
+
+        BusHospitalConfigEntity undoConfig = new BusHospitalConfigEntity();
+        undoConfig.setTenantId("1");
+        undoConfig.setType(ConfigEnum.undo);
+        undoConfig.setConfig(getUndoDefault());
+        try {
+            this.save(undoConfig);
+        } catch (Exception e){
+        }
+    }
+
+    public BusHospitalConfigEntity getDefaultConfig( ConfigEnum type){
+        return this.getOne(new QueryWrapper<BusHospitalConfigEntity>()
+                .lambda()
+                .eq(BusHospitalConfigEntity::getType,type)
+                .eq(BusHospitalConfigEntity::getTenantId, "1"));
+    }
+
+
+
+    private Map<String,Object> getOtherDefault(){
+        FunctionExtraConfig extraConfig=new FunctionExtraConfig();
+        //不在服务区默认10分钟
+        extraConfig.setLowInfusion(10);
+        //低输注时间默认30分钟
+        extraConfig.setNoSignal(30);
+
+
+        FunctionAnalConfig anal=new FunctionAnalConfig();
+
+        //镇痛消失时间默认120分钟
+        anal.setDisappearTime(120);
+        //镇痛不足判定次数3次
+        anal.setInsufficientCount(3);
+        //镇痛不足判定时间60分钟
+        anal.setInsufficientTime(60);
+        //镇痛不足判定类型 有效
+        anal.setValid(true);
+
+        FunctionOtherConfig result = new FunctionOtherConfig();
+        result.setExtra(extraConfig);
+        result.setAnal(anal);
+        return JSONUtil.parseObj(result);
+    }
+
+    private Map<String,Object> getUndoDefault(){
+        FunctionFinishMonitorConfig finishMonitorConfig = new FunctionFinishMonitorConfig();
+        finishMonitorConfig.setEnable(true);
+        //不在服务区到结束时间默认14天
+        finishMonitorConfig.setNoSignalInterval(14);
+        //关机到结束时间默认14天
+        finishMonitorConfig.setShutDownInterval(14);
+
+        FunctionAutoUndoConfig autoUndoConfig = new FunctionAutoUndoConfig();
+        autoUndoConfig.setEnable(true);
+        autoUndoConfig.setUndoByType(true);
+        //不在服务区到撤泵时间 默认60分钟
+        autoUndoConfig.setNoSignalInterval(60);
+        //关机到撤泵时间 默认60分钟
+        autoUndoConfig.setShutDownInterval(60);
+
+        FunctionManualUndoConfig manualUndoConfig = new FunctionManualUndoConfig();
+        manualUndoConfig.setEnable(false);
+
+        FunctionUndoConfig result = new FunctionUndoConfig();
+        result.setAuto(autoUndoConfig);
+        result.setFinishMonitor(finishMonitorConfig);
+        result.setManual(manualUndoConfig);
+        return JSONUtil.parseObj(result);
+    }
 }

+ 38 - 16
coffee-system/src/main/java/com/coffee/bus/service/LocalBusHospitalService.java

@@ -1,17 +1,17 @@
 package com.coffee.bus.service;
 
-import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.coffee.bus.bean.GeoPoint;
 import com.coffee.bus.entity.BusHospitalEntity;
-import com.coffee.bus.his.HisScriptSession;
-import com.coffee.bus.his.HisScriptSessionManager;
-import com.coffee.bus.his.strategy.HisStrategyEnum;
+import com.coffee.bus.hospital.HospitalManagerRegister;
+import com.coffee.bus.hospital.his.strategy.HisStrategyEnum;
 import com.coffee.bus.mapper.BusHospitalMapper;
 import com.coffee.bus.utils.CodeUtils;
+import com.coffee.common.cache.ConfigStorage;
+import com.coffee.common.cache.manager.ConfigStorageManager;
 import com.coffee.common.config.mybatis.GetNameInterface;
 import com.coffee.common.crud.BaseService;
 import com.coffee.common.exception.CustomException;
@@ -19,7 +19,10 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.CommandLineRunner;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
-import java.util.Optional;
+
+import javax.annotation.PostConstruct;
+import java.util.List;
+import java.util.Map;
 
 /**
  * @author lifang
@@ -32,7 +35,21 @@ import java.util.Optional;
 public class LocalBusHospitalService extends BaseService<BusHospitalMapper, BusHospitalEntity,String> implements CommandLineRunner, GetNameInterface<String,String> {
     @Autowired
     @Lazy
-    private HisScriptSessionManager scriptSessionManager;
+    private ConfigStorageManager configStorageManager;
+
+    private ConfigStorage configStorage;
+
+    @Autowired
+    @Lazy
+    private HospitalManagerRegister hospitalManagerRegister;
+    @Autowired
+    @Lazy
+    private LocalBusHospitalConfigService configService;
+    @PostConstruct
+    public void init(){
+        configStorage=configStorageManager.getStorage("hospital_name");
+    }
+
     @Override
     public void validateBeforeSave(BusHospitalEntity entity) {
         long id = IdWorker.getId();
@@ -72,34 +89,37 @@ public class LocalBusHospitalService extends BaseService<BusHospitalMapper, BusH
 
     @Override
     public void postSave(BusHospitalEntity entity) {
-        HisScriptSession hisScriptSession = scriptSessionManager.get(entity.getId());
-        hisScriptSession.refresh(entity);
+        configStorage.setConfig(entity.getId(),entity.getName());
     }
 
     @Override
     public void postUpdate(BusHospitalEntity entity) {
-        HisScriptSession hisScriptSession = scriptSessionManager.get(entity.getId());
-        hisScriptSession.refresh(entity);
+        hospitalManagerRegister.refresh(entity.getId(),true,null!=entity.getScript());
+        if(StrUtil.isNotEmpty(entity.getName())){
+            configStorage.setConfig(entity.getId(),entity.getName());
+        }
     }
 
     @Override
     public void postDelete(String id) {
-        scriptSessionManager.unregister(id);
+
     }
 
     @Override
     public void run(String... args) {
         saveDefaultHospital();
+        List<BusHospitalEntity> list = list();
+        list.forEach(entity -> {
+            configStorage.setConfig(entity.getId(),entity.getName());
+        });
+        configService.saveDefaultConfig();
+        list.forEach(hospital->hospitalManagerRegister.refresh(hospital.getId(),true,true,true));
     }
 
 
     @Override
     public String getName(String id) {
-        if(StrUtil.isAllBlank(id)){
-            return "";
-        }
-        HisScriptSession hisScriptSession = scriptSessionManager.get(id);
-        return Optional.ofNullable(hisScriptSession.getHospitalInfo()).orElse(new BusHospitalEntity()).getName();
+        return configStorage.getConfig(id).asString();
     }
 
 
@@ -119,6 +139,8 @@ public class LocalBusHospitalService extends BaseService<BusHospitalMapper, BusH
         }
     }
 
+
+
     /**
      * 描述: 医院名称是否有效
      * @author lifang

+ 26 - 14
coffee-system/src/main/java/com/coffee/bus/service/LocalBusPatientService.java

@@ -1,13 +1,12 @@
 package com.coffee.bus.service;
 
 import cn.hutool.core.collection.CollectionUtil;
-import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.date.LocalDateTimeUtil;
-import cn.hutool.json.JSONObject;
-import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.coffee.bus.entity.BusClinicEntity;
 import com.coffee.bus.entity.BusPatientEntity;
@@ -15,29 +14,26 @@ import com.coffee.bus.entity.PatientDeviceRepeatDomain;
 import com.coffee.bus.enums.DeviceAlarmEnum;
 import com.coffee.bus.enums.DeviceStatusEnum;
 import com.coffee.bus.enums.PatientAlarmEnum;
-import com.coffee.bus.his.HisScriptSession;
-import com.coffee.bus.his.HisScriptSessionManager;
-import com.coffee.bus.his.strategy.HisStrategyManager;
+import com.coffee.bus.hospital.his.HisScriptSession;
+import com.coffee.bus.hospital.his.HisScriptSessionManager;
 import com.coffee.bus.service.dto.*;
 import com.coffee.bus.mapper.BusPatientMapper;
 import com.coffee.bus.registry.patient.PatientOperator;
 import com.coffee.bus.registry.patient.PatientRegistry;
 import com.coffee.bus.registry.patient.bean.PatientCacheInfo;
 import com.coffee.bus.utils.WsPublishUtils;
-import com.coffee.common.config.websocket.WebSocketConstant;
 import com.coffee.common.crud.BaseService;
 import com.coffee.common.enums.SexEnum;
 import com.coffee.common.result.R;
 import lombok.extern.slf4j.Slf4j;
-import net.bytebuddy.asm.Advice;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Lazy;
-import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.context.request.async.DeferredResult;
 
 import java.time.LocalDateTime;
+import java.time.ZoneOffset;
 import java.util.*;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.Executors;
@@ -113,6 +109,22 @@ public class LocalBusPatientService extends BaseService<BusPatientMapper, BusPat
         return sync?hisScriptSession.syncGetPatientInfo(patientCode,timeout,TimeUnit.SECONDS):hisScriptSession.asyncGetPatientInfo(patientCode,timeout,TimeUnit.SECONDS,true);
     }
 
+    /**
+     * 描述: 对病人报警数量进行统计
+     * @author lifang
+     * @date 2022/5/20 16:42
+     * @param tenantId
+     * @param alarm
+     * @return long
+     */
+    public long patientAlarmCount(String tenantId,PatientAlarmEnum alarm){
+        return this.baseMapper.selectAlarmCount(tenantId,alarm.getValue());
+    }
+
+    public long patientAlarmCount(PatientAlarmEnum alarm){
+        return patientAlarmCount(null,alarm);
+    }
+
     /**
      * 获取给定医院下所有的挂载多个设备的病人信息
      *
@@ -288,15 +300,15 @@ public class LocalBusPatientService extends BaseService<BusPatientMapper, BusPat
                 result.setToday(result.getToday()+1);
                 return;
             }
-            if (includeTimes(startTime, 1)) {
+            if (includeTimes(startTime, -1)) {
                 result.setOneDay(result.getOneDay()+1);
                 return;
             }
-            if (includeTimes(startTime, 2)) {
+            if (includeTimes(startTime, -2)) {
                 result.setTwoDay(result.getTwoDay()+1);
                 return;
             }
-            if (includeTimes(startTime, 3)) {
+            if (includeTimes(startTime, -3)) {
                 result.setThreeDay(result.getThreeDay()+1);
                 return;
             }
@@ -321,7 +333,7 @@ public class LocalBusPatientService extends BaseService<BusPatientMapper, BusPat
         LocalDateTime dateTime = LocalDateTime.now().plusDays(offset);
         LocalDateTime beginTime = LocalDateTimeUtil.beginOfDay(dateTime);
         LocalDateTime endTime = LocalDateTimeUtil.endOfDay(dateTime);
-        return beginTime.getSecond()<time.getSeconds()
-                && time.getSeconds()<endTime.getSecond();
+        return beginTime.toInstant(ZoneOffset.of("+8")).toEpochMilli()<time.getTime()
+                && time.getTime()<endTime.toInstant(ZoneOffset.of("+8")).toEpochMilli();
     }
 }

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

@@ -71,7 +71,7 @@ public class ClinicAnalRecordResult implements Serializable {
     public void fillUndoInfo(List<BusInfusionHistoryEntity> infusionHistories){
         infusionHistories.sort((t1,t2)->t2.getStartTime().compareTo(t1.getStartTime()));
         //找到最后一个撤泵信息
-        Optional<BusInfusionHistoryEntity> undoInfo = infusionHistories.stream().filter(infusion -> Boolean.TRUE.equals(infusion.getIsUndo()))
+        Optional<BusInfusionHistoryEntity> undoInfo = infusionHistories.parallelStream().filter(infusion -> Boolean.TRUE.equals(infusion.getIsUndo()))
                 .findFirst();
         if(undoInfo.isPresent()){
             this.setUndoBy(undoInfo.get().getUndoBy());
@@ -90,13 +90,13 @@ public class ClinicAnalRecordResult implements Serializable {
      * @return void
      */
     public void fillInfusionRecords(List<BusInfusionHistoryEntity> infusionHistories, List<BusInfusionModifyEntity> infusionModifies) {
-        List<ClinicAnalInfusionRecord> infusionRecords = infusionHistories.stream().map(ClinicAnalInfusionRecord::parse).collect(Collectors.toList());
-        List<ClinicAnalInfusionModify> modifies = infusionModifies.stream().map(ClinicAnalInfusionModify::parse).collect(Collectors.toList());
+        List<ClinicAnalInfusionRecord> infusionRecords = infusionHistories.parallelStream().map(ClinicAnalInfusionRecord::parse).collect(Collectors.toList());
+        List<ClinicAnalInfusionModify> modifies = infusionModifies.parallelStream().map(ClinicAnalInfusionModify::parse).collect(Collectors.toList());
         this.setInfusionRecords(infusionRecords);
 
         Map<String, ClinicAnalInfusionRecord> recordHashMap = new HashMap<>();
         infusionRecords.forEach(infusionRecord->recordHashMap.put(infusionRecord.getId(),infusionRecord));
-        Map<String, List<ClinicAnalInfusionModify>> modifyMapByInfusionId = modifies.stream().collect(Collectors.groupingBy(ClinicAnalInfusionModify::getInfusionId));
+        Map<String, List<ClinicAnalInfusionModify>> modifyMapByInfusionId = modifies.parallelStream().collect(Collectors.groupingBy(ClinicAnalInfusionModify::getInfusionId));
         //将修改记录有输注记录绑定
         modifyMapByInfusionId.forEach((k,v)->
                 recordHashMap.computeIfPresent(k,(id,infusion)->{

+ 3 - 0
coffee-system/src/main/java/com/coffee/bus/service/dto/ClinicStatsReturnResult.java

@@ -40,6 +40,9 @@ public class ClinicStatsReturnResult implements Serializable {
             return result;
         }
         queryResults.forEach(queryResult -> {
+            if(queryResult.getUploadTime()==null){
+                return;
+            }
             String uploadTime = DateUtil.format(queryResult.getUploadTime(), DatePattern.NORM_DATETIME_PATTERN);
             List<BigDecimal> continueDoses = Optional.ofNullable(result.getContinueDose()).orElse(new ArrayList<>());
             List<BigDecimal> appendDoses = Optional.ofNullable(result.getAppendDose()).orElse(new ArrayList<>());

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

@@ -25,6 +25,7 @@ import java.util.*;
 public class ManualUndoConfig implements Serializable {
 
     @ApiModelProperty("进行撤泵的所有运行数据id")
+    @NotNull(message = "撤泵泵号不能为空")
     private List<String> deviceIds;
 
     @ApiModelProperty("撤泵病号")
@@ -34,7 +35,8 @@ public class ManualUndoConfig implements Serializable {
     @JsonIgnore
     private String clinicId;
 
-    @ApiModelProperty("医院id")
+    @ApiModelProperty(value = "医院id",hidden = true)
+    @JsonIgnore
     private String tenantId;
 
     @ApiModelProperty("是否为有泵监护,0、无泵 1、有泵")

+ 3 - 0
coffee-system/src/main/java/com/coffee/bus/service/dto/PatientDeviceNoneResult.java

@@ -19,6 +19,9 @@ import java.io.Serializable;
 @Data
 @ApiModel("病人无设备返回数据")
 public class PatientDeviceNoneResult  implements Serializable {
+    @ApiModelProperty("临床id")
+    private String clinicId;
+
     @ApiModelProperty("病患名称")
     private String name;
 

+ 9 - 20
coffee-system/src/main/java/com/coffee/bus/utils/WsPublishUtils.java

@@ -1,12 +1,9 @@
 package com.coffee.bus.utils;
 
 
-import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.json.JSONObject;
-import com.alibaba.fastjson.serializer.JSONObjectCodec;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.coffee.bus.entity.BusClinicEntity;
-import com.coffee.bus.entity.BusPatientEntity;
 import com.coffee.bus.enums.PatientAlarmEnum;
 import com.coffee.bus.service.LocalBusClinicService;
 import com.coffee.bus.service.LocalBusPatientService;
@@ -14,17 +11,9 @@ import com.coffee.bus.service.dto.MonitorStatusStatsCountResult;
 import com.coffee.bus.service.dto.PatientMonitorResult;
 import com.coffee.common.config.websocket.TopicMessage;
 import com.coffee.common.config.websocket.WebSocketConstant;
-import com.coffee.common.redis.RedisUtils;
 import com.coffee.common.util.RedissonUtil;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.redisson.RedissonTopic;
-import org.redisson.api.RedissonClient;
-import org.redisson.codec.JsonJacksonCodec;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Component;
 import org.springframework.util.Assert;
@@ -47,7 +36,7 @@ public class WsPublishUtils implements Serializable{
     private final RedissonUtil redissonUtil;
 
     private void publish(String topic,TopicMessage msg){
-        redissonUtil.getTopic(topic).publish(msg);
+        redissonUtil.getTopic(topic).publishAsync(msg);
     }
 
     /**
@@ -62,9 +51,12 @@ public class WsPublishUtils implements Serializable{
     public void publishPatientMonitor(String patientCode,String tenantId){
         Assert.hasText(tenantId,"医院id不能为空");
         PatientMonitorResult message = patientService.lookMonitorByPatientCode(patientCode, tenantId);
-        this.publish(WebSocketConstant.getPatientMonitor(null, patientCode, tenantId).getTopic(),
-                TopicMessage.of(message,patientCode)
-        );
+        if(message!=null){
+            message.handleWarn();
+            this.publish(WebSocketConstant.getPatientMonitor(null, patientCode, tenantId).getTopic(),
+                    TopicMessage.of(message,patientCode)
+            );
+        }
     }
 
     /**
@@ -107,8 +99,7 @@ public class WsPublishUtils implements Serializable{
     @Async
     public void publishDeviceRepeat(String tenantId){
         Assert.hasText(tenantId,"医院id不能为空");
-        JSONObject message = new JSONObject().putOpt("count", patientService.count(new QueryWrapper<BusPatientEntity>().lambda().eq(BusPatientEntity::getTenantId, tenantId)
-                .eq(BusPatientEntity::getAlarm, PatientAlarmEnum.DEVICE_REPEAT)));
+        JSONObject message = new JSONObject().putOpt("count", patientService.patientAlarmCount(tenantId,PatientAlarmEnum.DEVICE_REPEAT));
         this.publish(WebSocketConstant.getDeviceRepeat(tenantId).getTopic(),
                 TopicMessage.of(message,tenantId)
         );
@@ -124,9 +115,7 @@ public class WsPublishUtils implements Serializable{
     @Async
     public void publishDeviceNone(String tenantId){
         Assert.hasText(tenantId,"医院id不能为空");
-        JSONObject message = new JSONObject().putOpt("count", patientService.count(new QueryWrapper<BusPatientEntity>()
-                .lambda().eq(BusPatientEntity::getTenantId, tenantId)
-                .eq(BusPatientEntity::getAlarm, PatientAlarmEnum.DEVICE_NONE)));
+        JSONObject message = new JSONObject().putOpt("count",patientService.patientAlarmCount(tenantId,PatientAlarmEnum.NONE));
         this.publish(WebSocketConstant.getDeviceNone(tenantId).getTopic(),
                 TopicMessage.of(message,tenantId)
         );

+ 2 - 3
coffee-system/src/main/java/com/coffee/bus/websocket/HisConnectionHandler.java

@@ -5,15 +5,14 @@ import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.coffee.bus.entity.BusHospitalEntity;
-import com.coffee.bus.his.HisScriptSession;
-import com.coffee.bus.his.HisScriptSessionManager;
+import com.coffee.bus.hospital.his.HisScriptSession;
+import com.coffee.bus.hospital.his.HisScriptSessionManager;
 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 com.coffee.common.result.R;
 import lombok.AllArgsConstructor;
-import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Component;
 import org.tio.core.ChannelContext;
 import org.tio.core.Tio;

+ 2 - 2
coffee-system/src/main/java/com/coffee/bus/websocket/WebSocketCloseHandler.java

@@ -24,8 +24,8 @@ public class WebSocketCloseHandler extends Subscribe {
     @Override
     public void close(ChannelContext channelContext) {
         //关闭则取消订阅
-        Map<String, DefaultMessageListener> topicListeners = getTopicListeners(channelContext);
-        topicListeners.forEach((topic,listener)->this.unsubscribe(channelContext,topic));
+//        Map<String, DefaultMessageListener> topicListeners = getTopicListeners(channelContext);
+//        topicListeners.forEach((topic,listener)->this.unsubscribe(channelContext,topic));
     }
 
     @Override

Some files were not shown because too many files changed in this diff