소스 검색

Merge branch 'develop' into dev/prec20200120_homepage

gaodm 5 년 전
부모
커밋
fc04054e44
66개의 변경된 파일4572개의 추가작업 그리고 3개의 파일을 삭제
  1. 4 1
      aipt-service/src/main/java/com/diagbot/aggregate/PushItemAggregate.java
  2. 1 0
      aipt-service/src/main/java/com/diagbot/facade/PushFacade.java
  3. 2 1
      common/src/main/java/com/diagbot/enums/SysTypeEnum.java
  4. 7 0
      config-server/src/main/resources/shared/gateway-service-dev.yml
  5. 7 0
      config-server/src/main/resources/shared/gateway-service-local.yml
  6. 7 0
      config-server/src/main/resources/shared/gateway-service-pre.yml
  7. 7 0
      config-server/src/main/resources/shared/gateway-service-pro.yml
  8. 7 0
      config-server/src/main/resources/shared/gateway-service-test.yml
  9. 99 0
      config-server/src/main/resources/shared/mrqcman-service-dev.yml
  10. 99 0
      config-server/src/main/resources/shared/mrqcman-service-local.yml
  11. 99 0
      config-server/src/main/resources/shared/mrqcman-service-pre.yml
  12. 99 0
      config-server/src/main/resources/shared/mrqcman-service-pro.yml
  13. 99 0
      config-server/src/main/resources/shared/mrqcman-service-test.yml
  14. 2 0
      data-service/src/main/java/com/diagbot/facade/PushFacade.java
  15. 26 0
      docs/027.20191220病历质控维护/init_mrqc.sql
  16. 1016 0
      docs/027.20191220病历质控维护/sys_user.sql
  17. 1 0
      icss-service/src/main/java/com/diagbot/facade/PushFacade.java
  18. 2 1
      knowledgeman-service/src/main/java/com/diagbot/enums/RelationModelTypeEnum.java
  19. 2 0
      ltapi-service/src/main/java/com/diagbot/facade/PushFacade.java
  20. 223 0
      mrqcman-service/pom.xml
  21. 36 0
      mrqcman-service/src/main/java/com/diagbot/MrqcmanServiceApplication.java
  22. 41 0
      mrqcman-service/src/main/java/com/diagbot/aop/SysLoggerAspect.java
  23. 30 0
      mrqcman-service/src/main/java/com/diagbot/client/UserServiceClient.java
  24. 35 0
      mrqcman-service/src/main/java/com/diagbot/client/hystrix/UserServiceHystrix.java
  25. 19 0
      mrqcman-service/src/main/java/com/diagbot/config/CustomAccessTokenConverter.java
  26. 15 0
      mrqcman-service/src/main/java/com/diagbot/config/GlobalMethodSecurityConfigurer.java
  27. 48 0
      mrqcman-service/src/main/java/com/diagbot/config/JwtConfigurer.java
  28. 33 0
      mrqcman-service/src/main/java/com/diagbot/config/MybatisPlusConfigurer.java
  29. 43 0
      mrqcman-service/src/main/java/com/diagbot/config/ResourceServerConfigurer.java
  30. 70 0
      mrqcman-service/src/main/java/com/diagbot/config/SwaggerConfigurer.java
  31. 106 0
      mrqcman-service/src/main/java/com/diagbot/config/security/UrlAccessDecisionManager.java
  32. 29 0
      mrqcman-service/src/main/java/com/diagbot/config/security/UrlConfigAttribute.java
  33. 79 0
      mrqcman-service/src/main/java/com/diagbot/config/security/UrlFilterSecurityInterceptor.java
  34. 40 0
      mrqcman-service/src/main/java/com/diagbot/config/security/UrlMetadataSourceService.java
  35. 28 0
      mrqcman-service/src/main/java/com/diagbot/dto/FileDTO.java
  36. 17 0
      mrqcman-service/src/main/java/com/diagbot/dto/FileDeleteDTO.java
  37. 25 0
      mrqcman-service/src/main/java/com/diagbot/dto/FileUploadDTO.java
  38. 18 0
      mrqcman-service/src/main/java/com/diagbot/dto/TokenContentDTO.java
  39. 116 0
      mrqcman-service/src/main/java/com/diagbot/entity/MrqcToken.java
  40. 21 0
      mrqcman-service/src/main/java/com/diagbot/entity/Token.java
  41. 81 0
      mrqcman-service/src/main/java/com/diagbot/exception/CommonExceptionHandler.java
  42. 39 0
      mrqcman-service/src/main/java/com/diagbot/exception/ServiceErrorCode.java
  43. 198 0
      mrqcman-service/src/main/java/com/diagbot/facade/MrqcTokenFacade.java
  44. 19 0
      mrqcman-service/src/main/java/com/diagbot/mapper/MrqcTokenMapper.java
  45. 23 0
      mrqcman-service/src/main/java/com/diagbot/rabbit/MyProcessor.java
  46. 27 0
      mrqcman-service/src/main/java/com/diagbot/rabbit/MySender.java
  47. 19 0
      mrqcman-service/src/main/java/com/diagbot/service/MrqcTokenService.java
  48. 13 0
      mrqcman-service/src/main/java/com/diagbot/service/UploadService.java
  49. 26 0
      mrqcman-service/src/main/java/com/diagbot/service/impl/MrqcTokenServiceImpl.java
  50. 129 0
      mrqcman-service/src/main/java/com/diagbot/service/impl/UploadServiceImpl.java
  51. 173 0
      mrqcman-service/src/main/java/com/diagbot/util/RSAEncrypt.java
  52. 302 0
      mrqcman-service/src/main/java/com/diagbot/util/SerialNumberUtil.java
  53. 26 0
      mrqcman-service/src/main/java/com/diagbot/vo/DecryptVO.java
  54. 26 0
      mrqcman-service/src/main/java/com/diagbot/vo/MrqcTokenContentVO.java
  55. 31 0
      mrqcman-service/src/main/java/com/diagbot/vo/MrqcTokenDeleteVO.java
  56. 26 0
      mrqcman-service/src/main/java/com/diagbot/vo/MrqcTokenIndexVO.java
  57. 59 0
      mrqcman-service/src/main/java/com/diagbot/vo/MrqcTokenPageVO.java
  58. 94 0
      mrqcman-service/src/main/java/com/diagbot/vo/MrqcTokenVO.java
  59. 116 0
      mrqcman-service/src/main/java/com/diagbot/web/MrqcTokenController.java
  60. 19 0
      mrqcman-service/src/main/resources/bootstrap.yml
  61. 306 0
      mrqcman-service/src/main/resources/logback-spring.xml
  62. 53 0
      mrqcman-service/src/main/resources/mapper/MrqcTokenMapper.xml
  63. 9 0
      mrqcman-service/src/main/resources/public.cert
  64. 83 0
      mrqcman-service/src/test/java/com/diagbot/CodeGeneration.java
  65. 16 0
      mrqcman-service/src/test/java/com/diagbot/MrqcmanServiceApplicationTests.java
  66. 1 0
      pom.xml

+ 4 - 1
aipt-service/src/main/java/com/diagbot/aggregate/PushItemAggregate.java

@@ -57,6 +57,7 @@ public class PushItemAggregate {
 
     @DataProvider("setAll")
     public PushDTO setAll(
+            @InvokeParameter("pushDTO") PushDTO pushDTO,
             @DataConsumer("getDept") ConceptPushDTO dept,
             @DataConsumer("setSymptom") List<ConceptPushDTO> symptom,
             @DataConsumer("setVital") List<ConceptPushDTO> vital,
@@ -64,7 +65,9 @@ public class PushItemAggregate {
             @DataConsumer("setRetPacs") List<ConceptPushDTO> pacs,
             @DataConsumer("setDis") Map<String, List<ConceptPushDTO>> dis,
             @DataConsumer("setMedicalIndications") List<MedicalIndication> medicalIndications) {
-        PushDTO pushDTO = new PushDTO();
+        if (pushDTO == null) {
+            pushDTO = new PushDTO();
+        }
         if (null != dept) {
             pushDTO.setDept(dept);
         }

+ 1 - 0
aipt-service/src/main/java/com/diagbot/facade/PushFacade.java

@@ -60,6 +60,7 @@ public class PushFacade {
 
         try {
             Map<String, Object> invokeParams = new HashMap<>();
+            invokeParams.put("pushDTO",pushDTO);
             invokeParams.put("featureTypeSet", featureTypeSet);
             invokeParams.put("data", data);
             invokeParams.put("isConnect", isConnect);

+ 2 - 1
common/src/main/java/com/diagbot/enums/SysTypeEnum.java

@@ -28,7 +28,8 @@ public enum SysTypeEnum implements KeyedNamed {
     AIPT_SERVICE(15, "aipt-service"),
     DATA_SERVICE(16, "data-service"),
     PREC_SERVICE(17, "prec-service"),
-    PRECMAN_SERVICE(18, "precman-service");
+    PRECMAN_SERVICE(18, "precman-service"),
+    MRQCMAN_SERVICE(19, "mrqcman-service");
 
     @Setter
     private int key;

+ 7 - 0
config-server/src/main/resources/shared/gateway-service-dev.yml

@@ -121,6 +121,13 @@ spring:
         filters:
 #        - SwaggerHeaderFilter
         - StripPrefix=2
+      - id: mrqcman-service
+        uri: lb://mrqcman-service
+        predicates:
+        - Path=/api/mrqcman/**
+        filters:
+        #        - SwaggerHeaderFilter
+        - StripPrefix=2
 
 server:
   port: 5050

+ 7 - 0
config-server/src/main/resources/shared/gateway-service-local.yml

@@ -125,6 +125,13 @@ spring:
         filters:
 #        - SwaggerHeaderFilter
         - StripPrefix=2
+      - id: mrqcman-service
+        uri: lb://mrqcman-service
+        predicates:
+        - Path=/api/mrqcman/**
+        filters:
+        #        - SwaggerHeaderFilter
+        - StripPrefix=2
 
 server:
   port: 5050

+ 7 - 0
config-server/src/main/resources/shared/gateway-service-pre.yml

@@ -128,6 +128,13 @@ spring:
         filters:
         #        - SwaggerHeaderFilter
         - StripPrefix=2
+      - id: mrqcman-service
+        uri: lb://mrqcman-service
+        predicates:
+        - Path=/api/mrqcman/**
+        filters:
+        #        - SwaggerHeaderFilter
+        - StripPrefix=2
 
 server:
   port: 5050

+ 7 - 0
config-server/src/main/resources/shared/gateway-service-pro.yml

@@ -121,6 +121,13 @@ spring:
         filters:
         #        - SwaggerHeaderFilter
         - StripPrefix=2
+      - id: mrqcman-service
+        uri: lb://mrqcman-service
+        predicates:
+        - Path=/api/mrqcman/**
+        filters:
+        #        - SwaggerHeaderFilter
+        - StripPrefix=2
 
 server:
   port: 5050

+ 7 - 0
config-server/src/main/resources/shared/gateway-service-test.yml

@@ -128,6 +128,13 @@ spring:
         filters:
 #        - SwaggerHeaderFilter
         - StripPrefix=2
+      - id: mrqcman-service
+        uri: lb://mrqcman-service
+        predicates:
+        - Path=/api/mrqcman/**
+        filters:
+        #        - SwaggerHeaderFilter
+        - StripPrefix=2
 
 server:
   port: 5050

+ 99 - 0
config-server/src/main/resources/shared/mrqcman-service-dev.yml

@@ -0,0 +1,99 @@
+server:
+  port: 8832
+
+# 驱动配置信息
+spring:
+  datasource:
+    druid:
+      driver-class-name: com.mysql.cj.jdbc.Driver
+      platform: mysql
+      url: jdbc:mysql://192.168.2.236:3306/sys-mrqc?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&useSSL=false
+      username: root
+      password: lantone
+      # 连接池的配置信息
+      # 初始化大小,最小,最大
+      initialSize: 5
+      minIdle: 5
+      maxActive: 20
+      # 配置获取连接等待超时的时间
+      maxWait: 60000
+      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+      timeBetweenEvictionRunsMillis: 60000
+      # 配置一个连接在池中最小生存的时间,单位是毫秒
+      minEvictableIdleTimeMillis: 300000
+      validationQuery: SELECT 1 FROM DUAL
+      testWhileIdle: true
+      testOnBorrow: false
+      testOnReturn: false
+      # 打开PSCache,并且指定每个连接上PSCache的大小
+      poolPreparedStatements: true
+      maxPoolPreparedStatementPerConnectionSize: 20
+      # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
+      filters.commons-log.connection-logger-name: wall,log4j
+      filter:
+        stat:
+          enabled: true
+          mergeSql: true
+          log-slow-sql: true
+          slow-sql-millis: 2000
+      #监控配置
+      web-stat-filter:
+        enabled: true
+        url-pattern: /*
+        exclusions: '*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*'
+
+      # StatViewServlet配置,说明请参考Druid Wiki,配置_StatViewServlet配置
+      stat-view-servlet:
+        enabled: true
+        url-pattern: /druid/*
+        reset-enable: false
+        login-username: root
+        login-password: root
+
+  cloud:
+    stream:
+      bindings:
+        outputLog:
+          destination: myLog
+  #          contentType: text/plain      # 实体 json string 在传递的类型装换 查看 http://docs.spring
+
+  #mq
+  rabbitmq:
+    host: 192.168.2.236
+    port: 5672
+    username: lantone
+    password: lantone
+    publisher-confirms: true
+    virtual-host: /
+
+#mybatis
+mybatis-plus:
+  mapper-locations: classpath:/mapper/*Mapper.xml
+  #实体扫描,多个package用逗号或者分号分隔
+  typeAliasesPackage: com.diagbot.entity
+  global-config:
+    #刷新mapper 调试神器
+    db-config:
+      #主键类型  0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID";
+      id-type: id_worker
+      #字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断"
+      field-strategy: not_empty
+      #驼峰下划线转换
+      column-underline: true
+      #数据库大写下划线转换
+      #capital-mode: true
+      #刷新mapper 调试神器
+      refresh-mapper: true
+      #逻辑删除配置
+      logic-delete-value: 0
+      logic-not-delete-value: 1
+      #自定义填充策略接口实现
+      #meta-object-handler: com.baomidou.springboot.xxx
+      #自定义SQL注入器
+      #sql-injector: com.baomidou.springboot.xxx
+  configuration:
+    map-underscore-to-camel-case: true
+    cache-enabled: false
+
+imageUrl:
+  prefix: http://192.168.2.236:82

+ 99 - 0
config-server/src/main/resources/shared/mrqcman-service-local.yml

@@ -0,0 +1,99 @@
+server:
+  port: 8832
+
+# 驱动配置信息
+spring:
+  datasource:
+    druid:
+      driver-class-name: com.mysql.cj.jdbc.Driver
+      platform: mysql
+      url: jdbc:mysql://192.168.2.236:3306/sys-mrqc?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&useSSL=false
+      username: root
+      password: lantone
+      # 连接池的配置信息
+      # 初始化大小,最小,最大
+      initialSize: 5
+      minIdle: 5
+      maxActive: 20
+      # 配置获取连接等待超时的时间
+      maxWait: 60000
+      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+      timeBetweenEvictionRunsMillis: 60000
+      # 配置一个连接在池中最小生存的时间,单位是毫秒
+      minEvictableIdleTimeMillis: 300000
+      validationQuery: SELECT 1 FROM DUAL
+      testWhileIdle: true
+      testOnBorrow: false
+      testOnReturn: false
+      # 打开PSCache,并且指定每个连接上PSCache的大小
+      poolPreparedStatements: true
+      maxPoolPreparedStatementPerConnectionSize: 20
+      # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
+      filters.commons-log.connection-logger-name: wall,log4j
+      filter:
+        stat:
+          enabled: true
+          mergeSql: true
+          log-slow-sql: true
+          slow-sql-millis: 2000
+      #监控配置
+      web-stat-filter:
+        enabled: true
+        url-pattern: /*
+        exclusions: '*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*'
+
+      # StatViewServlet配置,说明请参考Druid Wiki,配置_StatViewServlet配置
+      stat-view-servlet:
+        enabled: true
+        url-pattern: /druid/*
+        reset-enable: false
+        login-username: root
+        login-password: root
+
+  cloud:
+    stream:
+      bindings:
+        outputLog:
+          destination: myLog
+  #          contentType: text/plain      # 实体 json string 在传递的类型装换 查看 http://docs.spring
+
+  #mq
+  rabbitmq:
+    host: localhost
+    port: 5672
+    username: guest
+    password: guest
+    publisher-confirms: true
+    virtual-host: /
+
+#mybatis
+mybatis-plus:
+  mapper-locations: classpath:/mapper/*Mapper.xml
+  #实体扫描,多个package用逗号或者分号分隔
+  typeAliasesPackage: com.diagbot.entity
+  global-config:
+    #刷新mapper 调试神器
+    db-config:
+      #主键类型  0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID";
+      id-type: id_worker
+      #字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断"
+      field-strategy: not_empty
+      #驼峰下划线转换
+      column-underline: true
+      #数据库大写下划线转换
+      #capital-mode: true
+      #刷新mapper 调试神器
+      refresh-mapper: true
+      #逻辑删除配置
+      logic-delete-value: 0
+      logic-not-delete-value: 1
+      #自定义填充策略接口实现
+      #meta-object-handler: com.baomidou.springboot.xxx
+      #自定义SQL注入器
+      #sql-injector: com.baomidou.springboot.xxx
+  configuration:
+    map-underscore-to-camel-case: true
+    cache-enabled: false
+
+imageUrl:
+  prefix: http://192.168.2.236:82

+ 99 - 0
config-server/src/main/resources/shared/mrqcman-service-pre.yml

@@ -0,0 +1,99 @@
+server:
+  port: 8832
+
+# 驱动配置信息
+spring:
+  datasource:
+    druid:
+      driver-class-name: com.mysql.cj.jdbc.Driver
+      platform: mysql
+      url: jdbc:mysql://192.168.2.121:3306/sys-mrqc?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&useSSL=false
+      username: teamback
+      password: goTulmLeon
+      # 连接池的配置信息
+      # 初始化大小,最小,最大
+      initialSize: 5
+      minIdle: 5
+      maxActive: 20
+      # 配置获取连接等待超时的时间
+      maxWait: 60000
+      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+      timeBetweenEvictionRunsMillis: 60000
+      # 配置一个连接在池中最小生存的时间,单位是毫秒
+      minEvictableIdleTimeMillis: 300000
+      validationQuery: SELECT 1 FROM DUAL
+      testWhileIdle: true
+      testOnBorrow: false
+      testOnReturn: false
+      # 打开PSCache,并且指定每个连接上PSCache的大小
+      poolPreparedStatements: true
+      maxPoolPreparedStatementPerConnectionSize: 20
+      # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
+      filters.commons-log.connection-logger-name: wall,log4j
+      filter:
+        stat:
+          enabled: true
+          mergeSql: true
+          log-slow-sql: true
+          slow-sql-millis: 2000
+      #监控配置
+      web-stat-filter:
+        enabled: true
+        url-pattern: /*
+        exclusions: '*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*'
+
+      # StatViewServlet配置,说明请参考Druid Wiki,配置_StatViewServlet配置
+      stat-view-servlet:
+        enabled: true
+        url-pattern: /druid/*
+        reset-enable: false
+        login-username: root
+        login-password: root
+
+  cloud:
+    stream:
+      bindings:
+        outputLog:
+          destination: myLog
+  #          contentType: text/plain      # 实体 json string 在传递的类型装换 查看 http://docs.spring
+
+  #mq
+  rabbitmq:
+    host: 192.168.2.121
+    port: 5672
+    username: lantone
+    password: lantone
+    publisher-confirms: true
+    virtual-host: /
+
+#mybatis
+mybatis-plus:
+  mapper-locations: classpath:/mapper/*Mapper.xml
+  #实体扫描,多个package用逗号或者分号分隔
+  typeAliasesPackage: com.diagbot.entity
+  global-config:
+    #刷新mapper 调试神器
+    db-config:
+      #主键类型  0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID";
+      id-type: id_worker
+      #字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断"
+      field-strategy: not_empty
+      #驼峰下划线转换
+      column-underline: true
+      #数据库大写下划线转换
+      #capital-mode: true
+      #刷新mapper 调试神器
+      refresh-mapper: true
+      #逻辑删除配置
+      logic-delete-value: 0
+      logic-not-delete-value: 1
+      #自定义填充策略接口实现
+      #meta-object-handler: com.baomidou.springboot.xxx
+      #自定义SQL注入器
+      #sql-injector: com.baomidou.springboot.xxx
+  configuration:
+    map-underscore-to-camel-case: true
+    cache-enabled: false
+
+imageUrl:
+  prefix: http://192.168.2.121:82

+ 99 - 0
config-server/src/main/resources/shared/mrqcman-service-pro.yml

@@ -0,0 +1,99 @@
+server:
+  port: 8832
+
+# 驱动配置信息
+spring:
+  datasource:
+    druid:
+      driver-class-name: com.mysql.cj.jdbc.Driver
+      platform: mysql
+      url: jdbc:mysql://192.168.2.122:3306/sys-mrqc?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&useSSL=false
+      username: root
+      password: lantone
+      # 连接池的配置信息
+      # 初始化大小,最小,最大
+      initialSize: 5
+      minIdle: 5
+      maxActive: 20
+      # 配置获取连接等待超时的时间
+      maxWait: 60000
+      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+      timeBetweenEvictionRunsMillis: 60000
+      # 配置一个连接在池中最小生存的时间,单位是毫秒
+      minEvictableIdleTimeMillis: 300000
+      validationQuery: SELECT 1 FROM DUAL
+      testWhileIdle: true
+      testOnBorrow: false
+      testOnReturn: false
+      # 打开PSCache,并且指定每个连接上PSCache的大小
+      poolPreparedStatements: true
+      maxPoolPreparedStatementPerConnectionSize: 20
+      # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
+      filters.commons-log.connection-logger-name: wall,log4j
+      filter:
+        stat:
+          enabled: true
+          mergeSql: true
+          log-slow-sql: true
+          slow-sql-millis: 2000
+      #监控配置
+      web-stat-filter:
+        enabled: true
+        url-pattern: /*
+        exclusions: '*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*'
+
+      # StatViewServlet配置,说明请参考Druid Wiki,配置_StatViewServlet配置
+      stat-view-servlet:
+        enabled: true
+        url-pattern: /druid/*
+        reset-enable: false
+        login-username: root
+        login-password: root
+
+  cloud:
+    stream:
+      bindings:
+        outputLog:
+          destination: myLog
+  #          contentType: text/plain      # 实体 json string 在传递的类型装换 查看 http://docs.spring
+
+  #mq
+  rabbitmq:
+    host: 192.168.2.122
+    port: 5672
+    username: lantone
+    password: lantone
+    publisher-confirms: true
+    virtual-host: /
+
+#mybatis
+mybatis-plus:
+  mapper-locations: classpath:/mapper/*Mapper.xml
+  #实体扫描,多个package用逗号或者分号分隔
+  typeAliasesPackage: com.diagbot.entity
+  global-config:
+    #刷新mapper 调试神器
+    db-config:
+      #主键类型  0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID";
+      id-type: id_worker
+      #字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断"
+      field-strategy: not_empty
+      #驼峰下划线转换
+      column-underline: true
+      #数据库大写下划线转换
+      #capital-mode: true
+      #刷新mapper 调试神器
+      refresh-mapper: true
+      #逻辑删除配置
+      logic-delete-value: 0
+      logic-not-delete-value: 1
+      #自定义填充策略接口实现
+      #meta-object-handler: com.baomidou.springboot.xxx
+      #自定义SQL注入器
+      #sql-injector: com.baomidou.springboot.xxx
+  configuration:
+    map-underscore-to-camel-case: true
+    cache-enabled: false
+
+imageUrl:
+  prefix: http://192.168.2.122:82

+ 99 - 0
config-server/src/main/resources/shared/mrqcman-service-test.yml

@@ -0,0 +1,99 @@
+server:
+  port: 8832
+
+# 驱动配置信息
+spring:
+  datasource:
+    druid:
+      driver-class-name: com.mysql.cj.jdbc.Driver
+      platform: mysql
+      url: jdbc:mysql://192.168.2.241:3306/sys-mrqc?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&useSSL=false
+      username: root
+      password: lantone
+      # 连接池的配置信息
+      # 初始化大小,最小,最大
+      initialSize: 5
+      minIdle: 5
+      maxActive: 20
+      # 配置获取连接等待超时的时间
+      maxWait: 60000
+      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+      timeBetweenEvictionRunsMillis: 60000
+      # 配置一个连接在池中最小生存的时间,单位是毫秒
+      minEvictableIdleTimeMillis: 300000
+      validationQuery: SELECT 1 FROM DUAL
+      testWhileIdle: true
+      testOnBorrow: false
+      testOnReturn: false
+      # 打开PSCache,并且指定每个连接上PSCache的大小
+      poolPreparedStatements: true
+      maxPoolPreparedStatementPerConnectionSize: 20
+      # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
+      filters.commons-log.connection-logger-name: wall,log4j
+      filter:
+        stat:
+          enabled: true
+          mergeSql: true
+          log-slow-sql: true
+          slow-sql-millis: 2000
+      #监控配置
+      web-stat-filter:
+        enabled: true
+        url-pattern: /*
+        exclusions: '*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*'
+
+      # StatViewServlet配置,说明请参考Druid Wiki,配置_StatViewServlet配置
+      stat-view-servlet:
+        enabled: true
+        url-pattern: /druid/*
+        reset-enable: false
+        login-username: root
+        login-password: root
+
+  cloud:
+    stream:
+      bindings:
+        outputLog:
+          destination: myLog
+  #          contentType: text/plain      # 实体 json string 在传递的类型装换 查看 http://docs.spring
+
+  #mq
+  rabbitmq:
+    host: 192.168.2.241
+    port: 5672
+    username: lantone
+    password: lantone
+    publisher-confirms: true
+    virtual-host: /
+
+#mybatis
+mybatis-plus:
+  mapper-locations: classpath:/mapper/*Mapper.xml
+  #实体扫描,多个package用逗号或者分号分隔
+  typeAliasesPackage: com.diagbot.entity
+  global-config:
+    #刷新mapper 调试神器
+    db-config:
+      #主键类型  0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID";
+      id-type: id_worker
+      #字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断"
+      field-strategy: not_empty
+      #驼峰下划线转换
+      column-underline: true
+      #数据库大写下划线转换
+      #capital-mode: true
+      #刷新mapper 调试神器
+      refresh-mapper: true
+      #逻辑删除配置
+      logic-delete-value: 0
+      logic-not-delete-value: 1
+      #自定义填充策略接口实现
+      #meta-object-handler: com.baomidou.springboot.xxx
+      #自定义SQL注入器
+      #sql-injector: com.baomidou.springboot.xxx
+  configuration:
+    map-underscore-to-camel-case: true
+    cache-enabled: false
+
+imageUrl:
+  prefix: http://192.168.2.241:82

+ 2 - 0
data-service/src/main/java/com/diagbot/facade/PushFacade.java

@@ -46,6 +46,8 @@ public class PushFacade {
         String[] featureTypes = featureType.split(",|,");
         Set<String> featureTypeSet = new HashSet(Arrays.asList(featureTypes));
 
+        pushDTO.setHasIndications(data.getHasIndications());
+
         //症状
         if (featureTypeSet.contains(String.valueOf(FeatureTypeEnum.Feature_Type_Symptom.getKey()))) {
             List<ConceptPushDTO> symptom = data.getSymptom();

+ 26 - 0
docs/027.20191220病历质控维护/init_mrqc.sql

@@ -0,0 +1,26 @@
+CREATE DATABASE  `sys-mrqc` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
+
+use `sys-mrqc`;
+
+DROP TABLE IF EXISTS `mrqc_token`;
+CREATE TABLE `mrqc_token` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
+  `is_deleted` char(1)  NOT NULL DEFAULT 'N' COMMENT '是否删除,N:未删除,Y:删除',
+  `gmt_create` datetime NOT NULL DEFAULT '1970-01-01 12:00:00' COMMENT '记录创建时间',
+  `gmt_modified` datetime NOT NULL DEFAULT '1970-01-01 12:00:00' COMMENT '记录修改时间,如果时间是1970年则表示纪录未修改',
+  `creator` varchar(20)  NOT NULL DEFAULT '' COMMENT '创建人姓名',
+  `modifier` varchar(20)  NOT NULL DEFAULT '' COMMENT '修改人姓名',
+  `server` varchar(255)  NOT NULL DEFAULT '' COMMENT '服务商',
+  `hospital` varchar(255)  NOT NULL DEFAULT '' COMMENT '医院',
+  `cpu` varchar(255)  NOT NULL DEFAULT '' COMMENT 'cpu',
+  `mainboard` varchar(255)  NOT NULL DEFAULT '' COMMENT '主板信息',
+  `disk` varchar(255)  NOT NULL DEFAULT '' COMMENT '硬盘信息',
+  `ip` varchar(255)  NOT NULL DEFAULT '' COMMENT 'ip',
+  `remain_day` int  NOT NULL DEFAULT 0 COMMENT '剩余使用天数',
+  `valid_time` int  NOT NULL DEFAULT 0 COMMENT '有效时间(分钟)',
+  `login_key` varchar(255)  NOT NULL DEFAULT '' COMMENT '登录key',
+  `url` varchar(255)  NOT NULL DEFAULT '' COMMENT '文件路径',
+  `content` text  COMMENT '拷贝内容',
+  `remark` varchar(255)  NOT NULL DEFAULT '' COMMENT '备注',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8  COMMENT='病历质控token信息';

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1016 - 0
docs/027.20191220病历质控维护/sys_user.sql


+ 1 - 0
icss-service/src/main/java/com/diagbot/facade/PushFacade.java

@@ -62,6 +62,7 @@ public class PushFacade {
 
         //推理结果返回科室
         pushDTO.setDept(data.getDept());
+        pushDTO.setHasIndications(data.getHasIndications());
 
         try {
             Map<String, Object> invokeParams = new HashMap<>();

+ 2 - 1
knowledgeman-service/src/main/java/com/diagbot/enums/RelationModelTypeEnum.java

@@ -12,7 +12,8 @@ public enum RelationModelTypeEnum implements KeyedNamed {
     KSCY(471011, "科室常用"),
     HYCY(4710112, "化验常用"),
     FJCY(4710116, "辅检常用"),
-    ZDGLLB(1810148, "诊断关联量表");
+    ZDGLLB(1810148, "诊断关联量表"),
+    ZDGLZZ(181011, "诊断关联症状");
 
     @Setter
     private int key;

+ 2 - 0
ltapi-service/src/main/java/com/diagbot/facade/PushFacade.java

@@ -46,6 +46,8 @@ public class PushFacade {
         String[] featureTypes = featureType.split(",|,");
         Set<String> featureTypeSet = new HashSet(Arrays.asList(featureTypes));
 
+        pushDTO.setHasIndications(data.getHasIndications());
+
         //症状
         if (featureTypeSet.contains(String.valueOf(FeatureTypeEnum.Feature_Type_Symptom.getKey()))) {
             List<ConceptPushDTO> symptom = data.getSymptom();

+ 223 - 0
mrqcman-service/pom.xml

@@ -0,0 +1,223 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>com.diagbot</groupId>
+    <artifactId>mrqcman-service</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <packaging>jar</packaging>
+
+    <name>mrqcman-service</name>
+    <description>mrqcman service for Spring Boot</description>
+
+    <parent>
+        <groupId>com.diagbot</groupId>
+        <artifactId>diagbotcloud</artifactId>
+        <version>0.0.1-SNAPSHOT</version>
+    </parent>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.diagbot</groupId>
+            <artifactId>common</artifactId>
+            <version>0.0.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
+        </dependency>
+
+        <!-- 配置-->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-config</artifactId>
+        </dependency>
+
+        <!-- 开启web-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-tomcat</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-undertow</artifactId>
+        </dependency>
+
+        <!-- 开启feign-->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+        </dependency>
+
+        <!-- dashboard -->
+        <!-- actuator-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-actuator</artifactId>
+        </dependency>
+        <!--hystrix-dashboard-->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
+        </dependency>
+        <!--hystrix -->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
+        </dependency>
+
+        <!-- zipkin-->
+        <!--<dependency>-->
+            <!--<groupId>org.springframework.cloud</groupId>-->
+            <!--<artifactId>spring-cloud-starter-zipkin</artifactId>-->
+        <!--</dependency>-->
+
+        <!--swagger-->
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger-ui</artifactId>
+        </dependency>
+        <!--database-->
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+        <!--security-->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-oauth2</artifactId>
+        </dependency>
+
+        <!-- mq -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-amqp</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>net.logstash.logback</groupId>
+            <artifactId>logstash-logback-encoder</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
+        </dependency>
+
+        <!-- mybatis-plus begin -->
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-generator</artifactId>
+        </dependency>
+        <!-- mybatis-plus end -->
+
+        <!-- 阿里巴巴druid数据库连接池 -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid-spring-boot-starter</artifactId>
+        </dependency>
+
+        <!-- springboot整合mybatis(核心就这一个) -->
+        <!-- 注意顺序,这个一定要放在最下面 -->
+        <dependency>
+            <groupId>org.mybatis.spring.boot</groupId>
+            <artifactId>mybatis-spring-boot-starter</artifactId>
+            <version>${mybatis-spring-boot.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
+        </dependency>
+
+        <!-- 文件上传相关架包 -->
+        <dependency>
+            <groupId>commons-fileupload</groupId>
+            <artifactId>commons-fileupload</artifactId>
+            <version>1.3.1</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>2.4</version>
+        </dependency>
+
+        <!--POI-->
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.squareup.okhttp3</groupId>
+            <artifactId>okhttp</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-test</artifactId>
+            <version>5.1.9.RELEASE</version>
+            <scope>compile</scope>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+            <!-- 添加docker-maven插件 -->
+            <plugin>
+                <groupId>com.spotify</groupId>
+                <artifactId>docker-maven-plugin</artifactId>
+                <configuration>
+                    <imageName>${docker.image.prefix}/${project.artifactId}:${project.version}</imageName>
+                    <forceTags>true</forceTags>
+                    <!--镜像的FROM,使用压缩的小镜像-->
+                    <baseImage>frolvlad/alpine-oraclejre8:slim</baseImage>
+                    <entryPoint>["java", "-jar", "-Xms256m", "-Xmx1024m", "-Duser.timezone=GMT+8", "/${project.build.finalName}.jar"]</entryPoint>
+                    <resources>
+                        <resource>
+                            <targetPath>/</targetPath>
+                            <directory>${project.build.directory}</directory>
+                            <include>${project.build.finalName}.jar</include>
+                        </resource>
+                    </resources>
+                    <serverId>docker-registry</serverId>
+                    <registryUrl>${registryUrl}</registryUrl>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 36 - 0
mrqcman-service/src/main/java/com/diagbot/MrqcmanServiceApplication.java

@@ -0,0 +1,36 @@
+package com.diagbot;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
+import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
+import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration;
+import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
+import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
+import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
+import org.springframework.cloud.netflix.hystrix.EnableHystrix;
+import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+
+/**
+ * @Description: 病历质控启动文件
+ * @author: gaodm
+ * @time: 2018/8/7 9:26
+ */
+@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
+        JmxAutoConfiguration.class, ThymeleafAutoConfiguration.class })
+@EnableEurekaClient
+@EnableFeignClients({ "com.diagbot.client" })
+@EnableHystrixDashboard
+@EnableHystrix
+@EnableCircuitBreaker
+@RefreshScope
+@ConfigurationPropertiesScan
+public class MrqcmanServiceApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(MrqcmanServiceApplication.class, args);
+    }
+}

+ 41 - 0
mrqcman-service/src/main/java/com/diagbot/aop/SysLoggerAspect.java

@@ -0,0 +1,41 @@
+package com.diagbot.aop;
+
+import com.diagbot.biz.log.entity.SysLog;
+import com.diagbot.enums.SysTypeEnum;
+import com.diagbot.rabbit.MySender;
+import com.diagbot.util.AopUtil;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.stereotype.Component;
+
+/**
+ * @Description: 日志拦截切面
+ * @author: gaodm
+ * @time: 2018/8/2 13:36
+ */
+@Aspect
+@Component
+@ConditionalOnProperty(prefix = "syslog", value = { "enable" }, havingValue = "true")
+public class SysLoggerAspect {
+    @Autowired
+    private MySender mySender;
+
+    @Pointcut("@annotation(com.diagbot.annotation.SysLogger)")
+    public void loggerPointCut() {
+
+    }
+
+    @Before("loggerPointCut()")
+    public void saveSysLog(JoinPoint joinPoint) {
+        //入参设置
+        SysLog sysLog = AopUtil.sysLoggerAspect(joinPoint, SysTypeEnum.MRQCMAN_SERVICE.getKey());
+        //保存系统日志
+        mySender.outputLogSend(sysLog);
+    }
+
+}
+

+ 30 - 0
mrqcman-service/src/main/java/com/diagbot/client/UserServiceClient.java

@@ -0,0 +1,30 @@
+package com.diagbot.client;
+
+import com.diagbot.client.hystrix.UserServiceHystrix;
+import com.diagbot.dto.RespDTO;
+import com.diagbot.entity.Token;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * @Description: 调用用户服务
+ * @author: gaodm
+ * @time: 2018/8/6 9:52
+ */
+@FeignClient(value = "user-service", fallback = UserServiceHystrix.class)
+public interface UserServiceClient {
+
+    @PostMapping(value = "/user/getUserInfoByIds")
+    RespDTO<Map<String, String>> getUserInfoByIds(@RequestBody List<String> ids);
+
+    @PostMapping("/user/verifyToken")
+    RespDTO<Boolean> verifyToken(@RequestBody Token token);
+}
+
+
+

+ 35 - 0
mrqcman-service/src/main/java/com/diagbot/client/hystrix/UserServiceHystrix.java

@@ -0,0 +1,35 @@
+package com.diagbot.client.hystrix;
+
+import com.diagbot.client.UserServiceClient;
+import com.diagbot.dto.RespDTO;
+import com.diagbot.entity.Token;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * @Description: 调用用户服务
+ * @author: gaodm
+ * @time: 2018/8/6 9:52
+ */
+@Component
+@Slf4j
+public class UserServiceHystrix implements UserServiceClient {
+
+    @Override
+    public RespDTO<Map<String, String>> getUserInfoByIds(@RequestBody List<String> ids) {
+        log.error("【hystrix】调用{}异常", "getUserInfoByIds");
+        return null;
+    }
+
+    @Override
+    public RespDTO<Boolean> verifyToken(Token token) {
+        log.error("【hystrix】调用{}异常", "verifyToken");
+        return null;
+    }
+
+}

+ 19 - 0
mrqcman-service/src/main/java/com/diagbot/config/CustomAccessTokenConverter.java

@@ -0,0 +1,19 @@
+package com.diagbot.config;
+
+import org.springframework.security.oauth2.provider.OAuth2Authentication;
+import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+@Component
+public class CustomAccessTokenConverter extends DefaultAccessTokenConverter {
+
+    @Override
+    public OAuth2Authentication extractAuthentication(Map<String, ?> claims) {
+        OAuth2Authentication authentication = super.extractAuthentication(claims);
+        authentication.setDetails(claims);
+        return authentication;
+    }
+
+}

+ 15 - 0
mrqcman-service/src/main/java/com/diagbot/config/GlobalMethodSecurityConfigurer.java

@@ -0,0 +1,15 @@
+package com.diagbot.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+
+/**
+ * @Description: 安全配置类
+ * @author: gaodm
+ * @time: 2018/8/2 13:38
+ */
+@Configuration
+@EnableGlobalMethodSecurity(prePostEnabled = true)
+public class GlobalMethodSecurityConfigurer {
+
+}

+ 48 - 0
mrqcman-service/src/main/java/com/diagbot/config/JwtConfigurer.java

@@ -0,0 +1,48 @@
+package com.diagbot.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.security.oauth2.provider.token.TokenStore;
+import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
+import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
+import org.springframework.util.FileCopyUtils;
+
+import java.io.IOException;
+
+/**
+ * @Description: JWT配置类
+ * @author: gaodm
+ * @time: 2018/8/2 13:38
+ */
+@Configuration
+public class JwtConfigurer {
+    @Autowired
+    private CustomAccessTokenConverter customAccessTokenConverter;
+
+    @Bean
+    @Qualifier("tokenStore")
+    public TokenStore tokenStore() {
+
+        System.out.println("Created JwtTokenStore");
+        return new JwtTokenStore(jwtTokenEnhancer());
+    }
+
+    @Bean
+    protected JwtAccessTokenConverter jwtTokenEnhancer() {
+        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
+        Resource resource = new ClassPathResource("public.cert");
+        String publicKey;
+        try {
+            publicKey = new String(FileCopyUtils.copyToByteArray(resource.getInputStream()));
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        converter.setVerifierKey(publicKey);
+        converter.setAccessTokenConverter(customAccessTokenConverter);
+        return converter;
+    }
+}

+ 33 - 0
mrqcman-service/src/main/java/com/diagbot/config/MybatisPlusConfigurer.java

@@ -0,0 +1,33 @@
+package com.diagbot.config;
+
+import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+/**
+ * @Description: MybatisPlus配置类
+ * @author: gaodm
+ * @time: 2018/8/2 13:39
+ */
+@EnableTransactionManagement
+@Configuration
+@MapperScan("com.diagbot.mapper*")//这个注解,作用相当于下面的@Bean MapperScannerConfigurer,2者配置1份即可
+public class MybatisPlusConfigurer {
+
+    /**
+     * mybatis-plus分页插件<br>
+     * 文档:http://mp.baomidou.com<br>
+     */
+    @Bean
+    public PaginationInterceptor paginationInterceptor() {
+        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
+        // 设置请求的页面大于最大页后操作,true调回到首页,false继续请求,默认false
+        //paginationInterceptor.setOverflow(false);
+        // 设置最大单页限制数量,默认500条,-1不受限制
+        paginationInterceptor.setLimit(500L);
+        return paginationInterceptor;
+    }
+
+}

+ 43 - 0
mrqcman-service/src/main/java/com/diagbot/config/ResourceServerConfigurer.java

@@ -0,0 +1,43 @@
+package com.diagbot.config;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
+import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
+import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
+import org.springframework.security.oauth2.provider.token.TokenStore;
+
+/**
+ * @Description: 权限资源配置类
+ * @author: gaodm
+ * @time: 2018/8/2 14:21
+ */
+@Configuration
+@EnableResourceServer
+public class ResourceServerConfigurer extends ResourceServerConfigurerAdapter {
+    Logger log = LoggerFactory.getLogger(ResourceServerConfigurer.class);
+
+    @Override
+    public void configure(HttpSecurity http) throws Exception {
+        http
+                .csrf().disable()
+                .authorizeRequests()
+                .regexMatchers(".*swagger.*", ".*v2.*", ".*webjars.*", "/druid.*", "/actuator.*", "/hystrix.*").permitAll()
+                .antMatchers("/mrqcToken/decrypt").permitAll()
+                .antMatchers("/**").authenticated();
+//                .antMatchers("/**").permitAll();
+    }
+
+
+    @Override
+    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
+        log.info("Configuring ResourceServerSecurityConfigurer ");
+        resources.resourceId("user-service").tokenStore(tokenStore);
+    }
+
+    @Autowired
+    TokenStore tokenStore;
+}

+ 70 - 0
mrqcman-service/src/main/java/com/diagbot/config/SwaggerConfigurer.java

@@ -0,0 +1,70 @@
+package com.diagbot.config;
+
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.ParameterBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.schema.ModelRef;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.Contact;
+import springfox.documentation.service.Parameter;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * @Description: Swagger配置类
+ * @author: gaodm
+ * @time: 2018/8/2 14:21
+ */
+@Configuration
+@ConditionalOnProperty(prefix = "swagger", value = { "enable" }, havingValue = "true")
+@EnableSwagger2
+public class SwaggerConfigurer {
+    /**
+     * 全局参数
+     *
+     * @return
+     */
+    private List<Parameter> parameter() {
+        List<Parameter> params = new ArrayList<>();
+        params.add(new ParameterBuilder().name("Authorization")
+                .description("Authorization Bearer token")
+                .modelRef(new ModelRef("string"))
+                .parameterType("header")
+                .required(false).build());
+        return params;
+    }
+
+
+    @Bean
+    public Docket sysApi() {
+        return new Docket(DocumentationType.SWAGGER_2)
+                .apiInfo(apiInfo())
+                .select()
+                .apis(RequestHandlerSelectors.basePackage("com.diagbot.web"))
+                .paths(PathSelectors.any())
+                .build().globalOperationParameters(parameter());
+        //.securitySchemes(newArrayList(oauth()))
+        // .securityContexts(newArrayList(securityContext()));
+    }
+
+    private ApiInfo apiInfo() {
+        return new ApiInfoBuilder()
+                .title(" mrqcman-service api ")
+                .description("mrqcman-service 微服务")
+                .termsOfServiceUrl("")
+                .contact(new Contact("diagbot","",""))
+                .version("1.0")
+                .build();
+    }
+
+}

+ 106 - 0
mrqcman-service/src/main/java/com/diagbot/config/security/UrlAccessDecisionManager.java

@@ -0,0 +1,106 @@
+package com.diagbot.config.security;
+
+import com.diagbot.client.UserServiceClient;
+import com.diagbot.dto.RespDTO;
+import com.diagbot.entity.Token;
+import com.diagbot.exception.CommonErrorCode;
+import com.diagbot.util.HttpUtils;
+import com.diagbot.util.StringUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.AccessDecisionManager;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.authentication.AccountExpiredException;
+import org.springframework.security.authentication.InsufficientAuthenticationException;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.web.FilterInvocation;
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
+import org.springframework.stereotype.Service;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Collection;
+
+/**
+ * @Description: 自定义权限拦截
+ * @author: gaodm
+ * @time: 2018/8/23 13:46
+ */
+@Service
+public class UrlAccessDecisionManager implements AccessDecisionManager {
+    @Autowired
+    private UserServiceClient userServiceClient;
+
+    @Override
+    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
+        HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
+        String url, method;
+        if (matchPermitAllUrl(request)) {
+            return;
+        }
+        if ("anonymousUser".equals(authentication.getPrincipal())) {
+            throw new AccessDeniedException("no right");
+        } else {
+            //验证token有效性
+            String tokenStr = HttpUtils.getHeaders(request).get("Authorization");
+            if (StringUtil.isNotEmpty(tokenStr)) {
+                Token token = new Token();
+                tokenStr = tokenStr.replaceFirst("Bearer ", "");
+                token.setToken(tokenStr);
+                RespDTO<Boolean> res = userServiceClient.verifyToken(token);
+                if (res == null || !CommonErrorCode.OK.getCode().equals(res.code)) {
+                    throw new AccountExpiredException("token expire");
+                }
+                if (!res.data) {
+                    throw new AccountExpiredException("token expire");
+                }
+            }
+            for (GrantedAuthority ga : authentication.getAuthorities()) {
+                String[] authority = ga.getAuthority().split(";");
+                url = authority[0];
+                method = authority[1];
+                if (matchers(url, request)) {
+                    if (method.equals(request.getMethod()) || "ALL".equals(method)) {
+                        return;
+                    }
+                }
+            }
+        }
+        throw new AccessDeniedException("no right");
+    }
+
+
+    @Override
+    public boolean supports(ConfigAttribute attribute) {
+        return true;
+    }
+
+    @Override
+    public boolean supports(Class<?> clazz) {
+        return true;
+    }
+
+    private Boolean matchPermitAllUrl(HttpServletRequest request) {
+        if (matchers("/swagger/**", request)
+                || matchers("/v2/**", request)
+                || matchers("/swagger-ui.html/**", request)
+                || matchers("/swagger-resources/**", request)
+                || matchers("/webjars/**", request)
+                || matchers("/druid/**", request)
+                || matchers("/actuator/**", request)
+                || matchers("/hystrix/**", request)
+                || matchers("/mrqcToken/decrypt", request)
+                || matchers("/", request)) {
+            return true;
+        }
+        return false;
+    }
+
+    private boolean matchers(String url, HttpServletRequest request) {
+        AntPathRequestMatcher matcher = new AntPathRequestMatcher(url);
+        if (matcher.matches(request)) {
+            return true;
+        }
+        return false;
+    }
+}

+ 29 - 0
mrqcman-service/src/main/java/com/diagbot/config/security/UrlConfigAttribute.java

@@ -0,0 +1,29 @@
+package com.diagbot.config.security;
+
+import org.springframework.security.access.ConfigAttribute;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * @Description: 自定义权限拦截
+ * @author: gaodm
+ * @time: 2018/8/23 13:47
+ */
+public class UrlConfigAttribute implements ConfigAttribute {
+
+    private final HttpServletRequest httpServletRequest;
+
+    public UrlConfigAttribute(HttpServletRequest httpServletRequest) {
+        this.httpServletRequest = httpServletRequest;
+    }
+
+
+    @Override
+    public String getAttribute() {
+        return null;
+    }
+
+    public HttpServletRequest getHttpServletRequest() {
+        return httpServletRequest;
+    }
+}

+ 79 - 0
mrqcman-service/src/main/java/com/diagbot/config/security/UrlFilterSecurityInterceptor.java

@@ -0,0 +1,79 @@
+package com.diagbot.config.security;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.SecurityMetadataSource;
+import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
+import org.springframework.security.access.intercept.InterceptorStatusToken;
+import org.springframework.security.web.FilterInvocation;
+import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
+import org.springframework.stereotype.Service;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import java.io.IOException;
+
+/**
+ * @Description: 自定义权限拦截
+ * @author: gaodm
+ * @time: 2018/8/23 13:47
+ */
+@Service
+public class UrlFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {
+
+
+    @Autowired
+    private FilterInvocationSecurityMetadataSource securityMetadataSource;
+
+    @Autowired
+    public void setUrlAccessDecisionManager(UrlAccessDecisionManager urlAccessDecisionManager) {
+        super.setAccessDecisionManager(urlAccessDecisionManager);
+    }
+
+
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException {
+
+    }
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+
+        FilterInvocation fi = new FilterInvocation(request, response, chain);
+        invoke(fi);
+    }
+
+
+    public void invoke(FilterInvocation fi) throws IOException, ServletException {
+        //fi里面有一个被拦截的url
+        //里面调用UrlMetadataSource的getAttributes(Object object)这个方法获取fi对应的所有权限
+        //再调用UrlAccessDecisionManager的decide方法来校验用户的权限是否足够
+        InterceptorStatusToken token = super.beforeInvocation(fi);
+        try {
+            //执行下一个拦截器
+            fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
+        } finally {
+            super.afterInvocation(token, null);
+        }
+    }
+
+
+    @Override
+    public void destroy() {
+
+    }
+
+    @Override
+    public Class<?> getSecureObjectClass() {
+        return FilterInvocation.class;
+
+    }
+
+    @Override
+    public SecurityMetadataSource obtainSecurityMetadataSource() {
+        return this.securityMetadataSource;
+    }
+}

+ 40 - 0
mrqcman-service/src/main/java/com/diagbot/config/security/UrlMetadataSourceService.java

@@ -0,0 +1,40 @@
+package com.diagbot.config.security;
+
+import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.web.FilterInvocation;
+import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
+import org.springframework.stereotype.Service;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @Description: 自定义权限拦截
+ * @author: gaodm
+ * @time: 2018/8/23 13:47
+ */
+@Service
+public class UrlMetadataSourceService implements
+        FilterInvocationSecurityMetadataSource {
+
+    @Override
+    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
+        final HttpServletRequest request = ((FilterInvocation) object).getRequest();
+        Set<ConfigAttribute> allAttributes = new HashSet<>();
+        ConfigAttribute configAttribute = new UrlConfigAttribute(request);
+        allAttributes.add(configAttribute);
+        return allAttributes;
+    }
+
+    @Override
+    public Collection<ConfigAttribute> getAllConfigAttributes() {
+        return null;
+    }
+
+    @Override
+    public boolean supports(Class<?> clazz) {
+        return true;
+    }
+}

+ 28 - 0
mrqcman-service/src/main/java/com/diagbot/dto/FileDTO.java

@@ -0,0 +1,28 @@
+package com.diagbot.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @Description:
+ * @Author:zhaops
+ * @time: 2018/12/18 17:08
+ */
+@Getter
+@Setter
+public class FileDTO {
+    private String state;
+    private String original;
+    private String title;
+    private String url;
+    private String md5;
+    private String info;
+
+    public FileDTO(String state, String info) {
+        this.state = state;
+        this.info = info;
+    }
+    public FileDTO(){
+
+    }
+}

+ 17 - 0
mrqcman-service/src/main/java/com/diagbot/dto/FileDeleteDTO.java

@@ -0,0 +1,17 @@
+package com.diagbot.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @Description:
+ * @author: gaodm
+ * @time: 2019/11/4 11:09
+ */
+@Getter
+@Setter
+public class FileDeleteDTO {
+    private Object data;
+    private String message;
+    private String status;
+}

+ 25 - 0
mrqcman-service/src/main/java/com/diagbot/dto/FileUploadDTO.java

@@ -0,0 +1,25 @@
+package com.diagbot.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @Description:
+ * @author: gaodm
+ * @time: 2019/11/4 10:55
+ */
+@Getter
+@Setter
+public class FileUploadDTO {
+    private String url;
+    private String md5;
+    private String path;
+    private String domain;
+    private String scene;
+    private int size;
+    private int mtime;
+    private String scenes;
+    private String retmsg;
+    private int retcode;
+    private String src;
+}

+ 18 - 0
mrqcman-service/src/main/java/com/diagbot/dto/TokenContentDTO.java

@@ -0,0 +1,18 @@
+package com.diagbot.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @Description:
+ * @Author:zhaops
+ * @time: 2018/12/18 17:08
+ */
+@Getter
+@Setter
+public class TokenContentDTO {
+    private String cpu; // cpu
+    private String mainboard; // 主板
+    private String disk; // 硬盘
+    private String ip; // ip
+}

+ 116 - 0
mrqcman-service/src/main/java/com/diagbot/entity/MrqcToken.java

@@ -0,0 +1,116 @@
+package com.diagbot.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * <p>
+ * 病历质控token信息
+ * </p>
+ *
+ * @author zhoutg
+ * @since 2019-12-23
+ */
+@Getter
+@Setter
+public class MrqcToken implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 是否删除,N:未删除,Y:删除
+     */
+    private String isDeleted;
+
+    /**
+     * 记录创建时间
+     */
+    private Date gmtCreate;
+
+    /**
+     * 记录修改时间,如果时间是1970年则表示纪录未修改
+     */
+    private Date gmtModified;
+
+    /**
+     * 创建人姓名
+     */
+    private String creator;
+
+    /**
+     * 修改人姓名
+     */
+    private String modifier;
+
+    /**
+     * 服务商
+     */
+    private String server;
+
+    /**
+     * 医院
+     */
+    private String hospital;
+
+    /**
+     * cpu
+     */
+    private String cpu;
+
+    /**
+     * 主板信息
+     */
+    private String mainboard;
+
+    /**
+     * 硬盘信息
+     */
+    private String disk;
+
+    /**
+     * ip
+     */
+    private String ip;
+
+    /**
+     * 剩余使用天数
+     */
+    private Integer remainDay;
+
+    /**
+     * 有效时间(分钟)
+     */
+    private Integer validTime;
+
+    /**
+     * 登录key
+     */
+    private String loginKey;
+
+    /**
+     * 文件路径
+     */
+    private String url;
+
+    /**
+     * 拷贝内容
+     */
+    private String content;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+}

+ 21 - 0
mrqcman-service/src/main/java/com/diagbot/entity/Token.java

@@ -0,0 +1,21 @@
+package com.diagbot.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+
+/**
+ * @Description: token
+ * @Author: ztg
+ * @Date: 2018/9/19 13:14
+ */
+@Getter
+@Setter
+public class Token implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private String token;
+
+}

+ 81 - 0
mrqcman-service/src/main/java/com/diagbot/exception/CommonExceptionHandler.java

@@ -0,0 +1,81 @@
+package com.diagbot.exception;
+
+import com.diagbot.dto.RespDTO;
+import com.diagbot.util.GsonUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.BindException;
+import org.springframework.validation.FieldError;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.MissingServletRequestParameterException;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * @Description: 错误通用处理
+ * @author: gaodm
+ * @time: 2018/8/2 14:22
+ */
+@ControllerAdvice
+@ResponseBody
+@Slf4j
+public class CommonExceptionHandler {
+
+    @ExceptionHandler(Exception.class)
+    public ResponseEntity<RespDTO> handleException(Exception e) {
+        RespDTO resp = new RespDTO();
+        if (e instanceof BindException) {
+            BindException ex = (BindException) e;
+            Map<String, String> stringMap = new HashMap<>();
+            for (FieldError fieldError : ex.getBindingResult().getFieldErrors()) {
+                stringMap.put(fieldError.getField(), fieldError.getDefaultMessage());
+            }
+            String msg = GsonUtil.toJson(stringMap);
+            log.warn("【参数异常】:{}", msg);
+            resp.code = CommonErrorCode.PARAM_ERROR.getCode();
+            resp.msg = msg;
+            return new ResponseEntity(resp, HttpStatus.OK);
+        }
+        if (e instanceof MethodArgumentNotValidException) {
+            MethodArgumentNotValidException ex = (MethodArgumentNotValidException) e;
+            Map<String, String> stringMap = new HashMap<>();
+            for (FieldError fieldError : ex.getBindingResult().getFieldErrors()) {
+                stringMap.put(fieldError.getField(), fieldError.getDefaultMessage());
+            }
+            String msg = GsonUtil.toJson(stringMap);
+            log.warn("【参数异常】:{}", msg);
+            resp.code = CommonErrorCode.PARAM_ERROR.getCode();
+            resp.msg = msg;
+            return new ResponseEntity(resp, HttpStatus.OK);
+        }
+        if (e instanceof MissingServletRequestParameterException) {
+            MissingServletRequestParameterException ex = (MissingServletRequestParameterException) e;
+            Map<String, String> stringMap = new HashMap<>();
+            stringMap.put(ex.getParameterName(), "不能为null");
+            String msg = GsonUtil.toJson(stringMap);
+            log.warn("【参数异常】:{}", msg);
+            resp.code = CommonErrorCode.PARAM_ERROR.getCode();
+            resp.msg = msg;
+            return new ResponseEntity(resp, HttpStatus.OK);
+        }
+        if (e instanceof CommonException) {
+            CommonException taiChiException = (CommonException) e;
+            resp.code = taiChiException.getCode();
+            resp.msg = e.getMessage();
+            log.error("【业务异常】:{}", e.getMessage());
+            return new ResponseEntity(resp, HttpStatus.OK);
+        }
+        resp.code = CommonErrorCode.FAIL.getCode();
+        resp.msg = e.getMessage();
+        log.error("【系统异常】:{}", e.getMessage());
+        e.printStackTrace();
+        return new ResponseEntity(resp, HttpStatus.OK);
+    }
+
+}

+ 39 - 0
mrqcman-service/src/main/java/com/diagbot/exception/ServiceErrorCode.java

@@ -0,0 +1,39 @@
+package com.diagbot.exception;
+
+/**
+ * @Description: 本服务错误码
+ * 系统码(3位) + 等级码(1位) + 4位顺序号
+ * 系统码 通用码 000;用户中心 100; 管理中心 200;
+ * @author: gaodm
+ * @time: 2018/9/10 11:11
+ */
+public enum ServiceErrorCode implements ErrorCode {
+    LOG_IS_NOT_EXIST("90020001", "该日志不存在");
+
+    private String code;
+    private String msg;
+
+
+    ServiceErrorCode(String code, String msg) {
+        this.code = code;
+        this.msg = msg;
+    }
+
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public static ServiceErrorCode codeOf(String code) {
+        for (ServiceErrorCode state : values()) {
+            if (state.getCode() == code) {
+                return state;
+            }
+        }
+        return null;
+    }
+}

+ 198 - 0
mrqcman-service/src/main/java/com/diagbot/facade/MrqcTokenFacade.java

@@ -0,0 +1,198 @@
+package com.diagbot.facade;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.diagbot.dto.FileDTO;
+import com.diagbot.entity.MrqcToken;
+import com.diagbot.enums.IsDeleteEnum;
+import com.diagbot.exception.CommonErrorCode;
+import com.diagbot.exception.CommonException;
+import com.diagbot.service.UploadService;
+import com.diagbot.service.impl.MrqcTokenServiceImpl;
+import com.diagbot.util.BeanUtil;
+import com.diagbot.util.DateUtil;
+import com.diagbot.util.ListUtil;
+import com.diagbot.util.RSAEncrypt;
+import com.diagbot.vo.DecryptVO;
+import com.diagbot.vo.MrqcTokenContentVO;
+import com.diagbot.vo.MrqcTokenDeleteVO;
+import com.diagbot.vo.MrqcTokenIndexVO;
+import com.diagbot.vo.MrqcTokenPageVO;
+import com.diagbot.vo.MrqcTokenVO;
+import org.bouncycastle.jcajce.provider.asymmetric.rsa.RSAUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mock.web.MockMultipartFile;
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+@Component
+public class MrqcTokenFacade extends MrqcTokenServiceImpl {
+
+    @Autowired
+    UploadService uploadService;
+
+    /**
+     * token保存
+     *
+     * @param mrqcTokenVO
+     */
+    public void saveOrUpdate(MrqcTokenVO mrqcTokenVO) {
+        Date date = DateUtil.now();
+        MrqcToken mrqcToken = new MrqcToken();
+        BeanUtil.copyProperties(mrqcTokenVO, mrqcToken);
+        List<MrqcToken> list = this.list(new QueryWrapper<MrqcToken>()
+                .eq("ip", mrqcTokenVO.getIp())
+                .eq("cpu", mrqcTokenVO.getCpu())
+//                .eq("server", mrqcTokenVO.getServer())
+//                .eq("hospital", mrqcTokenVO.getHospital())
+                .eq("mainboard", mrqcTokenVO.getMainboard())
+                .eq("disk", mrqcTokenVO.getDisk())
+                .eq("is_deleted", IsDeleteEnum.N.getKey())
+                .ne(mrqcTokenVO.getId() != null, "id", mrqcTokenVO.getId())
+        );
+        if (ListUtil.isNotEmpty(list)) {
+            StringBuffer sb = new StringBuffer();
+            sb.append("当前loginKey已生成!<br>" );
+            for (MrqcToken bean : list) {
+                sb.append("服务商【").append(bean.getServer())
+                    .append("】,医院【").append(bean.getHospital())
+                    .append("】<br>");
+            }
+            throw new CommonException(CommonErrorCode.SERVER_IS_ERROR, sb.toString());
+        }
+        // id为空表示新增,只有新增时才生成loginKey
+        if (mrqcTokenVO.getId() == null) {
+            mrqcToken.setGmtCreate(date);
+            mrqcToken.setLoginKey(UUID.randomUUID().toString()); // 生成登录获取token需要的key
+        }
+        mrqcToken.setGmtModified(date);
+        mrqcToken.setModifier(mrqcTokenVO.getCreator());
+
+        // 创建文件
+        FileDTO fileDTO = null;
+        try {
+            StringBuffer sb = new StringBuffer();
+            sb.append("server.cpu=" + mrqcToken.getCpu()) // cpu信息
+                .append("$$")
+                .append("server.key=" + mrqcToken.getLoginKey())  // 加密key信息
+                .append("$$")
+                .append("server.remainday=" + mrqcToken.getRemainDay()) // 剩余天数
+                .append("$$")
+                .append("server.validtime=" + mrqcToken.getValidTime()) // 有效时间
+                .append("$$")
+                .append("server.hospital=" + mrqcToken.getHospital()) // 医院
+                .append("$$")
+                .append("server.provider=" + mrqcToken.getServer()); // 服务商
+            MultipartFile file = fileToMultipartFile(
+                    RSAEncrypt.encrypt(sb.toString()),
+                    "license.properties");
+            fileDTO = uploadService.singleFileUpload(file);
+        } catch (Exception e) {
+            throw new CommonException(CommonErrorCode.SERVER_IS_ERROR, "文件上传失败!");
+        }
+        mrqcToken.setUrl("{imageUrlPrefix}" + fileDTO.getUrl());
+        this.saveOrUpdate(mrqcToken);
+    }
+
+
+    /**
+     *
+     * @param content 文件内容
+     * @param fileName
+     * @return
+     * @throws Exception
+     */
+    public MultipartFile  fileToMultipartFile(String content, String fileName) throws Exception {
+        InputStream  inputstream = new ByteArrayInputStream(content.getBytes());
+        MultipartFile toMultipartFile = new MockMultipartFile(fileName, fileName, "text/plain", inputstream);
+        return toMultipartFile;
+    }
+
+
+    /**
+     * token删除
+     *
+     * @param mrqcTokenVO
+     */
+    public void deleteById(MrqcTokenDeleteVO mrqcTokenVO) {
+        MrqcToken mrqcToken = new MrqcToken();
+        this.update(new MrqcToken(),
+                new UpdateWrapper<MrqcToken>()
+                    .eq("id", mrqcTokenVO.getId())
+                    .eq("is_deleted", IsDeleteEnum.N.getKey())
+                    .set("modifier", mrqcTokenVO.getCreator())
+                    .set("gmt_modified", DateUtil.now())
+                    .set("is_deleted", IsDeleteEnum.Y.getKey())
+        );
+    }
+
+
+    /**
+     * token列表
+     *
+     * @param mrqcTokenPageVO
+     * @return
+     */
+    public IPage<MrqcToken> getListFac(MrqcTokenPageVO mrqcTokenPageVO) {
+        return this.getList(mrqcTokenPageVO);
+    }
+
+
+    /**
+     * 获取明细
+     * @param mrqcTokenIndexVO
+     * @return
+     */
+    public MrqcToken getById(MrqcTokenIndexVO mrqcTokenIndexVO) {
+        return this.getOne(new QueryWrapper<MrqcToken>()
+                        .eq("is_deleted", IsDeleteEnum.N.getKey())
+                        .eq("id", mrqcTokenIndexVO.getId())
+                , false
+        );
+    }
+
+
+    /**
+     * 解析内容
+     *
+     * @param mrqcTokenContentVO
+     * @return
+     */
+    public Map analysis(MrqcTokenContentVO mrqcTokenContentVO) {
+        Map<String, String> map = new HashMap<>();
+        try {
+            String content = mrqcTokenContentVO.getContent();
+            String contentDe = RSAEncrypt.decrypt(content);
+            String[] item = contentDe.split("\\$\\$"); // $$作为分隔符
+            for (String s : item) {
+                String[] keyVal = s.split("=");
+                map.put(keyVal[0], keyVal[1]);
+            }
+        } catch (Exception e) {
+            throw new CommonException(CommonErrorCode.SERVER_IS_ERROR, "内容格式有误,不能解析!");
+        }
+        return map;
+    }
+
+
+    public String decrypt(DecryptVO decryptVO) {
+        String contentDe = "";
+        try {
+            contentDe = RSAEncrypt.decrypt(decryptVO.getContent());
+        } catch (Exception e) {
+            throw new CommonException(CommonErrorCode.SERVER_IS_ERROR, "内容格式有误,不能解析!");
+        }
+        return contentDe;
+    }
+
+}

+ 19 - 0
mrqcman-service/src/main/java/com/diagbot/mapper/MrqcTokenMapper.java

@@ -0,0 +1,19 @@
+package com.diagbot.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.diagbot.entity.MrqcToken;
+import com.diagbot.vo.MrqcTokenPageVO;
+
+/**
+ * <p>
+ * 病历质控token信息 Mapper 接口
+ * </p>
+ *
+ * @author zhoutg
+ * @since 2019-12-23
+ */
+public interface MrqcTokenMapper extends BaseMapper<MrqcToken> {
+
+    IPage<MrqcToken> getList(MrqcTokenPageVO mrqcTokenPageVO);
+}

+ 23 - 0
mrqcman-service/src/main/java/com/diagbot/rabbit/MyProcessor.java

@@ -0,0 +1,23 @@
+package com.diagbot.rabbit;
+
+import org.springframework.cloud.stream.annotation.Input;
+import org.springframework.cloud.stream.annotation.Output;
+import org.springframework.messaging.MessageChannel;
+import org.springframework.messaging.SubscribableChannel;
+
+/**
+ * @Description: 自定义Stream发布和消费对象
+ * @author: gaodm
+ * @time: 2018/8/29 13:39
+ */
+public interface MyProcessor {
+
+    String INPUT_LOG = "inputLog";
+    String OUTPUT_LOG = "outputLog";
+
+    @Input(INPUT_LOG)
+    SubscribableChannel inputLog();
+
+    @Output(OUTPUT_LOG)
+    MessageChannel outputLog();
+}

+ 27 - 0
mrqcman-service/src/main/java/com/diagbot/rabbit/MySender.java

@@ -0,0 +1,27 @@
+package com.diagbot.rabbit;
+
+import com.diagbot.biz.log.entity.SysLog;
+import com.diagbot.util.GsonUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.cloud.stream.annotation.EnableBinding;
+import org.springframework.integration.support.MessageBuilder;
+import org.springframework.messaging.MessageChannel;
+import org.springframework.stereotype.Component;
+
+/**
+ * @Description: 发布者
+ * @author: gaodm
+ * @time: 2018/8/29 13:41
+ */
+@Component
+@EnableBinding({ MyProcessor.class })
+public class MySender {
+    @Autowired
+    @Qualifier("outputLog")
+    MessageChannel outputLog;
+
+    public void outputLogSend(SysLog sysLog) {
+        outputLog.send(MessageBuilder.withPayload(GsonUtil.toJson(sysLog)).build());
+    }
+}

+ 19 - 0
mrqcman-service/src/main/java/com/diagbot/service/MrqcTokenService.java

@@ -0,0 +1,19 @@
+package com.diagbot.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.diagbot.entity.MrqcToken;
+import com.diagbot.vo.MrqcTokenPageVO;
+
+/**
+ * <p>
+ * 病历质控token信息 服务类
+ * </p>
+ *
+ * @author zhoutg
+ * @since 2019-12-23
+ */
+public interface MrqcTokenService extends IService<MrqcToken> {
+
+    IPage<MrqcToken> getList(MrqcTokenPageVO mrqcTokenPageVO);
+}

+ 13 - 0
mrqcman-service/src/main/java/com/diagbot/service/UploadService.java

@@ -0,0 +1,13 @@
+package com.diagbot.service;
+
+import com.diagbot.dto.FileDTO;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * @Description: 文件上传服务接口
+ * @author: gaodm
+ * @time: 2018/11/13 13:50
+ */
+public interface UploadService {
+    FileDTO singleFileUpload(MultipartFile file);
+}

+ 26 - 0
mrqcman-service/src/main/java/com/diagbot/service/impl/MrqcTokenServiceImpl.java

@@ -0,0 +1,26 @@
+package com.diagbot.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.diagbot.entity.MrqcToken;
+import com.diagbot.mapper.MrqcTokenMapper;
+import com.diagbot.service.MrqcTokenService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.diagbot.vo.MrqcTokenPageVO;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 病历质控token信息 服务实现类
+ * </p>
+ *
+ * @author zhoutg
+ * @since 2019-12-23
+ */
+@Service
+public class MrqcTokenServiceImpl extends ServiceImpl<MrqcTokenMapper, MrqcToken> implements MrqcTokenService {
+
+    @Override
+    public IPage<MrqcToken> getList(MrqcTokenPageVO mrqcTokenPageVO) {
+        return baseMapper.getList(mrqcTokenPageVO);
+    }
+}

+ 129 - 0
mrqcman-service/src/main/java/com/diagbot/service/impl/UploadServiceImpl.java

@@ -0,0 +1,129 @@
+package com.diagbot.service.impl;
+
+import com.diagbot.dto.FileDTO;
+import com.diagbot.dto.FileDeleteDTO;
+import com.diagbot.dto.FileUploadDTO;
+import com.diagbot.service.UploadService;
+import com.diagbot.util.GsonUtil;
+import com.diagbot.util.StringUtil;
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.FormBody;
+import okhttp3.MediaType;
+import okhttp3.MultipartBody;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import okhttp3.Response;
+import okhttp3.ResponseBody;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * @Description: 文件上传服务接口实现
+ * @author: gaodm
+ * @time: 2018/11/13 13:50
+ */
+@Slf4j
+@Service
+public class UploadServiceImpl implements UploadService {
+    @Value("${imageUrl.prefix}")
+    private String imagerUrl;
+
+    @Override
+    public FileDTO singleFileUpload(MultipartFile file) {
+        if (file.isEmpty()) {
+            return new FileDTO("FAILURE", "文件不能为空");
+        }
+        //文件大小上限1M
+        if (file.getSize() > 1024 * 1024) {
+            return new FileDTO("FAILURE", "文件上传失败,超出大小限制1MB");
+        }
+
+        String result = "";
+        try {
+            OkHttpClient httpClient = new OkHttpClient();
+            MultipartBody multipartBody = new MultipartBody.Builder().
+                    setType(MultipartBody.FORM)
+                    .addFormDataPart("file", file.getOriginalFilename(),
+                            RequestBody.create(MediaType.parse("multipart/form-data;charset=utf-8"),
+                                    file.getBytes()))
+                    .addFormDataPart("scene", "M03")
+                    .addFormDataPart("output", "json")
+                    .build();
+
+            Request request = new Request.Builder()
+                    .url(imagerUrl + "/group1/upload")
+                    .post(multipartBody)
+                    .build();
+
+            Response response = httpClient.newCall(request).execute();
+            if (response.isSuccessful()) {
+                ResponseBody body = response.body();
+                if (body != null) {
+                    result = body.string();
+                    //System.out.println(result);
+                }
+            }
+
+            if (StringUtil.isBlank(result)) {
+                return new FileDTO("FAILURE", "文件上传失败,请重新上传");
+            }
+        } catch (Exception e) {
+            log.error("文件上传失败", e);
+            return new FileDTO("FAILURE", "文件上传失败,请重新上传");
+        }
+
+        FileUploadDTO fileUploadDTO = GsonUtil.toObject(result, FileUploadDTO.class);
+        FileDTO fileDTO = new FileDTO("SUCCESS", "文件上传成功");
+        fileDTO.setUrl(fileUploadDTO.getPath());
+        fileDTO.setMd5(fileUploadDTO.getMd5());
+        fileDTO.setOriginal(file.getOriginalFilename());
+        fileDTO.setTitle(file.getOriginalFilename());
+        return fileDTO;
+    }
+
+    /**
+     * 删除服务端文件
+     *
+     * @param md5
+     * @return
+     */
+    public FileDTO deleteRemoteFile(String md5) {
+        String result = "";
+        try {
+            OkHttpClient httpClient = new OkHttpClient();
+            RequestBody formBody = new FormBody.Builder()
+                    .add("md5", md5)
+                    .build();
+
+            Request request = new Request.Builder()
+                    .url(imagerUrl + "/group1/delete")
+                    .post(formBody)
+                    .build();
+
+            Response response = httpClient.newCall(request).execute();
+            if (response.isSuccessful()) {
+                ResponseBody body = response.body();
+                if (body != null) {
+                    result = body.string();
+                    //System.out.println(result);
+                }
+            }
+
+            if (StringUtil.isBlank(result)) {
+                return new FileDTO("FAILURE", "文件删除失败");
+            }
+
+        } catch (Exception e) {
+            log.error("", e);
+            return new FileDTO("FAILURE", "文件删除失败");
+        }
+
+        FileDeleteDTO fileDeleteDTO = GsonUtil.toObject(result, FileDeleteDTO.class);
+        if (fileDeleteDTO.getStatus().equals("fail")) {
+            return new FileDTO("FAILURE", fileDeleteDTO.getMessage());
+        }
+        return new FileDTO("SUCCESS", "文件删除成功");
+    }
+}

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 173 - 0
mrqcman-service/src/main/java/com/diagbot/util/RSAEncrypt.java


+ 302 - 0
mrqcman-service/src/main/java/com/diagbot/util/SerialNumberUtil.java

@@ -0,0 +1,302 @@
+package com.diagbot.util;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @description:
+ * @author: zhoutg
+ * @time: 2019/12/23 10:40
+ */
+@Component
+public class SerialNumberUtil {
+    static Logger log = LogManager.getLogger(SerialNumberUtil.class);
+
+    /**
+     * 获取主板序列号
+     *
+     * @return
+     */
+    public static String getMotherboardSN() {
+        String result = "";
+        try {
+            File file = File.createTempFile("realhowto", ".vbs");
+            file.deleteOnExit();
+            FileWriter fw = new java.io.FileWriter(file);
+
+            String vbs = "Set objWMIService = GetObject(\"winmgmts:\\\\.\\root\\cimv2\")\n"
+                    + "Set colItems = objWMIService.ExecQuery _ \n"
+                    + "   (\"Select * from Win32_BaseBoard\") \n"
+                    + "For Each objItem in colItems \n"
+                    + "    Wscript.Echo objItem.SerialNumber \n"
+                    + "    exit for  ' do the first cpu only! \n" + "Next \n";
+
+            fw.write(vbs);
+            fw.close();
+            String path = file.getPath().replace("%20", " ");
+            Process p = Runtime.getRuntime().exec(
+                    "cscript //NoLogo " + path);
+            BufferedReader input = new BufferedReader(new InputStreamReader(
+                    p.getInputStream()));
+            String line;
+            while ((line = input.readLine()) != null) {
+                result += line;
+            }
+            input.close();
+        } catch (Exception e) {
+            System.out.println(e.getMessage());
+            log.error(e.getMessage());
+        }
+        return result.trim();
+    }
+
+    /**
+     * 获取硬盘序列号(该方法获取的是硬盘本身的序列号)
+     * @return
+     */
+    public static String getHardDiskSN() {
+        String result = "";
+        try {
+            File file = File.createTempFile("realhowto", ".vbs");
+            file.deleteOnExit();
+            FileWriter fw = new java.io.FileWriter(file);
+            String vbs = "Set objWMIService = GetObject(\"winmgmts:\\\\.\\root\\cimv2\")\n"
+                    + "Set colItems = objWMIService.ExecQuery _ \n"
+                    + "   (\"Select * from Win32_DiskDrive\") \n"
+                    + "For Each objItem in colItems \n"
+                    + "    Wscript.Echo objItem.SerialNumber \n"
+                    + "    exit for  ' do the first cpu only! \n" + "Next \n";
+
+            fw.write(vbs);
+            fw.close();
+            String path = file.getPath().replace("%20", " ");
+            Process p = Runtime.getRuntime().exec(
+                    "cscript //NoLogo " + path);
+            BufferedReader input = new BufferedReader(new InputStreamReader(
+                    p.getInputStream()));
+            String line;
+            while ((line = input.readLine()) != null) {
+                result += line;
+            }
+            input.close();
+        } catch (Exception e) {
+            log.error(e.getMessage());
+        }
+        return result.trim();
+    }
+
+    /**
+     * 获取CPU序列号
+     *
+     * @return
+     */
+    public static String getCPUSerial() {
+        String result = "";
+        try {
+            File file = File.createTempFile("tmp", ".vbs");
+            file.deleteOnExit();
+            FileWriter fw = new java.io.FileWriter(file);
+            String vbs = "Set objWMIService = GetObject(\"winmgmts:\\\\.\\root\\cimv2\")\n"
+                    + "Set colItems = objWMIService.ExecQuery _ \n"
+                    + "   (\"Select * from Win32_Processor\") \n"
+                    + "For Each objItem in colItems \n"
+                    + "    Wscript.Echo objItem.ProcessorId \n"
+                    + "    exit for  ' do the first cpu only! \n" + "Next \n";
+
+            // + "    exit for  \r\n" + "Next";
+            fw.write(vbs);
+            fw.close();
+            String path = file.getPath().replace("%20", " ");
+            Process p = Runtime.getRuntime().exec(
+                    "cscript //NoLogo " + path);
+            BufferedReader input = new BufferedReader(new InputStreamReader(
+                    p.getInputStream()));
+            String line;
+            while ((line = input.readLine()) != null) {
+                result += line;
+            }
+            input.close();
+            file.delete();
+        } catch (Exception e) {
+            log.error(e.getMessage());
+        }
+        if (result.trim().length() < 1 || result == null) {
+            result = "无CPU_ID被读取";
+        }
+        return result.trim();
+    }
+
+    private static List<String> getLocalHostLANAddress() throws UnknownHostException, SocketException {
+        List<String> ips = new ArrayList<String>();
+        Enumeration<NetworkInterface> interfs = NetworkInterface.getNetworkInterfaces();
+        while (interfs.hasMoreElements()) {
+            NetworkInterface interf = interfs.nextElement();
+            Enumeration<InetAddress> addres = interf.getInetAddresses();
+            while (addres.hasMoreElements()) {
+                InetAddress in = addres.nextElement();
+                if (in instanceof Inet4Address) {
+                    System.out.println("v4:" + in.getHostAddress());
+                    if (!"127.0.0.1".equals(in.getHostAddress())) {
+                        ips.add(in.getHostAddress());
+                    }
+                }
+            }
+        }
+        return ips;
+    }
+
+    /**
+     * MAC
+     * 通过jdk自带的方法,先获取本机所有的ip,然后通过NetworkInterface获取mac地址
+     *
+     * @return
+     */
+    public static String getMac() {
+        try {
+            String resultStr = "";
+            List<String> ls = getLocalHostLANAddress();
+            for (String str : ls) {
+                InetAddress ia = InetAddress.getByName(str);// 获取本地IP对象
+                // 获得网络接口对象(即网卡),并得到mac地址,mac地址存在于一个byte数组中。
+                byte[] mac = NetworkInterface.getByInetAddress(ia)
+                        .getHardwareAddress();
+                // 下面代码是把mac地址拼装成String
+                StringBuilder sb = new StringBuilder();
+                for (int i = 0; i < mac.length; i++) {
+                    if (i != 0) {
+                        sb.append("-");
+                    }
+                    // mac[i] & 0xFF 是为了把byte转化为正整数
+                    String s = Integer.toHexString(mac[i] & 0xFF);
+                    sb.append(s.length() == 1 ? 0 + s : s);
+                }
+                // 把字符串所有小写字母改为大写成为正规的mac地址并返回
+                resultStr += sb.toString().toUpperCase() + ",";
+            }
+            return resultStr;
+        } catch (Exception e) {
+            log.error(e.getMessage());
+        }
+        return null;
+    }
+
+    /***************************linux*********************************/
+
+    public static String executeLinuxCmd(String cmd) {
+        try {
+            System.out.println("got cmd job : " + cmd);
+            Runtime run = Runtime.getRuntime();
+            Process process;
+            process = run.exec(cmd);
+            InputStream in = process.getInputStream();
+            BufferedReader bs = new BufferedReader(new InputStreamReader(in));
+            StringBuffer out = new StringBuffer();
+            byte[] b = new byte[8192];
+            for (int n; (n = in.read(b)) != -1; ) {
+                out.append(new String(b, 0, n));
+            }
+
+            in.close();
+            process.destroy();
+            return out.toString();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * @param cmd    命令语句
+     * @param record 要查看的字段
+     * @param symbol 分隔符
+     * @return
+     */
+    public static String getSerialNumber(String cmd, String record, String symbol) {
+        String execResult = executeLinuxCmd(cmd);
+        String[] infos = execResult.split("\n");
+
+        for (String info : infos) {
+            info = info.trim();
+            if (info.indexOf(record) != -1) {
+                info.replace(" ", "");
+                String[] sn = info.split(symbol);
+                return sn[1];
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * 获取CPUID、硬盘序列号、MAC地址、主板序列号
+     *
+     * @return
+     */
+    public static Map<String, String> getAllSn() {
+        String os = System.getProperty("os.name").toUpperCase();
+        Map<String, String> snVo = new HashMap<String, String>();
+        snVo.put("server.os", os);
+        if ("LINUX".equals(os)) {
+            System.out.println("=============>for linux");
+            String cpuid = getSerialNumber("dmidecode -t processor | grep 'ID'", "ID", ":");
+            System.out.println("cpuid : " + cpuid);
+            String mainboardNumber = getSerialNumber("dmidecode |grep 'Serial Number'", "Serial Number", ":");
+            System.out.println("mainboardNumber : " + mainboardNumber);
+            String diskNumber = getSerialNumber("fdisk -l", "Disk identifier", ":");
+            System.out.println("diskNumber : " + diskNumber);
+            // String mac = getSerialNumber("ifconfig -a", "ether", " ");
+            snVo.put("server.cpu", cpuid.toUpperCase().replace(" ", ""));
+            snVo.put("server.disk", diskNumber.toUpperCase().replace(" ", ""));
+            // snVo.put("mac", mac.toUpperCase().replace(" ", ""));
+            snVo.put("server.mainboard", mainboardNumber.toUpperCase().replace(" ", ""));
+        } else {
+            System.out.println("=============>for windows");
+            String cpuid = SerialNumberUtil.getCPUSerial();
+            String mainboard = SerialNumberUtil.getMotherboardSN();
+            String disk = SerialNumberUtil.getHardDiskSN();
+            // String mac = SerialNumberUtil.getMac();
+
+            System.out.println("CPU  SN:" + cpuid);
+            System.out.println("主板  SN:" + mainboard);
+            System.out.println("C盘   SN:" + disk);
+            //  System.out.println("MAC  SN:" + mac);
+
+            snVo.put("server.cpu", cpuid.toUpperCase().replace(" ", ""));
+            snVo.put("server.disk", disk.toUpperCase().replace(" ", ""));
+            // snVo.put("server.mac", mac.toUpperCase().replace(" ", ""));
+            snVo.put("server.mainboard", mainboard.toUpperCase().replace(" ", ""));
+        }
+
+        return snVo;
+    }
+
+    /**
+     * linux
+     * cpuid : dmidecode -t processor | grep 'ID'
+     * mainboard : dmidecode |grep 'Serial Number'
+     * disk : fdisk -l
+     * mac : ifconfig -a
+     *
+     * @param args
+     */
+    public static void main(String[] args) {
+        getAllSn();
+    }
+}

+ 26 - 0
mrqcman-service/src/main/java/com/diagbot/vo/DecryptVO.java

@@ -0,0 +1,26 @@
+package com.diagbot.vo;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 需要解密的内容
+ * </p>
+ *
+ * @author zhoutg
+ * @since 2019-12-23
+ */
+@Getter
+@Setter
+public class DecryptVO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 内容
+     */
+    private String content;
+}

+ 26 - 0
mrqcman-service/src/main/java/com/diagbot/vo/MrqcTokenContentVO.java

@@ -0,0 +1,26 @@
+package com.diagbot.vo;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 病历质控token信息
+ * </p>
+ *
+ * @author zhoutg
+ * @since 2019-12-23
+ */
+@Getter
+@Setter
+public class MrqcTokenContentVO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 内容
+     */
+    private String content;
+}

+ 31 - 0
mrqcman-service/src/main/java/com/diagbot/vo/MrqcTokenDeleteVO.java

@@ -0,0 +1,31 @@
+package com.diagbot.vo;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 病历质控token信息
+ * </p>
+ *
+ * @author zhoutg
+ * @since 2019-12-23
+ */
+@Getter
+@Setter
+public class MrqcTokenDeleteVO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    private Long id;
+
+    /**
+     * 修改人姓名
+     */
+    private String creator;
+}

+ 26 - 0
mrqcman-service/src/main/java/com/diagbot/vo/MrqcTokenIndexVO.java

@@ -0,0 +1,26 @@
+package com.diagbot.vo;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 病历质控token信息
+ * </p>
+ *
+ * @author zhoutg
+ * @since 2019-12-23
+ */
+@Getter
+@Setter
+public class MrqcTokenIndexVO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    private Long id;
+}

+ 59 - 0
mrqcman-service/src/main/java/com/diagbot/vo/MrqcTokenPageVO.java

@@ -0,0 +1,59 @@
+package com.diagbot.vo;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 病历质控token信息
+ * </p>
+ *
+ * @author zhoutg
+ * @since 2019-12-23
+ */
+@Getter
+@Setter
+public class MrqcTokenPageVO extends Page implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+
+    /**
+     * 修改人姓名
+     */
+    private String modified;
+
+    /**
+     * 服务商
+     */
+    private String server;
+
+    /**
+     * 医院
+     */
+    private String hospital;
+
+    /**
+     * cpu
+     */
+    private String cpu;
+
+    /**
+     * 主板信息
+     */
+    private String mainboard;
+
+    /**
+     * 硬盘信息
+     */
+    private String disk;
+
+    /**
+     * ip
+     */
+    private String ip;
+
+}

+ 94 - 0
mrqcman-service/src/main/java/com/diagbot/vo/MrqcTokenVO.java

@@ -0,0 +1,94 @@
+package com.diagbot.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 病历质控token信息
+ * </p>
+ *
+ * @author zhoutg
+ * @since 2019-12-23
+ */
+@Getter
+@Setter
+public class MrqcTokenVO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    private Long id;
+
+
+    /**
+     * 创建人(修改人)姓名
+     */
+    private String creator;
+
+    /**
+     * 服务商
+     */
+    private String server;
+
+    /**
+     * 医院
+     */
+    private String hospital;
+
+    /**
+     * cpu
+     */
+    private String cpu;
+
+    /**
+     * 主板信息
+     */
+    private String mainboard;
+
+    /**
+     * 硬盘信息
+     */
+    private String disk;
+
+    /**
+     * ip
+     */
+    private String ip;
+
+    /**
+     * 剩余使用天数
+     */
+    private Integer remainDay;
+
+    /**
+     * 有效时间(分钟)
+     */
+    private Integer validTime;
+
+    /**
+     * 登录Key
+     */
+    @ApiModelProperty(hidden = true)
+    private String loginKey;
+
+    /**
+     * 拷贝内容
+     */
+    private String content;
+
+    /**
+     * 文件路径
+     */
+    private String url;
+
+    /**
+     * 备注
+     */
+    private String remark;
+}

+ 116 - 0
mrqcman-service/src/main/java/com/diagbot/web/MrqcTokenController.java

@@ -0,0 +1,116 @@
+package com.diagbot.web;
+
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.diagbot.annotation.SysLogger;
+import com.diagbot.dto.RespDTO;
+import com.diagbot.entity.MrqcToken;
+import com.diagbot.facade.MrqcTokenFacade;
+import com.diagbot.vo.DecryptVO;
+import com.diagbot.vo.MrqcTokenContentVO;
+import com.diagbot.vo.MrqcTokenDeleteVO;
+import com.diagbot.vo.MrqcTokenIndexVO;
+import com.diagbot.vo.MrqcTokenPageVO;
+import com.diagbot.vo.MrqcTokenVO;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Map;
+
+/**
+ * <p>
+ * 病历质控token信息 前端控制器
+ * </p>
+ *
+ * @author zhoutg
+ * @since 2019-12-23
+ */
+@RestController
+@RequestMapping("/mrqcToken")
+@Api(value = "token相关接口", tags = { "token相关接口" })
+public class MrqcTokenController {
+
+    @Autowired
+    private MrqcTokenFacade mrqcTokenFacade;
+
+    @ApiOperation(value = "token新增或更新[by:zhoutg]",
+            notes = "id: 主键,修改传值<br>" +
+                    "creator:创建人(修改人)姓名<br>" +
+                    "server:服务商<br>" +
+                    "hospital:医院<br>" +
+                    "cpu:cpu<br>" +
+                    "mainboard: 主板<br>" +
+                    "disk:硬盘<br>" +
+                    "ip: ip<br>" +
+                    "loginKey:登录Key<br>" +
+                    "remark:备注<br>" +
+                    "content:内容<br>" +
+                    "remainDay:剩余使用天数<br>" +
+                    "validTime:有效时间(分钟)")
+    @PostMapping("/saveOrUpdate")
+    @SysLogger("saveOrUpdate")
+    @Transactional
+    RespDTO<Boolean> saveOrUpdate(@RequestBody MrqcTokenVO mrqcTokenVO) {
+        mrqcTokenFacade.saveOrUpdate(mrqcTokenVO);
+        return RespDTO.onSuc(true);
+    }
+
+
+    @ApiOperation(value = "token删除[by:zhoutg]",
+            notes = "")
+    @PostMapping("/delete")
+    @SysLogger("delete")
+    @Transactional
+    public RespDTO<Boolean> delete(@RequestBody MrqcTokenDeleteVO mrqcTokenDeleteVO) {
+        mrqcTokenFacade.deleteById(mrqcTokenDeleteVO);
+        return RespDTO.onSuc(true);
+    }
+
+
+    @ApiOperation(value = "token列表[by:zhoutg]",
+            notes = "")
+    @PostMapping("/list")
+    @SysLogger("list")
+    public RespDTO<IPage<MrqcToken>> list(@RequestBody MrqcTokenPageVO mrqcTokenPageVO) {
+        IPage<MrqcToken> data = mrqcTokenFacade.getListFac(mrqcTokenPageVO);
+        return RespDTO.onSuc(data);
+    }
+
+
+    @ApiOperation(value = "token获取明细[by:zhoutg]",
+            notes = "")
+    @PostMapping("/getById")
+    @SysLogger("getById")
+    public RespDTO<MrqcToken> index(@RequestBody MrqcTokenIndexVO mrqcTokenIndexVO) {
+        MrqcToken data = mrqcTokenFacade.getById(mrqcTokenIndexVO);
+        return RespDTO.onSuc(data);
+    }
+
+
+    @ApiOperation(value = "解析配置信息[by:zhoutg]",
+            notes = "server.cpu:cpu<br>" +
+                    "server.mainboard:主板<br>" +
+                    "server.disk:硬盘<br>")
+    @PostMapping("/analysis")
+    @SysLogger("analysis")
+    public RespDTO<Map<String, String>> analysis(@RequestBody MrqcTokenContentVO mrqcTokenContentVO) {
+        Map<String, String> map = mrqcTokenFacade.analysis(mrqcTokenContentVO);
+        return RespDTO.onSuc(map);
+    }
+
+
+    @ApiOperation(value = "解密[by:zhoutg]",
+            notes = "")
+    @PostMapping("/decrypt")
+    @SysLogger("decrypt")
+    public RespDTO<String> decrypt(@RequestBody DecryptVO decryptVO) {
+        String data = mrqcTokenFacade.decrypt(decryptVO);
+        return RespDTO.onSuc(data);
+    }
+}

+ 19 - 0
mrqcman-service/src/main/resources/bootstrap.yml

@@ -0,0 +1,19 @@
+spring:
+  application:
+    name: mrqcman-service
+  cloud:
+    config:
+      #uri: http://${myuri}:8769
+      fail-fast: true
+      discovery:
+        enabled: true
+        serviceId: config-server
+  profiles:
+    active: local
+
+eureka:
+  client:
+    serviceUrl:
+      defaultZone: http://${myuri}:8761/eureka/
+
+myuri: localhost

+ 306 - 0
mrqcman-service/src/main/resources/logback-spring.xml

@@ -0,0 +1,306 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+    <!-- 项目名称 -->
+    <property name="APPDIR" value="mrqcman-service"/>
+    <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
+    <property name="LOG_PATH" value="../logs"/>
+
+    <!-- 彩色日志 -->
+    <!-- 彩色日志依赖的渲染类 -->
+    <conversionRule conversionWord="clr"
+                    converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
+    <conversionRule conversionWord="wex"
+                    converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
+    <conversionRule conversionWord="wEx"
+                    converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
+    <!-- 彩色日志格式 -->
+    <!--<property name="CONSOLE_LOG_PATTERN"-->
+    <!--value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(-&#45;&#45;){faint} %clr([%15.15t]){faint} %clr(%logger){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>-->
+    <!--包名输出缩进对齐-->
+    <property name="CONSOLE_LOG_PATTERN"
+              value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
+
+    <!--  日志记录器,日期滚动记录
+            ERROR 级别
+     -->
+    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/${APPDIR}/${APPDIR}_error.log</file>
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 归档的日志文件的路径,例如今天是1992-11-06日志,当前写的日志文件路径为file节点指定,
+            可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
+            而1992-11-06的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
+            <fileNamePattern>${LOG_PATH}/${APPDIR}/error/${APPDIR}-error-%d{yyyy-MM-dd}.%i.log
+            </fileNamePattern>
+            <!--  保留日志天数 -->
+            <maxHistory>30</maxHistory>
+            <!-- 除按日志记录之外,还配置了日志文件不能超过10MB,若超过10MB,日志文件会以索引0开始,
+            命名日志文件,例如log-error-1992-11-06.0.log -->
+            <timeBasedFileNamingAndTriggeringPolicy
+                    class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>10MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+        </rollingPolicy>
+        <!-- 追加方式记录日志 -->
+        <append>true</append>
+        <!-- 日志文件的格式 -->
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level --- [%thread] %logger Line:%-3L - %msg%n
+            </pattern>
+            <charset>utf-8</charset>
+        </encoder>
+        <!-- 此日志文件记录error级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>error</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+
+    <!-- 日志记录器,日期滚动记录
+            WARN  级别
+     -->
+    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/${APPDIR}/${APPDIR}_warn.log</file>
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 归档的日志文件的路径,例如今天1992-11-06日志,当前写的日志文件路径为file节点指定,
+            可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
+            而1992-11-06的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
+            <fileNamePattern>${LOG_PATH}/${APPDIR}/warn/${APPDIR}-warn-%d{yyyy-MM-dd}.%i.log
+            </fileNamePattern>
+            <!--  保留日志天数 -->
+            <maxHistory>15</maxHistory>
+            <!-- 除按日志记录之外,还配置了日志文件不能超过10MB,若超过10MB,日志文件会以索引0开始,
+            命名日志文件,例如log-warn-1992-11-06.0.log -->
+            <timeBasedFileNamingAndTriggeringPolicy
+                    class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>10MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+        </rollingPolicy>
+        <!-- 追加方式记录日志 -->
+        <append>true</append>
+        <!-- 日志文件的格式 -->
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level --- [%thread] %logger Line:%-3L - %msg%n
+            </pattern>
+            <charset>utf-8</charset>
+        </encoder>
+        <!-- 此日志文件只记录warn级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>warn</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+
+    <!-- 日志记录器,日期滚动记录
+            INFO  级别
+    -->
+    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/${APPDIR}/${APPDIR}_info.log</file>
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 归档的日志文件的路径,例如今天是1992-11-06日志,当前写的日志文件路径为file节点指定,
+            可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
+            而1992-11-06的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
+            <fileNamePattern>${LOG_PATH}/${APPDIR}/info/${APPDIR}-info-%d{yyyy-MM-dd}.%i.log
+            </fileNamePattern>
+            <!--  保留日志天数 -->
+            <maxHistory>15</maxHistory>
+            <!-- 除按日志记录之外,还配置了日志文件不能超过10MB,若超过10MB,日志文件会以索引0开始,
+            命名日志文件,例如log-info-1992-11-06.0.log -->
+            <timeBasedFileNamingAndTriggeringPolicy
+                    class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>10MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+        </rollingPolicy>
+        <!-- 追加方式记录日志 -->
+        <append>true</append>
+        <!-- 日志文件的格式 -->
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level --- [%thread] %logger Line:%-3L - %msg%n
+            </pattern>
+            <charset>utf-8</charset>
+        </encoder>
+        <!-- 此日志文件只记录info级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>info</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+
+    <!-- 日志记录器,日期滚动记录
+            DEBUG  级别
+    -->
+    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/${APPDIR}/${APPDIR}_debug.log</file>
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 归档的日志文件的路径,例如今天是1992-11-06日志,当前写的日志文件路径为file节点指定,
+            可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
+            而1992-11-06的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
+            <fileNamePattern>${LOG_PATH}/${APPDIR}/debug/${APPDIR}-debug-%d{yyyy-MM-dd}.%i.log
+            </fileNamePattern>
+            <!--  保留日志天数 -->
+            <maxHistory>15</maxHistory>
+            <!-- 除按日志记录之外,还配置了日志文件不能超过10MB,若超过10MB,日志文件会以索引0开始,
+            命名日志文件,例如log-debug-1992-11-06.0.log -->
+            <timeBasedFileNamingAndTriggeringPolicy
+                    class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>10MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+        </rollingPolicy>
+        <!-- 追加方式记录日志 -->
+        <append>true</append>
+        <!-- 日志文件的格式 -->
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level --- [%thread] %logger Line:%-3L - %msg%n
+            </pattern>
+            <charset>utf-8</charset>
+        </encoder>
+        <!-- 此日志文件只记录debug级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>debug</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+    <!-- ConsoleAppender 控制台输出日志 -->
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <!--encoder 默认配置为PatternLayoutEncoder-->
+        <encoder>
+            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
+            <!--<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level -&#45;&#45; [%thread] %logger Line:%-3L - %msg%n</pattern>-->
+            <charset>utf-8</charset>
+        </encoder>
+        <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>debug</level>
+        </filter>
+    </appender>
+
+
+    <!--&lt;!&ndash;输出到mysql数据库的appender配置     &ndash;&gt;-->
+    <!--<appender name="db" class="ch.qos.logback.classic.db.DBAppender">-->
+    <!--<connectionSource-->
+    <!--class="ch.qos.logback.core.db.DriverManagerConnectionSource">-->
+    <!--<driverClass>com.mysql.cj.jdbc.Driver</driverClass>-->
+    <!--<url>jdbc:mysql://120.77.222.42:3306/logback_member?characterEncoding=utf8</url>-->
+    <!--<user>root</user>-->
+    <!--<password>a123456789</password>-->
+    <!--</connectionSource>-->
+    <!--</appender>-->
+
+    <!-- FrameworkServlet日志-->
+    <logger name="org.springframework" level="WARN"/>
+
+    <!-- mybatis日志打印-->
+    <logger name="org.apache.ibatis" level="DEBUG"/>
+    <logger name="java.sql" level="DEBUG"/>
+
+    <!--  项目 mapper 路径
+            console控制台显示sql语句:STDOUT.filter.level -> debug级别
+    -->
+    <logger name="com.diagbot.mapper" level="DEBUG"/>
+
+    <appender name="LOGSTASHDEV" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
+        <destination>192.168.2.236:5044</destination>
+        <!-- encoder必须配置,有多种可选 -->
+        <encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder">
+            <customFields>{"appname":"mrqcman-service"}</customFields>
+        </encoder>
+    </appender>
+
+    <appender name="LOGSTASHTEST" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
+        <destination>192.168.2.241:5044</destination>
+        <!-- encoder必须配置,有多种可选 -->
+        <encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder">
+            <customFields>{"appname":"mrqcman-service"}</customFields>
+        </encoder>
+    </appender>
+
+    <appender name="LOGSTASHPRE" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
+        <destination>192.168.2.121:5044</destination>
+        <!-- encoder必须配置,有多种可选 -->
+        <encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder">
+            <customFields>{"appname":"mrqcman-service"}</customFields>
+        </encoder>
+    </appender>
+
+    <appender name="LOGSTASHPRO" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
+        <destination>192.168.2.122:5044</destination>
+        <!-- encoder必须配置,有多种可选 -->
+        <encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder">
+            <customFields>{"appname":"mrqcman-service"}</customFields>
+        </encoder>
+    </appender>
+
+    <!-- 本地环境下的日志配置 -->
+    <springProfile name="local">
+        <root level="INFO">
+            <appender-ref ref="ERROR"/>
+            <appender-ref ref="WARN"/>
+            <appender-ref ref="INFO"/>
+            <appender-ref ref="DEBUG"/>
+            <appender-ref ref="STDOUT"/>
+        </root>
+    </springProfile>
+
+    <!-- 开发环境下的日志配置 -->
+    <springProfile name="dev">
+        <root level="INFO">
+            <appender-ref ref="ERROR"/>
+            <appender-ref ref="WARN"/>
+            <appender-ref ref="INFO"/>
+            <appender-ref ref="DEBUG"/>
+            <appender-ref ref="STDOUT"/>
+            <appender-ref ref="LOGSTASHDEV"/>
+        </root>
+    </springProfile>
+
+    <!-- 测试环境下的日志配置 -->
+    <springProfile name="test">
+        <root level="INFO">
+            <appender-ref ref="ERROR"/>
+            <appender-ref ref="WARN"/>
+            <appender-ref ref="INFO"/>
+            <appender-ref ref="DEBUG"/>
+            <appender-ref ref="STDOUT"/>
+            <appender-ref ref="LOGSTASHTEST"/>
+        </root>
+    </springProfile>
+
+    <!-- 预发布环境下的日志配置 -->
+    <springProfile name="pre">
+        <root level="INFO">
+            <appender-ref ref="ERROR"/>
+            <appender-ref ref="WARN"/>
+            <appender-ref ref="INFO"/>
+            <appender-ref ref="DEBUG"/>
+            <appender-ref ref="STDOUT"/>
+            <appender-ref ref="LOGSTASHPRE"/>
+        </root>
+    </springProfile>
+
+    <!-- 生产环境下的日志配置 -->
+    <springProfile name="pro">
+        <root level="INFO">
+            <appender-ref ref="ERROR"/>
+            <appender-ref ref="WARN"/>
+            <appender-ref ref="INFO"/>
+            <appender-ref ref="DEBUG"/>
+            <appender-ref ref="STDOUT"/>
+            <appender-ref ref="LOGSTASHPRO"/>
+        </root>
+    </springProfile>
+</configuration>

+ 53 - 0
mrqcman-service/src/main/resources/mapper/MrqcTokenMapper.xml

@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.diagbot.mapper.MrqcTokenMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.diagbot.entity.MrqcToken">
+        <id column="id" property="id" />
+        <result column="is_deleted" property="isDeleted" />
+        <result column="gmt_create" property="gmtCreate" />
+        <result column="gmt_modified" property="gmtModified" />
+        <result column="creator" property="creator" />
+        <result column="modifier" property="modifier" />
+        <result column="server" property="server" />
+        <result column="hospital" property="hospital" />
+        <result column="cpu" property="cpu" />
+        <result column="mainboard" property="mainboard" />
+        <result column="disk" property="disk" />
+        <result column="ip" property="ip" />
+        <result column="remain_day" property="remainDay" />
+        <result column="login_key" property="loginKey" />
+        <result column="url" property="url" />
+        <result column="content" property="content" />
+        <result column="valid_time" property="validTime" />
+        <result column="remark" property="remark" />
+    </resultMap>
+
+    <select id="getList" resultMap="BaseResultMap">
+        select * from mrqc_token
+        where is_deleted = 'N'
+        <if test="modified != null and modified != ''">
+             and modified like concat ('%', UPPER(trim(#{modified})), '%')
+        </if>
+        <if test="server != null and server != ''">
+            and server like concat ('%', UPPER(trim(#{server})), '%')
+        </if>
+        <if test="hospital != null and hospital != ''">
+            and hospital like concat ('%', UPPER(trim(#{hospital})), '%')
+        </if>
+        <if test="cpu != null and cpu != ''">
+            and cpu like concat ('%', UPPER(trim(#{cpu})), '%')
+        </if>
+        <if test="mainboard != null and mainboard != ''">
+            and mainboard like concat ('%', UPPER(trim(#{mainboard})), '%')
+        </if>
+        <if test="disk != null and disk != ''">
+            and disk like concat ('%', UPPER(trim(#{disk})), '%')
+        </if>
+        <if test="ip != null and ip != ''">
+            and ip like concat ('%', UPPER(trim(#{ip})), '%')
+        </if>
+        order by gmt_modified desc
+    </select>
+</mapper>

+ 9 - 0
mrqcman-service/src/main/resources/public.cert

@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxXZWH/WgxW9eTT6AmPRo
+GFY3T5V1+F1458dcQFw0EZejjHuGwEeHvxcgl4059Me2B1xXTs3FDXTWQ5z19EtP
+3ITYtnFTo2cxhwxiwqN8ZqFdpq5Uac0mzjlYKcyGp8x6t+Nc2cv3D3Ul2VIbGvbP
+sQOeKvt3WxWwdpQ+q3RXjRUFQGiygSD7yuXHIUpcOsm4ZWDlUkjfwX1q4pjiwFfA
+Mq5xgkzPwolUKnI0NFnom3Th3i4oFXzUg2s6cEj7jL7YU35c2/9kE7WQPbeYhoSi
+XH2OwWgBk/2Ki6+Q0Yq/eAsXSBjp1jqh337vvKBk5ocPG1Imi8uTLIgYQCMwzvg+
+VQIDAQAB
+-----END PUBLIC KEY-----

+ 83 - 0
mrqcman-service/src/test/java/com/diagbot/CodeGeneration.java

@@ -0,0 +1,83 @@
+package com.diagbot;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.generator.AutoGenerator;
+import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
+import com.baomidou.mybatisplus.generator.config.GlobalConfig;
+import com.baomidou.mybatisplus.generator.config.PackageConfig;
+import com.baomidou.mybatisplus.generator.config.StrategyConfig;
+import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
+import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
+
+/**
+ * @Description: 代码生成器
+ * @author: gaodm
+ * @time: 2018/8/2 10:15
+ */
+public class CodeGeneration {
+
+    /**
+     *
+     * @Title: main
+     * @Description: 生成
+     * @param args
+     */
+    public static void main(String[] args) {
+        AutoGenerator mpg = new AutoGenerator();
+
+        // 全局配置
+        GlobalConfig gc = new GlobalConfig();
+        gc.setOutputDir("E://code//mrqcmanservice");
+        gc.setFileOverride(true);
+        gc.setActiveRecord(false);// 不需要ActiveRecord特性的请改为false
+        gc.setEnableCache(false);// XML 二级缓存
+        gc.setBaseResultMap(true);// XML ResultMap
+        gc.setBaseColumnList(false);// XML columList
+        gc.setAuthor("zhoutg");// 作者
+
+        // 自定义文件命名,注意 %s 会自动填充表实体属性!
+        gc.setControllerName("%sController");
+        gc.setServiceName("%sService");
+        gc.setServiceImplName("%sServiceImpl");
+        gc.setMapperName("%sMapper");
+        gc.setXmlName("%sMapper");
+        mpg.setGlobalConfig(gc);
+
+        // 数据源配置
+        DataSourceConfig dsc = new DataSourceConfig();
+        dsc.setDbType(DbType.MYSQL);
+        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
+        dsc.setUsername("root");
+        dsc.setPassword("lantone");
+        dsc.setUrl("jdbc:mysql://192.168.2.236:3306/sys-mrqc?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8");
+        mpg.setDataSource(dsc);
+
+        // 策略配置
+        StrategyConfig strategy = new StrategyConfig();
+//        strategy.setTablePrefix(new String[] { "sys_" });// 此处可以修改为您的表前缀
+        strategy.setNaming(NamingStrategy.underline_to_camel);// 表名生成策略
+        strategy.setInclude(new String[] { "mrqc_token" }); // 需要生成的表
+
+        strategy.setSuperServiceClass(null);
+        strategy.setSuperServiceImplClass(null);
+        strategy.setSuperMapperClass(null);
+
+        mpg.setStrategy(strategy);
+
+        // 包配置
+        PackageConfig pc = new PackageConfig();
+        pc.setParent("com.diagbot");
+        pc.setController("web");
+        pc.setService("service");
+        pc.setServiceImpl("service.impl");
+        pc.setMapper("mapper");
+        pc.setEntity("entity");
+        pc.setXml("resources.mapper");
+        mpg.setPackageInfo(pc);
+
+        // 执行生成
+        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
+        mpg.execute();
+
+    }
+}

+ 16 - 0
mrqcman-service/src/test/java/com/diagbot/MrqcmanServiceApplicationTests.java

@@ -0,0 +1,16 @@
+package com.diagbot;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class MrqcmanServiceApplicationTests {
+
+    @Test
+    public void contextLoads() {
+    }
+
+}

+ 1 - 0
pom.xml

@@ -32,6 +32,7 @@
         <module>data-service</module>
         <module>prec-service</module>
         <module>precman-service</module>
+        <module>mrqcman-service</module>
     </modules>
 
     <parent>