Kaynağa Gözat

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

# Conflicts:
#	coffee-admin/src/test/java/com/coffee/admin/BusPatientTest.java
15638522405 3 yıl önce
ebeveyn
işleme
034e4857d0
100 değiştirilmiş dosya ile 2642 ekleme ve 765 silme
  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. 4 3
      coffee-admin/src/test/java/com/coffee/admin/BusHospitalTest.java
  5. 185 23
      coffee-admin/src/test/java/com/coffee/admin/BusPatientTest.java
  6. 6 8
      coffee-admin/src/test/java/com/coffee/admin/HisStrategyTest.java
  7. 11 0
      coffee-common/pom.xml
  8. 7 3
      coffee-common/src/main/java/com/coffee/common/cache/manager/ClusterConfigStorageManager.java
  9. 2 2
      coffee-common/src/main/java/com/coffee/common/config/CorsConfig.java
  10. 1 0
      coffee-common/src/main/java/com/coffee/common/config/mybatis/TenantNameHandler.java
  11. 23 35
      coffee-common/src/main/java/com/coffee/common/config/websocket/DefaultMessageListener.java
  12. 0 1
      coffee-common/src/main/java/com/coffee/common/config/websocket/DefaultWebSocketMsgHandler.java
  13. 1 1
      coffee-common/src/main/java/com/coffee/common/config/websocket/MessageResponse.java
  14. 16 0
      coffee-common/src/main/java/com/coffee/common/config/websocket/TopicMessage.java
  15. 32 91
      coffee-common/src/main/java/com/coffee/common/config/websocket/handler/Subscribe.java
  16. 4 3
      coffee-common/src/main/java/com/coffee/common/entity/GenericEntity.java
  17. 3 3
      coffee-common/src/main/java/com/coffee/common/entity/TenantGenericEntity.java
  18. 79 0
      coffee-common/src/main/java/com/coffee/common/util/RedissonUtil.java
  19. 6 0
      coffee-framework/pom.xml
  20. 174 0
      coffee-framework/src/main/java/com/coffee/framework/config/RedissonClientAutoConfiguration.java
  21. 16 12
      coffee-framework/src/main/java/com/coffee/framework/config/WebAppMvcConfig.java
  22. 1 1
      coffee-framework/src/main/java/com/coffee/framework/web/exception/GlobalExceptionHandler.java
  23. 2 1
      coffee-system/src/main/java/com/coffee/aliyun/AliyunConsumerGroupService.java
  24. 7 0
      coffee-system/src/main/java/com/coffee/aliyun/utils/Items.java
  25. 11 0
      coffee-system/src/main/java/com/coffee/bus/bean/GeoPoint.java
  26. 5 0
      coffee-system/src/main/java/com/coffee/bus/bean/HisInfo.java
  27. 2 0
      coffee-system/src/main/java/com/coffee/bus/bean/Script.java
  28. 0 11
      coffee-system/src/main/java/com/coffee/bus/bean/config/Config.java
  29. 0 97
      coffee-system/src/main/java/com/coffee/bus/bean/config/EvalConfig.java
  30. 0 55
      coffee-system/src/main/java/com/coffee/bus/bean/config/OtherConfig.java
  31. 0 62
      coffee-system/src/main/java/com/coffee/bus/bean/config/UndoConfig.java
  32. 5 8
      coffee-system/src/main/java/com/coffee/bus/controller/BusAlarmController.java
  33. 84 51
      coffee-system/src/main/java/com/coffee/bus/controller/BusClinicController.java
  34. 2 28
      coffee-system/src/main/java/com/coffee/bus/controller/BusDeviceManualController.java
  35. 15 26
      coffee-system/src/main/java/com/coffee/bus/controller/BusHospitalConfigController.java
  36. 55 6
      coffee-system/src/main/java/com/coffee/bus/controller/BusHospitalController.java
  37. 62 18
      coffee-system/src/main/java/com/coffee/bus/controller/BusPatientController.java
  38. 22 0
      coffee-system/src/main/java/com/coffee/bus/controller/vo/CauseVo.java
  39. 8 3
      coffee-system/src/main/java/com/coffee/bus/controller/vo/ClinicEditVo.java
  40. 3 0
      coffee-system/src/main/java/com/coffee/bus/controller/vo/ClinicStatsVo.java
  41. 27 0
      coffee-system/src/main/java/com/coffee/bus/controller/vo/ExecScript.java
  42. 8 3
      coffee-system/src/main/java/com/coffee/bus/entity/BusClinicEntity.java
  43. 0 1
      coffee-system/src/main/java/com/coffee/bus/entity/BusDeviceAlarmEntity.java
  44. 4 8
      coffee-system/src/main/java/com/coffee/bus/entity/BusDeviceEntity.java
  45. 4 7
      coffee-system/src/main/java/com/coffee/bus/entity/BusDeviceHistoryEntity.java
  46. 12 0
      coffee-system/src/main/java/com/coffee/bus/entity/BusDeviceRunningEntity.java
  47. 1 0
      coffee-system/src/main/java/com/coffee/bus/entity/BusFormulaEntity.java
  48. 1 8
      coffee-system/src/main/java/com/coffee/bus/entity/BusHospitalConfigEntity.java
  49. 11 43
      coffee-system/src/main/java/com/coffee/bus/entity/BusHospitalEntity.java
  50. 2 2
      coffee-system/src/main/java/com/coffee/bus/entity/BusInfusionHistoryEntity.java
  51. 1 0
      coffee-system/src/main/java/com/coffee/bus/entity/BusInfusionModifyEntity.java
  52. 2 1
      coffee-system/src/main/java/com/coffee/bus/entity/PatientDeviceRepeatDomain.java
  53. 61 0
      coffee-system/src/main/java/com/coffee/bus/entity/common/CommonDeviceParam.java
  54. 15 8
      coffee-system/src/main/java/com/coffee/bus/enums/ConfigEnum.java
  55. 13 0
      coffee-system/src/main/java/com/coffee/bus/enums/PatientAlarmEnum.java
  56. 168 0
      coffee-system/src/main/java/com/coffee/bus/hospital/HospitalManager.java
  57. 88 0
      coffee-system/src/main/java/com/coffee/bus/hospital/HospitalManagerRegister.java
  58. 57 0
      coffee-system/src/main/java/com/coffee/bus/hospital/config/AbstractHospitalConfigHandler.java
  59. 154 0
      coffee-system/src/main/java/com/coffee/bus/hospital/config/HospitalAutoUndoConfigHandler.java
  60. 37 0
      coffee-system/src/main/java/com/coffee/bus/hospital/config/HospitalConfigHandler.java
  61. 169 0
      coffee-system/src/main/java/com/coffee/bus/hospital/config/HospitalFinishMonitorConfigHandler.java
  62. 217 0
      coffee-system/src/main/java/com/coffee/bus/hospital/config/HospitalFunctionAnalConfigHandler.java
  63. 220 0
      coffee-system/src/main/java/com/coffee/bus/hospital/config/HospitalFunctionExtraConfigHandler.java
  64. 27 0
      coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionAnalConfig.java
  65. 29 0
      coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionAutoUndoConfig.java
  66. 23 0
      coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionExtraConfig.java
  67. 28 0
      coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionFinishMonitorConfig.java
  68. 31 0
      coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionManualUndoConfig.java
  69. 23 0
      coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionOtherConfig.java
  70. 22 0
      coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionUndoConfig.java
  71. 22 0
      coffee-system/src/main/java/com/coffee/bus/hospital/enums/ConfigHandlerEnums.java
  72. 9 3
      coffee-system/src/main/java/com/coffee/bus/hospital/his/HisRequest.java
  73. 7 1
      coffee-system/src/main/java/com/coffee/bus/hospital/his/HisResponse.java
  74. 76 44
      coffee-system/src/main/java/com/coffee/bus/hospital/his/HisScriptSession.java
  75. 8 7
      coffee-system/src/main/java/com/coffee/bus/hospital/his/HisScriptSessionManager.java
  76. 15 1
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/HisStrategyEnum.java
  77. 1 1
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/HisStrategyHandler.java
  78. 1 1
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/HisStrategyManager.java
  79. 1 1
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/HisStrategyManagerRegister.java
  80. 1 4
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/all/EqualsStrategyHandler.java
  81. 2 2
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/all/HisAllStrategyHandler.java
  82. 3 3
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/all/HisAllStrategyManager.java
  83. 1 2
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/all/LessToMoreHisStrategyHandler.java
  84. 1 2
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/all/MoreToLessHisStrategyHandler.java
  85. 1 1
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/onlynew/DefaultHisNewStrategyHandler.java
  86. 2 2
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/onlynew/HisNewStrategyHandler.java
  87. 3 3
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/onlynew/HisNewStrategyManager.java
  88. 3 3
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/part/DefaultHisPartStrategyHandler.java
  89. 2 2
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/part/HisPartStrategyHandler.java
  90. 3 3
      coffee-system/src/main/java/com/coffee/bus/hospital/his/strategy/part/HisPartStrategyManager.java
  91. 1 3
      coffee-system/src/main/java/com/coffee/bus/hospital/script/DefaultParse.java
  92. 13 6
      coffee-system/src/main/java/com/coffee/bus/hospital/script/ExecuteResult.java
  93. 20 7
      coffee-system/src/main/java/com/coffee/bus/hospital/script/PythonParse.java
  94. 23 16
      coffee-system/src/main/java/com/coffee/bus/hospital/script/ScriptManager.java
  95. 1 3
      coffee-system/src/main/java/com/coffee/bus/hospital/script/ScriptParse.java
  96. 28 0
      coffee-system/src/main/java/com/coffee/bus/listener/event/bean/DeviceLifecycleEvent.java
  97. 4 0
      coffee-system/src/main/java/com/coffee/bus/mapper/BusPatientMapper.java
  98. 1 3
      coffee-system/src/main/java/com/coffee/bus/registry/Operator.java
  99. 2 0
      coffee-system/src/main/java/com/coffee/bus/registry/constant/DeviceKeyConstant.java
  100. 12 2
      coffee-system/src/main/java/com/coffee/bus/registry/device/ClusterDeviceOperator.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));
+        }
+
+    }
 }

+ 4 - 3
coffee-admin/src/test/java/com/coffee/admin/BusHospitalTest.java

@@ -1,6 +1,7 @@
 package com.coffee.admin;
 
 import cn.dev33.satoken.stp.StpUtil;
+import com.coffee.bus.bean.GeoPoint;
 import com.coffee.bus.bean.Script;
 import com.coffee.bus.controller.BusHospitalController;
 import com.coffee.bus.entity.BusHospitalEntity;
@@ -37,7 +38,7 @@ public class BusHospitalTest {
         busHospitalEntity.setAddress("河南长垣");
         busHospitalEntity.setAreaCode("453400");
 
-        BusHospitalEntity.GeoPoint geoPoint = new BusHospitalEntity.GeoPoint();
+        GeoPoint geoPoint = new GeoPoint();
         geoPoint.setLat("101");
         geoPoint.setLon("1010");
         busHospitalEntity.setCoordinate(geoPoint);
@@ -86,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);
     }
 }

+ 185 - 23
coffee-admin/src/test/java/com/coffee/admin/BusPatientTest.java

@@ -1,20 +1,31 @@
 package com.coffee.admin;
 
+import cn.hutool.core.date.DateField;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.EnumUtil;
+import cn.hutool.core.util.RandomUtil;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.coffee.bus.controller.vo.DeviceUse;
-import com.coffee.bus.entity.BusDeviceAlarmEntity;
-import com.coffee.bus.enums.DeviceAlarmEnum;
-import com.coffee.bus.mapper.BusDeviceAlarmMapper;
-import com.coffee.bus.service.LocalBusDeviceAlarmService;
+import com.coffee.bus.controller.BusDeviceManualController;
+import com.coffee.bus.controller.vo.ClinicEditVo;
+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.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.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.junit4.SpringRunner;
 
-import java.util.List;
+import java.io.UnsupportedEncodingException;
+import java.math.BigDecimal;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * @author lifang
@@ -28,39 +39,190 @@ import java.util.List;
 public class BusPatientTest {
     @Autowired
     private LocalBusPatientService patientService;
+
     @Autowired
-    private LocalBusDeviceAlarmService deviceAlarmService;
-    @Autowired
-    private BusDeviceAlarmMapper deviceAlarmMapper;
+    private LocalBusClinicService clinicService;
 
+    @Autowired
+    private EqualsStrategyHandler equalsStrategyHandler;
+    @Autowired
+    private BusDeviceManualController manualController;
     @Test
     public  void test(){
         List<PatientDeviceRepeatResult> patientDeviceRepeatResults = patientService.repeatDevice();
+        System.out.println(getName());
         System.out.println(patientDeviceRepeatResults);
     }
 
+    public static List<String> clinicNames= Arrays.asList("阑尾手术","肛门手术","肝脏手术","感冒","发烧","肠其他手术","结肠造口术","回肠造口术","肠造口闭合术","肠固定术","肠的其他修补","阑尾切除术","腹腔镜下阑尾切除术","阑尾切除术","阑尾残端切除术");
+    public static List<String> anaTypes=Arrays.asList("局部麻醉","全麻");
+    public static List<String> analTypes=Arrays.asList("PCIA","PCEA","PCSA","PCNA");
+
     @Test
-    public  void test1(){
-        List<DeviceUse> deviceUseList = deviceAlarmService.countAlarm();
-        for (DeviceUse d:
-             deviceUseList) {
-            System.out.println(d);
+    public void save(){
+        for (int i = 0; i < 30; i++) {
+            BusClinicEntity clinic = new BusClinicEntity();
+            clinic.setStartTime(new Date());
+            clinic.setSurgeryName(clinicNames.get(RandomUtil.randomInt(clinicNames.size()-1)));
+            clinic.setPatientName(getName());
+            clinic.setPatientGender(EnumUtil.likeValueOf(SexEnum.class,RandomUtil.randomInt(1,2)));
+            clinic.setBedNo(String.valueOf(RandomUtil.randomInt(10,100)));
+            clinic.setWard(String.valueOf(RandomUtil.randomInt(10,100)));
+            clinic.setWeight(String.valueOf(RandomUtil.randomInt(90,150)));
+            clinic.setWeight(String.valueOf(RandomUtil.randomInt(150,200)));
+            clinic.setAnaDoctor(getName());
+            clinic.setAnaType(anaTypes.get(RandomUtil.randomInt(anaTypes.size()-1)));
+            clinic.setAnalType(analTypes.get(RandomUtil.randomInt(analTypes.size()-1)));
+            clinic.setSurgeryDoctor(getName());
+            clinic.setConfigPerson(getName());
+            clinic.setPatientCode(String.valueOf(RandomUtil.randomInt(100000,300000)));
+            clinic.setMonitorType(true);
+            clinic.setTenantId("1");
+            BusPatientEntity patient = BusPatientEntity.of(clinic);
+//        patientService.save(patient);
+//        clinicService.save(clinic);
+            patientService.manualEdit(clinic);
         }
     }
+
+    @Test
+    public void fill(){
+        List<BusClinicEntity> clinicList = clinicService.list(new QueryWrapper<BusClinicEntity>().lambda().eq(BusClinicEntity::getMonitorType, true));
+        Map<String, List<BusClinicEntity>> groupByHospital = clinicList.stream().collect(Collectors.groupingBy(BusClinicEntity::getTenantId));
+        groupByHospital.forEach((tenantId,list)->{
+            Map< String, List<BusClinicEntity>> groupByPatientCode = list.stream().collect(Collectors.groupingBy(BusClinicEntity::getPatientCode));
+            groupByPatientCode.forEach((k,targets)->{
+                List<BusClinicEntity> source = new ArrayList<>();
+                for (BusClinicEntity target : targets) {
+                    BusClinicEntity clinic = new BusClinicEntity();
+                    clinic.setStartTime(target.getStartTime()==null?
+                            RandomUtil.randomDate(DateUtil.beginOfMonth(new Date()), DateField.HOUR,-30,30):target.getStartTime());
+                    clinic.setSurgeryName(clinicNames.get(RandomUtil.randomInt(clinicNames.size()-1)));
+                    clinic.setPatientName(getName());
+                    clinic.setPatientGender(EnumUtil.likeValueOf(SexEnum.class,RandomUtil.randomInt(1,2)));
+                    clinic.setBedNo(target.getBedNo());
+                    clinic.setWard(target.getWard());
+                    clinic.setWeight(String.valueOf(RandomUtil.randomInt(90,150)));
+                    clinic.setWeight(String.valueOf(RandomUtil.randomInt(150,200)));
+                    clinic.setAnaDoctor(getName());
+                    clinic.setAnaType(anaTypes.get(RandomUtil.randomInt(anaTypes.size()-1)));
+                    clinic.setAnalType(analTypes.get(RandomUtil.randomInt(analTypes.size()-1)));
+                    clinic.setSurgeryDoctor(getName());
+                    clinic.setConfigPerson(getName());
+                    clinic.setPatientCode(target.getPatientCode());
+                    clinic.setMonitorType(true);
+                    clinic.setTenantId("1");
+                    source.add(clinic);
+                }
+                equalsStrategyHandler.handle(source,targets);
+            });
+
+        });
+
+    }
+    public void fillPatientCode(){
+        List<BusPatientEntity> list = patientService.list();
+    }
+
     @Test
-    public  void test2(){
+    public void manualSave(){
+        for (int i = 0; i < 30; i++) {
+            ClinicEditVo clinicEditVo = new ClinicEditVo();
+            BusClinicEntity clinic = new BusClinicEntity();
+            clinic.setStartTime(new Date());
+            clinic.setSurgeryName(clinicNames.get(RandomUtil.randomInt(clinicNames.size()-1)));
+            clinic.setPatientAge(RandomUtil.randomInt(15,50));
+            clinic.setPatientName(getName());
+            clinic.setPatientGender(EnumUtil.likeValueOf(SexEnum.class,RandomUtil.randomInt(1,2)));
+            clinic.setBedNo(String.valueOf(RandomUtil.randomInt(10,100)));
+            clinic.setWard(String.valueOf(RandomUtil.randomInt(10,100)));
+            clinic.setWeight(String.valueOf(RandomUtil.randomInt(90,150)));
+            clinic.setWeight(String.valueOf(RandomUtil.randomInt(150,200)));
+            clinic.setAnaDoctor(getName());
+            clinic.setAnaType(anaTypes.get(RandomUtil.randomInt(anaTypes.size()-1)));
+            clinic.setAnalType(analTypes.get(RandomUtil.randomInt(analTypes.size()-1)));
+            clinic.setSurgeryDoctor(getName());
+            clinic.setConfigPerson(getName());
+            clinic.setPatientCode(String.valueOf(RandomUtil.randomInt(100000,300000)));
+            clinic.setTenantId("1");
+
+            clinicEditVo.setClinic(clinic);
 
-        QueryWrapper<BusDeviceAlarmEntity> busDeviceAlarmEntityQueryWrapper = new QueryWrapper<>();
-        BusDeviceAlarmEntity busDeviceAlarmEntity = new BusDeviceAlarmEntity();
+            BusDeviceManualEntity manual = new BusDeviceManualEntity();
+            manual.setType(DeviceManualEnum.machine);
+            manual.setTotalDose(RandomUtil.randomInt(100));
+            manual.setContinueDose(RandomUtil.randomBigDecimal(BigDecimal.valueOf(10)));
+            manual.setSelfControlDose(RandomUtil.randomBigDecimal(BigDecimal.valueOf(10)));
+            manual.setSelfControlLockTime(RandomUtil.randomInt(100));
+            clinicEditVo.setManual(manual);
+//            manualController.save(clinicEditVo);
 
-        //busDeviceAlarmEntity.setTenantId("1");
-        busDeviceAlarmEntityQueryWrapper.setEntity(busDeviceAlarmEntity);
-        busDeviceAlarmEntity.setAlarm(DeviceAlarmEnum.LowBattery);
+//        patientService.save(patient);
+//        clinicService.save(clinic);
+        }
+    }
 
-        System.out.println(busDeviceAlarmEntityQueryWrapper.getEntity().getAlarm());
-        //System.out.println("----------------------------------------"+busDeviceAlarmEntityQueryWrapper.getEntity().getTenantId());
-        System.out.println("=================================="+deviceAlarmMapper.selectCount(busDeviceAlarmEntityQueryWrapper));
+    public static void main(String[] args) {
+        System.out.println(getName());
     }
 
+    public static String getName(){
+        Random random=new Random(System.currentTimeMillis());
+        /* 598 百家姓 */
+        String[] Surname= {"赵","钱","孙","李","周","吴","郑","王","冯","陈","褚","卫","蒋","沈","韩","杨","朱","秦","尤","许",
+                "何","吕","施","张","孔","曹","严","华","金","魏","陶","姜","戚","谢","邹","喻","柏","水","窦","章","云","苏","潘","葛","奚","范","彭","郎",
+                "鲁","韦","昌","马","苗","凤","花","方","俞","任","袁","柳","酆","鲍","史","唐","费","廉","岑","薛","雷","贺","倪","汤","滕","殷",
+                "罗","毕","郝","邬","安","常","乐","于","时","傅","皮","卞","齐","康","伍","余","元","卜","顾","孟","平","黄","和",
+                "穆","萧","尹","姚","邵","湛","汪","祁","毛","禹","狄","米","贝","明","臧","计","伏","成","戴","谈","宋","茅","庞","熊","纪","舒",
+                "屈","项","祝","董","梁","杜","阮","蓝","闵","席","季","麻","强","贾","路","娄","危","江","童","颜","郭","梅","盛","林","刁","钟",
+                "徐","邱","骆","高","夏","蔡","田","樊","胡","凌","霍","虞","万","支","柯","昝","管","卢","莫","经","房","裘","缪","干","解","应",
+                "宗","丁","宣","贲","邓","郁","单","杭","洪","包","诸","左","石","崔","吉","钮","龚","程","嵇","邢","滑","裴","陆","荣","翁","荀",
+                "羊","于","惠","甄","曲","家","封","芮","羿","储","靳","汲","邴","糜","松","井","段","富","巫","乌","焦","巴","弓","牧","隗","山",
+                "谷","车","侯","宓","蓬","全","郗","班","仰","秋","仲","伊","宫","宁","仇","栾","暴","甘","钭","厉","戎","祖","武","符","刘","景",
+                "詹","束","龙","叶","幸","司","韶","郜","黎","蓟","溥","印","宿","白","怀","蒲","邰","从","鄂","索","咸","籍","赖","卓","蔺","屠",
+                "蒙","池","乔","阴","郁","胥","能","苍","双","闻","莘","党","翟","谭","贡","劳","逄","姬","申","扶","堵","冉","宰","郦","雍","却",
+                "璩","桑","桂","濮","牛","寿","通","边","扈","燕","冀","浦","尚","农","温","别","庄","晏","柴","瞿","阎","充","慕","连","茹","习",
+                "宦","艾","鱼","容","向","古","易","慎","戈","廖","庾","终","暨","居","衡","步","都","耿","满","弘","匡","国","文","寇","广","禄",
+                "阙","东","欧","殳","沃","利","蔚","越","夔","隆","师","巩","厍","聂","晁","勾","敖","融","冷","訾","辛","阚","那","简","饶","空",
+                "曾","毋","沙","乜","养","鞠","须","丰","巢","关","蒯","相","查","后","荆","红","游","郏","竺","权","逯","盖","益","桓","公","仉",
+                "督","岳","帅","缑","亢","况","郈","有","琴","归","海","晋","楚","闫","法","汝","鄢","涂","钦","商","牟","佘","佴","伯","赏","墨",
+                "哈","谯","篁","年","爱","阳","佟","言","福","南","火","铁","迟","漆","官","冼","真","展","繁","檀","祭","密","敬","揭","舜","楼",
+                "疏","冒","浑","挚","胶","随","高","皋","原","种","练","弥","仓","眭","蹇","覃","阿","门","恽","来","綦","召","仪","风","介","巨",
+                "木","京","狐","郇","虎","枚","抗","达","杞","苌","折","麦","庆","过","竹","端","鲜","皇","亓","老","是","秘","畅","邝","还","宾",
+                "闾","辜","纵","侴","万俟","司马","上官","欧阳","夏侯","诸葛","闻人","东方","赫连","皇甫","羊舌","尉迟","公羊","澹台","公冶","宗正",
+                "濮阳","淳于","单于","太叔","申屠","公孙","仲孙","轩辕","令狐","钟离","宇文","长孙","慕容","鲜于","闾丘","司徒","司空","兀官","司寇",
+                "南门","呼延","子车","颛孙","端木","巫马","公西","漆雕","车正","壤驷","公良","拓跋","夹谷","宰父","谷梁","段干","百里","东郭","微生",
+                "梁丘","左丘","东门","西门","南宫","第五","公仪","公乘","太史","仲长","叔孙","屈突","尔朱","东乡","相里","胡母","司城","张廖","雍门",
+                "毋丘","贺兰","綦毋","屋庐","独孤","南郭","北宫","王孙"};
+
+        int index=random.nextInt(Surname.length-1);
+        String name = Surname[index]; //获得一个随机的姓氏
 
+        /* 从常用字中选取一个或两个字作为名 */
+        if(random.nextBoolean()){
+            name+=getChinese()+getChinese();
+        }else {
+            name+=getChinese();
+        }
+        return name;
+    }
+
+    public static String getChinese() {
+        String str = null;
+        int highPos, lowPos;
+        Random random = new Random();
+        highPos = (176 + Math.abs(random.nextInt(71)));//区码,0xA0打头,从第16区开始,即0xB0=11*16=176,16~55一级汉字,56~87二级汉字
+        random = new Random();
+        lowPos = 161 + Math.abs(random.nextInt(94));//位码,0xA0打头,范围第1~94列
+
+        byte[] bArr = new byte[2];
+        bArr[0] = (new Integer(highPos)).byteValue();
+        bArr[1] = (new Integer(lowPos)).byteValue();
+        try {
+            str = new String(bArr, "GB2312");    //区位码组合成汉字
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return str;
+    }
 }

+ 6 - 8
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;
@@ -60,7 +58,7 @@ public class HisStrategyTest {
             BusClinicEntity clinic = new BusClinicEntity();
             clinic.setStartTime(target.getStartTime()==null?
                     RandomUtil.randomDate(DateUtil.beginOfMonth(new Date()), DateField.HOUR,-30,30):DateUtil.date(target.getStartTime()).offset(DateField.HOUR_OF_DAY,-1));
-            clinic.setName(BusPatientTest.clinicNames.get(RandomUtil.randomInt(BusPatientTest.clinicNames.size()-1)));
+            clinic.setSurgeryName(BusPatientTest.clinicNames.get(RandomUtil.randomInt(BusPatientTest.clinicNames.size()-1)));
             clinic.setPatientName(getName());
             clinic.setPatientGender(EnumUtil.likeValueOf(SexEnum.class,RandomUtil.randomInt(1,2)));
             clinic.setBedNo(target.getBedNo());
@@ -79,7 +77,7 @@ public class HisStrategyTest {
         }
         BusClinicEntity clinic = new BusClinicEntity();
         clinic.setStartTime(DateUtil.beginOfDay(new Date()));
-        clinic.setName(BusPatientTest.clinicNames.get(RandomUtil.randomInt(BusPatientTest.clinicNames.size()-1)));
+        clinic.setSurgeryName(BusPatientTest.clinicNames.get(RandomUtil.randomInt(BusPatientTest.clinicNames.size()-1)));
         clinic.setPatientName(getName());
         clinic.setPatientGender(EnumUtil.likeValueOf(SexEnum.class,RandomUtil.randomInt(1,2)));
         clinic.setBedNo("10");

+ 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>

+ 7 - 3
coffee-common/src/main/java/com/coffee/common/cache/manager/ClusterConfigStorageManager.java

@@ -2,6 +2,7 @@ package com.coffee.common.cache.manager;
 
 import com.coffee.common.cache.ClusterConfigStorage;
 import com.coffee.common.cache.ConfigStorage;
+import org.redisson.api.RedissonClient;
 import org.springframework.cache.CacheManager;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Component;
@@ -19,14 +20,17 @@ import java.util.concurrent.ConcurrentHashMap;
 
 @Component
 public class ClusterConfigStorageManager implements ConfigStorageManager {
-    private final RedisTemplate redisTemplate;
 
+    private final RedissonClient redissonClient;
+
+    private final RedisTemplate redisTemplate;
 
 
     private Map<String,ClusterConfigStorage > storageMap=new ConcurrentHashMap<>();
 
-    public ClusterConfigStorageManager(RedisTemplate redisTemplate) {
-        this.redisTemplate = redisTemplate;
+    public ClusterConfigStorageManager(RedissonClient redissonClient,RedisTemplate redisTemplate) {
+        this.redissonClient = redissonClient;
+        this.redisTemplate=redisTemplate;
     }
 
     @Override

+ 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) {
 

+ 23 - 35
coffee-common/src/main/java/com/coffee/common/config/websocket/DefaultMessageListener.java

@@ -1,25 +1,20 @@
 package com.coffee.common.config.websocket;
 
-import cn.hutool.core.collection.CollectionUtil;
-import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
-import com.coffee.common.cache.value.Value;
-import com.coffee.common.config.websocket.handler.TopicWrapper;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import lombok.Data;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.data.redis.connection.Message;
-import org.springframework.data.redis.connection.MessageListener;
+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;
 import org.tio.websocket.common.WsPacket;
 import org.tio.websocket.common.WsResponse;
 
-import java.util.HashSet;
-import java.util.Set;
-
 /**
  * @author lifang
  * @version 1.0.0
@@ -29,34 +24,27 @@ import java.util.Set;
  */
 @Data
 @Slf4j
-public class DefaultMessageListener implements MessageListener {
+public class DefaultMessageListener implements PatternMessageListener<TopicMessage> {
     private final String id;
-    private final TopicWrapper topicWrapper;
     private final ObjectMapper objectMapper;
-    private final  Set<ChannelContext> channelContexts;
+    private final ChannelContext channelContext;
+    private final RPatternTopic rPatternTopic;
+
+
     @Override
-    public void onMessage(Message message, byte[] pattern) {
-        if (CollectionUtil.isNotEmpty(channelContexts)) {
-            Set<ChannelContext> closeChannel = new HashSet<>();
-            channelContexts.parallelStream()
-                    .forEach(channel -> {
-                        if (!TioUtils.checkBeforeIO(channel)) {
-                            closeChannel.add(channel);
-                            return;
-                        }
-                        String json = null;
-                        try {
-                            JSONObject jsonObject = JSONUtil.parseObj(message.toString());
-                            json = objectMapper.writeValueAsString(MessageResponse.of(id, "result", Value.simple( jsonObject.get("param")).asString(),
-                                    JSONUtil.parse(jsonObject.get("message"))));
-                            Tio.send(channel,WsResponse.fromText(json, WsPacket.CHARSET_NAME));
-                        } catch (JsonProcessingException e) {
-                            log.error("ws消息订阅,解析失败,message:【】",message.toString());
-                        }
-                            }
-                    );
-            channelContexts.removeAll(closeChannel);
+    public void onMessage(CharSequence pattern, CharSequence channel, TopicMessage msg) {
+        if (TioUtils.checkBeforeIO(channelContext)) {
+            String json = null;
+            try {
+                json = objectMapper.writeValueAsString(MessageResponse.of(id, "result", msg.getParam(),
+                        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);
         }
     }
-
-}
+}

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

@@ -6,7 +6,6 @@ import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONUtil;
 import com.coffee.common.Constants;
 import com.coffee.common.bo.LoginUser;
-import com.coffee.common.cache.value.Value;
 import com.coffee.common.config.websocket.handler.WsHandler;
 import com.coffee.common.result.R;
 import lombok.AllArgsConstructor;

+ 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;
 }

+ 16 - 0
coffee-common/src/main/java/com/coffee/common/config/websocket/TopicMessage.java

@@ -0,0 +1,16 @@
+package com.coffee.common.config.websocket;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+@Data
+@AllArgsConstructor(staticName = "of")
+@NoArgsConstructor
+public class TopicMessage implements Serializable {
+    private Object message;
+    private String param;
+
+}

+ 32 - 91
coffee-common/src/main/java/com/coffee/common/config/websocket/handler/Subscribe.java

@@ -6,25 +6,17 @@ import com.coffee.common.Constants;
 import com.coffee.common.bo.LoginUser;
 import com.coffee.common.config.websocket.DefaultMessageListener;
 import com.coffee.common.config.websocket.MessagingRequest;
+import com.coffee.common.config.websocket.TopicMessage;
 import com.coffee.common.config.websocket.WebSocketConstant;
+import com.coffee.common.util.RedissonUtil;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import lombok.extern.slf4j.Slf4j;
+import org.redisson.api.RPatternTopic;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.dao.DataAccessException;
-import org.springframework.data.redis.connection.RedisConnection;
-import org.springframework.data.redis.connection.RedisPubSubCommands;
-import org.springframework.data.redis.connection.Subscription;
-import org.springframework.data.redis.core.RedisCallback;
-import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.util.ConcurrentReferenceHashMap;
 import org.tio.core.ChannelContext;
 
-import javax.annotation.Resource;
 import java.util.*;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.stream.Collectors;
 
 /**
@@ -36,23 +28,15 @@ import java.util.stream.Collectors;
  */
 @Slf4j
 public abstract class Subscribe implements WsHandler {
-    @Autowired
-    private RedisTemplate<String,Object> redisTemplate;
-
     @Autowired
     private ObjectMapper objectMapper;
 
-    public static final String SUBSCRIBE_TOPIC="subscribe-topic";
-    /**
-     * 存储主题与ws通道关联
-     */
-    private static Map<String,Set<ChannelContext>> subscribeTopics=new ConcurrentHashMap<>();
-
-
+    @Autowired
+    private RedissonUtil redissonUtil;
     /**
      * 存储主题与redis通道关联
      */
-    private static Map<String,RedisConnection> redisConnectionMap=new ConcurrentReferenceHashMap<>();
+    private static Map<String, RPatternTopic> topicMap=new ConcurrentReferenceHashMap<>();
 
 
     public TopicWrapper getTopic(String productName,String param,String tenantId){
@@ -60,10 +44,6 @@ public abstract class Subscribe implements WsHandler {
 
     };
 
-    public static Set<ChannelContext> getSubscribeChannel(String topic){
-        return subscribeTopics.get(topic);
-    }
-
 
     @Override
     public void onMessage(MessagingRequest message, ChannelContext channelContext) {
@@ -91,13 +71,10 @@ public abstract class Subscribe implements WsHandler {
         MessagingRequest.Type type = message.getType();
         if(MessagingRequest.Type.sub==type){
             //订阅主题
-            for (TopicWrapper topicWrapper : subScribeTopic) {
-                this.subscribe(channelContext,topicWrapper);
-            }
-//            subScribeTopic.forEach(topicWrapper->this.subscribe(channelContext,topicWrapper));
+            subScribeTopic.forEach(topicWrapper->this.subscribe(channelContext,topicWrapper));
         }else {
             //取消订阅主题
-//            subScribeTopic.forEach(topicWrapper->this.unsubscribe(channelContext,topicWrapper.getTopic()));
+            subScribeTopic.forEach(topicWrapper->this.unsubscribe(channelContext,topicWrapper.getTopic()));
         }
         log.error("订阅成功{}",subScribeTopic.stream().map(TopicWrapper::getTopic).collect(Collectors.toList()));
 
@@ -110,40 +87,8 @@ public abstract class Subscribe implements WsHandler {
      */
     public void subscribe(ChannelContext channelContext, TopicWrapper topicWrapper){
         //同一主题只订阅一次
-        Set<ChannelContext> channelContexts = subscribeTopics.computeIfAbsent(topicWrapper.getTopic(), k -> new HashSet<>());
-        channelContexts.add(channelContext);
-        boolean subscribe=false;
-        RedisConnection redisConnection = redisConnectionMap.get(topicWrapper.getTopic());
-        if(redisConnection==null){
-            subscribe=true;
-        }else {
-            Subscription subscription = redisConnection.getSubscription();
-            if(subscription==null||CollectionUtil.isEmpty(subscription.getPatterns())){
-                subscribe=true;
-            }else {
-                Collection<byte[]> patterns = subscription.getPatterns();
-                for (byte[] pattern : patterns) {
-                    String patternName = new String(pattern);
-                    if(topicWrapper.getTopic().equals(patternName)){
-                        subscribe=true;
-                        break;
-                    }
-                }
-            }
-        }
-        if(subscribe){
-            redisTemplate.execute(new RedisCallback<Object>() {
-                @Override
-                public Object doInRedis(RedisConnection connection) throws DataAccessException {
-                    CompletableFuture.runAsync(()->{
-                        connection.pSubscribe(new DefaultMessageListener(getId(),topicWrapper,objectMapper,channelContexts),topicWrapper.getTopic().getBytes());
-                    });
-                    redisConnectionMap.put(topicWrapper.getTopic(),connection);
-                    return null;
-                }
-            });
-        }
-        getTopicByChannel(channelContext).add(topicWrapper.getTopic());
+        RPatternTopic rTopic = topicMap.computeIfAbsent(topicWrapper.getTopic(),topic->redissonUtil.getPatternTopic(topicWrapper.getTopic()));
+        addTopicListener(rTopic,channelContext, topicWrapper.getTopic());
     };
 
     /**
@@ -155,37 +100,33 @@ public abstract class Subscribe implements WsHandler {
         if(StrUtil.isEmpty(topic)){
             return;
         }
-        AtomicBoolean remove = new AtomicBoolean(false);
-        subscribeTopics.computeIfPresent(topic,(k,v)->{
-            v.remove(channelContext);
-//            if(CollectionUtil.isEmpty(v)){
-                remove.set(true);
-//                redisTemplate.execute(new RedisCallback<Object>() {
-//                    @Override
-//                    public Object doInRedis(RedisConnection connection) throws DataAccessException {
-//                        RedisConnection redisConnection = redisConnectionMap.get(topic);
-//                        if (redisConnection!=null) {
-//                            Optional.ofNullable(redisConnection.getSubscription())
-//                                    .map(subscription -> {
-//                                        subscription.pUnsubscribe(topic.getBytes());
-//                                        return subscription;
-//                                    });
-//                        }
-//                        return null;
-//                    }
-//                });
-//                redisConnectionMap.remove(topic);
-//            }
-            return v;
+        topicMap.computeIfPresent(topic,(k,rTopic)->{
+            rTopic.removeListener( getTopicListener(channelContext,k));
+            return rTopic;
         });
+        Map<String, DefaultMessageListener> topicListeners = getTopicListeners(channelContext);
+        topicListeners.remove(topic);
     };
 
 
-    public Set<String> getTopicByChannel(ChannelContext channelContext){
-        Object result = Optional.ofNullable(channelContext.get(SUBSCRIBE_TOPIC)).orElse(new HashSet<>());
-        channelContext.set(SUBSCRIBE_TOPIC,result);
-        return  (Set<String>) result;
+    public Map<String,DefaultMessageListener> getTopicListeners(ChannelContext channelContext){
+        Object result = Optional.ofNullable(channelContext.get("topic")).orElse(new HashMap<String,DefaultMessageListener>());
+        channelContext.set("topic",result);
+        return  (Map<String,DefaultMessageListener>) result;
     }
 
+    public DefaultMessageListener getTopicListener(ChannelContext channelContext,String topic){
+        Map<String,DefaultMessageListener> result = (Map<String, DefaultMessageListener>) Optional.ofNullable(channelContext.get("topic")).orElse(new HashMap<>());
+        return  result.get(topic);
+    }
 
+    public DefaultMessageListener addTopicListener(RPatternTopic rTopic,ChannelContext channelContext,String topic){
+        Map<String, DefaultMessageListener> topicByChannel = getTopicListeners(channelContext);
+        DefaultMessageListener messageListener = topicByChannel.computeIfAbsent(topic, k -> {
+            DefaultMessageListener defaultMessageListener = new DefaultMessageListener(getId(), objectMapper, channelContext,rTopic);
+            rTopic.addListenerAsync(TopicMessage.class, defaultMessageListener);
+            return defaultMessageListener;
+        });
+        return  messageListener;
+    }
 }

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

@@ -14,10 +14,11 @@ import org.springframework.validation.annotation.Validated;
 
 
 import javax.validation.constraints.NotNull;
+import java.io.Serializable;
 import java.util.Date;
 
 @Data
-public abstract class  GenericEntity<PK> implements Entity,RecordModifierEntity,RecordCreationEntity {
+public abstract class  GenericEntity<PK> implements Entity,RecordModifierEntity,RecordCreationEntity, Serializable {
     private static final long serialVersionUID = 1L;
 
     @TableId(type = IdType.ASSIGN_ID)
@@ -39,9 +40,9 @@ public abstract class  GenericEntity<PK> implements Entity,RecordModifierEntity,
     private Date updateTime;
 
     /* 分组校验 */
-    public @interface Update {
+    public static @interface Update {
     }
 
-    public @interface Insert {
+    public static @interface Insert {
     }
 }

+ 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;
 }

+ 79 - 0
coffee-common/src/main/java/com/coffee/common/util/RedissonUtil.java

@@ -0,0 +1,79 @@
+package com.coffee.common.util;
+
+
+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.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName RedissonUtil.java
+ * @Description TODO
+ * @createTime 2022年05月17日 16:16:00
+ */
+@Component
+public class RedissonUtil {
+
+    @Autowired
+    @Getter
+    private RedissonClient redissonClient;
+
+    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);
+    }
+
+    public RTopic getTopic(String pattern){
+        return redissonClient.getTopic(pattern);
+    }
+
+    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);
+        }
+    }
+}

+ 6 - 0
coffee-framework/pom.xml

@@ -47,5 +47,11 @@
             <groupId>com.coffee</groupId>
             <artifactId>coffee-system</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>org.redisson</groupId>
+            <artifactId>redisson-spring-boot-starter</artifactId>
+        </dependency>
+
     </dependencies>
 </project>

+ 174 - 0
coffee-framework/src/main/java/com/coffee/framework/config/RedissonClientAutoConfiguration.java

@@ -0,0 +1,174 @@
+//
+// Source code recreated from a .class file by IntelliJ IDEA
+// (powered by Fernflower decompiler)
+//
+
+package com.coffee.framework.config;
+
+import org.redisson.Redisson;
+import org.redisson.api.RedissonClient;
+import org.redisson.config.ClusterServersConfig;
+import org.redisson.config.Config;
+import org.redisson.config.SentinelServersConfig;
+import org.redisson.config.SingleServerConfig;
+import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer;
+import org.redisson.spring.starter.RedissonProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.AutoConfigureBefore;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
+import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
+import org.springframework.boot.autoconfigure.data.redis.RedisProperties.Sentinel;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.core.io.Resource;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.util.ReflectionUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+@Configuration
+@ConditionalOnClass({Redisson.class, RedisOperations.class})
+@AutoConfigureBefore({RedisAutoConfiguration.class})
+@EnableConfigurationProperties({RedissonProperties.class, RedisProperties.class})
+public class RedissonClientAutoConfiguration {
+    private static final String REDIS_PROTOCOL_PREFIX = "redis://";
+    private static final String REDISS_PROTOCOL_PREFIX = "rediss://";
+    @Autowired(
+        required = false
+    )
+    private List<RedissonAutoConfigurationCustomizer> redissonAutoConfigurationCustomizers;
+    @Autowired
+    private RedissonProperties redissonProperties;
+    @Autowired
+    private RedisProperties redisProperties;
+    @Autowired
+    private ApplicationContext ctx;
+
+    public RedissonClientAutoConfiguration() {
+    }
+
+    @Bean(
+        destroyMethod = "shutdown"
+    )
+    @ConditionalOnMissingBean({RedissonClient.class})
+    public RedissonClient redisson() throws IOException {
+        Config config = null;
+        Method clusterMethod = ReflectionUtils.findMethod(RedisProperties.class, "getCluster");
+        Method timeoutMethod = ReflectionUtils.findMethod(RedisProperties.class, "getTimeout");
+        Object timeoutValue = ReflectionUtils.invokeMethod(timeoutMethod, this.redisProperties);
+        int timeout;
+        Method nodesMethod;
+        if (null == timeoutValue) {
+            timeout = 10000;
+        } else if (!(timeoutValue instanceof Integer)) {
+            nodesMethod = ReflectionUtils.findMethod(timeoutValue.getClass(), "toMillis");
+            timeout = ((Long) ReflectionUtils.invokeMethod(nodesMethod, timeoutValue)).intValue();
+        } else {
+            timeout = (Integer)timeoutValue;
+        }
+
+        if (this.redissonProperties.getConfig() != null) {
+            try {
+                config = Config.fromYAML(this.redissonProperties.getConfig());
+            } catch (IOException var13) {
+                try {
+                    config = Config.fromJSON(this.redissonProperties.getConfig());
+                } catch (IOException var12) {
+                    throw new IllegalArgumentException("Can't parse config", var12);
+                }
+            }
+        } else if (this.redissonProperties.getFile() != null) {
+            try {
+                InputStream is = this.getConfigStream();
+                config = Config.fromYAML(is);
+            } catch (IOException var11) {
+                try {
+                    InputStream is = this.getConfigStream();
+                    config = Config.fromJSON(is);
+                } catch (IOException var10) {
+                    throw new IllegalArgumentException("Can't parse config", var10);
+                }
+            }
+        } else if (this.redisProperties.getSentinel() != null) {
+            nodesMethod = ReflectionUtils.findMethod(Sentinel.class, "getNodes");
+            Object nodesValue = ReflectionUtils.invokeMethod(nodesMethod, this.redisProperties.getSentinel());
+            String[] nodes;
+            if (nodesValue instanceof String) {
+                nodes = this.convert(Arrays.asList(((String)nodesValue).split(",")));
+            } else {
+                nodes = this.convert((List)nodesValue);
+            }
+
+            config = new Config();
+            ((SentinelServersConfig)config.useSentinelServers().setMasterName(this.redisProperties.getSentinel().getMaster()).addSentinelAddress(nodes).setDatabase(this.redisProperties.getDatabase()).setConnectTimeout(timeout)).setPassword(this.redisProperties.getPassword());
+        } else {
+            Method method;
+            if (clusterMethod != null && ReflectionUtils.invokeMethod(clusterMethod, this.redisProperties) != null) {
+                Object clusterObject = ReflectionUtils.invokeMethod(clusterMethod, this.redisProperties);
+                method = ReflectionUtils.findMethod(clusterObject.getClass(), "getNodes");
+                List<String> nodesObject = (List) ReflectionUtils.invokeMethod(method, clusterObject);
+                String[] nodes = this.convert(nodesObject);
+                config = new Config();
+                ((ClusterServersConfig)config.useClusterServers().addNodeAddress(nodes).setConnectTimeout(timeout)).setPassword(this.redisProperties.getPassword());
+            } else {
+                config = new Config();
+                String prefix = "redis://";
+                method = ReflectionUtils.findMethod(RedisProperties.class, "isSsl");
+                if (method != null && (Boolean) ReflectionUtils.invokeMethod(method, this.redisProperties)) {
+                    prefix = "rediss://";
+                }
+
+                ((SingleServerConfig)config.useSingleServer().setAddress(prefix + this.redisProperties.getHost() + ":" + this.redisProperties.getPort()).setConnectTimeout(timeout)).setDatabase(this.redisProperties.getDatabase()).setPassword(this.redisProperties.getPassword());
+            }
+        }
+
+        if (this.redissonAutoConfigurationCustomizers != null) {
+            Iterator var19 = this.redissonAutoConfigurationCustomizers.iterator();
+
+            while(var19.hasNext()) {
+                RedissonAutoConfigurationCustomizer customizer = (RedissonAutoConfigurationCustomizer)var19.next();
+                customizer.customize(config);
+            }
+        }
+
+        return Redisson.create(config);
+    }
+
+    private String[] convert(List<String> nodesObject) {
+        List<String> nodes = new ArrayList(nodesObject.size());
+        Iterator var3 = nodesObject.iterator();
+
+        while(true) {
+            while(var3.hasNext()) {
+                String node = (String)var3.next();
+                if (!node.startsWith("redis://") && !node.startsWith("rediss://")) {
+                    nodes.add("redis://" + node);
+                } else {
+                    nodes.add(node);
+                }
+            }
+
+            return (String[])nodes.toArray(new String[nodes.size()]);
+        }
+    }
+
+    private InputStream getConfigStream() throws IOException {
+        Resource resource = this.ctx.getResource(this.redissonProperties.getFile());
+        InputStream is = resource.getInputStream();
+        return is;
+    }
+}

+ 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);
     }

+ 11 - 0
coffee-system/src/main/java/com/coffee/bus/bean/GeoPoint.java

@@ -0,0 +1,11 @@
+package com.coffee.bus.bean;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class  GeoPoint implements Serializable {
+    private String lon;
+    private String lat;
+}

+ 5 - 0
coffee-system/src/main/java/com/coffee/bus/bean/HisInfo.java

@@ -86,4 +86,9 @@ public class HisInfo {
      * 配置医生(配置人员、配药医生)
      */
     private String configPerson;
+    /**
+     * 医嘱
+     */
+    private String entrust;
+
 }

+ 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 - 11
coffee-system/src/main/java/com/coffee/bus/bean/config/Config.java

@@ -1,11 +0,0 @@
-package com.coffee.bus.bean.config;
-
-/**
- * @author lifang
- * @version 1.0.0
- * @ClassName Config.java
- * @Description TODO
- * @createTime 2022年04月12日 11:14:00
- */
-public abstract class Config {
-}

+ 0 - 97
coffee-system/src/main/java/com/coffee/bus/bean/config/EvalConfig.java

@@ -1,97 +0,0 @@
-package com.coffee.bus.bean.config;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-/**
- * @author lifang
- * @version 1.0.0
- * @ClassName EvalConfig.java
- * @Description 医院评价设置
- * @createTime 2022年04月12日 10:17:00
- */
-@Data
-@ApiModel("医院功能配置--评价设置")
-public class EvalConfig extends Config{
-
-    @ApiModelProperty(value = "评价提醒时间")
-    private Integer remindTime;
-
-    @ApiModelProperty(value = "已评价提醒间隔")
-    private Integer interval;
-
-    @ApiModelProperty(value = "疼痛评分静止")
-    private  Boolean statics;
-
-    @ApiModelProperty(value = "疼痛评分活动")
-    private  Boolean activity;
-
-    @ApiModelProperty(value = "镇静评分")
-    private  Boolean calm;
-
-    @ApiModelProperty(value = "左上肢")
-    private  Boolean leftArm;
-
-    @ApiModelProperty(value = "左下肢")
-    private  Boolean leftLeg;
-
-    @ApiModelProperty(value = "右上肢")
-    private  Boolean rightArm;
-
-    @ApiModelProperty(value = "右下肢")
-    private  Boolean rightLeg;
-
-    @ApiModelProperty(value = "恶心呕吐")
-    private  Boolean nauseaVomit;
-
-    @ApiModelProperty(value = "瘙痒")
-    private  Boolean itch;
-
-    @ApiModelProperty(value = "眩晕")
-    private  Boolean vertigo;
-
-    @ApiModelProperty(value = "咽喉疼痛")
-    private  Boolean soreThroat;
-
-    @ApiModelProperty(value = "尿潴留")
-    private  Boolean uroschesis;
-
-    @ApiModelProperty(value = "呼吸抑制")
-    private  Boolean breathDepression;
-
-    @ApiModelProperty(value = "声音嘶哑")
-    private  Boolean hoarseness;
-
-    @ApiModelProperty(value = "认知障碍")
-    private  Boolean cognitionObstacle;
-
-    @ApiModelProperty(value = "其他")
-    private  Boolean other;
-
-    @ApiModelProperty(value = "满意度")
-    private  Boolean satisfaction;
-
-
-    @ApiModelProperty(value = "评价时间",hidden = true)
-    private  Boolean evaluateTime;
-
-    @ApiModelProperty(value = "评价人")
-    private  Boolean evaluator;
-
-    @ApiModelProperty(value = "收缩压")
-    private  Boolean  shrinkPressure;
-
-
-    @ApiModelProperty(value = "舒张压")
-    private  Boolean  diastolicPressure;
-
-    @ApiModelProperty(value = "心率")
-    private  Boolean heartRate;
-
-    @ApiModelProperty(value = "呼吸频率")
-    private  Boolean breathRate;
-
-    @ApiModelProperty(value = "血氧饱和度")
-    private  Boolean bloodOxygenSaturation;
-}

+ 0 - 55
coffee-system/src/main/java/com/coffee/bus/bean/config/OtherConfig.java

@@ -1,55 +0,0 @@
-package com.coffee.bus.bean.config;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * @author lifang
- * @version 1.0.0
- * @ClassName OtherConfig.java
- * @Description TODO
- * @createTime 2022年04月12日 10:17:00
- */
-@Data
-@NoArgsConstructor
-@ApiModel("医院功能配置--其他设置")
-public class OtherConfig extends Config{
-
-    @ApiModelProperty("镇痛不足设置")
-    private Anal anal;
-
-    @ApiModelProperty("其他设置")
-    private Other other;
-
-    @Data
-    @NoArgsConstructor
-    @ApiModel("镇痛不足设置")
-    public static class Anal{
-        @ApiModelProperty("镇痛不足时间判定")
-        private Integer insufficientTime;
-        @ApiModelProperty("镇痛不足类型设置")
-        private Boolean valid;
-        @ApiModelProperty("镇痛不足次数设置")
-        private Integer insufficientCount;
-        @ApiModelProperty("镇痛不足提醒消失时间设置")
-        private Integer disappearTime;
-    }
-
-    @Data
-    @NoArgsConstructor
-    @ApiModel("其他设置")
-    public static class Other{
-        /**
-         * 不在服务区设置
-         */
-        @ApiModelProperty("不在服务区设置")
-        private Integer noSignal;
-        /**
-         * 低输注时间设置
-         */
-        @ApiModelProperty("低输注时间设置")
-        private Integer lowInfusion;
-    }
-}

+ 0 - 62
coffee-system/src/main/java/com/coffee/bus/bean/config/UndoConfig.java

@@ -1,62 +0,0 @@
-package com.coffee.bus.bean.config;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * @author lifang
- * @version 1.0.0
- * @ClassName ManualUndoConfig.java
- * @Description 医院撤泵设置
- * @createTime 2022年04月12日 10:17:00
- */
-@Data
-@ApiModel("医院功能配置--撤泵配置")
-public class UndoConfig extends Config{
-
-    @ApiModelProperty("自动撤泵")
-    private  AutoUndo auto;
-
-    @ApiModelProperty("手动撤泵")
-    private ManualUndo manual;
-    /**
-     * 自动撤泵
-     */
-    @ApiModel("自动撤泵")
-    @Data
-    @NoArgsConstructor
-    public static class AutoUndo{
-        @ApiModelProperty("开始自动撤泵")
-        private Boolean enable;
-        @ApiModelProperty("自动撤泵人类型")
-        private String undoByType;
-        @ApiModelProperty("自动撤泵人姓名")
-        private String undoBy;
-        @ApiModelProperty("关机到撤泵时间")
-        private Integer shutDownInterval;
-        @ApiModelProperty("不在服务区到撤泵时间")
-        private Integer noSignalInterval;
-    }
-
-    /**
-     * 手动撤泵
-     */
-    @ApiModel("手动撤泵")
-    @Data
-    @NoArgsConstructor
-    public static class  ManualUndo{
-        @ApiModelProperty("开启手动撤泵配置")
-        private Boolean enable;
-        @ApiModelProperty("撤泵人为空检测")
-        private Boolean undoByCheck;
-        @ApiModelProperty("销毁人为空检测")
-        private Boolean destroyerCheck;
-        @ApiModelProperty("见证人为空检测")
-        private Boolean witnessesCheck;
-        @ApiModelProperty("不在服务区撤泵时间")
-        private Boolean undoTime;
-
-    }
-}

+ 5 - 8
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;
@@ -30,16 +31,12 @@ public class BusAlarmController extends BaseCrudController<BusDeviceAlarmEntity,
 
     private final LocalBusDeviceAlarmService deviceAlarmService;
 
-    @PutMapping("/cause/{id}")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "cause",value = "报警原因",dataTypeClass = String.class,required = true,example = "设备误报"),
-            @ApiImplicitParam(name = "id",value = "报警信息id",dataTypeClass = String.class,required = true)
-    })
+    @PostMapping("/cause/{id}")
     @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);
     }
 
 

+ 84 - 51
coffee-system/src/main/java/com/coffee/bus/controller/BusClinicController.java

@@ -1,9 +1,11 @@
 package com.coffee.bus.controller;
 
 import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.coffee.bus.controller.vo.ClinicStatsVo;
+import com.coffee.bus.controller.vo.ClinicEditVo;
 import com.coffee.bus.entity.*;
 import com.coffee.bus.registry.device.DeviceRegistry;
 import com.coffee.bus.service.*;
@@ -12,12 +14,13 @@ 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 lombok.extern.slf4j.Slf4j;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.CompletableFuture;
 import java.util.stream.Collectors;
 
 /**
@@ -30,6 +33,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;
@@ -38,9 +42,14 @@ public class BusClinicController {
     private final LocalBusInfusionModifyService infusionModifyService;
     private final LocalBusDeviceHistoryService deviceHistoryService;
     private final DeviceRegistry deviceRegistry;
+    private final LocalBusDeviceManualService deviceManualService;
+    private final LocalBusPatientService patientService;
     @PostMapping("/stats")
     @ApiOperation(value = "临床过程中的数据记录",notes = "权限【无】")
-    public R<ClinicStatsReturnResult> stats(@RequestBody ClinicStatsVo statsVo) {
+    public R<ClinicStatsReturnResult> stats(@RequestBody@Validated ClinicStatsVo statsVo) {
+        if (!(statsVo.isAppendDose()||statsVo.isContinueDose()||statsVo.isInputDose()||statsVo.isInValidCount()||statsVo.isValidCount())){
+            return R.success(new ClinicStatsReturnResult());
+        }
         return R.success(clinicService.stats(statsVo));
     }
 
@@ -56,7 +65,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){
@@ -64,56 +74,79 @@ public class BusClinicController {
         }
         //填充临床信息
         result.setClinic(ClinicAnalClinicRecord.parse(clinic));
-        CompletableFuture
-                .runAsync(()->{
-                    //填充评价记录
-                    result.setEvaluations(evaluationService.list(new QueryWrapper<BusEvaluationEntity>().lambda().eq(BusEvaluationEntity::getClinicId,clinicId).orderByAsc(BusEvaluationEntity::getEvaluateTime)));
-                })
-                .thenAcceptAsync(ignore->{
-                    //填充输注记录
-                    List<BusInfusionHistoryEntity> infusionHistories = infusionHistoryService.list(new QueryWrapper<BusInfusionHistoryEntity>().lambda()
-                            .eq(BusInfusionHistoryEntity::getClinicId, clinicId)
-                            .orderByAsc(BusInfusionHistoryEntity::getStartTime));
-
-                    //添加设备别名
-                    Map<String, List<BusInfusionHistoryEntity>> infusionByDeviceId = infusionHistories.stream().collect(Collectors.groupingBy(BusInfusionHistoryEntity::getDeviceId));
-                    infusionByDeviceId.forEach((deviceId,infusions)->{
-                        String alias = deviceRegistry.getOperator(deviceId).getAlias();
-                        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);
-                })
-                .thenAccept(ignore->{
-                    List<String> infusionIds = result.getInfusionRecords().stream().map(ClinicAnalInfusionRecord::getId).collect(Collectors.toList());
-                    List<BusDeviceHistoryEntity> deviceHistories = deviceHistoryService.list(new QueryWrapper<BusDeviceHistoryEntity>()
-                            .lambda()
-                            .select(BusDeviceHistoryEntity::getInfusionId,BusDeviceHistoryEntity::getPcaValidCount,BusDeviceHistoryEntity::getInfusionModifyId,
-                                    BusDeviceHistoryEntity::getPcaInvalidCount,BusDeviceHistoryEntity::getInputDose,BusDeviceHistoryEntity::getUploadTime)
-                            .in(BusDeviceHistoryEntity::getInfusionId, infusionIds)
-                            .eq(BusDeviceHistoryEntity::getMaster, true));
-                    //标记输注
-                    result.markInfusion(deviceHistories);
-                    List<ClinicStatsQueryResult> statsQueryResults = deviceHistories.stream().map(history -> {
-                        ClinicStatsQueryResult statsQueryResult = new ClinicStatsQueryResult();
-                        statsQueryResult.setInputDose(history.getInputDose());
-                        statsQueryResult.setInValidCount(history.getPcaInvalidCount());
-                        statsQueryResult.setValidCount(history.getPcaValidCount());
-                        statsQueryResult.setUploadTime(history.getUploadTime());
-                        return statsQueryResult;
-                    }).collect(Collectors.toList());
-                    //填充统计信息
-                    result.setStats(ClinicStatsReturnResult.of(statsQueryResults));
-                })
-                .join();
+
+        //填充评价记录
+        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)->{
+            String alias = deviceRegistry.getOperator(deviceId).getAlias();
+            infusions.forEach(infusion->infusion.setAlias(alias));
+        });
+
+        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>()
+                .lambda()
+                .select(BusDeviceHistoryEntity::getInfusionId,BusDeviceHistoryEntity::getPcaValidCount,BusDeviceHistoryEntity::getInfusionModifyId,
+                        BusDeviceHistoryEntity::getPcaInvalidCount,BusDeviceHistoryEntity::getInputDose,BusDeviceHistoryEntity::getUploadTime)
+                .in(BusDeviceHistoryEntity::getInfusionId, infusionIds)
+                .eq(BusDeviceHistoryEntity::getMaster, true));
+        //标记输注
+        result.markInfusion(deviceHistories);
+        List<ClinicStatsQueryResult> statsQueryResults = deviceHistories.stream().map(history -> {
+            ClinicStatsQueryResult statsQueryResult = new ClinicStatsQueryResult();
+            statsQueryResult.setInputDose(history.getInputDose());
+            statsQueryResult.setInValidCount(history.getPcaInvalidCount());
+            statsQueryResult.setValidCount(history.getPcaValidCount());
+            statsQueryResult.setUploadTime(history.getUploadTime());
+            return statsQueryResult;
+        }).collect(Collectors.toList());
+        //填充统计信息
+        result.setStats(ClinicStatsReturnResult.of(statsQueryResults));
+
 
 
         return R.success(result);
     }
+
+
+    @PostMapping("/edit")
+    @SaCheckPermission("bus:clinic:edit")
+    @ApiOperation(value = "编辑病人信息",notes = "编辑病人临床信息,权限【bus:clinic:edit】")
+    public R<Boolean> edit(@RequestAttribute("tenantId")@ApiParam(hidden = true) String tenantId, @RequestBody @Validated ClinicEditVo entity){
+        if(entity.getHaveDevice()){
+            BusClinicEntity clinic = entity.getClinic();
+            if(clinic==null|| StrUtil.isEmpty(clinic.getId())){
+                throw new CustomException("临床信息不能为空");
+            }
+            clinic.setTenantId(tenantId);
+            patientService.manualEdit(clinic);
+            return R.success(true);
+        }else {
+            deviceManualService.edit(entity.getManual(),entity.getClinic());
+            return R.success(true);
+        }
+    }
+
+    @PostMapping("/save")
+    @SaCheckPermission("bus:clinic:save")
+    @ApiOperation(value = "新增手术信息",notes = "新增病人信息,权限【bus:clinic:save】")
+    public R save(@RequestBody ClinicEditVo entity){
+        deviceManualService.save(entity.getManual(),entity.getClinic());
+        return R.success();
+    }
+
 }

+ 2 - 28
coffee-system/src/main/java/com/coffee/bus/controller/BusDeviceManualController.java

@@ -1,20 +1,10 @@
 package com.coffee.bus.controller;
 
-import cn.dev33.satoken.SaManager;
 import cn.dev33.satoken.annotation.SaCheckPermission;
-import cn.dev33.satoken.stp.StpLogic;
-import cn.hutool.core.util.StrUtil;
-import com.baomidou.mybatisplus.core.mapper.Mapper;
-import com.coffee.bus.controller.vo.DeviceManualVo;
-import com.coffee.bus.entity.BusDeviceManualEntity;
-import com.coffee.bus.entity.BusDrugEntity;
+import com.coffee.bus.controller.vo.ClinicEditVo;
 import com.coffee.bus.service.LocalBusDeviceManualService;
-import com.coffee.bus.service.LocalBusDrugService;
 import com.coffee.bus.service.dto.ManualMonitorQuery;
 import com.coffee.bus.service.dto.ManualMonitorResult;
-import com.coffee.common.crud.BaseService;
-import com.coffee.common.crud.controller.BaseCrudController;
-import com.coffee.common.crud.controller.BaseQueryController;
 import com.coffee.common.result.R;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -40,25 +30,9 @@ import java.util.List;
 public class BusDeviceManualController {
     private final LocalBusDeviceManualService deviceManualService;
 
-    @PostMapping("/edit")
-    @SaCheckPermission("device:manual:edit")
-    @ApiOperation(value = "编辑病人信息",notes = "编辑病人信息,权限【device:manual:edit】")
-    public R edit(@RequestBody DeviceManualVo entity){
-        deviceManualService.edit(entity.getManual(),entity.getClinic());
-        return R.success();
-    }
-
-    @PostMapping("/save")
-    @SaCheckPermission("device:manual:save")
-    @ApiOperation(value = "新增病人信息",notes = "新增病人信息,权限【device:manual:save】")
-    public R save(@RequestBody DeviceManualVo entity){
-        deviceManualService.save(entity.getManual(),entity.getClinic());
-        return R.success();
-    }
-
     @PostMapping("/no_page")
     @SaCheckPermission("device:manual:query")
-    @ApiOperation(value = "查询其他监控输注列表,不分页",notes = "新增病人信息,权限【device:manual:query】")
+    @ApiOperation(value = "查询其他监控输注列表,不分页",notes = "查询其他监控输注列表,权限【device:manual:query】")
     public R<List<ManualMonitorResult>> list(@RequestBody ManualMonitorQuery query){
         return R.success(deviceManualService.selectMonitor(query));
     }

+ 15 - 26
coffee-system/src/main/java/com/coffee/bus/controller/BusHospitalConfigController.java

@@ -1,13 +1,13 @@
 package com.coffee.bus.controller;
 
+import cn.dev33.satoken.annotation.SaCheckPermission;
 import com.baomidou.mybatisplus.core.mapper.Mapper;
-import com.coffee.bus.bean.config.EvalConfig;
-import com.coffee.bus.bean.config.OtherConfig;
-import com.coffee.bus.bean.config.UndoConfig;
 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;
@@ -28,29 +28,6 @@ import org.springframework.web.bind.annotation.*;
 public class BusHospitalConfigController extends BaseCrudController<BusHospitalConfigEntity, String> {
     private final LocalBusHospitalConfigService hospitalConfigService;
 
-    @PostMapping("/eval")
-    @ApiOperation(value = "",hidden = true)
-    @Deprecated
-    public R evalConfig(@RequestBody EvalConfig evalConfig){
-        return R.success();
-    }
-
-
-    @PostMapping("/other")
-    @ApiOperation(value = "",hidden = true)
-    @Deprecated
-    public R otherConfig(@RequestBody OtherConfig evalConfig){
-        return R.success();
-    }
-
-
-    @PostMapping("/undo")
-    @ApiOperation(value = "",hidden = true)
-    @Deprecated
-    public R undoConfig(@RequestBody UndoConfig evalConfig){
-        return R.success();
-    }
-
 
     /**
      * 权限控制前缀
@@ -61,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】")

+ 62 - 18
coffee-system/src/main/java/com/coffee/bus/controller/BusPatientController.java

@@ -6,6 +6,7 @@ import cn.dev33.satoken.stp.StpLogic;
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.Update;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.mapper.Mapper;
 import com.coffee.bus.controller.vo.GetPatientInfoVo;
@@ -22,11 +23,12 @@ import com.coffee.bus.service.dto.*;
 import com.coffee.bus.utils.WsPublishUtils;
 import com.coffee.common.crud.BaseService;
 import com.coffee.common.crud.controller.BaseQueryController;
+import com.coffee.common.entity.GenericEntity;
 import com.coffee.common.exception.CustomException;
 import com.coffee.common.result.R;
-import com.coffee.common.result.ResultCode;
 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;
 
@@ -90,7 +92,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)){
@@ -102,7 +104,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))));
     }
 
@@ -133,7 +136,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());
 
@@ -181,15 +193,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();
@@ -198,7 +223,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);
         //判断当前病号下是否还存在副泵
@@ -221,17 +247,21 @@ 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();
     }
 
 
-    @PostMapping("/edit")
-    @SaCheckPermission("device:patient:edit")
-    @ApiOperation(value = "编辑病人当前手术信息",notes = "编辑病人信息及病人当前手术信息,权限标识为【device:patient:edit】")
-    public R edit(@RequestBody BusClinicEntity clinic){
-        patientService.manualEdit(clinic);
-        return R.success();
-    }
+//    @PostMapping("/edit")
+//    @SaCheckPermission("device:patient:edit")
+//    @ApiOperation(value = "编辑病人当前手术信息",notes = "编辑病人信息及病人当前手术信息,权限标识为【device:patient:edit】")
+//    public R edit(@RequestAttribute("tenantId")@ApiParam(hidden = true) String tenantId,@RequestBody@Validated(GenericEntity.Update.class) BusClinicEntity clinic){
+//        clinic.setTenantId(tenantId);
+//        patientService.manualEdit(clinic);
+//        return R.success(true);
+//    }
 
 
     @GetMapping("/monitor/{monitorType}/{clinicId}")
@@ -278,11 +308,25 @@ public class BusPatientController  implements BaseQueryController<BusPatientEnti
 
     @PostMapping("/pull/async")
     @SaCheckPermission("device:patient:pull")
-    @ApiOperation(value = "步更新患者信息,超时时间默认为10s,超时后数据返回继续处理,输注监控",notes = "权限标识为【bus:patient:pull】")
-    public DeferredResult<R<BusClinicEntity>> syn(@RequestAttribute("tenantId") String tenantId, @RequestBody GetPatientInfoVo vo){
+    @ApiOperation(value = "步更新患者信息,超时时间默认为10s,超时后数据返回继续处理,输注监控",notes = "权限标识为【bus:patient:pull】")
+    public DeferredResult<R<BusClinicEntity>> syn(@RequestAttribute("tenantId")@ApiParam(hidden = true) String tenantId, @RequestBody GetPatientInfoVo vo){
         return patientService.getPatientInfoFromHis(tenantId,vo.getPatientCode(),vo.getTimeout(),false);
     }
 
+
+    @SaCheckPermission("device:patient:query")
+    @ApiOperation(value = "泵重复绑定数量",notes = "权限标识为【bus:patient:query】")
+    @PostMapping("/_count/repeat")
+    public R<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
@@ -294,7 +338,7 @@ public class BusPatientController  implements BaseQueryController<BusPatientEnti
     @PostMapping("/pull/sync")
     @SaCheckPermission("device:patient:pull")
     @ApiOperation(value = "同步更新患者信息,超时时间默认为10s,超时后数据返回则不进行处理,无泵更新",notes = "权限标识为【bus:patient:pull】")
-    public DeferredResult<R<BusClinicEntity>>  async(@RequestAttribute("tenantId") String tenantId, @RequestBody GetPatientInfoVo vo){
+    public DeferredResult<R<BusClinicEntity>>  async(@RequestAttribute("tenantId")@ApiParam(hidden = true) String tenantId, @RequestBody GetPatientInfoVo vo){
         return patientService.getPatientInfoFromHis(tenantId,vo.getPatientCode(),vo.getTimeout(),true);
     }
 

+ 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;
+}

+ 8 - 3
coffee-system/src/main/java/com/coffee/bus/controller/vo/DeviceManualVo.java → coffee-system/src/main/java/com/coffee/bus/controller/vo/ClinicEditVo.java

@@ -6,16 +6,21 @@ 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 DeviceManualVo.java
+ * @ClassName ClinicEditVo.java
  * @Description TODO
  * @createTime 2022年05月06日 09:29:00
  */
-@ApiModel("手动添加其他监控视图")
+@ApiModel("编辑/新增")
 @Data
-public class DeviceManualVo {
+public class ClinicEditVo {
+    @ApiModelProperty("0、无泵 1、输注 ")
+    @NotNull(message = "输注判断标识不能为空")
+    private Boolean haveDevice;
     @ApiModelProperty("设备信息")
     private BusDeviceManualEntity manual;
     @ApiModelProperty("手术信息")

+ 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;
+}

+ 8 - 3
coffee-system/src/main/java/com/coffee/bus/entity/BusClinicEntity.java

@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.annotation.TableLogic;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
 import com.coffee.bus.bean.HisInfo;
+import com.coffee.bus.service.dto.FormulaDrugDomain;
 import com.coffee.bus.service.dto.UndoDeviceConfig;
 import com.coffee.common.entity.TenantGenericEntity;
 import com.coffee.common.enums.SexEnum;
@@ -34,7 +35,7 @@ public class BusClinicEntity extends TenantGenericEntity<String,String> {
 
     @ApiModelProperty(value = "临床手术名称")
     @Length(max = 255,message = "临床手术名称长度不得超过255个字节")
-    private String name;
+    private String surgeryName;
 
     @ApiModelProperty(value = "病号")
     @Length(max = 255,message = "病号长度不得超过255个字节")
@@ -98,7 +99,7 @@ public class BusClinicEntity extends TenantGenericEntity<String,String> {
 
     @ApiModelProperty(value = "配方")
     @TableField(typeHandler = FastjsonTypeHandler.class,javaType = true)
-    private List<FormulaDrugDomain> formula;
+    private FormulaDrugDomain formula;
 
     @ApiModelProperty(value = "临床是否结束,0、未结束 1、结束 ")
     private Boolean finished;
@@ -120,6 +121,9 @@ public class BusClinicEntity extends TenantGenericEntity<String,String> {
     @JsonIgnoreProperties(allowGetters = true)
     private Boolean monitorType;
 
+    @ApiModelProperty(value = "医嘱")
+    private String entrust;
+
     public static BusClinicEntity of(HisInfo hisInfo){
         BusClinicEntity clinic = new BusClinicEntity();
         clinic.setTenantId(hisInfo.getHospitalId());
@@ -132,13 +136,14 @@ public class BusClinicEntity extends TenantGenericEntity<String,String> {
         //病区 需新增 todo
         clinic.setWard(hisInfo.getWard());
         clinic.setBedNo(hisInfo.getBedNo());
-        clinic.setName(hisInfo.getOperation());
+        clinic.setSurgeryName(hisInfo.getOperation());
         clinic.setSurgeryDoctor(hisInfo.getSurgeon());
         clinic.setStartTime(hisInfo.getOperationTime());
         //asa分级 todo
         //easymode todo
 //        clinic.setFormula(hisInfo.getFormula());
         clinic.setConfigPerson(hisInfo.getConfigPerson());
+        clinic.setEntrust(hisInfo.getEntrust());
         return clinic;
     }
 }

+ 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 - 0
coffee-system/src/main/java/com/coffee/bus/entity/BusFormulaEntity.java

@@ -3,6 +3,7 @@ package com.coffee.bus.entity;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
+import com.coffee.bus.service.dto.FormulaDrugDomain;
 import com.coffee.common.entity.TenantGenericEntity;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;

+ 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)

+ 11 - 43
coffee-system/src/main/java/com/coffee/bus/entity/BusHospitalEntity.java

@@ -2,13 +2,12 @@ package com.coffee.bus.entity;
 
 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;
@@ -73,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;
@@ -86,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)
@@ -138,9 +110,5 @@ public class BusHospitalEntity implements RecordModifierEntity, RecordCreationEn
     @TableLogic(value = "0",delval = "1")
     private Integer isDelete;
 
-    @Data
-    public static class  GeoPoint{
-        private String lon;
-        private String lat;
-    }
+
 }

+ 2 - 2
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());
         /**
          * 脉冲泵参数
          */
@@ -137,7 +137,7 @@ public class BusInfusionHistoryEntity extends CommonDeviceParam<String,String> {
         entity.setAlarm(running.getAlarm());
 
         //若当前临床信息不存在,则将时间戳置为 3000/01/01 01:01:01
-        entity.setClinicStartTime(new Date(32503654861L));
+        entity.setClinicStartTime(new Date(32503654861000L));
         return entity;
     }
 

+ 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());
         /**
          * 脉冲泵参数
          */

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

@@ -1,6 +1,7 @@
 package com.coffee.bus.entity;
 
 import com.coffee.bus.enums.DeviceAlarmEnum;
+import com.coffee.bus.enums.DeviceStatusEnum;
 import com.coffee.bus.enums.DeviceTypeEnum;
 import com.coffee.common.enums.SexEnum;
 import io.swagger.annotations.ApiModel;
@@ -40,7 +41,7 @@ public class PatientDeviceRepeatDomain {
     @ApiModelProperty("设备别名")
     private String deviceAlias;
     @ApiModelProperty("设备运行状态")
-    private DeviceTypeEnum deviceRunState;
+    private DeviceStatusEnum deviceRunState;
     @ApiModelProperty("设备报警信息")
     private DeviceAlarmEnum deviceAlarm;
     @ApiModelProperty("输注开始时间")

+ 61 - 0
coffee-system/src/main/java/com/coffee/bus/entity/common/CommonDeviceParam.java

@@ -1,10 +1,13 @@
 package com.coffee.bus.entity.common;
 
+import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.annotation.FieldStrategy;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.coffee.bus.enums.DeviceAlarmEnum;
 import com.coffee.bus.enums.DeviceStatusEnum;
 import com.coffee.bus.enums.FlowStatusEnum;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.experimental.Accessors;
@@ -30,18 +33,76 @@ public class CommonDeviceParam<PK,TN>  extends DeviceProperties<PK,TN>  {
 
     @ApiModelProperty(value = "输注即将结束提醒",readOnly = true)
     @TableField(updateStrategy = FieldStrategy.IGNORED)
+    @JsonIgnore
     private Boolean warnWillFinished;
 
     @ApiModelProperty(value = "镇痛不足提醒",readOnly = true)
     @TableField(updateStrategy = FieldStrategy.IGNORED)
+    @JsonIgnore
     private Boolean warnAnalgesicPoor;
 
     @ApiModelProperty(value = "电量偏低提醒",readOnly = true)
     @TableField(updateStrategy = FieldStrategy.IGNORED)
+    @JsonIgnore
     private Boolean warnLowBattery;
 
     @ApiModelProperty(value = "加减档提示",readOnly = true)
     @TableField(updateStrategy = FieldStrategy.IGNORED)
+    @JsonIgnore
     private FlowStatusEnum warnFlow;
 
+    @TableField(exist = false)
+    @ApiModelProperty("提醒字段")
+    private String warns;
+
+    private void judgeWarnWillFinished() {
+        if(!Boolean.TRUE.equals(this.warnWillFinished)){
+            return;
+        }
+        if (StrUtil.isEmpty(this.warns)) {
+            this.warns="输注即将结束;";
+        }else {
+            this.warns=this.warns+"输注即将结束;";
+        }
+    }
+
+    private void judgeWarnAnalgesicPoor() {
+        if(!Boolean.TRUE.equals(this.warnAnalgesicPoor)){
+            return;
+        }
+        if (StrUtil.isEmpty(this.warns)) {
+            this.warns="镇痛不足;";
+        }else {
+            this.warns=this.warns+"镇痛不足;";
+        }
+    }
+
+    private void judgeWarnLowBattery() {
+        if(!Boolean.TRUE.equals(this.warnLowBattery)){
+            return;
+        }
+        if (StrUtil.isEmpty(this.warns)) {
+            this.warns="电量偏低;";
+        }else {
+            this.warns=this.warns+"电量偏低;";
+        }
+    }
+
+    private void judgeWarnFlow() {
+        if(this.warnFlow==null){
+            return;
+        }
+        if (StrUtil.isEmpty(this.warns)) {
+            this.warns=warnFlow.getText()+";";
+        }else {
+            this.warns=this.warns+warnFlow.getText()+";";
+        }
+    }
+
+    public void handleWarn(){
+        judgeWarnAnalgesicPoor();
+        judgeWarnFlow();
+        judgeWarnLowBattery();
+        judgeWarnWillFinished();
+    }
 }

+ 15 - 8
coffee-system/src/main/java/com/coffee/bus/enums/ConfigEnum.java

@@ -1,10 +1,6 @@
 package com.coffee.bus.enums;
 
 import com.baomidou.mybatisplus.annotation.IEnum;
-import com.coffee.bus.bean.config.EvalConfig;
-import com.coffee.bus.bean.config.OtherConfig;
-import com.coffee.bus.bean.config.UndoConfig;
-import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 
@@ -18,11 +14,22 @@ import lombok.Getter;
 @Getter
 @AllArgsConstructor
 public enum  ConfigEnum implements IEnum<Integer> {
-    undo(0,"撤泵配置", UndoConfig.class),
-    eval(1,"评价配置", EvalConfig.class),
-    other(2,"其他配置", OtherConfig.class);
+    undo(0,"撤泵配置"),
+    eval(1,"评价配置"),
+    other(2,"其他配置");
 
     private Integer value;
     private String text;
-    private Class configClass;
+
+    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;
+    }
+}

+ 37 - 0
coffee-system/src/main/java/com/coffee/bus/hospital/config/HospitalConfigHandler.java

@@ -0,0 +1,37 @@
+package com.coffee.bus.hospital.config;
+
+import com.coffee.bus.hospital.enums.ConfigHandlerEnums;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName HospitalConfigHandler.java
+ * @Description 医院配置处理器
+ * @createTime 2022年05月18日 10:33:00
+ */
+public interface HospitalConfigHandler<E,T> {
+
+    String getHospitalId();
+
+    ConfigHandlerEnums getId();
+
+    String getDescription();
+
+    /**
+     * 描述: 设置配置参数
+     * @author lifang
+     * @date 2022/5/18 10:34
+     * @param config
+     * @return void
+     */
+    void setConfig(E config);
+
+    /**
+     * 描述: 处理传入数据
+     * @author lifang
+     * @date 2022/5/18 10:34
+     * @param source 处理数据
+     * @return void
+     */
+    void handler(T source);
+}

+ 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;
+    }
+}

+ 27 - 0
coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionAnalConfig.java

@@ -0,0 +1,27 @@
+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 FunctionAnalConfig.java
+ * @Description TODO
+ * @createTime 2022年05月18日 10:18:00
+ */
+@ApiModel("镇痛不足配置")
+@Data
+public class FunctionAnalConfig implements Serializable {
+    @ApiModelProperty("镇痛不足提醒消失时间")
+    private Integer disappearTime;
+    @ApiModelProperty("镇痛不足判定次数")
+    private Integer insufficientCount;
+    @ApiModelProperty("镇痛不足判定时间")
+    private Integer insufficientTime;
+    @ApiModelProperty("镇痛不足判定 pca有效 pca无效")
+    private Boolean valid;
+}

+ 29 - 0
coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionAutoUndoConfig.java

@@ -0,0 +1,29 @@
+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 FunctionAutoUndoConfig.java
+ * @Description TODO
+ * @createTime 2022年05月18日 08:42:00
+ */
+@ApiModel("自动撤泵配置")
+@Data
+public class FunctionAutoUndoConfig implements Serializable {
+    @ApiModelProperty("是否开启自动撤泵")
+    private boolean enable;
+    @ApiModelProperty("不在服务区撤泵时间间隔")
+    private Integer noSignalInterval;
+    @ApiModelProperty("关机撤泵时间间隔")
+    private Integer shutDownInterval;
+    @ApiModelProperty("自动撤泵人姓名")
+    private String undoBy;
+    @ApiModelProperty("自动撤泵人是否为麻醉医生")
+    private boolean undoByType;
+}

+ 23 - 0
coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionExtraConfig.java

@@ -0,0 +1,23 @@
+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 FunctionExtraConfig.java
+ * @Description TODO
+ * @createTime 2022年05月18日 10:22:00
+ */
+@ApiModel("其他配置中的其他配置")
+@Data
+public class FunctionExtraConfig implements Serializable {
+    @ApiModelProperty("低输注时间设置")
+    private Integer lowInfusion;
+    @ApiModelProperty("不在服务区时间设置")
+    private Integer noSignal;
+}

+ 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;
+
+}

+ 31 - 0
coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionManualUndoConfig.java

@@ -0,0 +1,31 @@
+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 FunctionAutoUndoConfig.java
+ * @Description TODO
+ * @createTime 2022年05月18日 08:42:00
+ */
+@ApiModel("手动撤泵配置")
+@Data
+public class FunctionManualUndoConfig implements Serializable {
+    @ApiModelProperty("是否开启手动撤泵配置")
+    private boolean enable;
+    @ApiModelProperty("撤泵人为空检测")
+    private boolean undoByCheck;
+    @ApiModelProperty("销毁人为空检测")
+    private boolean destroyerCheck;
+    @ApiModelProperty("见证人为空检测")
+    private boolean witnessesCheck;
+    @ApiModelProperty("不在服务区到撤泵时间,当设备处于不在服务区状态时,过了一定的时间间隔才能手动撤泵")
+    @Deprecated
+    private Integer undoTime;
+
+}

+ 23 - 0
coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionOtherConfig.java

@@ -0,0 +1,23 @@
+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 FunctionOtherConfig.java
+ * @Description TODO
+ * @createTime 2022年05月18日 08:54:00
+ */
+@Data
+@ApiModel("其他配置")
+public class FunctionOtherConfig implements Serializable {
+    @ApiModelProperty("其他配置")
+    private FunctionExtraConfig extra;
+    @ApiModelProperty("镇痛不足配置")
+    private FunctionAnalConfig anal;
+}

+ 22 - 0
coffee-system/src/main/java/com/coffee/bus/hospital/config/bean/FunctionUndoConfig.java

@@ -0,0 +1,22 @@
+package com.coffee.bus.hospital.config.bean;
+
+import io.swagger.annotations.ApiModel;
+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 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;
+}

+ 9 - 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;
@@ -70,6 +70,12 @@ public class HisRequest implements Serializable {
      */
     private boolean sync;
 
+    /**
+     *
+     * 医院id
+     *
+     */
+    private String tenantId;
     /**
      *
      * 用户响应结果
@@ -77,5 +83,5 @@ public class HisRequest implements Serializable {
      */
     @JsonIgnore
     @NotNull
-    private DeferredResult<R<BusClinicEntity>> result;
+    private List<DeferredResult<R<BusClinicEntity>>> result;
 }

+ 7 - 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;
 
@@ -69,5 +69,11 @@ public class HisResponse {
      */
     private Date timestamp;
 
+    /**
+     *
+     * 医院id
+     *
+     */
+    private String tenantId;
 
 }

+ 76 - 44
coffee-system/src/main/java/com/coffee/bus/his/HisScriptSession.java → coffee-system/src/main/java/com/coffee/bus/hospital/his/HisScriptSession.java

@@ -1,8 +1,9 @@
-package com.coffee.bus.his;
+package com.coffee.bus.hospital.his;
 
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.date.DateField;
+import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.RandomUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.extra.spring.SpringUtil;
@@ -14,17 +15,22 @@ 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.bus.service.dto.FormulaDrugDetailDomain;
+import com.coffee.bus.service.dto.FormulaDrugDomain;
+import com.coffee.common.cache.ConfigStorage;
+import com.coffee.common.cache.manager.ConfigStorageManager;
 import com.coffee.common.cache.value.Value;
+import com.coffee.common.enums.SexEnum;
+import com.coffee.common.exception.CustomException;
 import com.coffee.common.result.R;
+import lombok.Getter;
 import lombok.extern.slf4j.Slf4j;
-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;
@@ -32,7 +38,7 @@ import org.tio.core.Tio;
 import org.tio.core.utils.TioUtils;
 import org.tio.websocket.common.WsResponse;
 
-import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executors;
@@ -48,38 +54,25 @@ import java.util.concurrent.TimeUnit;
  */
 @Slf4j
 public class HisScriptSession {
+    @Getter
     private String hospitalId;
     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,
-                            RedisTemplate redisTemplate, LocalBusClinicService clinicService, LocalBusHospitalService hospitalService) {
-        this.hospitalId = hospitalId;
-        this.channelContext = channelContext;
-        this.scriptManager = scriptManager;
-        this.clinicService = clinicService;
-        this.hospitalService=hospitalService;
-        init(redisTemplate,hospitalId,hospitalService);
-    }
 
-    public HisScriptSession(String hospitalId, ScriptManager scriptManager, RedisTemplate redisTemplate, LocalBusClinicService clinicService,LocalBusHospitalService hospitalService) {
+    public HisScriptSession(String hospitalId, ScriptManager scriptManager, ConfigStorageManager configStorageManager, LocalBusClinicService clinicService, LocalBusHospitalService hospitalService) {
         this.hospitalId = hospitalId;
         this.scriptManager = scriptManager;
         this.clinicService = clinicService;
         this.hospitalService=hospitalService;
-        init(redisTemplate,hospitalId,hospitalService);
+        init(configStorageManager,hospitalId);
     }
 
-    private void init(RedisTemplate redisTemplate,String hospitalId,LocalBusHospitalService hospitalService){
-        BusHospitalEntity hospital = hospitalService.getById(hospitalId);
-        if(hospital==null){
-            throw new RuntimeException(String.format("医院{%s}不存在,获取医院脚本会话失败",hospitalId));
-        }
-        clusterConfigStorage=new ClusterConfigStorage(redisTemplate,hospitalId);
-        clusterConfigStorage.setConfig("info",hospital);
+    private void init(ConfigStorageManager configStorageManager, String hospitalId){
+        clusterConfigStorage = configStorageManager.getStorage(hospitalId);
     }
 
     /**
@@ -113,9 +106,9 @@ public class HisScriptSession {
      * @return BusClinicEntity
      */
     public  DeferredResult<R<BusClinicEntity>>  syncGetPatientInfo(String patientCode, long timeout, TimeUnit unit){
-//        if (!isOnline()) {
-//            throw new CustomException("医院不在线,拉取信息失败");
-//        }
+        if (!isOnline()) {
+            throw new CustomException("医院不在线,拉取信息失败");
+        }
         String messageId = IdWorker.getIdStr();
         DeferredResult<R<BusClinicEntity>> result = new DeferredResult<>(unit.toMillis(timeout));
         HisRequest request = HisRequest.builder()
@@ -124,7 +117,7 @@ public class HisScriptSession {
                 .sync(true)
                 .timeout(timeout)
                 .timeUnit(unit)
-                .result(result)
+                .result(Arrays.asList(result))
                 .timestamp(new Date())
                 .build();
         sendRequest(channelContext,request);
@@ -161,7 +154,7 @@ public class HisScriptSession {
                 .sync(true)
                 .timeout(timeout)
                 .timeUnit(unit)
-                .result(result)
+                .result(Arrays.asList(result))
                 .timestamp(new Date())
                 .build();
         result.onTimeout(()->{
@@ -253,11 +246,15 @@ 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"));
         executorService.schedule(()->{
             BusClinicEntity clinicEntity = clinicService.recentClinicByPatientCode("1", request.getPatientCode());
+            if(clinicEntity==null){
+                clinicEntity=new BusClinicEntity();
+            }
             List<BusClinicEntity> clinic = new ArrayList<>();
             HisResponse hisResponse = new HisResponse();
             hisResponse.setMessageId(request.getMessageId());
@@ -267,7 +264,34 @@ public class HisScriptSession {
             for (int i = 0; i < 5; i++) {
                 clinicEntity.setId(null);
                 clinicEntity.setMonitorType(true);
-                clinicEntity.setName("新的临床数据"+i);
+                clinicEntity.setPatientCode(request.getPatientCode());
+                clinicEntity.setPatientGender(SexEnum.MAN);
+                clinicEntity.setPatientAge(RandomUtil.randomInt(20,40));
+                clinicEntity.setPatientName("病人名称"+i);
+                clinicEntity.setSurgeryName("新的临床数据"+i);
+                clinicEntity.setSurgeryDoctor("手术医生"+i);
+                clinicEntity.setAnaDoctor("麻醉医生"+i);
+                clinicEntity.setConfigPerson("配置人员"+i);
+                clinicEntity.setAnaType("麻醉方式"+i);
+                clinicEntity.setStartTime(DateUtil.yesterday());
+                clinicEntity.setAnalType("镇痛方式"+i);
+                clinicEntity.setEntrust("医嘱"+i);
+                clinicEntity.setAsa("ASA"+i);
+                clinicEntity.setTenantId(this.getHospitalId());
+                FormulaDrugDomain formulaDrugDomain = new FormulaDrugDomain();
+                formulaDrugDomain.setName("镇痛配方"+i);
+
+                FormulaDrugDetailDomain detailDomain = new FormulaDrugDetailDomain();
+                detailDomain.setDose("1");
+                detailDomain.setUnit("ml");
+                detailDomain.setName("鸦胆子");
+                FormulaDrugDetailDomain detailDomain1 = new FormulaDrugDetailDomain();
+                detailDomain1.setDose("1");
+                detailDomain1.setUnit("ml");
+                detailDomain1.setName("利多卡因");
+                formulaDrugDomain.setDetail(Arrays.asList(detailDomain,detailDomain1));
+
+                clinicEntity.setFormula(formulaDrugDomain);
                 BusClinicEntity c = new BusClinicEntity();
                 BeanUtil.copyProperties(clinicEntity,c);
                 c.setStartTime(RandomUtil.randomDate(new Date(), DateField.HOUR_OF_DAY,-30,10));
@@ -298,22 +322,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()+"]")));
+                }
             }
         }
     }

+ 8 - 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,10 +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;
@@ -22,15 +23,15 @@ public class HisScriptSessionManager {
     private Map<String,HisScriptSession> sessionMap=new ConcurrentHashMap<>();
     private LocalBusClinicService clinicService;
     private ScriptManager scriptManager;
-    private RedisTemplate redisTemplate;
     private LocalBusHospitalService hospitalService;
+    private ClusterConfigStorageManager configStorageManager;
 
     @Autowired
-    public HisScriptSessionManager(LocalBusClinicService clinicService, ScriptManager scriptManager, RedisTemplate redisTemplate, LocalBusHospitalService hospitalService) {
+    public HisScriptSessionManager( LocalBusClinicService clinicService, ScriptManager scriptManager, LocalBusHospitalService hospitalService, ClusterConfigStorageManager configStorageManager) {
         this.clinicService = clinicService;
         this.scriptManager = scriptManager;
-        this.redisTemplate = redisTemplate;
         this.hospitalService = hospitalService;
+        this.configStorageManager = configStorageManager;
     }
 
     /**
@@ -52,7 +53,7 @@ public class HisScriptSessionManager {
      * @return HisScriptSession
      */
     public HisScriptSession register(String hospitalId){
-        return new HisScriptSession(hospitalId, scriptManager,redisTemplate, 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() {

+ 20 - 7
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;
@@ -27,10 +28,12 @@ public class PythonParse implements ScriptParse {
 //        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());
+////        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 +49,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 +86,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);
 }

+ 1 - 3
coffee-system/src/main/java/com/coffee/bus/registry/Operator.java

@@ -1,10 +1,8 @@
 package com.coffee.bus.registry;
 
-import cn.hutool.core.util.ObjectUtil;
+
 import com.coffee.common.cache.ConfigStorage;
 import com.coffee.common.cache.value.Value;
-import org.springframework.cache.support.SimpleValueWrapper;
-import org.springframework.util.CollectionUtils;
 import org.springframework.util.ReflectionUtils;
 
 import java.lang.reflect.Field;

+ 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();
     }
 

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor